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 static com.android.server.power.stats.MobileRadioPowerStatsCollector.mapRadioAccessNetworkTypeToRadioAccessTechnology;
27 
28 import android.annotation.IntDef;
29 import android.annotation.NonNull;
30 import android.annotation.Nullable;
31 import android.app.ActivityManager;
32 import android.app.AlarmManager;
33 import android.app.usage.NetworkStatsManager;
34 import android.bluetooth.BluetoothActivityEnergyInfo;
35 import android.bluetooth.BluetoothAdapter;
36 import android.bluetooth.BluetoothManager;
37 import android.bluetooth.UidTraffic;
38 import android.content.BroadcastReceiver;
39 import android.content.ContentResolver;
40 import android.content.Context;
41 import android.content.Intent;
42 import android.content.IntentFilter;
43 import android.content.pm.PackageManager;
44 import android.database.ContentObserver;
45 import android.hardware.usb.UsbManager;
46 import android.location.GnssSignalQuality;
47 import android.net.NetworkStats;
48 import android.net.Uri;
49 import android.net.wifi.WifiManager;
50 import android.os.BatteryConsumer;
51 import android.os.BatteryManager;
52 import android.os.BatteryStats;
53 import android.os.BatteryUsageStats;
54 import android.os.BatteryUsageStatsQuery;
55 import android.os.Binder;
56 import android.os.BluetoothBatteryStats;
57 import android.os.Build;
58 import android.os.ConditionVariable;
59 import android.os.Handler;
60 import android.os.IBatteryPropertiesRegistrar;
61 import android.os.Looper;
62 import android.os.Message;
63 import android.os.OsProtoEnums;
64 import android.os.Parcel;
65 import android.os.ParcelFormatException;
66 import android.os.Parcelable;
67 import android.os.PowerManager;
68 import android.os.Process;
69 import android.os.RemoteException;
70 import android.os.ServiceManager;
71 import android.os.SystemClock;
72 import android.os.UserHandle;
73 import android.os.WakeLockStats;
74 import android.os.WorkSource;
75 import android.os.WorkSource.WorkChain;
76 import android.os.connectivity.CellularBatteryStats;
77 import android.os.connectivity.GpsBatteryStats;
78 import android.os.connectivity.WifiActivityEnergyInfo;
79 import android.os.connectivity.WifiBatteryStats;
80 import android.power.PowerStatsInternal;
81 import android.provider.Settings;
82 import android.telephony.AccessNetworkConstants;
83 import android.telephony.Annotation.NetworkType;
84 import android.telephony.CellSignalStrength;
85 import android.telephony.CellSignalStrengthLte;
86 import android.telephony.CellSignalStrengthNr;
87 import android.telephony.DataConnectionRealTimeInfo;
88 import android.telephony.ModemActivityInfo;
89 import android.telephony.NetworkRegistrationInfo;
90 import android.telephony.ServiceState;
91 import android.telephony.ServiceState.RegState;
92 import android.telephony.SignalStrength;
93 import android.telephony.TelephonyManager;
94 import android.text.TextUtils;
95 import android.text.format.DateUtils;
96 import android.util.ArrayMap;
97 import android.util.ArraySet;
98 import android.util.AtomicFile;
99 import android.util.IndentingPrintWriter;
100 import android.util.KeyValueListParser;
101 import android.util.Log;
102 import android.util.LongSparseArray;
103 import android.util.LongSparseLongArray;
104 import android.util.MutableInt;
105 import android.util.PrintWriterPrinter;
106 import android.util.Printer;
107 import android.util.Slog;
108 import android.util.SparseArray;
109 import android.util.SparseBooleanArray;
110 import android.util.SparseDoubleArray;
111 import android.util.SparseIntArray;
112 import android.util.SparseLongArray;
113 import android.util.TimeUtils;
114 import android.util.Xml;
115 import android.view.Display;
116 
117 import com.android.internal.annotations.GuardedBy;
118 import com.android.internal.annotations.VisibleForTesting;
119 import com.android.internal.os.BackgroundThread;
120 import com.android.internal.os.BatteryStatsHistory;
121 import com.android.internal.os.BatteryStatsHistory.HistoryStepDetailsCalculator;
122 import com.android.internal.os.BatteryStatsHistoryIterator;
123 import com.android.internal.os.BinderCallsStats;
124 import com.android.internal.os.BinderTransactionNameResolver;
125 import com.android.internal.os.Clock;
126 import com.android.internal.os.CpuScalingPolicies;
127 import com.android.internal.os.KernelCpuSpeedReader;
128 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
129 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
130 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
131 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
132 import com.android.internal.os.KernelMemoryBandwidthStats;
133 import com.android.internal.os.KernelSingleUidTimeReader;
134 import com.android.internal.os.LongArrayMultiStateCounter;
135 import com.android.internal.os.LongMultiStateCounter;
136 import com.android.internal.os.MonotonicClock;
137 import com.android.internal.os.PowerProfile;
138 import com.android.internal.os.PowerStats;
139 import com.android.internal.os.RailStats;
140 import com.android.internal.os.RpmStats;
141 import com.android.internal.power.EnergyConsumerStats;
142 import com.android.internal.power.EnergyConsumerStats.StandardPowerBucket;
143 import com.android.internal.util.ArrayUtils;
144 import com.android.internal.util.FrameworkStatsLog;
145 import com.android.internal.util.XmlUtils;
146 import com.android.modules.utils.TypedXmlPullParser;
147 import com.android.modules.utils.TypedXmlSerializer;
148 import com.android.server.LocalServices;
149 import com.android.server.power.optimization.Flags;
150 import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
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.Future;
179 import java.util.concurrent.TimeUnit;
180 import java.util.concurrent.atomic.AtomicInteger;
181 import java.util.concurrent.locks.ReentrantLock;
182 import java.util.function.IntSupplier;
183 import java.util.function.LongSupplier;
184 import java.util.function.Supplier;
185 
186 /**
187  * All information we are collecting about things that can happen that impact
188  * battery life.  All times are represented in microseconds except where indicated
189  * otherwise.
190  */
191 public class BatteryStatsImpl extends BatteryStats {
192     private static final String TAG = "BatteryStatsImpl";
193     private static final boolean DEBUG = false;
194     public static final boolean DEBUG_ENERGY = false;
195     private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
196     private static final boolean DEBUG_BINDER_STATS = false;
197     private static final boolean DEBUG_MEMORY = false;
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     public static final int RESET_REASON_CORRUPT_FILE = 1;
230     public static final int RESET_REASON_ADB_COMMAND = 2;
231     public static final int RESET_REASON_FULL_CHARGE = 3;
232     public static final int RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE = 4;
233     public static final int RESET_REASON_PLUGGED_IN_FOR_LONG_DURATION = 5;
234     @NonNull
235     private final MonotonicClock mMonotonicClock;
236 
237     protected Clock mClock;
238 
239     private final AtomicFile mStatsFile;
240     public final AtomicFile mCheckinFile;
241     public final AtomicFile mDailyFile;
242 
243     static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1;
244     static final int MSG_REPORT_POWER_CHANGE = 2;
245     static final int MSG_REPORT_CHARGING = 3;
246     static final int MSG_REPORT_RESET_STATS = 4;
247     static final long DELAY_UPDATE_WAKELOCKS = 60 * 1000;
248 
249     private static final double MILLISECONDS_IN_HOUR = 3600 * 1000;
250     private static final long MILLISECONDS_IN_YEAR = 365 * 24 * 3600 * 1000L;
251 
252     private static final LongCounter ZERO_LONG_COUNTER = new LongCounter() {
253         @Override
254         public long getCountLocked(int which) {
255             return 0;
256         }
257 
258         @Override
259         public long getCountForProcessState(int procState) {
260             return 0;
261         }
262 
263         @Override
264         public void logState(Printer pw, String prefix) {
265             pw.println(prefix + "mCount=0");
266         }
267     };
268 
269     private static final LongCounter[] ZERO_LONG_COUNTER_ARRAY =
270             new LongCounter[]{ZERO_LONG_COUNTER};
271 
272     @VisibleForTesting
273     protected CpuScalingPolicies mCpuScalingPolicies;
274 
275     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
276 
277     @VisibleForTesting
278     protected KernelWakelockReader mKernelWakelockReader;
279     @VisibleForTesting
280     protected KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader;
281     @VisibleForTesting
282     protected KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
283     @VisibleForTesting
284     protected KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader;
285     @VisibleForTesting
286     protected KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader;
287     @VisibleForTesting
288     protected KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader;
289     @VisibleForTesting
290     protected KernelSingleUidTimeReader mKernelSingleUidTimeReader;
291     @VisibleForTesting
292     protected SystemServerCpuThreadReader mSystemServerCpuThreadReader;
293 
294     private KernelMemoryBandwidthStats mKernelMemoryBandwidthStats;
295     private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>();
296     private int[] mCpuPowerBracketMap;
297     private final CpuPowerStatsCollector mCpuPowerStatsCollector;
298     private final MobileRadioPowerStatsCollector mMobileRadioPowerStatsCollector;
299     private final WifiPowerStatsCollector mWifiPowerStatsCollector;
300     private final BluetoothPowerStatsCollector mBluetoothPowerStatsCollector;
301     private final SparseBooleanArray mPowerStatsCollectorEnabled = new SparseBooleanArray();
302     private final WifiPowerStatsCollector.WifiStatsRetriever mWifiStatsRetriever =
303             new WifiPowerStatsCollector.WifiStatsRetriever() {
304                 @Override
305                 public void retrieveWifiScanTimes(Callback callback) {
306                     synchronized (BatteryStatsImpl.this) {
307                         retrieveWifiScanTimesLocked(callback);
308                     }
309                 }
310 
311                 @Override
312                 public long getWifiActiveDuration() {
313                     synchronized (BatteryStatsImpl.this) {
314                         return getGlobalWifiRunningTime(mClock.elapsedRealtime() * 1000,
315                                 STATS_SINCE_CHARGED) / 1000;
316                     }
317                 }
318             };
319 
320     private class BluetoothStatsRetrieverImpl implements
321             BluetoothPowerStatsCollector.BluetoothStatsRetriever {
322         private final BluetoothManager mBluetoothManager;
323 
BluetoothStatsRetrieverImpl(BluetoothManager bluetoothManager)324         BluetoothStatsRetrieverImpl(BluetoothManager bluetoothManager) {
325             mBluetoothManager = bluetoothManager;
326         }
327 
328         @Override
retrieveBluetoothScanTimes(Callback callback)329         public void retrieveBluetoothScanTimes(Callback callback) {
330             synchronized (BatteryStatsImpl.this) {
331                 retrieveBluetoothScanTimesLocked(callback);
332             }
333         }
334 
335         @Override
requestControllerActivityEnergyInfo(Executor executor, BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback callback)336         public boolean requestControllerActivityEnergyInfo(Executor executor,
337                 BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback callback) {
338             if (mBluetoothManager == null) {
339                 return false;
340             }
341 
342             BluetoothAdapter adapter = mBluetoothManager.getAdapter();
343             if (adapter == null) {
344                 return false;
345             }
346 
347             adapter.requestControllerActivityEnergyInfo(executor, callback);
348             return true;
349         }
350     }
351 
getKernelMemoryStats()352     public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
353         return mKernelMemoryStats;
354     }
355 
356     private static final int[] SUPPORTED_PER_PROCESS_STATE_STANDARD_ENERGY_BUCKETS = {
357             EnergyConsumerStats.POWER_BUCKET_CPU,
358             EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO,
359             EnergyConsumerStats.POWER_BUCKET_WIFI,
360             EnergyConsumerStats.POWER_BUCKET_BLUETOOTH,
361     };
362 
363     // TimeInState counters need NUM_PROCESS_STATE states in order to accommodate
364     // Uid.PROCESS_STATE_NONEXISTENT, which is outside the range of legitimate proc states.
365     private static final int PROC_STATE_TIME_COUNTER_STATE_COUNT = NUM_PROCESS_STATE + 1;
366 
367     @GuardedBy("this")
368     public boolean mPerProcStateCpuTimesAvailable = true;
369 
370     @GuardedBy("this")
371     private long mNumSingleUidCpuTimeReads;
372     @GuardedBy("this")
373     private long mCpuTimeReadsTrackingStartTimeMs = SystemClock.uptimeMillis();
374     @GuardedBy("this")
375     private int mNumUidsRemoved;
376     @GuardedBy("this")
377     private int mNumAllUidCpuTimeReads;
378 
379     /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
380     private RpmStats mTmpRpmStats = null;
381     /** The soonest the RPM stats can be updated after it was last updated. */
382     private static final long RPM_STATS_UPDATE_FREQ_MS = 1000;
383     /** Last time that RPM stats were updated by updateRpmStatsLocked. */
384     private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
385 
386     /** Container for Rail Energy Data stats. */
387     private RailStats mTmpRailStats;
388 
389     /**
390      * Estimate UID modem power usage based on their estimated mobile radio active time.
391      */
392     public static final int PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME = 1;
393     /**
394      * Estimate UID modem power consumption by proportionally attributing estimated Rx and Tx
395      * power consumption individually.
396      * ModemActivityInfo must be available.
397      */
398     public static final int PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX = 2;
399 
400     @IntDef(flag = true, prefix = "PER_UID_MODEM_MODEL_", value = {
401             PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME,
402             PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX,
403     })
404     @Retention(RetentionPolicy.SOURCE)
405     public @interface PerUidModemPowerModel {
406     }
407 
408     /**
409      * Use a queue to delay removing UIDs from {@link KernelCpuUidUserSysTimeReader},
410      * {@link KernelCpuUidActiveTimeReader}, {@link KernelCpuUidClusterTimeReader},
411      * {@link KernelCpuUidFreqTimeReader} and from the Kernel.
412      *
413      * Isolated and invalid UID info must be removed to conserve memory. However, STATSD and
414      * Batterystats both need to access UID cpu time. To resolve this race condition, only
415      * Batterystats shall remove UIDs, and a delay {@link Constants#UID_REMOVE_DELAY_MS} is
416      * implemented so that STATSD can capture those UID times before they are deleted.
417      */
418     @GuardedBy("this")
419     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
420     protected Queue<UidToRemove> mPendingRemovedUids = new LinkedList<>();
421 
422     @NonNull
getHistory()423     public BatteryStatsHistory getHistory() {
424         return mHistory;
425     }
426 
427     @NonNull
copyHistory()428     BatteryStatsHistory copyHistory() {
429         return mHistory.copy();
430     }
431 
432     @VisibleForTesting
433     public final class UidToRemove {
434         private final int mStartUid;
435         private final int mEndUid;
436         private final long mUidRemovalTimestamp;
437 
438         /** Remove just one UID */
UidToRemove(int uid, long timestamp)439         public UidToRemove(int uid, long timestamp) {
440             this(uid, uid, timestamp);
441         }
442 
443         /** Remove a range of UIDs, startUid must be smaller than endUid. */
UidToRemove(int startUid, int endUid, long timestamp)444         public UidToRemove(int startUid, int endUid, long timestamp) {
445             mStartUid = startUid;
446             mEndUid = endUid;
447             mUidRemovalTimestamp = timestamp;
448         }
449 
getUidRemovalTimestamp()450         public long getUidRemovalTimestamp() {
451             return mUidRemovalTimestamp;
452         }
453 
454         @GuardedBy("BatteryStatsImpl.this")
removeLocked()455         void removeLocked() {
456             removeCpuStatsForUidRangeLocked(mStartUid, mEndUid);
457         }
458     }
459 
460     private boolean mSaveBatteryUsageStatsOnReset;
461     private BatteryUsageStatsProvider mBatteryUsageStatsProvider;
462     private PowerStatsStore mPowerStatsStore;
463 
464     public interface BatteryCallback {
batteryNeedsCpuUpdate()465         public void batteryNeedsCpuUpdate();
batteryPowerChanged(boolean onBattery)466         public void batteryPowerChanged(boolean onBattery);
batterySendBroadcast(Intent intent)467         public void batterySendBroadcast(Intent intent);
batteryStatsReset()468         public void batteryStatsReset();
469     }
470 
471     public interface PlatformIdleStateCallback {
fillLowPowerStats(RpmStats rpmStats)472         public void fillLowPowerStats(RpmStats rpmStats);
getSubsystemLowPowerStats()473         public String getSubsystemLowPowerStats();
474     }
475 
476     /** interface to update rail information for power monitor */
477     public interface EnergyStatsRetriever {
478         /** Function to fill the map for the rail data stats
479          * Used for power monitoring feature
480          * @param railStats
481          */
fillRailDataStats(RailStats railStats)482         void fillRailDataStats(RailStats railStats);
483     }
484 
485     public static abstract class UserInfoProvider {
486         private int[] userIds;
getUserIds()487         protected abstract @Nullable int[] getUserIds();
488         @VisibleForTesting
refreshUserIds()489         public final void refreshUserIds() {
490             userIds = getUserIds();
491         }
492         @VisibleForTesting
exists(int userId)493         public boolean exists(int userId) {
494             return userIds != null ? ArrayUtils.contains(userIds, userId) : true;
495         }
496     }
497 
498     /** Provide BatteryStatsImpl configuration choices */
499     public static class BatteryStatsConfig {
500         static final int RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG = 1 << 0;
501         static final int RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG = 1 << 1;
502 
503         private final int mFlags;
504         private final Long mDefaultPowerStatsThrottlePeriod;
505         private final Map<String, Long> mPowerStatsThrottlePeriods;
506 
507         @VisibleForTesting
BatteryStatsConfig()508         public BatteryStatsConfig() {
509             mFlags = 0;
510             mDefaultPowerStatsThrottlePeriod = 0L;
511             mPowerStatsThrottlePeriods = Map.of();
512         }
513 
BatteryStatsConfig(Builder builder)514         private BatteryStatsConfig(Builder builder) {
515             int flags = 0;
516             if (builder.mResetOnUnplugHighBatteryLevel) {
517                 flags |= RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG;
518             }
519             if (builder.mResetOnUnplugAfterSignificantCharge) {
520                 flags |= RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG;
521             }
522             mFlags = flags;
523             mDefaultPowerStatsThrottlePeriod = builder.mDefaultPowerStatsThrottlePeriod;
524             mPowerStatsThrottlePeriods = builder.mPowerStatsThrottlePeriods;
525         }
526 
527         /**
528          * Returns whether a BatteryStats reset should occur on unplug when the battery level is
529          * high.
530          */
shouldResetOnUnplugHighBatteryLevel()531         public boolean shouldResetOnUnplugHighBatteryLevel() {
532             return (mFlags & RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG)
533                     == RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG;
534         }
535 
536         /**
537          * Returns whether a BatteryStats reset should occur on unplug if the battery charge a
538          * significant amount since it has been plugged in.
539          */
shouldResetOnUnplugAfterSignificantCharge()540         public boolean shouldResetOnUnplugAfterSignificantCharge() {
541             return (mFlags & RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG)
542                     == RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG;
543         }
544 
545         /**
546          * Returns  the minimum amount of time (in millis) to wait between passes
547          * of power stats collection for the specified power component.
548          */
getPowerStatsThrottlePeriod(String powerComponentName)549         public long getPowerStatsThrottlePeriod(String powerComponentName) {
550             return mPowerStatsThrottlePeriods.getOrDefault(powerComponentName,
551                     mDefaultPowerStatsThrottlePeriod);
552         }
553 
554         /**
555          * Builder for BatteryStatsConfig
556          */
557         public static class Builder {
558             private boolean mResetOnUnplugHighBatteryLevel;
559             private boolean mResetOnUnplugAfterSignificantCharge;
560             public static final long DEFAULT_POWER_STATS_THROTTLE_PERIOD =
561                     TimeUnit.HOURS.toMillis(1);
562             public static final long DEFAULT_POWER_STATS_THROTTLE_PERIOD_CPU =
563                     TimeUnit.MINUTES.toMillis(1);
564             private long mDefaultPowerStatsThrottlePeriod = DEFAULT_POWER_STATS_THROTTLE_PERIOD;
565             private final Map<String, Long> mPowerStatsThrottlePeriods = new HashMap<>();
566 
Builder()567             public Builder() {
568                 mResetOnUnplugHighBatteryLevel = true;
569                 mResetOnUnplugAfterSignificantCharge = true;
570                 setPowerStatsThrottlePeriodMillis(BatteryConsumer.powerComponentIdToString(
571                                 BatteryConsumer.POWER_COMPONENT_CPU),
572                         DEFAULT_POWER_STATS_THROTTLE_PERIOD_CPU);
573             }
574 
575             /**
576              * Build the BatteryStatsConfig.
577              */
build()578             public BatteryStatsConfig build() {
579                 return new BatteryStatsConfig(this);
580             }
581 
582             /**
583              * Set whether a BatteryStats reset should occur on unplug when the battery level is
584              * high.
585              */
setResetOnUnplugHighBatteryLevel(boolean reset)586             public Builder setResetOnUnplugHighBatteryLevel(boolean reset) {
587                 mResetOnUnplugHighBatteryLevel = reset;
588                 return this;
589             }
590 
591             /**
592              * Set whether a BatteryStats reset should occur on unplug if the battery charge a
593              * significant amount since it has been plugged in.
594              */
setResetOnUnplugAfterSignificantCharge(boolean reset)595             public Builder setResetOnUnplugAfterSignificantCharge(boolean reset) {
596                 mResetOnUnplugAfterSignificantCharge = reset;
597                 return this;
598             }
599 
600             /**
601              * Sets the minimum amount of time (in millis) to wait between passes
602              * of power stats collection for the specified power component.
603              */
setPowerStatsThrottlePeriodMillis(String powerComponentName, long periodMs)604             public Builder setPowerStatsThrottlePeriodMillis(String powerComponentName,
605                     long periodMs) {
606                 mPowerStatsThrottlePeriods.put(powerComponentName, periodMs);
607                 return this;
608             }
609 
610             /**
611              * Sets the minimum amount of time (in millis) to wait between passes
612              * of power stats collection for any components not configured explicitly.
613              */
setDefaultPowerStatsThrottlePeriodMillis(long periodMs)614             public Builder setDefaultPowerStatsThrottlePeriodMillis(long periodMs) {
615                 mDefaultPowerStatsThrottlePeriod = periodMs;
616                 return this;
617             }
618         }
619     }
620 
621     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
622 
623     private final Runnable mDeferSetCharging = new Runnable() {
624         @Override
625         public void run() {
626             synchronized (BatteryStatsImpl.this) {
627                 if (mOnBattery) {
628                     // if the device gets unplugged in the time between this runnable being
629                     // executed and the lock being taken, we don't want to set charging state
630                     return;
631                 }
632                 boolean changed = setChargingLocked(true);
633                 if (changed) {
634                     final long uptimeMs = mClock.uptimeMillis();
635                     final long elapsedRealtimeMs = mClock.elapsedRealtime();
636                     mHistory.writeHistoryItem(elapsedRealtimeMs, uptimeMs);
637                 }
638             }
639         }
640     };
641 
642     public final EnergyStatsRetriever mEnergyConsumerRetriever;
643 
644     /**
645      * This handler is running on {@link BackgroundThread}.
646      */
647     final class MyHandler extends Handler {
MyHandler(Looper looper)648         public MyHandler(Looper looper) {
649             super(looper, null, true);
650         }
651 
652         @Override
handleMessage(Message msg)653         public void handleMessage(Message msg) {
654             BatteryCallback cb = mCallback;
655             switch (msg.what) {
656                 case MSG_REPORT_CPU_UPDATE_NEEDED:
657                     if (cb != null) {
658                         cb.batteryNeedsCpuUpdate();
659                     }
660                     break;
661                 case MSG_REPORT_POWER_CHANGE:
662                     if (cb != null) {
663                         cb.batteryPowerChanged(msg.arg1 != 0);
664                     }
665                     break;
666                 case MSG_REPORT_CHARGING:
667                     if (cb != null) {
668                         final String action;
669                         synchronized (BatteryStatsImpl.this) {
670                             action = mCharging ? BatteryManager.ACTION_CHARGING
671                                     : BatteryManager.ACTION_DISCHARGING;
672                         }
673                         Intent intent = new Intent(action);
674                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
675                         cb.batterySendBroadcast(intent);
676                     }
677                     break;
678                 case MSG_REPORT_RESET_STATS:
679                     if (cb != null) {
680                         cb.batteryStatsReset();
681                     }
682                 }
683         }
684     }
685 
postBatteryNeedsCpuUpdateMsg()686     public void postBatteryNeedsCpuUpdateMsg() {
687         mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED);
688     }
689 
690     /**
691      * Update per-freq cpu times for the supplied UID.
692      */
693     @GuardedBy("this")
694     @SuppressWarnings("GuardedBy")    // errorprone false positive on getProcStateTimeCounter
695     @VisibleForTesting
updateProcStateCpuTimesLocked(int uid, long elapsedRealtimeMs, long uptimeMs)696     public void updateProcStateCpuTimesLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
697         if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
698             return;
699         }
700 
701         ensureKernelSingleUidTimeReaderLocked();
702 
703         final Uid u = getUidStatsLocked(uid);
704 
705         mNumSingleUidCpuTimeReads++;
706 
707         LongArrayMultiStateCounter onBatteryCounter =
708                 u.getProcStateTimeCounter(elapsedRealtimeMs).getCounter();
709         LongArrayMultiStateCounter onBatteryScreenOffCounter =
710                 u.getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter();
711 
712 
713         mKernelSingleUidTimeReader.addDelta(uid, onBatteryCounter, elapsedRealtimeMs);
714         mKernelSingleUidTimeReader.addDelta(uid, onBatteryScreenOffCounter, elapsedRealtimeMs);
715 
716         if (u.mChildUids != null) {
717             LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
718                     getCpuTimeInFreqContainer();
719             int childUidCount = u.mChildUids.size();
720             for (int j = childUidCount - 1; j >= 0; --j) {
721                 LongArrayMultiStateCounter cpuTimeInFreqCounter =
722                         u.mChildUids.valueAt(j).cpuTimeInFreqCounter;
723                 if (cpuTimeInFreqCounter != null) {
724                     mKernelSingleUidTimeReader.addDelta(u.mChildUids.keyAt(j),
725                             cpuTimeInFreqCounter, elapsedRealtimeMs, deltaContainer);
726                     onBatteryCounter.addCounts(deltaContainer);
727                     onBatteryScreenOffCounter.addCounts(deltaContainer);
728                 }
729             }
730         }
731     }
732 
733     /**
734      * Removes kernel CPU stats for removed UIDs, in the order they were added to the
735      * mPendingRemovedUids queue.
736      */
737     @GuardedBy("this")
738     @SuppressWarnings("GuardedBy")    // errorprone false positive on removeLocked
clearPendingRemovedUidsLocked()739     public void clearPendingRemovedUidsLocked() {
740         long cutOffTimeMs = mClock.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS;
741         while (!mPendingRemovedUids.isEmpty()
742                 && mPendingRemovedUids.peek().getUidRemovalTimestamp() < cutOffTimeMs) {
743             mPendingRemovedUids.poll().removeLocked();
744         }
745     }
746 
747     /**
748      * When the battery/screen state changes, we don't attribute the cpu times to any process
749      * but we still need to take snapshots of all uids to get correct deltas later on.
750      */
751     @SuppressWarnings("GuardedBy")    // errorprone false positive on getProcStateTimeCounter
updateCpuTimesForAllUids()752     public void updateCpuTimesForAllUids() {
753         if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
754             mCpuPowerStatsCollector.schedule();
755             return;
756         }
757 
758         synchronized (BatteryStatsImpl.this) {
759             if (!trackPerProcStateCpuTimes()) {
760                 return;
761             }
762 
763             ensureKernelSingleUidTimeReaderLocked();
764 
765             // TODO(b/197162116): just get a list of UIDs
766             final SparseArray<long[]> allUidCpuFreqTimesMs =
767                     mCpuUidFreqTimeReader.getAllUidCpuFreqTimeMs();
768             for (int i = allUidCpuFreqTimesMs.size() - 1; i >= 0; --i) {
769                 final int uid = allUidCpuFreqTimesMs.keyAt(i);
770                 final int parentUid = mapUid(uid);
771                 final Uid u = getAvailableUidStatsLocked(parentUid);
772                 if (u == null) {
773                     continue;
774                 }
775 
776                 final int procState = u.mProcessState;
777                 if (procState == Uid.PROCESS_STATE_NONEXISTENT) {
778                     continue;
779                 }
780 
781                 final long elapsedRealtimeMs = mClock.elapsedRealtime();
782                 final long uptimeMs = mClock.uptimeMillis();
783                 final LongArrayMultiStateCounter onBatteryCounter =
784                         u.getProcStateTimeCounter(elapsedRealtimeMs).getCounter();
785                 final LongArrayMultiStateCounter onBatteryScreenOffCounter =
786                         u.getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter();
787 
788                 if (uid == parentUid || Process.isSdkSandboxUid(uid)) {
789                     mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryCounter,
790                             elapsedRealtimeMs);
791                     mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryScreenOffCounter,
792                             elapsedRealtimeMs);
793                 } else {
794                     Uid.ChildUid childUid = u.getChildUid(uid);
795                     if (childUid != null) {
796                         final LongArrayMultiStateCounter counter = childUid.cpuTimeInFreqCounter;
797                         if (counter != null) {
798                             final LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
799                                     getCpuTimeInFreqContainer();
800                             mKernelSingleUidTimeReader.addDelta(uid, counter, elapsedRealtimeMs,
801                                     deltaContainer);
802                             onBatteryCounter.addCounts(deltaContainer);
803                             onBatteryScreenOffCounter.addCounts(deltaContainer);
804                         }
805                     }
806                 }
807             }
808         }
809     }
810 
811     @GuardedBy("this")
ensureKernelSingleUidTimeReaderLocked()812     private void ensureKernelSingleUidTimeReaderLocked() {
813         if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)
814                 || mKernelSingleUidTimeReader != null) {
815             return;
816         }
817 
818         mKernelSingleUidTimeReader = new KernelSingleUidTimeReader(
819                 mCpuScalingPolicies.getScalingStepCount());
820         mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.perClusterTimesAvailable()
821                 && mKernelSingleUidTimeReader.singleUidCpuTimesAvailable();
822     }
823 
824     public interface ExternalStatsSync {
825         int UPDATE_CPU = 0x01;
826         int UPDATE_WIFI = 0x02;
827         int UPDATE_RADIO = 0x04;
828         int UPDATE_BT = 0x08;
829         int UPDATE_RPM = 0x10;
830         int UPDATE_DISPLAY = 0x20;
831         int UPDATE_CAMERA = 0x40;
832         int RESET = 0x80;
833 
834         int UPDATE_ALL =
835                 UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM | UPDATE_DISPLAY
836                         | UPDATE_CAMERA;
837 
838         int UPDATE_ON_PROC_STATE_CHANGE = UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
839 
840         int UPDATE_ON_RESET = UPDATE_ALL | RESET;
841 
842         @IntDef(flag = true, prefix = "UPDATE_", value = {
843                 UPDATE_CPU,
844                 UPDATE_WIFI,
845                 UPDATE_RADIO,
846                 UPDATE_BT,
847                 UPDATE_RPM,
848                 UPDATE_DISPLAY,
849                 UPDATE_CAMERA,
850                 UPDATE_ALL,
851         })
852         @Retention(RetentionPolicy.SOURCE)
853         public @interface ExternalUpdateFlag {
854         }
855 
scheduleSync(String reason, int flags)856         Future<?> scheduleSync(String reason, int flags);
scheduleCpuSyncDueToRemovedUid(int uid)857         Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
858 
859         /**
860          * Schedule a sync because of a screen state change.
861          */
scheduleSyncDueToScreenStateChange(int flags, boolean onBattery, boolean onBatteryScreenOff, int screenState, int[] perDisplayScreenStates)862         Future<?> scheduleSyncDueToScreenStateChange(int flags, boolean onBattery,
863                 boolean onBatteryScreenOff, int screenState, int[] perDisplayScreenStates);
scheduleCpuSyncDueToWakelockChange(long delayMillis)864         Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis);
cancelCpuSyncDueToWakelockChange()865         void cancelCpuSyncDueToWakelockChange();
scheduleSyncDueToBatteryLevelChange(long delayMillis)866         Future<?> scheduleSyncDueToBatteryLevelChange(long delayMillis);
867         /** Schedule removal of UIDs corresponding to a removed user */
scheduleCleanupDueToRemovedUser(int userId)868         Future<?> scheduleCleanupDueToRemovedUser(int userId);
869         /** Schedule a sync because of a process state change */
scheduleSyncDueToProcessStateChange(int flags, long delayMillis)870         void scheduleSyncDueToProcessStateChange(int flags, long delayMillis);
871     }
872 
873     public Handler mHandler;
874     private ExternalStatsSync mExternalSync = null;
875     @VisibleForTesting
876     protected UserInfoProvider mUserInfoProvider = null;
877 
878     private BatteryCallback mCallback;
879 
880     /**
881      * Mapping child uids to their parent uid.
882      */
883     @VisibleForTesting
884     protected final PowerStatsUidResolver mPowerStatsUidResolver;
885 
886     /**
887      * The statistics we have collected organized by uids.
888      */
889     private final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
890 
891     // A set of pools of currently active timers.  When a timer is queried, we will divide the
892     // elapsed time by the number of active timers to arrive at that timer's share of the time.
893     // In order to do this, we must refresh each timer whenever the number of active timers
894     // changes.
895     @VisibleForTesting
896     protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
897     private final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
898     private final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
899     private final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
900     private final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
901     private final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
902     private final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
903     private final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
904     private final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
905     private final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers =
906             new SparseArray<>();
907     private final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
908     private final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
909     private final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
910     private final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
911     private final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
912 
913     // Last partial timers we use for distributing CPU usage.
914     @VisibleForTesting
915     protected ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
916 
917     // These are the objects that will want to do something when the device
918     // is unplugged from power.
919     protected final TimeBase mOnBatteryTimeBase = new TimeBase(true);
920 
921     // These are the objects that will want to do something when the device
922     // is unplugged from power *and* the screen is off or doze.
923     protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(true);
924 
925     private boolean mSystemReady;
926     private boolean mShuttingDown;
927 
928     private final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
929     private final HistoryStepDetailsCalculatorImpl mStepDetailsCalculator =
930             new HistoryStepDetailsCalculatorImpl();
931 
932     private boolean mHaveBatteryLevel = false;
933     private boolean mBatteryPluggedIn;
934     private long mBatteryPluggedInRealTimeMs = 0;
935     private int mBatteryStatus;
936     private int mBatteryLevel;
937     private int mBatteryPlugType;
938     private int mBatteryChargeUah;
939     private int mBatteryHealth;
940     private int mBatteryTemperature;
941     private int mBatteryVoltageMv;
942 
943     @NonNull
944     private final BatteryStatsHistory mHistory;
945 
946     int mStartCount;
947 
948     /**
949      * Set to true when a reset occurs, informing us that the next time BatteryExternalStatsWorker
950      * gives us data, we mustn't process it since this data includes pre-reset-period data.
951      */
952     @GuardedBy("this")
953     boolean mIgnoreNextExternalStats = false;
954 
955     long mStartClockTimeMs;
956     String mStartPlatformVersion;
957     String mEndPlatformVersion;
958 
959     long mUptimeUs;
960     long mUptimeStartUs;
961     long mRealtimeUs;
962     long mRealtimeStartUs;
963     long mMonotonicStartTime;
964     long mMonotonicEndTime = MonotonicClock.UNDEFINED;
965 
966     int mWakeLockNesting;
967     boolean mWakeLockImportant;
968     public boolean mRecordAllHistory;
969     boolean mNoAutoReset;
970 
971     /**
972      * Overall screen state. For multidisplay devices, this represents the current highest screen
973      * state of the displays.
974      */
975     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
976     protected int mScreenState = Display.STATE_UNKNOWN;
977     /**
978      * Overall screen on timer. For multidisplay devices, this represents the time spent with at
979      * least one display in the screen on state.
980      */
981     StopwatchTimer mScreenOnTimer;
982     /**
983      * Overall screen doze timer. For multidisplay devices, this represents the time spent with
984      * screen doze being the highest screen state.
985      */
986     StopwatchTimer mScreenDozeTimer;
987     /**
988      * Overall screen brightness bin. For multidisplay devices, this represents the current
989      * brightest screen.
990      */
991     int mScreenBrightnessBin = -1;
992     /**
993      * Overall screen brightness timers. For multidisplay devices, the {@link mScreenBrightnessBin}
994      * timer will be active at any given time
995      */
996     final StopwatchTimer[] mScreenBrightnessTimer =
997             new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
998 
999     boolean mPretendScreenOff;
1000 
1001     private static class DisplayBatteryStats {
1002         /**
1003          * Per display screen state.
1004          */
1005         public int screenState = Display.STATE_UNKNOWN;
1006         /**
1007          * Per display screen on timers.
1008          */
1009         public StopwatchTimer screenOnTimer;
1010         /**
1011          * Per display screen doze timers.
1012          */
1013         public StopwatchTimer screenDozeTimer;
1014         /**
1015          * Per display screen brightness bins.
1016          */
1017         public int screenBrightnessBin = -1;
1018         /**
1019          * Per display screen brightness timers.
1020          */
1021         public StopwatchTimer[] screenBrightnessTimers =
1022                 new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
1023         /**
1024          * Per display screen state the last time {@link #updateDisplayEnergyConsumerStatsLocked}
1025          * was called.
1026          */
1027         public int screenStateAtLastEnergyMeasurement = Display.STATE_UNKNOWN;
1028 
DisplayBatteryStats(Clock clock, TimeBase timeBase)1029         DisplayBatteryStats(Clock clock, TimeBase timeBase) {
1030             screenOnTimer = new StopwatchTimer(clock, null, -1, null,
1031                     timeBase);
1032             screenDozeTimer = new StopwatchTimer(clock, null, -1, null,
1033                     timeBase);
1034             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1035                 screenBrightnessTimers[i] = new StopwatchTimer(clock, null, -100 - i, null,
1036                         timeBase);
1037             }
1038         }
1039 
1040         /**
1041          * Reset display timers.
1042          */
reset(long elapsedRealtimeUs)1043         public void reset(long elapsedRealtimeUs) {
1044             screenOnTimer.reset(false, elapsedRealtimeUs);
1045             screenDozeTimer.reset(false, elapsedRealtimeUs);
1046             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1047                 screenBrightnessTimers[i].reset(false, elapsedRealtimeUs);
1048             }
1049         }
1050 
1051         /**
1052          * Write data to summary parcel
1053          */
writeSummaryToParcel(Parcel out, long elapsedRealtimeUs)1054         public void writeSummaryToParcel(Parcel out, long elapsedRealtimeUs) {
1055             screenOnTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
1056             screenDozeTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
1057             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1058                 screenBrightnessTimers[i].writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
1059             }
1060         }
1061 
1062         /**
1063          * Read data from summary parcel
1064          */
readSummaryFromParcel(Parcel in)1065         public void readSummaryFromParcel(Parcel in) {
1066             screenOnTimer.readSummaryFromParcelLocked(in);
1067             screenDozeTimer.readSummaryFromParcelLocked(in);
1068             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1069                 screenBrightnessTimers[i].readSummaryFromParcelLocked(in);
1070             }
1071         }
1072     }
1073 
1074     DisplayBatteryStats[] mPerDisplayBatteryStats;
1075 
1076     private int mDisplayMismatchWtfCount = 0;
1077 
1078     boolean mInteractive;
1079     StopwatchTimer mInteractiveTimer;
1080 
1081     boolean mPowerSaveModeEnabled;
1082     StopwatchTimer mPowerSaveModeEnabledTimer;
1083 
1084     boolean mDeviceIdling;
1085     StopwatchTimer mDeviceIdlingTimer;
1086 
1087     boolean mDeviceLightIdling;
1088     StopwatchTimer mDeviceLightIdlingTimer;
1089 
1090     int mDeviceIdleMode;
1091     long mLastIdleTimeStartMs;
1092     long mLongestLightIdleTimeMs;
1093     long mLongestFullIdleTimeMs;
1094     StopwatchTimer mDeviceIdleModeLightTimer;
1095     StopwatchTimer mDeviceIdleModeFullTimer;
1096 
1097     boolean mPhoneOn;
1098     StopwatchTimer mPhoneOnTimer;
1099 
1100     int mAudioOnNesting;
1101     StopwatchTimer mAudioOnTimer;
1102 
1103     int mVideoOnNesting;
1104     StopwatchTimer mVideoOnTimer;
1105 
1106     int mFlashlightOnNesting;
1107     StopwatchTimer mFlashlightOnTimer;
1108 
1109     int mCameraOnNesting;
1110     StopwatchTimer mCameraOnTimer;
1111 
1112     private static final int USB_DATA_UNKNOWN = 0;
1113     private static final int USB_DATA_DISCONNECTED = 1;
1114     private static final int USB_DATA_CONNECTED = 2;
1115     int mUsbDataState = USB_DATA_UNKNOWN;
1116 
1117     private static final int GPS_SIGNAL_QUALITY_NONE = 2;
1118     int mGpsSignalQualityBin = -1;
1119     final StopwatchTimer[] mGpsSignalQualityTimer =
1120         new StopwatchTimer[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
1121 
1122     int mPhoneSignalStrengthBin = -1;
1123     int mPhoneSignalStrengthBinRaw = -1;
1124     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
1125             new StopwatchTimer[CELL_SIGNAL_STRENGTH_LEVEL_COUNT];
1126 
1127     StopwatchTimer mPhoneSignalScanningTimer;
1128 
1129     int mPhoneDataConnectionType = -1;
1130     final StopwatchTimer[] mPhoneDataConnectionsTimer =
1131             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
1132 
1133     int mNrState = -1;
1134     StopwatchTimer mNrNsaTimer;
1135 
1136     @RadioAccessTechnology
1137     int mActiveRat = RADIO_ACCESS_TECHNOLOGY_OTHER;
1138 
1139     private static class RadioAccessTechnologyBatteryStats {
1140         /**
1141          * This RAT is currently being used.
1142          */
1143         private boolean mActive = false;
1144         /**
1145          * Current active frequency range for this RAT.
1146          */
1147         @ServiceState.FrequencyRange
1148         private int mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
1149         /**
1150          * Current signal strength for this RAT.
1151          */
1152         private int mSignalStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
1153         /**
1154          * Timers for each combination of frequency range and signal strength.
1155          */
1156         public final StopwatchTimer[][] perStateTimers;
1157         /**
1158          * Counters tracking the time (in milliseconds) spent transmitting data in a given state.
1159          */
1160         @Nullable
1161         private LongSamplingCounter[][] mPerStateTxDurationMs = null;
1162         /**
1163          * Counters tracking the time (in milliseconds) spent receiving data in at given frequency.
1164          */
1165         @Nullable
1166         private LongSamplingCounter[] mPerFrequencyRxDurationMs = null;
1167 
RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase)1168         RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase) {
1169             perStateTimers =
1170                     new StopwatchTimer[freqCount][CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS];
1171             for (int i = 0; i < freqCount; i++) {
1172                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1173                     perStateTimers[i][j] = new StopwatchTimer(clock, null, -1, null, timeBase);
1174                 }
1175             }
1176         }
1177 
1178         /**
1179          * Note this RAT is currently being used.
1180          */
noteActive(boolean active, long elapsedRealtimeMs)1181         public void noteActive(boolean active, long elapsedRealtimeMs) {
1182             if (mActive == active) return;
1183             mActive = active;
1184             if (mActive) {
1185                 perStateTimers[mFrequencyRange][mSignalStrength].startRunningLocked(
1186                         elapsedRealtimeMs);
1187             } else {
1188                 perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(
1189                         elapsedRealtimeMs);
1190             }
1191         }
1192 
1193         /**
1194          * Note current frequency range has changed.
1195          */
noteFrequencyRange(@erviceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs)1196         public void noteFrequencyRange(@ServiceState.FrequencyRange int frequencyRange,
1197                 long elapsedRealtimeMs) {
1198             if (mFrequencyRange == frequencyRange) return;
1199 
1200             if (!mActive) {
1201                 // RAT not in use, note the frequency change and move on.
1202                 mFrequencyRange = frequencyRange;
1203                 return;
1204             }
1205             perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(elapsedRealtimeMs);
1206             perStateTimers[frequencyRange][mSignalStrength].startRunningLocked(elapsedRealtimeMs);
1207             mFrequencyRange = frequencyRange;
1208         }
1209 
1210         /**
1211          * Note current signal strength has changed.
1212          */
noteSignalStrength(int signalStrength, long elapsedRealtimeMs)1213         public void noteSignalStrength(int signalStrength, long elapsedRealtimeMs) {
1214             if (mSignalStrength == signalStrength) return;
1215 
1216             if (!mActive) {
1217                 // RAT not in use, note the signal strength change and move on.
1218                 mSignalStrength = signalStrength;
1219                 return;
1220             }
1221             perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(elapsedRealtimeMs);
1222             perStateTimers[mFrequencyRange][signalStrength].startRunningLocked(elapsedRealtimeMs);
1223             mSignalStrength = signalStrength;
1224         }
1225 
1226         /**
1227          * Returns the duration in milliseconds spent in a given state since the last mark.
1228          */
getTimeSinceMark(@erviceState.FrequencyRange int frequencyRange, int signalStrength, long elapsedRealtimeMs)1229         public long getTimeSinceMark(@ServiceState.FrequencyRange int frequencyRange,
1230                 int signalStrength, long elapsedRealtimeMs) {
1231             return perStateTimers[frequencyRange][signalStrength].getTimeSinceMarkLocked(
1232                     elapsedRealtimeMs * 1000) / 1000;
1233         }
1234 
1235         /**
1236          * Set mark for all timers.
1237          */
setMark(long elapsedRealtimeMs)1238         public void setMark(long elapsedRealtimeMs) {
1239             final int size = perStateTimers.length;
1240             for (int i = 0; i < size; i++) {
1241                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1242                     perStateTimers[i][j].setMark(elapsedRealtimeMs);
1243                 }
1244             }
1245         }
1246 
1247         /**
1248          * Returns numbers of frequencies tracked for this RAT.
1249          */
getFrequencyRangeCount()1250         public int getFrequencyRangeCount() {
1251             return perStateTimers.length;
1252         }
1253 
1254         /**
1255          * Add TX time for a given state.
1256          */
incrementTxDuration(@erviceState.FrequencyRange int frequencyRange, int signalStrength, long durationMs)1257         public void incrementTxDuration(@ServiceState.FrequencyRange int frequencyRange,
1258                 int signalStrength, long durationMs) {
1259             getTxDurationCounter(frequencyRange, signalStrength, true).addCountLocked(durationMs);
1260         }
1261 
1262         /**
1263          * Add TX time for a given frequency.
1264          */
incrementRxDuration(@erviceState.FrequencyRange int frequencyRange, long durationMs)1265         public void incrementRxDuration(@ServiceState.FrequencyRange int frequencyRange,
1266                 long durationMs) {
1267             getRxDurationCounter(frequencyRange, true).addCountLocked(durationMs);
1268         }
1269 
1270         /**
1271          * Reset radio access technology timers and counts.
1272          */
reset(long elapsedRealtimeUs)1273         public void reset(long elapsedRealtimeUs) {
1274             final int size = perStateTimers.length;
1275             for (int i = 0; i < size; i++) {
1276                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1277                     perStateTimers[i][j].reset(false, elapsedRealtimeUs);
1278                     if (mPerStateTxDurationMs == null) continue;
1279                     mPerStateTxDurationMs[i][j].reset(false, elapsedRealtimeUs);
1280                 }
1281                 if (mPerFrequencyRxDurationMs == null) continue;
1282                 mPerFrequencyRxDurationMs[i].reset(false, elapsedRealtimeUs);
1283             }
1284         }
1285 
1286         /**
1287          * Write data to summary parcel
1288          */
writeSummaryToParcel(Parcel out, long elapsedRealtimeUs)1289         public void writeSummaryToParcel(Parcel out, long elapsedRealtimeUs) {
1290             final int freqCount = perStateTimers.length;
1291             out.writeInt(freqCount);
1292             out.writeInt(CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS);
1293             for (int i = 0; i < freqCount; i++) {
1294                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1295                     perStateTimers[i][j].writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
1296                 }
1297             }
1298 
1299             if (mPerStateTxDurationMs == null) {
1300                 out.writeInt(0);
1301             } else {
1302                 out.writeInt(1);
1303                 for (int i = 0; i < freqCount; i++) {
1304                     for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1305                         mPerStateTxDurationMs[i][j].writeSummaryFromParcelLocked(out);
1306                     }
1307                 }
1308             }
1309 
1310             if (mPerFrequencyRxDurationMs == null) {
1311                 out.writeInt(0);
1312             } else {
1313                 out.writeInt(1);
1314                 for (int i = 0; i < freqCount; i++) {
1315                     mPerFrequencyRxDurationMs[i].writeSummaryFromParcelLocked(out);
1316                 }
1317             }
1318         }
1319 
1320         /**
1321          * Read data from summary parcel
1322          */
readSummaryFromParcel(Parcel in)1323         public void readSummaryFromParcel(Parcel in) {
1324             final int oldFreqCount = in.readInt();
1325             final int oldSignalStrengthCount = in.readInt();
1326             final int currFreqCount = perStateTimers.length;
1327             final int currSignalStrengthCount = CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS;
1328 
1329             for (int freq = 0; freq < oldFreqCount; freq++) {
1330                 for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
1331                     if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
1332                         // Mismatch with the summary parcel. Consume the data but don't use it.
1333                         final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
1334                                 new TimeBase());
1335                         // Consume perStateTimers data.
1336                         temp.readSummaryFromParcelLocked(in);
1337                     } else {
1338                         perStateTimers[freq][strength].readSummaryFromParcelLocked(in);
1339                     }
1340                 }
1341             }
1342 
1343             if (in.readInt() == 1) {
1344                 for (int freq = 0; freq < oldFreqCount; freq++) {
1345                     for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
1346                         if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
1347                             // Mismatch with the summary parcel. Consume the data but don't use it.
1348                             final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
1349                                     new TimeBase());
1350                             // Consume mPerStateTxDurationMs data.
1351                             temp.readSummaryFromParcelLocked(in);
1352                         }
1353                         getTxDurationCounter(freq, strength, true).readSummaryFromParcelLocked(in);
1354                     }
1355                 }
1356             }
1357 
1358             if (in.readInt() == 1) {
1359                 for (int freq = 0; freq < oldFreqCount; freq++) {
1360                     if (freq >= currFreqCount) {
1361                         // Mismatch with the summary parcel. Consume the data but don't use it.
1362                         final StopwatchTimer
1363                                 temp = new StopwatchTimer(null, null, -1, null, new TimeBase());
1364                         // Consume mPerFrequencyRxDurationMs data.
1365                         temp.readSummaryFromParcelLocked(in);
1366                         continue;
1367                     }
1368                     getRxDurationCounter(freq, true).readSummaryFromParcelLocked(in);
1369                 }
1370             }
1371         }
1372 
getTxDurationCounter( @erviceState.FrequencyRange int frequencyRange, int signalStrength, boolean make)1373         private LongSamplingCounter getTxDurationCounter(
1374                 @ServiceState.FrequencyRange int frequencyRange, int signalStrength, boolean make) {
1375             if (mPerStateTxDurationMs == null) {
1376                 if (!make) return null;
1377 
1378                 final int freqCount = getFrequencyRangeCount();
1379                 final int signalStrengthCount = perStateTimers[0].length;
1380                 final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
1381                 mPerStateTxDurationMs = new LongSamplingCounter[freqCount][signalStrengthCount];
1382                 for (int freq = 0; freq < freqCount; freq++) {
1383                     for (int strength = 0; strength < signalStrengthCount; strength++) {
1384                         mPerStateTxDurationMs[freq][strength] = new LongSamplingCounter(timeBase);
1385                     }
1386                 }
1387             }
1388             if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
1389                 Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
1390                         + ") requested in getTxDurationCounter");
1391                 return null;
1392             }
1393             if (signalStrength < 0 || signalStrength >= perStateTimers[0].length) {
1394                 Slog.w(TAG, "Unexpected signal strength (" + signalStrength
1395                         + ") requested in getTxDurationCounter");
1396                 return null;
1397             }
1398             return mPerStateTxDurationMs[frequencyRange][signalStrength];
1399         }
1400 
getRxDurationCounter( @erviceState.FrequencyRange int frequencyRange, boolean make)1401         private LongSamplingCounter getRxDurationCounter(
1402                 @ServiceState.FrequencyRange int frequencyRange, boolean make) {
1403             if (mPerFrequencyRxDurationMs == null) {
1404                 if (!make) return null;
1405 
1406                 final int freqCount = getFrequencyRangeCount();
1407                 final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
1408                 mPerFrequencyRxDurationMs = new LongSamplingCounter[freqCount];
1409                 for (int freq = 0; freq < freqCount; freq++) {
1410                     mPerFrequencyRxDurationMs[freq] = new LongSamplingCounter(timeBase);
1411                 }
1412             }
1413             if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
1414                 Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
1415                         + ") requested in getRxDurationCounter");
1416                 return null;
1417             }
1418             return mPerFrequencyRxDurationMs[frequencyRange];
1419         }
1420     }
1421 
1422     /**
1423      * Number of frequency ranges, keep in sync with {@link ServiceState.FrequencyRange}
1424      */
1425     private static final int NR_FREQUENCY_COUNT = 5;
1426 
1427     RadioAccessTechnologyBatteryStats[] mPerRatBatteryStats =
1428             new RadioAccessTechnologyBatteryStats[RADIO_ACCESS_TECHNOLOGY_COUNT];
1429 
1430     @GuardedBy("this")
getRatBatteryStatsLocked( @adioAccessTechnology int rat)1431     private RadioAccessTechnologyBatteryStats getRatBatteryStatsLocked(
1432             @RadioAccessTechnology int rat) {
1433         RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
1434         if (stats == null) {
1435             final int freqCount = rat == RADIO_ACCESS_TECHNOLOGY_NR ? NR_FREQUENCY_COUNT : 1;
1436             stats = new RadioAccessTechnologyBatteryStats(freqCount, mClock, mOnBatteryTimeBase);
1437             mPerRatBatteryStats[rat] = stats;
1438         }
1439         return stats;
1440     }
1441 
1442     final LongSamplingCounter[] mNetworkByteActivityCounters =
1443             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
1444 
1445     final LongSamplingCounter[] mNetworkPacketActivityCounters =
1446             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
1447 
1448     /**
1449      * The WiFi Overall wakelock timer
1450      * This timer tracks the actual aggregate time for which MC wakelocks are enabled
1451      * since addition of per UID timers would not result in an accurate value due to overlapp of
1452      * per uid wakelock timers
1453      */
1454     StopwatchTimer mWifiMulticastWakelockTimer;
1455 
1456     /**
1457      * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
1458      */
1459     ControllerActivityCounterImpl mWifiActivity;
1460 
1461     /**
1462      * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
1463      */
1464     ControllerActivityCounterImpl mBluetoothActivity;
1465 
1466     /**
1467      * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
1468      */
1469     ControllerActivityCounterImpl mModemActivity;
1470 
1471     /**
1472      * Whether the device supports WiFi controller energy reporting. This is set to true on
1473      * the first WiFi energy report. See {@link #mWifiActivity}.
1474      */
1475     boolean mHasWifiReporting = false;
1476 
1477     /**
1478      * Whether the device supports Bluetooth controller energy reporting. This is set to true on
1479      * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
1480      */
1481     boolean mHasBluetoothReporting = false;
1482 
1483     /**
1484      * Whether the device supports Modem controller energy reporting. This is set to true on
1485      * the first Modem energy report. See {@link #mModemActivity}.
1486      */
1487     boolean mHasModemReporting = false;
1488 
1489     boolean mWifiOn;
1490     StopwatchTimer mWifiOnTimer;
1491 
1492     boolean mGlobalWifiRunning;
1493     StopwatchTimer mGlobalWifiRunningTimer;
1494 
1495     int mWifiState = -1;
1496     final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
1497 
1498     int mWifiSupplState = -1;
1499     final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
1500 
1501     int mWifiSignalStrengthBin = -1;
1502     final StopwatchTimer[] mWifiSignalStrengthsTimer =
1503             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
1504 
1505     StopwatchTimer mWifiActiveTimer;
1506 
1507     int mBluetoothScanNesting;
1508     StopwatchTimer mBluetoothScanTimer;
1509 
1510     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
1511     long mMobileRadioActiveStartTimeMs;
1512     StopwatchTimer mMobileRadioActiveTimer;
1513     StopwatchTimer mMobileRadioActivePerAppTimer;
1514     LongSamplingCounter mMobileRadioActiveAdjustedTime;
1515     LongSamplingCounter mMobileRadioActiveUnknownTime;
1516     LongSamplingCounter mMobileRadioActiveUnknownCount;
1517 
1518     /**
1519      * The soonest the Mobile Radio stats can be updated due to a mobile radio power state change
1520      * after it was last updated.
1521      */
1522     @VisibleForTesting
1523     protected static final long MOBILE_RADIO_POWER_STATE_UPDATE_FREQ_MS = 1000 * 60 * 10;
1524 
1525     int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
1526 
1527     @GuardedBy("this")
1528     @VisibleForTesting
1529     protected @Nullable EnergyConsumerStats.Config mEnergyConsumerStatsConfig;
1530 
1531     /**
1532      * Accumulated global (generally, device-wide total) charge consumption of various consumers
1533      * while on battery.
1534      * Its '<b>custom</b> power buckets' correspond to the
1535      * {@link android.hardware.power.stats.EnergyConsumer.ordinal}s of (custom) energy consumer
1536      * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
1537      *
1538      * If energy consumer data is completely unavailable this will be null.
1539      */
1540     @GuardedBy("this")
1541     @VisibleForTesting
1542     @Nullable
1543     protected EnergyConsumerStats mGlobalEnergyConsumerStats;
1544     /** Bluetooth Power calculator for attributing bluetooth EnergyConsumer to uids */
1545     @Nullable BluetoothPowerCalculator mBluetoothPowerCalculator = null;
1546     /** Cpu Power calculator for attributing cpu EnergyConsumer to uids */
1547     @Nullable CpuPowerCalculator mCpuPowerCalculator = null;
1548     /** Mobile Radio Power calculator for attributing radio EnergyConsumer to uids */
1549     @Nullable MobileRadioPowerCalculator mMobileRadioPowerCalculator = null;
1550     /** Wifi Power calculator for attributing wifi EnergyConsumer to uids */
1551     @Nullable WifiPowerCalculator mWifiPowerCalculator = null;
1552 
1553     /**
1554      * These provide time bases that discount the time the device is plugged
1555      * in to power.
1556      */
1557     boolean mOnBattery;
1558     @VisibleForTesting
1559     protected boolean mOnBatteryInternal;
1560 
1561     /**
1562      * External reporting of whether the device is actually charging.
1563      */
1564     boolean mCharging = true;
1565 
1566     /*
1567      * These keep track of battery levels (1-100) at the last unplug event.
1568      */
1569     int mDischargeUnplugLevel;
1570     int mDischargePlugLevel;
1571     int mDischargeCurrentLevel;
1572     int mLowDischargeAmountSinceCharge;
1573     int mHighDischargeAmountSinceCharge;
1574     int mDischargeScreenOnUnplugLevel;
1575     int mDischargeScreenOffUnplugLevel;
1576     int mDischargeScreenDozeUnplugLevel;
1577     int mDischargeAmountScreenOn;
1578     int mDischargeAmountScreenOnSinceCharge;
1579     int mDischargeAmountScreenOff;
1580     int mDischargeAmountScreenOffSinceCharge;
1581     int mDischargeAmountScreenDoze;
1582     int mDischargeAmountScreenDozeSinceCharge;
1583 
1584     private LongSamplingCounter mDischargeScreenOffCounter;
1585     private LongSamplingCounter mDischargeScreenDozeCounter;
1586     private LongSamplingCounter mDischargeCounter;
1587     private LongSamplingCounter mDischargeLightDozeCounter;
1588     private LongSamplingCounter mDischargeDeepDozeCounter;
1589 
1590     static final int MAX_LEVEL_STEPS = 200;
1591 
1592     int mInitStepMode = 0;
1593     int mCurStepMode = 0;
1594     int mModStepMode = 0;
1595 
1596     int mLastDischargeStepLevel;
1597     int mMinDischargeStepLevel;
1598     final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
1599     final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
1600     ArrayList<PackageChange> mDailyPackageChanges;
1601 
1602     int mLastChargeStepLevel;
1603     int mMaxChargeStepLevel;
1604     final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
1605     final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
1606 
1607     static final int MAX_DAILY_ITEMS = 10;
1608 
1609     long mDailyStartTimeMs = 0;
1610     long mNextMinDailyDeadlineMs = 0;
1611     long mNextMaxDailyDeadlineMs = 0;
1612 
1613     final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
1614 
1615     long mLastWriteTimeMs = 0; // Milliseconds
1616 
1617     private int mPhoneServiceState = -1;
1618     private int mPhoneServiceStateRaw = -1;
1619     private int mPhoneSimStateRaw = -1;
1620 
1621     private int mNumConnectivityChange;
1622 
1623     private int mEstimatedBatteryCapacityMah = -1;
1624 
1625     private int mLastLearnedBatteryCapacityUah = -1;
1626     private int mMinLearnedBatteryCapacityUah = -1;
1627     private int mMaxLearnedBatteryCapacityUah = -1;
1628 
1629     private long mBatteryTimeToFullSeconds = -1;
1630 
1631     private LongArrayMultiStateCounter.LongArrayContainer mTmpCpuTimeInFreq;
1632 
1633     /**
1634      * Times spent by the system server threads handling incoming binder requests.
1635      */
1636     private LongSamplingCounterArray mBinderThreadCpuTimesUs;
1637 
1638     @VisibleForTesting
1639     protected PowerProfile mPowerProfile;
1640 
1641     @VisibleForTesting
1642     @GuardedBy("this")
1643     protected final Constants mConstants;
1644 
1645     @VisibleForTesting
1646     protected final BatteryStatsConfig mBatteryStatsConfig;
1647 
1648     @GuardedBy("this")
1649     private AlarmManager mAlarmManager = null;
1650 
1651     private final AlarmManager.OnAlarmListener mLongPlugInAlarmHandler = () ->
1652             mHandler.post(() -> {
1653                 synchronized (BatteryStatsImpl.this) {
1654                     maybeResetWhilePluggedInLocked();
1655                 }
1656             });
1657 
1658     /*
1659      * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
1660      * recording their times when on-battery (regardless of screen state).
1661      */
1662     private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>();
1663     /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */
1664     private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>();
1665 
1666     @Override
getRpmStats()1667     public Map<String, ? extends Timer> getRpmStats() {
1668         return mRpmStats;
1669     }
1670 
1671     // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED.
1672     @Override
getScreenOffRpmStats()1673     public Map<String, ? extends Timer> getScreenOffRpmStats() {
1674         return mScreenOffRpmStats;
1675     }
1676 
1677     /*
1678      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
1679      */
1680     private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
1681 
getKernelWakelockStats()1682     public Map<String, ? extends Timer> getKernelWakelockStats() {
1683         return mKernelWakelockStats;
1684     }
1685 
1686     @Override
getWakeLockStats()1687     public WakeLockStats getWakeLockStats() {
1688         final long realtimeMs = mClock.elapsedRealtime();
1689         List<WakeLockStats.WakeLock> uidWakeLockStats = new ArrayList<>();
1690         List<WakeLockStats.WakeLock> uidAggregatedWakeLockStats = new ArrayList<>();
1691         for (int i = mUidStats.size() - 1; i >= 0; i--) {
1692             final Uid uid = mUidStats.valueAt(i);
1693 
1694             // Converts unaggregated wakelocks.
1695             final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats =
1696                     uid.mWakelockStats.getMap();
1697             for (int j = wakelockStats.size() - 1; j >= 0; j--) {
1698                 final String name = wakelockStats.keyAt(j);
1699                 final Uid.Wakelock wakelock = (Uid.Wakelock) wakelockStats.valueAt(j);
1700                 final WakeLockStats.WakeLock wakeLockItem =
1701                         createWakeLock(uid, name, /* isAggregated= */ false, wakelock.mTimerPartial,
1702                                 realtimeMs);
1703                 if (wakeLockItem != null) {
1704                     uidWakeLockStats.add(wakeLockItem);
1705                 }
1706             }
1707 
1708             // Converts aggregated wakelocks.
1709             final WakeLockStats.WakeLock aggregatedWakeLockItem =
1710                     createWakeLock(
1711                     uid,
1712                     WakeLockStats.WakeLock.NAME_AGGREGATED,
1713                     /* isAggregated= */ true,
1714                     uid.mAggregatedPartialWakelockTimer,
1715                     realtimeMs);
1716             if (aggregatedWakeLockItem != null) {
1717                 uidAggregatedWakeLockStats.add(aggregatedWakeLockItem);
1718             }
1719         }
1720         return new WakeLockStats(uidWakeLockStats, uidAggregatedWakeLockStats);
1721     }
1722 
1723     // Returns a valid {@code WakeLockStats.WakeLock} or null.
createWakeLock( Uid uid, String name, boolean isAggregated, DualTimer timer, final long realtimeMs)1724     private WakeLockStats.WakeLock createWakeLock(
1725             Uid uid, String name, boolean isAggregated, DualTimer timer, final long realtimeMs) {
1726         if (timer == null) {
1727             return null;
1728         }
1729         // Uses the primary timer for total wakelock data and used the sub timer for background
1730         // wakelock data.
1731         final WakeLockStats.WakeLockData totalWakeLockData = createWakeLockData(timer, realtimeMs);
1732         final WakeLockStats.WakeLockData backgroundWakeLockData =
1733                 createWakeLockData(timer.getSubTimer(), realtimeMs);
1734 
1735         return WakeLockStats.WakeLock.isDataValid(totalWakeLockData, backgroundWakeLockData)
1736                 ? new WakeLockStats.WakeLock(
1737                 uid.getUid(),
1738                 name,
1739                 isAggregated,
1740                 totalWakeLockData,
1741                 backgroundWakeLockData) : null;
1742     }
1743 
1744     @NonNull
createWakeLockData( DurationTimer timer, final long realtimeMs)1745     private WakeLockStats.WakeLockData createWakeLockData(
1746             DurationTimer timer, final long realtimeMs) {
1747         if (timer == null) {
1748             return WakeLockStats.WakeLockData.EMPTY;
1749         }
1750         final long totalTimeLockHeldMs =
1751                 timer.getTotalTimeLocked(realtimeMs * 1000, STATS_SINCE_CHARGED) / 1000;
1752         if (totalTimeLockHeldMs == 0) {
1753             return WakeLockStats.WakeLockData.EMPTY;
1754         }
1755         return new WakeLockStats.WakeLockData(
1756             timer.getCountLocked(STATS_SINCE_CHARGED),
1757             totalTimeLockHeldMs,
1758             timer.isRunningLocked() ? timer.getCurrentDurationMsLocked(realtimeMs) : 0);
1759     }
1760 
1761     @Override
1762     @GuardedBy("this")
getBluetoothBatteryStats()1763     public BluetoothBatteryStats getBluetoothBatteryStats() {
1764         final long elapsedRealtimeUs = mClock.elapsedRealtime() * 1000;
1765         ArrayList<BluetoothBatteryStats.UidStats> uidStats = new ArrayList<>();
1766         for (int i = mUidStats.size() - 1; i >= 0; i--) {
1767             final Uid uid = mUidStats.valueAt(i);
1768             final Timer scanTimer = uid.getBluetoothScanTimer();
1769             final long scanTimeMs =
1770                     scanTimer != null ? scanTimer.getTotalTimeLocked(
1771                             elapsedRealtimeUs, STATS_SINCE_CHARGED) / 1000 : 0;
1772 
1773             final Timer unoptimizedScanTimer = uid.getBluetoothUnoptimizedScanTimer();
1774             final long unoptimizedScanTimeMs =
1775                     unoptimizedScanTimer != null ? unoptimizedScanTimer.getTotalTimeLocked(
1776                             elapsedRealtimeUs, STATS_SINCE_CHARGED) / 1000 : 0;
1777 
1778             final Counter scanResultCounter = uid.getBluetoothScanResultCounter();
1779             final int scanResultCount =
1780                     scanResultCounter != null ? scanResultCounter.getCountLocked(
1781                             STATS_SINCE_CHARGED) : 0;
1782 
1783             final ControllerActivityCounter counter = uid.getBluetoothControllerActivity();
1784             final long rxTimeMs =  counter != null ? counter.getRxTimeCounter().getCountLocked(
1785                     STATS_SINCE_CHARGED) : 0;
1786             final long txTimeMs =  counter != null ? counter.getTxTimeCounters()[0].getCountLocked(
1787                     STATS_SINCE_CHARGED) : 0;
1788 
1789             if (scanTimeMs != 0 || unoptimizedScanTimeMs != 0 || scanResultCount != 0
1790                     || rxTimeMs != 0 || txTimeMs != 0) {
1791                 uidStats.add(new BluetoothBatteryStats.UidStats(uid.getUid(),
1792                         scanTimeMs,
1793                         unoptimizedScanTimeMs,
1794                         scanResultCount,
1795                         rxTimeMs,
1796                         txTimeMs));
1797             }
1798         }
1799 
1800         return new BluetoothBatteryStats(uidStats);
1801     }
1802 
1803     String mLastWakeupReason = null;
1804     long mLastWakeupUptimeMs = 0;
1805     long mLastWakeupElapsedTimeMs = 0;
1806     private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
1807 
getWakeupReasonStats()1808     public Map<String, ? extends Timer> getWakeupReasonStats() {
1809         return mWakeupReasonStats;
1810     }
1811 
1812     @Override
getUahDischarge(int which)1813     public long getUahDischarge(int which) {
1814         return mDischargeCounter.getCountLocked(which);
1815     }
1816 
1817     @Override
getUahDischargeScreenOff(int which)1818     public long getUahDischargeScreenOff(int which) {
1819         return mDischargeScreenOffCounter.getCountLocked(which);
1820     }
1821 
1822     @Override
getUahDischargeScreenDoze(int which)1823     public long getUahDischargeScreenDoze(int which) {
1824         return mDischargeScreenDozeCounter.getCountLocked(which);
1825     }
1826 
1827     @Override
getUahDischargeLightDoze(int which)1828     public long getUahDischargeLightDoze(int which) {
1829         return mDischargeLightDozeCounter.getCountLocked(which);
1830     }
1831 
1832     @Override
getUahDischargeDeepDoze(int which)1833     public long getUahDischargeDeepDoze(int which) {
1834         return mDischargeDeepDozeCounter.getCountLocked(which);
1835     }
1836 
1837     @Override
getEstimatedBatteryCapacity()1838     public int getEstimatedBatteryCapacity() {
1839         return mEstimatedBatteryCapacityMah;
1840     }
1841 
1842     @Override
getLearnedBatteryCapacity()1843     public int getLearnedBatteryCapacity() {
1844         return mLastLearnedBatteryCapacityUah;
1845     }
1846 
1847     @Override
getMinLearnedBatteryCapacity()1848     public int getMinLearnedBatteryCapacity() {
1849         return mMinLearnedBatteryCapacityUah;
1850     }
1851 
1852     @Override
getMaxLearnedBatteryCapacity()1853     public int getMaxLearnedBatteryCapacity() {
1854         return mMaxLearnedBatteryCapacityUah;
1855     }
1856 
1857     public static class FrameworkStatsLogger {
uidProcessStateChanged(int uid, int state)1858         public void uidProcessStateChanged(int uid, int state) {
1859             // TODO(b/155216561): It is possible for isolated uids to be in a higher
1860             // state than its parent uid. We should track the highest state within the union of host
1861             // and isolated uids rather than only the parent uid.
1862             FrameworkStatsLog.write(FrameworkStatsLog.UID_PROCESS_STATE_CHANGED, uid,
1863                     ActivityManager.processStateAmToProto(state));
1864         }
1865 
wakelockStateChanged(int uid, WorkChain wc, String name, int procState, boolean acquired, int powerManagerWakeLockLevel)1866         public void wakelockStateChanged(int uid, WorkChain wc, String name,
1867                 int procState, boolean acquired, int powerManagerWakeLockLevel) {
1868             int event = acquired
1869                     ? FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE
1870                     : FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE;
1871             if (wc != null) {
1872                 FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(),
1873                         wc.getTags(), powerManagerWakeLockLevel, name, event, procState);
1874             } else {
1875                 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, uid,
1876                         null, powerManagerWakeLockLevel, name, event, procState);
1877             }
1878         }
1879 
kernelWakeupReported(long deltaUptimeUs, String lastWakeupReason, long lastWakeupElapsedTimeMs)1880         public void kernelWakeupReported(long deltaUptimeUs, String lastWakeupReason,
1881                 long lastWakeupElapsedTimeMs) {
1882             FrameworkStatsLog.write(FrameworkStatsLog.KERNEL_WAKEUP_REPORTED, lastWakeupReason,
1883                     /* duration_usec */ deltaUptimeUs, lastWakeupElapsedTimeMs);
1884         }
1885 
gpsScanStateChanged(int uid, WorkChain workChain, boolean stateOn)1886         public void gpsScanStateChanged(int uid, WorkChain workChain, boolean stateOn) {
1887             int event = stateOn
1888                     ? FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON
1889                     : FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF;
1890             if (workChain != null) {
1891                 FrameworkStatsLog.write(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
1892                         workChain.getUids(), workChain.getTags(), event);
1893             } else {
1894                 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
1895                         uid, null, event);
1896             }
1897         }
1898 
batterySaverModeChanged(boolean enabled)1899         public void batterySaverModeChanged(boolean enabled) {
1900             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
1901                     enabled
1902                             ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
1903                             : FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
1904         }
1905 
deviceIdlingModeStateChanged(int mode)1906         public void deviceIdlingModeStateChanged(int mode) {
1907             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLING_MODE_STATE_CHANGED, mode);
1908         }
1909 
deviceIdleModeStateChanged(int mode)1910         public void deviceIdleModeStateChanged(int mode) {
1911             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mode);
1912         }
1913 
chargingStateChanged(int status)1914         public void chargingStateChanged(int status) {
1915             FrameworkStatsLog.write(FrameworkStatsLog.CHARGING_STATE_CHANGED, status);
1916         }
1917 
pluggedStateChanged(int plugType)1918         public void pluggedStateChanged(int plugType) {
1919             FrameworkStatsLog.write(FrameworkStatsLog.PLUGGED_STATE_CHANGED, plugType);
1920         }
1921 
batteryLevelChanged(int level)1922         public void batteryLevelChanged(int level) {
1923             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_LEVEL_CHANGED, level);
1924         }
1925 
phoneServiceStateChanged(int state, int simState, int strengthBin)1926         public void phoneServiceStateChanged(int state, int simState, int strengthBin) {
1927             FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
1928                     simState, strengthBin);
1929         }
1930 
phoneSignalStrengthChanged(int strengthBin)1931         public void phoneSignalStrengthChanged(int strengthBin) {
1932             FrameworkStatsLog.write(
1933                     FrameworkStatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
1934         }
1935 
1936         /**
1937          * Records a statsd event when the batterystats config file is written to disk.
1938          */
writeCommitSysConfigFile(String fileName, long durationMs)1939         public void writeCommitSysConfigFile(String fileName, long durationMs) {
1940             com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(fileName,
1941                     durationMs);
1942         }
1943     }
1944 
1945     private final FrameworkStatsLogger mFrameworkStatsLogger;
1946 
initKernelStatsReaders()1947     private void initKernelStatsReaders() {
1948         if (!isKernelStatsAvailable()) {
1949             return;
1950         }
1951 
1952         mCpuUidUserSysTimeReader = new KernelCpuUidUserSysTimeReader(true, mClock);
1953         mCpuUidFreqTimeReader = new KernelCpuUidFreqTimeReader(true, mClock);
1954         mCpuUidActiveTimeReader = new KernelCpuUidActiveTimeReader(true, mClock);
1955         mCpuUidClusterTimeReader = new KernelCpuUidClusterTimeReader(true, mClock);
1956         mKernelWakelockReader = new KernelWakelockReader();
1957         if (!Flags.disableSystemServicePowerAttr()) {
1958             mSystemServerCpuThreadReader = SystemServerCpuThreadReader.create();
1959         }
1960         mKernelMemoryBandwidthStats = new KernelMemoryBandwidthStats();
1961         mTmpRailStats = new RailStats();
1962     }
1963 
1964     private class PowerStatsCollectorInjector implements CpuPowerStatsCollector.Injector,
1965             MobileRadioPowerStatsCollector.Injector, WifiPowerStatsCollector.Injector,
1966             BluetoothPowerStatsCollector.Injector {
1967         private PackageManager mPackageManager;
1968         private PowerStatsCollector.ConsumedEnergyRetriever mConsumedEnergyRetriever;
1969         private NetworkStatsManager mNetworkStatsManager;
1970         private TelephonyManager mTelephonyManager;
1971         private WifiManager mWifiManager;
1972         private BluetoothPowerStatsCollector.BluetoothStatsRetriever mBluetoothStatsRetriever;
1973 
setContext(Context context)1974         void setContext(Context context) {
1975             mPackageManager = context.getPackageManager();
1976             mConsumedEnergyRetriever = new PowerStatsCollector.ConsumedEnergyRetrieverImpl(
1977                     LocalServices.getService(PowerStatsInternal.class));
1978             mNetworkStatsManager = context.getSystemService(NetworkStatsManager.class);
1979             mTelephonyManager = context.getSystemService(TelephonyManager.class);
1980             mWifiManager = context.getSystemService(WifiManager.class);
1981             mBluetoothStatsRetriever = new BluetoothStatsRetrieverImpl(
1982                     context.getSystemService(BluetoothManager.class));
1983         }
1984 
1985         @Override
getHandler()1986         public Handler getHandler() {
1987             return mHandler;
1988         }
1989 
1990         @Override
getClock()1991         public Clock getClock() {
1992             return mClock;
1993         }
1994 
1995         @Override
getPowerStatsCollectionThrottlePeriod(String powerComponentName)1996         public long getPowerStatsCollectionThrottlePeriod(String powerComponentName) {
1997             return mBatteryStatsConfig.getPowerStatsThrottlePeriod(powerComponentName);
1998         }
1999 
2000         @Override
getUidResolver()2001         public PowerStatsUidResolver getUidResolver() {
2002             return mPowerStatsUidResolver;
2003         }
2004 
2005         @Override
getCpuScalingPolicies()2006         public CpuScalingPolicies getCpuScalingPolicies() {
2007             return mCpuScalingPolicies;
2008         }
2009 
2010         @Override
getPowerProfile()2011         public PowerProfile getPowerProfile() {
2012             return mPowerProfile;
2013         }
2014 
2015         @Override
getKernelCpuStatsReader()2016         public CpuPowerStatsCollector.KernelCpuStatsReader getKernelCpuStatsReader() {
2017             return new CpuPowerStatsCollector.KernelCpuStatsReader();
2018         }
2019 
2020         @Override
getPackageManager()2021         public PackageManager getPackageManager() {
2022             return mPackageManager;
2023         }
2024 
2025         @Override
getConsumedEnergyRetriever()2026         public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
2027             return mConsumedEnergyRetriever;
2028         }
2029 
2030         @Override
getVoltageSupplier()2031         public IntSupplier getVoltageSupplier() {
2032             return () -> mBatteryVoltageMv;
2033         }
2034 
2035         @Override
getMobileNetworkStatsSupplier()2036         public Supplier<NetworkStats> getMobileNetworkStatsSupplier() {
2037             return () -> readMobileNetworkStatsLocked(mNetworkStatsManager);
2038         }
2039 
2040         @Override
getWifiNetworkStatsSupplier()2041         public Supplier<NetworkStats> getWifiNetworkStatsSupplier() {
2042             return () -> readWifiNetworkStatsLocked(mNetworkStatsManager);
2043         }
2044 
2045         @Override
getWifiStatsRetriever()2046         public WifiPowerStatsCollector.WifiStatsRetriever getWifiStatsRetriever() {
2047             return mWifiStatsRetriever;
2048         }
2049 
2050         @Override
getTelephonyManager()2051         public TelephonyManager getTelephonyManager() {
2052             return mTelephonyManager;
2053         }
2054 
2055         @Override
getWifiManager()2056         public WifiManager getWifiManager() {
2057             return mWifiManager;
2058         }
2059 
2060         @Override
getBluetoothStatsRetriever()2061         public BluetoothPowerStatsCollector.BluetoothStatsRetriever getBluetoothStatsRetriever() {
2062             return mBluetoothStatsRetriever;
2063         }
2064 
2065         @Override
getCallDurationSupplier()2066         public LongSupplier getCallDurationSupplier() {
2067             return () -> mPhoneOnTimer.getTotalTimeLocked(mClock.elapsedRealtime() * 1000,
2068                     STATS_SINCE_CHARGED);
2069         }
2070 
2071         @Override
getPhoneSignalScanDurationSupplier()2072         public LongSupplier getPhoneSignalScanDurationSupplier() {
2073             return () -> mPhoneSignalScanningTimer.getTotalTimeLocked(
2074                     mClock.elapsedRealtime() * 1000, STATS_SINCE_CHARGED);
2075         }
2076     }
2077 
2078     private final PowerStatsCollectorInjector mPowerStatsCollectorInjector =
2079             new PowerStatsCollectorInjector();
2080 
2081     /**
2082      * TimeBase observer.
2083      */
2084     public interface TimeBaseObs {
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2085         void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs);
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2086         void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs);
2087 
2088         /**
2089          * Reset the observer's state, returns true if the timer/counter is inactive
2090          * so it can be destroyed.
2091          * @param detachIfReset detach if true, no-op if false.
2092          * @return Returns true if the timer/counter is inactive and can be destroyed.
2093          */
reset(boolean detachIfReset)2094         default boolean reset(boolean detachIfReset) {
2095             return reset(detachIfReset, SystemClock.elapsedRealtime() * 1000);
2096         }
2097 
2098         /**
2099          * @see #reset(boolean)
2100          * @param detachIfReset detach if true, no-op if false.
2101          * @param elapsedRealtimeUs the timestamp when this reset is actually reequested
2102          * @return Returns true if the timer/counter is inactive and can be destroyed.
2103          */
reset(boolean detachIfReset, long elapsedRealtimeUs)2104         boolean reset(boolean detachIfReset, long elapsedRealtimeUs);
2105 
2106         /**
2107          * Detach the observer from TimeBase.
2108          */
detach()2109         void detach();
2110     }
2111 
2112     // methods are protected not private to be VisibleForTesting
2113     public static class TimeBase {
2114         protected final Collection<TimeBaseObs> mObservers;
2115 
2116         // All below time metrics are in microseconds.
2117         protected long mUptimeUs;
2118         protected long mRealtimeUs;
2119 
2120         protected boolean mRunning;
2121 
2122         protected long mPastUptimeUs;
2123         protected long mUptimeStartUs;
2124         protected long mPastRealtimeUs;
2125         protected long mRealtimeStartUs;
2126         protected long mUnpluggedUptimeUs;
2127         protected long mUnpluggedRealtimeUs;
2128 
dump(PrintWriter pw, String prefix)2129         public void dump(PrintWriter pw, String prefix) {
2130             StringBuilder sb = new StringBuilder(128);
2131             pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
2132             sb.setLength(0);
2133             sb.append(prefix);
2134                     sb.append("mUptime=");
2135                     formatTimeMs(sb, mUptimeUs / 1000);
2136             pw.println(sb.toString());
2137             sb.setLength(0);
2138             sb.append(prefix);
2139                     sb.append("mRealtime=");
2140                     formatTimeMs(sb, mRealtimeUs / 1000);
2141             pw.println(sb.toString());
2142             sb.setLength(0);
2143             sb.append(prefix);
2144                     sb.append("mPastUptime=");
2145                     formatTimeMs(sb, mPastUptimeUs / 1000); sb.append("mUptimeStart=");
2146                     formatTimeMs(sb, mUptimeStartUs / 1000);
2147                     sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptimeUs / 1000);
2148             pw.println(sb.toString());
2149             sb.setLength(0);
2150             sb.append(prefix);
2151                     sb.append("mPastRealtime=");
2152                     formatTimeMs(sb, mPastRealtimeUs / 1000); sb.append("mRealtimeStart=");
2153                     formatTimeMs(sb, mRealtimeStartUs / 1000);
2154                     sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtimeUs / 1000);
2155             pw.println(sb.toString());
2156         }
2157         /**
2158          * The mObservers of TimeBase in BatteryStatsImpl object can contain up to 20k entries.
2159          * The mObservers of TimeBase in BatteryStatsImpl.Uid object only contains a few or tens of
2160          * entries.
2161          * mObservers must have good performance on add(), remove(), also be memory efficient.
2162          * This is why we provide isLongList parameter for long and short list user cases.
2163          * @param isLongList If true, use HashSet for mObservers list.
2164          *                   If false, use ArrayList for mObservers list.
2165         */
TimeBase(boolean isLongList)2166         public TimeBase(boolean isLongList) {
2167             mObservers = isLongList ? new HashSet<>() : new ArrayList<>();
2168         }
2169 
TimeBase()2170         public TimeBase() {
2171             this(false);
2172         }
2173 
add(TimeBaseObs observer)2174         public void add(TimeBaseObs observer) {
2175             mObservers.add(observer);
2176         }
2177 
remove(TimeBaseObs observer)2178         public void remove(TimeBaseObs observer) {
2179             mObservers.remove(observer);
2180         }
2181 
hasObserver(TimeBaseObs observer)2182         public boolean hasObserver(TimeBaseObs observer) {
2183             return mObservers.contains(observer);
2184         }
2185 
init(long uptimeUs, long elapsedRealtimeUs)2186         public void init(long uptimeUs, long elapsedRealtimeUs) {
2187             mRealtimeUs = 0;
2188             mUptimeUs = 0;
2189             mPastUptimeUs = 0;
2190             mPastRealtimeUs = 0;
2191             mUptimeStartUs = uptimeUs;
2192             mRealtimeStartUs = elapsedRealtimeUs;
2193             mUnpluggedUptimeUs = getUptime(mUptimeStartUs);
2194             mUnpluggedRealtimeUs = getRealtime(mRealtimeStartUs);
2195         }
2196 
reset(long uptimeUs, long elapsedRealtimeUs)2197         public void reset(long uptimeUs, long elapsedRealtimeUs) {
2198             if (!mRunning) {
2199                 mPastUptimeUs = 0;
2200                 mPastRealtimeUs = 0;
2201             } else {
2202                 mUptimeStartUs = uptimeUs;
2203                 mRealtimeStartUs = elapsedRealtimeUs;
2204                 // TODO: Since mUptimeStartUs was just reset and we are running, getUptime will
2205                 // just return mPastUptimeUs. Also, are we sure we don't want to reset that?
2206                 mUnpluggedUptimeUs = getUptime(uptimeUs);
2207                 // TODO: likewise.
2208                 mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs);
2209             }
2210         }
2211 
computeUptime(long curTimeUs, int which)2212         public long computeUptime(long curTimeUs, int which) {
2213             return mUptimeUs + getUptime(curTimeUs);
2214         }
2215 
computeRealtime(long curTimeUs, int which)2216         public long computeRealtime(long curTimeUs, int which) {
2217             return mRealtimeUs + getRealtime(curTimeUs);
2218         }
2219 
getUptime(long curTimeUs)2220         public long getUptime(long curTimeUs) {
2221             long time = mPastUptimeUs;
2222             if (mRunning) {
2223                 time += curTimeUs - mUptimeStartUs;
2224             }
2225             return time;
2226         }
2227 
getRealtime(long curTimeUs)2228         public long getRealtime(long curTimeUs) {
2229             long time = mPastRealtimeUs;
2230             if (mRunning) {
2231                 time += curTimeUs - mRealtimeStartUs;
2232             }
2233             return time;
2234         }
2235 
getUptimeStart()2236         public long getUptimeStart() {
2237             return mUptimeStartUs;
2238         }
2239 
getRealtimeStart()2240         public long getRealtimeStart() {
2241             return mRealtimeStartUs;
2242         }
2243 
isRunning()2244         public boolean isRunning() {
2245             return mRunning;
2246         }
2247 
setRunning(boolean running, long uptimeUs, long elapsedRealtimeUs)2248         public boolean setRunning(boolean running, long uptimeUs, long elapsedRealtimeUs) {
2249             if (mRunning != running) {
2250                 mRunning = running;
2251                 if (running) {
2252                     mUptimeStartUs = uptimeUs;
2253                     mRealtimeStartUs = elapsedRealtimeUs;
2254                     long batteryUptimeUs = mUnpluggedUptimeUs = getUptime(uptimeUs);
2255                     long batteryRealtimeUs = mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs);
2256                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
2257                     // Iterator object, here is an exception because mObservers' type is Collection
2258                     // instead of list.
2259                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
2260                     while (iter.hasNext()) {
2261                         iter.next().onTimeStarted(
2262                                 elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs);
2263                     }
2264                 } else {
2265                     mPastUptimeUs += uptimeUs - mUptimeStartUs;
2266                     mPastRealtimeUs += elapsedRealtimeUs - mRealtimeStartUs;
2267                     long batteryUptimeUs = getUptime(uptimeUs);
2268                     long batteryRealtimeUs = getRealtime(elapsedRealtimeUs);
2269                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
2270                     // Iterator object, here is an exception because mObservers' type is Collection
2271                     // instead of list.
2272                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
2273                     while (iter.hasNext()) {
2274                         iter.next().onTimeStopped(
2275                                 elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs);
2276                     }
2277                 }
2278                 return true;
2279             }
2280             return false;
2281         }
2282 
readSummaryFromParcel(Parcel in)2283         public void readSummaryFromParcel(Parcel in) {
2284             mUptimeUs = in.readLong();
2285             mRealtimeUs = in.readLong();
2286         }
2287 
writeSummaryToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs)2288         public void writeSummaryToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
2289             out.writeLong(computeUptime(uptimeUs, STATS_SINCE_CHARGED));
2290             out.writeLong(computeRealtime(elapsedRealtimeUs, STATS_SINCE_CHARGED));
2291         }
2292 
readFromParcel(Parcel in)2293         public void readFromParcel(Parcel in) {
2294             mRunning = false;
2295             mUptimeUs = in.readLong();
2296             mPastUptimeUs = in.readLong();
2297             mUptimeStartUs = in.readLong();
2298             mRealtimeUs = in.readLong();
2299             mPastRealtimeUs = in.readLong();
2300             mRealtimeStartUs = in.readLong();
2301             mUnpluggedUptimeUs = in.readLong();
2302             mUnpluggedRealtimeUs = in.readLong();
2303         }
2304 
writeToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs)2305         public void writeToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
2306             final long runningUptime = getUptime(uptimeUs);
2307             final long runningRealtime = getRealtime(elapsedRealtimeUs);
2308             out.writeLong(mUptimeUs);
2309             out.writeLong(runningUptime);
2310             out.writeLong(mUptimeStartUs);
2311             out.writeLong(mRealtimeUs);
2312             out.writeLong(runningRealtime);
2313             out.writeLong(mRealtimeStartUs);
2314             out.writeLong(mUnpluggedUptimeUs);
2315             out.writeLong(mUnpluggedRealtimeUs);
2316         }
2317     }
2318 
2319     /**
2320      * State for keeping track of counting information.
2321      */
2322     public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
2323         final AtomicInteger mCount = new AtomicInteger();
2324         final TimeBase mTimeBase;
2325 
Counter(TimeBase timeBase, Parcel in)2326         public Counter(TimeBase timeBase, Parcel in) {
2327             mTimeBase = timeBase;
2328             mCount.set(in.readInt());
2329             timeBase.add(this);
2330         }
2331 
Counter(TimeBase timeBase)2332         public Counter(TimeBase timeBase) {
2333             mTimeBase = timeBase;
2334             timeBase.add(this);
2335         }
2336 
writeToParcel(Parcel out)2337         public void writeToParcel(Parcel out) {
2338             out.writeInt(mCount.get());
2339         }
2340 
2341         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2342         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2343         }
2344 
2345         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2346         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2347         }
2348 
2349         @Override
getCountLocked(int which)2350         public int getCountLocked(int which) {
2351             return mCount.get();
2352         }
2353 
logState(Printer pw, String prefix)2354         public void logState(Printer pw, String prefix) {
2355             pw.println(prefix + "mCount=" + mCount.get());
2356         }
2357 
2358         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
stepAtomic()2359         public void stepAtomic() {
2360             if (mTimeBase.isRunning()) {
2361                 mCount.incrementAndGet();
2362             }
2363         }
2364 
addAtomic(int delta)2365         void addAtomic(int delta) {
2366             if (mTimeBase.isRunning()) {
2367                 mCount.addAndGet(delta);
2368             }
2369         }
2370 
2371         /**
2372          * Clear state of this counter.
2373          */
2374         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2375         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2376             mCount.set(0);
2377             if (detachIfReset) {
2378                 detach();
2379             }
2380             return true;
2381         }
2382 
2383         @Override
detach()2384         public void detach() {
2385             mTimeBase.remove(this);
2386         }
2387 
2388         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
writeSummaryFromParcelLocked(Parcel out)2389         public void writeSummaryFromParcelLocked(Parcel out) {
2390             out.writeInt(mCount.get());
2391         }
2392 
2393         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
readSummaryFromParcelLocked(Parcel in)2394         public void readSummaryFromParcelLocked(Parcel in) {
2395             mCount.set(in.readInt());
2396         }
2397     }
2398 
2399     @VisibleForTesting
2400     public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
2401         final TimeBase mTimeBase;
2402         public long[] mCounts;
2403 
LongSamplingCounterArray(TimeBase timeBase, Parcel in)2404         private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
2405             mTimeBase = timeBase;
2406             mCounts = in.createLongArray();
2407             timeBase.add(this);
2408         }
2409 
LongSamplingCounterArray(TimeBase timeBase)2410         public LongSamplingCounterArray(TimeBase timeBase) {
2411             mTimeBase = timeBase;
2412             timeBase.add(this);
2413         }
2414 
writeToParcel(Parcel out)2415         private void writeToParcel(Parcel out) {
2416             out.writeLongArray(mCounts);
2417         }
2418 
2419         @Override
onTimeStarted(long elapsedRealTimeUs, long baseUptimeUs, long baseRealtimeUs)2420         public void onTimeStarted(long elapsedRealTimeUs, long baseUptimeUs, long baseRealtimeUs) {
2421         }
2422 
2423         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2424         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2425         }
2426 
2427         @Override
getCountsLocked(int which)2428         public long[] getCountsLocked(int which) {
2429             return mCounts == null ? null : Arrays.copyOf(mCounts, mCounts.length);
2430         }
2431 
2432         @Override
logState(Printer pw, String prefix)2433         public void logState(Printer pw, String prefix) {
2434             pw.println(prefix + "mCounts=" + Arrays.toString(mCounts));
2435         }
2436 
addCountLocked(long[] counts)2437         public void addCountLocked(long[] counts) {
2438             addCountLocked(counts, mTimeBase.isRunning());
2439         }
2440 
addCountLocked(long[] counts, boolean isRunning)2441         public void addCountLocked(long[] counts, boolean isRunning) {
2442             if (counts == null) {
2443                 return;
2444             }
2445             if (isRunning) {
2446                 if (mCounts == null) {
2447                     mCounts = new long[counts.length];
2448                 }
2449                 for (int i = 0; i < counts.length; ++i) {
2450                     mCounts[i] += counts[i];
2451                 }
2452             }
2453         }
2454 
getSize()2455         public int getSize() {
2456             return mCounts == null ? 0 : mCounts.length;
2457         }
2458 
2459         /**
2460          * Clear state of this counter.
2461          */
2462         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2463         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2464             if (mCounts != null) {
2465                 Arrays.fill(mCounts, 0);
2466             }
2467             if (detachIfReset) {
2468                 detach();
2469             }
2470             return true;
2471         }
2472 
2473         @Override
detach()2474         public void detach() {
2475             mTimeBase.remove(this);
2476         }
2477 
writeSummaryToParcelLocked(Parcel out)2478         private void writeSummaryToParcelLocked(Parcel out) {
2479             out.writeLongArray(mCounts);
2480         }
2481 
readSummaryFromParcelLocked(Parcel in)2482         private void readSummaryFromParcelLocked(Parcel in) {
2483             mCounts = in.createLongArray();
2484         }
2485 
writeToParcel(Parcel out, LongSamplingCounterArray counterArray)2486         public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
2487             if (counterArray != null) {
2488                 out.writeInt(1);
2489                 counterArray.writeToParcel(out);
2490             } else {
2491                 out.writeInt(0);
2492             }
2493         }
2494 
readFromParcel(Parcel in, TimeBase timeBase)2495         public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
2496             if (in.readInt() != 0) {
2497                 return new LongSamplingCounterArray(timeBase, in);
2498             } else {
2499                 return null;
2500             }
2501         }
2502 
writeSummaryToParcelLocked(Parcel out, LongSamplingCounterArray counterArray)2503         public static void writeSummaryToParcelLocked(Parcel out,
2504                 LongSamplingCounterArray counterArray) {
2505             if (counterArray != null) {
2506                 out.writeInt(1);
2507                 counterArray.writeSummaryToParcelLocked(out);
2508             } else {
2509                 out.writeInt(0);
2510             }
2511         }
2512 
readSummaryFromParcelLocked(Parcel in, TimeBase timeBase)2513         public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
2514                 TimeBase timeBase) {
2515             if (in.readInt() != 0) {
2516                 final LongSamplingCounterArray counterArray
2517                         = new LongSamplingCounterArray(timeBase);
2518                 counterArray.readSummaryFromParcelLocked(in);
2519                 return counterArray;
2520             } else {
2521                 return null;
2522             }
2523         }
2524     }
2525 
2526     private static class TimeMultiStateCounter extends LongCounter implements TimeBaseObs {
2527         private final TimeBase mTimeBase;
2528         private final LongMultiStateCounter mCounter;
2529 
TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs)2530         private TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs) {
2531             this(timeBase, new LongMultiStateCounter(stateCount), timestampMs);
2532         }
2533 
TimeMultiStateCounter(TimeBase timeBase, LongMultiStateCounter counter, long timestampMs)2534         private TimeMultiStateCounter(TimeBase timeBase, LongMultiStateCounter counter,
2535                 long timestampMs) {
2536             mTimeBase = timeBase;
2537             mCounter = counter;
2538             mCounter.setEnabled(mTimeBase.isRunning(), timestampMs);
2539             timeBase.add(this);
2540         }
2541 
2542         @Nullable
readFromParcel(Parcel in, TimeBase timeBase, int stateCount, long timestampMs)2543         private static TimeMultiStateCounter readFromParcel(Parcel in, TimeBase timeBase,
2544                 int stateCount, long timestampMs) {
2545             LongMultiStateCounter counter = LongMultiStateCounter.CREATOR.createFromParcel(in);
2546             if (counter.getStateCount() != stateCount) {
2547                 return null;
2548             }
2549             return new TimeMultiStateCounter(timeBase, counter, timestampMs);
2550         }
2551 
writeToParcel(Parcel out)2552         private void writeToParcel(Parcel out) {
2553             mCounter.writeToParcel(out, 0);
2554         }
2555 
2556         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2557         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2558             mCounter.setEnabled(true, elapsedRealtimeUs / 1000);
2559         }
2560 
2561         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2562         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2563             mCounter.setEnabled(false, elapsedRealtimeUs / 1000);
2564         }
2565 
getStateCount()2566         public int getStateCount() {
2567             return mCounter.getStateCount();
2568         }
2569 
setState(@atteryConsumer.ProcessState int processState, long elapsedRealtimeMs)2570         private void setState(@BatteryConsumer.ProcessState int processState,
2571                 long elapsedRealtimeMs) {
2572             mCounter.setState(processState, elapsedRealtimeMs);
2573         }
2574 
update(long value, long timestampMs)2575         private long update(long value, long timestampMs) {
2576             return mCounter.updateValue(value, timestampMs);
2577         }
2578 
increment(long increment, long timestampMs)2579         private void increment(long increment, long timestampMs) {
2580             mCounter.incrementValue(increment, timestampMs);
2581         }
2582 
2583         /**
2584          * Returns accumulated count for the specified state.
2585          */
getCountForProcessState(@atteryConsumer.ProcessState int procState)2586         public long getCountForProcessState(@BatteryConsumer.ProcessState int procState) {
2587             return mCounter.getCount(procState);
2588         }
2589 
getTotalCountLocked()2590         public long getTotalCountLocked() {
2591             return mCounter.getTotalCount();
2592         }
2593 
2594         @Override
getCountLocked(int statsType)2595         public long getCountLocked(int statsType) {
2596             return getTotalCountLocked();
2597         }
2598 
2599         @Override
logState(Printer pw, String prefix)2600         public void logState(Printer pw, String prefix) {
2601             pw.println(prefix + "mCounter=" + mCounter);
2602         }
2603 
2604         /**
2605          * Clears state of this counter.
2606          */
2607         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2608         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2609             mCounter.reset();
2610             if (detachIfReset) {
2611                 detach();
2612             }
2613             return true;
2614         }
2615 
2616         @Override
detach()2617         public void detach() {
2618             mTimeBase.remove(this);
2619         }
2620     }
2621 
2622     private static class TimeInFreqMultiStateCounter implements TimeBaseObs {
2623         private final TimeBase mTimeBase;
2624         private final LongArrayMultiStateCounter mCounter;
2625 
TimeInFreqMultiStateCounter(TimeBase timeBase, int stateCount, int cpuFreqCount, long timestampMs)2626         private TimeInFreqMultiStateCounter(TimeBase timeBase, int stateCount, int cpuFreqCount,
2627                 long timestampMs) {
2628             this(timeBase, new LongArrayMultiStateCounter(stateCount, cpuFreqCount), timestampMs);
2629         }
2630 
TimeInFreqMultiStateCounter(TimeBase timeBase, LongArrayMultiStateCounter counter, long timestampMs)2631         private TimeInFreqMultiStateCounter(TimeBase timeBase, LongArrayMultiStateCounter counter,
2632                 long timestampMs) {
2633             mTimeBase = timeBase;
2634             mCounter = counter;
2635             mCounter.setEnabled(mTimeBase.isRunning(), timestampMs);
2636             timeBase.add(this);
2637         }
2638 
writeToParcel(Parcel out)2639         private void writeToParcel(Parcel out) {
2640             mCounter.writeToParcel(out, 0);
2641         }
2642 
2643         @Nullable
readFromParcel(Parcel in, TimeBase timeBase, int stateCount, int cpuFreqCount, long timestampMs)2644         private static TimeInFreqMultiStateCounter readFromParcel(Parcel in, TimeBase timeBase,
2645                 int stateCount, int cpuFreqCount, long timestampMs) {
2646             // Read the object from the Parcel, whether it's usable or not
2647             LongArrayMultiStateCounter counter =
2648                     LongArrayMultiStateCounter.CREATOR.createFromParcel(in);
2649             if (counter.getStateCount() != stateCount
2650                     || counter.getArrayLength() != cpuFreqCount) {
2651                 return null;
2652             }
2653             return new TimeInFreqMultiStateCounter(timeBase, counter, timestampMs);
2654         }
2655 
2656         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2657         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2658             mCounter.setEnabled(true, elapsedRealtimeUs / 1000);
2659         }
2660 
2661         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2662         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2663             mCounter.setEnabled(false, elapsedRealtimeUs / 1000);
2664         }
2665 
getCounter()2666         public LongArrayMultiStateCounter getCounter() {
2667             return mCounter;
2668         }
2669 
getStateCount()2670         public int getStateCount() {
2671             return mCounter.getStateCount();
2672         }
2673 
setTrackingEnabled(boolean enabled, long timestampMs)2674         public void setTrackingEnabled(boolean enabled, long timestampMs) {
2675             mCounter.setEnabled(enabled && mTimeBase.isRunning(), timestampMs);
2676         }
2677 
setState(int uidRunningState, long elapsedRealtimeMs)2678         private void setState(int uidRunningState, long elapsedRealtimeMs) {
2679             mCounter.setState(uidRunningState, elapsedRealtimeMs);
2680         }
2681 
2682         /**
2683          * Returns accumulated counts for the specified state, or false if all counts are zero.
2684          */
getCountsLocked(long[] counts, int procState)2685         public boolean getCountsLocked(long[] counts, int procState) {
2686             if (counts.length != mCounter.getArrayLength()) {
2687                 return false;
2688             }
2689 
2690             mCounter.getCounts(counts, procState);
2691 
2692             // Return counts only if at least one of the elements is non-zero.
2693             for (int i = counts.length - 1; i >= 0; --i) {
2694                 if (counts[i] != 0) {
2695                     return true;
2696                 }
2697             }
2698             return false;
2699         }
2700 
logState(Printer pw, String prefix)2701         public void logState(Printer pw, String prefix) {
2702             pw.println(prefix + "mCounter=" + mCounter);
2703         }
2704 
2705         /**
2706          * Clears state of this counter.
2707          */
2708         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2709         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2710             mCounter.reset();
2711             if (detachIfReset) {
2712                 detach();
2713             }
2714             return true;
2715         }
2716 
2717         @Override
detach()2718         public void detach() {
2719             mTimeBase.remove(this);
2720         }
2721     }
2722 
2723     @VisibleForTesting
2724     public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
2725         final TimeBase mTimeBase;
2726         private long mCount;
2727 
LongSamplingCounter(TimeBase timeBase, Parcel in)2728         public LongSamplingCounter(TimeBase timeBase, Parcel in) {
2729             mTimeBase = timeBase;
2730             mCount = in.readLong();
2731             timeBase.add(this);
2732         }
2733 
LongSamplingCounter(TimeBase timeBase)2734         public LongSamplingCounter(TimeBase timeBase) {
2735             mTimeBase = timeBase;
2736             timeBase.add(this);
2737         }
2738 
writeToParcel(Parcel out)2739         public void writeToParcel(Parcel out) {
2740             out.writeLong(mCount);
2741         }
2742 
2743         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2744         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2745         }
2746 
2747         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2748         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2749         }
2750 
getCountLocked(int which)2751         public long getCountLocked(int which) {
2752             return mCount;
2753         }
2754 
2755         @Override
getCountForProcessState(int procState)2756         public long getCountForProcessState(int procState) {
2757             if (procState == BatteryConsumer.PROCESS_STATE_ANY) {
2758                 return getCountLocked(STATS_SINCE_CHARGED);
2759             }
2760             return 0;
2761         }
2762 
2763         @Override
logState(Printer pw, String prefix)2764         public void logState(Printer pw, String prefix) {
2765             pw.println(prefix + "mCount=" + mCount);
2766         }
2767 
addCountLocked(long count)2768         public void addCountLocked(long count) {
2769             addCountLocked(count, mTimeBase.isRunning());
2770         }
2771 
addCountLocked(long count, boolean isRunning)2772         public void addCountLocked(long count, boolean isRunning) {
2773             if (isRunning) {
2774                 mCount += count;
2775             }
2776         }
2777 
2778         /**
2779          * Clear state of this counter.
2780          */
2781         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2782         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2783             mCount = 0;
2784             if (detachIfReset) {
2785                 detach();
2786             }
2787             return true;
2788         }
2789 
2790         @Override
detach()2791         public void detach() {
2792             mTimeBase.remove(this);
2793         }
2794 
writeSummaryFromParcelLocked(Parcel out)2795         public void writeSummaryFromParcelLocked(Parcel out) {
2796             out.writeLong(mCount);
2797         }
2798 
readSummaryFromParcelLocked(Parcel in)2799         public void readSummaryFromParcelLocked(Parcel in) {
2800             mCount = in.readLong();
2801         }
2802     }
2803 
2804     /**
2805      * State for keeping track of timing information.
2806      */
2807     public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
2808         protected final Clock mClock;
2809         protected final int mType;
2810         protected final TimeBase mTimeBase;
2811 
2812         protected int mCount;
2813 
2814         // Times are in microseconds for better accuracy when dividing by the
2815         // lock count, and are in "battery realtime" units.
2816 
2817         /**
2818          * The total time we have accumulated since the start of the original
2819          * boot, to the last time something interesting happened in the
2820          * current run.
2821          */
2822         protected long mTotalTimeUs;
2823 
2824         /**
2825          * The total time this timer has been running until the latest mark has been set.
2826          * Subtract this from mTotalTimeUs to get the time spent running since the mark was set.
2827          */
2828         protected long mTimeBeforeMarkUs;
2829 
2830         /**
2831          * Constructs from a parcel.
2832          * @param type
2833          * @param timeBase
2834          * @param in
2835          */
Timer(Clock clock, int type, TimeBase timeBase, Parcel in)2836         public Timer(Clock clock, int type, TimeBase timeBase, Parcel in) {
2837             mClock = clock;
2838             mType = type;
2839             mTimeBase = timeBase;
2840 
2841             mCount = in.readInt();
2842             mTotalTimeUs = in.readLong();
2843             mTimeBeforeMarkUs = in.readLong();
2844             timeBase.add(this);
2845             if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTimeUs);
2846         }
2847 
Timer(Clock clock, int type, TimeBase timeBase)2848         public Timer(Clock clock, int type, TimeBase timeBase) {
2849             mClock = clock;
2850             mType = type;
2851             mTimeBase = timeBase;
2852             timeBase.add(this);
2853         }
2854 
writeToParcel(Parcel out, long elapsedRealtimeUs)2855         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2856             if (DEBUG) {
2857                 Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
2858                         + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2859                                 elapsedRealtimeUs));
2860             }
2861             out.writeInt(computeCurrentCountLocked());
2862             out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2863                         elapsedRealtimeUs));
2864             out.writeLong(mTimeBeforeMarkUs);
2865         }
2866 
computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs)2867         protected abstract long computeRunTimeLocked(long curBatteryRealtime,
2868                 long elapsedRealtimeUs);
2869 
computeCurrentCountLocked()2870         protected abstract int computeCurrentCountLocked();
2871 
2872         /**
2873          * Clear state of this timer.  Returns true if the timer is inactive
2874          * so can be completely dropped.
2875          */
2876         @Override
reset(boolean detachIfReset)2877         public boolean reset(boolean detachIfReset) {
2878             return reset(detachIfReset, mClock.elapsedRealtime() * 1000);
2879         }
2880 
2881         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2882         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2883             mTotalTimeUs = mTimeBeforeMarkUs = 0;
2884             mCount = 0;
2885             if (detachIfReset) {
2886                 detach();
2887             }
2888             return true;
2889         }
2890 
2891         @Override
detach()2892         public void detach() {
2893             mTimeBase.remove(this);
2894         }
2895 
2896         @Override
onTimeStarted(long elapsedRealtimeUs, long timeBaseUptimeUs, long baseRealtimeUs)2897         public void onTimeStarted(long elapsedRealtimeUs, long timeBaseUptimeUs,
2898                 long baseRealtimeUs) {
2899         }
2900 
2901         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2902         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2903             if (DEBUG && mType < 0) {
2904                 Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtimeUs
2905                         + " old mTotalTime=" + mTotalTimeUs);
2906             }
2907             mTotalTimeUs = computeRunTimeLocked(baseRealtimeUs, elapsedRealtimeUs);
2908             mCount = computeCurrentCountLocked();
2909             if (DEBUG && mType < 0) {
2910                 Log.v(TAG, "plug #" + mType + ": new mTotalTime=" + mTotalTimeUs);
2911             }
2912         }
2913 
2914         /**
2915          * Writes a possibly null Timer to a Parcel.
2916          *
2917          * @param out the Parcel to be written to.
2918          * @param timer a Timer, or null.
2919          */
writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs)2920         public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
2921             if (timer == null) {
2922                 out.writeInt(0); // indicates null
2923                 return;
2924             }
2925             out.writeInt(1); // indicates non-null
2926             timer.writeToParcel(out, elapsedRealtimeUs);
2927         }
2928 
2929         @Override
getTotalTimeLocked(long elapsedRealtimeUs, int which)2930         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
2931             return computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2932                     elapsedRealtimeUs);
2933         }
2934 
2935         @Override
getCountLocked(int which)2936         public int getCountLocked(int which) {
2937             return computeCurrentCountLocked();
2938         }
2939 
2940         @Override
getTimeSinceMarkLocked(long elapsedRealtimeUs)2941         public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
2942             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2943                     elapsedRealtimeUs);
2944             return val - mTimeBeforeMarkUs;
2945         }
2946 
2947         @Override
logState(Printer pw, String prefix)2948         public void logState(Printer pw, String prefix) {
2949             pw.println(prefix + "mCount=" + mCount);
2950             pw.println(prefix + "mTotalTime=" + mTotalTimeUs);
2951         }
2952 
2953 
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2954         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2955             long runTimeUs = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2956                     elapsedRealtimeUs);
2957             out.writeLong(runTimeUs);
2958             out.writeInt(computeCurrentCountLocked());
2959         }
2960 
readSummaryFromParcelLocked(Parcel in)2961         public void readSummaryFromParcelLocked(Parcel in) {
2962             // Multiply by 1000 for backwards compatibility
2963             mTotalTimeUs = in.readLong();
2964             mCount = in.readInt();
2965             // When reading the summary, we set the mark to be the latest information.
2966             mTimeBeforeMarkUs = mTotalTimeUs;
2967         }
2968     }
2969 
2970     /**
2971      * A counter meant to accept monotonically increasing values to its {@link #update(long, int)}
2972      * method. The state of the timer according to its {@link TimeBase} will determine how much
2973      * of the value is recorded.
2974      *
2975      * If the value being recorded resets, {@link #endSample()} can be called in order to
2976      * account for the change. If the value passed in to {@link #update(long, int)} decreased
2977      * between calls, the {@link #endSample()} is automatically called and the new value is
2978      * expected to increase monotonically from that point on.
2979      */
2980     public static class SamplingTimer extends Timer {
2981 
2982         /**
2983          * The most recent reported count from /proc/wakelocks.
2984          */
2985         int mCurrentReportedCount;
2986 
2987         /**
2988          * The reported count from /proc/wakelocks when unplug() was last
2989          * called.
2990          */
2991         int mBaseReportedCount;
2992 
2993         /**
2994          * The most recent reported total_time from /proc/wakelocks.
2995          */
2996         long mCurrentReportedTotalTimeUs;
2997 
2998         /**
2999          * The reported total_time from /proc/wakelocks when unplug() was last
3000          * called.
3001          */
3002         long mBaseReportedTotalTimeUs;
3003 
3004         /**
3005          * Whether we are currently in a discharge cycle.
3006          */
3007         boolean mTimeBaseRunning;
3008 
3009         /**
3010          * Whether we are currently recording reported values.
3011          */
3012         boolean mTrackingReportedValues;
3013 
3014         /*
3015          * A sequence counter, incremented once for each update of the stats.
3016          */
3017         int mUpdateVersion;
3018 
3019         @VisibleForTesting
SamplingTimer(Clock clock, TimeBase timeBase, Parcel in)3020         public SamplingTimer(Clock clock, TimeBase timeBase, Parcel in) {
3021             super(clock, 0, timeBase, in);
3022             mCurrentReportedCount = in.readInt();
3023             mBaseReportedCount = in.readInt();
3024             mCurrentReportedTotalTimeUs = in.readLong();
3025             mBaseReportedTotalTimeUs = in.readLong();
3026             mTrackingReportedValues = in.readInt() == 1;
3027             mTimeBaseRunning = timeBase.isRunning();
3028         }
3029 
3030         @VisibleForTesting
SamplingTimer(Clock clock, TimeBase timeBase)3031         public SamplingTimer(Clock clock, TimeBase timeBase) {
3032             super(clock, 0, timeBase);
3033             mTrackingReportedValues = false;
3034             mTimeBaseRunning = timeBase.isRunning();
3035         }
3036 
3037         /**
3038          * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to
3039          * be less than the values used for a previous invocation.
3040          */
endSample()3041         public void endSample() {
3042             endSample(mClock.elapsedRealtime() * 1000);
3043         }
3044 
3045         /**
3046          * @see #endSample()
3047          */
endSample(long elapsedRealtimeUs)3048         public void endSample(long elapsedRealtimeUs) {
3049             mTotalTimeUs = computeRunTimeLocked(0 /* unused by us */, elapsedRealtimeUs);
3050             mCount = computeCurrentCountLocked();
3051             mBaseReportedTotalTimeUs = mCurrentReportedTotalTimeUs = 0;
3052             mBaseReportedCount = mCurrentReportedCount = 0;
3053             mTrackingReportedValues = false;
3054         }
3055 
setUpdateVersion(int version)3056         public void setUpdateVersion(int version) {
3057             mUpdateVersion = version;
3058         }
3059 
getUpdateVersion()3060         public int getUpdateVersion() {
3061             return mUpdateVersion;
3062         }
3063 
3064         /**
3065          * Updates the current recorded values. These are meant to be monotonically increasing
3066          * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}.
3067          *
3068          * If the values being recorded have been reset, the monotonically increasing requirement
3069          * will be broken. In this case, {@link #endSample()} is automatically called and
3070          * the total value of totalTimeUs and count are recorded, starting a new monotonically
3071          * increasing sample.
3072          *
3073          * @param totalTimeUs total time of sample in microseconds.
3074          * @param count total number of times the event being sampled occurred.
3075          */
update(long totalTimeUs, int count, long elapsedRealtimeUs)3076         public void update(long totalTimeUs, int count, long elapsedRealtimeUs) {
3077             update(totalTimeUs, 0, count, elapsedRealtimeUs);
3078         }
3079 
3080         /**
3081          * Updates the current recorded values. See {@link #update(long, int, long)}
3082          *
3083          * @param activeTimeUs Time that the currently active wake lock has been held.
3084          */
update(long totalTimeUs, long activeTimeUs, int count, long elapsedRealtimeUs)3085         public void update(long totalTimeUs, long activeTimeUs, int count,
3086                 long elapsedRealtimeUs) {
3087             if (mTimeBaseRunning && !mTrackingReportedValues) {
3088                 // Updating the reported value for the first time. If the wake lock is currently
3089                 // active, mark the time it was acquired as the base timestamp.
3090                 mBaseReportedTotalTimeUs = totalTimeUs - activeTimeUs;
3091                 mBaseReportedCount = activeTimeUs == 0 ? count : count - 1;
3092             }
3093 
3094             mTrackingReportedValues = true;
3095 
3096             if (totalTimeUs < mCurrentReportedTotalTimeUs || count < mCurrentReportedCount) {
3097                 endSample(elapsedRealtimeUs);
3098             }
3099 
3100             mCurrentReportedTotalTimeUs = totalTimeUs;
3101             mCurrentReportedCount = count;
3102         }
3103 
3104         /**
3105          * Adds deltaTime and deltaCount to the current sample.
3106          *
3107          * @param deltaTime additional time recorded since the last sampled event, in microseconds.
3108          * @param deltaCount additional number of times the event being sampled occurred.
3109          */
add(long deltaTimeUs, int deltaCount)3110         public void add(long deltaTimeUs, int deltaCount) {
3111             add(deltaTimeUs, deltaCount, mClock.elapsedRealtime() * 1000);
3112         }
3113 
3114         /**
3115          * @see #add(long, int)
3116          */
add(long deltaTimeUs, int deltaCount, long elapsedRealtimeUs)3117         public void add(long deltaTimeUs, int deltaCount, long elapsedRealtimeUs) {
3118             update(mCurrentReportedTotalTimeUs + deltaTimeUs, mCurrentReportedCount + deltaCount,
3119                     elapsedRealtimeUs);
3120         }
3121 
3122         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3123         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3124             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3125             if (mTrackingReportedValues) {
3126                 mBaseReportedTotalTimeUs = mCurrentReportedTotalTimeUs;
3127                 mBaseReportedCount = mCurrentReportedCount;
3128             }
3129             mTimeBaseRunning = true;
3130         }
3131 
3132         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3133         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3134             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3135             mTimeBaseRunning = false;
3136         }
3137 
3138         @Override
logState(Printer pw, String prefix)3139         public void logState(Printer pw, String prefix) {
3140             super.logState(pw, prefix);
3141             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
3142                     + " mBaseReportedCount=" + mBaseReportedCount
3143                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTimeUs
3144                     + " mBaseReportedTotalTimeUs=" + mBaseReportedTotalTimeUs);
3145         }
3146 
3147         @Override
computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs)3148         protected long computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs) {
3149             return mTotalTimeUs + (mTimeBaseRunning && mTrackingReportedValues
3150                     ? mCurrentReportedTotalTimeUs - mBaseReportedTotalTimeUs : 0);
3151         }
3152 
3153         @Override
computeCurrentCountLocked()3154         protected int computeCurrentCountLocked() {
3155             return mCount + (mTimeBaseRunning && mTrackingReportedValues
3156                     ? mCurrentReportedCount - mBaseReportedCount : 0);
3157         }
3158 
3159         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)3160         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3161             super.writeToParcel(out, elapsedRealtimeUs);
3162             out.writeInt(mCurrentReportedCount);
3163             out.writeInt(mBaseReportedCount);
3164             out.writeLong(mCurrentReportedTotalTimeUs);
3165             out.writeLong(mBaseReportedTotalTimeUs);
3166             out.writeInt(mTrackingReportedValues ? 1 : 0);
3167         }
3168 
3169         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3170         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3171             super.reset(detachIfReset, elapsedRealtimeUs);
3172             mTrackingReportedValues = false;
3173             mBaseReportedTotalTimeUs = 0;
3174             mBaseReportedCount = 0;
3175             return true;
3176         }
3177     }
3178 
3179     /**
3180      * A timer that increments in batches.  It does not run for durations, but just jumps
3181      * for a pre-determined amount.
3182      */
3183     public static class BatchTimer extends Timer {
3184         final Uid mUid;
3185 
3186         /**
3187          * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
3188          */
3189         long mLastAddedTimeUs;
3190 
3191         /**
3192          * The last duration that we added to the timer.  This is in microseconds.
3193          */
3194         long mLastAddedDurationUs;
3195 
3196         /**
3197          * Whether we are currently in a discharge cycle.
3198          */
3199         boolean mInDischarge;
3200 
BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase, Parcel in)3201         BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase, Parcel in) {
3202             super(clock, type, timeBase, in);
3203             mUid = uid;
3204             mLastAddedTimeUs = in.readLong();
3205             mLastAddedDurationUs = in.readLong();
3206             mInDischarge = timeBase.isRunning();
3207         }
3208 
BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase)3209         BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase) {
3210             super(clock, type, timeBase);
3211             mUid = uid;
3212             mInDischarge = timeBase.isRunning();
3213         }
3214 
3215         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)3216         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3217             super.writeToParcel(out, elapsedRealtimeUs);
3218             out.writeLong(mLastAddedTimeUs);
3219             out.writeLong(mLastAddedDurationUs);
3220         }
3221 
3222         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3223         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3224             recomputeLastDuration(elapsedRealtimeUs, false);
3225             mInDischarge = false;
3226             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3227         }
3228 
3229         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3230         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3231             recomputeLastDuration(elapsedRealtimeUs, false);
3232             mInDischarge = true;
3233             // If we are still within the last added duration, then re-added whatever remains.
3234             if (mLastAddedTimeUs == elapsedRealtimeUs) {
3235                 mTotalTimeUs += mLastAddedDurationUs;
3236             }
3237             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3238         }
3239 
3240         @Override
logState(Printer pw, String prefix)3241         public void logState(Printer pw, String prefix) {
3242             super.logState(pw, prefix);
3243             pw.println(prefix + "mLastAddedTime=" + mLastAddedTimeUs
3244                     + " mLastAddedDuration=" + mLastAddedDurationUs);
3245         }
3246 
computeOverage(long curTimeUs)3247         private long computeOverage(long curTimeUs) {
3248             if (mLastAddedTimeUs > 0) {
3249                 return mLastAddedDurationUs - curTimeUs;
3250             }
3251             return 0;
3252         }
3253 
recomputeLastDuration(long curTimeUs, boolean abort)3254         private void recomputeLastDuration(long curTimeUs, boolean abort) {
3255             final long overage = computeOverage(curTimeUs);
3256             if (overage > 0) {
3257                 // Aborting before the duration ran out -- roll back the remaining
3258                 // duration.  Only do this if currently discharging; otherwise we didn't
3259                 // actually add the time.
3260                 if (mInDischarge) {
3261                     mTotalTimeUs -= overage;
3262                 }
3263                 if (abort) {
3264                     mLastAddedTimeUs = 0;
3265                 } else {
3266                     mLastAddedTimeUs = curTimeUs;
3267                     mLastAddedDurationUs -= overage;
3268                 }
3269             }
3270         }
3271 
addDuration(long durationMs, long elapsedRealtimeMs)3272         public void addDuration(long durationMs, long elapsedRealtimeMs) {
3273             final long nowUs = elapsedRealtimeMs * 1000;
3274             recomputeLastDuration(nowUs, true);
3275             mLastAddedTimeUs = nowUs;
3276             mLastAddedDurationUs = durationMs * 1000;
3277             if (mInDischarge) {
3278                 mTotalTimeUs += mLastAddedDurationUs;
3279                 mCount++;
3280             }
3281         }
3282 
abortLastDuration(long elapsedRealtimeMs)3283         public void abortLastDuration(long elapsedRealtimeMs) {
3284             final long nowUs = elapsedRealtimeMs * 1000;
3285             recomputeLastDuration(nowUs, true);
3286         }
3287 
3288         @Override
computeCurrentCountLocked()3289         protected int computeCurrentCountLocked() {
3290             return mCount;
3291         }
3292 
3293         @Override
computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs)3294         protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) {
3295             final long overage = computeOverage(elapsedRealtimeUs);
3296             if (overage > 0) {
3297                 return mTotalTimeUs = overage;
3298             }
3299             return mTotalTimeUs;
3300         }
3301 
3302         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3303         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3304             recomputeLastDuration(elapsedRealtimeUs, true);
3305             boolean stillActive = mLastAddedTimeUs == elapsedRealtimeUs;
3306             super.reset(!stillActive && detachIfReset, elapsedRealtimeUs);
3307             return !stillActive;
3308         }
3309     }
3310 
3311 
3312     /**
3313      * A StopwatchTimer that also tracks the total and max individual
3314      * time spent active according to the given timebase.  Whereas
3315      * StopwatchTimer apportions the time amongst all in the pool,
3316      * the total and max durations are not apportioned.
3317      */
3318     public static class DurationTimer extends StopwatchTimer {
3319         /**
3320          * The time (in ms) that the timer was last acquired or the time base
3321          * last (re-)started. Increasing the nesting depth does not reset this time.
3322          *
3323          * -1 if the timer is currently not running or the time base is not running.
3324          *
3325          * If written to a parcel, the start time is reset, as is mNesting in the base class
3326          * StopwatchTimer.
3327          */
3328         long mStartTimeMs = -1;
3329 
3330         /**
3331          * The longest time period (in ms) that the timer has been active. Not pooled.
3332          */
3333         long mMaxDurationMs;
3334 
3335         /**
3336          * The time (in ms) that that the timer has been active since most recent
3337          * stopRunningLocked() or reset(). Not pooled.
3338          */
3339         long mCurrentDurationMs;
3340 
3341         /**
3342          * The total time (in ms) that that the timer has been active since most recent reset()
3343          * prior to the current startRunningLocked. This is the sum of all past currentDurations
3344          * (but not including the present currentDuration) since reset. Not pooled.
3345          */
3346         long mTotalDurationMs;
3347 
DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)3348         public DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3349                 TimeBase timeBase, Parcel in) {
3350             super(clock, uid, type, timerPool, timeBase, in);
3351             mMaxDurationMs = in.readLong();
3352             mTotalDurationMs = in.readLong();
3353             mCurrentDurationMs = in.readLong();
3354         }
3355 
DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)3356         public DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3357                 TimeBase timeBase) {
3358             super(clock, uid, type, timerPool, timeBase);
3359         }
3360 
3361         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)3362         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3363             super.writeToParcel(out, elapsedRealtimeUs);
3364             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
3365             out.writeLong(mTotalDurationMs);
3366             out.writeLong(getCurrentDurationMsLocked(elapsedRealtimeUs / 1000));
3367         }
3368 
3369         /**
3370          * Write the summary to the parcel.
3371          *
3372          * Since the time base is probably meaningless after we come back, reading
3373          * from this will have the effect of stopping the timer. So here all we write
3374          * is the max and total durations.
3375          */
3376         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)3377         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
3378             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
3379             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
3380             out.writeLong(getTotalDurationMsLocked(elapsedRealtimeUs / 1000));
3381         }
3382 
3383         /**
3384          * Read the summary parcel.
3385          *
3386          * Has the side effect of stopping the timer.
3387          */
3388         @Override
readSummaryFromParcelLocked(Parcel in)3389         public void readSummaryFromParcelLocked(Parcel in) {
3390             super.readSummaryFromParcelLocked(in);
3391             mMaxDurationMs = in.readLong();
3392             mTotalDurationMs = in.readLong();
3393             mStartTimeMs = -1;
3394             mCurrentDurationMs = 0;
3395         }
3396 
3397         /**
3398          * The TimeBase time started (again).
3399          *
3400          * If the timer is also running, store the start time.
3401          */
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3402         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3403             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3404             if (mNesting > 0) {
3405                 mStartTimeMs = baseRealtimeUs / 1000;
3406             }
3407         }
3408 
3409         /**
3410          * The TimeBase stopped running.
3411          *
3412          * If the timer is running, add the duration into mCurrentDurationMs.
3413          */
3414         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3415         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3416             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3417             if (mNesting > 0) {
3418                 // baseRealtimeUs has already been converted to the timebase's realtime.
3419                 mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
3420             }
3421             mStartTimeMs = -1;
3422         }
3423 
3424         @Override
logState(Printer pw, String prefix)3425         public void logState(Printer pw, String prefix) {
3426             super.logState(pw, prefix);
3427         }
3428 
3429         @Override
startRunningLocked(long elapsedRealtimeMs)3430         public void startRunningLocked(long elapsedRealtimeMs) {
3431             super.startRunningLocked(elapsedRealtimeMs);
3432             if (mNesting == 1 && mTimeBase.isRunning()) {
3433                 // Just started
3434                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000;
3435             }
3436         }
3437 
3438         /**
3439          * Decrements the mNesting ref-count on this timer.
3440          *
3441          * If it actually stopped (mNesting went to 0), then possibly update
3442          * mMaxDuration if the current duration was the longest ever.
3443          */
3444         @Override
stopRunningLocked(long elapsedRealtimeMs)3445         public void stopRunningLocked(long elapsedRealtimeMs) {
3446             if (mNesting == 1) {
3447                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
3448                 mTotalDurationMs += durationMs;
3449                 if (durationMs > mMaxDurationMs) {
3450                     mMaxDurationMs = durationMs;
3451                 }
3452                 mStartTimeMs = -1;
3453                 mCurrentDurationMs = 0;
3454             }
3455             // super method decrements mNesting, which getCurrentDurationMsLocked relies on,
3456             // so call super.stopRunningLocked after calling getCurrentDurationMsLocked.
3457             super.stopRunningLocked(elapsedRealtimeMs);
3458         }
3459 
3460         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3461         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3462             boolean result = super.reset(detachIfReset, elapsedRealtimeUs);
3463             mMaxDurationMs = 0;
3464             mTotalDurationMs = 0;
3465             mCurrentDurationMs = 0;
3466             if (mNesting > 0) {
3467                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeUs) / 1000;
3468             } else {
3469                 mStartTimeMs = -1;
3470             }
3471             return result;
3472         }
3473 
3474         /**
3475          * Returns the max duration that this timer has ever seen.
3476          *
3477          * Note that this time is NOT split between the timers in the timer group that
3478          * this timer is attached to.  It is the TOTAL time.
3479          */
3480         @Override
getMaxDurationMsLocked(long elapsedRealtimeMs)3481         public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
3482             if (mNesting > 0) {
3483                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
3484                 if (durationMs > mMaxDurationMs) {
3485                     return durationMs;
3486                 }
3487             }
3488             return mMaxDurationMs;
3489         }
3490 
3491         /**
3492          * Returns the time since the timer was started.
3493          * Returns 0 if the timer is not currently running.
3494          *
3495          * Note that this time is NOT split between the timers in the timer group that
3496          * this timer is attached to.  It is the TOTAL time.
3497          *
3498          * Note that if running timer is parceled and unparceled, this method will return
3499          * current duration value at the time of parceling even though timer may not be
3500          * currently running.
3501          */
3502         @Override
getCurrentDurationMsLocked(long elapsedRealtimeMs)3503         public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
3504             long durationMs = mCurrentDurationMs;
3505             if (mNesting > 0 && mTimeBase.isRunning()) {
3506                 durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000)
3507                         - mStartTimeMs;
3508             }
3509             return durationMs;
3510         }
3511 
3512         /**
3513          * Returns the total cumulative duration that this timer has been on since reset().
3514          * If mTimerPool == null, this should be the same
3515          * as getTotalTimeLocked(elapsedRealtimeMs*1000, STATS_SINCE_CHARGED)/1000.
3516          *
3517          * Note that this time is NOT split between the timers in the timer group that
3518          * this timer is attached to.  It is the TOTAL time. For this reason, if mTimerPool != null,
3519          * the result will not be equivalent to getTotalTimeLocked.
3520          */
3521         @Override
getTotalDurationMsLocked(long elapsedRealtimeMs)3522         public long getTotalDurationMsLocked(long elapsedRealtimeMs) {
3523             return mTotalDurationMs + getCurrentDurationMsLocked(elapsedRealtimeMs);
3524         }
3525     }
3526 
3527     /**
3528      * State for keeping track of timing information.
3529      */
3530     public static class StopwatchTimer extends Timer {
3531         final Uid mUid;
3532         final ArrayList<StopwatchTimer> mTimerPool;
3533 
3534         int mNesting;
3535 
3536         /**
3537          * The last time at which we updated the timer.  If mNesting is > 0,
3538          * subtract this from the current battery time to find the amount of
3539          * time we have been running since we last computed an update.
3540          */
3541         long mUpdateTimeUs;
3542 
3543         /**
3544          * The total time at which the timer was acquired, to determine if it
3545          * was actually held for an interesting duration. If time base was not running when timer
3546          * was acquired, will be -1.
3547          */
3548         long mAcquireTimeUs = -1;
3549 
3550         long mTimeoutUs;
3551 
3552         /**
3553          * For partial wake locks, keep track of whether we are in the list
3554          * to consume CPU cycles.
3555          */
3556         @VisibleForTesting
3557         public boolean mInList;
3558 
StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)3559         public StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3560                 TimeBase timeBase, Parcel in) {
3561             super(clock, type, timeBase, in);
3562             mUid = uid;
3563             mTimerPool = timerPool;
3564             mUpdateTimeUs = in.readLong();
3565         }
3566 
StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)3567         public StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3568                 TimeBase timeBase) {
3569             super(clock, type, timeBase);
3570             mUid = uid;
3571             mTimerPool = timerPool;
3572         }
3573 
setTimeout(long timeoutUs)3574         public void setTimeout(long timeoutUs) {
3575             mTimeoutUs = timeoutUs;
3576         }
3577 
writeToParcel(Parcel out, long elapsedRealtimeUs)3578         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3579             super.writeToParcel(out, elapsedRealtimeUs);
3580             out.writeLong(mUpdateTimeUs);
3581         }
3582 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3583         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3584             if (mNesting > 0) {
3585                 if (DEBUG && mType < 0) {
3586                     Log.v(TAG, "old mUpdateTime=" + mUpdateTimeUs);
3587                 }
3588                 super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3589                 mUpdateTimeUs = baseRealtimeUs;
3590                 if (DEBUG && mType < 0) {
3591                     Log.v(TAG, "new mUpdateTime=" + mUpdateTimeUs);
3592                 }
3593             }
3594         }
3595 
logState(Printer pw, String prefix)3596         public void logState(Printer pw, String prefix) {
3597             super.logState(pw, prefix);
3598             pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTimeUs
3599                     + " mAcquireTime=" + mAcquireTimeUs);
3600         }
3601 
startRunningLocked(long elapsedRealtimeMs)3602         public void startRunningLocked(long elapsedRealtimeMs) {
3603             if (mNesting++ == 0) {
3604                 final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
3605                 mUpdateTimeUs = batteryRealtimeUs;
3606                 if (mTimerPool != null) {
3607                     // Accumulate time to all currently active timers before adding
3608                     // this new one to the pool.
3609                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, null);
3610                     // Add this timer to the active pool
3611                     mTimerPool.add(this);
3612                 }
3613                 if (mTimeBase.isRunning()) {
3614                     // Increment the count
3615                     mCount++;
3616                     mAcquireTimeUs = mTotalTimeUs;
3617                 } else {
3618                     mAcquireTimeUs = -1;
3619                 }
3620                 if (DEBUG && mType < 0) {
3621                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTimeUs
3622                             + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount
3623                             + " mAcquireTime=" + mAcquireTimeUs);
3624                 }
3625             }
3626         }
3627 
isRunningLocked()3628         public boolean isRunningLocked() {
3629             return mNesting > 0;
3630         }
3631 
stopRunningLocked(long elapsedRealtimeMs)3632         public void stopRunningLocked(long elapsedRealtimeMs) {
3633             // Ignore attempt to stop a timer that isn't running
3634             if (mNesting == 0) {
3635                 return;
3636             }
3637             if (--mNesting == 0) {
3638                 final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
3639                 if (mTimerPool != null) {
3640                     // Accumulate time to all active counters, scaled by the total
3641                     // active in the pool, before taking this one out of the pool.
3642                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, null);
3643                     // Remove this timer from the active pool
3644                     mTimerPool.remove(this);
3645                 } else {
3646                     mNesting = 1;
3647                     mTotalTimeUs = computeRunTimeLocked(batteryRealtimeUs,
3648                             elapsedRealtimeMs * 1000);
3649                     mNesting = 0;
3650                 }
3651 
3652                 if (DEBUG && mType < 0) {
3653                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTimeUs
3654                             + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount
3655                             + " mAcquireTime=" + mAcquireTimeUs);
3656                 }
3657 
3658                 if (mAcquireTimeUs >= 0 && mTotalTimeUs == mAcquireTimeUs) {
3659                     // If there was no change in the time, then discard this
3660                     // count.  A somewhat cheezy strategy, but hey.
3661                     mCount--;
3662                 }
3663             }
3664         }
3665 
stopAllRunningLocked(long elapsedRealtimeMs)3666         public void stopAllRunningLocked(long elapsedRealtimeMs) {
3667             if (mNesting > 0) {
3668                 mNesting = 1;
3669                 stopRunningLocked(elapsedRealtimeMs);
3670             }
3671         }
3672 
3673         // Update the total time for all other running Timers with the same type as this Timer
3674         // due to a change in timer count
refreshTimersLocked(long batteryRealtimeUs, final ArrayList<StopwatchTimer> pool, StopwatchTimer self)3675         private static long refreshTimersLocked(long batteryRealtimeUs,
3676                 final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
3677             long selfTimeUs = 0;
3678             final int N = pool.size();
3679             for (int i=N-1; i>= 0; i--) {
3680                 final StopwatchTimer t = pool.get(i);
3681                 long heldTimeUs = batteryRealtimeUs - t.mUpdateTimeUs;
3682                 if (heldTimeUs > 0) {
3683                     final long myTimeUs = heldTimeUs / N;
3684                     if (t == self) {
3685                         selfTimeUs = myTimeUs;
3686                     }
3687                     t.mTotalTimeUs += myTimeUs;
3688                 }
3689                 t.mUpdateTimeUs = batteryRealtimeUs;
3690             }
3691             return selfTimeUs;
3692         }
3693 
3694         @Override
computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs)3695         protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) {
3696             if (mTimeoutUs > 0 && curBatteryRealtimeUs > mUpdateTimeUs + mTimeoutUs) {
3697                 curBatteryRealtimeUs = mUpdateTimeUs + mTimeoutUs;
3698             }
3699             return mTotalTimeUs + (mNesting > 0
3700                     ? (curBatteryRealtimeUs - mUpdateTimeUs)
3701                             / (mTimerPool != null && mTimerPool.size() > 0 ? mTimerPool.size() : 1)
3702                     : 0);
3703         }
3704 
3705         @Override
computeCurrentCountLocked()3706         protected int computeCurrentCountLocked() {
3707             return mCount;
3708         }
3709 
3710         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3711         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3712             boolean canDetach = mNesting <= 0;
3713             super.reset(canDetach && detachIfReset, elapsedRealtimeUs);
3714             if (mNesting > 0) {
3715                 mUpdateTimeUs = mTimeBase.getRealtime(elapsedRealtimeUs);
3716             }
3717             // To ensure mCount isn't decreased to -1 if timer is stopped later.
3718             mAcquireTimeUs = -1;
3719             return canDetach;
3720         }
3721 
3722         @Override
detach()3723         public void detach() {
3724             super.detach();
3725             if (mTimerPool != null) {
3726                 mTimerPool.remove(this);
3727             }
3728         }
3729 
3730         @Override
readSummaryFromParcelLocked(Parcel in)3731         public void readSummaryFromParcelLocked(Parcel in) {
3732             super.readSummaryFromParcelLocked(in);
3733             mNesting = 0;
3734         }
3735 
3736         /**
3737          * Set the mark so that we can query later for the total time the timer has
3738          * accumulated since this point. The timer can be running or not.
3739          *
3740          * @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
3741          */
setMark(long elapsedRealtimeMs)3742         public void setMark(long elapsedRealtimeMs) {
3743             final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
3744             if (mNesting > 0) {
3745                 // We are running.
3746                 if (mTimerPool != null) {
3747                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, this);
3748                 } else {
3749                     mTotalTimeUs += batteryRealtimeUs - mUpdateTimeUs;
3750                     mUpdateTimeUs = batteryRealtimeUs;
3751                 }
3752             }
3753             mTimeBeforeMarkUs = mTotalTimeUs;
3754         }
3755     }
3756 
3757     /**
3758      * State for keeping track of two DurationTimers with different TimeBases, presumably where one
3759      * TimeBase is effectively a subset of the other.
3760      */
3761     public static class DualTimer extends DurationTimer {
3762         // This class both is a DurationTimer and also holds a second DurationTimer.
3763         // The main timer (this) typically tracks the total time. It may be pooled (but since it's a
3764         // durationTimer, it also has the unpooled getTotalDurationMsLocked() for
3765         // STATS_SINCE_CHARGED).
3766         // mSubTimer typically tracks only part of the total time, such as background time, as
3767         // determined by a subTimeBase. It is NOT pooled.
3768         private final DurationTimer mSubTimer;
3769 
3770         /**
3771          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
3772          * The main timer (this) is based on the given timeBase and timerPool.
3773          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
3774          * the main timer is.
3775          */
DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase, Parcel in)3776         public DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3777                 TimeBase timeBase, TimeBase subTimeBase, Parcel in) {
3778             super(clock, uid, type, timerPool, timeBase, in);
3779             mSubTimer = new DurationTimer(clock, uid, type, null, subTimeBase, in);
3780         }
3781 
3782         /**
3783          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
3784          * The main timer (this) is based on the given timeBase and timerPool.
3785          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
3786          * the main timer is.
3787          */
DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase)3788         public DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3789                 TimeBase timeBase, TimeBase subTimeBase) {
3790             super(clock, uid, type, timerPool, timeBase);
3791             mSubTimer = new DurationTimer(clock, uid, type, null, subTimeBase);
3792         }
3793 
3794         /** Get the secondary timer. */
3795         @Override
getSubTimer()3796         public DurationTimer getSubTimer() {
3797             return mSubTimer;
3798         }
3799 
3800         @Override
startRunningLocked(long elapsedRealtimeMs)3801         public void startRunningLocked(long elapsedRealtimeMs) {
3802             super.startRunningLocked(elapsedRealtimeMs);
3803             mSubTimer.startRunningLocked(elapsedRealtimeMs);
3804         }
3805 
3806         @Override
stopRunningLocked(long elapsedRealtimeMs)3807         public void stopRunningLocked(long elapsedRealtimeMs) {
3808             super.stopRunningLocked(elapsedRealtimeMs);
3809             mSubTimer.stopRunningLocked(elapsedRealtimeMs);
3810         }
3811 
3812         @Override
stopAllRunningLocked(long elapsedRealtimeMs)3813         public void stopAllRunningLocked(long elapsedRealtimeMs) {
3814             super.stopAllRunningLocked(elapsedRealtimeMs);
3815             mSubTimer.stopAllRunningLocked(elapsedRealtimeMs);
3816         }
3817 
3818         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3819         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3820             boolean active = false;
3821             // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
3822             active |= !mSubTimer.reset(false, elapsedRealtimeUs);
3823             active |= !super.reset(detachIfReset, elapsedRealtimeUs);
3824             return !active;
3825         }
3826 
3827         @Override
detach()3828         public void detach() {
3829             mSubTimer.detach();
3830             super.detach();
3831         }
3832 
3833         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)3834         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3835             super.writeToParcel(out, elapsedRealtimeUs);
3836             mSubTimer.writeToParcel(out, elapsedRealtimeUs);
3837         }
3838 
3839         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)3840         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
3841             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
3842             mSubTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
3843         }
3844 
3845         @Override
readSummaryFromParcelLocked(Parcel in)3846         public void readSummaryFromParcelLocked(Parcel in) {
3847             super.readSummaryFromParcelLocked(in);
3848             mSubTimer.readSummaryFromParcelLocked(in);
3849         }
3850     }
3851 
3852 
3853     public abstract class OverflowArrayMap<T> {
3854         private static final String OVERFLOW_NAME = "*overflow*";
3855 
3856         final int mUid;
3857         final ArrayMap<String, T> mMap = new ArrayMap<>();
3858         T mCurOverflow;
3859         ArrayMap<String, MutableInt> mActiveOverflow;
3860         long mLastOverflowTimeMs;
3861         long mLastOverflowFinishTimeMs;
3862         long mLastClearTimeMs;
3863         long mLastCleanupTimeMs;
3864 
OverflowArrayMap(int uid)3865         public OverflowArrayMap(int uid) {
3866             mUid = uid;
3867         }
3868 
getMap()3869         public ArrayMap<String, T> getMap() {
3870             return mMap;
3871         }
3872 
clear()3873         public void clear() {
3874             mLastClearTimeMs = SystemClock.elapsedRealtime();
3875             mMap.clear();
3876             mCurOverflow = null;
3877             mActiveOverflow = null;
3878         }
3879 
add(String name, T obj)3880         public void add(String name, T obj) {
3881             if (name == null) {
3882                 name = "";
3883             }
3884             mMap.put(name, obj);
3885             if (OVERFLOW_NAME.equals(name)) {
3886                 mCurOverflow = obj;
3887             }
3888         }
3889 
cleanup(long elapsedRealtimeMs)3890         public void cleanup(long elapsedRealtimeMs) {
3891             mLastCleanupTimeMs = elapsedRealtimeMs;
3892             if (mActiveOverflow != null) {
3893                 if (mActiveOverflow.size() == 0) {
3894                     mActiveOverflow = null;
3895                 }
3896             }
3897             if (mActiveOverflow == null) {
3898                 // There is no currently active overflow, so we should no longer have
3899                 // an overflow entry.
3900                 if (mMap.containsKey(OVERFLOW_NAME)) {
3901                     Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
3902                             + mMap.get(OVERFLOW_NAME));
3903                     mMap.remove(OVERFLOW_NAME);
3904                 }
3905                 mCurOverflow = null;
3906             } else {
3907                 // There is currently active overflow, so we should still have an overflow entry.
3908                 if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
3909                     Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
3910                             + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
3911                 }
3912             }
3913         }
3914 
startObject(String name, long elapsedRealtimeMs)3915         public T startObject(String name, long elapsedRealtimeMs) {
3916             if (name == null) {
3917                 name = "";
3918             }
3919             T obj = mMap.get(name);
3920             if (obj != null) {
3921                 return obj;
3922             }
3923 
3924             // No object exists for the given name, but do we currently have it
3925             // running as part of the overflow?
3926             if (mActiveOverflow != null) {
3927                 MutableInt over = mActiveOverflow.get(name);
3928                 if (over != null) {
3929                     // We are already actively counting this name in the overflow object.
3930                     obj = mCurOverflow;
3931                     if (obj == null) {
3932                         // Shouldn't be here, but we'll try to recover.
3933                         Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
3934                         obj = mCurOverflow = instantiateObject();
3935                         mMap.put(OVERFLOW_NAME, obj);
3936                     }
3937                     over.value++;
3938                     return obj;
3939                 }
3940             }
3941 
3942             // No object exists for given name nor in the overflow; we need to make
3943             // a new one.
3944             final int N = mMap.size();
3945             if (N >= MAX_WAKELOCKS_PER_UID) {
3946                 // Went over the limit on number of objects to track; this one goes
3947                 // in to the overflow.
3948                 obj = mCurOverflow;
3949                 if (obj == null) {
3950                     // Need to start overflow now...
3951                     obj = mCurOverflow = instantiateObject();
3952                     mMap.put(OVERFLOW_NAME, obj);
3953                 }
3954                 if (mActiveOverflow == null) {
3955                     mActiveOverflow = new ArrayMap<>();
3956                 }
3957                 mActiveOverflow.put(name, new MutableInt(1));
3958                 mLastOverflowTimeMs = elapsedRealtimeMs;
3959                 return obj;
3960             }
3961 
3962             // Normal case where we just need to make a new object.
3963             obj = instantiateObject();
3964             mMap.put(name, obj);
3965             return obj;
3966         }
3967 
stopObject(String name, long elapsedRealtimeMs)3968         public T stopObject(String name, long elapsedRealtimeMs) {
3969             if (name == null) {
3970                 name = "";
3971             }
3972             T obj = mMap.get(name);
3973             if (obj != null) {
3974                 return obj;
3975             }
3976 
3977             // No object exists for the given name, but do we currently have it
3978             // running as part of the overflow?
3979             if (mActiveOverflow != null) {
3980                 MutableInt over = mActiveOverflow.get(name);
3981                 if (over != null) {
3982                     // We are already actively counting this name in the overflow object.
3983                     obj = mCurOverflow;
3984                     if (obj != null) {
3985                         over.value--;
3986                         if (over.value <= 0) {
3987                             mActiveOverflow.remove(name);
3988                             mLastOverflowFinishTimeMs = elapsedRealtimeMs;
3989                         }
3990                         return obj;
3991                     }
3992                 }
3993             }
3994 
3995             // Huh, they are stopping an active operation but we can't find one!
3996             // That's not good.
3997             StringBuilder sb = new StringBuilder();
3998             sb.append("Unable to find object for ");
3999             sb.append(name);
4000             sb.append(" in uid ");
4001             sb.append(mUid);
4002             sb.append(" mapsize=");
4003             sb.append(mMap.size());
4004             sb.append(" activeoverflow=");
4005             sb.append(mActiveOverflow);
4006             sb.append(" curoverflow=");
4007             sb.append(mCurOverflow);
4008             long now = elapsedRealtimeMs;
4009             if (mLastOverflowTimeMs != 0) {
4010                 sb.append(" lastOverflowTime=");
4011                 TimeUtils.formatDuration(mLastOverflowTimeMs - now, sb);
4012             }
4013             if (mLastOverflowFinishTimeMs != 0) {
4014                 sb.append(" lastOverflowFinishTime=");
4015                 TimeUtils.formatDuration(mLastOverflowFinishTimeMs - now, sb);
4016             }
4017             if (mLastClearTimeMs != 0) {
4018                 sb.append(" lastClearTime=");
4019                 TimeUtils.formatDuration(mLastClearTimeMs - now, sb);
4020             }
4021             if (mLastCleanupTimeMs != 0) {
4022                 sb.append(" lastCleanupTime=");
4023                 TimeUtils.formatDuration(mLastCleanupTimeMs - now, sb);
4024             }
4025             Slog.wtf(TAG, sb.toString());
4026             return null;
4027         }
4028 
instantiateObject()4029         public abstract T instantiateObject();
4030     }
4031 
4032     @SuppressWarnings("ParcelableCreator")
4033     public static class ControllerActivityCounterImpl extends ControllerActivityCounter
4034             implements Parcelable {
4035         private final Clock mClock;
4036         private final TimeBase mTimeBase;
4037         private int mNumTxStates;
4038         private int mProcessState;
4039         private TimeMultiStateCounter mIdleTimeMillis;
4040         private final LongSamplingCounter mScanTimeMillis;
4041         private final LongSamplingCounter mSleepTimeMillis;
4042         private TimeMultiStateCounter mRxTimeMillis;
4043         private TimeMultiStateCounter[] mTxTimeMillis;
4044         private final LongSamplingCounter mPowerDrainMaMs;
4045         private final LongSamplingCounter mMonitoredRailChargeConsumedMaMs;
4046 
ControllerActivityCounterImpl(Clock clock, TimeBase timeBase, int numTxStates)4047         public ControllerActivityCounterImpl(Clock clock, TimeBase timeBase, int numTxStates) {
4048             mClock = clock;
4049             mTimeBase = timeBase;
4050             mNumTxStates = numTxStates;
4051             mScanTimeMillis = new LongSamplingCounter(timeBase);
4052             mSleepTimeMillis = new LongSamplingCounter(timeBase);
4053             mPowerDrainMaMs = new LongSamplingCounter(timeBase);
4054             mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase);
4055         }
4056 
readSummaryFromParcel(Parcel in)4057         public void readSummaryFromParcel(Parcel in) {
4058             mIdleTimeMillis = readTimeMultiStateCounter(in, mTimeBase);
4059             mScanTimeMillis.readSummaryFromParcelLocked(in);
4060             mSleepTimeMillis.readSummaryFromParcelLocked(in);
4061             mRxTimeMillis = readTimeMultiStateCounter(in, mTimeBase);
4062             mTxTimeMillis = readTimeMultiStateCounters(in, mTimeBase, mNumTxStates);
4063 
4064             mPowerDrainMaMs.readSummaryFromParcelLocked(in);
4065             mMonitoredRailChargeConsumedMaMs.readSummaryFromParcelLocked(in);
4066         }
4067 
4068         @Override
describeContents()4069         public int describeContents() {
4070             return 0;
4071         }
4072 
writeSummaryToParcel(Parcel dest)4073         public void writeSummaryToParcel(Parcel dest) {
4074             writeTimeMultiStateCounter(dest, mIdleTimeMillis);
4075             mScanTimeMillis.writeSummaryFromParcelLocked(dest);
4076             mSleepTimeMillis.writeSummaryFromParcelLocked(dest);
4077             writeTimeMultiStateCounter(dest, mRxTimeMillis);
4078             writeTimeMultiStateCounters(dest, mTxTimeMillis);
4079             mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
4080             mMonitoredRailChargeConsumedMaMs.writeSummaryFromParcelLocked(dest);
4081         }
4082 
4083         @Override
writeToParcel(Parcel dest, int flags)4084         public void writeToParcel(Parcel dest, int flags) {
4085             writeTimeMultiStateCounter(dest, mIdleTimeMillis);
4086             mScanTimeMillis.writeToParcel(dest);
4087             mSleepTimeMillis.writeToParcel(dest);
4088             writeTimeMultiStateCounter(dest, mRxTimeMillis);
4089             writeTimeMultiStateCounters(dest, mTxTimeMillis);
4090             mPowerDrainMaMs.writeToParcel(dest);
4091             mMonitoredRailChargeConsumedMaMs.writeToParcel(dest);
4092         }
4093 
readTimeMultiStateCounter(Parcel in, TimeBase timeBase)4094         private TimeMultiStateCounter readTimeMultiStateCounter(Parcel in, TimeBase timeBase) {
4095             if (in.readBoolean()) {
4096                 return TimeMultiStateCounter.readFromParcel(in, timeBase,
4097                         BatteryConsumer.PROCESS_STATE_COUNT, mClock.elapsedRealtime());
4098             }
4099             return null;
4100         }
4101 
writeTimeMultiStateCounter(Parcel dest, TimeMultiStateCounter counter)4102         private void writeTimeMultiStateCounter(Parcel dest, TimeMultiStateCounter counter) {
4103             if (counter != null) {
4104                 dest.writeBoolean(true);
4105                 counter.writeToParcel(dest);
4106             } else {
4107                 dest.writeBoolean(false);
4108             }
4109         }
4110 
readTimeMultiStateCounters(Parcel in, TimeBase timeBase, int expectedNumCounters)4111         private TimeMultiStateCounter[] readTimeMultiStateCounters(Parcel in, TimeBase timeBase,
4112                 int expectedNumCounters) {
4113             if (in.readBoolean()) {
4114                 final int numCounters = in.readInt();
4115                 boolean valid = (numCounters == expectedNumCounters);
4116                 // Need to read counters out of the Parcel, even if all or some of them are
4117                 // invalid.
4118                 TimeMultiStateCounter[] counters = new TimeMultiStateCounter[numCounters];
4119                 for (int i = 0; i < numCounters; i++) {
4120                     final TimeMultiStateCounter counter = TimeMultiStateCounter.readFromParcel(in,
4121                             timeBase, BatteryConsumer.PROCESS_STATE_COUNT,
4122                             mClock.elapsedRealtime());
4123                     if (counter != null) {
4124                         counters[i] = counter;
4125                     } else {
4126                         valid = false;
4127                     }
4128                 }
4129                 if (valid) {
4130                     return counters;
4131                 }
4132             }
4133             return null;
4134         }
4135 
writeTimeMultiStateCounters(Parcel dest, TimeMultiStateCounter[] counters)4136         private void writeTimeMultiStateCounters(Parcel dest, TimeMultiStateCounter[] counters) {
4137             if (counters != null) {
4138                 dest.writeBoolean(true);
4139                 dest.writeInt(counters.length);
4140                 for (TimeMultiStateCounter counter : counters) {
4141                     counter.writeToParcel(dest);
4142                 }
4143             } else {
4144                 dest.writeBoolean(false);
4145             }
4146         }
4147 
reset(boolean detachIfReset, long elapsedRealtimeUs)4148         public void reset(boolean detachIfReset, long elapsedRealtimeUs) {
4149             resetIfNotNull(mIdleTimeMillis, detachIfReset, elapsedRealtimeUs);
4150             mScanTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
4151             mSleepTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
4152             resetIfNotNull(mRxTimeMillis, detachIfReset, elapsedRealtimeUs);
4153             resetIfNotNull(mTxTimeMillis, detachIfReset, elapsedRealtimeUs);
4154             mPowerDrainMaMs.reset(detachIfReset, elapsedRealtimeUs);
4155             mMonitoredRailChargeConsumedMaMs.reset(detachIfReset, elapsedRealtimeUs);
4156         }
4157 
detach()4158         public void detach() {
4159             detachIfNotNull(mIdleTimeMillis);
4160             mScanTimeMillis.detach();
4161             mSleepTimeMillis.detach();
4162             detachIfNotNull(mRxTimeMillis);
4163             detachIfNotNull(mTxTimeMillis);
4164             mPowerDrainMaMs.detach();
4165             mMonitoredRailChargeConsumedMaMs.detach();
4166         }
4167 
4168         /**
4169          * @return a LongSamplingCounter, measuring time spent in the idle state in
4170          * milliseconds.
4171          */
4172         @Override
getIdleTimeCounter()4173         public LongCounter getIdleTimeCounter() {
4174             if (mIdleTimeMillis == null) {
4175                 return ZERO_LONG_COUNTER;
4176             }
4177             return mIdleTimeMillis;
4178         }
4179 
getOrCreateIdleTimeCounter()4180         private TimeMultiStateCounter getOrCreateIdleTimeCounter() {
4181             if (mIdleTimeMillis == null) {
4182                 mIdleTimeMillis = createTimeMultiStateCounter();
4183             }
4184             return mIdleTimeMillis;
4185         }
4186 
4187         /**
4188          * @return a LongSamplingCounter, measuring time spent in the scan state in
4189          * milliseconds.
4190          */
4191         @Override
getScanTimeCounter()4192         public LongSamplingCounter getScanTimeCounter() {
4193             return mScanTimeMillis;
4194         }
4195 
4196         /**
4197          * @return a LongSamplingCounter, measuring time spent in the sleep state in
4198          * milliseconds.
4199          */
4200         @Override
getSleepTimeCounter()4201         public LongSamplingCounter getSleepTimeCounter() {
4202             return mSleepTimeMillis;
4203         }
4204 
4205         /**
4206          * @return a LongSamplingCounter, measuring time spent in the receive state in
4207          * milliseconds.
4208          */
4209         @Override
getRxTimeCounter()4210         public LongCounter getRxTimeCounter() {
4211             if (mRxTimeMillis == null) {
4212                 return ZERO_LONG_COUNTER;
4213             }
4214             return mRxTimeMillis;
4215         }
4216 
getOrCreateRxTimeCounter()4217         private TimeMultiStateCounter getOrCreateRxTimeCounter() {
4218             if (mRxTimeMillis == null) {
4219                 mRxTimeMillis = createTimeMultiStateCounter();
4220             }
4221             return mRxTimeMillis;
4222         }
4223 
4224         /**
4225          * @return a LongSamplingCounter[], measuring time spent in various transmit states in
4226          * milliseconds.
4227          */
4228         @Override
getTxTimeCounters()4229         public LongCounter[] getTxTimeCounters() {
4230             if (mTxTimeMillis == null) {
4231                 return ZERO_LONG_COUNTER_ARRAY;
4232             }
4233             return mTxTimeMillis;
4234         }
4235 
getOrCreateTxTimeCounters()4236         private TimeMultiStateCounter[] getOrCreateTxTimeCounters() {
4237             if (mTxTimeMillis == null) {
4238                 mTxTimeMillis = new TimeMultiStateCounter[mNumTxStates];
4239                 for (int i = 0; i < mNumTxStates; i++) {
4240                     mTxTimeMillis[i] = createTimeMultiStateCounter();
4241                 }
4242             }
4243             return mTxTimeMillis;
4244         }
4245 
createTimeMultiStateCounter()4246         private TimeMultiStateCounter createTimeMultiStateCounter() {
4247             final long timestampMs = mClock.elapsedRealtime();
4248             TimeMultiStateCounter counter = new TimeMultiStateCounter(mTimeBase,
4249                     BatteryConsumer.PROCESS_STATE_COUNT, timestampMs);
4250             counter.setState(mapUidProcessStateToBatteryConsumerProcessState(mProcessState),
4251                     timestampMs);
4252             counter.update(0, timestampMs);
4253             return counter;
4254         }
4255 
4256         /**
4257          * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
4258          */
4259         @Override
getPowerCounter()4260         public LongSamplingCounter getPowerCounter() {
4261             return mPowerDrainMaMs;
4262         }
4263 
4264         /**
4265          * @return a LongSamplingCounter, measuring actual monitored rail energy consumed
4266          * milli-ampere milli-seconds (mAmS).
4267          */
4268         @Override
getMonitoredRailChargeConsumedMaMs()4269         public LongSamplingCounter getMonitoredRailChargeConsumedMaMs() {
4270             return mMonitoredRailChargeConsumedMaMs;
4271         }
4272 
setState(int processState, long elapsedTimeMs)4273         private void setState(int processState, long elapsedTimeMs) {
4274             mProcessState = processState;
4275             if (mIdleTimeMillis != null) {
4276                 mIdleTimeMillis.setState(processState, elapsedTimeMs);
4277             }
4278             if (mRxTimeMillis != null) {
4279                 mRxTimeMillis.setState(processState, elapsedTimeMs);
4280             }
4281             if (mTxTimeMillis != null) {
4282                 for (int i = 0; i < mTxTimeMillis.length; i++) {
4283                     mTxTimeMillis[i].setState(processState, elapsedTimeMs);
4284                 }
4285             }
4286         }
4287     }
4288 
4289     /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */
getRpmTimerLocked(String name)4290     public SamplingTimer getRpmTimerLocked(String name) {
4291         SamplingTimer rpmt = mRpmStats.get(name);
4292         if (rpmt == null) {
4293             rpmt = new SamplingTimer(mClock, mOnBatteryTimeBase);
4294             mRpmStats.put(name, rpmt);
4295         }
4296         return rpmt;
4297     }
4298 
4299     /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */
getScreenOffRpmTimerLocked(String name)4300     public SamplingTimer getScreenOffRpmTimerLocked(String name) {
4301         SamplingTimer rpmt = mScreenOffRpmStats.get(name);
4302         if (rpmt == null) {
4303             rpmt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase);
4304             mScreenOffRpmStats.put(name, rpmt);
4305         }
4306         return rpmt;
4307     }
4308 
4309     /*
4310      * Get the wakeup reason counter, and create a new one if one
4311      * doesn't already exist.
4312      */
getWakeupReasonTimerLocked(String name)4313     public SamplingTimer getWakeupReasonTimerLocked(String name) {
4314         SamplingTimer timer = mWakeupReasonStats.get(name);
4315         if (timer == null) {
4316             timer = new SamplingTimer(mClock, mOnBatteryTimeBase);
4317             mWakeupReasonStats.put(name, timer);
4318         }
4319         return timer;
4320     }
4321 
4322     /*
4323      * Get the KernelWakelockTimer associated with name, and create a new one if one
4324      * doesn't already exist.
4325      */
getKernelWakelockTimerLocked(String name)4326     public SamplingTimer getKernelWakelockTimerLocked(String name) {
4327         SamplingTimer kwlt = mKernelWakelockStats.get(name);
4328         if (kwlt == null) {
4329             kwlt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase);
4330             mKernelWakelockStats.put(name, kwlt);
4331         }
4332         return kwlt;
4333     }
4334 
getKernelMemoryTimerLocked(long bucket)4335     public SamplingTimer getKernelMemoryTimerLocked(long bucket) {
4336         SamplingTimer kmt = mKernelMemoryStats.get(bucket);
4337         if (kmt == null) {
4338             kmt = new SamplingTimer(mClock, mOnBatteryTimeBase);
4339             mKernelMemoryStats.put(bucket, kmt);
4340         }
4341         return kmt;
4342     }
4343 
4344     private class HistoryStepDetailsCalculatorImpl implements HistoryStepDetailsCalculator {
4345         private final HistoryStepDetails mDetails = new HistoryStepDetails();
4346 
4347         private boolean mHasHistoryStepDetails;
4348         private boolean mUpdateRequested;
4349 
4350         /**
4351          * Total time (in milliseconds) spent executing in user code.
4352          */
4353         private long mLastStepCpuUserTimeMs;
4354         private long mCurStepCpuUserTimeMs;
4355         /**
4356          * Total time (in milliseconds) spent executing in kernel code.
4357          */
4358         private long mLastStepCpuSystemTimeMs;
4359         private long mCurStepCpuSystemTimeMs;
4360         /**
4361          * Times from /proc/stat (but measured in milliseconds).
4362          */
4363         private long mLastStepStatUserTimeMs;
4364         private long mLastStepStatSystemTimeMs;
4365         private long mLastStepStatIOWaitTimeMs;
4366         private long mLastStepStatIrqTimeMs;
4367         private long mLastStepStatSoftIrqTimeMs;
4368         private long mLastStepStatIdleTimeMs;
4369         private long mCurStepStatUserTimeMs;
4370         private long mCurStepStatSystemTimeMs;
4371         private long mCurStepStatIOWaitTimeMs;
4372         private long mCurStepStatIrqTimeMs;
4373         private long mCurStepStatSoftIrqTimeMs;
4374         private long mCurStepStatIdleTimeMs;
4375 
4376         @Override
getHistoryStepDetails()4377         public HistoryStepDetails getHistoryStepDetails() {
4378             if (!mUpdateRequested) {
4379                 mUpdateRequested = true;
4380                 // Perform a CPU update right after we do this collection, so we have started
4381                 // collecting good data for the next step.
4382                 requestImmediateCpuUpdate();
4383 
4384                 if (mPlatformIdleStateCallback != null) {
4385                     mDetails.statSubsystemPowerState =
4386                             mPlatformIdleStateCallback.getSubsystemLowPowerStats();
4387                     if (DEBUG) {
4388                         Slog.i(TAG,
4389                                 "WRITE SubsystemPowerState:" + mDetails.statSubsystemPowerState);
4390                     }
4391                 }
4392             }
4393 
4394             if (!mHasHistoryStepDetails) {
4395                 // We are not generating a delta, so all we need to do is reset the stats
4396                 // we will later be doing a delta from.
4397                 final int uidCount = mUidStats.size();
4398                 for (int i = 0; i < uidCount; i++) {
4399                     final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4400                     uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
4401                     uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
4402                 }
4403                 mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
4404                 mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
4405                 mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
4406                 mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
4407                 mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
4408                 mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
4409                 mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
4410                 mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
4411                 return null;
4412             } else {
4413                 if (DEBUG) {
4414                     Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTimeMs + " sys="
4415                             + mLastStepStatSystemTimeMs + " io=" + mLastStepStatIOWaitTimeMs
4416                             + " irq=" + mLastStepStatIrqTimeMs + " sirq="
4417                             + mLastStepStatSoftIrqTimeMs + " idle=" + mLastStepStatIdleTimeMs);
4418                     Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTimeMs + " sys="
4419                             + mCurStepStatSystemTimeMs + " io=" + mCurStepStatIOWaitTimeMs
4420                             + " irq=" + mCurStepStatIrqTimeMs + " sirq="
4421                             + mCurStepStatSoftIrqTimeMs + " idle=" + mCurStepStatIdleTimeMs);
4422                 }
4423                 mDetails.userTime = (int) (mCurStepCpuUserTimeMs - mLastStepCpuUserTimeMs);
4424                 mDetails.systemTime = (int) (mCurStepCpuSystemTimeMs - mLastStepCpuSystemTimeMs);
4425                 mDetails.statUserTime = (int) (mCurStepStatUserTimeMs - mLastStepStatUserTimeMs);
4426                 mDetails.statSystemTime =
4427                         (int) (mCurStepStatSystemTimeMs - mLastStepStatSystemTimeMs);
4428                 mDetails.statIOWaitTime =
4429                         (int) (mCurStepStatIOWaitTimeMs - mLastStepStatIOWaitTimeMs);
4430                 mDetails.statIrqTime = (int) (mCurStepStatIrqTimeMs - mLastStepStatIrqTimeMs);
4431                 mDetails.statSoftIrqTime =
4432                         (int) (mCurStepStatSoftIrqTimeMs - mLastStepStatSoftIrqTimeMs);
4433                 mDetails.statIdlTime = (int) (mCurStepStatIdleTimeMs - mLastStepStatIdleTimeMs);
4434                 mDetails.appCpuUid1 = mDetails.appCpuUid2 = mDetails.appCpuUid3 = -1;
4435                 mDetails.appCpuUTime1 = mDetails.appCpuUTime2 = mDetails.appCpuUTime3 = 0;
4436                 mDetails.appCpuSTime1 = mDetails.appCpuSTime2 = mDetails.appCpuSTime3 = 0;
4437                 final int uidCount = mUidStats.size();
4438                 for (int i = 0; i < uidCount; i++) {
4439                     final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4440                     final int totalUTimeMs =
4441                             (int) (uid.mCurStepUserTimeMs - uid.mLastStepUserTimeMs);
4442                     final int totalSTimeMs =
4443                             (int) (uid.mCurStepSystemTimeMs - uid.mLastStepSystemTimeMs);
4444                     final int totalTimeMs = totalUTimeMs + totalSTimeMs;
4445                     uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
4446                     uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
4447                     if (totalTimeMs <= (mDetails.appCpuUTime3 + mDetails.appCpuSTime3)) {
4448                         continue;
4449                     }
4450                     if (totalTimeMs <= (mDetails.appCpuUTime2 + mDetails.appCpuSTime2)) {
4451                         mDetails.appCpuUid3 = uid.mUid;
4452                         mDetails.appCpuUTime3 = totalUTimeMs;
4453                         mDetails.appCpuSTime3 = totalSTimeMs;
4454                     } else {
4455                         mDetails.appCpuUid3 = mDetails.appCpuUid2;
4456                         mDetails.appCpuUTime3 = mDetails.appCpuUTime2;
4457                         mDetails.appCpuSTime3 = mDetails.appCpuSTime2;
4458                         if (totalTimeMs <= (mDetails.appCpuUTime1 + mDetails.appCpuSTime1)) {
4459                             mDetails.appCpuUid2 = uid.mUid;
4460                             mDetails.appCpuUTime2 = totalUTimeMs;
4461                             mDetails.appCpuSTime2 = totalSTimeMs;
4462                         } else {
4463                             mDetails.appCpuUid2 = mDetails.appCpuUid1;
4464                             mDetails.appCpuUTime2 = mDetails.appCpuUTime1;
4465                             mDetails.appCpuSTime2 = mDetails.appCpuSTime1;
4466                             mDetails.appCpuUid1 = uid.mUid;
4467                             mDetails.appCpuUTime1 = totalUTimeMs;
4468                             mDetails.appCpuSTime1 = totalSTimeMs;
4469                         }
4470                     }
4471                 }
4472                 mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
4473                 mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
4474                 mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
4475                 mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
4476                 mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
4477                 mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
4478                 mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
4479                 mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
4480                 return mDetails;
4481             }
4482         }
4483 
addCpuStats(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs, int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs, int statSoftIrqTimeMs, int statIdleTimeMs)4484         public void addCpuStats(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs,
4485                 int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
4486                 int statSoftIrqTimeMs, int statIdleTimeMs) {
4487             if (DEBUG) {
4488                 Slog.d(TAG, "Adding cpu: tuser=" + totalUTimeMs + " tsys=" + totalSTimeMs
4489                         + " user=" + statUserTimeMs + " sys=" + statSystemTimeMs
4490                         + " io=" + statIOWaitTimeMs + " irq=" + statIrqTimeMs
4491                         + " sirq=" + statSoftIrqTimeMs + " idle=" + statIdleTimeMs);
4492             }
4493             mCurStepCpuUserTimeMs += totalUTimeMs;
4494             mCurStepCpuSystemTimeMs += totalSTimeMs;
4495             mCurStepStatUserTimeMs += statUserTimeMs;
4496             mCurStepStatSystemTimeMs += statSystemTimeMs;
4497             mCurStepStatIOWaitTimeMs += statIOWaitTimeMs;
4498             mCurStepStatIrqTimeMs += statIrqTimeMs;
4499             mCurStepStatSoftIrqTimeMs += statSoftIrqTimeMs;
4500             mCurStepStatIdleTimeMs += statIdleTimeMs;
4501         }
4502 
finishAddingCpuLocked()4503         public void finishAddingCpuLocked() {
4504             mHasHistoryStepDetails = true;
4505             mUpdateRequested = false;
4506         }
4507 
4508         @Override
clear()4509         public void clear() {
4510             mHasHistoryStepDetails = false;
4511             mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs = 0;
4512             mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs = 0;
4513             mLastStepStatUserTimeMs = mCurStepStatUserTimeMs = 0;
4514             mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs = 0;
4515             mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs = 0;
4516             mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs = 0;
4517             mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs = 0;
4518             mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs = 0;
4519         }
4520     }
4521 
4522     @GuardedBy("this")
4523     @Override
commitCurrentHistoryBatchLocked()4524     public void commitCurrentHistoryBatchLocked() {
4525         mHistory.commitCurrentHistoryBatchLocked();
4526     }
4527 
4528     @GuardedBy("this")
createFakeHistoryEvents(long numEvents)4529     public void createFakeHistoryEvents(long numEvents) {
4530         final long elapsedRealtimeMs = mClock.elapsedRealtime();
4531         final long uptimeMs = mClock.uptimeMillis();
4532         for(long i = 0; i < numEvents; i++) {
4533             noteLongPartialWakelockStart("name1", "historyName1", 1000,
4534                     elapsedRealtimeMs, uptimeMs);
4535             noteLongPartialWakelockFinish("name1", "historyName1", 1000,
4536                     elapsedRealtimeMs, uptimeMs);
4537         }
4538     }
4539 
4540     @GuardedBy("this")
recordHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code, String name, int uid)4541     public void recordHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
4542             String name, int uid) {
4543         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, code, name, uid);
4544     }
4545 
4546     @GuardedBy("this")
updateTimeBasesLocked(boolean unplugged, int screenState, long uptimeUs, long realtimeUs)4547     public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptimeUs,
4548             long realtimeUs) {
4549         final boolean screenOff = !Display.isOnState(screenState);
4550         final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
4551         final boolean updateOnBatteryScreenOffTimeBase =
4552                 (unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
4553 
4554         if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) {
4555             if (updateOnBatteryScreenOffTimeBase) {
4556                 updateKernelWakelocksLocked(realtimeUs);
4557                 updateBatteryPropertiesLocked();
4558             }
4559             // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
4560             // updateRpmStatsLocked is too slow to run each screen change. When the speed is
4561             // improved, remove the surrounding if{}.
4562             if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
4563                 // if either OnBattery or OnBatteryScreenOfftimebase changes.
4564                 updateRpmStatsLocked(realtimeUs);
4565             }
4566             if (DEBUG_ENERGY_CPU) {
4567                 Slog.d(TAG, "Updating cpu time because screen is now "
4568                         + Display.stateToString(screenState)
4569                         + " and battery is " + (unplugged ? "on" : "off"));
4570             }
4571 
4572             mOnBatteryTimeBase.setRunning(unplugged, uptimeUs, realtimeUs);
4573             if (updateOnBatteryTimeBase) {
4574                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
4575                     mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptimeUs, realtimeUs);
4576                 }
4577             }
4578             if (updateOnBatteryScreenOffTimeBase) {
4579                 mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff,
4580                         uptimeUs, realtimeUs);
4581                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
4582                     mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptimeUs, realtimeUs);
4583                 }
4584             }
4585         }
4586     }
4587 
4588     @GuardedBy("this")
updateBatteryPropertiesLocked()4589     protected void updateBatteryPropertiesLocked() {
4590         try {
4591             IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
4592                     ServiceManager.getService("batteryproperties"));
4593             if (registrar != null) {
4594                 registrar.scheduleUpdate();
4595             }
4596         } catch (RemoteException e) {
4597             // Ignore.
4598         }
4599     }
4600 
onIsolatedUidAdded(int isolatedUid, int parentUid)4601     private void onIsolatedUidAdded(int isolatedUid, int parentUid) {
4602         long realtime = mClock.elapsedRealtime();
4603         long uptime = mClock.uptimeMillis();
4604         synchronized (this) {
4605             getUidStatsLocked(parentUid, realtime, uptime).addIsolatedUid(isolatedUid);
4606         }
4607     }
4608 
onBeforeIsolatedUidRemoved(int isolatedUid, int parentUid)4609     private void onBeforeIsolatedUidRemoved(int isolatedUid, int parentUid) {
4610         long realtime = mClock.elapsedRealtime();
4611         mPowerStatsUidResolver.retainIsolatedUid(isolatedUid);
4612         synchronized (this) {
4613             mPendingRemovedUids.add(new UidToRemove(isolatedUid, realtime));
4614         }
4615         if (mExternalSync != null) {
4616             mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
4617         }
4618     }
4619 
onAfterIsolatedUidRemoved(int isolatedUid, int parentUid)4620     private void onAfterIsolatedUidRemoved(int isolatedUid, int parentUid) {
4621         long realtime = mClock.elapsedRealtime();
4622         long uptime = mClock.uptimeMillis();
4623         synchronized (this) {
4624             getUidStatsLocked(parentUid, realtime, uptime).removeIsolatedUid(isolatedUid);
4625         }
4626     }
4627 
4628     /**
4629      * Isolated uid should only be removed after all wakelocks associated with the uid are stopped
4630      * and the cpu time-in-state has been read one last time for the uid.
4631      */
4632     @GuardedBy("this")
releaseIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs, long uptimeMs)4633     public void releaseIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs, long uptimeMs) {
4634         mPowerStatsUidResolver.releaseIsolatedUid(isolatedUid);
4635     }
4636 
mapUid(int uid)4637     private int mapUid(int uid) {
4638         if (Process.isSdkSandboxUid(uid)) {
4639             return Process.getAppUidForSdkSandboxUid(uid);
4640         }
4641         return mPowerStatsUidResolver.mapUid(uid);
4642     }
4643 
mapIsolatedUid(int uid)4644     private int mapIsolatedUid(int uid) {
4645         return mPowerStatsUidResolver.mapUid(uid);
4646     }
4647 
4648     @GuardedBy("this")
noteEventLocked(int code, String name, int uid, long elapsedRealtimeMs, long uptimeMs)4649     public void noteEventLocked(int code, String name, int uid,
4650             long elapsedRealtimeMs, long uptimeMs) {
4651         uid = mapUid(uid);
4652         if (!mActiveEvents.updateState(code, name, uid, 0)) {
4653             return;
4654         }
4655         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, code, name, uid);
4656     }
4657 
4658     @GuardedBy("this")
noteCurrentTimeChangedLocked(long currentTimeMs, long elapsedRealtimeMs, long uptimeMs)4659     public void noteCurrentTimeChangedLocked(long currentTimeMs,
4660             long elapsedRealtimeMs, long uptimeMs) {
4661         mHistory.recordCurrentTimeChange(elapsedRealtimeMs, uptimeMs, currentTimeMs);
4662         adjustStartClockTime(currentTimeMs);
4663     }
4664 
adjustStartClockTime(long currentTimeMs)4665     private void adjustStartClockTime(long currentTimeMs) {
4666         mStartClockTimeMs =
4667                 currentTimeMs - (mClock.elapsedRealtime() - (mRealtimeStartUs / 1000));
4668     }
4669 
4670     @GuardedBy("this")
noteProcessStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4671     public void noteProcessStartLocked(String name, int uid,
4672             long elapsedRealtimeMs, long uptimeMs) {
4673         uid = mapUid(uid);
4674         if (isOnBattery()) {
4675             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4676             u.getProcessStatsLocked(name).incStartsLocked();
4677         }
4678         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
4679             return;
4680         }
4681         if (!mRecordAllHistory) {
4682             return;
4683         }
4684         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid);
4685     }
4686 
4687     @GuardedBy("this")
noteProcessCrashLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4688     public void noteProcessCrashLocked(String name, int uid,
4689             long elapsedRealtimeMs, long uptimeMs) {
4690         uid = mapUid(uid);
4691         if (isOnBattery()) {
4692             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4693             u.getProcessStatsLocked(name).incNumCrashesLocked();
4694         }
4695     }
4696 
4697     @GuardedBy("this")
noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4698     public void noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4699         uid = mapUid(uid);
4700         if (isOnBattery()) {
4701             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4702             u.getProcessStatsLocked(name).incNumAnrsLocked();
4703         }
4704     }
4705 
4706     @GuardedBy("this")
noteUidProcessStateLocked(int uid, int state)4707     public void noteUidProcessStateLocked(int uid, int state) {
4708         noteUidProcessStateLocked(uid, state, mClock.elapsedRealtime(), mClock.uptimeMillis());
4709     }
4710 
4711     @GuardedBy("this")
4712     @SuppressWarnings("GuardedBy")   // errorprone false positive on u.updateUidProcessStateLocked
noteUidProcessStateLocked(int uid, int state, long elapsedRealtimeMs, long uptimeMs)4713     public void noteUidProcessStateLocked(int uid, int state,
4714             long elapsedRealtimeMs, long uptimeMs) {
4715         int parentUid = mapUid(uid);
4716         if (uid != parentUid) {
4717             if (Process.isIsolated(uid)) {
4718                 // Isolated UIDs process state is already rolled up into parent, so no need to track
4719                 // Otherwise the parent's process state will get downgraded incorrectly
4720                 return;
4721             }
4722         }
4723         mFrameworkStatsLogger.uidProcessStateChanged(uid, state);
4724         getUidStatsLocked(parentUid, elapsedRealtimeMs, uptimeMs)
4725                 .updateUidProcessStateLocked(state, elapsedRealtimeMs, uptimeMs);
4726     }
4727 
4728     @GuardedBy("this")
noteProcessFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4729     public void noteProcessFinishLocked(String name, int uid,
4730             long elapsedRealtimeMs, long uptimeMs) {
4731         uid = mapUid(uid);
4732         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
4733             return;
4734         }
4735         if (!mRecordAllHistory) {
4736             return;
4737         }
4738         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH, name, uid);
4739     }
4740 
4741     @GuardedBy("this")
noteSyncStartLocked(String name, int uid)4742     public void noteSyncStartLocked(String name, int uid) {
4743         noteSyncStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4744     }
4745 
4746     @GuardedBy("this")
noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4747     public void noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4748         uid = mapUid(uid);
4749         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4750                 .noteStartSyncLocked(name, elapsedRealtimeMs);
4751         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
4752             return;
4753         }
4754         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid);
4755     }
4756 
4757     @GuardedBy("this")
noteSyncFinishLocked(String name, int uid)4758     public void noteSyncFinishLocked(String name, int uid) {
4759         noteSyncFinishLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4760     }
4761 
4762     @GuardedBy("this")
noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4763     public void noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4764         uid = mapUid(uid);
4765         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4766                 .noteStopSyncLocked(name, elapsedRealtimeMs);
4767         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
4768             return;
4769         }
4770         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH, name, uid);
4771     }
4772 
4773     @GuardedBy("this")
noteJobStartLocked(String name, int uid)4774     public void noteJobStartLocked(String name, int uid) {
4775         noteJobStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4776     }
4777 
4778     @GuardedBy("this")
noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4779     public void noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4780         uid = mapUid(uid);
4781         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4782                 .noteStartJobLocked(name, elapsedRealtimeMs);
4783         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
4784             return;
4785         }
4786         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid);
4787     }
4788 
4789     @GuardedBy("this")
noteJobFinishLocked(String name, int uid, int stopReason)4790     public void noteJobFinishLocked(String name, int uid, int stopReason) {
4791         noteJobFinishLocked(name, uid, stopReason,
4792                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4793     }
4794 
4795     @GuardedBy("this")
noteJobFinishLocked(String name, int uid, int stopReason, long elapsedRealtimeMs, long uptimeMs)4796     public void noteJobFinishLocked(String name, int uid, int stopReason,
4797             long elapsedRealtimeMs, long uptimeMs) {
4798         uid = mapUid(uid);
4799         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4800                 .noteStopJobLocked(name, elapsedRealtimeMs, stopReason);
4801         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
4802             return;
4803         }
4804         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid);
4805     }
4806 
4807     @GuardedBy("this")
noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast, long elapsedRealtimeMs, long uptimeMs)4808     public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast,
4809             long elapsedRealtimeMs, long uptimeMs) {
4810         uid = mapUid(uid);
4811         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4812                 .noteJobsDeferredLocked(numDeferred, sinceLast);
4813     }
4814 
4815     @GuardedBy("this")
noteAlarmStartLocked(String name, WorkSource workSource, int uid)4816     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
4817         noteAlarmStartLocked(name, workSource, uid,
4818                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4819     }
4820 
4821     @GuardedBy("this")
noteAlarmStartLocked(String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4822     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid,
4823             long elapsedRealtimeMs, long uptimeMs) {
4824         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid,
4825                 elapsedRealtimeMs, uptimeMs);
4826     }
4827 
4828     @GuardedBy("this")
noteAlarmFinishLocked(String name, WorkSource workSource, int uid)4829     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
4830         noteAlarmFinishLocked(name, workSource, uid,
4831                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4832     }
4833 
4834     @GuardedBy("this")
noteAlarmFinishLocked(String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4835     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid,
4836             long elapsedRealtimeMs, long uptimeMs) {
4837         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid,
4838                 elapsedRealtimeMs, uptimeMs);
4839     }
4840 
4841     @GuardedBy("this")
noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4842     private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
4843             int uid, long elapsedRealtimeMs, long uptimeMs) {
4844         if (!mRecordAllHistory) {
4845             return;
4846         }
4847 
4848         if (workSource != null) {
4849             for (int i = 0; i < workSource.size(); ++i) {
4850                 uid = mapUid(workSource.getUid(i));
4851                 if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4852                     mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4853                 }
4854             }
4855 
4856             List<WorkChain> workChains = workSource.getWorkChains();
4857             if (workChains != null) {
4858                 for (int i = 0; i < workChains.size(); ++i) {
4859                     uid = mapUid(workChains.get(i).getAttributionUid());
4860                     if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4861                         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4862                     }
4863                 }
4864             }
4865         } else {
4866             uid = mapUid(uid);
4867 
4868             if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4869                 mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4870             }
4871         }
4872     }
4873 
4874     @GuardedBy("this")
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag)4875     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4876             String tag) {
4877         noteWakupAlarmLocked(packageName, uid, workSource, tag,
4878                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4879     }
4880 
4881     @GuardedBy("this")
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag, long elapsedRealtimeMs, long uptimeMs)4882     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4883             String tag, long elapsedRealtimeMs, long uptimeMs) {
4884         if (workSource != null) {
4885             for (int i = 0; i < workSource.size(); ++i) {
4886                 uid = workSource.getUid(i);
4887                 final String workSourceName = workSource.getPackageName(i);
4888 
4889                 if (isOnBattery()) {
4890                     BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
4891                             workSourceName != null ? workSourceName : packageName,
4892                             elapsedRealtimeMs, uptimeMs);
4893                     pkg.noteWakeupAlarmLocked(tag);
4894                 }
4895             }
4896 
4897             List<WorkChain> workChains = workSource.getWorkChains();
4898             if (workChains != null) {
4899                 for (int i = 0; i < workChains.size(); ++i) {
4900                     final WorkChain wc = workChains.get(i);
4901                     uid = wc.getAttributionUid();
4902 
4903                     if (isOnBattery()) {
4904                         BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName,
4905                                 elapsedRealtimeMs, uptimeMs);
4906                         pkg.noteWakeupAlarmLocked(tag);
4907                     }
4908                 }
4909             }
4910         } else {
4911             if (isOnBattery()) {
4912                 BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName,
4913                         elapsedRealtimeMs, uptimeMs);
4914                 pkg.noteWakeupAlarmLocked(tag);
4915             }
4916         }
4917     }
4918 
requestWakelockCpuUpdate()4919     private void requestWakelockCpuUpdate() {
4920         mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS);
4921     }
4922 
requestImmediateCpuUpdate()4923     private void requestImmediateCpuUpdate() {
4924         mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
4925     }
4926 
4927     @GuardedBy("this")
setRecordAllHistoryLocked(boolean enabled)4928     public void setRecordAllHistoryLocked(boolean enabled) {
4929         mRecordAllHistory = enabled;
4930         if (!enabled) {
4931             // Clear out any existing state.
4932             mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
4933             mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
4934             // Record the currently running processes as stopping, now that we are no
4935             // longer tracking them.
4936             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4937                     HistoryItem.EVENT_PROC);
4938             if (active != null) {
4939                 long mSecRealtime = mClock.elapsedRealtime();
4940                 final long mSecUptime = mClock.uptimeMillis();
4941                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4942                     SparseIntArray uids = ent.getValue();
4943                     for (int j=0; j<uids.size(); j++) {
4944                         mHistory.recordEvent(mSecRealtime, mSecUptime,
4945                                 HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
4946                     }
4947                 }
4948             }
4949         } else {
4950             // Record the currently running processes as starting, now that we are tracking them.
4951             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4952                     HistoryItem.EVENT_PROC);
4953             if (active != null) {
4954                 long mSecRealtime = mClock.elapsedRealtime();
4955                 final long mSecUptime = mClock.uptimeMillis();
4956                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4957                     SparseIntArray uids = ent.getValue();
4958                     for (int j=0; j<uids.size(); j++) {
4959                         mHistory.recordEvent(mSecRealtime, mSecUptime, HistoryItem.EVENT_PROC_START,
4960                                 ent.getKey(), uids.keyAt(j));
4961                     }
4962                 }
4963             }
4964         }
4965     }
4966 
setNoAutoReset(boolean enabled)4967     public void setNoAutoReset(boolean enabled) {
4968         mNoAutoReset = enabled;
4969     }
4970 
4971     @GuardedBy("this")
setPretendScreenOff(boolean pretendScreenOff)4972     public void setPretendScreenOff(boolean pretendScreenOff) {
4973         if (mPretendScreenOff != pretendScreenOff) {
4974             mPretendScreenOff = pretendScreenOff;
4975             final int primaryScreenState = mPerDisplayBatteryStats[0].screenState;
4976             noteScreenStateLocked(0, primaryScreenState,
4977                     mClock.elapsedRealtime(), mClock.uptimeMillis(),
4978                     mClock.currentTimeMillis());
4979         }
4980     }
4981 
4982     @GuardedBy("this")
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging)4983     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4984             int type, boolean unimportantForLogging) {
4985         noteStartWakeLocked(uid, pid, wc, name, historyName, type, unimportantForLogging,
4986                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4987     }
4988 
4989     @GuardedBy("this")
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs)4990     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4991             int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs) {
4992         final int mappedUid = mapUid(uid);
4993         if (type == WAKE_TYPE_PARTIAL) {
4994             // Only care about partial wake locks, since full wake locks
4995             // will be canceled when the user puts the screen to sleep.
4996             if (historyName == null) {
4997                 historyName = name;
4998             }
4999             if (mRecordAllHistory) {
5000                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
5001                         mappedUid, 0)) {
5002                     mHistory.recordEvent(elapsedRealtimeMs, uptimeMs,
5003                             HistoryItem.EVENT_WAKE_LOCK_START, historyName, mappedUid);
5004                 }
5005             }
5006             if (mWakeLockNesting == 0) {
5007                 mWakeLockImportant = !unimportantForLogging;
5008                 mHistory.recordWakelockStartEvent(elapsedRealtimeMs, uptimeMs, historyName,
5009                         mappedUid);
5010             } else if (!mWakeLockImportant && !unimportantForLogging) {
5011                 if (mHistory.maybeUpdateWakelockTag(elapsedRealtimeMs, uptimeMs, historyName,
5012                         mappedUid)) {
5013                     mWakeLockImportant = true;
5014                 }
5015             }
5016             mWakeLockNesting++;
5017         }
5018         if (mappedUid >= 0) {
5019             if (mappedUid != uid) {
5020                 // Prevent the isolated uid mapping from being removed while the wakelock is
5021                 // being held.
5022                 mPowerStatsUidResolver.retainIsolatedUid(uid);
5023             }
5024             if (mOnBatteryScreenOffTimeBase.isRunning()) {
5025                 // We only update the cpu time when a wake lock is acquired if the screen is off.
5026                 // If the screen is on, we don't distribute the power amongst partial wakelocks.
5027                 if (DEBUG_ENERGY_CPU) {
5028                     Slog.d(TAG, "Updating cpu time because of +wake_lock");
5029                 }
5030                 requestWakelockCpuUpdate();
5031             }
5032 
5033             Uid uidStats = getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs);
5034             uidStats.noteStartWakeLocked(pid, name, type, elapsedRealtimeMs);
5035 
5036             mFrameworkStatsLogger.wakelockStateChanged(mapIsolatedUid(uid), wc, name,
5037                     uidStats.mProcessState, true /* acquired */,
5038                     getPowerManagerWakeLockLevel(type));
5039         }
5040     }
5041 
5042     @GuardedBy("this")
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type)5043     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
5044             int type) {
5045         noteStopWakeLocked(uid, pid, wc, name, historyName, type,
5046                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5047     }
5048 
5049     @GuardedBy("this")
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs)5050     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
5051             int type, long elapsedRealtimeMs, long uptimeMs) {
5052         final int mappedUid = mapUid(uid);
5053         if (type == WAKE_TYPE_PARTIAL) {
5054             mWakeLockNesting--;
5055             if (historyName == null) {
5056                 historyName = name;
5057             }
5058             if (mRecordAllHistory) {
5059                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
5060                         mappedUid, 0)) {
5061                     mHistory.recordEvent(elapsedRealtimeMs, uptimeMs,
5062                             HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, mappedUid);
5063                 }
5064             }
5065             if (mWakeLockNesting == 0) {
5066                 mHistory.recordWakelockStopEvent(elapsedRealtimeMs, uptimeMs, historyName,
5067                         mappedUid);
5068             }
5069         }
5070         if (mappedUid >= 0) {
5071             if (mOnBatteryScreenOffTimeBase.isRunning()) {
5072                 if (DEBUG_ENERGY_CPU) {
5073                     Slog.d(TAG, "Updating cpu time because of -wake_lock");
5074                 }
5075                 requestWakelockCpuUpdate();
5076             }
5077 
5078             Uid uidStats = getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs);
5079             uidStats.noteStopWakeLocked(pid, name, type, elapsedRealtimeMs);
5080 
5081             mFrameworkStatsLogger.wakelockStateChanged(mapIsolatedUid(uid), wc, name,
5082                     uidStats.mProcessState, false/* acquired */,
5083                     getPowerManagerWakeLockLevel(type));
5084 
5085             if (mappedUid != uid) {
5086                 // Decrement the ref count for the isolated uid and delete the mapping if uneeded.
5087                 releaseIsolatedUidLocked(uid, elapsedRealtimeMs, uptimeMs);
5088             }
5089         }
5090     }
5091 
5092     /**
5093      * Converts BatteryStats wakelock types back into PowerManager wakelock levels.
5094      * This is the inverse map of Notifier.getBatteryStatsWakeLockMonitorType().
5095      * These are estimations, since batterystats loses some of the original data.
5096      * TODO: Delete this. Instead, FrameworkStatsLog.write should be called from
5097      * PowerManager's Notifier.
5098      */
getPowerManagerWakeLockLevel(int batteryStatsWakelockType)5099     private int getPowerManagerWakeLockLevel(int batteryStatsWakelockType) {
5100         switch (batteryStatsWakelockType) {
5101             // PowerManager.PARTIAL_WAKE_LOCK or PROXIMITY_SCREEN_OFF_WAKE_LOCK
5102             case BatteryStats.WAKE_TYPE_PARTIAL:
5103                 return PowerManager.PARTIAL_WAKE_LOCK;
5104 
5105             // PowerManager.SCREEN_DIM_WAKE_LOCK or SCREEN_BRIGHT_WAKE_LOCK
5106             case BatteryStats.WAKE_TYPE_FULL:
5107                 return PowerManager.FULL_WAKE_LOCK;
5108 
5109             case BatteryStats.WAKE_TYPE_DRAW:
5110                 return PowerManager.DRAW_WAKE_LOCK;
5111 
5112             // It appears that nothing can ever make a Window and PowerManager lacks an equivalent.
5113             case BatteryStats.WAKE_TYPE_WINDOW:
5114                 Slog.e(TAG, "Illegal window wakelock type observed in batterystats.");
5115                 return -1;
5116 
5117             default:
5118                 Slog.e(TAG, "Illegal wakelock type in batterystats: " + batteryStatsWakelockType);
5119                 return -1;
5120         }
5121     }
5122 
5123     @GuardedBy("this")
noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs)5124     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
5125             String historyName, int type, boolean unimportantForLogging,
5126             long elapsedRealtimeMs, long uptimeMs) {
5127         final int N = ws.size();
5128         for (int i=0; i<N; i++) {
5129             noteStartWakeLocked(ws.getUid(i), pid, null, name, historyName, type,
5130                     unimportantForLogging, elapsedRealtimeMs, uptimeMs);
5131         }
5132 
5133         List<WorkChain> wcs = ws.getWorkChains();
5134         if (wcs != null) {
5135             for (int i = 0; i < wcs.size(); ++i) {
5136                 final WorkChain wc = wcs.get(i);
5137                 noteStartWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
5138                         unimportantForLogging, elapsedRealtimeMs, uptimeMs);
5139             }
5140         }
5141     }
5142 
5143     @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)5144     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
5145             String historyName, int type, WorkSource newWs, int newPid, String newName,
5146             String newHistoryName, int newType, boolean newUnimportantForLogging,
5147             long elapsedRealtimeMs, long uptimeMs) {
5148         List<WorkChain>[] wcs = WorkSource.diffChains(ws, newWs);
5149 
5150         // For correct semantics, we start the need worksources first, so that we won't
5151         // make inappropriate history items as if all wake locks went away and new ones
5152         // appeared.  This is okay because tracking of wake locks allows nesting.
5153         //
5154         // First the starts :
5155         final int NN = newWs.size();
5156         for (int i=0; i<NN; i++) {
5157             noteStartWakeLocked(newWs.getUid(i), newPid, null, newName, newHistoryName, newType,
5158                     newUnimportantForLogging, elapsedRealtimeMs, uptimeMs);
5159         }
5160         if (wcs != null) {
5161             List<WorkChain> newChains = wcs[0];
5162             if (newChains != null) {
5163                 for (int i = 0; i < newChains.size(); ++i) {
5164                     final WorkChain newChain = newChains.get(i);
5165                     noteStartWakeLocked(newChain.getAttributionUid(), newPid, newChain, newName,
5166                             newHistoryName, newType, newUnimportantForLogging, elapsedRealtimeMs,
5167                             uptimeMs);
5168                 }
5169             }
5170         }
5171 
5172         // Then the stops :
5173         final int NO = ws.size();
5174         for (int i=0; i<NO; i++) {
5175             noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs,
5176                     uptimeMs);
5177         }
5178         if (wcs != null) {
5179             List<WorkChain> goneChains = wcs[1];
5180             if (goneChains != null) {
5181                 for (int i = 0; i < goneChains.size(); ++i) {
5182                     final WorkChain goneChain = goneChains.get(i);
5183                     noteStopWakeLocked(goneChain.getAttributionUid(), pid, goneChain, name,
5184                             historyName, type, elapsedRealtimeMs, uptimeMs);
5185                 }
5186             }
5187         }
5188     }
5189 
5190     @GuardedBy("this")
noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs)5191     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
5192             String historyName, int type, long elapsedRealtimeMs, long uptimeMs) {
5193         final int N = ws.size();
5194         for (int i=0; i<N; i++) {
5195             noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs,
5196                     uptimeMs);
5197         }
5198 
5199         List<WorkChain> wcs = ws.getWorkChains();
5200         if (wcs != null) {
5201             for (int i = 0; i < wcs.size(); ++i) {
5202                 final WorkChain wc = wcs.get(i);
5203                 noteStopWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
5204                         elapsedRealtimeMs, uptimeMs);
5205             }
5206         }
5207     }
5208 
5209     @GuardedBy("this")
noteLongPartialWakelockStart(String name, String historyName, int uid)5210     public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
5211         noteLongPartialWakelockStart(name, historyName, uid,
5212                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5213     }
5214 
5215     @GuardedBy("this")
noteLongPartialWakelockStart(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5216     public void noteLongPartialWakelockStart(String name, String historyName, int uid,
5217             long elapsedRealtimeMs, long uptimeMs) {
5218         noteLongPartialWakeLockStartInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
5219     }
5220 
5221     @GuardedBy("this")
noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource, long elapsedRealtimeMs, long uptimeMs)5222     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
5223             WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
5224         final int N = workSource.size();
5225         for (int i = 0; i < N; ++i) {
5226             final int uid = mapUid(workSource.getUid(i));
5227             noteLongPartialWakeLockStartInternal(name, historyName, uid,
5228                     elapsedRealtimeMs, uptimeMs);
5229         }
5230 
5231         final List<WorkChain> workChains = workSource.getWorkChains();
5232         if (workChains != null) {
5233             for (int i = 0; i < workChains.size(); ++i) {
5234                 final WorkChain workChain = workChains.get(i);
5235                 final int uid = workChain.getAttributionUid();
5236                 noteLongPartialWakeLockStartInternal(name, historyName, uid,
5237                         elapsedRealtimeMs, uptimeMs);
5238             }
5239         }
5240     }
5241 
5242     @GuardedBy("this")
noteLongPartialWakeLockStartInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5243     private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid,
5244             long elapsedRealtimeMs, long uptimeMs) {
5245         final int mappedUid = mapUid(uid);
5246         if (historyName == null) {
5247             historyName = name;
5248         }
5249         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName,
5250                 mappedUid, 0)) {
5251             return;
5252         }
5253         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
5254                 historyName, mappedUid);
5255         if (mappedUid != uid) {
5256             // Prevent the isolated uid mapping from being removed while the wakelock is
5257             // being held.
5258             mPowerStatsUidResolver.retainIsolatedUid(uid);
5259         }
5260     }
5261 
5262     @GuardedBy("this")
noteLongPartialWakelockFinish(String name, String historyName, int uid)5263     public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
5264         noteLongPartialWakelockFinish(name, historyName, uid,
5265                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5266     }
5267 
5268     @GuardedBy("this")
noteLongPartialWakelockFinish(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5269     public void noteLongPartialWakelockFinish(String name, String historyName, int uid,
5270             long elapsedRealtimeMs, long uptimeMs) {
5271         noteLongPartialWakeLockFinishInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
5272     }
5273 
5274     @GuardedBy("this")
noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource, long elapsedRealtimeMs, long uptimeMs)5275     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
5276             WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
5277         final int N = workSource.size();
5278         for (int i = 0; i < N; ++i) {
5279             final int uid = mapUid(workSource.getUid(i));
5280             noteLongPartialWakeLockFinishInternal(name, historyName, uid,
5281                     elapsedRealtimeMs, uptimeMs);
5282         }
5283 
5284         final List<WorkChain> workChains = workSource.getWorkChains();
5285         if (workChains != null) {
5286             for (int i = 0; i < workChains.size(); ++i) {
5287                 final WorkChain workChain = workChains.get(i);
5288                 final int uid = workChain.getAttributionUid();
5289                 noteLongPartialWakeLockFinishInternal(name, historyName, uid,
5290                         elapsedRealtimeMs, uptimeMs);
5291             }
5292         }
5293     }
5294 
5295     @GuardedBy("this")
noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5296     private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid,
5297             long elapsedRealtimeMs, long uptimeMs) {
5298         final int mappedUid = mapUid(uid);
5299         if (historyName == null) {
5300             historyName = name;
5301         }
5302         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName,
5303                 mappedUid, 0)) {
5304             return;
5305         }
5306         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
5307                 historyName, mappedUid);
5308         if (mappedUid != uid) {
5309             // Decrement the ref count for the isolated uid and delete the mapping if uneeded.
5310             releaseIsolatedUidLocked(uid, elapsedRealtimeMs, uptimeMs);
5311         }
5312     }
5313 
5314     @GuardedBy("this")
noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs)5315     public void noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs) {
5316         if (mLastWakeupReason != null) {
5317             long deltaUptimeMs = uptimeMs - mLastWakeupUptimeMs;
5318             SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
5319             timer.add(deltaUptimeMs * 1000, 1, elapsedRealtimeMs); // time in in microseconds
5320             mFrameworkStatsLogger.kernelWakeupReported(deltaUptimeMs * 1000, mLastWakeupReason,
5321                     mLastWakeupElapsedTimeMs);
5322         }
5323         mHistory.recordWakeupEvent(elapsedRealtimeMs, uptimeMs, reason);
5324         mLastWakeupReason = reason;
5325         mLastWakeupUptimeMs = uptimeMs;
5326         mLastWakeupElapsedTimeMs = elapsedRealtimeMs;
5327     }
5328 
5329     @GuardedBy("this")
startAddingCpuStatsLocked()5330     public boolean startAddingCpuStatsLocked() {
5331         mExternalSync.cancelCpuSyncDueToWakelockChange();
5332         return mOnBatteryInternal;
5333     }
5334 
5335     @GuardedBy("this")
addCpuStatsLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs, int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs, int statSoftIrqTimeMs, int statIdleTimeMs)5336     public void addCpuStatsLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs,
5337             int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
5338             int statSoftIrqTimeMs, int statIdleTimeMs) {
5339         mStepDetailsCalculator.addCpuStats(totalUTimeMs, totalSTimeMs, statUserTimeMs,
5340                 statSystemTimeMs, statIOWaitTimeMs, statIrqTimeMs,
5341                 statSoftIrqTimeMs, statIdleTimeMs);
5342     }
5343 
5344     /**
5345      * Called after {@link #addCpuStatsLocked} has been invoked for all active apps.
5346      */
5347     @GuardedBy("this")
finishAddingCpuStatsLocked()5348     public void finishAddingCpuStatsLocked() {
5349         mStepDetailsCalculator.finishAddingCpuLocked();
5350     }
5351 
noteProcessDiedLocked(int uid, int pid)5352     public void noteProcessDiedLocked(int uid, int pid) {
5353         uid = mapUid(uid);
5354         Uid u = mUidStats.get(uid);
5355         if (u != null) {
5356             u.mPids.remove(pid);
5357         }
5358     }
5359 
reportExcessiveCpuLocked(int uid, String proc, long overTimeMs, long usedTimeMs)5360     public void reportExcessiveCpuLocked(int uid, String proc, long overTimeMs, long usedTimeMs) {
5361         uid = mapUid(uid);
5362         Uid u = mUidStats.get(uid);
5363         if (u != null) {
5364             u.reportExcessiveCpuLocked(proc, overTimeMs, usedTimeMs);
5365         }
5366     }
5367 
5368     int mSensorNesting;
5369 
5370     @GuardedBy("this")
noteStartSensorLocked(int uid, int sensor)5371     public void noteStartSensorLocked(int uid, int sensor) {
5372         noteStartSensorLocked(uid, sensor, mClock.elapsedRealtime(), mClock.uptimeMillis());
5373     }
5374 
5375     @GuardedBy("this")
noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs)5376     public void noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
5377         uid = mapUid(uid);
5378         if (mSensorNesting == 0) {
5379             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
5380                     HistoryItem.STATE_SENSOR_ON_FLAG);
5381         }
5382         mSensorNesting++;
5383         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5384                 .noteStartSensor(sensor, elapsedRealtimeMs);
5385     }
5386 
5387     @GuardedBy("this")
noteStopSensorLocked(int uid, int sensor)5388     public void noteStopSensorLocked(int uid, int sensor) {
5389         noteStopSensorLocked(uid, sensor, mClock.elapsedRealtime(), mClock.uptimeMillis());
5390     }
5391 
5392     @GuardedBy("this")
noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs)5393     public void noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
5394         uid = mapUid(uid);
5395         mSensorNesting--;
5396         if (mSensorNesting == 0) {
5397             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
5398                     HistoryItem.STATE_SENSOR_ON_FLAG);
5399         }
5400         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5401                 .noteStopSensor(sensor, elapsedRealtimeMs);
5402     }
5403 
5404     int mGpsNesting;
5405 
5406     @GuardedBy("this")
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs)5407     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
5408         noteGpsChangedLocked(oldWs, newWs, mClock.elapsedRealtime(), mClock.uptimeMillis());
5409     }
5410 
5411     @GuardedBy("this")
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs, long elapsedRealtimeMs, long uptimeMs)5412     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs,
5413             long elapsedRealtimeMs, long uptimeMs) {
5414         for (int i = 0; i < newWs.size(); ++i) {
5415             noteStartGpsLocked(newWs.getUid(i), null, elapsedRealtimeMs, uptimeMs);
5416         }
5417 
5418         for (int i = 0; i < oldWs.size(); ++i) {
5419             noteStopGpsLocked((oldWs.getUid(i)), null, elapsedRealtimeMs, uptimeMs);
5420         }
5421 
5422         List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
5423         if (wcs != null) {
5424             if (wcs[0] != null) {
5425                 final List<WorkChain> newChains = wcs[0];
5426                 for (int i = 0; i < newChains.size(); ++i) {
5427                     noteStartGpsLocked(-1, newChains.get(i), elapsedRealtimeMs, uptimeMs);
5428                 }
5429             }
5430 
5431             if (wcs[1] != null) {
5432                 final List<WorkChain> goneChains = wcs[1];
5433                 for (int i = 0; i < goneChains.size(); ++i) {
5434                     noteStopGpsLocked(-1, goneChains.get(i), elapsedRealtimeMs, uptimeMs);
5435                 }
5436             }
5437         }
5438     }
5439 
5440     @GuardedBy("this")
noteStartGpsLocked(int uid, WorkChain workChain, long elapsedRealtimeMs, long uptimeMs)5441     private void noteStartGpsLocked(int uid, WorkChain workChain,
5442             long elapsedRealtimeMs, long uptimeMs) {
5443         if (workChain != null) {
5444             uid = workChain.getAttributionUid();
5445         }
5446         final int mappedUid = mapUid(uid);
5447         if (mGpsNesting == 0) {
5448             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
5449                     HistoryItem.STATE_GPS_ON_FLAG);
5450         }
5451         mGpsNesting++;
5452 
5453         mFrameworkStatsLogger.gpsScanStateChanged(mapIsolatedUid(uid), workChain, /* on */true);
5454 
5455         getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs).noteStartGps(elapsedRealtimeMs);
5456     }
5457 
5458     @GuardedBy("this")
noteStopGpsLocked(int uid, WorkChain workChain, long elapsedRealtimeMs, long uptimeMs)5459     private void noteStopGpsLocked(int uid, WorkChain workChain,
5460             long elapsedRealtimeMs, long uptimeMs) {
5461         if (workChain != null) {
5462             uid = workChain.getAttributionUid();
5463         }
5464         final int mappedUid = mapUid(uid);
5465         mGpsNesting--;
5466         if (mGpsNesting == 0) {
5467             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
5468                     HistoryItem.STATE_GPS_ON_FLAG);
5469             mHistory.recordGpsSignalQualityEvent(elapsedRealtimeMs, uptimeMs,
5470                     GPS_SIGNAL_QUALITY_NONE);
5471             stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
5472             mGpsSignalQualityBin = -1;
5473         }
5474 
5475         mFrameworkStatsLogger.gpsScanStateChanged(mapIsolatedUid(uid), workChain, /* on */ false);
5476 
5477         getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs).noteStopGps(elapsedRealtimeMs);
5478     }
5479 
5480     @GuardedBy("this")
noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs)5481     public void noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs) {
5482         if (mGpsNesting == 0) {
5483             return;
5484         }
5485         if (signalLevel < 0 || signalLevel >= mGpsSignalQualityTimer.length) {
5486             stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
5487             return;
5488         }
5489         if (mGpsSignalQualityBin != signalLevel) {
5490             if (mGpsSignalQualityBin >= 0) {
5491                 mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtimeMs);
5492             }
5493             if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
5494                 mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtimeMs);
5495             }
5496             mHistory.recordGpsSignalQualityEvent(elapsedRealtimeMs, uptimeMs, signalLevel);
5497             mGpsSignalQualityBin = signalLevel;
5498         }
5499     }
5500 
5501     @GuardedBy("this")
noteScreenStateLocked(int display, int state)5502     public void noteScreenStateLocked(int display, int state) {
5503         noteScreenStateLocked(display, state, mClock.elapsedRealtime(), mClock.uptimeMillis(),
5504                 mClock.currentTimeMillis());
5505     }
5506 
5507     @GuardedBy("this")
noteScreenStateLocked(int display, int displayState, long elapsedRealtimeMs, long uptimeMs, long currentTimeMs)5508     public void noteScreenStateLocked(int display, int displayState,
5509             long elapsedRealtimeMs, long uptimeMs, long currentTimeMs) {
5510         // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
5511         // original 4 are mapped to one of the originals.
5512         if (displayState > MAX_TRACKED_SCREEN_STATE) {
5513             if (Display.isOnState(displayState)) {
5514                 displayState = Display.STATE_ON;
5515             } else if (Display.isDozeState(displayState)) {
5516                 if (Display.isSuspendedState(displayState)) {
5517                     displayState = Display.STATE_DOZE_SUSPEND;
5518                 } else {
5519                     displayState = Display.STATE_DOZE;
5520                 }
5521             } else if (Display.isOffState(displayState)) {
5522                 displayState = Display.STATE_OFF;
5523             } else {
5524                 Slog.wtf(TAG, "Unknown screen state (not mapped): " + displayState);
5525                 displayState = Display.STATE_UNKNOWN;
5526             }
5527         }
5528         // As of this point, displayState should be mapped to one of:
5529         //  - Display.STATE_ON,
5530         //  - Display.STATE_DOZE
5531         //  - Display.STATE_DOZE_SUSPEND
5532         //  - Display.STATE_OFF
5533         //  - Display.STATE_UNKNOWN
5534 
5535         int state;
5536         int overallBin = mScreenBrightnessBin;
5537         int externalUpdateFlag = 0;
5538         boolean shouldScheduleSync = false;
5539         final int numDisplay = mPerDisplayBatteryStats.length;
5540         if (display < 0 || display >= numDisplay) {
5541             Slog.wtf(TAG, "Unexpected note screen state for display " + display + " (only "
5542                     + mPerDisplayBatteryStats.length + " displays exist...)");
5543             return;
5544         }
5545         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
5546         final int oldDisplayState = displayStats.screenState;
5547 
5548         if (oldDisplayState == displayState) {
5549             // Nothing changed
5550             state = mScreenState;
5551         } else {
5552             displayStats.screenState = displayState;
5553 
5554             // Stop timer for previous display state.
5555             switch (oldDisplayState) {
5556                 case Display.STATE_ON:
5557                     displayStats.screenOnTimer.stopRunningLocked(elapsedRealtimeMs);
5558                     final int bin = displayStats.screenBrightnessBin;
5559                     if (bin >= 0) {
5560                         displayStats.screenBrightnessTimers[bin].stopRunningLocked(
5561                                 elapsedRealtimeMs);
5562                     }
5563                     overallBin = evaluateOverallScreenBrightnessBinLocked();
5564                     shouldScheduleSync = true;
5565                     break;
5566                 case Display.STATE_DOZE:
5567                     // Transition from doze to doze suspend can be ignored.
5568                     if (displayState == Display.STATE_DOZE_SUSPEND) break;
5569                     displayStats.screenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5570                     shouldScheduleSync = true;
5571                     break;
5572                 case Display.STATE_DOZE_SUSPEND:
5573                     // Transition from doze suspend to doze can be ignored.
5574                     if (displayState == Display.STATE_DOZE) break;
5575                     displayStats.screenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5576                     shouldScheduleSync = true;
5577                     break;
5578                 case Display.STATE_OFF: // fallthrough
5579                 case Display.STATE_UNKNOWN:
5580                     // Not tracked by timers.
5581                     break;
5582                 default:
5583                     Slog.wtf(TAG,
5584                             "Attempted to stop timer for unexpected display state " + display);
5585             }
5586 
5587             // Start timer for new display state.
5588             switch (displayState) {
5589                 case Display.STATE_ON:
5590                     displayStats.screenOnTimer.startRunningLocked(elapsedRealtimeMs);
5591                     final int bin = displayStats.screenBrightnessBin;
5592                     if (bin >= 0) {
5593                         displayStats.screenBrightnessTimers[bin].startRunningLocked(
5594                                 elapsedRealtimeMs);
5595                     }
5596                     overallBin = evaluateOverallScreenBrightnessBinLocked();
5597                     shouldScheduleSync = true;
5598                     break;
5599                 case Display.STATE_DOZE:
5600                     // Transition from doze suspend to doze can be ignored.
5601                     if (oldDisplayState == Display.STATE_DOZE_SUSPEND) break;
5602                     displayStats.screenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5603                     shouldScheduleSync = true;
5604                     break;
5605                 case Display.STATE_DOZE_SUSPEND:
5606                     // Transition from doze to doze suspend can be ignored.
5607                     if (oldDisplayState == Display.STATE_DOZE) break;
5608                     displayStats.screenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5609                     shouldScheduleSync = true;
5610                     break;
5611                 case Display.STATE_OFF: // fallthrough
5612                 case Display.STATE_UNKNOWN:
5613                     // Not tracked by timers.
5614                     break;
5615                 default:
5616                     Slog.wtf(TAG,
5617                             "Attempted to start timer for unexpected display state " + displayState
5618                                     + " for display " + display);
5619             }
5620 
5621             if (shouldScheduleSync
5622                     && mGlobalEnergyConsumerStats != null
5623                     && mGlobalEnergyConsumerStats.isStandardBucketSupported(
5624                     EnergyConsumerStats.POWER_BUCKET_SCREEN_ON)) {
5625                 // Display energy consumption stats is available. Prepare to schedule an
5626                 // external sync.
5627                 externalUpdateFlag |= ExternalStatsSync.UPDATE_DISPLAY;
5628             }
5629 
5630             // Reevaluate most important display screen state.
5631             state = Display.STATE_UNKNOWN;
5632             for (int i = 0; i < numDisplay; i++) {
5633                 final int tempState = mPerDisplayBatteryStats[i].screenState;
5634                 if (tempState == Display.STATE_ON
5635                         || state == Display.STATE_ON) {
5636                     state = Display.STATE_ON;
5637                 } else if (tempState == Display.STATE_DOZE
5638                         || state == Display.STATE_DOZE) {
5639                     state = Display.STATE_DOZE;
5640                 } else if (tempState == Display.STATE_DOZE_SUSPEND
5641                         || state == Display.STATE_DOZE_SUSPEND) {
5642                     state = Display.STATE_DOZE_SUSPEND;
5643                 } else if (tempState == Display.STATE_OFF
5644                         || state == Display.STATE_OFF) {
5645                     state = Display.STATE_OFF;
5646                 }
5647             }
5648         }
5649 
5650         final boolean batteryRunning = mOnBatteryTimeBase.isRunning();
5651         final boolean batteryScreenOffRunning = mOnBatteryScreenOffTimeBase.isRunning();
5652 
5653         state = mPretendScreenOff ? Display.STATE_OFF : state;
5654         if (mScreenState != state) {
5655             recordDailyStatsIfNeededLocked(true, currentTimeMs);
5656             final int oldState = mScreenState;
5657             mScreenState = state;
5658             if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
5659                     + ", newState=" + Display.stateToString(state));
5660 
5661             if (state != Display.STATE_UNKNOWN) {
5662                 int stepState = state-1;
5663                 if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
5664                     mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
5665                     mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
5666                 } else {
5667                     Slog.wtf(TAG, "Unexpected screen state: " + state);
5668                 }
5669             }
5670 
5671             int startStates = 0;
5672             int stopStates = 0;
5673             if (Display.isDozeState(state) && !Display.isDozeState(oldState)) {
5674                 startStates |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
5675                 mScreenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5676             } else if (Display.isDozeState(oldState) && !Display.isDozeState(state)) {
5677                 stopStates |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
5678                 mScreenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5679             }
5680             if (Display.isOnState(state)) {
5681                 startStates |= HistoryItem.STATE_SCREEN_ON_FLAG;
5682                 mScreenOnTimer.startRunningLocked(elapsedRealtimeMs);
5683                 if (mScreenBrightnessBin >= 0) {
5684                     mScreenBrightnessTimer[mScreenBrightnessBin]
5685                             .startRunningLocked(elapsedRealtimeMs);
5686                 }
5687             } else if (Display.isOnState(oldState)) {
5688                 stopStates |= HistoryItem.STATE_SCREEN_ON_FLAG;
5689                 mScreenOnTimer.stopRunningLocked(elapsedRealtimeMs);
5690                 if (mScreenBrightnessBin >= 0) {
5691                     mScreenBrightnessTimer[mScreenBrightnessBin]
5692                             .stopRunningLocked(elapsedRealtimeMs);
5693                 }
5694             }
5695             if (startStates != 0 || stopStates != 0) {
5696                 mHistory.recordStateChangeEvent(elapsedRealtimeMs, uptimeMs, startStates,
5697                         stopStates);
5698             }
5699 
5700             // Per screen state Cpu stats needed. Prepare to schedule an external sync.
5701             externalUpdateFlag |= ExternalStatsSync.UPDATE_CPU;
5702             shouldScheduleSync = true;
5703 
5704             if (Display.isOnState(state)) {
5705                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
5706                         uptimeMs * 1000, elapsedRealtimeMs * 1000);
5707                 // Fake a wake lock, so we consider the device waked as long as the screen is on.
5708                 noteStartWakeLocked(-1, -1, null, "screen", null, WAKE_TYPE_PARTIAL, false,
5709                         elapsedRealtimeMs, uptimeMs);
5710             } else if (Display.isOnState(oldState)) {
5711                 noteStopWakeLocked(-1, -1, null, "screen", "screen", WAKE_TYPE_PARTIAL,
5712                         elapsedRealtimeMs, uptimeMs);
5713                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
5714                         uptimeMs * 1000, elapsedRealtimeMs * 1000);
5715             }
5716             // Update discharge amounts.
5717             if (mOnBatteryInternal) {
5718                 updateDischargeScreenLevelsLocked(oldState, state);
5719             }
5720         }
5721 
5722         // Changing display states might have changed the screen used to determine the overall
5723         // brightness.
5724         maybeUpdateOverallScreenBrightness(overallBin, elapsedRealtimeMs, uptimeMs);
5725 
5726         if (shouldScheduleSync) {
5727             final int numDisplays = mPerDisplayBatteryStats.length;
5728             final int[] displayStates = new int[numDisplays];
5729             for (int i = 0; i < numDisplays; i++) {
5730                 displayStates[i] = mPerDisplayBatteryStats[i].screenState;
5731             }
5732             mExternalSync.scheduleSyncDueToScreenStateChange(externalUpdateFlag,
5733                     batteryRunning, batteryScreenOffRunning, state, displayStates);
5734         }
5735     }
5736 
5737     /**
5738      * Note screen brightness change for a display.
5739      */
5740     @GuardedBy("this")
noteScreenBrightnessLocked(int display, int brightness)5741     public void noteScreenBrightnessLocked(int display, int brightness) {
5742         noteScreenBrightnessLocked(display, brightness, mClock.elapsedRealtime(),
5743                 mClock.uptimeMillis());
5744     }
5745 
5746 
5747     /**
5748      * Note screen brightness change for a display.
5749      */
5750     @GuardedBy("this")
noteScreenBrightnessLocked(int display, int brightness, long elapsedRealtimeMs, long uptimeMs)5751     public void noteScreenBrightnessLocked(int display, int brightness, long elapsedRealtimeMs,
5752             long uptimeMs) {
5753         // Bin the brightness.
5754         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
5755         if (bin < 0) bin = 0;
5756         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
5757 
5758         final int overallBin;
5759 
5760         final int numDisplays = mPerDisplayBatteryStats.length;
5761         if (display < 0 || display >= numDisplays) {
5762             Slog.wtf(TAG, "Unexpected note screen brightness for display " + display + " (only "
5763                     + mPerDisplayBatteryStats.length + " displays exist...)");
5764             return;
5765         }
5766 
5767         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
5768         final int oldBin = displayStats.screenBrightnessBin;
5769         if (oldBin == bin) {
5770             // Nothing changed
5771             overallBin = mScreenBrightnessBin;
5772         } else {
5773             displayStats.screenBrightnessBin = bin;
5774             if (displayStats.screenState == Display.STATE_ON) {
5775                 if (oldBin >= 0) {
5776                     displayStats.screenBrightnessTimers[oldBin].stopRunningLocked(
5777                             elapsedRealtimeMs);
5778                 }
5779                 displayStats.screenBrightnessTimers[bin].startRunningLocked(
5780                         elapsedRealtimeMs);
5781             }
5782             overallBin = evaluateOverallScreenBrightnessBinLocked();
5783         }
5784 
5785         maybeUpdateOverallScreenBrightness(overallBin, elapsedRealtimeMs, uptimeMs);
5786     }
5787 
5788     @GuardedBy("this")
evaluateOverallScreenBrightnessBinLocked()5789     private int evaluateOverallScreenBrightnessBinLocked() {
5790         int overallBin = -1;
5791         final int numDisplays = getDisplayCount();
5792         for (int display = 0; display < numDisplays; display++) {
5793             final int displayBrightnessBin;
5794             if (mPerDisplayBatteryStats[display].screenState == Display.STATE_ON) {
5795                 displayBrightnessBin = mPerDisplayBatteryStats[display].screenBrightnessBin;
5796             } else {
5797                 displayBrightnessBin = -1;
5798             }
5799             if (displayBrightnessBin > overallBin) {
5800                 overallBin = displayBrightnessBin;
5801             }
5802         }
5803         return overallBin;
5804     }
5805 
5806     @GuardedBy("this")
maybeUpdateOverallScreenBrightness(int overallBin, long elapsedRealtimeMs, long uptimeMs)5807     private void maybeUpdateOverallScreenBrightness(int overallBin, long elapsedRealtimeMs,
5808             long uptimeMs) {
5809         if (mScreenBrightnessBin != overallBin) {
5810             if (overallBin >= 0) {
5811                 mHistory.recordScreenBrightnessEvent(elapsedRealtimeMs, uptimeMs, overallBin);
5812             }
5813             if (mScreenState == Display.STATE_ON) {
5814                 if (mScreenBrightnessBin >= 0) {
5815                     mScreenBrightnessTimer[mScreenBrightnessBin]
5816                             .stopRunningLocked(elapsedRealtimeMs);
5817                 }
5818                 if (overallBin >= 0) {
5819                     mScreenBrightnessTimer[overallBin]
5820                             .startRunningLocked(elapsedRealtimeMs);
5821                 }
5822             }
5823             mScreenBrightnessBin = overallBin;
5824         }
5825     }
5826 
5827     @GuardedBy("this")
noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event, long elapsedRealtimeMs, long uptimeMs)5828     public void noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event,
5829             long elapsedRealtimeMs, long uptimeMs) {
5830         if (mOnBatteryInternal) {
5831             uid = mapUid(uid);
5832             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteUserActivityLocked(event);
5833         }
5834     }
5835 
5836     @GuardedBy("this")
noteWakeUpLocked(String reason, int reasonUid, long elapsedRealtimeMs, long uptimeMs)5837     public void noteWakeUpLocked(String reason, int reasonUid,
5838             long elapsedRealtimeMs, long uptimeMs) {
5839         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP, reason,
5840                 reasonUid);
5841     }
5842 
5843     @GuardedBy("this")
noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs)5844     public void noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs) {
5845         if (mInteractive != interactive) {
5846             mInteractive = interactive;
5847             if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
5848             if (interactive) {
5849                 mInteractiveTimer.startRunningLocked(elapsedRealtimeMs);
5850             } else {
5851                 mInteractiveTimer.stopRunningLocked(elapsedRealtimeMs);
5852             }
5853         }
5854     }
5855 
5856     @GuardedBy("this")
noteConnectivityChangedLocked(int type, String extra, long elapsedRealtimeMs, long uptimeMs)5857     public void noteConnectivityChangedLocked(int type, String extra,
5858             long elapsedRealtimeMs, long uptimeMs) {
5859         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
5860                 extra, type);
5861         mNumConnectivityChange++;
5862     }
5863 
5864     @GuardedBy("this")
noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)5865     private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
5866             final long uptimeMillis, int uid) {
5867         uid = mapUid(uid);
5868         mHistory.recordEvent(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
5869                 uid);
5870         getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteMobileRadioApWakeupLocked();
5871     }
5872 
5873     /**
5874      * Updates the radio power state and returns true if an external stats collection should occur.
5875      */
5876     @GuardedBy("this")
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid)5877     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
5878         return noteMobileRadioPowerStateLocked(powerState, timestampNs, uid,
5879                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5880     }
5881 
5882     @GuardedBy("this")
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid, long elapsedRealtimeMs, long uptimeMs)5883     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid,
5884             long elapsedRealtimeMs, long uptimeMs) {
5885         if (mMobileRadioPowerState != powerState) {
5886             long realElapsedRealtimeMs;
5887             final boolean active = isActiveRadioPowerState(powerState);
5888             if (active) {
5889                 if (uid > 0) {
5890                     noteMobileRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
5891                 }
5892 
5893                 mMobileRadioActiveStartTimeMs = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
5894                 mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
5895                         HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG);
5896             } else {
5897                 realElapsedRealtimeMs = timestampNs / (1000*1000);
5898                 long lastUpdateTimeMs = mMobileRadioActiveStartTimeMs;
5899                 if (realElapsedRealtimeMs < lastUpdateTimeMs) {
5900                     Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
5901                             + " is before start time " + lastUpdateTimeMs);
5902                     realElapsedRealtimeMs = elapsedRealtimeMs;
5903                 } else if (realElapsedRealtimeMs < elapsedRealtimeMs) {
5904                     mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtimeMs
5905                             - realElapsedRealtimeMs);
5906                 }
5907                 mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
5908                         HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG);
5909             }
5910             mMobileRadioPowerState = powerState;
5911 
5912             // Inform current RatBatteryStats that the modem active state might have changed.
5913             getRatBatteryStatsLocked(mActiveRat).noteActive(active, elapsedRealtimeMs);
5914 
5915             if (active) {
5916                 mMobileRadioActiveTimer.startRunningLocked(elapsedRealtimeMs);
5917                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtimeMs);
5918             } else {
5919                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
5920                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
5921 
5922                 if (mMobileRadioPowerStatsCollector.isEnabled()) {
5923                     mMobileRadioPowerStatsCollector.schedule();
5924                 } else {
5925                     // Check if modem Activity info has been collected recently, don't bother
5926                     // triggering another update.
5927                     if (mLastModemActivityInfo == null
5928                             || elapsedRealtimeMs >= mLastModemActivityInfo.getTimestampMillis()
5929                             + MOBILE_RADIO_POWER_STATE_UPDATE_FREQ_MS) {
5930                         mExternalSync.scheduleSync("modem-data",
5931                                 BatteryExternalStatsWorker.UPDATE_RADIO);
5932                         return true;
5933                     }
5934                 }
5935             }
5936         }
5937         return false;
5938     }
5939 
isActiveRadioPowerState(int powerState)5940     private static boolean isActiveRadioPowerState(int powerState) {
5941         return powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
5942                 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
5943     }
5944 
5945     /**
5946      * Toggles the power save mode state.
5947      */
5948     @GuardedBy("this")
notePowerSaveModeLockedInit(boolean enabled, long elapsedRealtimeMs, long uptimeMs)5949     public void notePowerSaveModeLockedInit(boolean enabled, long elapsedRealtimeMs,
5950             long uptimeMs) {
5951         if (mPowerSaveModeEnabled != enabled) {
5952             notePowerSaveModeLocked(enabled, elapsedRealtimeMs, uptimeMs);
5953         } else {
5954             // Log an initial value for BATTERY_SAVER_MODE_STATE_CHANGED in order to
5955             // allow the atom to read all future state changes.
5956             mFrameworkStatsLogger.batterySaverModeChanged(enabled);
5957         }
5958     }
5959 
5960     @GuardedBy("this")
notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs)5961     public void notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs) {
5962         if (mPowerSaveModeEnabled != enabled) {
5963             int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
5964             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
5965             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
5966             mPowerSaveModeEnabled = enabled;
5967             if (enabled) {
5968                 mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
5969                         HistoryItem.STATE2_POWER_SAVE_FLAG);
5970                 mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtimeMs);
5971             } else {
5972                 mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
5973                         HistoryItem.STATE2_POWER_SAVE_FLAG);
5974                 mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtimeMs);
5975             }
5976             mFrameworkStatsLogger.batterySaverModeChanged(enabled);
5977         }
5978     }
5979 
5980     @GuardedBy("this")
noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid, long elapsedRealtimeMs, long uptimeMs)5981     public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid,
5982             long elapsedRealtimeMs, long uptimeMs) {
5983         boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
5984         if (mDeviceIdling && !nowIdling && activeReason == null) {
5985             // We don't go out of general idling mode until explicitly taken out of
5986             // device idle through going active or significant motion.
5987             nowIdling = true;
5988         }
5989         boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
5990         if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
5991             // We don't go out of general light idling mode until explicitly taken out of
5992             // device idle through going active or significant motion.
5993             nowLightIdling = true;
5994         }
5995         if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
5996             mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE,
5997                     activeReason, activeUid);
5998         }
5999         if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
6000             int statsmode;
6001             if (nowIdling)           statsmode = DEVICE_IDLE_MODE_DEEP;
6002             else if (nowLightIdling) statsmode = DEVICE_IDLE_MODE_LIGHT;
6003             else                     statsmode = DEVICE_IDLE_MODE_OFF;
6004             mFrameworkStatsLogger.deviceIdlingModeStateChanged(statsmode);
6005         }
6006         if (mDeviceIdling != nowIdling) {
6007             mDeviceIdling = nowIdling;
6008             int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
6009             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
6010             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
6011             if (nowIdling) {
6012                 mDeviceIdlingTimer.startRunningLocked(elapsedRealtimeMs);
6013             } else {
6014                 mDeviceIdlingTimer.stopRunningLocked(elapsedRealtimeMs);
6015             }
6016         }
6017         if (mDeviceLightIdling != nowLightIdling) {
6018             mDeviceLightIdling = nowLightIdling;
6019             if (nowLightIdling) {
6020                 mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtimeMs);
6021             } else {
6022                 mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtimeMs);
6023             }
6024         }
6025         if (mDeviceIdleMode != mode) {
6026             mHistory.recordDeviceIdleEvent(elapsedRealtimeMs, uptimeMs, mode);
6027             long lastDuration = elapsedRealtimeMs - mLastIdleTimeStartMs;
6028             mLastIdleTimeStartMs = elapsedRealtimeMs;
6029             if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
6030                 if (lastDuration > mLongestLightIdleTimeMs) {
6031                     mLongestLightIdleTimeMs = lastDuration;
6032                 }
6033                 mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtimeMs);
6034             } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
6035                 if (lastDuration > mLongestFullIdleTimeMs) {
6036                     mLongestFullIdleTimeMs = lastDuration;
6037                 }
6038                 mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtimeMs);
6039             }
6040             if (mode == DEVICE_IDLE_MODE_LIGHT) {
6041                 mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtimeMs);
6042             } else if (mode == DEVICE_IDLE_MODE_DEEP) {
6043                 mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtimeMs);
6044             }
6045             mDeviceIdleMode = mode;
6046             mFrameworkStatsLogger.deviceIdleModeStateChanged(mode);
6047         }
6048     }
6049 
6050     @GuardedBy("this")
notePackageInstalledLocked(String pkgName, long versionCode, long elapsedRealtimeMs, long uptimeMs)6051     public void notePackageInstalledLocked(String pkgName, long versionCode,
6052             long elapsedRealtimeMs, long uptimeMs) {
6053         // XXX need to figure out what to do with long version codes.
6054         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED,
6055                 pkgName, (int)versionCode);
6056         PackageChange pc = new PackageChange();
6057         pc.mPackageName = pkgName;
6058         pc.mUpdate = true;
6059         pc.mVersionCode = versionCode;
6060         addPackageChange(pc);
6061     }
6062 
6063     @GuardedBy("this")
notePackageUninstalledLocked(String pkgName, long elapsedRealtimeMs, long uptimeMs)6064     public void notePackageUninstalledLocked(String pkgName,
6065             long elapsedRealtimeMs, long uptimeMs) {
6066         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
6067                 pkgName, 0);
6068         PackageChange pc = new PackageChange();
6069         pc.mPackageName = pkgName;
6070         pc.mUpdate = true;
6071         addPackageChange(pc);
6072     }
6073 
addPackageChange(PackageChange pc)6074     private void addPackageChange(PackageChange pc) {
6075         if (mDailyPackageChanges == null) {
6076             mDailyPackageChanges = new ArrayList<>();
6077         }
6078         mDailyPackageChanges.add(pc);
6079     }
6080 
6081     @GuardedBy("this")
stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs)6082     void stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs) {
6083         for (int i = 0; i < mGpsSignalQualityTimer.length; i++) {
6084             if (i == except) {
6085                 continue;
6086             }
6087             while (mGpsSignalQualityTimer[i].isRunningLocked()) {
6088                 mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtimeMs);
6089             }
6090         }
6091     }
6092 
6093     @GuardedBy("this")
notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs)6094     public void notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs) {
6095         if (!mPhoneOn) {
6096             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6097                     HistoryItem.STATE2_PHONE_IN_CALL_FLAG);
6098             mPhoneOn = true;
6099             mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs);
6100             if (mConstants.PHONE_ON_EXTERNAL_STATS_COLLECTION) {
6101                 scheduleSyncExternalStatsLocked("phone-on", ExternalStatsSync.UPDATE_RADIO);
6102                 mMobileRadioPowerStatsCollector.schedule();
6103             }
6104         }
6105     }
6106 
6107     @GuardedBy("this")
notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs)6108     public void notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs) {
6109         if (mPhoneOn) {
6110             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6111                     HistoryItem.STATE2_PHONE_IN_CALL_FLAG);
6112             mPhoneOn = false;
6113             mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs);
6114             scheduleSyncExternalStatsLocked("phone-off", ExternalStatsSync.UPDATE_RADIO);
6115             mMobileRadioPowerStatsCollector.schedule();
6116         }
6117     }
6118 
6119     @GuardedBy("this")
registerUsbStateReceiver(Context context)6120     private void registerUsbStateReceiver(Context context) {
6121         final IntentFilter usbStateFilter = new IntentFilter();
6122         usbStateFilter.addAction(UsbManager.ACTION_USB_STATE);
6123         context.registerReceiver(new BroadcastReceiver() {
6124             @Override
6125             public void onReceive(Context context, Intent intent) {
6126                 final boolean state = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
6127                 synchronized (BatteryStatsImpl.this) {
6128                     noteUsbConnectionStateLocked(state, mClock.elapsedRealtime(),
6129                             mClock.uptimeMillis());
6130                 }
6131             }
6132         }, usbStateFilter);
6133         synchronized (this) {
6134             if (mUsbDataState == USB_DATA_UNKNOWN) {
6135                 final Intent usbState = context.registerReceiver(null, usbStateFilter);
6136                 final boolean initState = usbState != null && usbState.getBooleanExtra(
6137                         UsbManager.USB_CONNECTED, false);
6138                 noteUsbConnectionStateLocked(initState, mClock.elapsedRealtime(),
6139                         mClock.uptimeMillis());
6140             }
6141         }
6142     }
6143 
6144     @GuardedBy("this")
noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs, long uptimeMs)6145     private void noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs,
6146             long uptimeMs) {
6147         int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED;
6148         if (mUsbDataState != newState) {
6149             mUsbDataState = newState;
6150             if (connected) {
6151                 mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6152                         HistoryItem.STATE2_USB_DATA_LINK_FLAG);
6153             } else {
6154                 mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6155                         HistoryItem.STATE2_USB_DATA_LINK_FLAG);
6156             }
6157         }
6158     }
6159 
6160     @GuardedBy("this")
stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs)6161     void stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
6162         for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
6163             if (i == except) {
6164                 continue;
6165             }
6166             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
6167                 mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs);
6168             }
6169         }
6170     }
6171 
6172     @GuardedBy("this")
updateAllPhoneStateLocked(int state, int simState, int strengthBin, long elapsedRealtimeMs, long uptimeMs)6173     private void updateAllPhoneStateLocked(int state, int simState, int strengthBin,
6174             long elapsedRealtimeMs, long uptimeMs) {
6175         boolean scanning = false;
6176         boolean newHistory = false;
6177         int addStateFlag = 0;
6178         int removeStateFlag = 0;
6179         int newState = -1;
6180         int newSignalStrength = -1;
6181 
6182         mPhoneServiceStateRaw = state;
6183         mPhoneSimStateRaw = simState;
6184         mPhoneSignalStrengthBinRaw = strengthBin;
6185 
6186         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
6187             // In this case we will always be STATE_OUT_OF_SERVICE, so need
6188             // to infer that we are scanning from other data.
6189             if (state == ServiceState.STATE_OUT_OF_SERVICE
6190                     && strengthBin > CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
6191                 state = ServiceState.STATE_IN_SERVICE;
6192             }
6193         }
6194 
6195         // If the phone is powered off, stop all timers.
6196         if (state == ServiceState.STATE_POWER_OFF) {
6197             strengthBin = -1;
6198 
6199         // If we are in service, make sure the correct signal string timer is running.
6200         } else if (state == ServiceState.STATE_IN_SERVICE) {
6201             // Bin will be changed below.
6202 
6203         // If we're out of service, we are in the lowest signal strength
6204         // bin and have the scanning bit set.
6205         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
6206             scanning = true;
6207             strengthBin = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
6208             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
6209                 addStateFlag = HistoryItem.STATE_PHONE_SCANNING_FLAG;
6210                 newHistory = true;
6211                 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtimeMs);
6212                 mFrameworkStatsLogger.phoneServiceStateChanged(state, simState, strengthBin);
6213             }
6214         }
6215 
6216         if (!scanning) {
6217             // If we are no longer scanning, then stop the scanning timer.
6218             if (mPhoneSignalScanningTimer.isRunningLocked()) {
6219                 removeStateFlag = HistoryItem.STATE_PHONE_SCANNING_FLAG;
6220                 newHistory = true;
6221                 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtimeMs);
6222                 mFrameworkStatsLogger.phoneServiceStateChanged(state, simState, strengthBin);
6223             }
6224         }
6225 
6226         if (mPhoneServiceState != state) {
6227             newState = state;
6228             newHistory = true;
6229             mPhoneServiceState = state;
6230         }
6231 
6232         if (mPhoneSignalStrengthBin != strengthBin) {
6233             if (mPhoneSignalStrengthBin >= 0) {
6234                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
6235                         elapsedRealtimeMs);
6236             }
6237             if (strengthBin >= 0) {
6238                 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
6239                     mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
6240                 }
6241                 newSignalStrength = strengthBin;
6242                 newHistory = true;
6243                 mFrameworkStatsLogger.phoneSignalStrengthChanged(strengthBin);
6244             } else {
6245                 stopAllPhoneSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
6246             }
6247             mPhoneSignalStrengthBin = strengthBin;
6248         }
6249 
6250         if (newHistory) {
6251             mHistory.recordPhoneStateChangeEvent(elapsedRealtimeMs, uptimeMs,
6252                     addStateFlag, removeStateFlag, newState, newSignalStrength);
6253         }
6254     }
6255 
6256     @GuardedBy("this")
notePhoneStateLocked(int state, int simState, long elapsedRealtimeMs, long uptimeMs)6257     public void notePhoneStateLocked(int state, int simState,
6258             long elapsedRealtimeMs, long uptimeMs) {
6259         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw,
6260                 elapsedRealtimeMs, uptimeMs);
6261     }
6262 
6263     @GuardedBy("this")
notePhoneSignalStrengthLocked(SignalStrength signalStrength, long elapsedRealtimeMs, long uptimeMs)6264     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength,
6265             long elapsedRealtimeMs, long uptimeMs) {
6266         final int overallSignalStrength = signalStrength.getLevel();
6267         final SparseIntArray perRatSignalStrength = new SparseIntArray(
6268                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT);
6269 
6270         // Extract signal strength level for each RAT.
6271         final List<CellSignalStrength> cellSignalStrengths =
6272                 signalStrength.getCellSignalStrengths();
6273         final int size = cellSignalStrengths.size();
6274         for (int i = 0; i < size; i++) {
6275             CellSignalStrength cellSignalStrength = cellSignalStrengths.get(i);
6276             // Map each CellSignalStrength to a BatteryStats.RadioAccessTechnology
6277             final int ratType;
6278             final int level;
6279             if (cellSignalStrength instanceof CellSignalStrengthNr) {
6280                 ratType = RADIO_ACCESS_TECHNOLOGY_NR;
6281                 level = cellSignalStrength.getLevel();
6282             } else if (cellSignalStrength instanceof CellSignalStrengthLte) {
6283                 ratType = RADIO_ACCESS_TECHNOLOGY_LTE;
6284                 level = cellSignalStrength.getLevel();
6285             } else {
6286                 ratType = RADIO_ACCESS_TECHNOLOGY_OTHER;
6287                 level = cellSignalStrength.getLevel();
6288             }
6289 
6290             // According to SignalStrength#getCellSignalStrengths(), multiple of the same
6291             // cellSignalStrength can be present. Just take the highest level one for each RAT.
6292             if (perRatSignalStrength.get(ratType, -1) < level) {
6293                 perRatSignalStrength.put(ratType, level);
6294             }
6295         }
6296 
6297         notePhoneSignalStrengthLocked(overallSignalStrength, perRatSignalStrength,
6298                 elapsedRealtimeMs, uptimeMs);
6299     }
6300 
6301     /**
6302      * Note phone signal strength change, including per RAT signal strength.
6303      *
6304      * @param signalStrength overall signal strength {@see SignalStrength#getLevel()}
6305      * @param perRatSignalStrength signal strength of available RATs
6306      */
6307     @GuardedBy("this")
notePhoneSignalStrengthLocked(int signalStrength, SparseIntArray perRatSignalStrength)6308     public void notePhoneSignalStrengthLocked(int signalStrength,
6309             SparseIntArray perRatSignalStrength) {
6310         notePhoneSignalStrengthLocked(signalStrength, perRatSignalStrength,
6311                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6312     }
6313 
6314     /**
6315      * Note phone signal strength change, including per RAT signal strength.
6316      *
6317      * @param signalStrength overall signal strength {@see SignalStrength#getLevel()}
6318      * @param perRatSignalStrength signal strength of available RATs
6319      */
6320     @GuardedBy("this")
notePhoneSignalStrengthLocked(int signalStrength, SparseIntArray perRatSignalStrength, long elapsedRealtimeMs, long uptimeMs)6321     public void notePhoneSignalStrengthLocked(int signalStrength,
6322             SparseIntArray perRatSignalStrength,
6323             long elapsedRealtimeMs, long uptimeMs) {
6324         // Note each RAT's signal strength.
6325         final int size = perRatSignalStrength.size();
6326         for (int i = 0; i < size; i++) {
6327             final int rat = perRatSignalStrength.keyAt(i);
6328             final int ratSignalStrength = perRatSignalStrength.valueAt(i);
6329             getRatBatteryStatsLocked(rat).noteSignalStrength(ratSignalStrength, elapsedRealtimeMs);
6330         }
6331         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, signalStrength,
6332                 elapsedRealtimeMs, uptimeMs);
6333     }
6334 
6335     @GuardedBy("this")
notePhoneDataConnectionStateLocked(@etworkType int dataType, boolean hasData, @RegState int serviceType, @NetworkRegistrationInfo.NRState int nrState, @ServiceState.FrequencyRange int nrFrequency)6336     public void notePhoneDataConnectionStateLocked(@NetworkType int dataType, boolean hasData,
6337             @RegState int serviceType, @NetworkRegistrationInfo.NRState int nrState,
6338             @ServiceState.FrequencyRange int nrFrequency) {
6339         notePhoneDataConnectionStateLocked(dataType, hasData, serviceType, nrState, nrFrequency,
6340                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6341     }
6342 
6343     @GuardedBy("this")
notePhoneDataConnectionStateLocked(@etworkType int dataType, boolean hasData, @RegState int serviceType, @NetworkRegistrationInfo.NRState int nrState, @ServiceState.FrequencyRange int nrFrequency, long elapsedRealtimeMs, long uptimeMs)6344     public void notePhoneDataConnectionStateLocked(@NetworkType int dataType, boolean hasData,
6345             @RegState int serviceType, @NetworkRegistrationInfo.NRState int nrState,
6346             @ServiceState.FrequencyRange int nrFrequency, long elapsedRealtimeMs, long uptimeMs) {
6347         // BatteryStats uses 0 to represent no network type.
6348         // Telephony does not have a concept of no network type, and uses 0 to represent unknown.
6349         // Unknown is included in DATA_CONNECTION_OTHER.
6350         int bin = DATA_CONNECTION_OUT_OF_SERVICE;
6351         if (hasData) {
6352             if (dataType > 0 && dataType <= NUM_ALL_NETWORK_TYPES) {
6353                 bin = dataType;
6354             } else {
6355                 switch (serviceType) {
6356                     case ServiceState.STATE_OUT_OF_SERVICE:
6357                         bin = DATA_CONNECTION_OUT_OF_SERVICE;
6358                         break;
6359                     case ServiceState.STATE_EMERGENCY_ONLY:
6360                         bin = DATA_CONNECTION_EMERGENCY_SERVICE;
6361                         break;
6362                     default:
6363                         bin = DATA_CONNECTION_OTHER;
6364                         break;
6365                 }
6366             }
6367         }
6368 
6369 
6370 
6371         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
6372         if (mPhoneDataConnectionType != bin) {
6373             mHistory.recordDataConnectionTypeChangeEvent(elapsedRealtimeMs, uptimeMs, bin);
6374             if (mPhoneDataConnectionType >= 0) {
6375                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
6376                         elapsedRealtimeMs);
6377             }
6378             mPhoneDataConnectionType = bin;
6379             mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtimeMs);
6380         }
6381 
6382         if (mNrState != nrState) {
6383             mHistory.recordNrStateChangeEvent(elapsedRealtimeMs, uptimeMs, nrState);
6384             mNrState = nrState;
6385         }
6386 
6387         final boolean newNrNsaActive = isNrNsa(bin, nrState);
6388         final boolean nrNsaActive = mNrNsaTimer.isRunningLocked();
6389         if (newNrNsaActive != nrNsaActive) {
6390             if (newNrNsaActive) {
6391                 mNrNsaTimer.startRunningLocked(elapsedRealtimeMs);
6392             } else {
6393                 mNrNsaTimer.stopRunningLocked(elapsedRealtimeMs);
6394             }
6395         }
6396 
6397         final int newRat = mapNetworkTypeToRadioAccessTechnology(bin, nrState);
6398         if (newRat == RADIO_ACCESS_TECHNOLOGY_NR) {
6399             // Note possible frequency change for the NR RAT.
6400             getRatBatteryStatsLocked(newRat).noteFrequencyRange(nrFrequency, elapsedRealtimeMs);
6401         }
6402         if (mActiveRat != newRat) {
6403             getRatBatteryStatsLocked(mActiveRat).noteActive(false, elapsedRealtimeMs);
6404             mActiveRat = newRat;
6405         }
6406         final boolean modemActive = mMobileRadioActiveTimer.isRunningLocked();
6407         getRatBatteryStatsLocked(newRat).noteActive(modemActive, elapsedRealtimeMs);
6408     }
6409 
6410     /**
6411      * Non-standalone (NSA) mode for 5G NR will have an LTE network type. If NR state is
6412      * connected while on an LTE network, the device is in NR NSA mode.
6413      */
isNrNsa(@etworkType int dataType, @NetworkRegistrationInfo.NRState int nrState)6414     private static boolean isNrNsa(@NetworkType int dataType,
6415             @NetworkRegistrationInfo.NRState int nrState) {
6416         return dataType == TelephonyManager.NETWORK_TYPE_LTE
6417                 && nrState == NetworkRegistrationInfo.NR_STATE_CONNECTED;
6418     }
6419 
6420     @RadioAccessTechnology
mapNetworkTypeToRadioAccessTechnology(@etworkType int dataType, @NetworkRegistrationInfo.NRState int nrState)6421     private static int mapNetworkTypeToRadioAccessTechnology(@NetworkType int dataType,
6422             @NetworkRegistrationInfo.NRState int nrState) {
6423         if (isNrNsa(dataType, nrState)) {
6424             // Treat an NR NSA connection as RADIO_ACCESS_TECHNOLOGY_NR
6425             return RADIO_ACCESS_TECHNOLOGY_NR;
6426         }
6427 
6428         switch (dataType) {
6429             case TelephonyManager.NETWORK_TYPE_NR:
6430                 return RADIO_ACCESS_TECHNOLOGY_NR;
6431             case TelephonyManager.NETWORK_TYPE_LTE:
6432                 return RADIO_ACCESS_TECHNOLOGY_LTE;
6433             case TelephonyManager.NETWORK_TYPE_UNKNOWN: //fallthrough
6434             case TelephonyManager.NETWORK_TYPE_GPRS: //fallthrough
6435             case TelephonyManager.NETWORK_TYPE_EDGE: //fallthrough
6436             case TelephonyManager.NETWORK_TYPE_UMTS: //fallthrough
6437             case TelephonyManager.NETWORK_TYPE_CDMA: //fallthrough
6438             case TelephonyManager.NETWORK_TYPE_EVDO_0: //fallthrough
6439             case TelephonyManager.NETWORK_TYPE_EVDO_A: //fallthrough
6440             case TelephonyManager.NETWORK_TYPE_1xRTT: //fallthrough
6441             case TelephonyManager.NETWORK_TYPE_HSDPA: //fallthrough
6442             case TelephonyManager.NETWORK_TYPE_HSUPA: //fallthrough
6443             case TelephonyManager.NETWORK_TYPE_HSPA: //fallthrough
6444             case TelephonyManager.NETWORK_TYPE_IDEN: //fallthrough
6445             case TelephonyManager.NETWORK_TYPE_EVDO_B: //fallthrough
6446             case TelephonyManager.NETWORK_TYPE_EHRPD: //fallthrough
6447             case TelephonyManager.NETWORK_TYPE_HSPAP: //fallthrough
6448             case TelephonyManager.NETWORK_TYPE_GSM: //fallthrough
6449             case TelephonyManager.NETWORK_TYPE_TD_SCDMA: //fallthrough
6450             case TelephonyManager.NETWORK_TYPE_IWLAN: //fallthrough
6451                 return RADIO_ACCESS_TECHNOLOGY_OTHER;
6452             default:
6453                 Slog.w(TAG, "Unhandled NetworkType (" + dataType + "), mapping to OTHER");
6454                 return RADIO_ACCESS_TECHNOLOGY_OTHER;
6455         }
6456     }
6457 
6458     @GuardedBy("this")
noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs)6459     public void noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs) {
6460         if (!mWifiOn) {
6461             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6462                     HistoryItem.STATE2_WIFI_ON_FLAG);
6463             mWifiOn = true;
6464             mWifiOnTimer.startRunningLocked(elapsedRealtimeMs);
6465             if (mWifiPowerStatsCollector.isEnabled()) {
6466                 mWifiPowerStatsCollector.schedule();
6467             } else {
6468                 scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
6469             }
6470         }
6471     }
6472 
6473     @GuardedBy("this")
noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs)6474     public void noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs) {
6475         if (mWifiOn) {
6476             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6477                     HistoryItem.STATE2_WIFI_ON_FLAG);
6478             mWifiOn = false;
6479             mWifiOnTimer.stopRunningLocked(elapsedRealtimeMs);
6480             if (mWifiPowerStatsCollector.isEnabled()) {
6481                 mWifiPowerStatsCollector.schedule();
6482             } else {
6483                 scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
6484             }
6485         }
6486     }
6487 
6488     @GuardedBy("this")
noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6489     public void noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6490         uid = mapUid(uid);
6491         if (mAudioOnNesting == 0) {
6492             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
6493                     HistoryItem.STATE_AUDIO_ON_FLAG, uid, "audio");
6494             mAudioOnTimer.startRunningLocked(elapsedRealtimeMs);
6495         }
6496         mAudioOnNesting++;
6497         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_AUDIO)) {
6498             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6499                     .noteAudioTurnedOnLocked(elapsedRealtimeMs);
6500         }
6501     }
6502 
6503     @GuardedBy("this")
noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6504     public void noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6505         if (mAudioOnNesting == 0) {
6506             return;
6507         }
6508         uid = mapUid(uid);
6509         if (--mAudioOnNesting == 0) {
6510             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
6511                     HistoryItem.STATE_AUDIO_ON_FLAG, uid, "audio");
6512             mAudioOnTimer.stopRunningLocked(elapsedRealtimeMs);
6513         }
6514         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_AUDIO)) {
6515             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6516                     .noteAudioTurnedOffLocked(elapsedRealtimeMs);
6517         }
6518     }
6519 
6520     @GuardedBy("this")
noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6521     public void noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6522         uid = mapUid(uid);
6523         if (mVideoOnNesting == 0) {
6524             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6525                     HistoryItem.STATE2_VIDEO_ON_FLAG, uid, "video");
6526             mVideoOnTimer.startRunningLocked(elapsedRealtimeMs);
6527         }
6528         mVideoOnNesting++;
6529         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_VIDEO)) {
6530             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6531                     .noteVideoTurnedOnLocked(elapsedRealtimeMs);
6532         }
6533     }
6534 
6535     @GuardedBy("this")
noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6536     public void noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6537         if (mVideoOnNesting == 0) {
6538             return;
6539         }
6540         uid = mapUid(uid);
6541         if (--mVideoOnNesting == 0) {
6542             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6543                     HistoryItem.STATE2_VIDEO_ON_FLAG, uid, "video");
6544             mVideoOnTimer.stopRunningLocked(elapsedRealtimeMs);
6545         }
6546         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_VIDEO)) {
6547             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6548                     .noteVideoTurnedOffLocked(elapsedRealtimeMs);
6549         }
6550     }
6551 
6552     @GuardedBy("this")
noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs)6553     public void noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs) {
6554         if (mAudioOnNesting > 0) {
6555             mAudioOnNesting = 0;
6556             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
6557                     HistoryItem.STATE_AUDIO_ON_FLAG);
6558             mAudioOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6559             for (int i=0; i<mUidStats.size(); i++) {
6560                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6561                 uid.noteResetAudioLocked(elapsedRealtimeMs);
6562             }
6563         }
6564     }
6565 
6566     @GuardedBy("this")
noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs)6567     public void noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs) {
6568         if (mVideoOnNesting > 0) {
6569             mVideoOnNesting = 0;
6570             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6571                     HistoryItem.STATE2_VIDEO_ON_FLAG);
6572             mVideoOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6573             for (int i=0; i<mUidStats.size(); i++) {
6574                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6575                 uid.noteResetVideoLocked(elapsedRealtimeMs);
6576             }
6577         }
6578     }
6579 
6580     @GuardedBy("this")
noteActivityResumedLocked(int uid)6581     public void noteActivityResumedLocked(int uid) {
6582         noteActivityResumedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
6583     }
6584 
6585     @GuardedBy("this")
noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6586     public void noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6587         uid = mapUid(uid);
6588         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6589                 .noteActivityResumedLocked(elapsedRealtimeMs);
6590     }
6591 
6592     @GuardedBy("this")
noteActivityPausedLocked(int uid)6593     public void noteActivityPausedLocked(int uid) {
6594         noteActivityPausedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
6595     }
6596 
6597     @GuardedBy("this")
noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6598     public void noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6599         uid = mapUid(uid);
6600         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6601                 .noteActivityPausedLocked(elapsedRealtimeMs);
6602     }
6603 
6604     @GuardedBy("this")
noteVibratorOnLocked(int uid, long durationMillis, long elapsedRealtimeMs, long uptimeMs)6605     public void noteVibratorOnLocked(int uid, long durationMillis,
6606             long elapsedRealtimeMs, long uptimeMs) {
6607         uid = mapUid(uid);
6608         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6609                 .noteVibratorOnLocked(durationMillis, elapsedRealtimeMs);
6610     }
6611 
6612     @GuardedBy("this")
noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6613     public void noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6614         uid = mapUid(uid);
6615         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6616                 .noteVibratorOffLocked(elapsedRealtimeMs);
6617     }
6618 
6619     @GuardedBy("this")
noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6620     public void noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6621         uid = mapUid(uid);
6622         if (mFlashlightOnNesting++ == 0) {
6623             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6624                     HistoryItem.STATE2_FLASHLIGHT_FLAG, uid, "flashlight");
6625             mFlashlightOnTimer.startRunningLocked(elapsedRealtimeMs);
6626         }
6627         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT)) {
6628             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6629                     .noteFlashlightTurnedOnLocked(elapsedRealtimeMs);
6630         }
6631     }
6632 
6633     @GuardedBy("this")
noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6634     public void noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6635         if (mFlashlightOnNesting == 0) {
6636             return;
6637         }
6638         uid = mapUid(uid);
6639         if (--mFlashlightOnNesting == 0) {
6640             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6641                     HistoryItem.STATE2_FLASHLIGHT_FLAG, uid, "flashlight");
6642             mFlashlightOnTimer.stopRunningLocked(elapsedRealtimeMs);
6643         }
6644         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT)) {
6645             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6646                     .noteFlashlightTurnedOffLocked(elapsedRealtimeMs);
6647         }
6648     }
6649 
6650     @GuardedBy("this")
noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6651     public void noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6652         uid = mapUid(uid);
6653         if (mCameraOnNesting++ == 0) {
6654             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6655                     HistoryItem.STATE2_CAMERA_FLAG);
6656             mCameraOnTimer.startRunningLocked(elapsedRealtimeMs);
6657         }
6658         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6659                 .noteCameraTurnedOnLocked(elapsedRealtimeMs);
6660 
6661         scheduleSyncExternalStatsLocked("camera-on", ExternalStatsSync.UPDATE_CAMERA);
6662     }
6663 
6664     @GuardedBy("this")
noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6665     public void noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6666         if (mCameraOnNesting == 0) {
6667             return;
6668         }
6669         uid = mapUid(uid);
6670         if (--mCameraOnNesting == 0) {
6671             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6672                     HistoryItem.STATE2_CAMERA_FLAG);
6673             mCameraOnTimer.stopRunningLocked(elapsedRealtimeMs);
6674         }
6675         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6676                 .noteCameraTurnedOffLocked(elapsedRealtimeMs);
6677 
6678         scheduleSyncExternalStatsLocked("camera-off", ExternalStatsSync.UPDATE_CAMERA);
6679     }
6680 
6681     @GuardedBy("this")
noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs)6682     public void noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs) {
6683         if (mCameraOnNesting > 0) {
6684             mCameraOnNesting = 0;
6685             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6686                     HistoryItem.STATE2_CAMERA_FLAG);
6687             mCameraOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6688             for (int i=0; i<mUidStats.size(); i++) {
6689                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6690                 uid.noteResetCameraLocked(elapsedRealtimeMs);
6691             }
6692         }
6693 
6694         scheduleSyncExternalStatsLocked("camera-reset", ExternalStatsSync.UPDATE_CAMERA);
6695     }
6696 
6697     @GuardedBy("this")
noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs)6698     public void noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs) {
6699         if (mFlashlightOnNesting > 0) {
6700             mFlashlightOnNesting = 0;
6701             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6702                     HistoryItem.STATE2_FLASHLIGHT_FLAG);
6703             mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6704             for (int i=0; i<mUidStats.size(); i++) {
6705                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6706                 uid.noteResetFlashlightLocked(elapsedRealtimeMs);
6707             }
6708         }
6709     }
6710 
6711     @GuardedBy("this")
noteBluetoothScanStartedLocked(WorkChain workChain, int uid, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6712     private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
6713             boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
6714         if (workChain != null) {
6715             uid = workChain.getAttributionUid();
6716         }
6717         uid = mapUid(uid);
6718         if (mBluetoothScanNesting == 0) {
6719             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6720                     HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
6721             mBluetoothScanTimer.startRunningLocked(elapsedRealtimeMs);
6722         }
6723         mBluetoothScanNesting++;
6724         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6725                 .noteBluetoothScanStartedLocked(elapsedRealtimeMs, isUnoptimized);
6726     }
6727 
6728     @GuardedBy("this")
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized)6729     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
6730         noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized,
6731                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6732     }
6733 
6734     @GuardedBy("this")
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6735     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
6736             long elapsedRealtimeMs, long uptimeMs) {
6737         final int N = ws.size();
6738         for (int i = 0; i < N; i++) {
6739             noteBluetoothScanStartedLocked(null, ws.getUid(i), isUnoptimized,
6740                     elapsedRealtimeMs, uptimeMs);
6741         }
6742 
6743         final List<WorkChain> workChains = ws.getWorkChains();
6744         if (workChains != null) {
6745             for (int i = 0; i < workChains.size(); ++i) {
6746                 noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized,
6747                         elapsedRealtimeMs, uptimeMs);
6748             }
6749         }
6750     }
6751 
6752     @GuardedBy("this")
noteBluetoothScanStoppedLocked(WorkChain workChain, int uid, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6753     private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
6754             boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
6755         if (workChain != null) {
6756             uid = workChain.getAttributionUid();
6757         }
6758         uid = mapUid(uid);
6759         mBluetoothScanNesting--;
6760         if (mBluetoothScanNesting == 0) {
6761             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6762                     HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
6763             mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
6764         }
6765         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6766                 .noteBluetoothScanStoppedLocked(elapsedRealtimeMs, isUnoptimized);
6767     }
6768 
6769     @GuardedBy("this")
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized)6770     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
6771         noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized,
6772                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6773     }
6774 
6775     @GuardedBy("this")
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6776     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
6777             long elapsedRealtimeMs, long uptimeMs) {
6778         final int N = ws.size();
6779         for (int i = 0; i < N; i++) {
6780             noteBluetoothScanStoppedLocked(null, ws.getUid(i), isUnoptimized,
6781                     elapsedRealtimeMs, uptimeMs);
6782         }
6783 
6784         final List<WorkChain> workChains = ws.getWorkChains();
6785         if (workChains != null) {
6786             for (int i = 0; i < workChains.size(); ++i) {
6787                 noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized,
6788                         elapsedRealtimeMs, uptimeMs);
6789             }
6790         }
6791     }
6792 
6793     @GuardedBy("this")
noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs)6794     public void noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs) {
6795         if (mBluetoothScanNesting > 0) {
6796             mBluetoothScanNesting = 0;
6797             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6798                     HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
6799             mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
6800             for (int i=0; i<mUidStats.size(); i++) {
6801                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6802                 uid.noteResetBluetoothScanLocked(elapsedRealtimeMs);
6803             }
6804         }
6805     }
6806 
6807     @GuardedBy("this")
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults)6808     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
6809         noteBluetoothScanResultsFromSourceLocked(ws, numNewResults,
6810                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6811     }
6812 
6813     @GuardedBy("this")
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults, long elapsedRealtimeMs, long uptimeMs)6814     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults,
6815             long elapsedRealtimeMs, long uptimeMs) {
6816         final int N = ws.size();
6817         for (int i = 0; i < N; i++) {
6818             int uid = mapUid(ws.getUid(i));
6819             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6820                     .noteBluetoothScanResultsLocked(numNewResults);
6821         }
6822 
6823         final List<WorkChain> workChains = ws.getWorkChains();
6824         if (workChains != null) {
6825             for (int i = 0; i < workChains.size(); ++i) {
6826                 final WorkChain wc = workChains.get(i);
6827                 int uid = mapUid(wc.getAttributionUid());
6828                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6829                         .noteBluetoothScanResultsLocked(numNewResults);
6830             }
6831         }
6832     }
6833 
retrieveBluetoothScanTimesLocked( BluetoothPowerStatsCollector.BluetoothStatsRetriever.Callback callback)6834     private void retrieveBluetoothScanTimesLocked(
6835             BluetoothPowerStatsCollector.BluetoothStatsRetriever.Callback callback) {
6836         long elapsedTimeUs = mClock.elapsedRealtime() * 1000;
6837         for (int i = mUidStats.size() - 1; i >= 0; i--) {
6838             Uid uidStats = mUidStats.valueAt(i);
6839             if (uidStats.mBluetoothScanTimer == null) {
6840                 continue;
6841             }
6842 
6843             long scanTimeUs = mBluetoothScanTimer.getTotalTimeLocked(elapsedTimeUs,
6844                     STATS_SINCE_CHARGED);
6845             if (scanTimeUs != 0) {
6846                 int uid = mUidStats.keyAt(i);
6847                 callback.onBluetoothScanTime(uid, (scanTimeUs + 500) / 1000);
6848             }
6849         }
6850     }
6851 
6852     @GuardedBy("this")
noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)6853     private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
6854             final long uptimeMillis, int uid) {
6855         uid = mapUid(uid);
6856         mHistory.recordEvent(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
6857                 uid);
6858         getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteWifiRadioApWakeupLocked();
6859     }
6860 
6861     @GuardedBy("this")
noteWifiRadioPowerState(int powerState, long timestampNs, int uid, long elapsedRealtimeMs, long uptimeMs)6862     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid,
6863             long elapsedRealtimeMs, long uptimeMs) {
6864         if (mWifiRadioPowerState != powerState) {
6865             final boolean active =
6866                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
6867                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
6868             if (active) {
6869                 if (uid > 0) {
6870                     noteWifiRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
6871                 }
6872                 mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
6873                         HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG);
6874                 mWifiActiveTimer.startRunningLocked(elapsedRealtimeMs);
6875             } else {
6876                 mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
6877                         HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG);
6878                 mWifiActiveTimer.stopRunningLocked(timestampNs / (1000 * 1000));
6879             }
6880             mWifiRadioPowerState = powerState;
6881         }
6882     }
6883 
6884     @GuardedBy("this")
noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6885     public void noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
6886         if (!mGlobalWifiRunning) {
6887             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6888                     HistoryItem.STATE2_WIFI_RUNNING_FLAG);
6889             mGlobalWifiRunning = true;
6890             mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
6891             int N = ws.size();
6892             for (int i=0; i<N; i++) {
6893                 int uid = mapUid(ws.getUid(i));
6894                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6895                         .noteWifiRunningLocked(elapsedRealtimeMs);
6896             }
6897 
6898             List<WorkChain> workChains = ws.getWorkChains();
6899             if (workChains != null) {
6900                 for (int i = 0; i < workChains.size(); ++i) {
6901                     int uid = mapUid(workChains.get(i).getAttributionUid());
6902                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6903                             .noteWifiRunningLocked(elapsedRealtimeMs);
6904                 }
6905             }
6906             if (mWifiPowerStatsCollector.isEnabled()) {
6907                 mWifiPowerStatsCollector.schedule();
6908             } else {
6909                 scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
6910             }
6911         } else {
6912             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
6913         }
6914     }
6915 
6916     @GuardedBy("this")
noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs, long elapsedRealtimeMs, long uptimeMs)6917     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs,
6918             long elapsedRealtimeMs, long uptimeMs) {
6919         if (mGlobalWifiRunning) {
6920             int N = oldWs.size();
6921             for (int i=0; i<N; i++) {
6922                 int uid = mapUid(oldWs.getUid(i));
6923                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6924                         .noteWifiStoppedLocked(elapsedRealtimeMs);
6925             }
6926 
6927             List<WorkChain> workChains = oldWs.getWorkChains();
6928             if (workChains != null) {
6929                 for (int i = 0; i < workChains.size(); ++i) {
6930                     int uid = mapUid(workChains.get(i).getAttributionUid());
6931                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6932                             .noteWifiStoppedLocked(elapsedRealtimeMs);
6933                 }
6934             }
6935 
6936             N = newWs.size();
6937             for (int i=0; i<N; i++) {
6938                 int uid = mapUid(newWs.getUid(i));
6939                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6940                         .noteWifiRunningLocked(elapsedRealtimeMs);
6941             }
6942 
6943             workChains = newWs.getWorkChains();
6944             if (workChains != null) {
6945                 for (int i = 0; i < workChains.size(); ++i) {
6946                     int uid = mapUid(workChains.get(i).getAttributionUid());
6947                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6948                             .noteWifiRunningLocked(elapsedRealtimeMs);
6949                 }
6950             }
6951         } else {
6952             Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
6953         }
6954     }
6955 
6956     @GuardedBy("this")
noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6957     public void noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
6958         if (mGlobalWifiRunning) {
6959             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6960                     HistoryItem.STATE2_WIFI_RUNNING_FLAG);
6961             mGlobalWifiRunning = false;
6962             mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
6963             int N = ws.size();
6964             for (int i=0; i<N; i++) {
6965                 int uid = mapUid(ws.getUid(i));
6966                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6967                         .noteWifiStoppedLocked(elapsedRealtimeMs);
6968             }
6969 
6970             List<WorkChain> workChains = ws.getWorkChains();
6971             if (workChains != null) {
6972                 for (int i = 0; i < workChains.size(); ++i) {
6973                     int uid = mapUid(workChains.get(i).getAttributionUid());
6974                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6975                             .noteWifiStoppedLocked(elapsedRealtimeMs);
6976                 }
6977             }
6978 
6979             if (mWifiPowerStatsCollector.isEnabled()) {
6980                 mWifiPowerStatsCollector.schedule();
6981             } else {
6982                 scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
6983             }
6984         } else {
6985             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
6986         }
6987     }
6988 
6989     @GuardedBy("this")
noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs)6990     public void noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs) {
6991         if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
6992         if (mWifiState != wifiState) {
6993             if (mWifiState >= 0) {
6994                 mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtimeMs);
6995             }
6996             mWifiState = wifiState;
6997             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtimeMs);
6998             if (mWifiPowerStatsCollector.isEnabled()) {
6999                 mWifiPowerStatsCollector.schedule();
7000             } else {
7001                 scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
7002             }
7003         }
7004     }
7005 
7006     @GuardedBy("this")
noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth, long elapsedRealtimeMs, long uptimeMs)7007     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth,
7008             long elapsedRealtimeMs, long uptimeMs) {
7009         if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
7010         if (mWifiSupplState != supplState) {
7011             if (mWifiSupplState >= 0) {
7012                 mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtimeMs);
7013             }
7014             mWifiSupplState = supplState;
7015             mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtimeMs);
7016             mHistory.recordWifiSupplicantStateChangeEvent(elapsedRealtimeMs, uptimeMs, supplState);
7017         }
7018     }
7019 
7020     @GuardedBy("this")
stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs)7021     void stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
7022         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
7023             if (i == except) {
7024                 continue;
7025             }
7026             while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
7027                 mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs);
7028             }
7029         }
7030     }
7031 
7032     @GuardedBy("this")
noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs)7033     public void noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs) {
7034         int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
7035         if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
7036         if (mWifiSignalStrengthBin != strengthBin) {
7037             if (mWifiSignalStrengthBin >= 0) {
7038                 mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
7039                         elapsedRealtimeMs);
7040             }
7041             if (strengthBin >= 0) {
7042                 if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
7043                     mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
7044                 }
7045                 mHistory.recordWifiSignalStrengthChangeEvent(elapsedRealtimeMs, uptimeMs,
7046                         strengthBin);
7047             } else {
7048                 stopAllWifiSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
7049             }
7050             mWifiSignalStrengthBin = strengthBin;
7051         }
7052     }
7053 
7054     private int mWifiFullLockNesting = 0;
7055 
7056     @GuardedBy("this")
noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7057     public void noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7058         if (mWifiFullLockNesting == 0) {
7059             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
7060                     HistoryItem.STATE_WIFI_FULL_LOCK_FLAG);
7061         }
7062         mWifiFullLockNesting++;
7063         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7064                 .noteFullWifiLockAcquiredLocked(elapsedRealtimeMs);
7065     }
7066 
7067     @GuardedBy("this")
noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7068     public void noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7069         mWifiFullLockNesting--;
7070         if (mWifiFullLockNesting == 0) {
7071             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
7072                     HistoryItem.STATE_WIFI_FULL_LOCK_FLAG);
7073         }
7074         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7075                 .noteFullWifiLockReleasedLocked(elapsedRealtimeMs);
7076     }
7077 
7078     int mWifiScanNesting = 0;
7079 
7080     @GuardedBy("this")
noteWifiScanStartedLocked(int uid)7081     public void noteWifiScanStartedLocked(int uid) {
7082         noteWifiScanStartedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7083     }
7084 
7085     @GuardedBy("this")
noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7086     public void noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7087         if (mWifiScanNesting == 0) {
7088             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
7089                     HistoryItem.STATE_WIFI_SCAN_FLAG);
7090         }
7091         mWifiScanNesting++;
7092         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7093                 .noteWifiScanStartedLocked(elapsedRealtimeMs);
7094     }
7095 
7096     @GuardedBy("this")
noteWifiScanStoppedLocked(int uid)7097     public void noteWifiScanStoppedLocked(int uid) {
7098         noteWifiScanStoppedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7099     }
7100 
7101     @GuardedBy("this")
noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7102     public void noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7103         mWifiScanNesting--;
7104         if (mWifiScanNesting == 0) {
7105             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
7106                     HistoryItem.STATE_WIFI_SCAN_FLAG);
7107         }
7108         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7109                 .noteWifiScanStoppedLocked(elapsedRealtimeMs);
7110     }
7111 
noteWifiBatchedScanStartedLocked(int uid, int csph, long elapsedRealtimeMs, long uptimeMs)7112     public void noteWifiBatchedScanStartedLocked(int uid, int csph,
7113             long elapsedRealtimeMs, long uptimeMs) {
7114         uid = mapUid(uid);
7115         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7116                 .noteWifiBatchedScanStartedLocked(csph, elapsedRealtimeMs);
7117     }
7118 
noteWifiBatchedScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7119     public void noteWifiBatchedScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7120         uid = mapUid(uid);
7121         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7122                 .noteWifiBatchedScanStoppedLocked(elapsedRealtimeMs);
7123     }
7124 
retrieveWifiScanTimesLocked( WifiPowerStatsCollector.WifiStatsRetriever.Callback callback)7125     private void retrieveWifiScanTimesLocked(
7126             WifiPowerStatsCollector.WifiStatsRetriever.Callback callback) {
7127         long elapsedTimeUs = mClock.elapsedRealtime() * 1000;
7128         for (int i = mUidStats.size() - 1; i >= 0; i--) {
7129             int uid = mUidStats.keyAt(i);
7130             Uid uidStats = mUidStats.valueAt(i);
7131             long scanTimeUs = uidStats.getWifiScanTime(elapsedTimeUs, STATS_SINCE_CHARGED);
7132             long batchScanTimeUs = 0;
7133             for (int bucket = 0; bucket < NUM_WIFI_BATCHED_SCAN_BINS; bucket++) {
7134                 batchScanTimeUs += uidStats.getWifiBatchedScanTime(bucket, elapsedTimeUs,
7135                         STATS_SINCE_CHARGED);
7136             }
7137             if (scanTimeUs != 0 || batchScanTimeUs != 0) {
7138                 callback.onWifiScanTime(uid, (scanTimeUs + 500) / 1000,
7139                         (batchScanTimeUs + 500) / 1000);
7140             }
7141         }
7142     }
7143 
7144     private int mWifiMulticastNesting = 0;
7145 
7146     @GuardedBy("this")
noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7147     public void noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7148         uid = mapUid(uid);
7149         if (mWifiMulticastNesting == 0) {
7150             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
7151                     HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG);
7152             // Start Wifi Multicast overall timer
7153             if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
7154                 mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtimeMs);
7155             }
7156         }
7157         mWifiMulticastNesting++;
7158         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7159                 .noteWifiMulticastEnabledLocked(elapsedRealtimeMs);
7160     }
7161 
7162     @GuardedBy("this")
noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7163     public void noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7164         uid = mapUid(uid);
7165         mWifiMulticastNesting--;
7166         if (mWifiMulticastNesting == 0) {
7167             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
7168                     HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG);
7169 
7170             // Stop Wifi Multicast overall timer
7171             if (mWifiMulticastWakelockTimer.isRunningLocked()) {
7172                 if (DEBUG) Slog.v(TAG, "Multicast Overall Timer Stopped");
7173                 mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
7174             }
7175         }
7176         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7177                 .noteWifiMulticastDisabledLocked(elapsedRealtimeMs);
7178     }
7179 
7180     @GuardedBy("this")
noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7181     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws,
7182             long elapsedRealtimeMs, long uptimeMs) {
7183         int N = ws.size();
7184         for (int i=0; i<N; i++) {
7185             final int uid = mapUid(ws.getUid(i));
7186             noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs);
7187         }
7188 
7189         final List<WorkChain> workChains = ws.getWorkChains();
7190         if (workChains != null) {
7191             for (int i = 0; i < workChains.size(); ++i) {
7192                 final WorkChain workChain = workChains.get(i);
7193                 final int uid = mapUid(workChain.getAttributionUid());
7194                 noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs);
7195             }
7196         }
7197     }
7198 
7199     @GuardedBy("this")
noteFullWifiLockReleasedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7200     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws,
7201             long elapsedRealtimeMs, long uptimeMs) {
7202         int N = ws.size();
7203         for (int i=0; i<N; i++) {
7204             final int uid = mapUid(ws.getUid(i));
7205             noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs);
7206         }
7207 
7208         final List<WorkChain> workChains = ws.getWorkChains();
7209         if (workChains != null) {
7210             for (int i = 0; i < workChains.size(); ++i) {
7211                 final WorkChain workChain = workChains.get(i);
7212                 final int uid = mapUid(workChain.getAttributionUid());
7213                 noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs);
7214             }
7215         }
7216     }
7217 
7218     @GuardedBy("this")
noteWifiScanStartedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7219     public void noteWifiScanStartedFromSourceLocked(WorkSource ws,
7220             long elapsedRealtimeMs, long uptimeMs) {
7221         int N = ws.size();
7222         for (int i=0; i<N; i++) {
7223             final int uid = mapUid(ws.getUid(i));
7224             noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs);
7225         }
7226 
7227         final List<WorkChain> workChains = ws.getWorkChains();
7228         if (workChains != null) {
7229             for (int i = 0; i < workChains.size(); ++i) {
7230                 final WorkChain workChain = workChains.get(i);
7231                 final int uid = mapUid(workChain.getAttributionUid());
7232                 noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs);
7233             }
7234         }
7235     }
7236 
7237     @GuardedBy("this")
noteWifiScanStoppedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7238     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws,
7239             long elapsedRealtimeMs, long uptimeMs) {
7240         int N = ws.size();
7241         for (int i=0; i<N; i++) {
7242             final int uid = mapUid(ws.getUid(i));
7243             noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs);
7244         }
7245 
7246         final List<WorkChain> workChains = ws.getWorkChains();
7247         if (workChains != null) {
7248             for (int i = 0; i < workChains.size(); ++i) {
7249                 final WorkChain workChain = workChains.get(i);
7250                 final int uid = mapUid(workChain.getAttributionUid());
7251                 noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs);
7252             }
7253         }
7254     }
7255 
7256     @GuardedBy("this")
noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph, long elapsedRealtimeMs, long uptimeMs)7257     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph,
7258             long elapsedRealtimeMs, long uptimeMs) {
7259         int N = ws.size();
7260         for (int i=0; i<N; i++) {
7261             noteWifiBatchedScanStartedLocked(ws.getUid(i), csph, elapsedRealtimeMs, uptimeMs);
7262         }
7263 
7264         final List<WorkChain> workChains = ws.getWorkChains();
7265         if (workChains != null) {
7266             for (int i = 0; i < workChains.size(); ++i) {
7267                 noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph,
7268                         elapsedRealtimeMs, uptimeMs);
7269             }
7270         }
7271     }
7272 
7273     @GuardedBy("this")
noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7274     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws,
7275             long elapsedRealtimeMs, long uptimeMs) {
7276         int N = ws.size();
7277         for (int i=0; i<N; i++) {
7278             noteWifiBatchedScanStoppedLocked(ws.getUid(i), elapsedRealtimeMs, uptimeMs);
7279         }
7280 
7281         final List<WorkChain> workChains = ws.getWorkChains();
7282         if (workChains != null) {
7283             for (int i = 0; i < workChains.size(); ++i) {
7284                 noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid(),
7285                         elapsedRealtimeMs, uptimeMs);
7286             }
7287         }
7288     }
7289 
includeInStringArray(String[] array, String str)7290     private static String[] includeInStringArray(String[] array, String str) {
7291         if (ArrayUtils.indexOf(array, str) >= 0) {
7292             return array;
7293         }
7294         String[] newArray = new String[array.length+1];
7295         System.arraycopy(array, 0, newArray, 0, array.length);
7296         newArray[array.length] = str;
7297         return newArray;
7298     }
7299 
excludeFromStringArray(String[] array, String str)7300     private static String[] excludeFromStringArray(String[] array, String str) {
7301         int index = ArrayUtils.indexOf(array, str);
7302         if (index >= 0) {
7303             String[] newArray = new String[array.length-1];
7304             if (index > 0) {
7305                 System.arraycopy(array, 0, newArray, 0, index);
7306             }
7307             if (index < array.length-1) {
7308                 System.arraycopy(array, index+1, newArray, index, array.length-index-1);
7309             }
7310             return newArray;
7311         }
7312         return array;
7313     }
7314 
7315     /** @hide */
noteNetworkInterfaceForTransports(String iface, int[] transportTypes)7316     public void noteNetworkInterfaceForTransports(String iface, int[] transportTypes) {
7317         if (TextUtils.isEmpty(iface)) return;
7318         final int displayTransport = getDisplayTransport(transportTypes);
7319 
7320         synchronized (mModemNetworkLock) {
7321             if (displayTransport == TRANSPORT_CELLULAR) {
7322                 mModemIfaces = includeInStringArray(mModemIfaces, iface);
7323                 if (DEBUG) {
7324                     Slog.d(TAG, "Note mobile iface " + iface + ": "
7325                             + Arrays.toString(mModemIfaces));
7326                 }
7327             } else {
7328                 mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
7329                 if (DEBUG) {
7330                     Slog.d(TAG, "Note non-mobile iface " + iface + ": "
7331                             + Arrays.toString(mModemIfaces));
7332                 }
7333             }
7334         }
7335 
7336         synchronized (mWifiNetworkLock) {
7337             if (displayTransport == TRANSPORT_WIFI) {
7338                 mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
7339                 if (DEBUG) {
7340                     Slog.d(TAG, "Note wifi iface " + iface + ": " + Arrays.toString(mWifiIfaces));
7341                 }
7342             } else {
7343                 mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
7344                 if (DEBUG) {
7345                     Slog.d(TAG, "Note non-wifi iface " + iface + ": "
7346                             + Arrays.toString(mWifiIfaces));
7347                 }
7348             }
7349         }
7350     }
7351 
7352     /**
7353      * Records timing data related to an incoming Binder call in order to attribute
7354      * the power consumption to the calling app.
7355      */
noteBinderCallStats(int workSourceUid, long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats)7356     public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
7357             Collection<BinderCallsStats.CallStat> callStats) {
7358         noteBinderCallStats(workSourceUid, incrementalCallCount, callStats,
7359                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7360     }
7361 
noteBinderCallStats(int workSourceUid, long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats, long elapsedRealtimeMs, long uptimeMs)7362     public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
7363             Collection<BinderCallsStats.CallStat> callStats,
7364             long elapsedRealtimeMs, long uptimeMs) {
7365         synchronized (this) {
7366             getUidStatsLocked(workSourceUid, elapsedRealtimeMs, uptimeMs)
7367                     .noteBinderCallStatsLocked(incrementalCallCount, callStats);
7368         }
7369     }
7370 
7371     /**
7372      * Takes note of native IDs of threads taking incoming binder calls. The CPU time
7373      * of these threads is attributed to the apps making those binder calls.
7374      */
noteBinderThreadNativeIds(int[] binderThreadNativeTids)7375     public void noteBinderThreadNativeIds(int[] binderThreadNativeTids) {
7376         mSystemServerCpuThreadReader.setBinderThreadNativeTids(binderThreadNativeTids);
7377     }
7378 
7379     /**
7380      * Estimates the proportion of system server CPU activity handling incoming binder calls
7381      * that can be attributed to each app
7382      */
7383     @VisibleForTesting
updateSystemServiceCallStats()7384     public void updateSystemServiceCallStats() {
7385         // Start off by computing the average duration of recorded binder calls,
7386         // regardless of which binder or transaction. We will use this as a fallback
7387         // for calls that were not sampled at all.
7388         int totalRecordedCallCount = 0;
7389         long totalRecordedCallTimeMicros = 0;
7390         for (int i = 0; i < mUidStats.size(); i++) {
7391             Uid uid = mUidStats.valueAt(i);
7392             ArraySet<BinderCallStats> binderCallStats = uid.mBinderCallStats;
7393             for (int j = binderCallStats.size() - 1; j >= 0; j--) {
7394                 BinderCallStats stats = binderCallStats.valueAt(j);
7395                 totalRecordedCallCount += stats.recordedCallCount;
7396                 totalRecordedCallTimeMicros += stats.recordedCpuTimeMicros;
7397             }
7398         }
7399 
7400         long totalSystemServiceTimeMicros = 0;
7401 
7402         // For every UID, use recorded durations of sampled binder calls to estimate
7403         // the total time the system server spent handling requests from this UID.
7404         for (int i = 0; i < mUidStats.size(); i++) {
7405             Uid uid = mUidStats.valueAt(i);
7406 
7407             long totalTimeForUidUs = 0;
7408             int totalCallCountForUid = 0;
7409             ArraySet<BinderCallStats> binderCallStats = uid.mBinderCallStats;
7410             for (int j = binderCallStats.size() - 1; j >= 0; j--) {
7411                 BinderCallStats stats = binderCallStats.valueAt(j);
7412                 totalCallCountForUid += stats.callCount;
7413                 if (stats.recordedCallCount > 0) {
7414                     totalTimeForUidUs +=
7415                             stats.callCount * stats.recordedCpuTimeMicros / stats.recordedCallCount;
7416                 } else if (totalRecordedCallCount > 0) {
7417                     totalTimeForUidUs +=
7418                             stats.callCount * totalRecordedCallTimeMicros / totalRecordedCallCount;
7419                 }
7420             }
7421 
7422             if (totalCallCountForUid < uid.mBinderCallCount && totalRecordedCallCount > 0) {
7423                 // Estimate remaining calls, which were not tracked because of binder call
7424                 // stats sampling
7425                 totalTimeForUidUs +=
7426                         (uid.mBinderCallCount - totalCallCountForUid) * totalRecordedCallTimeMicros
7427                                 / totalRecordedCallCount;
7428             }
7429 
7430             uid.mSystemServiceTimeUs = totalTimeForUidUs;
7431             totalSystemServiceTimeMicros += totalTimeForUidUs;
7432         }
7433 
7434         for (int i = 0; i < mUidStats.size(); i++) {
7435             Uid uid = mUidStats.valueAt(i);
7436             if (totalSystemServiceTimeMicros > 0) {
7437                 uid.mProportionalSystemServiceUsage =
7438                         (double) uid.mSystemServiceTimeUs / totalSystemServiceTimeMicros;
7439             } else {
7440                 uid.mProportionalSystemServiceUsage = 0;
7441             }
7442         }
7443     }
7444 
getWifiIfaces()7445     public String[] getWifiIfaces() {
7446         synchronized (mWifiNetworkLock) {
7447             return mWifiIfaces;
7448         }
7449     }
7450 
getMobileIfaces()7451     public String[] getMobileIfaces() {
7452         synchronized (mModemNetworkLock) {
7453             return mModemIfaces;
7454         }
7455     }
7456 
getScreenOnTime(long elapsedRealtimeUs, int which)7457     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
7458         return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7459     }
7460 
getScreenOnCount(int which)7461     @Override public int getScreenOnCount(int which) {
7462         return mScreenOnTimer.getCountLocked(which);
7463     }
7464 
getScreenDozeTime(long elapsedRealtimeUs, int which)7465     @Override public long getScreenDozeTime(long elapsedRealtimeUs, int which) {
7466         return mScreenDozeTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7467     }
7468 
getScreenDozeCount(int which)7469     @Override public int getScreenDozeCount(int which) {
7470         return mScreenDozeTimer.getCountLocked(which);
7471     }
7472 
getScreenBrightnessTime(int brightnessBin, long elapsedRealtimeUs, int which)7473     @Override public long getScreenBrightnessTime(int brightnessBin,
7474             long elapsedRealtimeUs, int which) {
7475         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
7476                 elapsedRealtimeUs, which);
7477     }
7478 
getScreenBrightnessTimer(int brightnessBin)7479     @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
7480         return mScreenBrightnessTimer[brightnessBin];
7481     }
7482 
7483     @Override
getDisplayCount()7484     public int getDisplayCount() {
7485         return mPerDisplayBatteryStats.length;
7486     }
7487 
7488     @Override
getDisplayScreenOnTime(int display, long elapsedRealtimeUs)7489     public long getDisplayScreenOnTime(int display, long elapsedRealtimeUs) {
7490         return mPerDisplayBatteryStats[display].screenOnTimer.getTotalTimeLocked(elapsedRealtimeUs,
7491                 STATS_SINCE_CHARGED);
7492     }
7493 
7494     @Override
getDisplayScreenDozeTime(int display, long elapsedRealtimeUs)7495     public long getDisplayScreenDozeTime(int display, long elapsedRealtimeUs) {
7496         return mPerDisplayBatteryStats[display].screenDozeTimer.getTotalTimeLocked(
7497                 elapsedRealtimeUs, STATS_SINCE_CHARGED);
7498     }
7499 
7500     @Override
getDisplayScreenBrightnessTime(int display, int brightnessBin, long elapsedRealtimeUs)7501     public long getDisplayScreenBrightnessTime(int display, int brightnessBin,
7502             long elapsedRealtimeUs) {
7503         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
7504         return displayStats.screenBrightnessTimers[brightnessBin].getTotalTimeLocked(
7505                 elapsedRealtimeUs, STATS_SINCE_CHARGED);
7506     }
7507 
getInteractiveTime(long elapsedRealtimeUs, int which)7508     @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
7509         return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7510     }
7511 
getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which)7512     @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
7513         return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7514     }
7515 
getPowerSaveModeEnabledCount(int which)7516     @Override public int getPowerSaveModeEnabledCount(int which) {
7517         return mPowerSaveModeEnabledTimer.getCountLocked(which);
7518     }
7519 
getDeviceIdleModeTime(int mode, long elapsedRealtimeUs, int which)7520     @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
7521             int which) {
7522         switch (mode) {
7523             case DEVICE_IDLE_MODE_LIGHT:
7524                 return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7525             case DEVICE_IDLE_MODE_DEEP:
7526                 return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7527         }
7528         return 0;
7529     }
7530 
getDeviceIdleModeCount(int mode, int which)7531     @Override public int getDeviceIdleModeCount(int mode, int which) {
7532         switch (mode) {
7533             case DEVICE_IDLE_MODE_LIGHT:
7534                 return mDeviceIdleModeLightTimer.getCountLocked(which);
7535             case DEVICE_IDLE_MODE_DEEP:
7536                 return mDeviceIdleModeFullTimer.getCountLocked(which);
7537         }
7538         return 0;
7539     }
7540 
getLongestDeviceIdleModeTime(int mode)7541     @Override public long getLongestDeviceIdleModeTime(int mode) {
7542         switch (mode) {
7543             case DEVICE_IDLE_MODE_LIGHT:
7544                 return mLongestLightIdleTimeMs;
7545             case DEVICE_IDLE_MODE_DEEP:
7546                 return mLongestFullIdleTimeMs;
7547         }
7548         return 0;
7549     }
7550 
getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which)7551     @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
7552         switch (mode) {
7553             case DEVICE_IDLE_MODE_LIGHT:
7554                 return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7555             case DEVICE_IDLE_MODE_DEEP:
7556                 return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7557         }
7558         return 0;
7559     }
7560 
getDeviceIdlingCount(int mode, int which)7561     @Override public int getDeviceIdlingCount(int mode, int which) {
7562         switch (mode) {
7563             case DEVICE_IDLE_MODE_LIGHT:
7564                 return mDeviceLightIdlingTimer.getCountLocked(which);
7565             case DEVICE_IDLE_MODE_DEEP:
7566                 return mDeviceIdlingTimer.getCountLocked(which);
7567         }
7568         return 0;
7569     }
7570 
getNumConnectivityChange(int which)7571     @Override public int getNumConnectivityChange(int which) {
7572         return mNumConnectivityChange;
7573     }
7574 
getGpsSignalQualityTime(int strengthBin, long elapsedRealtimeUs, int which)7575     @Override public long getGpsSignalQualityTime(int strengthBin,
7576             long elapsedRealtimeUs, int which) {
7577         if (strengthBin < 0 || strengthBin >= mGpsSignalQualityTimer.length) {
7578             return 0;
7579         }
7580         return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
7581                 elapsedRealtimeUs, which);
7582     }
7583 
getGpsBatteryDrainMaMs()7584     @Override public long getGpsBatteryDrainMaMs() {
7585         final double opVolt = mPowerProfile.getAveragePower(
7586             PowerProfile.POWER_GPS_OPERATING_VOLTAGE) / 1000.0;
7587         if (opVolt == 0) {
7588             return 0;
7589         }
7590         double energyUsedMaMs = 0.0;
7591         final int which = STATS_SINCE_CHARGED;
7592         final long rawRealtimeUs = SystemClock.elapsedRealtime() * 1000;
7593         for(int i=0; i < mGpsSignalQualityTimer.length; i++) {
7594             energyUsedMaMs
7595                     += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
7596                     * (getGpsSignalQualityTime(i, rawRealtimeUs, which) / 1000);
7597         }
7598         return (long) energyUsedMaMs;
7599     }
7600 
getPhoneOnTime(long elapsedRealtimeUs, int which)7601     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
7602         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7603     }
7604 
getPhoneOnCount(int which)7605     @Override public int getPhoneOnCount(int which) {
7606         return mPhoneOnTimer.getCountLocked(which);
7607     }
7608 
getPhoneSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)7609     @Override public long getPhoneSignalStrengthTime(int strengthBin,
7610             long elapsedRealtimeUs, int which) {
7611         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
7612                 elapsedRealtimeUs, which);
7613     }
7614 
getPhoneSignalScanningTime( long elapsedRealtimeUs, int which)7615     @Override public long getPhoneSignalScanningTime(
7616             long elapsedRealtimeUs, int which) {
7617         return mPhoneSignalScanningTimer.getTotalTimeLocked(
7618                 elapsedRealtimeUs, which);
7619     }
7620 
getPhoneSignalScanningTimer()7621     @Override public Timer getPhoneSignalScanningTimer() {
7622         return mPhoneSignalScanningTimer;
7623     }
7624 
getPhoneSignalStrengthCount(int strengthBin, int which)7625     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
7626         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
7627     }
7628 
getPhoneSignalStrengthTimer(int strengthBin)7629     @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
7630         return mPhoneSignalStrengthsTimer[strengthBin];
7631     }
7632 
getPhoneDataConnectionTime(int dataType, long elapsedRealtimeUs, int which)7633     @Override public long getPhoneDataConnectionTime(int dataType,
7634             long elapsedRealtimeUs, int which) {
7635         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
7636                 elapsedRealtimeUs, which);
7637     }
7638 
getPhoneDataConnectionCount(int dataType, int which)7639     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
7640         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
7641     }
7642 
getPhoneDataConnectionTimer(int dataType)7643     @Override public Timer getPhoneDataConnectionTimer(int dataType) {
7644         return mPhoneDataConnectionsTimer[dataType];
7645     }
7646 
getNrNsaTime(long elapsedRealtimeUs)7647     @Override public long getNrNsaTime(long elapsedRealtimeUs) {
7648         return mNrNsaTimer.getTotalTimeLocked(elapsedRealtimeUs, STATS_SINCE_CHARGED);
7649     }
7650 
getActiveRadioDurationMs(@adioAccessTechnology int rat, @ServiceState.FrequencyRange int frequencyRange, int signalStrength, long elapsedRealtimeMs)7651     @Override public long getActiveRadioDurationMs(@RadioAccessTechnology int rat,
7652             @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
7653             long elapsedRealtimeMs) {
7654         final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
7655         if (stats == null) return 0L;
7656 
7657         final int freqCount = stats.perStateTimers.length;
7658         if (frequencyRange < 0 || frequencyRange >= freqCount) return 0L;
7659 
7660         final StopwatchTimer[] strengthTimers = stats.perStateTimers[frequencyRange];
7661         final int strengthCount = strengthTimers.length;
7662         if (signalStrength < 0 || signalStrength >= strengthCount) return 0L;
7663 
7664         return stats.perStateTimers[frequencyRange][signalStrength].getTotalTimeLocked(
7665                 elapsedRealtimeMs * 1000, STATS_SINCE_CHARGED) / 1000;
7666     }
7667 
7668     @Override
getActiveTxRadioDurationMs(@adioAccessTechnology int rat, @ServiceState.FrequencyRange int frequencyRange, int signalStrength, long elapsedRealtimeMs)7669     public long getActiveTxRadioDurationMs(@RadioAccessTechnology int rat,
7670             @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
7671             long elapsedRealtimeMs) {
7672         final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
7673         if (stats == null) return DURATION_UNAVAILABLE;
7674 
7675         final LongSamplingCounter counter = stats.getTxDurationCounter(frequencyRange,
7676                 signalStrength, false);
7677         if (counter == null) return DURATION_UNAVAILABLE;
7678 
7679         return counter.getCountLocked(STATS_SINCE_CHARGED);
7680     }
7681 
7682     @Override
getActiveRxRadioDurationMs(@adioAccessTechnology int rat, @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs)7683     public long getActiveRxRadioDurationMs(@RadioAccessTechnology int rat,
7684             @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs) {
7685         final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
7686         if (stats == null) return DURATION_UNAVAILABLE;
7687 
7688         final LongSamplingCounter counter = stats.getRxDurationCounter(frequencyRange, false);
7689         if (counter == null) return DURATION_UNAVAILABLE;
7690 
7691         return counter.getCountLocked(STATS_SINCE_CHARGED);
7692     }
7693 
getMobileRadioActiveTime(long elapsedRealtimeUs, int which)7694     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
7695         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7696     }
7697 
getMobileRadioActiveCount(int which)7698     @Override public int getMobileRadioActiveCount(int which) {
7699         return mMobileRadioActiveTimer.getCountLocked(which);
7700     }
7701 
getMobileRadioActiveAdjustedTime(int which)7702     @Override public long getMobileRadioActiveAdjustedTime(int which) {
7703         return mMobileRadioActiveAdjustedTime.getCountLocked(which);
7704     }
7705 
getMobileRadioActiveUnknownTime(int which)7706     @Override public long getMobileRadioActiveUnknownTime(int which) {
7707         return mMobileRadioActiveUnknownTime.getCountLocked(which);
7708     }
7709 
getMobileRadioActiveUnknownCount(int which)7710     @Override public int getMobileRadioActiveUnknownCount(int which) {
7711         return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
7712     }
7713 
getWifiMulticastWakelockTime( long elapsedRealtimeUs, int which)7714     @Override public long getWifiMulticastWakelockTime(
7715             long elapsedRealtimeUs, int which) {
7716         return mWifiMulticastWakelockTimer.getTotalTimeLocked(
7717                 elapsedRealtimeUs, which);
7718     }
7719 
getWifiMulticastWakelockCount(int which)7720     @Override public int getWifiMulticastWakelockCount(int which) {
7721         return mWifiMulticastWakelockTimer.getCountLocked(which);
7722     }
7723 
getWifiOnTime(long elapsedRealtimeUs, int which)7724     @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
7725         return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7726     }
7727 
getWifiActiveTime(long elapsedRealtimeUs, int which)7728     @Override public long getWifiActiveTime(long elapsedRealtimeUs, int which) {
7729         return mWifiActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7730     }
7731 
getGlobalWifiRunningTime(long elapsedRealtimeUs, int which)7732     @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
7733         return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7734     }
7735 
getWifiStateTime(int wifiState, long elapsedRealtimeUs, int which)7736     @Override public long getWifiStateTime(int wifiState,
7737             long elapsedRealtimeUs, int which) {
7738         return mWifiStateTimer[wifiState].getTotalTimeLocked(
7739                 elapsedRealtimeUs, which);
7740     }
7741 
getWifiStateCount(int wifiState, int which)7742     @Override public int getWifiStateCount(int wifiState, int which) {
7743         return mWifiStateTimer[wifiState].getCountLocked(which);
7744     }
7745 
getWifiStateTimer(int wifiState)7746     @Override public Timer getWifiStateTimer(int wifiState) {
7747         return mWifiStateTimer[wifiState];
7748     }
7749 
getWifiSupplStateTime(int state, long elapsedRealtimeUs, int which)7750     @Override public long getWifiSupplStateTime(int state,
7751             long elapsedRealtimeUs, int which) {
7752         return mWifiSupplStateTimer[state].getTotalTimeLocked(
7753                 elapsedRealtimeUs, which);
7754     }
7755 
getWifiSupplStateCount(int state, int which)7756     @Override public int getWifiSupplStateCount(int state, int which) {
7757         return mWifiSupplStateTimer[state].getCountLocked(which);
7758     }
7759 
getWifiSupplStateTimer(int state)7760     @Override public Timer getWifiSupplStateTimer(int state) {
7761         return mWifiSupplStateTimer[state];
7762     }
7763 
getWifiSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)7764     @Override public long getWifiSignalStrengthTime(int strengthBin,
7765             long elapsedRealtimeUs, int which) {
7766         return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
7767                 elapsedRealtimeUs, which);
7768     }
7769 
getWifiSignalStrengthCount(int strengthBin, int which)7770     @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
7771         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
7772     }
7773 
getWifiSignalStrengthTimer(int strengthBin)7774     @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
7775         return mWifiSignalStrengthsTimer[strengthBin];
7776     }
7777 
7778     @Override
getBluetoothControllerActivity()7779     public ControllerActivityCounter getBluetoothControllerActivity() {
7780         return mBluetoothActivity;
7781     }
7782 
7783     @Override
getWifiControllerActivity()7784     public ControllerActivityCounter getWifiControllerActivity() {
7785         return mWifiActivity;
7786     }
7787 
7788     @Override
getModemControllerActivity()7789     public ControllerActivityCounter getModemControllerActivity() {
7790         return mModemActivity;
7791     }
7792 
7793     @Override
hasBluetoothActivityReporting()7794     public boolean hasBluetoothActivityReporting() {
7795         return mHasBluetoothReporting;
7796     }
7797 
7798     @Override
hasWifiActivityReporting()7799     public boolean hasWifiActivityReporting() {
7800         return mHasWifiReporting;
7801     }
7802 
7803     @Override
hasModemActivityReporting()7804     public boolean hasModemActivityReporting() {
7805         return mHasModemReporting;
7806     }
7807 
7808     @Override
getFlashlightOnTime(long elapsedRealtimeUs, int which)7809     public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
7810         return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7811     }
7812 
7813     @Override
getFlashlightOnCount(int which)7814     public long getFlashlightOnCount(int which) {
7815         return mFlashlightOnTimer.getCountLocked(which);
7816     }
7817 
7818     @Override
getCameraOnTime(long elapsedRealtimeUs, int which)7819     public long getCameraOnTime(long elapsedRealtimeUs, int which) {
7820         return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7821     }
7822 
7823     @Override
getBluetoothScanTime(long elapsedRealtimeUs, int which)7824     public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
7825         return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7826     }
7827 
7828     @Override
getNetworkActivityBytes(int type, int which)7829     public long getNetworkActivityBytes(int type, int which) {
7830         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
7831             return mNetworkByteActivityCounters[type].getCountLocked(which);
7832         } else {
7833             return 0;
7834         }
7835     }
7836 
7837     @Override
getNetworkActivityPackets(int type, int which)7838     public long getNetworkActivityPackets(int type, int which) {
7839         if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
7840             return mNetworkPacketActivityCounters[type].getCountLocked(which);
7841         } else {
7842             return 0;
7843         }
7844     }
7845 
7846     @GuardedBy("this")
7847     @Override
getBluetoothEnergyConsumptionUC()7848     public long getBluetoothEnergyConsumptionUC() {
7849         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_BLUETOOTH);
7850     }
7851 
7852     @GuardedBy("this")
7853     @Override
getCpuEnergyConsumptionUC()7854     public long getCpuEnergyConsumptionUC() {
7855         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CPU);
7856     }
7857 
7858     @GuardedBy("this")
7859     @Override
getGnssEnergyConsumptionUC()7860     public long getGnssEnergyConsumptionUC() {
7861         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_GNSS);
7862     }
7863 
7864     @GuardedBy("this")
7865     @Override
getMobileRadioEnergyConsumptionUC()7866     public long getMobileRadioEnergyConsumptionUC() {
7867         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO);
7868     }
7869 
7870     @GuardedBy("this")
7871     @Override
getPhoneEnergyConsumptionUC()7872     public long getPhoneEnergyConsumptionUC() {
7873         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_PHONE);
7874     }
7875 
7876     @GuardedBy("this")
7877     @Override
getScreenOnEnergyConsumptionUC()7878     public long getScreenOnEnergyConsumptionUC() {
7879         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_SCREEN_ON);
7880     }
7881 
7882     @GuardedBy("this")
7883     @Override
getScreenDozeEnergyConsumptionUC()7884     public long getScreenDozeEnergyConsumptionUC() {
7885         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_SCREEN_DOZE);
7886     }
7887 
7888     @GuardedBy("this")
7889     @Override
getWifiEnergyConsumptionUC()7890     public long getWifiEnergyConsumptionUC() {
7891         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_WIFI);
7892     }
7893 
7894     @GuardedBy("this")
7895     @Override
getCameraEnergyConsumptionUC()7896     public long getCameraEnergyConsumptionUC() {
7897         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CAMERA);
7898     }
7899 
7900     /**
7901      * Returns the consumption (in microcoulombs) that the given standard power bucket consumed.
7902      * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable
7903      *
7904      * @param bucket standard power bucket of interest
7905      * @return charge (in microcoulombs) used for this power bucket
7906      */
7907     @GuardedBy("this")
getPowerBucketConsumptionUC(@tandardPowerBucket int bucket)7908     private long getPowerBucketConsumptionUC(@StandardPowerBucket int bucket) {
7909         if (mGlobalEnergyConsumerStats == null) {
7910             return POWER_DATA_UNAVAILABLE;
7911         }
7912         return mGlobalEnergyConsumerStats.getAccumulatedStandardBucketCharge(bucket);
7913     }
7914 
7915     @GuardedBy("this")
7916     @Override
getCustomEnergyConsumerBatteryConsumptionUC()7917     public @Nullable long[] getCustomEnergyConsumerBatteryConsumptionUC() {
7918         if (mGlobalEnergyConsumerStats == null) {
7919             return null;
7920         }
7921         return mGlobalEnergyConsumerStats.getAccumulatedCustomBucketCharges();
7922     }
7923 
7924     /**
7925      * Returns the names of custom power components.
7926      */
7927     @Override
getCustomEnergyConsumerNames()7928     public @NonNull String[] getCustomEnergyConsumerNames() {
7929         synchronized (this) {
7930             if (mEnergyConsumerStatsConfig == null) {
7931                 return new String[0];
7932             }
7933             final String[] names = mEnergyConsumerStatsConfig.getCustomBucketNames();
7934             for (int i = 0; i < names.length; i++) {
7935                 if (TextUtils.isEmpty(names[i])) {
7936                     names[i] = "CUSTOM_" + BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + i;
7937                 }
7938             }
7939             return names;
7940         }
7941     }
7942 
7943     @Override
getStartClockTime()7944     public long getStartClockTime() {
7945         synchronized (this) {
7946             final long currentTimeMs = mClock.currentTimeMillis();
7947             if ((currentTimeMs > MILLISECONDS_IN_YEAR
7948                     && mStartClockTimeMs < (currentTimeMs - MILLISECONDS_IN_YEAR))
7949                 || (mStartClockTimeMs > currentTimeMs)) {
7950                 // If the start clock time has changed by more than a year, then presumably
7951                 // the previous time was completely bogus.  So we are going to figure out a
7952                 // new time based on how much time has elapsed since we started counting.
7953                 mHistory.recordCurrentTimeChange(mClock.elapsedRealtime(), mClock.uptimeMillis(),
7954                         currentTimeMs);
7955                 adjustStartClockTime(currentTimeMs);
7956             }
7957             return mStartClockTimeMs;
7958         }
7959     }
7960 
7961     /**
7962      * Returns the monotonic time when the BatteryStats session started.
7963      */
getMonotonicStartTime()7964     public long getMonotonicStartTime() {
7965         return mMonotonicStartTime;
7966     }
7967 
7968     /**
7969      * Returns the monotonic time when the BatteryStats session ended, or
7970      * {@link MonotonicClock#UNDEFINED} if the session is still ongoing.
7971      */
getMonotonicEndTime()7972     public long getMonotonicEndTime() {
7973         return mMonotonicEndTime;
7974     }
7975 
getStartPlatformVersion()7976     @Override public String getStartPlatformVersion() {
7977         return mStartPlatformVersion;
7978     }
7979 
getEndPlatformVersion()7980     @Override public String getEndPlatformVersion() {
7981         return mEndPlatformVersion;
7982     }
7983 
getParcelVersion()7984     @Override public int getParcelVersion() {
7985         return VERSION;
7986     }
7987 
getIsOnBattery()7988     @Override public boolean getIsOnBattery() {
7989         return mOnBattery;
7990     }
7991 
getStatsStartRealtime()7992     @Override public long getStatsStartRealtime() {
7993         return mRealtimeStartUs;
7994     }
7995 
getUidStats()7996     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
7997         return mUidStats;
7998     }
7999 
resetIfNotNull(T t, boolean detachIfReset, long elapsedRealtimeUs)8000     private static <T extends TimeBaseObs> boolean resetIfNotNull(T t, boolean detachIfReset,
8001             long elapsedRealtimeUs) {
8002         if (t != null) {
8003             return t.reset(detachIfReset, elapsedRealtimeUs);
8004         }
8005         return true;
8006     }
8007 
resetIfNotNull(T[] t, boolean detachIfReset, long elapsedRealtimeUs)8008     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[] t, boolean detachIfReset,
8009             long elapsedRealtimeUs) {
8010         if (t != null) {
8011             boolean ret = true;
8012             for (int i = 0; i < t.length; i++) {
8013                 ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs);
8014             }
8015             return ret;
8016         }
8017         return true;
8018     }
8019 
resetIfNotNull(T[][] t, boolean detachIfReset, long elapsedRealtimeUs)8020     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[][] t, boolean detachIfReset,
8021             long elapsedRealtimeUs) {
8022         if (t != null) {
8023             boolean ret = true;
8024             for (int i = 0; i < t.length; i++) {
8025                 ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs);
8026             }
8027             return ret;
8028         }
8029         return true;
8030     }
8031 
resetIfNotNull(ControllerActivityCounterImpl counter, boolean detachIfReset, long elapsedRealtimeUs)8032     private static boolean resetIfNotNull(ControllerActivityCounterImpl counter,
8033             boolean detachIfReset, long elapsedRealtimeUs) {
8034         if (counter != null) {
8035             counter.reset(detachIfReset, elapsedRealtimeUs);
8036         }
8037         return true;
8038     }
8039 
detachIfNotNull(T t)8040     private static <T extends TimeBaseObs> void detachIfNotNull(T t) {
8041         if (t != null) {
8042             t.detach();
8043         }
8044     }
8045 
detachIfNotNull(T[] t)8046     private static <T extends TimeBaseObs> void detachIfNotNull(T[] t) {
8047         if (t != null) {
8048             for (int i = 0; i < t.length; i++) {
8049                 detachIfNotNull(t[i]);
8050             }
8051         }
8052     }
8053 
detachIfNotNull(T[][] t)8054     private static <T extends TimeBaseObs> void detachIfNotNull(T[][] t) {
8055         if (t != null) {
8056             for (int i = 0; i < t.length; i++) {
8057                 detachIfNotNull(t[i]);
8058             }
8059         }
8060     }
8061 
detachIfNotNull(ControllerActivityCounterImpl counter)8062     private static void detachIfNotNull(ControllerActivityCounterImpl counter) {
8063         if (counter != null) {
8064             counter.detach();
8065         }
8066     }
8067 
8068     /**
8069      * Accumulates stats for a specific binder transaction.
8070      */
8071     @VisibleForTesting
8072     protected static class BinderCallStats {
8073         public Class<? extends Binder> binderClass;
8074         public int transactionCode;
8075         public String methodName;
8076 
8077         public long callCount;
8078         public long recordedCallCount;
8079         public long recordedCpuTimeMicros;
8080 
8081 
8082         @Override
hashCode()8083         public int hashCode() {
8084             return binderClass.hashCode() * 31 + transactionCode;
8085         }
8086 
8087         @Override
equals(Object obj)8088         public boolean equals(Object obj) {
8089             if (!(obj instanceof BinderCallStats)) {
8090                 return false;
8091             }
8092             BinderCallStats bcsk = (BinderCallStats) obj;
8093             return binderClass.equals(bcsk.binderClass) && transactionCode == bcsk.transactionCode;
8094         }
8095 
getClassName()8096         public String getClassName() {
8097             return binderClass.getName();
8098         }
8099 
getMethodName()8100         public String getMethodName() {
8101             return methodName;
8102         }
8103 
8104         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
ensureMethodName(BinderTransactionNameResolver resolver)8105         public void ensureMethodName(BinderTransactionNameResolver resolver) {
8106             if (methodName == null) {
8107                 methodName = resolver.getMethodName(binderClass, transactionCode);
8108             }
8109         }
8110 
8111         @Override
toString()8112         public String toString() {
8113             return "BinderCallStats{"
8114                     + binderClass
8115                     + " transaction=" + transactionCode
8116                     + " callCount=" + callCount
8117                     + " recordedCallCount=" + recordedCallCount
8118                     + " recorderCpuTimeMicros=" + recordedCpuTimeMicros
8119                     + "}";
8120         }
8121     }
8122 
8123     /**
8124      * The statistics associated with a particular uid.
8125      */
8126     public static class Uid extends BatteryStats.Uid {
8127         /**
8128          * BatteryStatsImpl that we are associated with.
8129          */
8130         protected BatteryStatsImpl mBsi;
8131 
8132         final int mUid;
8133 
8134         /** TimeBase for when uid is in background and device is on battery. */
8135         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
8136         public final TimeBase mOnBatteryBackgroundTimeBase;
8137         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
8138         public final TimeBase mOnBatteryScreenOffBackgroundTimeBase;
8139 
8140         boolean mWifiRunning;
8141         StopwatchTimer mWifiRunningTimer;
8142 
8143         boolean mFullWifiLockOut;
8144         StopwatchTimer mFullWifiLockTimer;
8145 
8146         boolean mWifiScanStarted;
8147         DualTimer mWifiScanTimer;
8148 
8149         static final int NO_BATCHED_SCAN_STARTED = -1;
8150         int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
8151         StopwatchTimer[] mWifiBatchedScanTimer;
8152 
8153         int mWifiMulticastWakelockCount;
8154         StopwatchTimer mWifiMulticastTimer;
8155 
8156         StopwatchTimer mAudioTurnedOnTimer;
8157         StopwatchTimer mVideoTurnedOnTimer;
8158         StopwatchTimer mFlashlightTurnedOnTimer;
8159         StopwatchTimer mCameraTurnedOnTimer;
8160         StopwatchTimer mForegroundActivityTimer;
8161         StopwatchTimer mForegroundServiceTimer;
8162         /** Total time spent by the uid holding any partial wakelocks. */
8163         DualTimer mAggregatedPartialWakelockTimer;
8164         DualTimer mBluetoothScanTimer;
8165         DualTimer mBluetoothUnoptimizedScanTimer;
8166         Counter mBluetoothScanResultCounter;
8167         Counter mBluetoothScanResultBgCounter;
8168 
8169         int mProcessState = Uid.PROCESS_STATE_NONEXISTENT;
8170         StopwatchTimer[] mProcessStateTimer;
8171 
8172         boolean mInForegroundService = false;
8173 
8174         BatchTimer mVibratorOnTimer;
8175 
8176         Counter[] mUserActivityCounters;
8177 
8178         LongSamplingCounter[] mNetworkByteActivityCounters;
8179         LongSamplingCounter[] mNetworkPacketActivityCounters;
8180         TimeMultiStateCounter mMobileRadioActiveTime;
8181         LongSamplingCounter mMobileRadioActiveCount;
8182 
8183         /**
8184          * How many times this UID woke up the Application Processor due to a Mobile radio packet.
8185          */
8186         private LongSamplingCounter mMobileRadioApWakeupCount;
8187 
8188         /**
8189          * How many times this UID woke up the Application Processor due to a Wifi packet.
8190          */
8191         private LongSamplingCounter mWifiRadioApWakeupCount;
8192 
8193         /**
8194          * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
8195          * Can be null if the UID has had no such activity.
8196          */
8197         private ControllerActivityCounterImpl mWifiControllerActivity;
8198 
8199         /**
8200          * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
8201          * Can be null if the UID has had no such activity.
8202          */
8203         private ControllerActivityCounterImpl mBluetoothControllerActivity;
8204 
8205         /**
8206          * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
8207          * Can be null if the UID has had no such activity.
8208          */
8209         private ControllerActivityCounterImpl mModemControllerActivity;
8210 
8211         /**
8212          * The CPU times we had at the last history details update.
8213          */
8214         long mLastStepUserTimeMs;
8215         long mLastStepSystemTimeMs;
8216         long mCurStepUserTimeMs;
8217         long mCurStepSystemTimeMs;
8218 
8219         LongSamplingCounter mUserCpuTime;
8220         LongSamplingCounter mSystemCpuTime;
8221         LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
8222         TimeMultiStateCounter mCpuActiveTimeMs;
8223 
8224         LongSamplingCounterArray mCpuFreqTimeMs;
8225         LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
8226         LongSamplingCounterArray mCpuClusterTimesMs;
8227 
8228         TimeInFreqMultiStateCounter mProcStateTimeMs;
8229         TimeInFreqMultiStateCounter mProcStateScreenOffTimeMs;
8230 
8231         SparseArray<ChildUid> mChildUids;
8232 
8233         /**
8234          * The statistics we have collected for this uid's wake locks.
8235          */
8236         final OverflowArrayMap<Wakelock> mWakelockStats;
8237 
8238         /**
8239          * The statistics we have collected for this uid's syncs.
8240          */
8241         final OverflowArrayMap<DualTimer> mSyncStats;
8242 
8243         /**
8244          * The statistics we have collected for this uid's jobs.
8245          */
8246         final OverflowArrayMap<DualTimer> mJobStats;
8247 
8248         /**
8249          * Count of the jobs that have completed and the reasons why they completed.
8250          */
8251         final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
8252 
8253         /**
8254          * Count of app launch events that had associated deferred job counts or info about
8255          * last time a job was run.
8256          */
8257         Counter mJobsDeferredEventCount;
8258 
8259         /**
8260          * Count of deferred jobs that were pending when the app was launched or brought to
8261          * the foreground through a user interaction.
8262          */
8263         Counter mJobsDeferredCount;
8264 
8265         /**
8266          * Sum of time since the last time a job was run for this app before it was launched.
8267          */
8268         LongSamplingCounter mJobsFreshnessTimeMs;
8269 
8270         /**
8271          * Array of counts of instances where the time since the last job was run for the app
8272          * fell within one of the thresholds in {@link #JOB_FRESHNESS_BUCKETS}.
8273          */
8274         final Counter[] mJobsFreshnessBuckets;
8275 
8276         /**
8277          * The statistics we have collected for this uid's sensor activations.
8278          */
8279         final SparseArray<Sensor> mSensorStats = new SparseArray<>();
8280 
8281         /**
8282          * The statistics we have collected for this uid's processes.
8283          */
8284         final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
8285 
8286         /**
8287          * The statistics we have collected for this uid's processes.
8288          */
8289         final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
8290 
8291         /**
8292          * The transient wake stats we have collected for this uid's pids.
8293          */
8294         final SparseArray<Pid> mPids = new SparseArray<>();
8295 
8296         /**
8297          * Grand total of system server binder calls made by this uid.
8298          */
8299         private long mBinderCallCount;
8300 
8301         /**
8302          * Detailed information about system server binder calls made by this uid.
8303          */
8304         private final ArraySet<BinderCallStats> mBinderCallStats = new ArraySet<>();
8305 
8306         /**
8307          * EnergyConsumer consumption by this uid while on battery.
8308          * Its '<b>custom</b> power buckets' correspond to the
8309          * {@link android.hardware.power.stats.EnergyConsumer.ordinal}s of (custom) energy consumer
8310          * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
8311          *
8312          * Will be null if energy consumer data is completely unavailable (in which case
8313          * {@link #mGlobalEnergyConsumerStats} will also be null) or if the power usage by this uid
8314          * is 0 for every bucket.
8315          */
8316         private EnergyConsumerStats mUidEnergyConsumerStats;
8317 
8318         /**
8319          * Estimated total time spent by the system server handling requests from this uid.
8320          */
8321         private long mSystemServiceTimeUs;
8322 
8323         /**
8324          * Estimated proportion of system server binder call CPU cost for this uid.
8325          */
8326         private double mProportionalSystemServiceUsage;
8327 
Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs)8328         public Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs) {
8329             mBsi = bsi;
8330             mUid = uid;
8331 
8332             /* Observer list of TimeBase object in Uid is short */
8333             mOnBatteryBackgroundTimeBase = new TimeBase(false);
8334             mOnBatteryBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
8335             /* Observer list of TimeBase object in Uid is short */
8336             mOnBatteryScreenOffBackgroundTimeBase = new TimeBase(false);
8337             mOnBatteryScreenOffBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
8338 
8339             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8340             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8341             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase);
8342 
8343             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
8344                 @Override public Wakelock instantiateObject() {
8345                     return new Wakelock(mBsi, Uid.this);
8346                 }
8347             };
8348             mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
8349                 @Override public DualTimer instantiateObject() {
8350                     return new DualTimer(mBsi.mClock, Uid.this, SYNC, null,
8351                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8352                 }
8353             };
8354             mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
8355                 @Override public DualTimer instantiateObject() {
8356                     return new DualTimer(mBsi.mClock, Uid.this, JOB, null,
8357                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8358                 }
8359             };
8360 
8361             mWifiRunningTimer = new StopwatchTimer(mBsi.mClock, this, WIFI_RUNNING,
8362                     mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
8363             mFullWifiLockTimer = new StopwatchTimer(mBsi.mClock, this, FULL_WIFI_LOCK,
8364                     mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
8365             mWifiScanTimer = new DualTimer(mBsi.mClock, this, WIFI_SCAN,
8366                     mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8367             mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
8368             mWifiMulticastTimer = new StopwatchTimer(mBsi.mClock, this, WIFI_MULTICAST_ENABLED,
8369                     mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
8370             mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
8371             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase);
8372             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase);
8373             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8374             mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length];
8375         }
8376 
8377         @GuardedBy("mBsi")
8378         @VisibleForTesting
setProcessStateForTest(int procState, long elapsedTimeMs)8379         public void setProcessStateForTest(int procState, long elapsedTimeMs) {
8380             mProcessState = procState;
8381             getProcStateTimeCounter(elapsedTimeMs).setState(procState, elapsedTimeMs);
8382             getProcStateScreenOffTimeCounter(elapsedTimeMs).setState(procState, elapsedTimeMs);
8383             final int batteryConsumerProcessState =
8384                     mapUidProcessStateToBatteryConsumerProcessState(procState);
8385             getCpuActiveTimeCounter().setState(batteryConsumerProcessState, elapsedTimeMs);
8386             getMobileRadioActiveTimeCounter().setState(batteryConsumerProcessState, elapsedTimeMs);
8387             final ControllerActivityCounterImpl wifiControllerActivity =
8388                     getWifiControllerActivity();
8389             if (wifiControllerActivity != null) {
8390                 wifiControllerActivity.setState(batteryConsumerProcessState, elapsedTimeMs);
8391             }
8392             final ControllerActivityCounterImpl bluetoothControllerActivity =
8393                     getBluetoothControllerActivity();
8394             if (bluetoothControllerActivity != null) {
8395                 bluetoothControllerActivity.setState(batteryConsumerProcessState, elapsedTimeMs);
8396             }
8397             final EnergyConsumerStats energyStats =
8398                     getOrCreateEnergyConsumerStatsIfSupportedLocked();
8399             if (energyStats != null) {
8400                 energyStats.setState(batteryConsumerProcessState, elapsedTimeMs);
8401             }
8402         }
8403 
8404         @Override
getCpuFreqTimes(int which)8405         public long[] getCpuFreqTimes(int which) {
8406             return nullIfAllZeros(mCpuFreqTimeMs, which);
8407         }
8408 
8409         @Override
getScreenOffCpuFreqTimes(int which)8410         public long[] getScreenOffCpuFreqTimes(int which) {
8411             return nullIfAllZeros(mScreenOffCpuFreqTimeMs, which);
8412         }
8413 
getCpuActiveTimeCounter()8414         private TimeMultiStateCounter getCpuActiveTimeCounter() {
8415             if (mCpuActiveTimeMs == null) {
8416                 final long timestampMs = mBsi.mClock.elapsedRealtime();
8417                 mCpuActiveTimeMs = new TimeMultiStateCounter(mBsi.mOnBatteryTimeBase,
8418                         BatteryConsumer.PROCESS_STATE_COUNT, timestampMs);
8419                 mCpuActiveTimeMs.setState(
8420                         mapUidProcessStateToBatteryConsumerProcessState(mProcessState),
8421                         timestampMs);
8422             }
8423             return mCpuActiveTimeMs;
8424         }
8425 
8426         @Override
getCpuActiveTime()8427         public long getCpuActiveTime() {
8428             if (mCpuActiveTimeMs == null) {
8429                 return 0;
8430             }
8431 
8432             long activeTime = 0;
8433             for (int procState = 0; procState < BatteryConsumer.PROCESS_STATE_COUNT; procState++) {
8434                 activeTime += mCpuActiveTimeMs.getCountForProcessState(procState);
8435             }
8436             return activeTime;
8437         }
8438 
8439         @Override
getCpuActiveTime(int procState)8440         public long getCpuActiveTime(int procState) {
8441             if (mCpuActiveTimeMs == null
8442                     || procState < 0 || procState >= BatteryConsumer.PROCESS_STATE_COUNT) {
8443                 return 0;
8444             }
8445 
8446             return mCpuActiveTimeMs.getCountForProcessState(procState);
8447         }
8448 
8449         @Override
getCpuClusterTimes()8450         public long[] getCpuClusterTimes() {
8451             return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
8452         }
8453 
8454         @GuardedBy("mBsi")
8455         @Override
getCpuFreqTimes(long[] timesInFreqMs, int procState)8456         public boolean getCpuFreqTimes(long[] timesInFreqMs, int procState) {
8457             if (procState < 0 || procState >= NUM_PROCESS_STATE) {
8458                 return false;
8459             }
8460             if (mProcStateTimeMs == null) {
8461                 return false;
8462             }
8463             if (!mBsi.mPerProcStateCpuTimesAvailable) {
8464                 mProcStateTimeMs = null;
8465                 return false;
8466             }
8467             return mProcStateTimeMs.getCountsLocked(timesInFreqMs, procState);
8468         }
8469 
8470         @GuardedBy("mBsi")
8471         @Override
getScreenOffCpuFreqTimes(long[] timesInFreqMs, int procState)8472         public boolean getScreenOffCpuFreqTimes(long[] timesInFreqMs, int procState) {
8473             if (procState < 0 || procState >= NUM_PROCESS_STATE) {
8474                 return false;
8475             }
8476             if (mProcStateScreenOffTimeMs == null) {
8477                 return false;
8478             }
8479             if (!mBsi.mPerProcStateCpuTimesAvailable) {
8480                 mProcStateScreenOffTimeMs = null;
8481                 return false;
8482             }
8483             return mProcStateScreenOffTimeMs.getCountsLocked(timesInFreqMs, procState);
8484         }
8485 
getBinderCallCount()8486         public long getBinderCallCount() {
8487             return mBinderCallCount;
8488         }
8489 
8490         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
getBinderCallStats()8491         public ArraySet<BinderCallStats> getBinderCallStats() {
8492             return mBinderCallStats;
8493         }
8494 
8495         @Override
getProportionalSystemServiceUsage()8496         public  double getProportionalSystemServiceUsage() {
8497             return mProportionalSystemServiceUsage;
8498         }
8499 
8500         /**
8501          * Adds isolated UID to the list of children.
8502          */
addIsolatedUid(int isolatedUid)8503         public void addIsolatedUid(int isolatedUid) {
8504             if (mChildUids == null) {
8505                 mChildUids = new SparseArray<>();
8506             } else if (mChildUids.indexOfKey(isolatedUid) >= 0) {
8507                 return;
8508             }
8509             mChildUids.put(isolatedUid, new ChildUid());
8510         }
8511 
8512         /**
8513          * Removes isolated UID from the list of children.
8514          */
removeIsolatedUid(int isolatedUid)8515         public void removeIsolatedUid(int isolatedUid) {
8516             final int idx = mChildUids == null ? -1 : mChildUids.indexOfKey(isolatedUid);
8517             if (idx < 0) {
8518                 return;
8519             }
8520             mChildUids.remove(idx);
8521         }
8522 
8523         @GuardedBy("mBsi")
getChildUid(int childUid)8524         ChildUid getChildUid(int childUid) {
8525             return mChildUids == null ? null : mChildUids.get(childUid);
8526         }
8527 
nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which)8528         private long[] nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which) {
8529             if (cpuTimesMs == null) {
8530                 return null;
8531             }
8532             final long[] counts = cpuTimesMs.getCountsLocked(which);
8533             if (counts == null) {
8534                 return null;
8535             }
8536             // Return counts only if at least one of the elements is non-zero.
8537             for (int i = counts.length - 1; i >= 0; --i) {
8538                 if (counts[i] != 0) {
8539                     return counts;
8540                 }
8541             }
8542             return null;
8543         }
8544 
8545         @GuardedBy("mBsi")
ensureMultiStateCounters(long timestampMs)8546         private void ensureMultiStateCounters(long timestampMs) {
8547             if (mBsi.mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
8548                 throw new IllegalStateException("Multi-state counters used in streamlined mode");
8549             }
8550 
8551             if (mProcStateTimeMs == null) {
8552                 mProcStateTimeMs =
8553                         new TimeInFreqMultiStateCounter(mBsi.mOnBatteryTimeBase,
8554                                 PROC_STATE_TIME_COUNTER_STATE_COUNT,
8555                                 mBsi.mCpuScalingPolicies.getScalingStepCount(),
8556                                 timestampMs);
8557             }
8558             if (mProcStateScreenOffTimeMs == null) {
8559                 mProcStateScreenOffTimeMs =
8560                         new TimeInFreqMultiStateCounter(mBsi.mOnBatteryScreenOffTimeBase,
8561                                 PROC_STATE_TIME_COUNTER_STATE_COUNT,
8562                                 mBsi.mCpuScalingPolicies.getScalingStepCount(),
8563                                 timestampMs);
8564             }
8565         }
8566 
8567         @GuardedBy("mBsi")
getProcStateTimeCounter(long timestampMs)8568         private TimeInFreqMultiStateCounter getProcStateTimeCounter(long timestampMs) {
8569             ensureMultiStateCounters(timestampMs);
8570             return mProcStateTimeMs;
8571         }
8572 
8573         @GuardedBy("mBsi")
getProcStateScreenOffTimeCounter(long timestampMs)8574         private TimeInFreqMultiStateCounter getProcStateScreenOffTimeCounter(long timestampMs) {
8575             ensureMultiStateCounters(timestampMs);
8576             return mProcStateScreenOffTimeMs;
8577         }
8578 
8579         @Override
getAggregatedPartialWakelockTimer()8580         public Timer getAggregatedPartialWakelockTimer() {
8581             return mAggregatedPartialWakelockTimer;
8582         }
8583 
8584         @Override
getWakelockStats()8585         public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
8586             return mWakelockStats.getMap();
8587         }
8588 
8589         @Override
getMulticastWakelockStats()8590         public Timer getMulticastWakelockStats() {
8591             return mWifiMulticastTimer;
8592         }
8593 
8594         @Override
getSyncStats()8595         public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
8596             return mSyncStats.getMap();
8597         }
8598 
8599         @Override
getJobStats()8600         public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
8601             return mJobStats.getMap();
8602         }
8603 
8604         @Override
getJobCompletionStats()8605         public ArrayMap<String, SparseIntArray> getJobCompletionStats() {
8606             return mJobCompletions;
8607         }
8608 
8609         @Override
getSensorStats()8610         public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
8611             return mSensorStats;
8612         }
8613 
8614         @Override
getProcessStats()8615         public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
8616             return mProcessStats;
8617         }
8618 
8619         @Override
getPackageStats()8620         public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
8621             return mPackageStats;
8622         }
8623 
8624         @Override
getUid()8625         public int getUid() {
8626             return mUid;
8627         }
8628 
8629         @Override
noteWifiRunningLocked(long elapsedRealtimeMs)8630         public void noteWifiRunningLocked(long elapsedRealtimeMs) {
8631             if (!mWifiRunning) {
8632                 mWifiRunning = true;
8633                 if (mWifiRunningTimer == null) {
8634                     mWifiRunningTimer = new StopwatchTimer(mBsi.mClock, Uid.this, WIFI_RUNNING,
8635                             mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
8636                 }
8637                 mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
8638             }
8639         }
8640 
8641         @Override
noteWifiStoppedLocked(long elapsedRealtimeMs)8642         public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
8643             if (mWifiRunning) {
8644                 mWifiRunning = false;
8645                 mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
8646             }
8647         }
8648 
8649         @Override
noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs)8650         public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
8651             if (!mFullWifiLockOut) {
8652                 mFullWifiLockOut = true;
8653                 if (mFullWifiLockTimer == null) {
8654                     mFullWifiLockTimer = new StopwatchTimer(mBsi.mClock, Uid.this, FULL_WIFI_LOCK,
8655                             mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
8656                 }
8657                 mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
8658             }
8659         }
8660 
8661         @Override
noteFullWifiLockReleasedLocked(long elapsedRealtimeMs)8662         public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
8663             if (mFullWifiLockOut) {
8664                 mFullWifiLockOut = false;
8665                 mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
8666             }
8667         }
8668 
8669         @Override
noteWifiScanStartedLocked(long elapsedRealtimeMs)8670         public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
8671             if (!mWifiScanStarted) {
8672                 mWifiScanStarted = true;
8673                 if (mWifiScanTimer == null) {
8674                     mWifiScanTimer = new DualTimer(mBsi.mClock, Uid.this, WIFI_SCAN,
8675                             mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase,
8676                             mOnBatteryBackgroundTimeBase);
8677                 }
8678                 mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
8679             }
8680         }
8681 
8682         @Override
noteWifiScanStoppedLocked(long elapsedRealtimeMs)8683         public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
8684             if (mWifiScanStarted) {
8685                 mWifiScanStarted = false;
8686                 mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
8687             }
8688         }
8689 
8690         @Override
noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs)8691         public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
8692             int bin = 0;
8693             while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
8694                 csph = csph >> 3;
8695                 bin++;
8696             }
8697 
8698             if (mWifiBatchedScanBinStarted == bin) return;
8699 
8700             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
8701                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
8702                         stopRunningLocked(elapsedRealtimeMs);
8703             }
8704             mWifiBatchedScanBinStarted = bin;
8705             if (mWifiBatchedScanTimer[bin] == null) {
8706                 makeWifiBatchedScanBin(bin, null);
8707             }
8708             mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
8709         }
8710 
8711         @Override
noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs)8712         public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
8713             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
8714                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
8715                         stopRunningLocked(elapsedRealtimeMs);
8716                 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
8717             }
8718         }
8719 
8720         @Override
noteWifiMulticastEnabledLocked(long elapsedRealtimeMs)8721         public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
8722             if (mWifiMulticastWakelockCount == 0) {
8723                 if (mWifiMulticastTimer == null) {
8724                     mWifiMulticastTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
8725                             WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
8726                 }
8727                 mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
8728             }
8729             mWifiMulticastWakelockCount++;
8730         }
8731 
8732         @Override
noteWifiMulticastDisabledLocked(long elapsedRealtimeMs)8733         public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
8734             if (mWifiMulticastWakelockCount == 0) {
8735                 return;
8736             }
8737 
8738             mWifiMulticastWakelockCount--;
8739             if (mWifiMulticastWakelockCount == 0) {
8740                 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
8741             }
8742         }
8743 
8744         @Override
getWifiControllerActivity()8745         public ControllerActivityCounterImpl getWifiControllerActivity() {
8746             return mWifiControllerActivity;
8747         }
8748 
8749         @Override
getBluetoothControllerActivity()8750         public ControllerActivityCounterImpl getBluetoothControllerActivity() {
8751             return mBluetoothControllerActivity;
8752         }
8753 
8754         @Override
getModemControllerActivity()8755         public ControllerActivityCounter getModemControllerActivity() {
8756             return mModemControllerActivity;
8757         }
8758 
getOrCreateWifiControllerActivityLocked()8759         public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
8760             if (mWifiControllerActivity == null) {
8761                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
8762                         mBsi.mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
8763             }
8764             return mWifiControllerActivity;
8765         }
8766 
getOrCreateBluetoothControllerActivityLocked()8767         public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
8768             if (mBluetoothControllerActivity == null) {
8769                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
8770                         mBsi.mOnBatteryTimeBase, NUM_BT_TX_LEVELS);
8771             }
8772             return mBluetoothControllerActivity;
8773         }
8774 
getOrCreateModemControllerActivityLocked()8775         public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
8776             if (mModemControllerActivity == null) {
8777                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
8778                         mBsi.mOnBatteryTimeBase, mBsi.MODEM_TX_POWER_LEVEL_COUNT);
8779             }
8780             return mModemControllerActivity;
8781         }
8782 
8783         @GuardedBy("mBsi")
getOrCreateEnergyConsumerStatsLocked()8784         private EnergyConsumerStats getOrCreateEnergyConsumerStatsLocked() {
8785             if (mUidEnergyConsumerStats == null) {
8786                 mUidEnergyConsumerStats = new EnergyConsumerStats(mBsi.mEnergyConsumerStatsConfig);
8787             }
8788             return mUidEnergyConsumerStats;
8789         }
8790 
8791         @GuardedBy("mBsi")
getOrCreateEnergyConsumerStatsIfSupportedLocked()8792         private EnergyConsumerStats getOrCreateEnergyConsumerStatsIfSupportedLocked() {
8793             if (mUidEnergyConsumerStats == null && mBsi.mEnergyConsumerStatsConfig != null) {
8794                 mUidEnergyConsumerStats = new EnergyConsumerStats(mBsi.mEnergyConsumerStatsConfig);
8795             }
8796             return mUidEnergyConsumerStats;
8797         }
8798 
8799         /** Adds the given charge to the given standard power bucket for this uid. */
8800         @GuardedBy("mBsi")
addChargeToStandardBucketLocked(long chargeDeltaUC, @StandardPowerBucket int powerBucket, long timestampMs)8801         private void addChargeToStandardBucketLocked(long chargeDeltaUC,
8802                 @StandardPowerBucket int powerBucket, long timestampMs) {
8803             final EnergyConsumerStats energyConsumerStats =
8804                     getOrCreateEnergyConsumerStatsLocked();
8805             energyConsumerStats.updateStandardBucket(powerBucket, chargeDeltaUC, timestampMs);
8806         }
8807 
8808         /** Adds the given charge to the given custom power bucket for this uid. */
8809         @GuardedBy("mBsi")
addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket)8810         private void addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket) {
8811             getOrCreateEnergyConsumerStatsLocked().updateCustomBucket(powerBucket, chargeDeltaUC,
8812                     mBsi.mClock.elapsedRealtime());
8813         }
8814 
8815         /**
8816          * Returns the battery consumption (in microcoulomb) of this uid for a standard power bucket
8817          * of interest.
8818          * @param bucket standard power bucket of interest
8819          * @return consumption (in microcolombs) used by this uid for this power bucket
8820          */
8821         @GuardedBy("mBsi")
getEnergyConsumptionUC(@tandardPowerBucket int bucket)8822         public long getEnergyConsumptionUC(@StandardPowerBucket int bucket) {
8823             if (mBsi.mGlobalEnergyConsumerStats == null
8824                     || !mBsi.mGlobalEnergyConsumerStats.isStandardBucketSupported(bucket)) {
8825                 return POWER_DATA_UNAVAILABLE;
8826             }
8827             if (mUidEnergyConsumerStats == null) {
8828                 return 0L; // It is supported, but was never filled, so it must be 0
8829             }
8830             return mUidEnergyConsumerStats.getAccumulatedStandardBucketCharge(bucket);
8831         }
8832 
8833         /**
8834          * Returns the battery consumption (in microcoulombs) of this uid for a standard power
8835          * bucket and a process state, such as Uid.PROCESS_STATE_TOP.
8836          */
8837         @GuardedBy("mBsi")
getEnergyConsumptionUC(@tandardPowerBucket int bucket, int processState)8838         public long getEnergyConsumptionUC(@StandardPowerBucket int bucket,
8839                 int processState) {
8840             if (mBsi.mGlobalEnergyConsumerStats == null
8841                     || !mBsi.mGlobalEnergyConsumerStats.isStandardBucketSupported(bucket)) {
8842                 return POWER_DATA_UNAVAILABLE;
8843             }
8844             if (mUidEnergyConsumerStats == null) {
8845                 return 0L; // It is supported, but was never filled, so it must be 0
8846             }
8847             return mUidEnergyConsumerStats.getAccumulatedStandardBucketCharge(bucket, processState);
8848         }
8849 
8850         @GuardedBy("mBsi")
8851         @Override
getCustomEnergyConsumerBatteryConsumptionUC()8852         public long[] getCustomEnergyConsumerBatteryConsumptionUC() {
8853             if (mBsi.mGlobalEnergyConsumerStats == null) {
8854                 return null;
8855             }
8856             if (mUidEnergyConsumerStats == null) {
8857                 // Custom buckets may exist. But all values for this uid are 0 so we report all 0s.
8858                 return new long[mBsi.mGlobalEnergyConsumerStats.getNumberCustomPowerBuckets()];
8859             }
8860             return mUidEnergyConsumerStats.getAccumulatedCustomBucketCharges();
8861         }
8862 
8863         @GuardedBy("mBsi")
8864         @Override
getBluetoothEnergyConsumptionUC()8865         public long getBluetoothEnergyConsumptionUC() {
8866             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_BLUETOOTH);
8867         }
8868 
8869         @GuardedBy("mBsi")
8870         @Override
getBluetoothEnergyConsumptionUC( @atteryConsumer.ProcessState int processState)8871         public long getBluetoothEnergyConsumptionUC(
8872                 @BatteryConsumer.ProcessState int processState) {
8873             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_BLUETOOTH,
8874                     processState);
8875         }
8876 
8877         @GuardedBy("mBsi")
8878         @Override
getCpuEnergyConsumptionUC()8879         public long getCpuEnergyConsumptionUC() {
8880             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CPU);
8881         }
8882 
8883         @GuardedBy("mBsi")
8884         @Override
getCpuEnergyConsumptionUC( @atteryConsumer.ProcessState int processState)8885         public long getCpuEnergyConsumptionUC(
8886                 @BatteryConsumer.ProcessState int processState) {
8887             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CPU,
8888                     processState);
8889         }
8890 
8891         @GuardedBy("mBsi")
8892         @Override
getGnssEnergyConsumptionUC()8893         public long getGnssEnergyConsumptionUC() {
8894             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_GNSS);
8895         }
8896 
8897         @GuardedBy("mBsi")
8898         @Override
getMobileRadioEnergyConsumptionUC()8899         public long getMobileRadioEnergyConsumptionUC() {
8900             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO);
8901         }
8902 
8903         @GuardedBy("mBsi")
8904         @Override
getMobileRadioEnergyConsumptionUC(int processState)8905         public long getMobileRadioEnergyConsumptionUC(int processState) {
8906             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO,
8907                     processState);
8908         }
8909 
8910         @GuardedBy("mBsi")
8911         @Override
getScreenOnEnergyConsumptionUC()8912         public long getScreenOnEnergyConsumptionUC() {
8913             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_SCREEN_ON);
8914         }
8915 
8916         @GuardedBy("mBsi")
8917         @Override
getWifiEnergyConsumptionUC()8918         public long getWifiEnergyConsumptionUC() {
8919             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_WIFI);
8920         }
8921 
8922         @GuardedBy("mBsi")
8923         @Override
getWifiEnergyConsumptionUC(int processState)8924         public long getWifiEnergyConsumptionUC(int processState) {
8925             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_WIFI,
8926                     processState);
8927         }
8928 
8929         @GuardedBy("mBsi")
8930         @Override
getCameraEnergyConsumptionUC()8931         public long getCameraEnergyConsumptionUC() {
8932             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CAMERA);
8933         }
8934 
8935         /**
8936          * Gets the minimum of the uid's foreground activity time and its PROCESS_STATE_TOP time
8937          * since last marked. Also sets the mark time for both these timers.
8938          *
8939          * @see CpuPowerCalculator
8940          *
8941          * @param doCalc if true, then calculate the minimum; else don't bother and return 0. Either
8942          *               way, the mark is set.
8943          */
markProcessForegroundTimeUs(long elapsedRealtimeMs, boolean doCalc)8944         private long markProcessForegroundTimeUs(long elapsedRealtimeMs,
8945                 boolean doCalc) {
8946             long fgTimeUs = 0;
8947             final StopwatchTimer fgTimer = mForegroundActivityTimer;
8948             if (fgTimer != null) {
8949                 if (doCalc) fgTimeUs = fgTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
8950                 fgTimer.setMark(elapsedRealtimeMs);
8951             }
8952 
8953             long topTimeUs = 0;
8954             final StopwatchTimer topTimer = mProcessStateTimer[PROCESS_STATE_TOP];
8955             if (topTimer != null) {
8956                 if (doCalc) topTimeUs = topTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
8957                 topTimer.setMark(elapsedRealtimeMs);
8958             }
8959 
8960             // Return the min of the two
8961             return (topTimeUs < fgTimeUs) ? topTimeUs : fgTimeUs;
8962         }
8963 
8964 
8965         /**
8966          * Gets the uid's time spent using the GNSS since last marked. Also sets the mark time for
8967          * the GNSS timer.
8968          */
markGnssTimeUs(long elapsedRealtimeMs)8969         private long markGnssTimeUs(long elapsedRealtimeMs) {
8970             final Sensor sensor = mSensorStats.get(Sensor.GPS);
8971             if (sensor == null) {
8972                 return 0;
8973             }
8974 
8975             final StopwatchTimer timer = sensor.mTimer;
8976             if (timer == null) {
8977                 return 0;
8978             }
8979 
8980             final long gnssTimeUs = timer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
8981             timer.setMark(elapsedRealtimeMs);
8982             return gnssTimeUs;
8983         }
8984 
8985         /**
8986          * Gets the uid's time spent using the camera since last marked. Also sets the mark time for
8987          * the camera timer.
8988          */
markCameraTimeUs(long elapsedRealtimeMs)8989         private long markCameraTimeUs(long elapsedRealtimeMs) {
8990             final StopwatchTimer timer = mCameraTurnedOnTimer;
8991             if (timer == null) {
8992                 return 0;
8993             }
8994             final long cameraTimeUs = timer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
8995             timer.setMark(elapsedRealtimeMs);
8996             return cameraTimeUs;
8997         }
8998 
createAudioTurnedOnTimerLocked()8999         public StopwatchTimer createAudioTurnedOnTimerLocked() {
9000             if (mAudioTurnedOnTimer == null) {
9001                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, AUDIO_TURNED_ON,
9002                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
9003             }
9004             return mAudioTurnedOnTimer;
9005         }
9006 
noteAudioTurnedOnLocked(long elapsedRealtimeMs)9007         public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
9008             createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
9009         }
9010 
noteAudioTurnedOffLocked(long elapsedRealtimeMs)9011         public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
9012             if (mAudioTurnedOnTimer != null) {
9013                 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
9014             }
9015         }
9016 
noteResetAudioLocked(long elapsedRealtimeMs)9017         public void noteResetAudioLocked(long elapsedRealtimeMs) {
9018             if (mAudioTurnedOnTimer != null) {
9019                 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
9020             }
9021         }
9022 
createVideoTurnedOnTimerLocked()9023         public StopwatchTimer createVideoTurnedOnTimerLocked() {
9024             if (mVideoTurnedOnTimer == null) {
9025                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, VIDEO_TURNED_ON,
9026                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
9027             }
9028             return mVideoTurnedOnTimer;
9029         }
9030 
noteVideoTurnedOnLocked(long elapsedRealtimeMs)9031         public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
9032             createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
9033         }
9034 
noteVideoTurnedOffLocked(long elapsedRealtimeMs)9035         public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
9036             if (mVideoTurnedOnTimer != null) {
9037                 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
9038             }
9039         }
9040 
noteResetVideoLocked(long elapsedRealtimeMs)9041         public void noteResetVideoLocked(long elapsedRealtimeMs) {
9042             if (mVideoTurnedOnTimer != null) {
9043                 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
9044             }
9045         }
9046 
createFlashlightTurnedOnTimerLocked()9047         public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
9048             if (mFlashlightTurnedOnTimer == null) {
9049                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
9050                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
9051             }
9052             return mFlashlightTurnedOnTimer;
9053         }
9054 
noteFlashlightTurnedOnLocked(long elapsedRealtimeMs)9055         public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
9056             createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
9057         }
9058 
noteFlashlightTurnedOffLocked(long elapsedRealtimeMs)9059         public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
9060             if (mFlashlightTurnedOnTimer != null) {
9061                 mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
9062             }
9063         }
9064 
noteResetFlashlightLocked(long elapsedRealtimeMs)9065         public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
9066             if (mFlashlightTurnedOnTimer != null) {
9067                 mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
9068             }
9069         }
9070 
createCameraTurnedOnTimerLocked()9071         public StopwatchTimer createCameraTurnedOnTimerLocked() {
9072             if (mCameraTurnedOnTimer == null) {
9073                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, CAMERA_TURNED_ON,
9074                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
9075             }
9076             return mCameraTurnedOnTimer;
9077         }
9078 
noteCameraTurnedOnLocked(long elapsedRealtimeMs)9079         public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
9080             createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
9081         }
9082 
noteCameraTurnedOffLocked(long elapsedRealtimeMs)9083         public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
9084             if (mCameraTurnedOnTimer != null) {
9085                 mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
9086             }
9087         }
9088 
noteResetCameraLocked(long elapsedRealtimeMs)9089         public void noteResetCameraLocked(long elapsedRealtimeMs) {
9090             if (mCameraTurnedOnTimer != null) {
9091                 mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
9092             }
9093         }
9094 
createForegroundActivityTimerLocked()9095         public StopwatchTimer createForegroundActivityTimerLocked() {
9096             if (mForegroundActivityTimer == null) {
9097                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
9098                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
9099             }
9100             return mForegroundActivityTimer;
9101         }
9102 
createForegroundServiceTimerLocked()9103         public StopwatchTimer createForegroundServiceTimerLocked() {
9104             if (mForegroundServiceTimer == null) {
9105                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
9106                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase);
9107             }
9108             return mForegroundServiceTimer;
9109         }
9110 
createAggregatedPartialWakelockTimerLocked()9111         public DualTimer createAggregatedPartialWakelockTimerLocked() {
9112             if (mAggregatedPartialWakelockTimer == null) {
9113                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClock, this,
9114                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
9115                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase);
9116             }
9117             return mAggregatedPartialWakelockTimer;
9118         }
9119 
createBluetoothScanTimerLocked()9120         public DualTimer createBluetoothScanTimerLocked() {
9121             if (mBluetoothScanTimer == null) {
9122                 mBluetoothScanTimer = new DualTimer(mBsi.mClock, Uid.this, BLUETOOTH_SCAN_ON,
9123                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
9124                         mOnBatteryBackgroundTimeBase);
9125             }
9126             return mBluetoothScanTimer;
9127         }
9128 
createBluetoothUnoptimizedScanTimerLocked()9129         public DualTimer createBluetoothUnoptimizedScanTimerLocked() {
9130             if (mBluetoothUnoptimizedScanTimer == null) {
9131                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClock, Uid.this,
9132                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
9133                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
9134             }
9135             return mBluetoothUnoptimizedScanTimer;
9136         }
9137 
noteBluetoothScanStartedLocked(long elapsedRealtimeMs, boolean isUnoptimized)9138         public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs,
9139                 boolean isUnoptimized) {
9140             createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
9141             if (isUnoptimized) {
9142                 createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
9143             }
9144         }
9145 
noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized)9146         public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
9147             if (mBluetoothScanTimer != null) {
9148                 mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
9149             }
9150             if (isUnoptimized && mBluetoothUnoptimizedScanTimer != null) {
9151                 mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs);
9152             }
9153         }
9154 
noteResetBluetoothScanLocked(long elapsedRealtimeMs)9155         public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
9156             if (mBluetoothScanTimer != null) {
9157                 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
9158             }
9159             if (mBluetoothUnoptimizedScanTimer != null) {
9160                 mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
9161             }
9162         }
9163 
createBluetoothScanResultCounterLocked()9164         public Counter createBluetoothScanResultCounterLocked() {
9165             if (mBluetoothScanResultCounter == null) {
9166                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase);
9167             }
9168             return mBluetoothScanResultCounter;
9169         }
9170 
createBluetoothScanResultBgCounterLocked()9171         public Counter createBluetoothScanResultBgCounterLocked() {
9172             if (mBluetoothScanResultBgCounter == null) {
9173                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase);
9174             }
9175             return mBluetoothScanResultBgCounter;
9176         }
9177 
noteBluetoothScanResultsLocked(int numNewResults)9178         public void noteBluetoothScanResultsLocked(int numNewResults) {
9179             createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
9180             // Uses background timebase, so the count will only be incremented if uid in background.
9181             createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults);
9182         }
9183 
9184         @Override
noteActivityResumedLocked(long elapsedRealtimeMs)9185         public void noteActivityResumedLocked(long elapsedRealtimeMs) {
9186             // We always start, since we want multiple foreground PIDs to nest
9187             createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
9188         }
9189 
9190         @Override
noteActivityPausedLocked(long elapsedRealtimeMs)9191         public void noteActivityPausedLocked(long elapsedRealtimeMs) {
9192             if (mForegroundActivityTimer != null) {
9193                 mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
9194             }
9195         }
9196 
noteForegroundServiceResumedLocked(long elapsedRealtimeMs)9197         public void noteForegroundServiceResumedLocked(long elapsedRealtimeMs) {
9198             createForegroundServiceTimerLocked().startRunningLocked(elapsedRealtimeMs);
9199         }
9200 
noteForegroundServicePausedLocked(long elapsedRealtimeMs)9201         public void noteForegroundServicePausedLocked(long elapsedRealtimeMs) {
9202             if (mForegroundServiceTimer != null) {
9203                 mForegroundServiceTimer.stopRunningLocked(elapsedRealtimeMs);
9204             }
9205         }
9206 
createVibratorOnTimerLocked()9207         public BatchTimer createVibratorOnTimerLocked() {
9208             if (mVibratorOnTimer == null) {
9209                 mVibratorOnTimer = new BatchTimer(mBsi.mClock, Uid.this, VIBRATOR_ON,
9210                         mBsi.mOnBatteryTimeBase);
9211             }
9212             return mVibratorOnTimer;
9213         }
9214 
noteVibratorOnLocked(long durationMillis, long elapsedRealtimeMs)9215         public void noteVibratorOnLocked(long durationMillis, long elapsedRealtimeMs) {
9216             createVibratorOnTimerLocked().addDuration(durationMillis, elapsedRealtimeMs);
9217         }
9218 
noteVibratorOffLocked(long elapsedRealtimeMs)9219         public void noteVibratorOffLocked(long elapsedRealtimeMs) {
9220             if (mVibratorOnTimer != null) {
9221                 mVibratorOnTimer.abortLastDuration(elapsedRealtimeMs);
9222             }
9223         }
9224 
9225         @Override
getWifiRunningTime(long elapsedRealtimeUs, int which)9226         public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
9227             if (mWifiRunningTimer == null) {
9228                 return 0;
9229             }
9230             return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
9231         }
9232 
9233         @Override
getFullWifiLockTime(long elapsedRealtimeUs, int which)9234         public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
9235             if (mFullWifiLockTimer == null) {
9236                 return 0;
9237             }
9238             return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
9239         }
9240 
9241         @Override
getWifiScanTime(long elapsedRealtimeUs, int which)9242         public long getWifiScanTime(long elapsedRealtimeUs, int which) {
9243             if (mWifiScanTimer == null) {
9244                 return 0;
9245             }
9246             return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
9247         }
9248 
9249         @Override
getWifiScanCount(int which)9250         public int getWifiScanCount(int which) {
9251             if (mWifiScanTimer == null) {
9252                 return 0;
9253             }
9254             return mWifiScanTimer.getCountLocked(which);
9255         }
9256 
9257         @Override
getWifiScanTimer()9258         public Timer getWifiScanTimer() {
9259             return mWifiScanTimer;
9260         }
9261 
9262         @Override
getWifiScanBackgroundCount(int which)9263         public int getWifiScanBackgroundCount(int which) {
9264             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
9265                 return 0;
9266             }
9267             return mWifiScanTimer.getSubTimer().getCountLocked(which);
9268         }
9269 
9270         @Override
getWifiScanActualTime(final long elapsedRealtimeUs)9271         public long getWifiScanActualTime(final long elapsedRealtimeUs) {
9272             if (mWifiScanTimer == null) {
9273                 return 0;
9274             }
9275             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
9276             return mWifiScanTimer.getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
9277         }
9278 
9279         @Override
getWifiScanBackgroundTime(final long elapsedRealtimeUs)9280         public long getWifiScanBackgroundTime(final long elapsedRealtimeUs) {
9281             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
9282                 return 0;
9283             }
9284             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
9285             return mWifiScanTimer.getSubTimer().getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
9286         }
9287 
9288         @Override
getWifiScanBackgroundTimer()9289         public Timer getWifiScanBackgroundTimer() {
9290             if (mWifiScanTimer == null) {
9291                 return null;
9292             }
9293             return mWifiScanTimer.getSubTimer();
9294         }
9295 
9296         @Override
getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which)9297         public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
9298             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
9299             if (mWifiBatchedScanTimer[csphBin] == null) {
9300                 return 0;
9301             }
9302             return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
9303         }
9304 
9305         @Override
getWifiBatchedScanCount(int csphBin, int which)9306         public int getWifiBatchedScanCount(int csphBin, int which) {
9307             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
9308             if (mWifiBatchedScanTimer[csphBin] == null) {
9309                 return 0;
9310             }
9311             return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
9312         }
9313 
9314         @Override
getWifiMulticastTime(long elapsedRealtimeUs, int which)9315         public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
9316             if (mWifiMulticastTimer == null) {
9317                 return 0;
9318             }
9319             return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
9320         }
9321 
9322         @Override
getAudioTurnedOnTimer()9323         public Timer getAudioTurnedOnTimer() {
9324             return mAudioTurnedOnTimer;
9325         }
9326 
9327         @Override
getVideoTurnedOnTimer()9328         public Timer getVideoTurnedOnTimer() {
9329             return mVideoTurnedOnTimer;
9330         }
9331 
9332         @Override
getFlashlightTurnedOnTimer()9333         public Timer getFlashlightTurnedOnTimer() {
9334             return mFlashlightTurnedOnTimer;
9335         }
9336 
9337         @Override
getCameraTurnedOnTimer()9338         public Timer getCameraTurnedOnTimer() {
9339             return mCameraTurnedOnTimer;
9340         }
9341 
9342         @Override
getForegroundActivityTimer()9343         public Timer getForegroundActivityTimer() {
9344             return mForegroundActivityTimer;
9345         }
9346 
9347         @Override
getForegroundServiceTimer()9348         public Timer getForegroundServiceTimer() {
9349             return mForegroundServiceTimer;
9350         }
9351 
9352         @Override
getBluetoothScanTimer()9353         public Timer getBluetoothScanTimer() {
9354             return mBluetoothScanTimer;
9355         }
9356 
9357         @Override
getBluetoothScanBackgroundTimer()9358         public Timer getBluetoothScanBackgroundTimer() {
9359             if (mBluetoothScanTimer == null) {
9360                 return null;
9361             }
9362             return mBluetoothScanTimer.getSubTimer();
9363         }
9364 
9365         @Override
getBluetoothUnoptimizedScanTimer()9366         public Timer getBluetoothUnoptimizedScanTimer() {
9367             return mBluetoothUnoptimizedScanTimer;
9368         }
9369 
9370         @Override
getBluetoothUnoptimizedScanBackgroundTimer()9371         public Timer getBluetoothUnoptimizedScanBackgroundTimer() {
9372             if (mBluetoothUnoptimizedScanTimer == null) {
9373                 return null;
9374             }
9375             return mBluetoothUnoptimizedScanTimer.getSubTimer();
9376         }
9377 
9378         @Override
getBluetoothScanResultCounter()9379         public Counter getBluetoothScanResultCounter() {
9380             return mBluetoothScanResultCounter;
9381         }
9382 
9383         @Override
getBluetoothScanResultBgCounter()9384         public Counter getBluetoothScanResultBgCounter() {
9385             return mBluetoothScanResultBgCounter;
9386         }
9387 
makeProcessState(int i, Parcel in)9388         void makeProcessState(int i, Parcel in) {
9389             if (i < 0 || i >= NUM_PROCESS_STATE) return;
9390 
9391             detachIfNotNull(mProcessStateTimer[i]);
9392             if (in == null) {
9393                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClock, this, PROCESS_STATE, null,
9394                         mBsi.mOnBatteryTimeBase);
9395             } else {
9396                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClock, this, PROCESS_STATE, null,
9397                         mBsi.mOnBatteryTimeBase, in);
9398             }
9399         }
9400 
9401         @Override
getProcessStateTime(int state, long elapsedRealtimeUs, int which)9402         public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
9403             if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
9404             if (mProcessStateTimer[state] == null) {
9405                 return 0;
9406             }
9407             return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
9408         }
9409 
9410         @Override
getProcessStateTimer(int state)9411         public Timer getProcessStateTimer(int state) {
9412             if (state < 0 || state >= NUM_PROCESS_STATE) return null;
9413             return mProcessStateTimer[state];
9414         }
9415 
9416         @Override
getVibratorOnTimer()9417         public Timer getVibratorOnTimer() {
9418             return mVibratorOnTimer;
9419         }
9420 
9421         @Override
noteUserActivityLocked(@owerManager.UserActivityEvent int event)9422         public void noteUserActivityLocked(@PowerManager.UserActivityEvent int event) {
9423             if (mUserActivityCounters == null) {
9424                 initUserActivityLocked();
9425             }
9426             if (event >= 0 && event < NUM_USER_ACTIVITY_TYPES) {
9427                 mUserActivityCounters[event].stepAtomic();
9428             } else {
9429                 Slog.w(TAG, "Unknown user activity type " + event + " was specified.",
9430                         new Throwable());
9431             }
9432         }
9433 
9434         @Override
hasUserActivity()9435         public boolean hasUserActivity() {
9436             return mUserActivityCounters != null;
9437         }
9438 
9439         @Override
getUserActivityCount(int type, int which)9440         public int getUserActivityCount(int type, int which) {
9441             if (mUserActivityCounters == null) {
9442                 return 0;
9443             }
9444             return mUserActivityCounters[type].getCountLocked(which);
9445         }
9446 
makeWifiBatchedScanBin(int i, Parcel in)9447         void makeWifiBatchedScanBin(int i, Parcel in) {
9448             if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
9449 
9450             ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
9451             if (collected == null) {
9452                 collected = new ArrayList<StopwatchTimer>();
9453                 mBsi.mWifiBatchedScanTimers.put(i, collected);
9454             }
9455             detachIfNotNull(mWifiBatchedScanTimer[i]);
9456             if (in == null) {
9457                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClock, this, WIFI_BATCHED_SCAN,
9458                         collected, mBsi.mOnBatteryTimeBase);
9459             } else {
9460                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClock, this, WIFI_BATCHED_SCAN,
9461                         collected, mBsi.mOnBatteryTimeBase, in);
9462             }
9463         }
9464 
9465 
initUserActivityLocked()9466         void initUserActivityLocked() {
9467             detachIfNotNull(mUserActivityCounters);
9468             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
9469             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
9470                 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
9471             }
9472         }
9473 
noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets)9474         void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
9475             ensureNetworkActivityLocked();
9476             if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
9477                 mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
9478                 mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
9479             } else {
9480                 Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
9481                         new Throwable());
9482             }
9483         }
9484 
noteMobileRadioActiveTimeLocked(long batteryUptimeDeltaUs, long elapsedTimeMs)9485         void noteMobileRadioActiveTimeLocked(long batteryUptimeDeltaUs, long elapsedTimeMs) {
9486             ensureNetworkActivityLocked();
9487             getMobileRadioActiveTimeCounter().increment(batteryUptimeDeltaUs, elapsedTimeMs);
9488             mMobileRadioActiveCount.addCountLocked(1);
9489         }
9490 
getMobileRadioActiveTimeCounter()9491         private TimeMultiStateCounter getMobileRadioActiveTimeCounter() {
9492             if (mMobileRadioActiveTime == null) {
9493                 final long timestampMs = mBsi.mClock.elapsedRealtime();
9494                 mMobileRadioActiveTime = new TimeMultiStateCounter(
9495                         mBsi.mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT, timestampMs);
9496                 mMobileRadioActiveTime.setState(
9497                         mapUidProcessStateToBatteryConsumerProcessState(mProcessState),
9498                         timestampMs);
9499                 mMobileRadioActiveTime.update(0, timestampMs);
9500             }
9501             return mMobileRadioActiveTime;
9502         }
9503 
9504         @Override
hasNetworkActivity()9505         public boolean hasNetworkActivity() {
9506             return mNetworkByteActivityCounters != null;
9507         }
9508 
9509         @Override
getNetworkActivityBytes(int type, int which)9510         public long getNetworkActivityBytes(int type, int which) {
9511             if (mNetworkByteActivityCounters != null && type >= 0
9512                     && type < mNetworkByteActivityCounters.length) {
9513                 return mNetworkByteActivityCounters[type].getCountLocked(which);
9514             } else {
9515                 return 0;
9516             }
9517         }
9518 
9519         @Override
getNetworkActivityPackets(int type, int which)9520         public long getNetworkActivityPackets(int type, int which) {
9521             if (mNetworkPacketActivityCounters != null && type >= 0
9522                     && type < mNetworkPacketActivityCounters.length) {
9523                 return mNetworkPacketActivityCounters[type].getCountLocked(which);
9524             } else {
9525                 return 0;
9526             }
9527         }
9528 
9529         @Override
getMobileRadioActiveTime(int which)9530         public long getMobileRadioActiveTime(int which) {
9531             return getMobileRadioActiveTimeInProcessState(BatteryConsumer.PROCESS_STATE_ANY);
9532         }
9533 
9534         @Override
getMobileRadioActiveTimeInProcessState( @atteryConsumer.ProcessState int processState)9535         public long getMobileRadioActiveTimeInProcessState(
9536                 @BatteryConsumer.ProcessState int processState) {
9537             if (mMobileRadioActiveTime == null) {
9538                 return 0;
9539             }
9540             if (processState == BatteryConsumer.PROCESS_STATE_ANY) {
9541                 return mMobileRadioActiveTime.getTotalCountLocked();
9542             } else {
9543                 return mMobileRadioActiveTime.getCountForProcessState(processState);
9544             }
9545         }
9546 
9547         @Override
getMobileRadioActiveCount(int which)9548         public int getMobileRadioActiveCount(int which) {
9549             return mMobileRadioActiveCount != null
9550                     ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
9551         }
9552 
9553         @Override
getUserCpuTimeUs(int which)9554         public long getUserCpuTimeUs(int which) {
9555             return mUserCpuTime.getCountLocked(which);
9556         }
9557 
9558         @Override
getSystemCpuTimeUs(int which)9559         public long getSystemCpuTimeUs(int which) {
9560             return mSystemCpuTime.getCountLocked(which);
9561         }
9562 
9563         @Override
9564         @Deprecated
getTimeAtCpuSpeed(int cluster, int step, int which)9565         public long getTimeAtCpuSpeed(int cluster, int step, int which) {
9566             if (mCpuClusterSpeedTimesUs != null) {
9567                 if (cluster >= 0 && cluster < mCpuClusterSpeedTimesUs.length) {
9568                     final LongSamplingCounter[] cpuSpeedTimesUs = mCpuClusterSpeedTimesUs[cluster];
9569                     if (cpuSpeedTimesUs != null) {
9570                         if (step >= 0 && step < cpuSpeedTimesUs.length) {
9571                             final LongSamplingCounter c = cpuSpeedTimesUs[step];
9572                             if (c != null) {
9573                                 return c.getCountLocked(which);
9574                             }
9575                         }
9576                     }
9577                 }
9578             }
9579             return 0;
9580         }
9581 
noteMobileRadioApWakeupLocked()9582         public void noteMobileRadioApWakeupLocked() {
9583             if (mMobileRadioApWakeupCount == null) {
9584                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9585             }
9586             mMobileRadioApWakeupCount.addCountLocked(1);
9587         }
9588 
9589         @Override
getMobileRadioApWakeupCount(int which)9590         public long getMobileRadioApWakeupCount(int which) {
9591             if (mMobileRadioApWakeupCount != null) {
9592                 return mMobileRadioApWakeupCount.getCountLocked(which);
9593             }
9594             return 0;
9595         }
9596 
noteWifiRadioApWakeupLocked()9597         public void noteWifiRadioApWakeupLocked() {
9598             if (mWifiRadioApWakeupCount == null) {
9599                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9600             }
9601             mWifiRadioApWakeupCount.addCountLocked(1);
9602         }
9603 
9604         @Override
getWifiRadioApWakeupCount(int which)9605         public long getWifiRadioApWakeupCount(int which) {
9606             if (mWifiRadioApWakeupCount != null) {
9607                 return mWifiRadioApWakeupCount.getCountLocked(which);
9608             }
9609             return 0;
9610         }
9611 
9612         @Override
getDeferredJobsCheckinLineLocked(StringBuilder sb, int which)9613         public void getDeferredJobsCheckinLineLocked(StringBuilder sb, int which) {
9614             sb.setLength(0);
9615             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
9616             if (deferredEventCount == 0) {
9617                 return;
9618             }
9619             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
9620             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
9621             sb.append(deferredEventCount); sb.append(',');
9622             sb.append(deferredCount); sb.append(',');
9623             sb.append(totalLatency);
9624             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
9625                 if (mJobsFreshnessBuckets[i] == null) {
9626                     sb.append(",0");
9627                 } else {
9628                     sb.append(",");
9629                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
9630                 }
9631             }
9632         }
9633 
9634         @Override
getDeferredJobsLineLocked(StringBuilder sb, int which)9635         public void getDeferredJobsLineLocked(StringBuilder sb, int which) {
9636             sb.setLength(0);
9637             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
9638             if (deferredEventCount == 0) {
9639                 return;
9640             }
9641             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
9642             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
9643             sb.append("times="); sb.append(deferredEventCount); sb.append(", ");
9644             sb.append("count="); sb.append(deferredCount); sb.append(", ");
9645             sb.append("totalLatencyMs="); sb.append(totalLatency); sb.append(", ");
9646             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
9647                 sb.append("<"); sb.append(JOB_FRESHNESS_BUCKETS[i]); sb.append("ms=");
9648                 if (mJobsFreshnessBuckets[i] == null) {
9649                     sb.append("0");
9650                 } else {
9651                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
9652                 }
9653                 sb.append(" ");
9654             }
9655         }
9656 
ensureNetworkActivityLocked()9657         void ensureNetworkActivityLocked() {
9658             if (mNetworkByteActivityCounters != null) {
9659                 return;
9660             }
9661 
9662             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
9663             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
9664             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9665                 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9666                 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9667             }
9668             mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9669         }
9670 
9671         /**
9672          * Clear all stats for this uid.  Returns true if the uid is completely
9673          * inactive so can be dropped.
9674          */
9675         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
reset(long uptimeUs, long realtimeUs, int resetReason)9676         public boolean reset(long uptimeUs, long realtimeUs, int resetReason) {
9677             boolean active = false;
9678 
9679             mOnBatteryBackgroundTimeBase.init(uptimeUs, realtimeUs);
9680             mOnBatteryScreenOffBackgroundTimeBase.init(uptimeUs, realtimeUs);
9681 
9682             if (mWifiRunningTimer != null) {
9683                 active |= !mWifiRunningTimer.reset(false, realtimeUs);
9684                 active |= mWifiRunning;
9685             }
9686             if (mFullWifiLockTimer != null) {
9687                 active |= !mFullWifiLockTimer.reset(false, realtimeUs);
9688                 active |= mFullWifiLockOut;
9689             }
9690             if (mWifiScanTimer != null) {
9691                 active |= !mWifiScanTimer.reset(false, realtimeUs);
9692                 active |= mWifiScanStarted;
9693             }
9694             if (mWifiBatchedScanTimer != null) {
9695                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
9696                     if (mWifiBatchedScanTimer[i] != null) {
9697                         active |= !mWifiBatchedScanTimer[i].reset(false, realtimeUs);
9698                     }
9699                 }
9700                 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
9701             }
9702             if (mWifiMulticastTimer != null) {
9703                 active |= !mWifiMulticastTimer.reset(false, realtimeUs);
9704                 active |= (mWifiMulticastWakelockCount > 0);
9705             }
9706 
9707             active |= !resetIfNotNull(mAudioTurnedOnTimer, false, realtimeUs);
9708             active |= !resetIfNotNull(mVideoTurnedOnTimer, false, realtimeUs);
9709             active |= !resetIfNotNull(mFlashlightTurnedOnTimer, false, realtimeUs);
9710             active |= !resetIfNotNull(mCameraTurnedOnTimer, false, realtimeUs);
9711             active |= !resetIfNotNull(mForegroundActivityTimer, false, realtimeUs);
9712             active |= !resetIfNotNull(mForegroundServiceTimer, false, realtimeUs);
9713             active |= !resetIfNotNull(mAggregatedPartialWakelockTimer, false, realtimeUs);
9714             active |= !resetIfNotNull(mBluetoothScanTimer, false, realtimeUs);
9715             active |= !resetIfNotNull(mBluetoothUnoptimizedScanTimer, false, realtimeUs);
9716 
9717             resetIfNotNull(mBluetoothScanResultCounter, false, realtimeUs);
9718             resetIfNotNull(mBluetoothScanResultBgCounter, false, realtimeUs);
9719 
9720             if (mProcessStateTimer != null) {
9721                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
9722                     active |= !resetIfNotNull(mProcessStateTimer[i], false, realtimeUs);
9723                 }
9724                 active |= (mProcessState != Uid.PROCESS_STATE_NONEXISTENT);
9725             }
9726             if (mVibratorOnTimer != null) {
9727                 if (mVibratorOnTimer.reset(false, realtimeUs)) {
9728                     mVibratorOnTimer.detach();
9729                     mVibratorOnTimer = null;
9730                 } else {
9731                     active = true;
9732                 }
9733             }
9734 
9735             resetIfNotNull(mUserActivityCounters, false, realtimeUs);
9736 
9737             resetIfNotNull(mNetworkByteActivityCounters, false, realtimeUs);
9738             resetIfNotNull(mNetworkPacketActivityCounters, false, realtimeUs);
9739             resetIfNotNull(mMobileRadioActiveTime, false, realtimeUs);
9740             resetIfNotNull(mMobileRadioActiveCount, false, realtimeUs);
9741 
9742             resetIfNotNull(mWifiControllerActivity, false, realtimeUs);
9743             resetIfNotNull(mBluetoothControllerActivity, false, realtimeUs);
9744             resetIfNotNull(mModemControllerActivity, false, realtimeUs);
9745 
9746             if (resetReason == RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE) {
9747                 mUidEnergyConsumerStats = null;
9748             } else {
9749                 EnergyConsumerStats.resetIfNotNull(mUidEnergyConsumerStats);
9750             }
9751 
9752             resetIfNotNull(mUserCpuTime, false, realtimeUs);
9753             resetIfNotNull(mSystemCpuTime, false, realtimeUs);
9754 
9755             resetIfNotNull(mCpuClusterSpeedTimesUs, false, realtimeUs);
9756 
9757             resetIfNotNull(mCpuFreqTimeMs, false, realtimeUs /* unused */);
9758             resetIfNotNull(mScreenOffCpuFreqTimeMs, false, realtimeUs /* unused */);
9759 
9760 
9761             resetIfNotNull(mCpuActiveTimeMs, false, realtimeUs /* unused */);
9762             resetIfNotNull(mCpuClusterTimesMs, false, realtimeUs /* unused */);
9763 
9764             resetIfNotNull(mProcStateTimeMs, false, realtimeUs /* unused */);
9765 
9766             resetIfNotNull(mProcStateScreenOffTimeMs, false, realtimeUs /* unused */);
9767 
9768             resetIfNotNull(mMobileRadioApWakeupCount, false, realtimeUs);
9769 
9770             resetIfNotNull(mWifiRadioApWakeupCount, false, realtimeUs);
9771 
9772 
9773             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
9774             for (int iw=wakeStats.size()-1; iw>=0; iw--) {
9775                 Wakelock wl = wakeStats.valueAt(iw);
9776                 if (wl.reset(realtimeUs)) {
9777                     wakeStats.removeAt(iw);
9778                 } else {
9779                     active = true;
9780                 }
9781             }
9782             final long realtimeMs = realtimeUs / 1000;
9783             mWakelockStats.cleanup(realtimeMs);
9784             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
9785             for (int is=syncStats.size()-1; is>=0; is--) {
9786                 DualTimer timer = syncStats.valueAt(is);
9787                 if (timer.reset(false, realtimeUs)) {
9788                     syncStats.removeAt(is);
9789                     timer.detach();
9790                 } else {
9791                     active = true;
9792                 }
9793             }
9794             mSyncStats.cleanup(realtimeMs);
9795             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
9796             for (int ij=jobStats.size()-1; ij>=0; ij--) {
9797                 DualTimer timer = jobStats.valueAt(ij);
9798                 if (timer.reset(false, realtimeUs)) {
9799                     jobStats.removeAt(ij);
9800                     timer.detach();
9801                 } else {
9802                     active = true;
9803                 }
9804             }
9805             mJobStats.cleanup(realtimeMs);
9806             mJobCompletions.clear();
9807 
9808             resetIfNotNull(mJobsDeferredEventCount, false, realtimeUs);
9809             resetIfNotNull(mJobsDeferredCount, false, realtimeUs);
9810             resetIfNotNull(mJobsFreshnessTimeMs, false, realtimeUs /* unused */);
9811             resetIfNotNull(mJobsFreshnessBuckets, false, realtimeUs);
9812 
9813             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
9814                 Sensor s = mSensorStats.valueAt(ise);
9815                 if (s.reset(realtimeUs)) {
9816                     mSensorStats.removeAt(ise);
9817                 } else {
9818                     active = true;
9819                 }
9820             }
9821 
9822             for (int ip = mProcessStats.size() - 1; ip >= 0; ip--) {
9823                 Proc proc = mProcessStats.valueAt(ip);
9824                 proc.detach();
9825             }
9826             mProcessStats.clear();
9827 
9828             for (int i = mPids.size() - 1; i >= 0; i--) {
9829                 Pid pid = mPids.valueAt(i);
9830                 if (pid.mWakeNesting > 0) {
9831                     active = true;
9832                 } else {
9833                     mPids.removeAt(i);
9834                 }
9835             }
9836 
9837 
9838             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
9839                 Pkg p = mPackageStats.valueAt(i);
9840                 p.detach();
9841             }
9842             mPackageStats.clear();
9843 
9844             mBinderCallCount = 0;
9845             mBinderCallStats.clear();
9846 
9847             mProportionalSystemServiceUsage = 0;
9848 
9849             mLastStepUserTimeMs = mLastStepSystemTimeMs = 0;
9850             mCurStepUserTimeMs = mCurStepSystemTimeMs = 0;
9851 
9852 
9853             return !active;
9854         }
9855 
9856         /**
9857          * This method MUST be called whenever the Uid object is destructed, otherwise it is a
9858          * memory leak in {@link TimeBase#mObservers} list.
9859          * Typically the Uid object is destructed when it is removed from
9860          * {@link BatteryStatsImpl#mUidStats}
9861          */
detachFromTimeBase()9862         void detachFromTimeBase() {
9863             detachIfNotNull(mWifiRunningTimer);
9864             detachIfNotNull(mFullWifiLockTimer);
9865             detachIfNotNull(mWifiScanTimer);
9866             detachIfNotNull(mWifiBatchedScanTimer);
9867             detachIfNotNull(mWifiMulticastTimer);
9868             detachIfNotNull(mAudioTurnedOnTimer);
9869             detachIfNotNull(mVideoTurnedOnTimer);
9870             detachIfNotNull(mFlashlightTurnedOnTimer);
9871 
9872             detachIfNotNull(mCameraTurnedOnTimer);
9873             detachIfNotNull(mForegroundActivityTimer);
9874             detachIfNotNull(mForegroundServiceTimer);
9875 
9876             detachIfNotNull(mAggregatedPartialWakelockTimer);
9877 
9878             detachIfNotNull(mBluetoothScanTimer);
9879             detachIfNotNull(mBluetoothUnoptimizedScanTimer);
9880             detachIfNotNull(mBluetoothScanResultCounter);
9881             detachIfNotNull(mBluetoothScanResultBgCounter);
9882 
9883             detachIfNotNull(mProcessStateTimer);
9884 
9885             detachIfNotNull(mVibratorOnTimer);
9886 
9887             detachIfNotNull(mUserActivityCounters);
9888 
9889             detachIfNotNull(mNetworkByteActivityCounters);
9890             detachIfNotNull(mNetworkPacketActivityCounters);
9891 
9892             detachIfNotNull(mMobileRadioActiveTime);
9893             detachIfNotNull(mMobileRadioActiveCount);
9894             detachIfNotNull(mMobileRadioApWakeupCount);
9895             detachIfNotNull(mWifiRadioApWakeupCount);
9896 
9897             detachIfNotNull(mWifiControllerActivity);
9898             detachIfNotNull(mBluetoothControllerActivity);
9899             detachIfNotNull(mModemControllerActivity);
9900 
9901             mPids.clear();
9902 
9903             detachIfNotNull(mUserCpuTime);
9904             detachIfNotNull(mSystemCpuTime);
9905 
9906             detachIfNotNull(mCpuClusterSpeedTimesUs);
9907 
9908             detachIfNotNull(mCpuActiveTimeMs);
9909             detachIfNotNull(mCpuFreqTimeMs);
9910 
9911             detachIfNotNull(mScreenOffCpuFreqTimeMs);
9912 
9913             detachIfNotNull(mCpuClusterTimesMs);
9914 
9915             detachIfNotNull(mProcStateTimeMs);
9916 
9917             detachIfNotNull(mProcStateScreenOffTimeMs);
9918 
9919             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
9920             for (int iw = wakeStats.size() - 1; iw >= 0; iw--) {
9921                 Wakelock wl = wakeStats.valueAt(iw);
9922                 wl.detachFromTimeBase();
9923             }
9924             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
9925             for (int is = syncStats.size() - 1; is >= 0; is--) {
9926                 DualTimer timer = syncStats.valueAt(is);
9927                 detachIfNotNull(timer);
9928             }
9929             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
9930             for (int ij = jobStats.size() - 1; ij >= 0; ij--) {
9931                 DualTimer timer = jobStats.valueAt(ij);
9932                 detachIfNotNull(timer);
9933             }
9934 
9935             detachIfNotNull(mJobsDeferredEventCount);
9936             detachIfNotNull(mJobsDeferredCount);
9937             detachIfNotNull(mJobsFreshnessTimeMs);
9938             detachIfNotNull(mJobsFreshnessBuckets);
9939 
9940 
9941             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
9942                 Sensor s = mSensorStats.valueAt(ise);
9943                 s.detachFromTimeBase();
9944             }
9945 
9946             for (int ip= mProcessStats.size() - 1; ip >= 0; ip--) {
9947                 Proc proc = mProcessStats.valueAt(ip);
9948                 proc.detach();
9949             }
9950             mProcessStats.clear();
9951 
9952             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
9953                 Pkg p = mPackageStats.valueAt(i);
9954                 p.detach();
9955             }
9956             mPackageStats.clear();
9957         }
9958 
writeJobCompletionsToParcelLocked(Parcel out)9959         void writeJobCompletionsToParcelLocked(Parcel out) {
9960             int NJC = mJobCompletions.size();
9961             out.writeInt(NJC);
9962             for (int ijc=0; ijc<NJC; ijc++) {
9963                 out.writeString(mJobCompletions.keyAt(ijc));
9964                 SparseIntArray types = mJobCompletions.valueAt(ijc);
9965                 int NT = types.size();
9966                 out.writeInt(NT);
9967                 for (int it=0; it<NT; it++) {
9968                     out.writeInt(types.keyAt(it));
9969                     out.writeInt(types.valueAt(it));
9970                 }
9971             }
9972         }
9973 
readJobCompletionsFromParcelLocked(Parcel in)9974         void readJobCompletionsFromParcelLocked(Parcel in) {
9975             int numJobCompletions = in.readInt();
9976             mJobCompletions.clear();
9977             for (int j = 0; j < numJobCompletions; j++) {
9978                 String jobName = in.readString();
9979                 int numTypes = in.readInt();
9980                 if (numTypes > 0) {
9981                     SparseIntArray types = new SparseIntArray();
9982                     for (int k = 0; k < numTypes; k++) {
9983                         int type = in.readInt();
9984                         int count = in.readInt();
9985                         types.put(type, count);
9986                     }
9987                     mJobCompletions.put(jobName, types);
9988                 }
9989             }
9990         }
9991 
noteJobsDeferredLocked(int numDeferred, long sinceLast)9992         public void noteJobsDeferredLocked(int numDeferred, long sinceLast) {
9993             mJobsDeferredEventCount.addAtomic(1);
9994             mJobsDeferredCount.addAtomic(numDeferred);
9995             if (sinceLast != 0) {
9996                 // Add the total time, which can be divided by the event count to get an average
9997                 mJobsFreshnessTimeMs.addCountLocked(sinceLast);
9998                 // Also keep track of how many times there were in these different buckets.
9999                 for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
10000                     if (sinceLast < JOB_FRESHNESS_BUCKETS[i]) {
10001                         if (mJobsFreshnessBuckets[i] == null) {
10002                             mJobsFreshnessBuckets[i] = new Counter(
10003                                     mBsi.mOnBatteryTimeBase);
10004                         }
10005                         mJobsFreshnessBuckets[i].addAtomic(1);
10006                         break;
10007                     }
10008                 }
10009             }
10010         }
10011 
10012         // Reusable object used as a key to lookup values in mBinderCallStats
10013         private static BinderCallStats sTempBinderCallStats = new BinderCallStats();
10014 
10015         /**
10016          * Notes incoming binder call stats associated with this work source UID.
10017          */
noteBinderCallStatsLocked(long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats)10018         public void noteBinderCallStatsLocked(long incrementalCallCount,
10019                 Collection<BinderCallsStats.CallStat> callStats) {
10020             if (DEBUG) {
10021                 Slog.d(TAG, "noteBinderCalls() workSourceUid = [" + mUid + "], "
10022                         + " incrementalCallCount: " + incrementalCallCount + " callStats = ["
10023                         + new ArrayList<>(callStats) + "]");
10024             }
10025             mBinderCallCount += incrementalCallCount;
10026             for (BinderCallsStats.CallStat stat : callStats) {
10027                 BinderCallStats bcs;
10028                 sTempBinderCallStats.binderClass = stat.binderClass;
10029                 sTempBinderCallStats.transactionCode = stat.transactionCode;
10030                 int index = mBinderCallStats.indexOf(sTempBinderCallStats);
10031                 if (index >= 0) {
10032                     bcs = mBinderCallStats.valueAt(index);
10033                 } else {
10034                     bcs = new BinderCallStats();
10035                     bcs.binderClass = stat.binderClass;
10036                     bcs.transactionCode = stat.transactionCode;
10037                     mBinderCallStats.add(bcs);
10038                 }
10039 
10040                 bcs.callCount += stat.incrementalCallCount;
10041                 bcs.recordedCallCount = stat.recordedCallCount;
10042                 bcs.recordedCpuTimeMicros = stat.cpuTimeMicros;
10043             }
10044         }
10045 
10046         /**
10047          * The statistics associated with a particular wake lock.
10048          */
10049         public static class Wakelock extends BatteryStats.Uid.Wakelock {
10050             /**
10051              * BatteryStatsImpl that we are associated with.
10052              */
10053             protected BatteryStatsImpl mBsi;
10054 
10055             /**
10056              * BatteryStatsImpl that we are associated with.
10057              */
10058             protected Uid mUid;
10059 
10060             /**
10061              * How long (in ms) this uid has been keeping the device partially awake.
10062              * Tracks both the total time and the time while the app was in the background.
10063              */
10064             DualTimer mTimerPartial;
10065 
10066             /**
10067              * How long (in ms) this uid has been keeping the device fully awake.
10068              */
10069             StopwatchTimer mTimerFull;
10070 
10071             /**
10072              * How long (in ms) this uid has had a window keeping the device awake.
10073              */
10074             StopwatchTimer mTimerWindow;
10075 
10076             /**
10077              * How long (in ms) this uid has had a draw wake lock.
10078              */
10079             StopwatchTimer mTimerDraw;
10080 
Wakelock(BatteryStatsImpl bsi, Uid uid)10081             public Wakelock(BatteryStatsImpl bsi, Uid uid) {
10082                 mBsi = bsi;
10083                 mUid = uid;
10084             }
10085 
10086             /**
10087              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
10088              * proper timer pool from the given BatteryStatsImpl object.
10089              *
10090              * @param in the Parcel to be read from.
10091              * return a new Timer, or null.
10092              */
readStopwatchTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in)10093             private StopwatchTimer readStopwatchTimerFromParcel(int type,
10094                     ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
10095                 if (in.readInt() == 0) {
10096                     return null;
10097                 }
10098 
10099                 return new StopwatchTimer(mBsi.mClock, mUid, type, pool, timeBase, in);
10100             }
10101 
10102             /**
10103              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
10104              * proper timer pool from the given BatteryStatsImpl object.
10105              *
10106              * @param in the Parcel to be read from.
10107              * return a new Timer, or null.
10108              */
readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, TimeBase bgTimeBase, Parcel in)10109             private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
10110                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
10111                 if (in.readInt() == 0) {
10112                     return null;
10113                 }
10114 
10115                 return new DualTimer(mBsi.mClock, mUid, type, pool, timeBase, bgTimeBase, in);
10116             }
10117 
reset(long elapsedRealtimeUs)10118             boolean reset(long elapsedRealtimeUs) {
10119                 boolean wlactive = false;
10120 
10121                 wlactive |= !resetIfNotNull(mTimerFull, false, elapsedRealtimeUs);
10122                 wlactive |= !resetIfNotNull(mTimerPartial, false, elapsedRealtimeUs);
10123                 wlactive |= !resetIfNotNull(mTimerWindow, false, elapsedRealtimeUs);
10124                 wlactive |= !resetIfNotNull(mTimerDraw, false, elapsedRealtimeUs);
10125 
10126                 if (!wlactive) {
10127                     detachIfNotNull(mTimerFull);
10128                     mTimerFull = null;
10129 
10130                     detachIfNotNull(mTimerPartial);
10131                     mTimerPartial = null;
10132 
10133                     detachIfNotNull(mTimerWindow);
10134                     mTimerWindow = null;
10135 
10136                     detachIfNotNull(mTimerDraw);
10137                     mTimerDraw = null;
10138                 }
10139                 return !wlactive;
10140             }
10141 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, TimeBase screenOffBgTimeBase, Parcel in)10142             void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase,
10143                     TimeBase screenOffBgTimeBase, Parcel in) {
10144                 mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL,
10145                         mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in);
10146                 mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
10147                         mBsi.mFullTimers, timeBase, in);
10148                 mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
10149                         mBsi.mWindowTimers, timeBase, in);
10150                 mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
10151                         mBsi.mDrawTimers, timeBase, in);
10152             }
10153 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)10154             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
10155                 Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
10156                 Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
10157                 Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
10158                 Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
10159             }
10160 
10161             @Override
getWakeTime(int type)10162             public Timer getWakeTime(int type) {
10163                 switch (type) {
10164                 case WAKE_TYPE_FULL: return mTimerFull;
10165                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
10166                 case WAKE_TYPE_WINDOW: return mTimerWindow;
10167                 case WAKE_TYPE_DRAW: return mTimerDraw;
10168                 default: throw new IllegalArgumentException("type = " + type);
10169                 }
10170             }
10171 
detachFromTimeBase()10172             public void detachFromTimeBase() {
10173                 detachIfNotNull(mTimerPartial);
10174                 detachIfNotNull(mTimerFull);
10175                 detachIfNotNull(mTimerWindow);
10176                 detachIfNotNull(mTimerDraw);
10177             }
10178         }
10179 
10180         public static class Sensor extends BatteryStats.Uid.Sensor {
10181             /**
10182              * BatteryStatsImpl that we are associated with.
10183              */
10184             protected BatteryStatsImpl mBsi;
10185 
10186             /**
10187              * Uid that we are associated with.
10188              */
10189             protected Uid mUid;
10190 
10191             final int mHandle;
10192             DualTimer mTimer;
10193 
Sensor(BatteryStatsImpl bsi, Uid uid, int handle)10194             public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
10195                 mBsi = bsi;
10196                 mUid = uid;
10197                 mHandle = handle;
10198             }
10199 
readTimersFromParcel( TimeBase timeBase, TimeBase bgTimeBase, Parcel in)10200             private DualTimer readTimersFromParcel(
10201                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
10202                 if (in.readInt() == 0) {
10203                     return null;
10204                 }
10205 
10206                 ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
10207                 if (pool == null) {
10208                     pool = new ArrayList<StopwatchTimer>();
10209                     mBsi.mSensorTimers.put(mHandle, pool);
10210                 }
10211                 return new DualTimer(mBsi.mClock, mUid, 0, pool, timeBase, bgTimeBase, in);
10212             }
10213 
reset(long elapsedRealtimeUs)10214             boolean reset(long elapsedRealtimeUs) {
10215                 if (mTimer.reset(true, elapsedRealtimeUs)) {
10216                     mTimer = null;
10217                     return true;
10218                 }
10219                 return false;
10220             }
10221 
readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in)10222             void readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
10223                 mTimer = readTimersFromParcel(timeBase, bgTimeBase, in);
10224             }
10225 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)10226             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
10227                 Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
10228             }
10229 
10230             @Override
getSensorTime()10231             public Timer getSensorTime() {
10232                 return mTimer;
10233             }
10234 
10235             @Override
getSensorBackgroundTime()10236             public Timer getSensorBackgroundTime() {
10237                 if (mTimer == null) {
10238                     return null;
10239                 }
10240                 return mTimer.getSubTimer();
10241             }
10242 
10243             @Override
getHandle()10244             public int getHandle() {
10245                 return mHandle;
10246             }
10247 
detachFromTimeBase()10248             public void  detachFromTimeBase() {
10249                 detachIfNotNull(mTimer);
10250             }
10251         }
10252 
10253         /**
10254          * The statistics associated with a particular process.
10255          */
10256         public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
10257             /**
10258              * BatteryStatsImpl that we are associated with.
10259              */
10260             protected BatteryStatsImpl mBsi;
10261 
10262             /**
10263              * The name of this process.
10264              */
10265             final String mName;
10266 
10267             /**
10268              * Remains true until removed from the stats.
10269              */
10270             boolean mActive = true;
10271 
10272             /**
10273              * Total time (in ms) spent executing in user code.
10274              */
10275             long mUserTimeMs;
10276 
10277             /**
10278              * Total time (in ms) spent executing in kernel code.
10279              */
10280             long mSystemTimeMs;
10281 
10282             /**
10283              * Amount of time (in ms) the process was running in the foreground.
10284              */
10285             long mForegroundTimeMs;
10286 
10287             /**
10288              * Number of times the process has been started.
10289              */
10290             int mStarts;
10291 
10292             /**
10293              * Number of times the process has crashed.
10294              */
10295             int mNumCrashes;
10296 
10297             /**
10298              * Number of times the process has had an ANR.
10299              */
10300             int mNumAnrs;
10301 
10302             ArrayList<ExcessivePower> mExcessivePower;
10303 
Proc(BatteryStatsImpl bsi, String name)10304             public Proc(BatteryStatsImpl bsi, String name) {
10305                 mBsi = bsi;
10306                 mName = name;
10307                 mBsi.mOnBatteryTimeBase.add(this);
10308             }
10309 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10310             public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
10311                     long baseRealtimeUs) {
10312             }
10313 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10314             public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
10315                     long baseRealtimeUs) {
10316             }
10317 
10318             @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)10319             public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
10320                 if (detachIfReset) {
10321                     this.detach();
10322                 }
10323                 return true;
10324             }
10325 
10326             @Override
detach()10327             public void detach() {
10328                 mActive = false;
10329                 mBsi.mOnBatteryTimeBase.remove(this);
10330             }
10331 
countExcessivePowers()10332             public int countExcessivePowers() {
10333                 return mExcessivePower != null ? mExcessivePower.size() : 0;
10334             }
10335 
getExcessivePower(int i)10336             public ExcessivePower getExcessivePower(int i) {
10337                 if (mExcessivePower != null) {
10338                     return mExcessivePower.get(i);
10339                 }
10340                 return null;
10341             }
10342 
addExcessiveCpu(long overTimeMs, long usedTimeMs)10343             public void addExcessiveCpu(long overTimeMs, long usedTimeMs) {
10344                 if (mExcessivePower == null) {
10345                     mExcessivePower = new ArrayList<ExcessivePower>();
10346                 }
10347                 ExcessivePower ew = new ExcessivePower();
10348                 ew.type = ExcessivePower.TYPE_CPU;
10349                 ew.overTime = overTimeMs;
10350                 ew.usedTime = usedTimeMs;
10351                 mExcessivePower.add(ew);
10352             }
10353 
writeExcessivePowerToParcelLocked(Parcel out)10354             void writeExcessivePowerToParcelLocked(Parcel out) {
10355                 if (mExcessivePower == null) {
10356                     out.writeInt(0);
10357                     return;
10358                 }
10359 
10360                 final int N = mExcessivePower.size();
10361                 out.writeInt(N);
10362                 for (int i=0; i<N; i++) {
10363                     ExcessivePower ew = mExcessivePower.get(i);
10364                     out.writeInt(ew.type);
10365                     out.writeLong(ew.overTime);
10366                     out.writeLong(ew.usedTime);
10367                 }
10368             }
10369 
readExcessivePowerFromParcelLocked(Parcel in)10370             void readExcessivePowerFromParcelLocked(Parcel in) {
10371                 final int N = in.readInt();
10372                 if (N == 0) {
10373                     mExcessivePower = null;
10374                     return;
10375                 }
10376 
10377                 if (N > 10000) {
10378                     throw new ParcelFormatException(
10379                             "File corrupt: too many excessive power entries " + N);
10380                 }
10381 
10382                 mExcessivePower = new ArrayList<>();
10383                 for (int i=0; i<N; i++) {
10384                     ExcessivePower ew = new ExcessivePower();
10385                     ew.type = in.readInt();
10386                     ew.overTime = in.readLong();
10387                     ew.usedTime = in.readLong();
10388                     mExcessivePower.add(ew);
10389                 }
10390             }
10391 
writeToParcelLocked(Parcel out)10392             void writeToParcelLocked(Parcel out) {
10393                 out.writeLong(mUserTimeMs);
10394                 out.writeLong(mSystemTimeMs);
10395                 out.writeLong(mForegroundTimeMs);
10396                 out.writeInt(mStarts);
10397                 out.writeInt(mNumCrashes);
10398                 out.writeInt(mNumAnrs);
10399                 writeExcessivePowerToParcelLocked(out);
10400             }
10401 
readFromParcelLocked(Parcel in)10402             void readFromParcelLocked(Parcel in) {
10403                 mUserTimeMs = in.readLong();
10404                 mSystemTimeMs = in.readLong();
10405                 mForegroundTimeMs = in.readLong();
10406                 mStarts = in.readInt();
10407                 mNumCrashes = in.readInt();
10408                 mNumAnrs = in.readInt();
10409                 readExcessivePowerFromParcelLocked(in);
10410             }
10411 
addCpuTimeLocked(int utimeMs, int stimeMs)10412             public void addCpuTimeLocked(int utimeMs, int stimeMs) {
10413                 addCpuTimeLocked(utimeMs, stimeMs, mBsi.mOnBatteryTimeBase.isRunning());
10414             }
10415 
addCpuTimeLocked(int utimeMs, int stimeMs, boolean isRunning)10416             public void addCpuTimeLocked(int utimeMs, int stimeMs, boolean isRunning) {
10417                 if (isRunning) {
10418                     mUserTimeMs += utimeMs;
10419                     mSystemTimeMs += stimeMs;
10420                 }
10421             }
10422 
addForegroundTimeLocked(long ttimeMs)10423             public void addForegroundTimeLocked(long ttimeMs) {
10424                 mForegroundTimeMs += ttimeMs;
10425             }
10426 
incStartsLocked()10427             public void incStartsLocked() {
10428                 mStarts++;
10429             }
10430 
incNumCrashesLocked()10431             public void incNumCrashesLocked() {
10432                 mNumCrashes++;
10433             }
10434 
incNumAnrsLocked()10435             public void incNumAnrsLocked() {
10436                 mNumAnrs++;
10437             }
10438 
10439             @Override
isActive()10440             public boolean isActive() {
10441                 return mActive;
10442             }
10443 
10444             @Override
getUserTime(int which)10445             public long getUserTime(int which) {
10446                 return mUserTimeMs;
10447             }
10448 
10449             @Override
getSystemTime(int which)10450             public long getSystemTime(int which) {
10451                 return mSystemTimeMs;
10452             }
10453 
10454             @Override
getForegroundTime(int which)10455             public long getForegroundTime(int which) {
10456                 return mForegroundTimeMs;
10457             }
10458 
10459             @Override
getStarts(int which)10460             public int getStarts(int which) {
10461                 return mStarts;
10462             }
10463 
10464             @Override
getNumCrashes(int which)10465             public int getNumCrashes(int which) {
10466                 return mNumCrashes;
10467             }
10468 
10469             @Override
getNumAnrs(int which)10470             public int getNumAnrs(int which) {
10471                 return mNumAnrs;
10472             }
10473         }
10474 
10475         /**
10476          * The statistics associated with a particular package.
10477          */
10478         public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
10479             /**
10480              * BatteryStatsImpl that we are associated with.
10481              */
10482             protected BatteryStatsImpl mBsi;
10483 
10484             /**
10485              * Number of times wakeup alarms have occurred for this app.
10486              * On screen-off timebase starting in report v25.
10487              */
10488             ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
10489 
10490             /**
10491              * The statics we have collected for this package's services.
10492              */
10493             final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
10494 
Pkg(BatteryStatsImpl bsi)10495             public Pkg(BatteryStatsImpl bsi) {
10496                 mBsi = bsi;
10497                 mBsi.mOnBatteryScreenOffTimeBase.add(this);
10498             }
10499 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10500             public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
10501                     long baseRealtimeUs) {
10502             }
10503 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10504             public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
10505                     long baseRealtimeUs) {
10506             }
10507 
10508             @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)10509             public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
10510                 if (detachIfReset) {
10511                     this.detach();
10512                 }
10513                 return true;
10514             }
10515 
10516             @Override
detach()10517             public void detach() {
10518                 mBsi.mOnBatteryScreenOffTimeBase.remove(this);
10519                 for (int j = mWakeupAlarms.size() - 1; j >= 0; j--) {
10520                     detachIfNotNull(mWakeupAlarms.valueAt(j));
10521                 }
10522                 for (int j = mServiceStats.size() - 1; j >= 0; j--) {
10523                     detachIfNotNull(mServiceStats.valueAt(j));
10524                 }
10525             }
10526 
readFromParcelLocked(Parcel in)10527             void readFromParcelLocked(Parcel in) {
10528                 int numWA = in.readInt();
10529                 mWakeupAlarms.clear();
10530                 for (int i=0; i<numWA; i++) {
10531                     String tag = in.readString();
10532                     mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryScreenOffTimeBase, in));
10533                 }
10534 
10535                 int numServs = in.readInt();
10536                 mServiceStats.clear();
10537                 for (int m = 0; m < numServs; m++) {
10538                     String serviceName = in.readString();
10539                     Uid.Pkg.Serv serv = new Serv(mBsi);
10540                     mServiceStats.put(serviceName, serv);
10541 
10542                     serv.readFromParcelLocked(in);
10543                 }
10544             }
10545 
writeToParcelLocked(Parcel out)10546             void writeToParcelLocked(Parcel out) {
10547                 int numWA = mWakeupAlarms.size();
10548                 out.writeInt(numWA);
10549                 for (int i=0; i<numWA; i++) {
10550                     out.writeString(mWakeupAlarms.keyAt(i));
10551                     mWakeupAlarms.valueAt(i).writeToParcel(out);
10552                 }
10553 
10554                 final int NS = mServiceStats.size();
10555                 out.writeInt(NS);
10556                 for (int i=0; i<NS; i++) {
10557                     out.writeString(mServiceStats.keyAt(i));
10558                     Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
10559                     serv.writeToParcelLocked(out);
10560                 }
10561             }
10562 
10563             @Override
getWakeupAlarmStats()10564             public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
10565                 return mWakeupAlarms;
10566             }
10567 
noteWakeupAlarmLocked(String tag)10568             public void noteWakeupAlarmLocked(String tag) {
10569                 Counter c = mWakeupAlarms.get(tag);
10570                 if (c == null) {
10571                     c = new Counter(mBsi.mOnBatteryScreenOffTimeBase);
10572                     mWakeupAlarms.put(tag, c);
10573                 }
10574                 c.stepAtomic();
10575             }
10576 
10577             @Override
getServiceStats()10578             public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
10579                 return mServiceStats;
10580             }
10581 
10582             /**
10583              * The statistics associated with a particular service.
10584              */
10585             public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
10586                 /**
10587                  * BatteryStatsImpl that we are associated with.
10588                  */
10589                 protected BatteryStatsImpl mBsi;
10590 
10591                 /**
10592                  * The android package in which this service resides.
10593                  */
10594                 protected Pkg mPkg;
10595 
10596                 /**
10597                  * Total time (ms in battery uptime) the service has been left started.
10598                  */
10599                 protected long mStartTimeMs;
10600 
10601                 /**
10602                  * If service has been started and not yet stopped, this is
10603                  * when it was started.
10604                  */
10605                 protected long mRunningSinceMs;
10606 
10607                 /**
10608                  * True if we are currently running.
10609                  */
10610                 protected boolean mRunning;
10611 
10612                 /**
10613                  * Total number of times startService() has been called.
10614                  */
10615                 protected int mStarts;
10616 
10617                 /**
10618                  * Total time (ms in battery uptime) the service has been left launched.
10619                  */
10620                 protected long mLaunchedTimeMs;
10621 
10622                 /**
10623                  * If service has been launched and not yet exited, this is
10624                  * when it was launched (ms in battery uptime).
10625                  */
10626                 protected long mLaunchedSinceMs;
10627 
10628                 /**
10629                  * True if we are currently launched.
10630                  */
10631                 protected boolean mLaunched;
10632 
10633                 /**
10634                  * Total number times the service has been launched.
10635                  */
10636                 protected int mLaunches;
10637 
10638                 /**
10639                  * Construct a Serv. Also adds it to the on-battery time base as a listener.
10640                  */
Serv(BatteryStatsImpl bsi)10641                 public Serv(BatteryStatsImpl bsi) {
10642                     mBsi = bsi;
10643                     mBsi.mOnBatteryTimeBase.add(this);
10644                 }
10645 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10646                 public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
10647                         long baseRealtimeUs) {
10648                 }
10649 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10650                 public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
10651                         long baseRealtimeUs) {
10652                 }
10653 
10654                 @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)10655                 public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
10656                     if (detachIfReset) {
10657                         this.detach();
10658                     }
10659                     return true;
10660                 }
10661 
10662                 /**
10663                  * Remove this Serv as a listener from the time base.
10664                  Ms*/
10665                 @Override
detach()10666                 public void detach() {
10667                     mBsi.mOnBatteryTimeBase.remove(this);
10668                 }
10669 
readFromParcelLocked(Parcel in)10670                 public void readFromParcelLocked(Parcel in) {
10671                     mStartTimeMs = in.readLong();
10672                     mRunningSinceMs = in.readLong();
10673                     mRunning = in.readInt() != 0;
10674                     mStarts = in.readInt();
10675                     mLaunchedTimeMs = in.readLong();
10676                     mLaunchedSinceMs = in.readLong();
10677                     mLaunched = in.readInt() != 0;
10678                     mLaunches = in.readInt();
10679                 }
10680 
writeToParcelLocked(Parcel out)10681                 public void writeToParcelLocked(Parcel out) {
10682                     out.writeLong(mStartTimeMs);
10683                     out.writeLong(mRunningSinceMs);
10684                     out.writeInt(mRunning ? 1 : 0);
10685                     out.writeInt(mStarts);
10686                     out.writeLong(mLaunchedTimeMs);
10687                     out.writeLong(mLaunchedSinceMs);
10688                     out.writeInt(mLaunched ? 1 : 0);
10689                     out.writeInt(mLaunches);
10690                 }
10691 
getLaunchTimeToNowLocked(long batteryUptimeMs)10692                 public long getLaunchTimeToNowLocked(long batteryUptimeMs) {
10693                     if (!mLaunched) return mLaunchedTimeMs;
10694                     return mLaunchedTimeMs + batteryUptimeMs - mLaunchedSinceMs;
10695                 }
10696 
getStartTimeToNowLocked(long batteryUptimeMs)10697                 public long getStartTimeToNowLocked(long batteryUptimeMs) {
10698                     if (!mRunning) return mStartTimeMs;
10699                     return mStartTimeMs + batteryUptimeMs - mRunningSinceMs;
10700                 }
10701 
startLaunchedLocked()10702                 public void startLaunchedLocked() {
10703                     startLaunchedLocked(mBsi.mClock.uptimeMillis());
10704                 }
10705 
startLaunchedLocked(long uptimeMs)10706                 public void startLaunchedLocked(long uptimeMs) {
10707                     if (!mLaunched) {
10708                         mLaunches++;
10709                         mLaunchedSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000;
10710                         mLaunched = true;
10711                     }
10712                 }
10713 
stopLaunchedLocked()10714                 public void stopLaunchedLocked() {
10715                     stopLaunchedLocked(mBsi.mClock.uptimeMillis());
10716                 }
10717 
stopLaunchedLocked(long uptimeMs)10718                 public void stopLaunchedLocked(long uptimeMs) {
10719                     if (mLaunched) {
10720                         long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000
10721                                 - mLaunchedSinceMs;
10722                         if (timeMs > 0) {
10723                             mLaunchedTimeMs += timeMs;
10724                         } else {
10725                             mLaunches--;
10726                         }
10727                         mLaunched = false;
10728                     }
10729                 }
10730 
startRunningLocked()10731                 public void startRunningLocked() {
10732                     startRunningLocked(mBsi.mClock.uptimeMillis());
10733                 }
10734 
startRunningLocked(long uptimeMs)10735                 public void startRunningLocked(long uptimeMs) {
10736                     if (!mRunning) {
10737                         mStarts++;
10738                         mRunningSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000;
10739                         mRunning = true;
10740                     }
10741                 }
10742 
stopRunningLocked()10743                 public void stopRunningLocked() {
10744                     stopRunningLocked(mBsi.mClock.uptimeMillis());
10745                 }
10746 
stopRunningLocked(long uptimeMs)10747                 public void stopRunningLocked(long uptimeMs) {
10748                     if (mRunning) {
10749                         long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000
10750                                 - mRunningSinceMs;
10751                         if (timeMs > 0) {
10752                             mStartTimeMs += timeMs;
10753                         } else {
10754                             mStarts--;
10755                         }
10756                         mRunning = false;
10757                     }
10758                 }
10759 
getBatteryStats()10760                 public BatteryStatsImpl getBatteryStats() {
10761                     return mBsi;
10762                 }
10763 
10764                 @Override
getLaunches(int which)10765                 public int getLaunches(int which) {
10766                     return mLaunches;
10767                 }
10768 
10769                 @Override
getStartTime(long now, int which)10770                 public long getStartTime(long now, int which) {
10771                     return getStartTimeToNowLocked(now);
10772                 }
10773 
10774                 @Override
getStarts(int which)10775                 public int getStarts(int which) {
10776                     return mStarts;
10777                 }
10778             }
10779 
newServiceStatsLocked()10780             final Serv newServiceStatsLocked() {
10781                 return new Serv(mBsi);
10782             }
10783         }
10784 
10785         private class ChildUid {
10786             public final TimeMultiStateCounter cpuActiveCounter;
10787             public final LongArrayMultiStateCounter cpuTimeInFreqCounter;
10788 
ChildUid()10789             ChildUid() {
10790                 final long timestampMs = mBsi.mClock.elapsedRealtime();
10791                 cpuActiveCounter =
10792                         new TimeMultiStateCounter(mBsi.mOnBatteryTimeBase, 1, timestampMs);
10793                 cpuActiveCounter.setState(0, timestampMs);
10794 
10795                 if (mBsi.trackPerProcStateCpuTimes()) {
10796                     final int cpuFreqCount = mBsi.mCpuScalingPolicies.getScalingStepCount();
10797 
10798                     cpuTimeInFreqCounter = new LongArrayMultiStateCounter(1, cpuFreqCount);
10799 
10800                     // Set initial values to all 0. This is a child UID and we want to include
10801                     // the entirety of its CPU time-in-freq stats into the parent's stats.
10802                     cpuTimeInFreqCounter.updateValues(
10803                             new LongArrayMultiStateCounter.LongArrayContainer(cpuFreqCount),
10804                             timestampMs);
10805                 } else {
10806                     cpuTimeInFreqCounter = null;
10807                 }
10808             }
10809         }
10810 
10811         /**
10812          * Retrieve the statistics object for a particular process, creating
10813          * if needed.
10814          */
getProcessStatsLocked(String name)10815         public Proc getProcessStatsLocked(String name) {
10816             Proc ps = mProcessStats.get(name);
10817             if (ps == null) {
10818                 ps = new Proc(mBsi, name);
10819                 mProcessStats.put(name, ps);
10820             }
10821 
10822             return ps;
10823         }
10824 
10825         @GuardedBy("mBsi")
updateUidProcessStateLocked(int procState, long elapsedRealtimeMs, long uptimeMs)10826         public void updateUidProcessStateLocked(int procState,
10827                 long elapsedRealtimeMs, long uptimeMs) {
10828             int uidRunningState;
10829             // Make special note of Foreground Services
10830             final boolean userAwareService = ActivityManager.isForegroundService(procState);
10831             uidRunningState = BatteryStats.mapToInternalProcessState(procState);
10832 
10833             if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
10834                 return;
10835             }
10836 
10837             if (mProcessState != uidRunningState) {
10838                 if (mProcessState != Uid.PROCESS_STATE_NONEXISTENT) {
10839                     mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
10840                 }
10841                 if (uidRunningState != Uid.PROCESS_STATE_NONEXISTENT) {
10842                     if (mProcessStateTimer[uidRunningState] == null) {
10843                         makeProcessState(uidRunningState, null);
10844                     }
10845                     mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
10846                 }
10847 
10848                 if (!mBsi.mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)
10849                         && mBsi.trackPerProcStateCpuTimes()) {
10850                     mBsi.updateProcStateCpuTimesLocked(mUid, elapsedRealtimeMs, uptimeMs);
10851 
10852                     LongArrayMultiStateCounter onBatteryCounter =
10853                             getProcStateTimeCounter(elapsedRealtimeMs).getCounter();
10854                     LongArrayMultiStateCounter onBatteryScreenOffCounter =
10855                             getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter();
10856 
10857                     onBatteryCounter.setState(uidRunningState, elapsedRealtimeMs);
10858                     onBatteryScreenOffCounter.setState(uidRunningState, elapsedRealtimeMs);
10859                 }
10860 
10861                 final int prevBatteryConsumerProcessState =
10862                         mapUidProcessStateToBatteryConsumerProcessState(mProcessState);
10863 
10864                 mProcessState = uidRunningState;
10865 
10866                 updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
10867                 updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
10868 
10869                 final int batteryConsumerProcessState =
10870                         mapUidProcessStateToBatteryConsumerProcessState(uidRunningState);
10871                 if (mBsi.mSystemReady && mBsi.mPowerStatsCollectorEnabled.get(
10872                         BatteryConsumer.POWER_COMPONENT_CPU)) {
10873                     mBsi.mHistory.recordProcessStateChange(elapsedRealtimeMs, uptimeMs, mUid,
10874                             batteryConsumerProcessState);
10875                 }
10876                 getCpuActiveTimeCounter().setState(batteryConsumerProcessState, elapsedRealtimeMs);
10877 
10878                 getMobileRadioActiveTimeCounter()
10879                         .setState(batteryConsumerProcessState, elapsedRealtimeMs);
10880 
10881                 final ControllerActivityCounterImpl wifiControllerActivity =
10882                         getWifiControllerActivity();
10883                 if (wifiControllerActivity != null) {
10884                     wifiControllerActivity.setState(batteryConsumerProcessState, elapsedRealtimeMs);
10885                 }
10886 
10887                 final ControllerActivityCounterImpl bluetoothControllerActivity =
10888                         getBluetoothControllerActivity();
10889                 if (bluetoothControllerActivity != null) {
10890                     bluetoothControllerActivity.setState(batteryConsumerProcessState,
10891                             elapsedRealtimeMs);
10892                 }
10893 
10894                 final EnergyConsumerStats energyStats =
10895                         getOrCreateEnergyConsumerStatsIfSupportedLocked();
10896                 if (energyStats != null) {
10897                     energyStats.setState(batteryConsumerProcessState, elapsedRealtimeMs);
10898                 }
10899                 maybeScheduleExternalStatsSync(prevBatteryConsumerProcessState,
10900                         batteryConsumerProcessState);
10901             }
10902 
10903             if (userAwareService != mInForegroundService) {
10904                 if (userAwareService) {
10905                     noteForegroundServiceResumedLocked(elapsedRealtimeMs);
10906                 } else {
10907                     noteForegroundServicePausedLocked(elapsedRealtimeMs);
10908                 }
10909                 mInForegroundService = userAwareService;
10910             }
10911         }
10912 
10913         @GuardedBy("mBsi")
maybeScheduleExternalStatsSync( @atteryConsumer.ProcessState int oldProcessState, @BatteryConsumer.ProcessState int newProcessState)10914         private void maybeScheduleExternalStatsSync(
10915                 @BatteryConsumer.ProcessState int oldProcessState,
10916                 @BatteryConsumer.ProcessState int newProcessState) {
10917             if (oldProcessState == newProcessState) {
10918                 return;
10919             }
10920             // Transitions between BACKGROUND and such non-foreground states like cached
10921             // or nonexistent do not warrant doing a sync.  If some of the stats for those
10922             // proc states bleed into the PROCESS_STATE_BACKGROUND, that's ok.
10923             if ((oldProcessState == BatteryConsumer.PROCESS_STATE_UNSPECIFIED
10924                     && newProcessState == BatteryConsumer.PROCESS_STATE_BACKGROUND)
10925                     || (oldProcessState == BatteryConsumer.PROCESS_STATE_BACKGROUND
10926                     && newProcessState == BatteryConsumer.PROCESS_STATE_UNSPECIFIED)) {
10927                 return;
10928             }
10929 
10930             int flags = ExternalStatsSync.UPDATE_ON_PROC_STATE_CHANGE;
10931             // Skip querying for inactive radio, where power usage is probably negligible.
10932             if (!BatteryStatsImpl.isActiveRadioPowerState(mBsi.mMobileRadioPowerState)) {
10933                 flags &= ~ExternalStatsSync.UPDATE_RADIO;
10934             }
10935 
10936             mBsi.mExternalSync.scheduleSyncDueToProcessStateChange(flags,
10937                     mBsi.mConstants.PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
10938         }
10939 
10940         /** Whether to consider Uid to be in the background for background timebase purposes. */
isInBackground()10941         public boolean isInBackground() {
10942             // Note that PROCESS_STATE_CACHED and Uid.PROCESS_STATE_NONEXISTENT is
10943             // also considered to be 'background' for our purposes, because it's not foreground.
10944             return mProcessState >= PROCESS_STATE_BACKGROUND;
10945         }
10946 
updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs)10947         public boolean updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs) {
10948             boolean on = mBsi.mOnBatteryTimeBase.isRunning() && isInBackground();
10949             return mOnBatteryBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
10950         }
10951 
updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs)10952         public boolean updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs) {
10953             boolean on = mBsi.mOnBatteryScreenOffTimeBase.isRunning() && isInBackground();
10954             return mOnBatteryScreenOffBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
10955         }
10956 
getPidStats()10957         public SparseArray<? extends Pid> getPidStats() {
10958             return mPids;
10959         }
10960 
getPidStatsLocked(int pid)10961         public Pid getPidStatsLocked(int pid) {
10962             Pid p = mPids.get(pid);
10963             if (p == null) {
10964                 p = new Pid();
10965                 mPids.put(pid, p);
10966             }
10967             return p;
10968         }
10969 
10970         /**
10971          * Retrieve the statistics object for a particular service, creating
10972          * if needed.
10973          */
getPackageStatsLocked(String name)10974         public Pkg getPackageStatsLocked(String name) {
10975             Pkg ps = mPackageStats.get(name);
10976             if (ps == null) {
10977                 ps = new Pkg(mBsi);
10978                 mPackageStats.put(name, ps);
10979             }
10980 
10981             return ps;
10982         }
10983 
10984         /**
10985          * Retrieve the statistics object for a particular service, creating
10986          * if needed.
10987          */
getServiceStatsLocked(String pkg, String serv)10988         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
10989             Pkg ps = getPackageStatsLocked(pkg);
10990             Pkg.Serv ss = ps.mServiceStats.get(serv);
10991             if (ss == null) {
10992                 ss = ps.newServiceStatsLocked();
10993                 ps.mServiceStats.put(serv, ss);
10994             }
10995 
10996             return ss;
10997         }
10998 
readSyncSummaryFromParcelLocked(String name, Parcel in)10999         public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
11000             DualTimer timer = mSyncStats.instantiateObject();
11001             timer.readSummaryFromParcelLocked(in);
11002             mSyncStats.add(name, timer);
11003         }
11004 
readJobSummaryFromParcelLocked(String name, Parcel in)11005         public void readJobSummaryFromParcelLocked(String name, Parcel in) {
11006             DualTimer timer = mJobStats.instantiateObject();
11007             timer.readSummaryFromParcelLocked(in);
11008             mJobStats.add(name, timer);
11009         }
11010 
readWakeSummaryFromParcelLocked(String wlName, Parcel in)11011         public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
11012             Wakelock wl = new Wakelock(mBsi, this);
11013             mWakelockStats.add(wlName, wl);
11014             if (in.readInt() != 0) {
11015                 getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
11016             }
11017             if (in.readInt() != 0) {
11018                 getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
11019             }
11020             if (in.readInt() != 0) {
11021                 getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
11022             }
11023             if (in.readInt() != 0) {
11024                 getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
11025             }
11026         }
11027 
getSensorTimerLocked(int sensor, boolean create)11028         public DualTimer getSensorTimerLocked(int sensor, boolean create) {
11029             Sensor se = mSensorStats.get(sensor);
11030             if (se == null) {
11031                 if (!create) {
11032                     return null;
11033                 }
11034                 se = new Sensor(mBsi, this, sensor);
11035                 mSensorStats.put(sensor, se);
11036             }
11037             DualTimer t = se.mTimer;
11038             if (t != null) {
11039                 return t;
11040             }
11041             ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
11042             if (timers == null) {
11043                 timers = new ArrayList<StopwatchTimer>();
11044                 mBsi.mSensorTimers.put(sensor, timers);
11045             }
11046             t = new DualTimer(mBsi.mClock, this, BatteryStats.SENSOR, timers,
11047                     mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
11048             se.mTimer = t;
11049             return t;
11050         }
11051 
noteStartSyncLocked(String name, long elapsedRealtimeMs)11052         public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
11053             DualTimer t = mSyncStats.startObject(name, elapsedRealtimeMs);
11054             if (t != null) {
11055                 t.startRunningLocked(elapsedRealtimeMs);
11056             }
11057         }
11058 
noteStopSyncLocked(String name, long elapsedRealtimeMs)11059         public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
11060             DualTimer t = mSyncStats.stopObject(name, elapsedRealtimeMs);
11061             if (t != null) {
11062                 t.stopRunningLocked(elapsedRealtimeMs);
11063             }
11064         }
11065 
noteStartJobLocked(String name, long elapsedRealtimeMs)11066         public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
11067             DualTimer t = mJobStats.startObject(name, elapsedRealtimeMs);
11068             if (t != null) {
11069                 t.startRunningLocked(elapsedRealtimeMs);
11070             }
11071         }
11072 
noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason)11073         public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
11074             DualTimer t = mJobStats.stopObject(name, elapsedRealtimeMs);
11075             if (t != null) {
11076                 t.stopRunningLocked(elapsedRealtimeMs);
11077             }
11078             if (mBsi.mOnBatteryTimeBase.isRunning()) {
11079                 SparseIntArray types = mJobCompletions.get(name);
11080                 if (types == null) {
11081                     types = new SparseIntArray();
11082                     mJobCompletions.put(name, types);
11083                 }
11084                 int last = types.get(stopReason, 0);
11085                 types.put(stopReason, last + 1);
11086             }
11087         }
11088 
getWakelockTimerLocked(Wakelock wl, int type)11089         public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
11090             if (wl == null) {
11091                 return null;
11092             }
11093             switch (type) {
11094                 case WAKE_TYPE_PARTIAL: {
11095                     DualTimer t = wl.mTimerPartial;
11096                     if (t == null) {
11097                         t = new DualTimer(mBsi.mClock, this, WAKE_TYPE_PARTIAL,
11098                                 mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase,
11099                                 mOnBatteryScreenOffBackgroundTimeBase);
11100                         wl.mTimerPartial = t;
11101                     }
11102                     return t;
11103                 }
11104                 case WAKE_TYPE_FULL: {
11105                     StopwatchTimer t = wl.mTimerFull;
11106                     if (t == null) {
11107                         t = new StopwatchTimer(mBsi.mClock, this, WAKE_TYPE_FULL,
11108                                 mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
11109                         wl.mTimerFull = t;
11110                     }
11111                     return t;
11112                 }
11113                 case WAKE_TYPE_WINDOW: {
11114                     StopwatchTimer t = wl.mTimerWindow;
11115                     if (t == null) {
11116                         t = new StopwatchTimer(mBsi.mClock, this, WAKE_TYPE_WINDOW,
11117                                 mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
11118                         wl.mTimerWindow = t;
11119                     }
11120                     return t;
11121                 }
11122                 case WAKE_TYPE_DRAW: {
11123                     StopwatchTimer t = wl.mTimerDraw;
11124                     if (t == null) {
11125                         t = new StopwatchTimer(mBsi.mClock, this, WAKE_TYPE_DRAW,
11126                                 mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
11127                         wl.mTimerDraw = t;
11128                     }
11129                     return t;
11130                 }
11131                 default:
11132                     throw new IllegalArgumentException("type=" + type);
11133             }
11134         }
11135 
noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)11136         public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
11137             Wakelock wl = mWakelockStats.startObject(name, elapsedRealtimeMs);
11138             if (wl != null) {
11139                 getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
11140             }
11141             if (type == WAKE_TYPE_PARTIAL) {
11142                 createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
11143                 if (pid >= 0) {
11144                     Pid p = getPidStatsLocked(pid);
11145                     if (p.mWakeNesting++ == 0) {
11146                         p.mWakeStartMs = elapsedRealtimeMs;
11147                     }
11148                 }
11149             }
11150         }
11151 
noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)11152         public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
11153             Wakelock wl = mWakelockStats.stopObject(name, elapsedRealtimeMs);
11154             if (wl != null) {
11155                 StopwatchTimer wlt = getWakelockTimerLocked(wl, type);
11156                 wlt.stopRunningLocked(elapsedRealtimeMs);
11157             }
11158             if (type == WAKE_TYPE_PARTIAL) {
11159                 if (mAggregatedPartialWakelockTimer != null) {
11160                     mAggregatedPartialWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
11161                 }
11162                 if (pid >= 0) {
11163                     Pid p = mPids.get(pid);
11164                     if (p != null && p.mWakeNesting > 0) {
11165                         if (p.mWakeNesting-- == 1) {
11166                             p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
11167                             p.mWakeStartMs = 0;
11168                         }
11169                     }
11170                 }
11171             }
11172         }
11173 
reportExcessiveCpuLocked(String proc, long overTimeMs, long usedTimeMs)11174         public void reportExcessiveCpuLocked(String proc, long overTimeMs, long usedTimeMs) {
11175             Proc p = getProcessStatsLocked(proc);
11176             if (p != null) {
11177                 p.addExcessiveCpu(overTimeMs, usedTimeMs);
11178             }
11179         }
11180 
noteStartSensor(int sensor, long elapsedRealtimeMs)11181         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
11182             DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
11183             t.startRunningLocked(elapsedRealtimeMs);
11184         }
11185 
noteStopSensor(int sensor, long elapsedRealtimeMs)11186         public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
11187             // Don't create a timer if one doesn't already exist
11188             DualTimer t = getSensorTimerLocked(sensor, false);
11189             if (t != null) {
11190                 t.stopRunningLocked(elapsedRealtimeMs);
11191             }
11192         }
11193 
noteStartGps(long elapsedRealtimeMs)11194         public void noteStartGps(long elapsedRealtimeMs) {
11195             noteStartSensor(Sensor.GPS, elapsedRealtimeMs);
11196         }
11197 
noteStopGps(long elapsedRealtimeMs)11198         public void noteStopGps(long elapsedRealtimeMs) {
11199             noteStopSensor(Sensor.GPS, elapsedRealtimeMs);
11200         }
11201     }
11202 
11203     @GuardedBy("this")
getCpuScalingPolicies()11204     public CpuScalingPolicies getCpuScalingPolicies() {
11205         return mCpuScalingPolicies;
11206     }
11207 
11208     @GuardedBy("this")
getCpuTimeInFreqContainer()11209     private LongArrayMultiStateCounter.LongArrayContainer getCpuTimeInFreqContainer() {
11210         if (mTmpCpuTimeInFreq == null) {
11211             mTmpCpuTimeInFreq =
11212                     new LongArrayMultiStateCounter.LongArrayContainer(
11213                             mCpuScalingPolicies.getScalingStepCount());
11214         }
11215         return mTmpCpuTimeInFreq;
11216     }
11217 
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)11218     public BatteryStatsImpl(@NonNull BatteryStatsConfig config, @NonNull Clock clock,
11219             @NonNull MonotonicClock monotonicClock, @Nullable File systemDir,
11220             @NonNull Handler handler, @Nullable PlatformIdleStateCallback platformIdleStateCallback,
11221             @Nullable EnergyStatsRetriever energyStatsRetriever,
11222             @NonNull UserInfoProvider userInfoProvider, @NonNull PowerProfile powerProfile,
11223             @NonNull CpuScalingPolicies cpuScalingPolicies,
11224             @NonNull PowerStatsUidResolver powerStatsUidResolver) {
11225         this(config, clock, monotonicClock, systemDir, handler, platformIdleStateCallback,
11226                 energyStatsRetriever, userInfoProvider, powerProfile, cpuScalingPolicies,
11227                 powerStatsUidResolver, new FrameworkStatsLogger(),
11228                 new BatteryStatsHistory.TraceDelegate(), new BatteryStatsHistory.EventLogger());
11229     }
11230 
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, @NonNull FrameworkStatsLogger frameworkStatsLogger, @NonNull BatteryStatsHistory.TraceDelegate traceDelegate, @NonNull BatteryStatsHistory.EventLogger eventLogger)11231     public BatteryStatsImpl(@NonNull BatteryStatsConfig config, @NonNull Clock clock,
11232             @NonNull MonotonicClock monotonicClock, @Nullable File systemDir,
11233             @NonNull Handler handler, @Nullable PlatformIdleStateCallback platformIdleStateCallback,
11234             @Nullable EnergyStatsRetriever energyStatsRetriever,
11235             @NonNull UserInfoProvider userInfoProvider, @NonNull PowerProfile powerProfile,
11236             @NonNull CpuScalingPolicies cpuScalingPolicies,
11237             @NonNull PowerStatsUidResolver powerStatsUidResolver,
11238             @NonNull FrameworkStatsLogger frameworkStatsLogger,
11239             @NonNull BatteryStatsHistory.TraceDelegate traceDelegate,
11240             @NonNull BatteryStatsHistory.EventLogger eventLogger) {
11241         mClock = clock;
11242         initKernelStatsReaders();
11243 
11244         mBatteryStatsConfig = config;
11245         mMonotonicClock = monotonicClock;
11246         mHandler = new MyHandler(handler.getLooper());
11247         mConstants = new Constants(mHandler);
11248 
11249         mPowerProfile = powerProfile;
11250         mCpuScalingPolicies = cpuScalingPolicies;
11251         mPowerStatsUidResolver = powerStatsUidResolver;
11252         mFrameworkStatsLogger = frameworkStatsLogger;
11253 
11254         initPowerProfile();
11255 
11256         if (systemDir != null) {
11257             mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
11258             mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
11259             mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
11260         } else {
11261             mStatsFile = null;
11262             mCheckinFile = null;
11263             mDailyFile = null;
11264         }
11265 
11266         mHistory = new BatteryStatsHistory(null /* historyBuffer */, systemDir,
11267                 mConstants.MAX_HISTORY_FILES, mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator,
11268                 mClock, mMonotonicClock, traceDelegate, eventLogger);
11269 
11270         mCpuPowerStatsCollector = new CpuPowerStatsCollector(mPowerStatsCollectorInjector);
11271         mCpuPowerStatsCollector.addConsumer(this::recordPowerStats);
11272 
11273         mMobileRadioPowerStatsCollector = new MobileRadioPowerStatsCollector(
11274                 mPowerStatsCollectorInjector);
11275         mMobileRadioPowerStatsCollector.addConsumer(this::recordPowerStats);
11276 
11277         mWifiPowerStatsCollector = new WifiPowerStatsCollector(mPowerStatsCollectorInjector);
11278         mWifiPowerStatsCollector.addConsumer(this::recordPowerStats);
11279 
11280         mBluetoothPowerStatsCollector = new BluetoothPowerStatsCollector(
11281                 mPowerStatsCollectorInjector);
11282         mBluetoothPowerStatsCollector.addConsumer(this::recordPowerStats);
11283 
11284         mStartCount++;
11285         initTimersAndCounters();
11286         mOnBattery = mOnBatteryInternal = false;
11287         long uptimeUs = mClock.uptimeMillis() * 1000;
11288         long realtimeUs = mClock.elapsedRealtime() * 1000;
11289         initTimes(uptimeUs, realtimeUs);
11290         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
11291         initDischarge(realtimeUs);
11292         updateDailyDeadlineLocked();
11293         mPlatformIdleStateCallback = platformIdleStateCallback;
11294         mEnergyConsumerRetriever = energyStatsRetriever;
11295         mUserInfoProvider = userInfoProvider;
11296 
11297         mPowerStatsUidResolver.addListener(new PowerStatsUidResolver.Listener() {
11298             @Override
11299             public void onIsolatedUidAdded(int isolatedUid, int parentUid) {
11300                 BatteryStatsImpl.this.onIsolatedUidAdded(isolatedUid, parentUid);
11301             }
11302 
11303             @Override
11304             public void onBeforeIsolatedUidRemoved(int isolatedUid, int parentUid) {
11305                 BatteryStatsImpl.this.onBeforeIsolatedUidRemoved(isolatedUid, parentUid);
11306             }
11307 
11308             @Override
11309             public void onAfterIsolatedUidRemoved(int isolatedUid, int parentUid) {
11310                 BatteryStatsImpl.this.onAfterIsolatedUidRemoved(isolatedUid, parentUid);
11311             }
11312         });
11313 
11314         // Notify statsd that the system is initially not in doze.
11315         mDeviceIdleMode = DEVICE_IDLE_MODE_OFF;
11316         mFrameworkStatsLogger.deviceIdleModeStateChanged(mDeviceIdleMode);
11317     }
11318 
recordPowerStats(PowerStats stats)11319     private void recordPowerStats(PowerStats stats) {
11320         if (stats.durationMs > 0) {
11321             synchronized (this) {
11322                 mHistory.recordPowerStats(mClock.elapsedRealtime(), mClock.uptimeMillis(), stats);
11323             }
11324         }
11325     }
11326 
11327     @VisibleForTesting
initTimersAndCounters()11328     protected void initTimersAndCounters() {
11329         mScreenOnTimer = new StopwatchTimer(mClock, null, -1, null, mOnBatteryTimeBase);
11330         mScreenDozeTimer = new StopwatchTimer(mClock, null, -1, null, mOnBatteryTimeBase);
11331         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11332             mScreenBrightnessTimer[i] = new StopwatchTimer(mClock, null, -100 - i, null,
11333                     mOnBatteryTimeBase);
11334         }
11335 
11336         mPerDisplayBatteryStats = new DisplayBatteryStats[1];
11337         mPerDisplayBatteryStats[0] = new DisplayBatteryStats(mClock, mOnBatteryTimeBase);
11338 
11339         mInteractiveTimer = new StopwatchTimer(mClock, null, -10, null, mOnBatteryTimeBase);
11340         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClock, null, -2, null,
11341                 mOnBatteryTimeBase);
11342         mDeviceIdleModeLightTimer = new StopwatchTimer(mClock, null, -11, null,
11343                 mOnBatteryTimeBase);
11344         mDeviceIdleModeFullTimer = new StopwatchTimer(mClock, null, -14, null, mOnBatteryTimeBase);
11345         mDeviceLightIdlingTimer = new StopwatchTimer(mClock, null, -15, null, mOnBatteryTimeBase);
11346         mDeviceIdlingTimer = new StopwatchTimer(mClock, null, -12, null, mOnBatteryTimeBase);
11347         mPhoneOnTimer = new StopwatchTimer(mClock, null, -3, null, mOnBatteryTimeBase);
11348         for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
11349             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClock, null, -200 - i, null,
11350                     mOnBatteryTimeBase);
11351         }
11352         mPhoneSignalScanningTimer = new StopwatchTimer(mClock, null, -200 + 1, null,
11353                 mOnBatteryTimeBase);
11354         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11355             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClock, null, -300 - i, null,
11356                     mOnBatteryTimeBase);
11357         }
11358         mNrNsaTimer = new StopwatchTimer(mClock, null, -200 + 2, null, mOnBatteryTimeBase);
11359         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11360             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
11361             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
11362         }
11363         mWifiActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
11364                 NUM_WIFI_TX_LEVELS);
11365         mBluetoothActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
11366                 NUM_BT_TX_LEVELS);
11367         mModemActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
11368                 MODEM_TX_POWER_LEVEL_COUNT);
11369         mMobileRadioActiveTimer = new StopwatchTimer(mClock, null, -400, null, mOnBatteryTimeBase);
11370         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClock, null, -401, null,
11371                 mOnBatteryTimeBase);
11372         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
11373         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
11374         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
11375         mWifiMulticastWakelockTimer = new StopwatchTimer(mClock, null,
11376                 WIFI_AGGREGATE_MULTICAST_ENABLED, null, mOnBatteryTimeBase);
11377         mWifiOnTimer = new StopwatchTimer(mClock, null, -4, null, mOnBatteryTimeBase);
11378         mGlobalWifiRunningTimer = new StopwatchTimer(mClock, null, -5, null, mOnBatteryTimeBase);
11379         for (int i=0; i<NUM_WIFI_STATES; i++) {
11380             mWifiStateTimer[i] = new StopwatchTimer(mClock, null, -600 - i, null,
11381                     mOnBatteryTimeBase);
11382         }
11383         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11384             mWifiSupplStateTimer[i] = new StopwatchTimer(mClock, null, -700 - i, null,
11385                     mOnBatteryTimeBase);
11386         }
11387         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11388             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClock, null, -800 - i, null,
11389                     mOnBatteryTimeBase);
11390         }
11391         mWifiActiveTimer = new StopwatchTimer(mClock, null, -900, null, mOnBatteryTimeBase);
11392         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
11393             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClock, null, -1000 - i, null,
11394                     mOnBatteryTimeBase);
11395         }
11396         mAudioOnTimer = new StopwatchTimer(mClock, null, -7, null, mOnBatteryTimeBase);
11397         mVideoOnTimer = new StopwatchTimer(mClock, null, -8, null, mOnBatteryTimeBase);
11398         mFlashlightOnTimer = new StopwatchTimer(mClock, null, -9, null, mOnBatteryTimeBase);
11399         mCameraOnTimer = new StopwatchTimer(mClock, null, -13, null, mOnBatteryTimeBase);
11400         mBluetoothScanTimer = new StopwatchTimer(mClock, null, -14, null, mOnBatteryTimeBase);
11401         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
11402         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
11403         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
11404         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
11405         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
11406         mDischargeUnplugLevel = 0;
11407         mDischargePlugLevel = -1;
11408         mDischargeCurrentLevel = 0;
11409         mBatteryLevel = 0;
11410     }
11411 
initPowerProfile()11412     private void initPowerProfile() {
11413         int[] policies = mCpuScalingPolicies.getPolicies();
11414         mKernelCpuSpeedReaders = new KernelCpuSpeedReader[policies.length];
11415         for (int i = 0; i < policies.length; i++) {
11416             int[] cpus = mCpuScalingPolicies.getRelatedCpus(policies[i]);
11417             int[] freqs = mCpuScalingPolicies.getFrequencies(policies[i]);
11418             // We need to initialize the KernelCpuSpeedReaders to read from
11419             // the first cpu of each core. Once we have the CpuScalingPolicy, we have access to this
11420             // information.
11421             mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(cpus[0], freqs.length);
11422         }
11423 
11424         // Initialize CPU power bracket map, which combines CPU states (cluster/freq pairs)
11425         // into a small number of brackets
11426         mCpuPowerBracketMap = new int[mCpuScalingPolicies.getScalingStepCount()];
11427         int index = 0;
11428         for (int policy : policies) {
11429             int steps = mCpuScalingPolicies.getFrequencies(policy).length;
11430             for (int step = 0; step < steps; step++) {
11431                 mCpuPowerBracketMap[index++] =
11432                         mPowerProfile.getCpuPowerBracketForScalingStep(policy, step);
11433             }
11434         }
11435 
11436         if (mEstimatedBatteryCapacityMah == -1) {
11437             // Initialize the estimated battery capacity to a known preset one.
11438             mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
11439         }
11440 
11441         setDisplayCountLocked(mPowerProfile.getNumDisplays());
11442     }
11443 
getPowerProfile()11444     PowerProfile getPowerProfile() {
11445         return mPowerProfile;
11446     }
11447 
11448     /**
11449      * Starts tracking CPU time-in-state for threads of the system server process,
11450      * keeping a separate account of threads receiving incoming binder calls.
11451      */
startTrackingSystemServerCpuTime()11452     public void startTrackingSystemServerCpuTime() {
11453         mSystemServerCpuThreadReader.startTrackingThreadCpuTime();
11454     }
11455 
getSystemServiceCpuThreadTimes()11456     public SystemServiceCpuThreadTimes getSystemServiceCpuThreadTimes() {
11457         return mSystemServerCpuThreadReader.readAbsolute();
11458     }
11459 
setCallback(BatteryCallback cb)11460     public void setCallback(BatteryCallback cb) {
11461         mCallback = cb;
11462     }
11463 
setRadioScanningTimeoutLocked(long timeoutUs)11464     public void setRadioScanningTimeoutLocked(long timeoutUs) {
11465         if (mPhoneSignalScanningTimer != null) {
11466             mPhoneSignalScanningTimer.setTimeout(timeoutUs);
11467         }
11468     }
11469 
setExternalStatsSyncLocked(ExternalStatsSync sync)11470     public void setExternalStatsSyncLocked(ExternalStatsSync sync) {
11471         mExternalSync = sync;
11472     }
11473 
11474     /**
11475      * Initialize and set multi display timers and states.
11476      */
setDisplayCountLocked(int numDisplays)11477     public void setDisplayCountLocked(int numDisplays) {
11478         mPerDisplayBatteryStats = new DisplayBatteryStats[numDisplays];
11479         for (int i = 0; i < numDisplays; i++) {
11480             mPerDisplayBatteryStats[i] = new DisplayBatteryStats(mClock, mOnBatteryTimeBase);
11481         }
11482     }
11483 
updateDailyDeadlineLocked()11484     public void updateDailyDeadlineLocked() {
11485         // Get the current time.
11486         long currentTimeMs = mDailyStartTimeMs = mClock.currentTimeMillis();
11487         Calendar calDeadline = Calendar.getInstance();
11488         calDeadline.setTimeInMillis(currentTimeMs);
11489 
11490         // Move time up to the next day, ranging from 1am to 3pm.
11491         calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
11492         calDeadline.set(Calendar.MILLISECOND, 0);
11493         calDeadline.set(Calendar.SECOND, 0);
11494         calDeadline.set(Calendar.MINUTE, 0);
11495         calDeadline.set(Calendar.HOUR_OF_DAY, 1);
11496         mNextMinDailyDeadlineMs = calDeadline.getTimeInMillis();
11497         calDeadline.set(Calendar.HOUR_OF_DAY, 3);
11498         mNextMaxDailyDeadlineMs = calDeadline.getTimeInMillis();
11499     }
11500 
recordDailyStatsIfNeededLocked(boolean settled, long currentTimeMs)11501     public void recordDailyStatsIfNeededLocked(boolean settled, long currentTimeMs) {
11502         if (currentTimeMs >= mNextMaxDailyDeadlineMs) {
11503             recordDailyStatsLocked();
11504         } else if (settled && currentTimeMs >= mNextMinDailyDeadlineMs) {
11505             recordDailyStatsLocked();
11506         } else if (currentTimeMs < (mDailyStartTimeMs - (1000 * 60 * 60 * 24))) {
11507             recordDailyStatsLocked();
11508         }
11509     }
11510 
recordDailyStatsLocked()11511     public void recordDailyStatsLocked() {
11512         DailyItem item = new DailyItem();
11513         item.mStartTime = mDailyStartTimeMs;
11514         item.mEndTime = mClock.currentTimeMillis();
11515         boolean hasData = false;
11516         if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
11517             hasData = true;
11518             item.mDischargeSteps = new LevelStepTracker(
11519                     mDailyDischargeStepTracker.mNumStepDurations,
11520                     mDailyDischargeStepTracker.mStepDurations);
11521         }
11522         if (mDailyChargeStepTracker.mNumStepDurations > 0) {
11523             hasData = true;
11524             item.mChargeSteps = new LevelStepTracker(
11525                     mDailyChargeStepTracker.mNumStepDurations,
11526                     mDailyChargeStepTracker.mStepDurations);
11527         }
11528         if (mDailyPackageChanges != null) {
11529             hasData = true;
11530             item.mPackageChanges = mDailyPackageChanges;
11531             mDailyPackageChanges = null;
11532         }
11533         mDailyDischargeStepTracker.init();
11534         mDailyChargeStepTracker.init();
11535         updateDailyDeadlineLocked();
11536 
11537         if (hasData) {
11538             final long startTimeMs = SystemClock.uptimeMillis();
11539             mDailyItems.add(item);
11540             while (mDailyItems.size() > MAX_DAILY_ITEMS) {
11541                 mDailyItems.remove(0);
11542             }
11543             final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
11544             try {
11545                 TypedXmlSerializer out = Xml.resolveSerializer(memStream);
11546                 writeDailyItemsLocked(out);
11547                 final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs;
11548                 BackgroundThread.getHandler().post(new Runnable() {
11549                     @Override
11550                     public void run() {
11551                         synchronized (mCheckinFile) {
11552                             final long startTimeMs2 = SystemClock.uptimeMillis();
11553                             FileOutputStream stream = null;
11554                             try {
11555                                 stream = mDailyFile.startWrite();
11556                                 memStream.writeTo(stream);
11557                                 stream.flush();
11558                                 mDailyFile.finishWrite(stream);
11559                                 mFrameworkStatsLogger.writeCommitSysConfigFile("batterystats-daily",
11560                                         initialTimeMs + SystemClock.uptimeMillis() - startTimeMs2);
11561                             } catch (IOException e) {
11562                                 Slog.w("BatteryStats",
11563                                         "Error writing battery daily items", e);
11564                                 mDailyFile.failWrite(stream);
11565                             }
11566                         }
11567                     }
11568                 });
11569             } catch (IOException e) {
11570             }
11571         }
11572     }
11573 
writeDailyItemsLocked(TypedXmlSerializer out)11574     private void writeDailyItemsLocked(TypedXmlSerializer out) throws IOException {
11575         StringBuilder sb = new StringBuilder(64);
11576         out.startDocument(null, true);
11577         out.startTag(null, "daily-items");
11578         for (int i=0; i<mDailyItems.size(); i++) {
11579             final DailyItem dit = mDailyItems.get(i);
11580             out.startTag(null, "item");
11581             out.attributeLong(null, "start", dit.mStartTime);
11582             out.attributeLong(null, "end", dit.mEndTime);
11583             writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
11584             writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
11585             if (dit.mPackageChanges != null) {
11586                 for (int j=0; j<dit.mPackageChanges.size(); j++) {
11587                     PackageChange pc = dit.mPackageChanges.get(j);
11588                     if (pc.mUpdate) {
11589                         out.startTag(null, "upd");
11590                         out.attribute(null, "pkg", pc.mPackageName);
11591                         out.attributeLong(null, "ver", pc.mVersionCode);
11592                         out.endTag(null, "upd");
11593                     } else {
11594                         out.startTag(null, "rem");
11595                         out.attribute(null, "pkg", pc.mPackageName);
11596                         out.endTag(null, "rem");
11597                     }
11598                 }
11599             }
11600             out.endTag(null, "item");
11601         }
11602         out.endTag(null, "daily-items");
11603         out.endDocument();
11604     }
11605 
writeDailyLevelSteps(TypedXmlSerializer out, String tag, LevelStepTracker steps, StringBuilder tmpBuilder)11606     private void writeDailyLevelSteps(TypedXmlSerializer out, String tag, LevelStepTracker steps,
11607             StringBuilder tmpBuilder) throws IOException {
11608         if (steps != null) {
11609             out.startTag(null, tag);
11610             out.attributeInt(null, "n", steps.mNumStepDurations);
11611             for (int i=0; i<steps.mNumStepDurations; i++) {
11612                 out.startTag(null, "s");
11613                 tmpBuilder.setLength(0);
11614                 steps.encodeEntryAt(i, tmpBuilder);
11615                 out.attribute(null, "v", tmpBuilder.toString());
11616                 out.endTag(null, "s");
11617             }
11618             out.endTag(null, tag);
11619         }
11620     }
11621 
11622     @GuardedBy("this")
readDailyStatsLocked()11623     public void readDailyStatsLocked() {
11624         Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
11625         mDailyItems.clear();
11626         FileInputStream stream;
11627         try {
11628             stream = mDailyFile.openRead();
11629         } catch (FileNotFoundException e) {
11630             return;
11631         }
11632         try {
11633             TypedXmlPullParser parser = Xml.resolvePullParser(stream);
11634             readDailyItemsLocked(parser);
11635         } catch (IOException e) {
11636         } finally {
11637             try {
11638                 stream.close();
11639             } catch (IOException e) {
11640             }
11641         }
11642     }
11643 
readDailyItemsLocked(TypedXmlPullParser parser)11644     private void readDailyItemsLocked(TypedXmlPullParser parser) {
11645         try {
11646             int type;
11647             while ((type = parser.next()) != XmlPullParser.START_TAG
11648                     && type != XmlPullParser.END_DOCUMENT) {
11649                 ;
11650             }
11651 
11652             if (type != XmlPullParser.START_TAG) {
11653                 throw new IllegalStateException("no start tag found");
11654             }
11655 
11656             int outerDepth = parser.getDepth();
11657             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11658                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11659                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11660                     continue;
11661                 }
11662 
11663                 String tagName = parser.getName();
11664                 if (tagName.equals("item")) {
11665                     readDailyItemTagLocked(parser);
11666                 } else {
11667                     Slog.w(TAG, "Unknown element under <daily-items>: "
11668                             + parser.getName());
11669                     XmlUtils.skipCurrentTag(parser);
11670                 }
11671             }
11672 
11673         } catch (IllegalStateException e) {
11674             Slog.w(TAG, "Failed parsing daily " + e);
11675         } catch (NullPointerException e) {
11676             Slog.w(TAG, "Failed parsing daily " + e);
11677         } catch (NumberFormatException e) {
11678             Slog.w(TAG, "Failed parsing daily " + e);
11679         } catch (XmlPullParserException e) {
11680             Slog.w(TAG, "Failed parsing daily " + e);
11681         } catch (IOException e) {
11682             Slog.w(TAG, "Failed parsing daily " + e);
11683         } catch (IndexOutOfBoundsException e) {
11684             Slog.w(TAG, "Failed parsing daily " + e);
11685         }
11686     }
11687 
readDailyItemTagLocked(TypedXmlPullParser parser)11688     void readDailyItemTagLocked(TypedXmlPullParser parser) throws NumberFormatException,
11689             XmlPullParserException, IOException {
11690         DailyItem dit = new DailyItem();
11691         dit.mStartTime = parser.getAttributeLong(null, "start", 0);
11692         dit.mEndTime = parser.getAttributeLong(null, "end", 0);
11693         int outerDepth = parser.getDepth();
11694         int type;
11695         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11696                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11697             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11698                 continue;
11699             }
11700 
11701             String tagName = parser.getName();
11702             if (tagName.equals("dis")) {
11703                 readDailyItemTagDetailsLocked(parser, dit, false, "dis");
11704             } else if (tagName.equals("chg")) {
11705                 readDailyItemTagDetailsLocked(parser, dit, true, "chg");
11706             } else if (tagName.equals("upd")) {
11707                 if (dit.mPackageChanges == null) {
11708                     dit.mPackageChanges = new ArrayList<>();
11709                 }
11710                 PackageChange pc = new PackageChange();
11711                 pc.mUpdate = true;
11712                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
11713                 pc.mVersionCode = parser.getAttributeLong(null, "ver", 0);
11714                 dit.mPackageChanges.add(pc);
11715                 XmlUtils.skipCurrentTag(parser);
11716             } else if (tagName.equals("rem")) {
11717                 if (dit.mPackageChanges == null) {
11718                     dit.mPackageChanges = new ArrayList<>();
11719                 }
11720                 PackageChange pc = new PackageChange();
11721                 pc.mUpdate = false;
11722                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
11723                 dit.mPackageChanges.add(pc);
11724                 XmlUtils.skipCurrentTag(parser);
11725             } else {
11726                 Slog.w(TAG, "Unknown element under <item>: "
11727                         + parser.getName());
11728                 XmlUtils.skipCurrentTag(parser);
11729             }
11730         }
11731         mDailyItems.add(dit);
11732     }
11733 
readDailyItemTagDetailsLocked(TypedXmlPullParser parser, DailyItem dit, boolean isCharge, String tag)11734     void readDailyItemTagDetailsLocked(TypedXmlPullParser parser, DailyItem dit, boolean isCharge,
11735             String tag)
11736             throws NumberFormatException, XmlPullParserException, IOException {
11737         final int num = parser.getAttributeInt(null, "n", -1);
11738         if (num == -1) {
11739             Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
11740             XmlUtils.skipCurrentTag(parser);
11741             return;
11742         }
11743         LevelStepTracker steps = new LevelStepTracker(num);
11744         if (isCharge) {
11745             dit.mChargeSteps = steps;
11746         } else {
11747             dit.mDischargeSteps = steps;
11748         }
11749         int i = 0;
11750         int outerDepth = parser.getDepth();
11751         int type;
11752         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11753                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11754             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11755                 continue;
11756             }
11757 
11758             String tagName = parser.getName();
11759             if ("s".equals(tagName)) {
11760                 if (i < num) {
11761                     String valueAttr = parser.getAttributeValue(null, "v");
11762                     if (valueAttr != null) {
11763                         steps.decodeEntryAt(i, valueAttr);
11764                         i++;
11765                     }
11766                 }
11767             } else {
11768                 Slog.w(TAG, "Unknown element under <" + tag + ">: "
11769                         + parser.getName());
11770                 XmlUtils.skipCurrentTag(parser);
11771             }
11772         }
11773         steps.mNumStepDurations = i;
11774     }
11775 
11776     @Override
getDailyItemLocked(int daysAgo)11777     public DailyItem getDailyItemLocked(int daysAgo) {
11778         int index = mDailyItems.size()-1-daysAgo;
11779         return index >= 0 ? mDailyItems.get(index) : null;
11780     }
11781 
11782     @Override
getCurrentDailyStartTime()11783     public long getCurrentDailyStartTime() {
11784         return mDailyStartTimeMs;
11785     }
11786 
11787     @Override
getNextMinDailyDeadline()11788     public long getNextMinDailyDeadline() {
11789         return mNextMinDailyDeadlineMs;
11790     }
11791 
11792     @Override
getNextMaxDailyDeadline()11793     public long getNextMaxDailyDeadline() {
11794         return mNextMaxDailyDeadlineMs;
11795     }
11796 
11797     @GuardedBy("this")
getHistoryTotalSize()11798     public int getHistoryTotalSize() {
11799         return mConstants.MAX_HISTORY_BUFFER * mConstants.MAX_HISTORY_FILES;
11800     }
11801 
getHistoryUsedSize()11802     public int getHistoryUsedSize() {
11803         return mHistory.getHistoryUsedSize();
11804     }
11805 
11806     /**
11807      * Creates an iterator for battery stats history.
11808      */
11809     @Override
iterateBatteryStatsHistory(long startTimeMs, long endTimeMs)11810     public BatteryStatsHistoryIterator iterateBatteryStatsHistory(long startTimeMs,
11811             long endTimeMs) {
11812         return mHistory.iterate(startTimeMs, endTimeMs);
11813     }
11814 
11815     @Override
getHistoryStringPoolSize()11816     public int getHistoryStringPoolSize() {
11817         return mHistory.getHistoryStringPoolSize();
11818     }
11819 
11820     @Override
getHistoryStringPoolBytes()11821     public int getHistoryStringPoolBytes() {
11822         return mHistory.getHistoryStringPoolBytes();
11823     }
11824 
11825     @Override
getHistoryTagPoolString(int index)11826     public String getHistoryTagPoolString(int index) {
11827         return mHistory.getHistoryTagPoolString(index);
11828     }
11829 
11830     @Override
getHistoryTagPoolUid(int index)11831     public int getHistoryTagPoolUid(int index) {
11832         return mHistory.getHistoryTagPoolUid(index);
11833     }
11834 
11835     @Override
getStartCount()11836     public int getStartCount() {
11837         return mStartCount;
11838     }
11839 
isOnBattery()11840     public boolean isOnBattery() {
11841         return mOnBattery;
11842     }
11843 
isCharging()11844     public boolean isCharging() {
11845         return mCharging;
11846     }
11847 
initTimes(long uptimeUs, long realtimeUs)11848     void initTimes(long uptimeUs, long realtimeUs) {
11849         mStartClockTimeMs = mClock.currentTimeMillis();
11850         mOnBatteryTimeBase.init(uptimeUs, realtimeUs);
11851         mOnBatteryScreenOffTimeBase.init(uptimeUs, realtimeUs);
11852         mRealtimeUs = 0;
11853         mUptimeUs = 0;
11854         mRealtimeStartUs = realtimeUs;
11855         mUptimeStartUs = uptimeUs;
11856         mMonotonicStartTime = mMonotonicClock.monotonicTime();
11857     }
11858 
initDischarge(long elapsedRealtimeUs)11859     void initDischarge(long elapsedRealtimeUs) {
11860         mLowDischargeAmountSinceCharge = 0;
11861         mHighDischargeAmountSinceCharge = 0;
11862         mDischargeAmountScreenOn = 0;
11863         mDischargeAmountScreenOnSinceCharge = 0;
11864         mDischargeAmountScreenOff = 0;
11865         mDischargeAmountScreenOffSinceCharge = 0;
11866         mDischargeAmountScreenDoze = 0;
11867         mDischargeAmountScreenDozeSinceCharge = 0;
11868         mDischargeStepTracker.init();
11869         mChargeStepTracker.init();
11870         mDischargeScreenOffCounter.reset(false, elapsedRealtimeUs);
11871         mDischargeScreenDozeCounter.reset(false, elapsedRealtimeUs);
11872         mDischargeLightDozeCounter.reset(false, elapsedRealtimeUs);
11873         mDischargeDeepDozeCounter.reset(false, elapsedRealtimeUs);
11874         mDischargeCounter.reset(false, elapsedRealtimeUs);
11875     }
11876 
11877     /**
11878      * Associates the BatteryStatsImpl object with a BatteryUsageStatsProvider and PowerStatsStore
11879      * to allow for a snapshot of battery usage stats to be taken and stored just before battery
11880      * reset.
11881      */
saveBatteryUsageStatsOnReset( @onNull BatteryUsageStatsProvider batteryUsageStatsProvider, @NonNull PowerStatsStore powerStatsStore)11882     public void saveBatteryUsageStatsOnReset(
11883             @NonNull BatteryUsageStatsProvider batteryUsageStatsProvider,
11884             @NonNull PowerStatsStore powerStatsStore) {
11885         mSaveBatteryUsageStatsOnReset = true;
11886         mBatteryUsageStatsProvider = batteryUsageStatsProvider;
11887         mPowerStatsStore = powerStatsStore;
11888     }
11889 
11890     @GuardedBy("this")
resetAllStatsAndHistoryLocked(int reason)11891     public void resetAllStatsAndHistoryLocked(int reason) {
11892         final long mSecUptime = mClock.uptimeMillis();
11893         long uptimeUs = mSecUptime * 1000;
11894         long mSecRealtime = mClock.elapsedRealtime();
11895         long realtimeUs = mSecRealtime * 1000;
11896         resetAllStatsLocked(mSecUptime, mSecRealtime, reason);
11897         pullPendingStateUpdatesLocked();
11898         mHistory.writeHistoryItem(mSecRealtime, mSecUptime);
11899         mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel = mBatteryLevel;
11900         mOnBatteryTimeBase.reset(uptimeUs, realtimeUs);
11901         mOnBatteryScreenOffTimeBase.reset(uptimeUs, realtimeUs);
11902         if (!mBatteryPluggedIn) {
11903             if (Display.isOnState(mScreenState)) {
11904                 mDischargeScreenOnUnplugLevel = mBatteryLevel;
11905                 mDischargeScreenDozeUnplugLevel = 0;
11906                 mDischargeScreenOffUnplugLevel = 0;
11907             } else if (Display.isDozeState(mScreenState)) {
11908                 mDischargeScreenOnUnplugLevel = 0;
11909                 mDischargeScreenDozeUnplugLevel = mBatteryLevel;
11910                 mDischargeScreenOffUnplugLevel = 0;
11911             } else {
11912                 mDischargeScreenOnUnplugLevel = 0;
11913                 mDischargeScreenDozeUnplugLevel = 0;
11914                 mDischargeScreenOffUnplugLevel = mBatteryLevel;
11915             }
11916             mDischargeAmountScreenOn = 0;
11917             mDischargeAmountScreenOff = 0;
11918             mDischargeAmountScreenDoze = 0;
11919         }
11920         initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
11921     }
11922 
11923     @GuardedBy("this")
resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis, int resetReason)11924     private void resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis,
11925             int resetReason) {
11926         saveBatteryUsageStatsOnReset(resetReason);
11927 
11928         final long uptimeUs = uptimeMillis * 1000;
11929         final long elapsedRealtimeUs = elapsedRealtimeMillis * 1000;
11930         mStartCount = 0;
11931         initTimes(uptimeUs, elapsedRealtimeUs);
11932         mScreenOnTimer.reset(false, elapsedRealtimeUs);
11933         mScreenDozeTimer.reset(false, elapsedRealtimeUs);
11934         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11935             mScreenBrightnessTimer[i].reset(false, elapsedRealtimeUs);
11936         }
11937 
11938         final int numDisplays = mPerDisplayBatteryStats.length;
11939         for (int i = 0; i < numDisplays; i++) {
11940             mPerDisplayBatteryStats[i].reset(elapsedRealtimeUs);
11941         }
11942 
11943         if (mPowerProfile != null) {
11944             mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
11945         } else {
11946             mEstimatedBatteryCapacityMah = -1;
11947         }
11948         mLastLearnedBatteryCapacityUah = -1;
11949         mMinLearnedBatteryCapacityUah = -1;
11950         mMaxLearnedBatteryCapacityUah = -1;
11951         mInteractiveTimer.reset(false, elapsedRealtimeUs);
11952         mPowerSaveModeEnabledTimer.reset(false, elapsedRealtimeUs);
11953         mLastIdleTimeStartMs = elapsedRealtimeMillis;
11954         mLongestLightIdleTimeMs = 0;
11955         mLongestFullIdleTimeMs = 0;
11956         mDeviceIdleModeLightTimer.reset(false, elapsedRealtimeUs);
11957         mDeviceIdleModeFullTimer.reset(false, elapsedRealtimeUs);
11958         mDeviceLightIdlingTimer.reset(false, elapsedRealtimeUs);
11959         mDeviceIdlingTimer.reset(false, elapsedRealtimeUs);
11960         mPhoneOnTimer.reset(false, elapsedRealtimeUs);
11961         mAudioOnTimer.reset(false, elapsedRealtimeUs);
11962         mVideoOnTimer.reset(false, elapsedRealtimeUs);
11963         mFlashlightOnTimer.reset(false, elapsedRealtimeUs);
11964         mCameraOnTimer.reset(false, elapsedRealtimeUs);
11965         mBluetoothScanTimer.reset(false, elapsedRealtimeUs);
11966         for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
11967             mPhoneSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs);
11968         }
11969         mPhoneSignalScanningTimer.reset(false, elapsedRealtimeUs);
11970         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11971             mPhoneDataConnectionsTimer[i].reset(false, elapsedRealtimeUs);
11972         }
11973         mNrNsaTimer.reset(false, elapsedRealtimeUs);
11974         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11975             mNetworkByteActivityCounters[i].reset(false, elapsedRealtimeUs);
11976             mNetworkPacketActivityCounters[i].reset(false, elapsedRealtimeUs);
11977         }
11978         for (int i = 0; i < RADIO_ACCESS_TECHNOLOGY_COUNT; i++) {
11979             final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[i];
11980             if (stats == null) continue;
11981             stats.reset(elapsedRealtimeUs);
11982         }
11983         mMobileRadioActiveTimer.reset(false, elapsedRealtimeUs);
11984         mMobileRadioActivePerAppTimer.reset(false, elapsedRealtimeUs);
11985         mMobileRadioActiveAdjustedTime.reset(false, elapsedRealtimeUs);
11986         mMobileRadioActiveUnknownTime.reset(false, elapsedRealtimeUs);
11987         mMobileRadioActiveUnknownCount.reset(false, elapsedRealtimeUs);
11988         mWifiOnTimer.reset(false, elapsedRealtimeUs);
11989         mGlobalWifiRunningTimer.reset(false, elapsedRealtimeUs);
11990         for (int i=0; i<NUM_WIFI_STATES; i++) {
11991             mWifiStateTimer[i].reset(false, elapsedRealtimeUs);
11992         }
11993         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11994             mWifiSupplStateTimer[i].reset(false, elapsedRealtimeUs);
11995         }
11996         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11997             mWifiSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs);
11998         }
11999         mWifiMulticastWakelockTimer.reset(false, elapsedRealtimeUs);
12000         mWifiActiveTimer.reset(false, elapsedRealtimeUs);
12001         mWifiActivity.reset(false, elapsedRealtimeUs);
12002         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
12003             mGpsSignalQualityTimer[i].reset(false, elapsedRealtimeUs);
12004         }
12005         mBluetoothActivity.reset(false, elapsedRealtimeUs);
12006         mModemActivity.reset(false, elapsedRealtimeUs);
12007         mNumConnectivityChange = 0;
12008 
12009         for (int i=0; i<mUidStats.size(); i++) {
12010             if (mUidStats.valueAt(i).reset(uptimeUs, elapsedRealtimeUs, resetReason)) {
12011                 mUidStats.valueAt(i).detachFromTimeBase();
12012                 mUidStats.remove(mUidStats.keyAt(i));
12013                 i--;
12014             }
12015         }
12016 
12017         if (mRpmStats.size() > 0) {
12018             for (SamplingTimer timer : mRpmStats.values()) {
12019                 mOnBatteryTimeBase.remove(timer);
12020             }
12021             mRpmStats.clear();
12022         }
12023         if (mScreenOffRpmStats.size() > 0) {
12024             for (SamplingTimer timer : mScreenOffRpmStats.values()) {
12025                 mOnBatteryScreenOffTimeBase.remove(timer);
12026             }
12027             mScreenOffRpmStats.clear();
12028         }
12029 
12030         if (mKernelWakelockStats.size() > 0) {
12031             for (SamplingTimer timer : mKernelWakelockStats.values()) {
12032                 mOnBatteryScreenOffTimeBase.remove(timer);
12033             }
12034             mKernelWakelockStats.clear();
12035         }
12036 
12037         if (mKernelMemoryStats.size() > 0) {
12038             for (int i = 0; i < mKernelMemoryStats.size(); i++) {
12039                 mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i));
12040             }
12041             mKernelMemoryStats.clear();
12042         }
12043 
12044         if (mWakeupReasonStats.size() > 0) {
12045             for (SamplingTimer timer : mWakeupReasonStats.values()) {
12046                 mOnBatteryTimeBase.remove(timer);
12047             }
12048             mWakeupReasonStats.clear();
12049         }
12050 
12051         if (mTmpRailStats != null) {
12052             mTmpRailStats.reset();
12053         }
12054 
12055         EnergyConsumerStats.resetIfNotNull(mGlobalEnergyConsumerStats);
12056 
12057         if (!Flags.disableSystemServicePowerAttr()) {
12058             resetIfNotNull(mBinderThreadCpuTimesUs, false, elapsedRealtimeUs);
12059         }
12060 
12061         mNumAllUidCpuTimeReads = 0;
12062         mNumUidsRemoved = 0;
12063 
12064         initDischarge(elapsedRealtimeUs);
12065 
12066         mHistory.reset();
12067 
12068         // Store the empty state to disk to ensure consistency
12069         writeSyncLocked();
12070 
12071         if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
12072             schedulePowerStatsSampleCollection();
12073         }
12074 
12075         // Flush external data, gathering snapshots, but don't process it since it is pre-reset data
12076         mIgnoreNextExternalStats = true;
12077         mExternalSync.scheduleSync("reset", ExternalStatsSync.UPDATE_ON_RESET);
12078 
12079         mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
12080     }
12081 
saveBatteryUsageStatsOnReset(int resetReason)12082     private void saveBatteryUsageStatsOnReset(int resetReason) {
12083         if (!mSaveBatteryUsageStatsOnReset
12084                 || resetReason == BatteryStatsImpl.RESET_REASON_CORRUPT_FILE) {
12085             return;
12086         }
12087 
12088         final BatteryUsageStats batteryUsageStats;
12089         synchronized (this) {
12090             batteryUsageStats = mBatteryUsageStatsProvider.getBatteryUsageStats(this,
12091                     new BatteryUsageStatsQuery.Builder()
12092                             .setMaxStatsAgeMs(0)
12093                             .includePowerModels()
12094                             .includeProcessStateData()
12095                             .build());
12096         }
12097 
12098         // TODO(b/188068523): BatteryUsageStats should use monotonic time for start and end
12099         // Once that change is made, we will be able to use the BatteryUsageStats' monotonic
12100         // start time
12101         long monotonicStartTime =
12102                 mMonotonicClock.monotonicTime() - batteryUsageStats.getStatsDuration();
12103         mHandler.post(() -> {
12104             mPowerStatsStore.storeBatteryUsageStats(monotonicStartTime, batteryUsageStats);
12105             try {
12106                 batteryUsageStats.close();
12107             } catch (IOException e) {
12108                 Log.e(TAG, "Cannot close BatteryUsageStats", e);
12109             }
12110         });
12111     }
12112 
12113     @GuardedBy("this")
initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs)12114     private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
12115         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
12116             if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
12117                 // Not recording process starts/stops.
12118                 continue;
12119             }
12120             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
12121             if (active == null) {
12122                 continue;
12123             }
12124             for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
12125                 SparseIntArray uids = ent.getValue();
12126                 for (int j=0; j<uids.size(); j++) {
12127                     mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
12128                             uids.keyAt(j));
12129                 }
12130             }
12131         }
12132     }
12133 
12134     @GuardedBy("this")
updateDischargeScreenLevelsLocked(int oldState, int newState)12135     void updateDischargeScreenLevelsLocked(int oldState, int newState) {
12136         updateOldDischargeScreenLevelLocked(oldState);
12137         updateNewDischargeScreenLevelLocked(newState);
12138     }
12139 
12140     @GuardedBy("this")
updateOldDischargeScreenLevelLocked(int state)12141     private void updateOldDischargeScreenLevelLocked(int state) {
12142         if (Display.isOnState(state)) {
12143             int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
12144             if (diff > 0) {
12145                 mDischargeAmountScreenOn += diff;
12146                 mDischargeAmountScreenOnSinceCharge += diff;
12147             }
12148         } else if (Display.isDozeState(state)) {
12149             int diff = mDischargeScreenDozeUnplugLevel - mDischargeCurrentLevel;
12150             if (diff > 0) {
12151                 mDischargeAmountScreenDoze += diff;
12152                 mDischargeAmountScreenDozeSinceCharge += diff;
12153             }
12154         } else if (Display.isOffState(state)) {
12155             int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
12156             if (diff > 0) {
12157                 mDischargeAmountScreenOff += diff;
12158                 mDischargeAmountScreenOffSinceCharge += diff;
12159             }
12160         }
12161     }
12162 
12163     @GuardedBy("this")
updateNewDischargeScreenLevelLocked(int state)12164     private void updateNewDischargeScreenLevelLocked(int state) {
12165         if (Display.isOnState(state)) {
12166             mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
12167             mDischargeScreenOffUnplugLevel = 0;
12168             mDischargeScreenDozeUnplugLevel = 0;
12169         } else if (Display.isDozeState(state)) {
12170             mDischargeScreenOnUnplugLevel = 0;
12171             mDischargeScreenDozeUnplugLevel = mDischargeCurrentLevel;
12172             mDischargeScreenOffUnplugLevel = 0;
12173         } else if (Display.isOffState(state)) {
12174             mDischargeScreenOnUnplugLevel = 0;
12175             mDischargeScreenDozeUnplugLevel = 0;
12176             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
12177         }
12178     }
12179 
12180     @GuardedBy("this")
pullPendingStateUpdatesLocked()12181     public void pullPendingStateUpdatesLocked() {
12182         if (mOnBatteryInternal) {
12183             updateDischargeScreenLevelsLocked(mScreenState, mScreenState);
12184         }
12185     }
12186 
12187     private final Object mWifiNetworkLock = new Object();
12188 
12189     @GuardedBy("mWifiNetworkLock")
12190     private String[] mWifiIfaces = EmptyArray.STRING;
12191 
12192     @GuardedBy("mWifiNetworkLock")
12193     private NetworkStats mLastWifiNetworkStats;
12194 
12195     private final Object mModemNetworkLock = new Object();
12196 
12197     @GuardedBy("mModemNetworkLock")
12198     private String[] mModemIfaces = EmptyArray.STRING;
12199 
12200     @GuardedBy("mModemNetworkLock")
12201     private NetworkStats mLastModemNetworkStats;
12202 
12203     @VisibleForTesting
readMobileNetworkStatsLocked( @onNull NetworkStatsManager networkStatsManager)12204     protected NetworkStats readMobileNetworkStatsLocked(
12205             @NonNull NetworkStatsManager networkStatsManager) {
12206         return networkStatsManager.getMobileUidStats();
12207     }
12208 
12209     @VisibleForTesting
readWifiNetworkStatsLocked( @onNull NetworkStatsManager networkStatsManager)12210     protected NetworkStats readWifiNetworkStatsLocked(
12211             @NonNull NetworkStatsManager networkStatsManager) {
12212         return networkStatsManager.getWifiUidStats();
12213     }
12214 
12215     static class NetworkStatsDelta {
12216         int mUid;
12217         int mSet;
12218         long mRxBytes;
12219         long mRxPackets;
12220         long mTxBytes;
12221         long mTxPackets;
12222 
getUid()12223         public int getUid() {
12224             return mUid;
12225         }
12226 
12227 
getSet()12228         public int getSet() {
12229             return mSet;
12230         }
12231 
getRxBytes()12232         public long getRxBytes() {
12233             return mRxBytes;
12234         }
12235 
getRxPackets()12236         public long getRxPackets() {
12237             return mRxPackets;
12238         }
12239 
getTxBytes()12240         public long getTxBytes() {
12241             return mTxBytes;
12242         }
12243 
getTxPackets()12244         public long getTxPackets() {
12245             return mTxPackets;
12246         }
12247 
12248         @Override
toString()12249         public String toString() {
12250             return "NetworkStatsDelta{mUid=" + mUid + ", mSet=" + mSet + ", mRxBytes=" + mRxBytes
12251                     + ", mRxPackets=" + mRxPackets + ", mTxBytes=" + mTxBytes + ", mTxPackets="
12252                     + mTxPackets + '}';
12253         }
12254     }
12255 
computeDelta(NetworkStats currentStats, NetworkStats lastStats)12256     static List<NetworkStatsDelta> computeDelta(NetworkStats currentStats,
12257             NetworkStats lastStats) {
12258         List<NetworkStatsDelta> deltaList = new ArrayList<>();
12259         for (NetworkStats.Entry entry : currentStats) {
12260             NetworkStatsDelta delta = new NetworkStatsDelta();
12261             delta.mUid = entry.getUid();
12262             delta.mSet = entry.getSet();
12263             NetworkStats.Entry lastEntry = null;
12264             if (lastStats != null) {
12265                 for (NetworkStats.Entry e : lastStats) {
12266                     if (e.getUid() == entry.getUid() && e.getSet() == entry.getSet()
12267                             && e.getTag() == entry.getTag()
12268                             && e.getMetered() == entry.getMetered()
12269                             && e.getRoaming() == entry.getRoaming()
12270                             && e.getDefaultNetwork() == entry.getDefaultNetwork()
12271                             /*&& Objects.equals(e.getIface(), entry.getIface())*/) {
12272                         lastEntry = e;
12273                         break;
12274                     }
12275                 }
12276             }
12277             if (lastEntry != null) {
12278                 delta.mRxBytes = Math.max(0, entry.getRxBytes() - lastEntry.getRxBytes());
12279                 delta.mRxPackets = Math.max(0, entry.getRxPackets() - lastEntry.getRxPackets());
12280                 delta.mTxBytes = Math.max(0, entry.getTxBytes() - lastEntry.getTxBytes());
12281                 delta.mTxPackets = Math.max(0, entry.getTxPackets() - lastEntry.getTxPackets());
12282             } else {
12283                 delta.mRxBytes = entry.getRxBytes();
12284                 delta.mRxPackets = entry.getRxPackets();
12285                 delta.mTxBytes = entry.getTxBytes();
12286                 delta.mTxPackets = entry.getTxPackets();
12287             }
12288             deltaList.add(delta);
12289         }
12290 
12291         return deltaList;
12292     }
12293 
12294     /**
12295      * Distribute WiFi energy info and network traffic to apps.
12296      * @param info The energy information from the WiFi controller.
12297      */
12298     @GuardedBy("this")
updateWifiState(@ullable final WifiActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs, @NonNull NetworkStatsManager networkStatsManager)12299     public void updateWifiState(@Nullable final WifiActivityEnergyInfo info,
12300             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs,
12301             @NonNull NetworkStatsManager networkStatsManager) {
12302         if (mWifiPowerStatsCollector.isEnabled()) {
12303             return;
12304         }
12305 
12306         if (DEBUG_ENERGY) {
12307             synchronized (mWifiNetworkLock) {
12308                 Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
12309             }
12310         }
12311 
12312         // Grab a separate lock to acquire the network stats, which may do I/O.
12313         List<NetworkStatsDelta> delta;
12314         synchronized (mWifiNetworkLock) {
12315             final NetworkStats latestStats = readWifiNetworkStatsLocked(networkStatsManager);
12316             if (latestStats != null) {
12317                 delta = computeDelta(latestStats, mLastWifiNetworkStats);
12318                 mLastWifiNetworkStats = latestStats;
12319             } else {
12320                 delta = null;
12321             }
12322         }
12323 
12324         synchronized (this) {
12325             if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
12326                 if (mIgnoreNextExternalStats) {
12327                     // TODO: Strictly speaking, we should re-mark all 5 timers for each uid (and the
12328                     //  global one) here like we do for display. But I'm not sure it's worth the
12329                     //  complicated code for a codepath that shouldn't ever actually happen in real
12330                     //  life.
12331                 }
12332                 return;
12333             }
12334 
12335             final SparseDoubleArray uidEstimatedConsumptionMah =
12336                     (mGlobalEnergyConsumerStats != null
12337                             && mWifiPowerCalculator != null && consumedChargeUC > 0) ?
12338                             new SparseDoubleArray() : null;
12339             double totalEstimatedConsumptionMah = 0;
12340 
12341             SparseLongArray rxPackets = new SparseLongArray();
12342             SparseLongArray txPackets = new SparseLongArray();
12343             SparseLongArray rxTimesMs = new SparseLongArray();
12344             SparseLongArray txTimesMs = new SparseLongArray();
12345             long totalTxPackets = 0;
12346             long totalRxPackets = 0;
12347             if (delta != null) {
12348                 for (NetworkStatsDelta entry : delta) {
12349                     if (DEBUG_ENERGY) {
12350                         Slog.d(TAG, "Wifi uid " + entry.getUid()
12351                                 + ": delta rx=" + entry.getRxBytes()
12352                                 + " tx=" + entry.getTxBytes()
12353                                 + " rxPackets=" + entry.getRxPackets()
12354                                 + " txPackets=" + entry.getTxPackets());
12355                     }
12356 
12357                     if (entry.getRxBytes() == 0 && entry.getTxBytes() == 0) {
12358                         // Skip the lookup below since there is no work to do.
12359                         continue;
12360                     }
12361 
12362                     final int uid = mapUid(entry.getUid());
12363                     final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
12364                     if (entry.getRxBytes() != 0) {
12365                         u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.getRxBytes(),
12366                                 entry.getRxPackets());
12367                         if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
12368                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.getRxBytes(),
12369                                     entry.getRxPackets());
12370                         }
12371                         mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
12372                                 entry.getRxBytes());
12373                         mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
12374                                 entry.getRxPackets());
12375 
12376                         rxPackets.incrementValue(uid, entry.getRxPackets());
12377 
12378                         // Sum the total number of packets so that the Rx Power can
12379                         // be evenly distributed amongst the apps.
12380                         totalRxPackets += entry.getRxPackets();
12381                     }
12382 
12383                     if (entry.getTxBytes() != 0) {
12384                         u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.getTxBytes(),
12385                                 entry.getTxPackets());
12386                         if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
12387                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.getTxBytes(),
12388                                     entry.getTxPackets());
12389                         }
12390                         mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
12391                                 entry.getTxBytes());
12392                         mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
12393                                 entry.getTxPackets());
12394 
12395                         txPackets.incrementValue(uid, entry.getTxPackets());
12396 
12397                         // Sum the total number of packets so that the Tx Power can
12398                         // be evenly distributed amongst the apps.
12399                         totalTxPackets += entry.getTxPackets();
12400                     }
12401 
12402                     // Calculate consumed energy for this uid. Only do so if WifiReporting isn't
12403                     // enabled (if it is, we'll do it later instead using info).
12404                     if (uidEstimatedConsumptionMah != null && info == null && !mHasWifiReporting) {
12405                         final long uidRunningMs = u.mWifiRunningTimer
12406                                 .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12407                         if (uidRunningMs > 0) u.mWifiRunningTimer.setMark(elapsedRealtimeMs);
12408 
12409                         final long uidScanMs = u.mWifiScanTimer
12410                                 .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12411                         if (uidScanMs > 0) u.mWifiScanTimer.setMark(elapsedRealtimeMs);
12412 
12413                         long uidBatchScanMs = 0;
12414                         for (int bn = 0; bn < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bn++) {
12415                             if (u.mWifiBatchedScanTimer[bn] != null) {
12416                                 long bnMs = u.mWifiBatchedScanTimer[bn]
12417                                         .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12418                                 if (bnMs > 0) {
12419                                     u.mWifiBatchedScanTimer[bn].setMark(elapsedRealtimeMs);
12420                                 }
12421                                 uidBatchScanMs += bnMs;
12422                             }
12423                         }
12424 
12425                         uidEstimatedConsumptionMah.incrementValue(u.getUid(),
12426                                 mWifiPowerCalculator.calcPowerWithoutControllerDataMah(
12427                                         entry.getRxPackets(), entry.getTxPackets(),
12428                                         uidRunningMs, uidScanMs, uidBatchScanMs));
12429                     }
12430                 }
12431                 delta = null;
12432             }
12433 
12434             if (info != null) {
12435                 mHasWifiReporting = true;
12436 
12437                 // Measured in mAms
12438                 final long txTimeMs = info.getControllerTxDurationMillis();
12439                 final long rxTimeMs = info.getControllerRxDurationMillis();
12440                 final long scanTimeMs = info.getControllerScanDurationMillis();
12441                 final long idleTimeMs = info.getControllerIdleDurationMillis();
12442                 final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
12443 
12444                 long leftOverRxTimeMs = rxTimeMs;
12445                 long leftOverTxTimeMs = txTimeMs;
12446 
12447                 if (DEBUG_ENERGY) {
12448                     Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
12449                     Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
12450                     Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
12451                     Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
12452                     Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
12453                     Slog.d(TAG, "  Scan Time:  " + scanTimeMs + " ms");
12454                 }
12455 
12456                 long totalWifiLockTimeMs = 0;
12457                 long totalScanTimeMs = 0;
12458 
12459                 // On the first pass, collect some totals so that we can normalize power
12460                 // calculations if we need to.
12461                 final int uidStatsSize = mUidStats.size();
12462                 for (int i = 0; i < uidStatsSize; i++) {
12463                     final Uid uid = mUidStats.valueAt(i);
12464 
12465                     // Sum the total scan power for all apps.
12466                     totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
12467                             elapsedRealtimeMs * 1000) / 1000;
12468 
12469                     // Sum the total time holding wifi lock for all apps.
12470                     totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
12471                             elapsedRealtimeMs * 1000) / 1000;
12472                 }
12473 
12474                 if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
12475                     Slog.d(TAG,
12476                             "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
12477                                     + rxTimeMs + " ms). Normalizing scan time.");
12478                 }
12479                 if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
12480                     Slog.d(TAG,
12481                             "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
12482                                     + txTimeMs + " ms). Normalizing scan time.");
12483                 }
12484 
12485                 // Actually assign and distribute power usage to apps.
12486                 for (int i = 0; i < uidStatsSize; i++) {
12487                     final Uid uid = mUidStats.valueAt(i);
12488 
12489                     final long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
12490                             elapsedRealtimeMs * 1000) / 1000;
12491                     long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
12492                     long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
12493                     if (scanTimeSinceMarkMs > 0) {
12494                         // Set the new mark so that next time we get new data since this point.
12495                         uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
12496 
12497                         // Our total scan time is more than the reported Tx/Rx time.
12498                         // This is possible because the cost of a scan is approximate.
12499                         // Let's normalize the result so that we evenly blame each app
12500                         // scanning.
12501                         //
12502                         // This means that we may have apps that transmitted/received packets not be
12503                         // blamed for this, but this is fine as scans are relatively more expensive.
12504                         if (totalScanTimeMs > rxTimeMs) {
12505                             scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
12506                                     totalScanTimeMs;
12507                         }
12508                         if (totalScanTimeMs > txTimeMs) {
12509                             scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
12510                                     totalScanTimeMs;
12511                         }
12512 
12513                         if (DEBUG_ENERGY) {
12514                             Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
12515                                     + scanRxTimeSinceMarkMs + " ms  Tx:"
12516                                     + scanTxTimeSinceMarkMs + " ms)");
12517                         }
12518 
12519                         rxTimesMs.incrementValue(uid.getUid(), scanRxTimeSinceMarkMs);
12520                         txTimesMs.incrementValue(uid.getUid(), scanTxTimeSinceMarkMs);
12521 
12522                         leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
12523                         leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
12524                     }
12525 
12526                     // Distribute evenly the power consumed while Idle to each app holding a WiFi
12527                     // lock.
12528                     long myIdleTimeMs = 0;
12529                     final long wifiLockTimeSinceMarkMs =
12530                             uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
12531                                     elapsedRealtimeMs * 1000) / 1000;
12532                     if (wifiLockTimeSinceMarkMs > 0) {
12533                         // Set the new mark so that next time we get new data since this point.
12534                         uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
12535 
12536                         myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs) / totalWifiLockTimeMs;
12537                         if (DEBUG_ENERGY) {
12538                             Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
12539                                     + myIdleTimeMs + " ms");
12540                         }
12541                         uid.getOrCreateWifiControllerActivityLocked().getOrCreateIdleTimeCounter()
12542                                 .increment(myIdleTimeMs, elapsedRealtimeMs);
12543                     }
12544 
12545                     if (uidEstimatedConsumptionMah != null) {
12546                         double uidEstMah = mWifiPowerCalculator.calcPowerFromControllerDataMah(
12547                                 scanRxTimeSinceMarkMs, scanTxTimeSinceMarkMs, myIdleTimeMs);
12548                         uidEstimatedConsumptionMah.incrementValue(uid.getUid(), uidEstMah);
12549                     }
12550                 }
12551 
12552                 if (DEBUG_ENERGY) {
12553                     Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
12554                     Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
12555                 }
12556 
12557                 // Distribute the remaining Tx power appropriately between all apps that transmitted
12558                 // packets.
12559                 for (int i = 0; i < txPackets.size(); i++) {
12560                     final int uid = txPackets.keyAt(i);
12561                     final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
12562                             / totalTxPackets;
12563                     txTimesMs.incrementValue(uid, myTxTimeMs);
12564                 }
12565 
12566                 // Distribute the remaining Rx power appropriately between all apps that received
12567                 // packets.
12568                 for (int i = 0; i < rxPackets.size(); i++) {
12569                     final int uid = rxPackets.keyAt(i);
12570                     final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
12571                             / totalRxPackets;
12572                     rxTimesMs.incrementValue(uid, myRxTimeMs);
12573                 }
12574 
12575                 for (int i = 0; i < txTimesMs.size(); i++) {
12576                     final int uid = txTimesMs.keyAt(i);
12577                     final long myTxTimeMs = txTimesMs.valueAt(i);
12578                     if (DEBUG_ENERGY) {
12579                         Slog.d(TAG, "  TxTime for UID " + uid + ": " + myTxTimeMs + " ms");
12580                     }
12581                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
12582                             .getOrCreateWifiControllerActivityLocked()
12583                             .getOrCreateTxTimeCounters()[0]
12584                             .increment(myTxTimeMs, elapsedRealtimeMs);
12585                     if (uidEstimatedConsumptionMah != null) {
12586                         uidEstimatedConsumptionMah.incrementValue(uid,
12587                                 mWifiPowerCalculator.calcPowerFromControllerDataMah(
12588                                         0, myTxTimeMs, 0));
12589                     }
12590                 }
12591 
12592                 for (int i = 0; i < rxTimesMs.size(); i++) {
12593                     final int uid = rxTimesMs.keyAt(i);
12594                     final long myRxTimeMs = rxTimesMs.valueAt(i);
12595                     if (DEBUG_ENERGY) {
12596                         Slog.d(TAG, "  RxTime for UID " + uid + ": " + myRxTimeMs + " ms");
12597                     }
12598 
12599                     getUidStatsLocked(rxTimesMs.keyAt(i), elapsedRealtimeMs, uptimeMs)
12600                             .getOrCreateWifiControllerActivityLocked()
12601                             .getOrCreateRxTimeCounter()
12602                             .increment(myRxTimeMs, elapsedRealtimeMs);
12603                     if (uidEstimatedConsumptionMah != null) {
12604                         uidEstimatedConsumptionMah.incrementValue(uid,
12605                                 mWifiPowerCalculator.calcPowerFromControllerDataMah(
12606                                         myRxTimeMs, 0, 0));
12607                     }
12608                 }
12609 
12610                 // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
12611 
12612                 // Update WiFi controller stats.
12613                 mWifiActivity.getOrCreateRxTimeCounter().increment(
12614                         info.getControllerRxDurationMillis(), elapsedRealtimeMs);
12615                 mWifiActivity.getOrCreateTxTimeCounters()[0].increment(
12616                         info.getControllerTxDurationMillis(), elapsedRealtimeMs);
12617                 mWifiActivity.getScanTimeCounter().addCountLocked(
12618                         info.getControllerScanDurationMillis());
12619                 mWifiActivity.getOrCreateIdleTimeCounter().increment(
12620                         info.getControllerIdleDurationMillis(), elapsedRealtimeMs);
12621 
12622                 // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
12623                 final double opVolt = mPowerProfile.getAveragePower(
12624                         PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
12625                 double controllerMaMs = 0;
12626                 if (opVolt != 0) {
12627                     // We store the power drain as mAms.
12628                     controllerMaMs = info.getControllerEnergyUsedMicroJoules() / opVolt;
12629                     mWifiActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
12630                 }
12631                 // Converting uWs to mAms.
12632                 // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
12633                 long monitoredRailChargeConsumedMaMs = mTmpRailStats != null
12634                         ? (long) (mTmpRailStats.getWifiTotalEnergyUseduWs() / opVolt)
12635                         : 0L;
12636                 mWifiActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
12637                         monitoredRailChargeConsumedMaMs);
12638                 mHistory.recordWifiConsumedCharge(elapsedRealtimeMs, uptimeMs,
12639                         (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR));
12640                 if (mTmpRailStats != null) {
12641                     mTmpRailStats.resetWifiTotalEnergyUsed();
12642                 }
12643 
12644                 if (uidEstimatedConsumptionMah != null) {
12645                     totalEstimatedConsumptionMah = Math.max(controllerMaMs / MILLISECONDS_IN_HOUR,
12646                             mWifiPowerCalculator.calcPowerFromControllerDataMah(
12647                                     rxTimeMs, txTimeMs, idleTimeMs));
12648                 }
12649             }
12650 
12651             // Update the EnergyConsumerStats information.
12652             if (uidEstimatedConsumptionMah != null) {
12653                 mGlobalEnergyConsumerStats.updateStandardBucket(
12654                         EnergyConsumerStats.POWER_BUCKET_WIFI, consumedChargeUC);
12655 
12656                 // Now calculate the consumption for each uid, according to its proportional usage.
12657                 if (!mHasWifiReporting) {
12658                     final long globalTimeMs = mGlobalWifiRunningTimer
12659                             .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12660                     mGlobalWifiRunningTimer.setMark(elapsedRealtimeMs);
12661                     totalEstimatedConsumptionMah = mWifiPowerCalculator
12662                             .calcGlobalPowerWithoutControllerDataMah(globalTimeMs);
12663                 }
12664                 distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_WIFI,
12665                         consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedConsumptionMah,
12666                         elapsedRealtimeMs);
12667             }
12668         }
12669     }
12670 
12671     private ModemActivityInfo mLastModemActivityInfo = null;
12672 
12673     /**
12674      * Distribute Cell radio energy info and network traffic to apps.
12675      */
noteModemControllerActivity(@ullable final ModemActivityInfo activityInfo, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs, @NonNull NetworkStatsManager networkStatsManager)12676     public void noteModemControllerActivity(@Nullable final ModemActivityInfo activityInfo,
12677             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs,
12678             @NonNull NetworkStatsManager networkStatsManager) {
12679         if (DEBUG_ENERGY) {
12680             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
12681         }
12682         ModemActivityInfo deltaInfo = mLastModemActivityInfo == null
12683                 ? (activityInfo == null ? null : activityInfo.getDelta(activityInfo))
12684                 : mLastModemActivityInfo.getDelta(activityInfo);
12685         mLastModemActivityInfo = activityInfo;
12686 
12687         // Add modem tx power to history.
12688         addModemTxPowerToHistory(deltaInfo, elapsedRealtimeMs, uptimeMs);
12689 
12690         // Grab a separate lock to acquire the network stats, which may do I/O.
12691         List<NetworkStatsDelta> delta = null;
12692         synchronized (mModemNetworkLock) {
12693             final NetworkStats latestStats = readMobileNetworkStatsLocked(networkStatsManager);
12694             if (latestStats != null) {
12695                 delta = computeDelta(latestStats, mLastModemNetworkStats);
12696                 mLastModemNetworkStats = latestStats;
12697             }
12698         }
12699 
12700         synchronized (this) {
12701             final long totalRadioDurationMs =
12702                     mMobileRadioActiveTimer.getTimeSinceMarkLocked(
12703                             elapsedRealtimeMs * 1000) / 1000;
12704             mMobileRadioActiveTimer.setMark(elapsedRealtimeMs);
12705             final long phoneOnDurationMs = Math.min(totalRadioDurationMs,
12706                     mPhoneOnTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000);
12707             mPhoneOnTimer.setMark(elapsedRealtimeMs);
12708 
12709             if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
12710                 return;
12711             }
12712 
12713             final SparseDoubleArray uidEstimatedConsumptionMah;
12714             final long dataConsumedChargeUC;
12715             if (consumedChargeUC > 0 && isMobileRadioEnergyConsumerSupportedLocked()) {
12716                 final long phoneConsumedChargeUC;
12717                 if (totalRadioDurationMs == 0) {
12718                     phoneConsumedChargeUC = 0;
12719                 } else {
12720                     // Crudely attribute power consumption. Added (totalRadioDurationMs / 2) to the
12721                     // numerator for long rounding.
12722                     phoneConsumedChargeUC =
12723                             (consumedChargeUC * phoneOnDurationMs + totalRadioDurationMs / 2)
12724                                     / totalRadioDurationMs;
12725                 }
12726                 dataConsumedChargeUC = consumedChargeUC - phoneConsumedChargeUC;
12727 
12728                 mGlobalEnergyConsumerStats.updateStandardBucket(
12729                         EnergyConsumerStats.POWER_BUCKET_PHONE, phoneConsumedChargeUC);
12730                 mGlobalEnergyConsumerStats.updateStandardBucket(
12731                         EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO, dataConsumedChargeUC);
12732                 uidEstimatedConsumptionMah = new SparseDoubleArray();
12733             } else {
12734                 uidEstimatedConsumptionMah = null;
12735                 dataConsumedChargeUC = POWER_DATA_UNAVAILABLE;
12736             }
12737 
12738             RxTxConsumption rxTxConsumption = null;
12739             boolean attributeWithModemActivityInfo = false;
12740             if (deltaInfo != null) {
12741                 mHasModemReporting = true;
12742                 mModemActivity.getOrCreateIdleTimeCounter()
12743                         .increment(deltaInfo.getIdleTimeMillis(), elapsedRealtimeMs);
12744                 mModemActivity.getSleepTimeCounter().addCountLocked(
12745                         deltaInfo.getSleepTimeMillis());
12746                 mModemActivity.getOrCreateRxTimeCounter()
12747                         .increment(deltaInfo.getReceiveTimeMillis(), elapsedRealtimeMs);
12748                 for (int lvl = 0; lvl < MODEM_TX_POWER_LEVEL_COUNT; lvl++) {
12749                     mModemActivity.getOrCreateTxTimeCounters()[lvl]
12750                             .increment(deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl),
12751                                     elapsedRealtimeMs);
12752                 }
12753 
12754                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
12755                 final double opVolt = mPowerProfile.getAveragePower(
12756                     PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
12757                 if (opVolt != 0) {
12758                     double energyUsed =
12759                             deltaInfo.getSleepTimeMillis() *
12760                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
12761                             + deltaInfo.getIdleTimeMillis() *
12762                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
12763                             + deltaInfo.getReceiveTimeMillis() *
12764                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
12765                     for (int i = 0; i < Math.min(MODEM_TX_POWER_LEVEL_COUNT,
12766                             CELL_SIGNAL_STRENGTH_LEVEL_COUNT); i++) {
12767                         energyUsed += deltaInfo.getTransmitDurationMillisAtPowerLevel(i)
12768                                 * mPowerProfile.getAveragePower(
12769                                         PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
12770                     }
12771 
12772                     // We store the power drain as mAms.
12773                     mModemActivity.getPowerCounter().addCountLocked((long) energyUsed);
12774                     // Converting uWs to mAms.
12775                     // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
12776                     long monitoredRailChargeConsumedMaMs =
12777                             (long) (mTmpRailStats.getCellularTotalEnergyUseduWs() / opVolt);
12778                     mModemActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
12779                             monitoredRailChargeConsumedMaMs);
12780                     mHistory.recordWifiConsumedCharge(elapsedRealtimeMs, uptimeMs,
12781                             (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR));
12782                     mTmpRailStats.resetCellularTotalEnergyUsed();
12783                 }
12784 
12785                 rxTxConsumption = incrementPerRatDataLocked(deltaInfo, elapsedRealtimeMs);
12786 
12787                 attributeWithModemActivityInfo = mConstants.PER_UID_MODEM_MODEL
12788                         == PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX
12789                         && rxTxConsumption != null;
12790             }
12791             long totalAppRadioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
12792                     elapsedRealtimeMs * 1000);
12793             mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
12794 
12795             long totalRxPackets = 0;
12796             long totalTxPackets = 0;
12797             if (delta != null) {
12798                 for (NetworkStatsDelta entry : delta) {
12799                     if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
12800                         continue;
12801                     }
12802 
12803                     if (DEBUG_ENERGY) {
12804                         Slog.d(TAG, "Mobile uid " + entry.getUid() + ": delta rx="
12805                                 + entry.getRxBytes() + " tx=" + entry.getTxBytes()
12806                                 + " rxPackets=" + entry.getRxPackets()
12807                                 + " txPackets=" + entry.getTxPackets());
12808                     }
12809 
12810                     totalRxPackets += entry.getRxPackets();
12811                     totalTxPackets += entry.getTxPackets();
12812 
12813                     final Uid u = getUidStatsLocked(
12814                             mapUid(entry.getUid()), elapsedRealtimeMs, uptimeMs);
12815                     u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.getRxBytes(),
12816                             entry.getRxPackets());
12817                     u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.getTxBytes(),
12818                             entry.getTxPackets());
12819                     if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
12820                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
12821                                 entry.getRxBytes(), entry.getRxPackets());
12822                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
12823                                 entry.getTxBytes(), entry.getTxPackets());
12824                     }
12825 
12826                     mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
12827                             entry.getRxBytes());
12828                     mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
12829                             entry.getTxBytes());
12830                     mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
12831                             entry.getRxPackets());
12832                     mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
12833                             entry.getTxPackets());
12834                 }
12835 
12836                 // Now distribute proportional blame to the apps that did networking.
12837                 long totalPackets = totalRxPackets + totalTxPackets;
12838                 if (totalPackets > 0) {
12839                     for (NetworkStatsDelta entry : delta) {
12840                         if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
12841                             continue;
12842                         }
12843 
12844                         final Uid u = getUidStatsLocked(mapUid(entry.getUid()),
12845                                 elapsedRealtimeMs, uptimeMs);
12846 
12847                         // Distribute total radio active time in to this app.
12848                         final long appPackets = entry.getRxPackets() + entry.getTxPackets();
12849                         final long appRadioTimeUs =
12850                                 (totalAppRadioTimeUs * appPackets) / totalPackets;
12851                         u.noteMobileRadioActiveTimeLocked(appRadioTimeUs, elapsedRealtimeMs);
12852 
12853                         if (uidEstimatedConsumptionMah != null) {
12854                             final double uidConsumptionMah;
12855                             if (attributeWithModemActivityInfo) {
12856                                 // Distribute measured mobile radio charge consumption based on
12857                                 // rx/tx packets and estimated rx/tx charge consumption.
12858                                 uidConsumptionMah = smearModemActivityInfoRxTxConsumptionMah(
12859                                         rxTxConsumption, entry.getRxPackets(), entry.getTxPackets(),
12860                                         totalRxPackets, totalTxPackets);
12861                             } else {
12862                                 // Distribute mobile radio charge consumption based on app radio
12863                                 // active time
12864                                 uidConsumptionMah =
12865                                     mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
12866                                                 appRadioTimeUs / 1000);
12867                             }
12868                             uidEstimatedConsumptionMah.incrementValue(u.getUid(),
12869                                     uidConsumptionMah);
12870                         }
12871 
12872                         // Remove this app from the totals, so that we don't lose any time
12873                         // due to rounding.
12874                         totalAppRadioTimeUs -= appRadioTimeUs;
12875                         totalPackets -= appPackets;
12876 
12877                         if (deltaInfo != null) {
12878                             ControllerActivityCounterImpl activityCounter =
12879                                     u.getOrCreateModemControllerActivityLocked();
12880                             if (totalRxPackets > 0 && entry.getRxPackets() > 0) {
12881                                 final long rxMs = (entry.getRxPackets()
12882                                     * deltaInfo.getReceiveTimeMillis()) / totalRxPackets;
12883                                 activityCounter.getOrCreateRxTimeCounter()
12884                                         .increment(rxMs, elapsedRealtimeMs);
12885                             }
12886 
12887                             if (totalTxPackets > 0 && entry.getTxPackets() > 0) {
12888                                 for (int lvl = 0; lvl < MODEM_TX_POWER_LEVEL_COUNT;
12889                                         lvl++) {
12890                                     long txMs = entry.getTxPackets()
12891                                             * deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl);
12892                                     txMs /= totalTxPackets;
12893                                     activityCounter.getOrCreateTxTimeCounters()[lvl]
12894                                             .increment(txMs, elapsedRealtimeMs);
12895                                 }
12896                             }
12897                         }
12898                     }
12899                 }
12900 
12901                 if (totalAppRadioTimeUs > 0) {
12902                     // Whoops, there is some radio time we can't blame on an app!
12903                     mMobileRadioActiveUnknownTime.addCountLocked(totalAppRadioTimeUs);
12904                     mMobileRadioActiveUnknownCount.addCountLocked(1);
12905                 }
12906 
12907                 // Update the EnergyConsumerStats information.
12908                 if (uidEstimatedConsumptionMah != null) {
12909                     double totalEstimatedConsumptionMah = 0.0;
12910                     if (attributeWithModemActivityInfo) {
12911                         // Estimate inactive modem power consumption and combine with previously
12912                         // estimated active power consumption for an estimate of total modem
12913                         // power consumption.
12914                         final long sleepTimeMs = deltaInfo.getSleepTimeMillis();
12915                         final long idleTimeMs = deltaInfo.getIdleTimeMillis();
12916                         final double inactiveConsumptionMah =
12917                                 mMobileRadioPowerCalculator.calcInactiveStatePowerMah(sleepTimeMs,
12918                                         idleTimeMs);
12919                         totalEstimatedConsumptionMah += inactiveConsumptionMah;
12920                         totalEstimatedConsumptionMah += rxTxConsumption.rxConsumptionMah;
12921                         totalEstimatedConsumptionMah += rxTxConsumption.txConsumptionMah;
12922                     } else {
12923                         // Estimate total active radio power consumption since last mark.
12924                         totalEstimatedConsumptionMah +=
12925                                 mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
12926                                         totalRadioDurationMs);
12927 
12928                         // Estimate idle power consumption at each signal strength level
12929                         final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length;
12930                         for (int lvl = 0; lvl < numSignalStrengthLevels; lvl++) {
12931                             final long strengthLevelDurationMs =
12932                                     mPhoneSignalStrengthsTimer[lvl].getTimeSinceMarkLocked(
12933                                             elapsedRealtimeMs * 1000) / 1000;
12934                             mPhoneSignalStrengthsTimer[lvl].setMark(elapsedRealtimeMs);
12935 
12936                             totalEstimatedConsumptionMah +=
12937                                     mMobileRadioPowerCalculator.calcIdlePowerAtSignalStrengthMah(
12938                                             strengthLevelDurationMs, lvl);
12939                         }
12940 
12941                         // Estimate total active radio power consumption since last mark.
12942                         final long scanTimeMs = mPhoneSignalScanningTimer.getTimeSinceMarkLocked(
12943                                 elapsedRealtimeMs * 1000) / 1000;
12944                         mPhoneSignalScanningTimer.setMark(elapsedRealtimeMs);
12945                         totalEstimatedConsumptionMah +=
12946                                 mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs);
12947                     }
12948                     distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO,
12949                             dataConsumedChargeUC, uidEstimatedConsumptionMah,
12950                             totalEstimatedConsumptionMah, elapsedRealtimeMs);
12951                 }
12952             }
12953         }
12954     }
12955 
12956     private static class RxTxConsumption {
12957         public final double rxConsumptionMah;
12958         public final long rxDurationMs;
12959         public final double txConsumptionMah;
12960         public final long txDurationMs;
12961 
12962         /**
12963          * Represents the ratio between time spent transmitting and the total active time.
12964          */
12965         public final double txToTotalRatio;
12966 
RxTxConsumption(double rxMah, long rxMs, double txMah, long txMs)12967         RxTxConsumption(double rxMah, long rxMs, double txMah, long txMs) {
12968             rxConsumptionMah = rxMah;
12969             rxDurationMs = rxMs;
12970             txConsumptionMah = txMah;
12971             txDurationMs = txMs;
12972 
12973             final long activeDurationMs = txDurationMs + rxDurationMs;
12974             if (activeDurationMs == 0) {
12975                 txToTotalRatio = 0.0;
12976             } else {
12977                 txToTotalRatio = ((double) txDurationMs) / activeDurationMs;
12978             }
12979         }
12980     }
12981 
12982     @GuardedBy("this")
12983     @Nullable
incrementPerRatDataLocked(ModemActivityInfo deltaInfo, long elapsedRealtimeMs)12984     private RxTxConsumption incrementPerRatDataLocked(ModemActivityInfo deltaInfo,
12985             long elapsedRealtimeMs) {
12986         double rxConsumptionMah = 0.0;
12987         long rxDurationMs = 0;
12988         double txConsumptionMah = 0.0;
12989         long txDurationMs = 0;
12990 
12991         final int infoSize = deltaInfo.getSpecificInfoLength();
12992         if (infoSize == 1 && deltaInfo.getSpecificInfoRat(0)
12993                 == AccessNetworkConstants.AccessNetworkType.UNKNOWN
12994                 && deltaInfo.getSpecificInfoFrequencyRange(0)
12995                 == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
12996             // Specific info data unavailable. Proportionally smear Rx and Tx times across each RAT.
12997             final int levelCount = CELL_SIGNAL_STRENGTH_LEVEL_COUNT;
12998             long[] perSignalStrengthActiveTimeMs = new long[levelCount];
12999             long totalActiveTimeMs = 0;
13000 
13001             for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
13002                 final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
13003                 if (ratStats == null) continue;
13004 
13005                 final int freqCount = ratStats.getFrequencyRangeCount();
13006                 for (int freq = 0; freq < freqCount; freq++) {
13007                     for (int level = 0; level < levelCount; level++) {
13008                         final long durationMs = ratStats.getTimeSinceMark(freq, level,
13009                                 elapsedRealtimeMs);
13010                         perSignalStrengthActiveTimeMs[level] += durationMs;
13011                         totalActiveTimeMs += durationMs;
13012                     }
13013                 }
13014             }
13015             if (totalActiveTimeMs != 0) {
13016                 // Smear the provided Tx/Rx durations across each RAT, frequency, and signal
13017                 // strength.
13018                 for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
13019                     final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
13020                     if (ratStats == null) continue;
13021 
13022                     final int freqCount = ratStats.getFrequencyRangeCount();
13023                     for (int freq = 0; freq < freqCount; freq++) {
13024                         long frequencyDurationMs = 0;
13025                         for (int level = 0; level < levelCount; level++) {
13026                             final long durationMs = ratStats.getTimeSinceMark(freq, level,
13027                                     elapsedRealtimeMs);
13028                             final long totalLvlDurationMs =
13029                                     perSignalStrengthActiveTimeMs[level];
13030                             if (totalLvlDurationMs == 0) continue;
13031                             final long totalTxLvlDurations =
13032                                     deltaInfo.getTransmitDurationMillisAtPowerLevel(level);
13033                             // Smear HAL provided Tx power level duration based on active modem
13034                             // duration in a given state. (Add totalLvlDurationMs / 2 before
13035                             // the integer division with totalLvlDurationMs for rounding.)
13036                             final long proportionalTxDurationMs =
13037                                     (durationMs * totalTxLvlDurations
13038                                             + (totalLvlDurationMs / 2)) / totalLvlDurationMs;
13039                             ratStats.incrementTxDuration(freq, level, proportionalTxDurationMs);
13040                             frequencyDurationMs += durationMs;
13041 
13042                             if (isMobileRadioEnergyConsumerSupportedLocked()) {
13043                                 // Accumulate the power cost of time spent transmitting in a
13044                                 // particular state.
13045                                 final double txStatePowerConsumptionMah =
13046                                         mMobileRadioPowerCalculator.calcTxStatePowerMah(rat, freq,
13047                                                 level, proportionalTxDurationMs);
13048                                 txConsumptionMah += txStatePowerConsumptionMah;
13049                                 txDurationMs += proportionalTxDurationMs;
13050                             }
13051                         }
13052                         final long totalRxDuration = deltaInfo.getReceiveTimeMillis();
13053                         // Smear HAL provided Rx power duration based on active modem
13054                         // duration in a given state.  (Add totalActiveTimeMs / 2 before the
13055                         // integer division with totalActiveTimeMs for rounding.)
13056                         final long proportionalRxDurationMs =
13057                                 (frequencyDurationMs * totalRxDuration + (totalActiveTimeMs
13058                                         / 2)) / totalActiveTimeMs;
13059                         ratStats.incrementRxDuration(freq, proportionalRxDurationMs);
13060 
13061                         if (isMobileRadioEnergyConsumerSupportedLocked()) {
13062                             // Accumulate the power cost of time spent receiving in a particular
13063                             // state.
13064                             final double rxStatePowerConsumptionMah =
13065                                     mMobileRadioPowerCalculator.calcRxStatePowerMah(rat, freq,
13066                                             proportionalRxDurationMs);
13067                             rxConsumptionMah += rxStatePowerConsumptionMah;
13068                             rxDurationMs += proportionalRxDurationMs;
13069                         }
13070                     }
13071 
13072                 }
13073             }
13074         } else {
13075             // Specific data available.
13076             for (int index = 0; index < infoSize; index++) {
13077                 final int rat = deltaInfo.getSpecificInfoRat(index);
13078                 final int freq = deltaInfo.getSpecificInfoFrequencyRange(index);
13079 
13080                 // Map RadioAccessNetworkType to course grain RadioAccessTechnology.
13081                 final int ratBucket = mapRadioAccessNetworkTypeToRadioAccessTechnology(rat);
13082                 final RadioAccessTechnologyBatteryStats ratStats = getRatBatteryStatsLocked(
13083                         ratBucket);
13084 
13085                 final long rxTimeMs = deltaInfo.getReceiveTimeMillis(rat, freq);
13086                 final int[] txTimesMs = deltaInfo.getTransmitTimeMillis(rat, freq);
13087 
13088                 ratStats.incrementRxDuration(freq, rxTimeMs);
13089                 if (isMobileRadioEnergyConsumerSupportedLocked()) {
13090                     // Accumulate the power cost of time spent receiving in a particular state.
13091                     final double rxStatePowerConsumptionMah =
13092                             mMobileRadioPowerCalculator.calcRxStatePowerMah(ratBucket, freq,
13093                                     rxTimeMs);
13094                     rxConsumptionMah += rxStatePowerConsumptionMah;
13095                     rxDurationMs += rxTimeMs;
13096                 }
13097 
13098                 final int numTxLvl = txTimesMs.length;
13099                 for (int lvl = 0; lvl < numTxLvl; lvl++) {
13100                     final long txTimeMs = txTimesMs[lvl];
13101                     ratStats.incrementTxDuration(freq, lvl, txTimeMs);
13102                     if (isMobileRadioEnergyConsumerSupportedLocked()) {
13103                         // Accumulate the power cost of time spent transmitting in a particular
13104                         // state.
13105                         final double txStatePowerConsumptionMah =
13106                                 mMobileRadioPowerCalculator.calcTxStatePowerMah(ratBucket, freq,
13107                                         lvl, txTimeMs);
13108                         txConsumptionMah += txStatePowerConsumptionMah;
13109                         txDurationMs += txTimeMs;
13110                     }
13111                 }
13112             }
13113         }
13114 
13115         for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
13116             final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
13117             if (ratStats == null) continue;
13118             ratStats.setMark(elapsedRealtimeMs);
13119         }
13120 
13121         if (isMobileRadioEnergyConsumerSupportedLocked()) {
13122             return new RxTxConsumption(rxConsumptionMah, rxDurationMs, txConsumptionMah,
13123                     txDurationMs);
13124         } else {
13125             return null;
13126         }
13127     }
13128 
13129     /**
13130      * Smear modem Rx/Tx power consumption calculated from {@link ModemActivityInfo} using Rx/Tx
13131      * packets.
13132      *
13133      * @return the combine Rx/Tx smeared power consumption in milliamp-hours.
13134      */
smearModemActivityInfoRxTxConsumptionMah(RxTxConsumption rxTxConsumption, long rxPackets, long txPackets, long totalRxPackets, long totalTxPackets)13135     private double smearModemActivityInfoRxTxConsumptionMah(RxTxConsumption rxTxConsumption,
13136             long rxPackets, long txPackets, long totalRxPackets, long totalTxPackets) {
13137         // Distribute measured mobile radio charge consumption based on
13138         // rx/tx packets and estimated rx/tx charge consumption.
13139         double consumptionMah = 0.0;
13140         if (totalRxPackets != 0) {
13141             // Proportionally distribute receive battery consumption.
13142             consumptionMah += rxTxConsumption.rxConsumptionMah * rxPackets
13143                     / totalRxPackets;
13144         }
13145         if (totalTxPackets != 0 || (totalRxPackets != 0 && rxTxConsumption.txToTotalRatio != 0.0)) {
13146             // ModemActivityInfo Tx time represents time spent both transmitting and receiving.
13147             // There is currently no way to distinguish how many Rx packets were received during
13148             // Rx time vs Tx time.
13149             // Assumption: The number of packets received while transmitting is proportional
13150             // to the time spent transmitting over total active time.
13151             final double totalPacketsDuringTxTime =
13152                     totalTxPackets + rxTxConsumption.txToTotalRatio * totalRxPackets;
13153             final double packetsDuringTxTime =
13154                     txPackets + rxTxConsumption.txToTotalRatio * rxPackets;
13155             consumptionMah += rxTxConsumption.txConsumptionMah * packetsDuringTxTime
13156                     / totalPacketsDuringTxTime;
13157         }
13158         return consumptionMah;
13159     }
13160 
13161     /**
13162      * Add modem tx power to history
13163      * Device is said to be in high cellular transmit power when it has spent most of the transmit
13164      * time at the highest power level.
13165      * @param activityInfo
13166      */
addModemTxPowerToHistory(final ModemActivityInfo activityInfo, long elapsedRealtimeMs, long uptimeMs)13167     private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo,
13168             long elapsedRealtimeMs, long uptimeMs) {
13169         if (activityInfo == null) {
13170             return;
13171         }
13172         int levelMaxTimeSpent = 0;
13173         for (int i = 1; i < MODEM_TX_POWER_LEVEL_COUNT; i++) {
13174             if (activityInfo.getTransmitDurationMillisAtPowerLevel(i)
13175                     > activityInfo.getTransmitDurationMillisAtPowerLevel(levelMaxTimeSpent)) {
13176                 levelMaxTimeSpent = i;
13177             }
13178         }
13179         if (levelMaxTimeSpent == MODEM_TX_POWER_LEVEL_COUNT - 1) {
13180             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
13181                     HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG);
13182         }
13183     }
13184 
13185     private final class BluetoothActivityInfoCache {
13186         long idleTimeMs;
13187         long rxTimeMs;
13188         long txTimeMs;
13189         long energy;
13190 
13191         SparseLongArray uidRxBytes = new SparseLongArray();
13192         SparseLongArray uidTxBytes = new SparseLongArray();
13193 
set(BluetoothActivityEnergyInfo info)13194         void set(BluetoothActivityEnergyInfo info) {
13195             idleTimeMs = info.getControllerIdleTimeMillis();
13196             rxTimeMs = info.getControllerRxTimeMillis();
13197             txTimeMs = info.getControllerTxTimeMillis();
13198             energy = info.getControllerEnergyUsed();
13199             if (!info.getUidTraffic().isEmpty()) {
13200                 for (UidTraffic traffic : info.getUidTraffic()) {
13201                     uidRxBytes.put(traffic.getUid(), traffic.getRxBytes());
13202                     uidTxBytes.put(traffic.getUid(), traffic.getTxBytes());
13203                 }
13204             }
13205         }
13206 
reset()13207         void reset() {
13208             idleTimeMs = 0;
13209             rxTimeMs = 0;
13210             txTimeMs = 0;
13211             energy = 0;
13212             uidRxBytes.clear();
13213             uidTxBytes.clear();
13214         }
13215     }
13216 
13217     private final BluetoothActivityInfoCache mLastBluetoothActivityInfo
13218             = new BluetoothActivityInfoCache();
13219 
13220     /**
13221      * Distribute Bluetooth energy info and network traffic to apps.
13222      *
13223      * @param info The accumulated energy information from the bluetooth controller.
13224      */
13225     @GuardedBy("this")
updateBluetoothStateLocked(@ullable final BluetoothActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs)13226     public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info,
13227             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
13228         if (mBluetoothPowerStatsCollector.isEnabled()) {
13229             return;
13230         }
13231 
13232         if (DEBUG_ENERGY) {
13233             Slog.d(TAG, "Updating bluetooth stats: " + info);
13234         }
13235 
13236         if (info == null) {
13237             return;
13238         }
13239 
13240         if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
13241             mLastBluetoothActivityInfo.set(info);
13242             return;
13243         }
13244 
13245         mHasBluetoothReporting = true;
13246 
13247         if (info.getControllerRxTimeMillis() < mLastBluetoothActivityInfo.rxTimeMs
13248                 || info.getControllerTxTimeMillis() < mLastBluetoothActivityInfo.txTimeMs
13249                 || info.getControllerIdleTimeMillis() < mLastBluetoothActivityInfo.idleTimeMs
13250                 || info.getControllerEnergyUsed() < mLastBluetoothActivityInfo.energy) {
13251             // A drop in accumulated Bluetooth stats is a sign of a Bluetooth crash.
13252             // Reset the preserved previous snapshot in order to restart accumulating deltas.
13253             mLastBluetoothActivityInfo.reset();
13254         }
13255 
13256         final long rxTimeMs =
13257                 info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs;
13258         final long txTimeMs =
13259                 info.getControllerTxTimeMillis() - mLastBluetoothActivityInfo.txTimeMs;
13260         final long idleTimeMs =
13261                 info.getControllerIdleTimeMillis() - mLastBluetoothActivityInfo.idleTimeMs;
13262 
13263         if (DEBUG_ENERGY) {
13264             Slog.d(TAG, "------ BEGIN BLE power blaming ------");
13265             Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
13266             Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
13267             Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
13268         }
13269 
13270         final SparseDoubleArray uidEstimatedConsumptionMah =
13271                 (mGlobalEnergyConsumerStats != null
13272                         && mBluetoothPowerCalculator != null && consumedChargeUC > 0) ?
13273                         new SparseDoubleArray() : null;
13274         long totalScanTimeMs = 0;
13275 
13276         final int uidCount = mUidStats.size();
13277         for (int i = 0; i < uidCount; i++) {
13278             final Uid u = mUidStats.valueAt(i);
13279             if (u.mBluetoothScanTimer == null) {
13280                 continue;
13281             }
13282 
13283             totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
13284                     elapsedRealtimeMs * 1000) / 1000;
13285         }
13286 
13287         final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
13288         final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
13289 
13290         if (DEBUG_ENERGY) {
13291             Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
13292                     + " TX=" + normalizeScanTxTime);
13293         }
13294 
13295         long leftOverRxTimeMs = rxTimeMs;
13296         long leftOverTxTimeMs = txTimeMs;
13297 
13298         final SparseLongArray rxTimesMs = new SparseLongArray(uidCount);
13299         final SparseLongArray txTimesMs = new SparseLongArray(uidCount);
13300 
13301         for (int i = 0; i < uidCount; i++) {
13302             final Uid u = mUidStats.valueAt(i);
13303             if (u.mBluetoothScanTimer == null) {
13304                 continue;
13305             }
13306 
13307             long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
13308                     elapsedRealtimeMs * 1000) / 1000;
13309             if (scanTimeSinceMarkMs > 0) {
13310                 // Set the new mark so that next time we get new data since this point.
13311                 u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
13312 
13313                 long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
13314                 long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
13315 
13316                 if (normalizeScanRxTime) {
13317                     // Scan time is longer than the total rx time in the controller,
13318                     // so distribute the scan time proportionately. This means regular traffic
13319                     // will not blamed, but scans are more expensive anyways.
13320                     scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
13321                 }
13322 
13323                 if (normalizeScanTxTime) {
13324                     // Scan time is longer than the total tx time in the controller,
13325                     // so distribute the scan time proportionately. This means regular traffic
13326                     // will not blamed, but scans are more expensive anyways.
13327                     scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
13328                 }
13329 
13330                 rxTimesMs.incrementValue(u.getUid(), scanTimeRxSinceMarkMs);
13331                 txTimesMs.incrementValue(u.getUid(), scanTimeTxSinceMarkMs);
13332 
13333                 if (uidEstimatedConsumptionMah != null) {
13334                     uidEstimatedConsumptionMah.incrementValue(u.getUid(),
13335                             mBluetoothPowerCalculator.calculatePowerMah(
13336                                     scanTimeRxSinceMarkMs, scanTimeTxSinceMarkMs, 0));
13337                 }
13338 
13339                 leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
13340                 leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
13341             }
13342         }
13343 
13344         if (DEBUG_ENERGY) {
13345             Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX="
13346                     + leftOverTxTimeMs);
13347         }
13348 
13349         //
13350         // Now distribute blame to apps that did bluetooth traffic.
13351         //
13352 
13353         long totalTxBytes = 0;
13354         long totalRxBytes = 0;
13355 
13356         final List<UidTraffic> uidTraffic = info.getUidTraffic();
13357         final int numUids = uidTraffic.size();
13358         for (int i = 0; i < numUids; i++) {
13359             final UidTraffic traffic = uidTraffic.get(i);
13360             final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(
13361                     traffic.getUid());
13362             final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(
13363                     traffic.getUid());
13364 
13365             // Add to the global counters.
13366             mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(rxBytes);
13367             mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes);
13368 
13369             // Add to the UID counters.
13370             final Uid u = getUidStatsLocked(mapUid(traffic.getUid()), elapsedRealtimeMs, uptimeMs);
13371             u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0);
13372             u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0);
13373 
13374             // Calculate the total traffic.
13375             totalRxBytes += rxBytes;
13376             totalTxBytes += txBytes;
13377         }
13378 
13379         if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0
13380                 || leftOverTxTimeMs != 0)) {
13381             for (int i = 0; i < numUids; i++) {
13382                 final UidTraffic traffic = uidTraffic.get(i);
13383                 final int uid = traffic.getUid();
13384                 final long rxBytes =
13385                         traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid);
13386                 final long txBytes =
13387                         traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid);
13388 
13389                 final Uid u = getUidStatsLocked(mapUid(uid), elapsedRealtimeMs, uptimeMs);
13390                 final ControllerActivityCounterImpl counter =
13391                         u.getOrCreateBluetoothControllerActivityLocked();
13392 
13393                 if (totalRxBytes > 0 && rxBytes > 0) {
13394                     final long timeRxMs = (leftOverRxTimeMs * rxBytes) / totalRxBytes;
13395                     rxTimesMs.incrementValue(uid, timeRxMs);
13396                 }
13397 
13398                 if (totalTxBytes > 0 && txBytes > 0) {
13399                     final long timeTxMs = (leftOverTxTimeMs * txBytes) / totalTxBytes;
13400                     txTimesMs.incrementValue(uid, timeTxMs);
13401                 }
13402             }
13403 
13404             for (int i = 0; i < txTimesMs.size(); i++) {
13405                 final int uid = txTimesMs.keyAt(i);
13406                 final long myTxTimeMs = txTimesMs.valueAt(i);
13407                 if (DEBUG_ENERGY) {
13408                     Slog.d(TAG, "  TxTime for UID " + uid + ": " + myTxTimeMs + " ms");
13409                 }
13410                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
13411                         .getOrCreateBluetoothControllerActivityLocked()
13412                         .getOrCreateTxTimeCounters()[0]
13413                         .increment(myTxTimeMs, elapsedRealtimeMs);
13414                 if (uidEstimatedConsumptionMah != null) {
13415                     uidEstimatedConsumptionMah.incrementValue(uid,
13416                             mBluetoothPowerCalculator.calculatePowerMah(0, myTxTimeMs, 0));
13417                 }
13418             }
13419 
13420             for (int i = 0; i < rxTimesMs.size(); i++) {
13421                 final int uid = rxTimesMs.keyAt(i);
13422                 final long myRxTimeMs = rxTimesMs.valueAt(i);
13423                 if (DEBUG_ENERGY) {
13424                     Slog.d(TAG, "  RxTime for UID " + uid + ": " + myRxTimeMs + " ms");
13425                 }
13426 
13427                 getUidStatsLocked(rxTimesMs.keyAt(i), elapsedRealtimeMs, uptimeMs)
13428                         .getOrCreateBluetoothControllerActivityLocked()
13429                         .getOrCreateRxTimeCounter()
13430                         .increment(myRxTimeMs, elapsedRealtimeMs);
13431                 if (uidEstimatedConsumptionMah != null) {
13432                     uidEstimatedConsumptionMah.incrementValue(uid,
13433                             mBluetoothPowerCalculator.calculatePowerMah(myRxTimeMs, 0, 0));
13434                 }
13435             }
13436         }
13437 
13438         mBluetoothActivity.getOrCreateRxTimeCounter().increment(rxTimeMs, elapsedRealtimeMs);
13439         mBluetoothActivity.getOrCreateTxTimeCounters()[0].increment(txTimeMs, elapsedRealtimeMs);
13440         mBluetoothActivity.getOrCreateIdleTimeCounter().increment(idleTimeMs, elapsedRealtimeMs);
13441 
13442         // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
13443         final double opVolt = mPowerProfile.getAveragePower(
13444                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
13445         double controllerMaMs = 0;
13446         if (opVolt != 0) {
13447             controllerMaMs = (info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
13448                     / opVolt;
13449             // We store the power drain as mAms.
13450             mBluetoothActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
13451         }
13452 
13453         // Update the EnergyConsumerStats information.
13454         if (uidEstimatedConsumptionMah != null) {
13455             mGlobalEnergyConsumerStats.updateStandardBucket(
13456                     EnergyConsumerStats.POWER_BUCKET_BLUETOOTH, consumedChargeUC);
13457 
13458             double totalEstimatedMah
13459                     = mBluetoothPowerCalculator.calculatePowerMah(rxTimeMs, txTimeMs, idleTimeMs);
13460             totalEstimatedMah = Math.max(totalEstimatedMah, controllerMaMs / MILLISECONDS_IN_HOUR);
13461             distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_BLUETOOTH,
13462                     consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedMah,
13463                     elapsedRealtimeMs);
13464         }
13465 
13466         mLastBluetoothActivityInfo.set(info);
13467     }
13468     /**
13469      * Read Resource Power Manager (RPM) state and voter times.
13470      * If RPM stats were fetched more recently than RPM_STATS_UPDATE_FREQ_MS ago, uses the old data
13471      * instead of fetching it anew.
13472      *
13473      * Note: This should be called without synchronizing this BatteryStatsImpl object
13474      */
fillLowPowerStats()13475     public void fillLowPowerStats() {
13476         if (mPlatformIdleStateCallback == null) return;
13477 
13478         RpmStats rpmStats = new RpmStats();
13479         long now = SystemClock.elapsedRealtime();
13480         if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
13481             mPlatformIdleStateCallback.fillLowPowerStats(rpmStats);
13482             synchronized (this) {
13483                 mTmpRpmStats = rpmStats;
13484                 mLastRpmStatsUpdateTimeMs = now;
13485             }
13486         }
13487     }
13488 
13489     /**
13490      * Record Resource Power Manager (RPM) state and voter times.
13491      * TODO(b/185252376): Remove this logging. PowerStatsService logs the same data more
13492      * efficiently.
13493      */
updateRpmStatsLocked(long elapsedRealtimeUs)13494     public void updateRpmStatsLocked(long elapsedRealtimeUs) {
13495         if (mTmpRpmStats == null) return;
13496 
13497         for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate
13498                 : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) {
13499 
13500             // Update values for this platform state.
13501             final String pName = pstate.getKey();
13502             final long pTimeUs = pstate.getValue().mTimeMs * 1000;
13503             final int pCount = pstate.getValue().mCount;
13504             getRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs);
13505             if (SCREEN_OFF_RPM_STATS_ENABLED) {
13506                 getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs);
13507             }
13508 
13509             // Update values for each voter of this platform state.
13510             for (Map.Entry<String, RpmStats.PowerStateElement> voter
13511                     : pstate.getValue().mVoters.entrySet()) {
13512                 final String vName = pName + "." + voter.getKey();
13513                 final long vTimeUs = voter.getValue().mTimeMs * 1000;
13514                 final int vCount = voter.getValue().mCount;
13515                 getRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs);
13516                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
13517                     getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs);
13518                 }
13519             }
13520         }
13521 
13522         for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys
13523                 : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) {
13524 
13525             final String subsysName = subsys.getKey();
13526             for (Map.Entry<String, RpmStats.PowerStateElement> sstate
13527                     : subsys.getValue().mStates.entrySet()) {
13528                 final String name = subsysName + "." + sstate.getKey();
13529                 final long timeUs = sstate.getValue().mTimeMs * 1000;
13530                 final int count = sstate.getValue().mCount;
13531                 getRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs);
13532                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
13533                     getScreenOffRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs);
13534                 }
13535             }
13536         }
13537     }
13538 
13539     /**
13540      * Accumulate Cpu charge consumption and distribute it to the correct state and the apps.
13541      * Only call if device is on battery.
13542      *
13543      * @param clusterChargeUC amount of charge (microcoulombs) consumed by each Cpu Cluster
13544      * @param accumulator collection of calculated uid cpu power consumption to smear
13545      *                    clusterChargeUC against.
13546      */
13547     @GuardedBy("this")
13548     @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToStandardBucketLocked
updateCpuEnergyConsumerStatsLocked(@onNull long[] clusterChargeUC, @NonNull CpuDeltaPowerAccumulator accumulator)13549     private void updateCpuEnergyConsumerStatsLocked(@NonNull long[] clusterChargeUC,
13550             @NonNull CpuDeltaPowerAccumulator accumulator) {
13551         if (DEBUG_ENERGY) {
13552             Slog.d(TAG, "Updating cpu cluster stats: " + Arrays.toString(clusterChargeUC));
13553         }
13554         if (mGlobalEnergyConsumerStats == null) {
13555             return;
13556         }
13557 
13558         final int numClusters = clusterChargeUC.length;
13559         long totalCpuChargeUC = 0;
13560         for (int i = 0; i < numClusters; i++) {
13561             totalCpuChargeUC += clusterChargeUC[i];
13562         }
13563         if (totalCpuChargeUC <= 0) return;
13564 
13565         final long timestampMs = mClock.elapsedRealtime();
13566 
13567         mGlobalEnergyConsumerStats.updateStandardBucket(EnergyConsumerStats.POWER_BUCKET_CPU,
13568                 totalCpuChargeUC, timestampMs);
13569 
13570         // Calculate the microcoulombs/milliamp-hour charge ratio for each
13571         // cluster to normalize  each uid's estimated power usage against actual power usage for
13572         // a given cluster.
13573         final double[] clusterChargeRatio = new double[numClusters];
13574         for (int cluster = 0; cluster < numClusters; cluster++) {
13575 
13576             final double totalClusterChargeMah = accumulator.totalClusterChargesMah[cluster];
13577             if (totalClusterChargeMah <= 0.0) {
13578                 // This cluster did not have any work on it, since last update.
13579                 // Avoid dividing by zero.
13580                 clusterChargeRatio[cluster] = 0.0;
13581             } else {
13582                 clusterChargeRatio[cluster] =
13583                         clusterChargeUC[cluster] / accumulator.totalClusterChargesMah[cluster];
13584             }
13585         }
13586 
13587         // Assign and distribute power usage to apps based on their calculated cpu cluster charge.
13588         final long uidChargeArraySize = accumulator.perUidCpuClusterChargesMah.size();
13589         for (int i = 0; i < uidChargeArraySize; i++) {
13590             final Uid uid = accumulator.perUidCpuClusterChargesMah.keyAt(i);
13591             final double[] uidClusterChargesMah = accumulator.perUidCpuClusterChargesMah.valueAt(i);
13592 
13593             // Iterate each cpu cluster and sum the proportional cpu cluster charge to
13594             // get the total cpu charge consumed by a uid.
13595             long uidCpuChargeUC = 0;
13596             for (int cluster = 0; cluster < numClusters; cluster++) {
13597                 final double uidClusterChargeMah = uidClusterChargesMah[cluster];
13598 
13599                 // Proportionally allocate the cpu cluster charge to a uid using the
13600                 // cluster charge/charge ratio. Add 0.5 to round the proportional
13601                 // charge double to the nearest long value.
13602                 final long uidClusterChargeUC =
13603                         (long) (uidClusterChargeMah * clusterChargeRatio[cluster]
13604                                 + 0.5);
13605 
13606                 uidCpuChargeUC += uidClusterChargeUC;
13607             }
13608 
13609             if (uidCpuChargeUC < 0) {
13610                 Slog.wtf(TAG, "Unexpected proportional EnergyConsumer charge "
13611                         + "(" + uidCpuChargeUC + ") for uid " + uid.mUid);
13612                 continue;
13613             }
13614 
13615             uid.addChargeToStandardBucketLocked(uidCpuChargeUC,
13616                     EnergyConsumerStats.POWER_BUCKET_CPU, timestampMs);
13617         }
13618     }
13619 
13620     /**
13621      * Accumulate Display charge consumption and distribute it to the correct state and the apps.
13622      *
13623      * NOTE: The algorithm used makes the strong assumption that app foreground activity time
13624      * is always 0 when the screen is not "ON" and whenever the rail energy is 0 (if supported).
13625      * To the extent that those assumptions are violated, the algorithm will err.
13626      *
13627      * @param chargesUC amount of charge (microcoulombs) used by each Display since this was last
13628      *                 called.
13629      * @param screenStates each screen state at the time this data collection was scheduled
13630      */
13631     @GuardedBy("this")
updateDisplayEnergyConsumerStatsLocked(long[] chargesUC, int[] screenStates, long elapsedRealtimeMs)13632     public void updateDisplayEnergyConsumerStatsLocked(long[] chargesUC, int[] screenStates,
13633             long elapsedRealtimeMs) {
13634         if (DEBUG_ENERGY) Slog.d(TAG, "Updating display stats: " + Arrays.toString(chargesUC));
13635         if (mGlobalEnergyConsumerStats == null) {
13636             return;
13637         }
13638 
13639         final int numDisplays;
13640         if (mPerDisplayBatteryStats.length == screenStates.length) {
13641             numDisplays = screenStates.length;
13642         } else {
13643             // if this point is reached, it will be reached every display state change.
13644             // Rate limit the wtf logging to once every 100 display updates.
13645             if (mDisplayMismatchWtfCount++ % 100 == 0) {
13646                 Slog.wtf(TAG, "Mismatch between PowerProfile reported display count ("
13647                         + mPerDisplayBatteryStats.length
13648                         + ") and PowerStatsHal reported display count (" + screenStates.length
13649                         + ")");
13650             }
13651             // Keep the show going, use the shorter of the two.
13652             numDisplays = mPerDisplayBatteryStats.length < screenStates.length
13653                     ? mPerDisplayBatteryStats.length : screenStates.length;
13654         }
13655 
13656         final int[] oldScreenStates = new int[numDisplays];
13657         for (int i = 0; i < numDisplays; i++) {
13658             final int screenState = screenStates[i];
13659             oldScreenStates[i] = mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement;
13660             mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState;
13661         }
13662 
13663         if (!mOnBatteryInternal) {
13664             // There's nothing further to update.
13665             return;
13666         }
13667         if (mIgnoreNextExternalStats) {
13668             // Although under ordinary resets we won't get here, and typically a new sync will
13669             // happen right after the reset, strictly speaking we need to set all mark times to now.
13670             final int uidStatsSize = mUidStats.size();
13671             for (int i = 0; i < uidStatsSize; i++) {
13672                 final Uid uid = mUidStats.valueAt(i);
13673                 uid.markProcessForegroundTimeUs(elapsedRealtimeMs, false);
13674             }
13675             return;
13676         }
13677 
13678         long totalScreenOnChargeUC = 0;
13679         for (int i = 0; i < numDisplays; i++) {
13680             final long chargeUC = chargesUC[i];
13681             if (chargeUC <= 0) {
13682                 // There's nothing further to update.
13683                 continue;
13684             }
13685 
13686             final @StandardPowerBucket int powerBucket =
13687                     EnergyConsumerStats.getDisplayPowerBucket(oldScreenStates[i]);
13688             mGlobalEnergyConsumerStats.updateStandardBucket(powerBucket, chargeUC);
13689             if (powerBucket == EnergyConsumerStats.POWER_BUCKET_SCREEN_ON) {
13690                 totalScreenOnChargeUC += chargeUC;
13691             }
13692         }
13693 
13694         // Now we blame individual apps, but only if the display was ON.
13695         if (totalScreenOnChargeUC <= 0) {
13696             return;
13697         }
13698         // TODO(b/175726779): Consider unifying the code with the non-rail display power blaming.
13699 
13700         // NOTE: fg time is NOT pooled. If two uids are both somehow in fg, then that time is
13701         // 'double counted' and will simply exceed the realtime that elapsed.
13702         // TODO(b/175726779): collect per display uid visibility for display power attribution.
13703 
13704         // Collect total time since mark so that we can normalize power.
13705         final SparseDoubleArray fgTimeUsArray = new SparseDoubleArray();
13706         final long elapsedRealtimeUs = elapsedRealtimeMs * 1000;
13707         // TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
13708         final int uidStatsSize = mUidStats.size();
13709         for (int i = 0; i < uidStatsSize; i++) {
13710             final Uid uid = mUidStats.valueAt(i);
13711             final long fgTimeUs = uid.markProcessForegroundTimeUs(elapsedRealtimeMs, true);
13712             if (fgTimeUs == 0) continue;
13713             fgTimeUsArray.put(uid.getUid(), (double) fgTimeUs);
13714         }
13715         distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_SCREEN_ON,
13716                 totalScreenOnChargeUC, fgTimeUsArray, 0, elapsedRealtimeMs);
13717     }
13718 
13719     /**
13720      * Accumulate GNSS charge consumption and distribute it to the correct state and the apps.
13721      *
13722      * @param chargeUC amount of charge (microcoulombs) used by GNSS since this was last called.
13723      */
13724     @GuardedBy("this")
13725     public void updateGnssEnergyConsumerStatsLocked(long chargeUC, long elapsedRealtimeMs) {
13726         if (DEBUG_ENERGY) Slog.d(TAG, "Updating gnss stats: " + chargeUC);
13727         if (mGlobalEnergyConsumerStats == null) {
13728             return;
13729         }
13730 
13731         if (!mOnBatteryInternal || chargeUC <= 0) {
13732             // There's nothing further to update.
13733             return;
13734         }
13735         if (mIgnoreNextExternalStats) {
13736             // Although under ordinary resets we won't get here, and typically a new sync will
13737             // happen right after the reset, strictly speaking we need to set all mark times to now.
13738             final int uidStatsSize = mUidStats.size();
13739             for (int i = 0; i < uidStatsSize; i++) {
13740                 final Uid uid = mUidStats.valueAt(i);
13741                 uid.markGnssTimeUs(elapsedRealtimeMs);
13742             }
13743             return;
13744         }
13745 
13746         mGlobalEnergyConsumerStats.updateStandardBucket(EnergyConsumerStats.POWER_BUCKET_GNSS,
13747                 chargeUC);
13748 
13749         // Collect the per uid time since mark so that we can normalize power.
13750         final SparseDoubleArray gnssTimeUsArray = new SparseDoubleArray();
13751         // TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
13752         final int uidStatsSize = mUidStats.size();
13753         for (int i = 0; i < uidStatsSize; i++) {
13754             final Uid uid = mUidStats.valueAt(i);
13755             final long gnssTimeUs = uid.markGnssTimeUs(elapsedRealtimeMs);
13756             if (gnssTimeUs == 0) continue;
13757             gnssTimeUsArray.put(uid.getUid(), (double) gnssTimeUs);
13758         }
13759         distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_GNSS, chargeUC,
13760                 gnssTimeUsArray, 0, elapsedRealtimeMs);
13761     }
13762 
13763     /**
13764      * Accumulate camera charge consumption and distribute it to the correct state and the apps.
13765      *
13766      * @param chargeUC amount of charge (microcoulombs) used by the camera since this was last
13767      *         called.
13768      */
13769     @GuardedBy("this")
13770     public void updateCameraEnergyConsumerStatsLocked(long chargeUC, long elapsedRealtimeMs) {
13771         if (DEBUG_ENERGY) Slog.d(TAG, "Updating camera stats: " + chargeUC);
13772         if (mGlobalEnergyConsumerStats == null) {
13773             return;
13774         }
13775 
13776         if (!mOnBatteryInternal || chargeUC <= 0) {
13777             // There's nothing further to update.
13778             return;
13779         }
13780 
13781         if (mIgnoreNextExternalStats) {
13782             // Although under ordinary resets we won't get here, and typically a new sync will
13783             // happen right after the reset, strictly speaking we need to set all mark times to now.
13784             final int uidStatsSize = mUidStats.size();
13785             for (int i = 0; i < uidStatsSize; i++) {
13786                 final Uid uid = mUidStats.valueAt(i);
13787                 uid.markCameraTimeUs(elapsedRealtimeMs);
13788             }
13789             return;
13790         }
13791 
13792         mGlobalEnergyConsumerStats.updateStandardBucket(
13793                 EnergyConsumerStats.POWER_BUCKET_CAMERA, chargeUC);
13794 
13795         // Collect the per uid time since mark so that we can normalize power.
13796         final SparseDoubleArray cameraTimeUsArray = new SparseDoubleArray();
13797 
13798         // Note: Iterating over all UIDs may be suboptimal.
13799         final int uidStatsSize = mUidStats.size();
13800         for (int i = 0; i < uidStatsSize; i++) {
13801             final Uid uid = mUidStats.valueAt(i);
13802             final long cameraTimeUs = uid.markCameraTimeUs(elapsedRealtimeMs);
13803             if (cameraTimeUs == 0) continue;
13804             cameraTimeUsArray.put(uid.getUid(), (double) cameraTimeUs);
13805         }
13806         distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_CAMERA, chargeUC,
13807                 cameraTimeUsArray, 0, elapsedRealtimeMs);
13808     }
13809 
13810     /**
13811      * Accumulate Custom power bucket charge, globally and for each app.
13812      *
13813      * @param totalChargeUC charge (microcoulombs) used for this bucket since this was last called.
13814      * @param uidCharges map of uid->charge (microcoulombs) for this bucket since last called.
13815      *                    Data inside uidCharges will not be modified (treated immutable).
13816      *                    Uids not already known to BatteryStats will be ignored.
13817      */
13818     @GuardedBy("this")
13819     @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToCustomBucketLocked
13820     public void updateCustomEnergyConsumerStatsLocked(int customPowerBucket,
13821             long totalChargeUC, @Nullable SparseLongArray uidCharges) {
13822         if (DEBUG_ENERGY) {
13823             Slog.d(TAG, "Updating attributed EnergyConsumer stats for custom bucket "
13824                     + customPowerBucket
13825                     + " with total charge " + totalChargeUC
13826                     + " and uid charges " + uidCharges);
13827         }
13828         if (mGlobalEnergyConsumerStats == null) return;
13829         if (!mOnBatteryInternal || mIgnoreNextExternalStats || totalChargeUC <= 0) return;
13830 
13831         mGlobalEnergyConsumerStats.updateCustomBucket(customPowerBucket, totalChargeUC,
13832                 mClock.elapsedRealtime());
13833 
13834         if (uidCharges == null) return;
13835         final int numUids = uidCharges.size();
13836         for (int i = 0; i < numUids; i++) {
13837             final int uidInt = mapUid(uidCharges.keyAt(i));
13838             final long uidChargeUC = uidCharges.valueAt(i);
13839             if (uidChargeUC == 0) continue;
13840 
13841             final Uid uidObj = getAvailableUidStatsLocked(uidInt);
13842             if (uidObj != null) {
13843                 uidObj.addChargeToCustomBucketLocked(uidChargeUC, customPowerBucket);
13844             } else {
13845                 // Ignore any uid not already known to BatteryStats, rather than creating a new Uid.
13846                 // Otherwise we could end up reviving dead Uids. Note that the CPU data is updated
13847                 // first, so any uid that has used any CPU should already be known to BatteryStats.
13848                 // Recently removed uids (especially common for isolated uids) can reach this path
13849                 // and are ignored.
13850                 if (!Process.isIsolated(uidInt)) {
13851                     Slog.w(TAG, "Received EnergyConsumer charge " + totalChargeUC
13852                             + " for custom bucket " + customPowerBucket + " for non-existent uid "
13853                             + uidInt);
13854                 }
13855             }
13856         }
13857     }
13858 
13859     /**
13860      * Attributes energy (for the given bucket) to each uid according to the following formula:
13861      *     blamedEnergy[uid] = totalEnergy * ratioNumerators[uid] / ratioDenominator;
13862      * <p>Does nothing if ratioDenominator is 0.
13863      *
13864      * <p>Here, ratioDenominator = max(sumOfAllRatioNumerators, minRatioDenominator),
13865      * so if given minRatioDenominator <= 0, then sumOfAllRatioNumerators will be used implicitly.
13866      *
13867      * <p>Note that ratioNumerators and minRatioDenominator must use the same units, but need not
13868      * use the same units as totalConsumedChargeUC (which must be in microcoulombs).
13869      *
13870      * <p>A consequence of minRatioDenominator is that the sum over all uids might be less than
13871      * totalConsumedChargeUC. This is intentional; the remainder is purposefully unnaccounted rather
13872      * than incorrectly blamed on uids, and implies unknown (non-uid) sources of drain.
13873      *
13874      * <p>All uids in ratioNumerators must exist in mUidStats already.
13875      */
13876     @GuardedBy("this")
13877     @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToStandardBucketLocked
13878     private void distributeEnergyToUidsLocked(@StandardPowerBucket int bucket,
13879             long totalConsumedChargeUC, SparseDoubleArray ratioNumerators,
13880             double minRatioDenominator, long timestampMs) {
13881 
13882         // If the sum of all app usage was greater than the total, use that instead:
13883         double sumRatioNumerators = 0;
13884         for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
13885             sumRatioNumerators += ratioNumerators.valueAt(i);
13886         }
13887         final double ratioDenominator = Math.max(sumRatioNumerators, minRatioDenominator);
13888         if (ratioDenominator <= 0) return;
13889 
13890         for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
13891             final Uid uid = getAvailableUidStatsLocked(ratioNumerators.keyAt(i));
13892             final double ratioNumerator = ratioNumerators.valueAt(i);
13893             final long uidActualUC
13894                     = (long) (totalConsumedChargeUC * ratioNumerator / ratioDenominator + 0.5);
13895             uid.addChargeToStandardBucketLocked(uidActualUC, bucket, timestampMs);
13896         }
13897     }
13898 
13899     /**
13900      * Read and record Rail Energy data.
13901      */
13902     public void updateRailStatsLocked() {
13903         if (mEnergyConsumerRetriever == null || !mTmpRailStats.isRailStatsAvailable()) {
13904             return;
13905         }
13906         mEnergyConsumerRetriever.fillRailDataStats(mTmpRailStats);
13907     }
13908 
13909     /** Informs that external stats data has been completely flushed. */
13910     public void informThatAllExternalStatsAreFlushed() {
13911         synchronized (this) {
13912             // Any data from the pre-reset era is flushed, so we can henceforth process future data.
13913             mIgnoreNextExternalStats = false;
13914         }
13915     }
13916 
13917     /**
13918      * Read and distribute kernel wake lock use across apps.
13919      */
13920     public void updateKernelWakelocksLocked(long elapsedRealtimeUs) {
13921         if (mKernelWakelockReader == null) {
13922             return;
13923         }
13924 
13925         final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
13926                 mTmpWakelockStats);
13927         if (wakelockStats == null) {
13928             // Not crashing might make board bringup easier.
13929             Slog.w(TAG, "Couldn't get kernel wake lock stats");
13930             return;
13931         }
13932 
13933         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
13934             String name = ent.getKey();
13935             KernelWakelockStats.Entry kws = ent.getValue();
13936 
13937             SamplingTimer kwlt = mKernelWakelockStats.get(name);
13938             if (kwlt == null) {
13939                 kwlt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase);
13940                 mKernelWakelockStats.put(name, kwlt);
13941             }
13942 
13943             kwlt.update(kws.totalTimeUs, kws.activeTimeUs, kws.count, elapsedRealtimeUs);
13944             kwlt.setUpdateVersion(kws.version);
13945         }
13946 
13947         int numWakelocksSetStale = 0;
13948         // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
13949         // this time.
13950         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
13951             SamplingTimer st = ent.getValue();
13952             if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
13953                 st.endSample(elapsedRealtimeUs);
13954                 numWakelocksSetStale++;
13955             }
13956         }
13957 
13958         if (DEBUG) {
13959             // Record whether we've seen a non-zero time (for debugging b/22716723).
13960             if (wakelockStats.isEmpty()) {
13961                 Slog.wtf(TAG, "All kernel wakelocks had time of zero");
13962             }
13963 
13964             if (numWakelocksSetStale == mKernelWakelockStats.size()) {
13965                 Slog.wtf(TAG, "All kernel wakelocks were set stale. new version="
13966                         + wakelockStats.kernelWakelockVersion);
13967             }
13968         }
13969     }
13970 
13971     // We use an anonymous class to access these variables,
13972     // so they can't live on the stack or they'd have to be
13973     // final MutableLong objects (more allocations).
13974     // Used in updateCpuTimeLocked().
13975     long mTempTotalCpuUserTimeUs;
13976     long mTempTotalCpuSystemTimeUs;
13977     long[][] mWakeLockAllocationsUs;
13978 
13979     /**
13980      * Reads the newest memory stats from the kernel.
13981      */
13982     public void updateKernelMemoryBandwidthLocked(long elapsedRealtimeUs) {
13983         mKernelMemoryBandwidthStats.updateStats();
13984         LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
13985         final int bandwidthEntryCount = bandwidthEntries.size();
13986         int index;
13987         for (int i = 0; i < bandwidthEntryCount; i++) {
13988             SamplingTimer timer;
13989             if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) {
13990                 timer = mKernelMemoryStats.valueAt(index);
13991             } else {
13992                 timer = new SamplingTimer(mClock, mOnBatteryTimeBase);
13993                 mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
13994             }
13995             timer.update(bandwidthEntries.valueAt(i), 1, elapsedRealtimeUs);
13996             if (DEBUG_MEMORY) {
13997                 Slog.d(TAG, String.format("Added entry %d and updated timer to: "
13998                         + "mUnpluggedReportedTotalTimeUs %d size %d", bandwidthEntries.keyAt(i),
13999                         mKernelMemoryStats.get(
14000                                 bandwidthEntries.keyAt(i)).mBaseReportedTotalTimeUs,
14001                         mKernelMemoryStats.size()));
14002             }
14003         }
14004     }
14005 
14006     public boolean isOnBatteryLocked() {
14007         return mOnBatteryTimeBase.isRunning();
14008     }
14009 
14010     public boolean isOnBatteryScreenOffLocked() {
14011         return mOnBatteryScreenOffTimeBase.isRunning();
14012     }
14013 
14014     /**
14015      * Object for calculating and accumulating the estimated cpu power used while reading the
14016      * various cpu kernel files.
14017      */
14018     @VisibleForTesting
14019     public static class CpuDeltaPowerAccumulator {
14020         // Keeps track of total charge used per cluster.
14021         public final double[] totalClusterChargesMah;
14022         // Keeps track of charge used per cluster per uid.
14023         public final ArrayMap<Uid, double[]> perUidCpuClusterChargesMah;
14024 
14025         private final CpuPowerCalculator mCalculator;
14026         private Uid mCachedUid = null;
14027         private double[] mUidClusterCache = null;
14028 
14029         CpuDeltaPowerAccumulator(CpuPowerCalculator calculator, int nClusters) {
14030             mCalculator = calculator;
14031             totalClusterChargesMah = new double[nClusters];
14032             perUidCpuClusterChargesMah = new ArrayMap<>();
14033         }
14034 
14035         /** Add per cpu cluster durations to the currently cached uid. */
14036         public void addCpuClusterDurationsMs(Uid uid, long[] durationsMs) {
14037             final double[] uidChargesMah = getOrCreateUidCpuClusterCharges(uid);
14038             for (int cluster = 0; cluster < durationsMs.length; cluster++) {
14039                 final double estimatedDeltaMah = mCalculator.calculatePerCpuClusterPowerMah(cluster,
14040                         durationsMs[cluster]);
14041                 uidChargesMah[cluster] += estimatedDeltaMah;
14042                 totalClusterChargesMah[cluster] += estimatedDeltaMah;
14043             }
14044         }
14045 
14046         /** Add per speed per cpu cluster durations to the currently cached uid. */
14047         public void addCpuClusterSpeedDurationsMs(Uid uid, int cluster, int speed,
14048                 long durationsMs) {
14049             final double[] uidChargesMah = getOrCreateUidCpuClusterCharges(uid);
14050             final double estimatedDeltaMah = mCalculator.calculatePerCpuFreqPowerMah(cluster, speed,
14051                     durationsMs);
14052             uidChargesMah[cluster] += estimatedDeltaMah;
14053             totalClusterChargesMah[cluster] += estimatedDeltaMah;
14054         }
14055 
14056         private double[] getOrCreateUidCpuClusterCharges(Uid uid) {
14057             // Repeated additions on the same uid is very likely.
14058             // Skip a lookup if getting the same uid as the last get.
14059             if (uid == mCachedUid) return mUidClusterCache;
14060 
14061             double[] uidChargesMah = perUidCpuClusterChargesMah.get(uid);
14062             if (uidChargesMah == null) {
14063                 uidChargesMah = new double[totalClusterChargesMah.length];
14064                 perUidCpuClusterChargesMah.put(uid, uidChargesMah);
14065             }
14066             mCachedUid = uid;
14067             mUidClusterCache = uidChargesMah;
14068             return uidChargesMah;
14069         }
14070     }
14071 
14072     /**
14073      * Read and distribute CPU usage across apps. If their are partial wakelocks being held
14074      * and we are on battery with screen off, we give more of the cpu time to those apps holding
14075      * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
14076      * It's possible this will be invoked after the internal battery/screen states are updated, so
14077      * passing the appropriate battery/screen states to try attribute the cpu times to correct
14078      * buckets.
14079      */
14080     @GuardedBy("this")
14081     public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff,
14082             long[] cpuClusterChargeUC) {
14083         if (DEBUG_ENERGY_CPU) {
14084             Slog.d(TAG, "!Cpu updating!");
14085         }
14086 
14087         // Calculate the wakelocks we have to distribute amongst. The system is excluded as it is
14088         // usually holding the wakelock on behalf of an app.
14089         // And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
14090         ArrayList<StopwatchTimer> partialTimersToConsider = null;
14091         if (onBatteryScreenOff) {
14092             partialTimersToConsider = new ArrayList<>();
14093             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
14094                 final StopwatchTimer timer = mPartialTimers.get(i);
14095                 // Since the collection and blaming of wakelocks can be scheduled to run after
14096                 // some delay, the mPartialTimers list may have new entries. We can't blame
14097                 // the newly added timer for past cpu time, so we only consider timers that
14098                 // were present for one round of collection. Once a timer has gone through
14099                 // a round of collection, its mInList field is set to true.
14100                 if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
14101                     partialTimersToConsider.add(timer);
14102                 }
14103             }
14104         }
14105         markPartialTimersAsEligible();
14106 
14107         // When the battery is not on, we don't attribute the cpu times to any timers but we still
14108         // need to take the snapshots.
14109         if (!onBattery) {
14110             mCpuUidUserSysTimeReader.readDelta(false, null);
14111             mCpuUidFreqTimeReader.readDelta(false, null);
14112             mNumAllUidCpuTimeReads += 2;
14113             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
14114                 mCpuUidActiveTimeReader.readDelta(false, null);
14115                 mCpuUidClusterTimeReader.readDelta(false, null);
14116                 mNumAllUidCpuTimeReads += 2;
14117             }
14118             for (int i = mKernelCpuSpeedReaders.length - 1; i >= 0; --i) {
14119                 if (mKernelCpuSpeedReaders[i] != null) {
14120                     mKernelCpuSpeedReaders[i].readDelta();
14121                 }
14122             }
14123             if (!Flags.disableSystemServicePowerAttr()) {
14124                 mSystemServerCpuThreadReader.readDelta();
14125             }
14126             return;
14127         }
14128 
14129         mUserInfoProvider.refreshUserIds();
14130         final SparseLongArray updatedUids = mCpuUidFreqTimeReader.allUidTimesAvailable()
14131                 ? null : new SparseLongArray();
14132 
14133         final CpuDeltaPowerAccumulator powerAccumulator;
14134         if (mGlobalEnergyConsumerStats != null
14135                 && mGlobalEnergyConsumerStats.isStandardBucketSupported(
14136                 EnergyConsumerStats.POWER_BUCKET_CPU)) {
14137             if (cpuClusterChargeUC == null) {
14138                 Slog.wtf(TAG,
14139                         "POWER_BUCKET_CPU supported but no EnergyConsumer Cpu Cluster charge "
14140                                 + "reported on updateCpuTimeLocked!");
14141                 powerAccumulator = null;
14142             } else {
14143                 if (mCpuPowerCalculator == null) {
14144                     mCpuPowerCalculator = new CpuPowerCalculator(mCpuScalingPolicies,
14145                             mPowerProfile);
14146                 }
14147                 // Cpu EnergyConsumer is supported, create an object to accumulate the estimated
14148                 // charge consumption since the last cpu update
14149                 powerAccumulator = new CpuDeltaPowerAccumulator(mCpuPowerCalculator,
14150                         mCpuScalingPolicies.getPolicies().length);
14151             }
14152         } else {
14153             powerAccumulator = null;
14154         }
14155 
14156         readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
14157         // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
14158         // freqs, so no need to approximate these values.
14159         if (updatedUids != null) {
14160             updateClusterSpeedTimes(updatedUids, onBattery, powerAccumulator);
14161         }
14162         readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff,
14163                 powerAccumulator);
14164         mNumAllUidCpuTimeReads += 2;
14165         if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
14166             // Cpu Active times do not get any info ony how to attribute Cpu Cluster
14167             // charge, so not need to provide the powerAccumulator
14168             readKernelUidCpuActiveTimesLocked(onBattery);
14169             readKernelUidCpuClusterTimesLocked(onBattery, powerAccumulator);
14170             mNumAllUidCpuTimeReads += 2;
14171         }
14172 
14173         if (!Flags.disableSystemServicePowerAttr()) {
14174             updateSystemServerThreadStats();
14175         }
14176 
14177         if (powerAccumulator != null) {
14178             updateCpuEnergyConsumerStatsLocked(cpuClusterChargeUC, powerAccumulator);
14179         }
14180     }
14181 
14182     /**
14183      * Estimates the proportion of the System Server CPU activity (per cluster per speed)
14184      * spent on handling incoming binder calls.
14185      */
14186     @VisibleForTesting
14187     public void updateSystemServerThreadStats() {
14188         // There are some simplifying assumptions made in this algorithm
14189         // 1) We assume that if a thread handles incoming binder calls, all of its activity
14190         //    is spent doing that.  Most incoming calls are handled by threads allocated
14191         //    by the native layer in the binder thread pool, so this assumption is reasonable.
14192         // 2) We use the aggregate CPU time spent in different threads as a proxy for the CPU
14193         //    cost. In reality, in multi-core CPUs, the CPU cost may not be linearly
14194         //    affected by additional threads.
14195 
14196         SystemServerCpuThreadReader.SystemServiceCpuThreadTimes systemServiceCpuThreadTimes =
14197                     mSystemServerCpuThreadReader.readDelta();
14198         if (systemServiceCpuThreadTimes == null) {
14199             return;
14200         }
14201 
14202         if (mBinderThreadCpuTimesUs == null) {
14203             mBinderThreadCpuTimesUs = new LongSamplingCounterArray(mOnBatteryTimeBase);
14204         }
14205         mBinderThreadCpuTimesUs.addCountLocked(systemServiceCpuThreadTimes.binderThreadCpuTimesUs);
14206 
14207         if (DEBUG_BINDER_STATS) {
14208             Slog.d(TAG, "System server threads per CPU cluster (incoming binder threads)");
14209             long binderThreadTimeMs = 0;
14210             final long[] binderThreadCpuTimesUs = mBinderThreadCpuTimesUs.getCountsLocked(
14211                     BatteryStats.STATS_SINCE_CHARGED);
14212             int index = 0;
14213             int[] policies = mCpuScalingPolicies.getPolicies();
14214             for (int policy : policies) {
14215                 StringBuilder sb = new StringBuilder();
14216                 sb.append("policy").append(policy).append(": [");
14217                 int numSpeeds = mCpuScalingPolicies.getFrequencies(policy).length;
14218                 for (int speed = 0; speed < numSpeeds; speed++) {
14219                     if (speed != 0) {
14220                         sb.append(", ");
14221                     }
14222                     long binderCountMs = binderThreadCpuTimesUs[index] / 1000;
14223                     sb.append(TextUtils.formatSimple("%10d", binderCountMs));
14224 
14225                     binderThreadTimeMs += binderCountMs;
14226                     index++;
14227                 }
14228                 Slog.d(TAG, sb.toString());
14229             }
14230         }
14231     }
14232 
14233     /**
14234      * Mark the current partial timers as gone through a collection so that they will be
14235      * considered in the next cpu times distribution to wakelock holders.
14236      */
14237     @VisibleForTesting
14238     public void markPartialTimersAsEligible() {
14239         if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
14240             // No difference, so each timer is now considered for the next collection.
14241             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
14242                 mPartialTimers.get(i).mInList = true;
14243             }
14244         } else {
14245             // The lists are different, meaning we added (or removed a timer) since the last
14246             // collection.
14247             for (int i = mLastPartialTimers.size() - 1; i >= 0; --i) {
14248                 mLastPartialTimers.get(i).mInList = false;
14249             }
14250             mLastPartialTimers.clear();
14251 
14252             // Mark the current timers as gone through a collection.
14253             final int numPartialTimers = mPartialTimers.size();
14254             for (int i = 0; i < numPartialTimers; ++i) {
14255                 final StopwatchTimer timer = mPartialTimers.get(i);
14256                 timer.mInList = true;
14257                 mLastPartialTimers.add(timer);
14258             }
14259         }
14260     }
14261 
14262     /**
14263      * Take snapshot of cpu times (aggregated over all uids) at different frequencies and
14264      * calculate cpu times spent by each uid at different frequencies. Will also add estimated
14265      * power consumptions, if powerAccumulator data structure is provided.
14266      *
14267      * @param updatedUids  The uids for which times spent at different frequencies are calculated.
14268      * @param onBattery whether or not this is onBattery
14269      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
14270      */
14271     @VisibleForTesting
14272     public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery,
14273             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
14274         long totalCpuClustersTimeMs = 0;
14275         // Read the time spent for each cluster at various cpu frequencies.
14276         final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
14277         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
14278             if (mKernelCpuSpeedReaders[cluster] != null) {
14279                 clusterSpeedTimesMs[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
14280                 if (clusterSpeedTimesMs[cluster] != null) {
14281                     for (int speed = clusterSpeedTimesMs[cluster].length - 1; speed >= 0; --speed) {
14282                         totalCpuClustersTimeMs += clusterSpeedTimesMs[cluster][speed];
14283                     }
14284                 }
14285             }
14286         }
14287         if (totalCpuClustersTimeMs != 0) {
14288             // We have cpu times per freq aggregated over all uids but we need the times per uid.
14289             // So, we distribute total time spent by an uid to different cpu freqs based on the
14290             // amount of time cpu was running at that freq.
14291             final int updatedUidsCount = updatedUids.size();
14292             final long elapsedRealtimeMs = mClock.elapsedRealtime();
14293             final long uptimeMs = mClock.uptimeMillis();
14294             for (int i = 0; i < updatedUidsCount; ++i) {
14295                 final Uid u = getUidStatsLocked(updatedUids.keyAt(i), elapsedRealtimeMs, uptimeMs);
14296                 final long appCpuTimeUs = updatedUids.valueAt(i);
14297                 // Add the cpu speeds to this UID.
14298                 int[] policies = mCpuScalingPolicies.getPolicies();
14299                 if (u.mCpuClusterSpeedTimesUs == null ||
14300                         u.mCpuClusterSpeedTimesUs.length != policies.length) {
14301                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[policies.length][];
14302                 }
14303 
14304                 for (int cluster = 0; cluster < policies.length; cluster++) {
14305                     final int speedsInCluster = clusterSpeedTimesMs[cluster].length;
14306                     if (u.mCpuClusterSpeedTimesUs[cluster] == null || speedsInCluster !=
14307                             u.mCpuClusterSpeedTimesUs[cluster].length) {
14308                         u.mCpuClusterSpeedTimesUs[cluster]
14309                                 = new LongSamplingCounter[speedsInCluster];
14310                     }
14311 
14312                     final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeedTimesUs[cluster];
14313                     for (int speed = 0; speed < speedsInCluster; speed++) {
14314                         if (cpuSpeeds[speed] == null) {
14315                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
14316                         }
14317                         final long deltaSpeedCount = appCpuTimeUs
14318                                 * clusterSpeedTimesMs[cluster][speed]
14319                                 / totalCpuClustersTimeMs;
14320                         cpuSpeeds[speed].addCountLocked(deltaSpeedCount, onBattery);
14321 
14322                         if (powerAccumulator != null) {
14323                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
14324                                     speed, deltaSpeedCount);
14325                         }
14326                     }
14327                 }
14328             }
14329         }
14330     }
14331 
14332     /**
14333      * Take a snapshot of the cpu times spent by each uid and update the corresponding counters.
14334      * If {@param partialTimers} is not null and empty, then we assign a portion of cpu times to
14335      * wakelock holders.
14336      *
14337      * @param partialTimers The wakelock holders among which the cpu times will be distributed.
14338      * @param updatedUids If not null, then the uids found in the snapshot will be added to this.
14339      */
14340     @VisibleForTesting
14341     public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
14342             @Nullable SparseLongArray updatedUids, boolean onBattery) {
14343         mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
14344         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
14345         final long startTimeMs = mClock.uptimeMillis();
14346         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14347 
14348         mCpuUidUserSysTimeReader.readDelta(false, (uid, timesUs) -> {
14349             long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
14350 
14351             uid = mapUid(uid);
14352             if (Process.isIsolated(uid)) {
14353                 // This could happen if the isolated uid mapping was removed before that process
14354                 // was actually killed.
14355                 if (DEBUG) Slog.d(TAG, "Got readings for an isolated uid: " + uid);
14356                 return;
14357             }
14358             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
14359                 if (DEBUG) Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
14360                 return;
14361             }
14362             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
14363 
14364             // Accumulate the total system and user time.
14365             mTempTotalCpuUserTimeUs += userTimeUs;
14366             mTempTotalCpuSystemTimeUs += systemTimeUs;
14367 
14368             StringBuilder sb = null;
14369             if (DEBUG_ENERGY_CPU) {
14370                 sb = new StringBuilder();
14371                 sb.append("  got time for uid=").append(u.mUid).append(": u=");
14372                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
14373                 sb.append(" s=");
14374                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
14375                 sb.append("\n");
14376             }
14377 
14378             if (numWakelocks > 0) {
14379                 // We have wakelocks being held, so only give a portion of the
14380                 // time to the process. The rest will be distributed among wakelock
14381                 // holders.
14382                 userTimeUs = (userTimeUs * WAKE_LOCK_WEIGHT) / 100;
14383                 systemTimeUs = (systemTimeUs * WAKE_LOCK_WEIGHT) / 100;
14384             }
14385 
14386             if (sb != null) {
14387                 sb.append("  adding to uid=").append(u.mUid).append(": u=");
14388                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
14389                 sb.append(" s=");
14390                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
14391                 Slog.d(TAG, sb.toString());
14392             }
14393 
14394             u.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
14395             u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
14396             if (updatedUids != null) {
14397                 updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
14398             }
14399         });
14400 
14401         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
14402         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
14403             Slog.d(TAG, "Reading cpu stats took " + elapsedTimeMs + "ms");
14404         }
14405 
14406         if (numWakelocks > 0) {
14407             // Distribute a portion of the total cpu time to wakelock holders.
14408             mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
14409             mTempTotalCpuSystemTimeUs =
14410                     (mTempTotalCpuSystemTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
14411 
14412             for (int i = 0; i < numWakelocks; ++i) {
14413                 final StopwatchTimer timer = partialTimers.get(i);
14414                 final int userTimeUs = (int) (mTempTotalCpuUserTimeUs / (numWakelocks - i));
14415                 final int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / (numWakelocks - i));
14416 
14417                 if (DEBUG_ENERGY_CPU) {
14418                     final StringBuilder sb = new StringBuilder();
14419                     sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
14420                             .append(": u=");
14421                     TimeUtils.formatDuration(userTimeUs / 1000, sb);
14422                     sb.append(" s=");
14423                     TimeUtils.formatDuration(systemTimeUs / 1000, sb);
14424                     Slog.d(TAG, sb.toString());
14425                 }
14426 
14427                 timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
14428                 timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
14429                 if (updatedUids != null) {
14430                     final int uid = timer.mUid.getUid();
14431                     updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
14432                 }
14433 
14434                 final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
14435                 proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery);
14436 
14437                 mTempTotalCpuUserTimeUs -= userTimeUs;
14438                 mTempTotalCpuSystemTimeUs -= systemTimeUs;
14439             }
14440         }
14441     }
14442 
14443     /**
14444      * Take a snapshot of the cpu times spent by each uid in each freq and update the
14445      * corresponding counters.  Will also add estimated power consumptions, if powerAccumulator
14446      * data structure is provided.
14447      *
14448      * @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
14449      * @param onBattery whether or not this is onBattery
14450      * @param onBatteryScreenOff whether or not this is onBattery with the screen off.
14451      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
14452      */
14453     @VisibleForTesting
14454     public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
14455             boolean onBattery, boolean onBatteryScreenOff,
14456             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
14457         final boolean perClusterTimesAvailable =
14458                 mCpuUidFreqTimeReader.perClusterTimesAvailable();
14459         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
14460         final int[] policies = mCpuScalingPolicies.getPolicies();
14461         final int numClusters = policies.length;
14462         mWakeLockAllocationsUs = null;
14463         final long startTimeMs = mClock.uptimeMillis();
14464         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14465         // If power is being accumulated for attribution, data needs to be read immediately.
14466         final boolean forceRead = powerAccumulator != null;
14467         mCpuUidFreqTimeReader.readDelta(forceRead, (uid, cpuFreqTimeMs) -> {
14468             uid = mapUid(uid);
14469             if (Process.isIsolated(uid)) {
14470                 if (DEBUG) Slog.d(TAG, "Got freq readings for an isolated uid: " + uid);
14471                 return;
14472             }
14473             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
14474                 if (DEBUG) Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
14475                 return;
14476             }
14477             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
14478             if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
14479                 detachIfNotNull(u.mCpuFreqTimeMs);
14480                 u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
14481             }
14482             u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
14483             if (u.mScreenOffCpuFreqTimeMs == null ||
14484                     u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
14485                 detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
14486                 u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
14487                         mOnBatteryScreenOffTimeBase);
14488             }
14489             u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff);
14490 
14491             if (perClusterTimesAvailable) {
14492                 if (u.mCpuClusterSpeedTimesUs == null ||
14493                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
14494                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
14495                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
14496                 }
14497                 if (numWakelocks > 0 && mWakeLockAllocationsUs == null) {
14498                     mWakeLockAllocationsUs = new long[numClusters][];
14499                 }
14500 
14501                 int freqIndex = 0;
14502                 for (int cluster = 0; cluster < numClusters; cluster++) {
14503                     final int[] freqs = mCpuScalingPolicies.getFrequencies(policies[cluster]);
14504                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
14505                             u.mCpuClusterSpeedTimesUs[cluster].length != freqs.length) {
14506                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
14507                         u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[freqs.length];
14508                     }
14509                     if (numWakelocks > 0 && mWakeLockAllocationsUs[cluster] == null) {
14510                         mWakeLockAllocationsUs[cluster] = new long[freqs.length];
14511                     }
14512                     final LongSamplingCounter[] cpuTimesUs = u.mCpuClusterSpeedTimesUs[cluster];
14513                     for (int speed = 0; speed < freqs.length; ++speed) {
14514                         if (cpuTimesUs[speed] == null) {
14515                             cpuTimesUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
14516                         }
14517                         final long appAllocationUs;
14518                         if (mWakeLockAllocationsUs != null) {
14519                             appAllocationUs =
14520                                     (cpuFreqTimeMs[freqIndex] * 1000 * WAKE_LOCK_WEIGHT) / 100;
14521                             mWakeLockAllocationsUs[cluster][speed] +=
14522                                     (cpuFreqTimeMs[freqIndex] * 1000 - appAllocationUs);
14523                         } else {
14524                             appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
14525                         }
14526                         cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
14527 
14528                         if (powerAccumulator != null) {
14529                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
14530                                     speed, appAllocationUs / 1000);
14531                         }
14532                         freqIndex++;
14533                     }
14534                 }
14535             }
14536         });
14537 
14538         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
14539         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
14540             Slog.d(TAG, "Reading cpu freq times took " + elapsedTimeMs + "ms");
14541         }
14542 
14543         if (mWakeLockAllocationsUs != null) {
14544             for (int i = 0; i < numWakelocks; ++i) {
14545                 final Uid u = partialTimers.get(i).mUid;
14546                 if (u.mCpuClusterSpeedTimesUs == null ||
14547                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
14548                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
14549                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
14550                 }
14551 
14552                 for (int cluster = 0; cluster < numClusters; ++cluster) {
14553                     final int speedsInCluster =
14554                             mCpuScalingPolicies.getFrequencies(policies[cluster]).length;
14555                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
14556                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
14557                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
14558                         u.mCpuClusterSpeedTimesUs[cluster]
14559                                 = new LongSamplingCounter[speedsInCluster];
14560                     }
14561                     final LongSamplingCounter[] cpuTimeUs = u.mCpuClusterSpeedTimesUs[cluster];
14562                     for (int speed = 0; speed < speedsInCluster; ++speed) {
14563                         if (cpuTimeUs[speed] == null) {
14564                             cpuTimeUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
14565                         }
14566                         final long allocationUs =
14567                                 mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
14568                         cpuTimeUs[speed].addCountLocked(allocationUs, onBattery);
14569                         mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
14570 
14571                         if (powerAccumulator != null) {
14572                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
14573                                     speed, allocationUs / 1000);
14574                         }
14575                     }
14576                 }
14577             }
14578         }
14579     }
14580 
14581     /**
14582      * Take a snapshot of the cpu active times spent by each uid and update the corresponding
14583      * counters.
14584      */
14585     @VisibleForTesting
14586     public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
14587         final long startTimeMs = mClock.uptimeMillis();
14588         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14589         mCpuUidActiveTimeReader.readAbsolute((uid, cpuActiveTimesMs) -> {
14590             final int parentUid = mapUid(uid);
14591             if (Process.isIsolated(parentUid)) {
14592                 if (DEBUG) Slog.w(TAG, "Got active times for an isolated uid: " + uid);
14593                 return;
14594             }
14595             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
14596                 if (DEBUG) Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
14597                 return;
14598             }
14599             final Uid u = getUidStatsLocked(parentUid, elapsedRealtimeMs, startTimeMs);
14600             if (parentUid == uid) {
14601                 u.getCpuActiveTimeCounter().update(cpuActiveTimesMs, elapsedRealtimeMs);
14602             } else {
14603                 final SparseArray<Uid.ChildUid> childUids = u.mChildUids;
14604                 if (childUids == null) {
14605                     return;
14606                 }
14607 
14608                 Uid.ChildUid childUid = childUids.get(uid);
14609                 if (childUid != null) {
14610                     final long delta =
14611                             childUid.cpuActiveCounter.update(cpuActiveTimesMs, elapsedRealtimeMs);
14612                     u.getCpuActiveTimeCounter().increment(delta, elapsedRealtimeMs);
14613                 }
14614             }
14615         });
14616 
14617         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
14618         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
14619             Slog.d(TAG, "Reading cpu active times took " + elapsedTimeMs + "ms");
14620         }
14621     }
14622 
14623     /**
14624      * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding
14625      * counters. Will also add estimated power consumptions, if powerAccumulator data structure
14626      * is provided.
14627      *
14628      * @param onBattery whether or not this is onBattery
14629      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
14630      */
14631     @VisibleForTesting
14632     public void readKernelUidCpuClusterTimesLocked(boolean onBattery,
14633             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
14634         final long startTimeMs = mClock.uptimeMillis();
14635         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14636         // If power is being accumulated for attribution, data needs to be read immediately.
14637         final boolean forceRead = powerAccumulator != null;
14638         mCpuUidClusterTimeReader.readDelta(forceRead, (uid, cpuClusterTimesMs) -> {
14639             uid = mapUid(uid);
14640             if (Process.isIsolated(uid)) {
14641                 if (DEBUG) Slog.w(TAG, "Got cluster times for an isolated uid: " + uid);
14642                 return;
14643             }
14644             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
14645                 if (DEBUG) Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
14646                 return;
14647             }
14648             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
14649             u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesMs, onBattery);
14650 
14651             if (powerAccumulator != null) {
14652                 powerAccumulator.addCpuClusterDurationsMs(u, cpuClusterTimesMs);
14653             }
14654         });
14655 
14656         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
14657         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
14658             Slog.d(TAG, "Reading cpu cluster times took " + elapsedTimeMs + "ms");
14659         }
14660     }
14661 
14662     boolean setChargingLocked(boolean charging) {
14663         // if the device is no longer charging, remove the callback
14664         // if the device is now charging, it means that this is either called
14665         // 1. directly when level >= 90
14666         // 2. or from within the runnable that we deferred
14667         // For 1. if we have an existing callback, remove it, since we will immediately send a
14668         // ACTION_CHARGING
14669         // For 2. we remove existing callback so we don't send multiple ACTION_CHARGING
14670         mHandler.removeCallbacks(mDeferSetCharging);
14671         if (mCharging != charging) {
14672             mCharging = charging;
14673             mHistory.setChargingState(charging);
14674             mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
14675             return true;
14676         }
14677         return false;
14678     }
14679 
14680     /**
14681      * Notifies BatteryStatsImpl that the system server is ready.
14682      */
14683     public void onSystemReady(Context context) {
14684         if (mCpuUidFreqTimeReader != null) {
14685             mCpuUidFreqTimeReader.onSystemReady();
14686         }
14687 
14688         mPowerStatsCollectorInjector.setContext(context);
14689 
14690         mCpuPowerStatsCollector.setEnabled(
14691                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU));
14692         mCpuPowerStatsCollector.schedule();
14693 
14694         mMobileRadioPowerStatsCollector.setEnabled(
14695                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO));
14696         mMobileRadioPowerStatsCollector.schedule();
14697 
14698         mWifiPowerStatsCollector.setEnabled(
14699                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_WIFI));
14700         mWifiPowerStatsCollector.schedule();
14701 
14702         mBluetoothPowerStatsCollector.setEnabled(
14703                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_BLUETOOTH));
14704         mBluetoothPowerStatsCollector.schedule();
14705 
14706         mSystemReady = true;
14707     }
14708 
14709     /**
14710      * Returns a PowerStatsCollector for the specified power component or null if unavailable.
14711      */
14712     @Nullable
14713     PowerStatsCollector getPowerStatsCollector(
14714             @BatteryConsumer.PowerComponent int powerComponent) {
14715         switch (powerComponent) {
14716             case BatteryConsumer.POWER_COMPONENT_CPU:
14717                 return mCpuPowerStatsCollector;
14718             case BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO:
14719                 return mMobileRadioPowerStatsCollector;
14720             case BatteryConsumer.POWER_COMPONENT_WIFI:
14721                 return mWifiPowerStatsCollector;
14722             case BatteryConsumer.POWER_COMPONENT_BLUETOOTH:
14723                 return mBluetoothPowerStatsCollector;
14724         }
14725         return null;
14726     }
14727 
14728 
14729     /**
14730      * Force recording of all history events regardless of the "charging" state.
14731      */
14732     @VisibleForTesting
14733     public void forceRecordAllHistory() {
14734         mHistory.forceRecordAllHistory();
14735         mRecordAllHistory = true;
14736     }
14737 
14738     /**
14739      * Might reset battery stats if conditions are met. Assumed the device is currently plugged in.
14740      */
14741     @VisibleForTesting
14742     @GuardedBy("this")
14743     public void maybeResetWhilePluggedInLocked() {
14744         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14745         if (shouldResetWhilePluggedInLocked(elapsedRealtimeMs)) {
14746             Slog.i(TAG,
14747                     "Resetting due to long plug in duration. elapsed time = " + elapsedRealtimeMs
14748                             + " ms, last plug in time = " + mBatteryPluggedInRealTimeMs
14749                             + " ms, last reset time = " + mRealtimeStartUs / 1000);
14750             resetAllStatsAndHistoryLocked(RESET_REASON_PLUGGED_IN_FOR_LONG_DURATION);
14751         }
14752 
14753         scheduleNextResetWhilePluggedInCheck();
14754     }
14755 
14756     @GuardedBy("this")
14757     private void scheduleNextResetWhilePluggedInCheck() {
14758         if (mAlarmManager == null) return;
14759         final long timeoutMs = mClock.currentTimeMillis()
14760                 + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
14761                 * DateUtils.HOUR_IN_MILLIS;
14762         Calendar nextAlarm = Calendar.getInstance();
14763         nextAlarm.setTimeInMillis(timeoutMs);
14764 
14765         // Find the 2 AM the same day as the end of the minimum duration.
14766         // This logic does not handle a Daylight Savings transition, or a timezone change
14767         // while the alarm has been set. The need to reset after a long period while plugged
14768         // in is not strict enough to warrant a well architected out solution.
14769         nextAlarm.set(Calendar.MILLISECOND, 0);
14770         nextAlarm.set(Calendar.SECOND, 0);
14771         nextAlarm.set(Calendar.MINUTE, 0);
14772         nextAlarm.set(Calendar.HOUR_OF_DAY, 2);
14773         long possibleNextTimeMs = nextAlarm.getTimeInMillis();
14774         if (possibleNextTimeMs < timeoutMs) {
14775             // The 2AM on the day of the timeout, move on the next day.
14776             possibleNextTimeMs += DateUtils.DAY_IN_MILLIS;
14777         }
14778         final long nextTimeMs = possibleNextTimeMs;
14779         final AlarmManager am = mAlarmManager;
14780         mHandler.post(() -> am.setWindow(AlarmManager.RTC, nextTimeMs,
14781                 DateUtils.HOUR_IN_MILLIS,
14782                 TAG, mLongPlugInAlarmHandler, mHandler));
14783     }
14784 
14785 
14786     @GuardedBy("this")
14787     private boolean shouldResetWhilePluggedInLocked(long elapsedRealtimeMs) {
14788         if (mNoAutoReset) return false;
14789         if (!mSystemReady) return false;
14790         if (!mHistory.isResetEnabled()) return false;
14791 
14792         final long pluggedInThresholdMs = mBatteryPluggedInRealTimeMs
14793                 + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
14794                 * DateUtils.HOUR_IN_MILLIS;
14795         if (elapsedRealtimeMs >= pluggedInThresholdMs) {
14796             // The device has been plugged in for a long time.
14797             final long resetThresholdMs = mRealtimeStartUs / 1000
14798                     + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
14799                     * DateUtils.HOUR_IN_MILLIS;
14800             if (elapsedRealtimeMs >= resetThresholdMs) {
14801                 // And it has been a long time since the last reset.
14802                 return true;
14803             }
14804         }
14805 
14806         return false;
14807     }
14808 
14809     @GuardedBy("this")
14810     private boolean shouldResetOnUnplugLocked(int batteryStatus, int batteryLevel) {
14811         if (mNoAutoReset) return false;
14812         if (!mSystemReady) return false;
14813         if (!mHistory.isResetEnabled()) return false;
14814         if (mBatteryStatsConfig.shouldResetOnUnplugHighBatteryLevel()) {
14815             // Allow resetting due to currently being at high battery level
14816             if (batteryStatus == BatteryManager.BATTERY_STATUS_FULL) return true;
14817             if (batteryLevel >= 90) return true;
14818         }
14819         if (mBatteryStatsConfig.shouldResetOnUnplugAfterSignificantCharge()) {
14820             // Allow resetting after a significant charge (from a very low level to a now very
14821             // high level).
14822             if (mDischargePlugLevel < 20 && batteryLevel >= 80) return true;
14823         }
14824         if (getHighDischargeAmountSinceCharge() >= 200) {
14825             // Reset the stats if battery got partially charged and discharged repeatedly without
14826             // ever reaching the full charge.
14827             // This reset is done in order to prevent stats sessions from going on forever.
14828             // Exceedingly long battery sessions would lead to an overflow of
14829             // data structures such as mWakeupReasonStats.
14830             return true;
14831         }
14832 
14833         return false;
14834     }
14835 
14836     @GuardedBy("this")
14837     protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
14838             final boolean onBattery, final int oldStatus, final int level, final int chargeUah) {
14839         boolean doWrite = false;
14840         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
14841         m.arg1 = onBattery ? 1 : 0;
14842         mHandler.sendMessage(m);
14843 
14844         final long uptimeUs = mSecUptime * 1000;
14845         final long realtimeUs = mSecRealtime * 1000;
14846         final int screenState = mScreenState;
14847         if (onBattery) {
14848             boolean reset = false;
14849             if (shouldResetOnUnplugLocked(oldStatus, level)) {
14850                 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
14851                         + " dischargeLevel=" + mDischargePlugLevel
14852                         + " lowAmount=" + getLowDischargeAmountSinceCharge()
14853                         + " highAmount=" + getHighDischargeAmountSinceCharge());
14854                 // Before we write, collect a snapshot of the final aggregated
14855                 // stats to be reported in the next checkin.  Only do this if we have
14856                 // a sufficient amount of data to make it interesting.
14857                 if (getLowDischargeAmountSinceCharge() >= 20) {
14858                     final long startTimeMs = SystemClock.uptimeMillis();
14859                     final Parcel parcel = Parcel.obtain();
14860                     writeSummaryToParcel(parcel, true);
14861                     final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs;
14862                     BackgroundThread.getHandler().post(new Runnable() {
14863                         @Override public void run() {
14864                             synchronized (mCheckinFile) {
14865                                 final long startTimeMs2 = SystemClock.uptimeMillis();
14866                                 FileOutputStream stream = null;
14867                                 try {
14868                                     stream = mCheckinFile.startWrite();
14869                                     stream.write(parcel.marshall());
14870                                     stream.flush();
14871                                     mCheckinFile.finishWrite(stream);
14872                                     mFrameworkStatsLogger.writeCommitSysConfigFile(
14873                                             "batterystats-checkin",
14874                                             initialTimeMs + SystemClock.uptimeMillis()
14875                                                     - startTimeMs2);
14876                                 } catch (IOException e) {
14877                                     Slog.w("BatteryStats",
14878                                             "Error writing checkin battery statistics", e);
14879                                     mCheckinFile.failWrite(stream);
14880                                 } finally {
14881                                     parcel.recycle();
14882                                 }
14883                             }
14884                         }
14885                     });
14886                 }
14887                 doWrite = true;
14888                 resetAllStatsLocked(mSecUptime, mSecRealtime, RESET_REASON_FULL_CHARGE);
14889                 if (chargeUah > 0 && level > 0) {
14890                     // Only use the reported coulomb charge value if it is supported and reported.
14891                     mEstimatedBatteryCapacityMah = (int) ((chargeUah / 1000) / (level / 100.0));
14892                 }
14893                 reset = true;
14894                 mDischargeStepTracker.init();
14895             }
14896             if (mCharging) {
14897                 setChargingLocked(false);
14898             }
14899             mOnBattery = mOnBatteryInternal = true;
14900             mLastDischargeStepLevel = level;
14901             mMinDischargeStepLevel = level;
14902             mDischargeStepTracker.clearTime();
14903             mDailyDischargeStepTracker.clearTime();
14904             mInitStepMode = mCurStepMode;
14905             mModStepMode = 0;
14906             pullPendingStateUpdatesLocked();
14907             if (reset) {
14908                 mHistory.startRecordingHistory(mSecRealtime, mSecUptime, reset);
14909                 initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
14910             }
14911             mBatteryPluggedIn = false;
14912             if (mAlarmManager != null) {
14913                 final AlarmManager am = mAlarmManager;
14914                 mHandler.post(() -> {
14915                     // No longer plugged in. Cancel the long plug in alarm.
14916                     am.cancel(mLongPlugInAlarmHandler);
14917                 });
14918             }
14919             mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
14920             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
14921             if (Display.isOnState(screenState)) {
14922                 mDischargeScreenOnUnplugLevel = level;
14923                 mDischargeScreenDozeUnplugLevel = 0;
14924                 mDischargeScreenOffUnplugLevel = 0;
14925             } else if (Display.isDozeState(screenState)) {
14926                 mDischargeScreenOnUnplugLevel = 0;
14927                 mDischargeScreenDozeUnplugLevel = level;
14928                 mDischargeScreenOffUnplugLevel = 0;
14929             } else {
14930                 mDischargeScreenOnUnplugLevel = 0;
14931                 mDischargeScreenDozeUnplugLevel = 0;
14932                 mDischargeScreenOffUnplugLevel = level;
14933             }
14934             mDischargeAmountScreenOn = 0;
14935             mDischargeAmountScreenDoze = 0;
14936             mDischargeAmountScreenOff = 0;
14937             updateTimeBasesLocked(true, screenState, uptimeUs, realtimeUs);
14938         } else {
14939             mOnBattery = mOnBatteryInternal = false;
14940             pullPendingStateUpdatesLocked();
14941             mBatteryPluggedIn = true;
14942             mBatteryPluggedInRealTimeMs = mSecRealtime;
14943             mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
14944             mDischargeCurrentLevel = mDischargePlugLevel = level;
14945             if (level < mDischargeUnplugLevel) {
14946                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
14947                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
14948             }
14949             updateDischargeScreenLevelsLocked(screenState, screenState);
14950             updateTimeBasesLocked(false, screenState, uptimeUs, realtimeUs);
14951             mChargeStepTracker.init();
14952             mLastChargeStepLevel = level;
14953             mMaxChargeStepLevel = level;
14954             mInitStepMode = mCurStepMode;
14955             mModStepMode = 0;
14956             scheduleNextResetWhilePluggedInCheck();
14957         }
14958         if (doWrite || (mLastWriteTimeMs + (60 * 1000)) < mSecRealtime) {
14959             if (mStatsFile != null && !mHistory.isReadOnly()) {
14960                 writeAsyncLocked();
14961             }
14962         }
14963     }
14964 
14965     private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
14966         if (mExternalSync != null) {
14967             mExternalSync.scheduleSync(reason, updateFlags);
14968         }
14969     }
14970 
14971     // This should probably be exposed in the API, though it's not critical
14972     public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
14973 
14974     @GuardedBy("this")
14975     public void setBatteryStateLocked(final int status, final int health, final int plugType,
14976             final int level, /* not final */ int temp, final int voltageMv, final int chargeUah,
14977             final int chargeFullUah, final long chargeTimeToFullSeconds,
14978             final long elapsedRealtimeMs, final long uptimeMs, final long currentTimeMs) {
14979 
14980         // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
14981         temp = Math.max(0, temp);
14982 
14983         reportChangesToStatsLog(status, plugType, level);
14984 
14985         final boolean onBattery = isOnBattery(plugType, status);
14986         if (!mHaveBatteryLevel) {
14987             mHaveBatteryLevel = true;
14988             // We start out assuming that the device is plugged in (not
14989             // on battery).  If our first report is now that we are indeed
14990             // plugged in, then twiddle our state to correctly reflect that
14991             // since we won't be going through the full setOnBattery().
14992             if (onBattery == mOnBattery) {
14993                 mHistory.setPluggedInState(!onBattery);
14994             }
14995             mBatteryStatus = status;
14996             mBatteryLevel = level;
14997             mBatteryChargeUah = chargeUah;
14998 
14999             // Always start out assuming charging, that will be updated later.
15000             mHistory.setBatteryState(true /* charging */, status, level, chargeUah);
15001 
15002             mMaxChargeStepLevel = mMinDischargeStepLevel =
15003                     mLastChargeStepLevel = mLastDischargeStepLevel = level;
15004         } else if (mBatteryLevel != level || mOnBattery != onBattery) {
15005             recordDailyStatsIfNeededLocked(level >= 100 && onBattery, currentTimeMs);
15006         }
15007         int oldStatus = mBatteryStatus;
15008         if (onBattery) {
15009             mDischargeCurrentLevel = level;
15010             if (!mHistory.isRecordingHistory()) {
15011                 mHistory.startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
15012             }
15013         } else if (level < 96 &&
15014                 status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
15015             if (!mHistory.isRecordingHistory()) {
15016                 mHistory.startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
15017             }
15018         }
15019         if (mDischargePlugLevel < 0) {
15020             mDischargePlugLevel = level;
15021         }
15022 
15023         if (onBattery != mOnBattery) {
15024             mBatteryLevel = level;
15025             mBatteryStatus = status;
15026             mBatteryHealth = health;
15027             mBatteryPlugType = plugType;
15028             mBatteryTemperature = temp;
15029             mBatteryVoltageMv = voltageMv;
15030             mHistory.setBatteryState(status, level, health, plugType, temp, voltageMv, chargeUah);
15031             if (chargeUah < mBatteryChargeUah) {
15032                 // Only record discharges
15033                 final long chargeDiff = (long) mBatteryChargeUah - chargeUah;
15034                 mDischargeCounter.addCountLocked(chargeDiff);
15035                 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
15036                 if (Display.isDozeState(mScreenState)) {
15037                     mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
15038                 }
15039                 if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
15040                     mDischargeLightDozeCounter.addCountLocked(chargeDiff);
15041                 } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
15042                     mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
15043                 }
15044             }
15045             mBatteryChargeUah = chargeUah;
15046             setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUah);
15047         } else {
15048             boolean changed = false;
15049             if (mBatteryLevel != level) {
15050                 mBatteryLevel = level;
15051                 changed = true;
15052 
15053                 // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
15054                 // which will pull external stats.
15055                 mExternalSync.scheduleSyncDueToBatteryLevelChange(
15056                         mConstants.BATTERY_LEVEL_COLLECTION_DELAY_MS);
15057             }
15058             if (mBatteryStatus != status) {
15059                 mBatteryStatus = status;
15060                 changed = true;
15061             }
15062             if (mBatteryHealth != health) {
15063                 mBatteryHealth = health;
15064                 changed = true;
15065             }
15066             if (mBatteryPlugType != plugType) {
15067                 mBatteryPlugType = plugType;
15068                 changed = true;
15069             }
15070             if (temp >= (mBatteryTemperature + 10)
15071                     || temp <= (mBatteryTemperature - 10)) {
15072                 mBatteryTemperature = temp;
15073                 changed = true;
15074             }
15075             if (voltageMv > (mBatteryVoltageMv + 20)
15076                     || voltageMv < (mBatteryVoltageMv - 20)) {
15077                 mBatteryVoltageMv = voltageMv;
15078                 changed = true;
15079             }
15080             if (chargeUah >= (mBatteryChargeUah + 10)
15081                     || chargeUah <= (mBatteryChargeUah - 10)) {
15082                 if (chargeUah < mBatteryChargeUah) {
15083                     // Only record discharges
15084                     final long chargeDiff = (long) mBatteryChargeUah - chargeUah;
15085                     mDischargeCounter.addCountLocked(chargeDiff);
15086                     mDischargeScreenOffCounter.addCountLocked(chargeDiff);
15087                     if (Display.isDozeState(mScreenState)) {
15088                         mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
15089                     }
15090                     if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
15091                         mDischargeLightDozeCounter.addCountLocked(chargeDiff);
15092                     } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
15093                         mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
15094                     }
15095                 }
15096                 mBatteryChargeUah = chargeUah;
15097                 changed = true;
15098             }
15099 
15100             long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
15101                     | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
15102                     | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
15103             if (onBattery) {
15104                 changed |= setChargingLocked(false);
15105                 if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
15106                     mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
15107                             modeBits, elapsedRealtimeMs);
15108                     mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
15109                             modeBits, elapsedRealtimeMs);
15110                     mLastDischargeStepLevel = level;
15111                     mMinDischargeStepLevel = level;
15112                     mInitStepMode = mCurStepMode;
15113                     mModStepMode = 0;
15114                 }
15115             } else {
15116                 if (level >= mConstants.BATTERY_CHARGING_ENFORCE_LEVEL) {
15117                     // If the battery level is at least Constants.BATTERY_CHARGING_ENFORCE_LEVEL,
15118                     // always consider the device to be charging even if it happens to go down a
15119                     // level.
15120                     changed |= setChargingLocked(true);
15121                 } else if (!mCharging) {
15122                     if (mLastChargeStepLevel < level) {
15123                         // We have not reported that we are charging, but the level has gone up,
15124                         // but we would like to not have tons of activity from charging-constraint
15125                         // jobs, so instead of reporting ACTION_CHARGING immediately, we defer it.
15126                         if (!mHandler.hasCallbacks(mDeferSetCharging)) {
15127                             mHandler.postDelayed(
15128                                     mDeferSetCharging,
15129                                     mConstants.BATTERY_CHARGED_DELAY_MS);
15130                         }
15131                     } else if (mLastChargeStepLevel > level) {
15132                         // if we had deferred a runnable due to charge level increasing, but then
15133                         // later the charge level drops (could be due to thermal issues), we don't
15134                         // want to trigger the deferred runnable, so remove it here
15135                         mHandler.removeCallbacks(mDeferSetCharging);
15136                     }
15137                 } else {
15138                     if (mLastChargeStepLevel > level) {
15139                         // We had reported that the device was charging, but here we are with
15140                         // power connected and the level going down.  Looks like the current
15141                         // power supplied isn't enough, so consider the device to now be
15142                         // discharging.
15143                         changed |= setChargingLocked(false);
15144                     }
15145                 }
15146                 if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
15147                     mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
15148                             modeBits, elapsedRealtimeMs);
15149                     mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
15150                             modeBits, elapsedRealtimeMs);
15151                     mMaxChargeStepLevel = level;
15152                     mInitStepMode = mCurStepMode;
15153                     mModStepMode = 0;
15154                 }
15155                 mLastChargeStepLevel = level;
15156             }
15157             if (changed) {
15158                 mHistory.setBatteryState(mBatteryStatus, mBatteryLevel, mBatteryHealth,
15159                         mBatteryPlugType, mBatteryTemperature, mBatteryVoltageMv,
15160                         mBatteryChargeUah);
15161                 mHistory.writeHistoryItem(elapsedRealtimeMs, uptimeMs);
15162             }
15163         }
15164         if (!onBattery &&
15165                 (status == BatteryManager.BATTERY_STATUS_FULL ||
15166                         status == BatteryManager.BATTERY_STATUS_UNKNOWN)) {
15167             // We don't record history while we are plugged in and fully charged
15168             // (or when battery is not present).  The next time we are
15169             // unplugged, history will be cleared.
15170             mHistory.setHistoryRecordingEnabled(DEBUG);
15171         }
15172 
15173         mLastLearnedBatteryCapacityUah = chargeFullUah;
15174         if (mMinLearnedBatteryCapacityUah == -1) {
15175             mMinLearnedBatteryCapacityUah = chargeFullUah;
15176         } else {
15177             mMinLearnedBatteryCapacityUah = Math.min(mMinLearnedBatteryCapacityUah, chargeFullUah);
15178         }
15179         mMaxLearnedBatteryCapacityUah = Math.max(mMaxLearnedBatteryCapacityUah, chargeFullUah);
15180 
15181         mBatteryTimeToFullSeconds = chargeTimeToFullSeconds;
15182     }
15183 
15184     public static boolean isOnBattery(int plugType, int status) {
15185         return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN;
15186     }
15187 
15188     // Inform StatsLog of setBatteryState changes.
15189     private void reportChangesToStatsLog(final int status, final int plugType, final int level) {
15190         if (!mHaveBatteryLevel || mBatteryStatus != status) {
15191             mFrameworkStatsLogger.chargingStateChanged(status);
15192         }
15193         if (!mHaveBatteryLevel || mBatteryPlugType != plugType) {
15194             mFrameworkStatsLogger.pluggedStateChanged(plugType);
15195         }
15196         if (!mHaveBatteryLevel || mBatteryLevel != level) {
15197             mFrameworkStatsLogger.batteryLevelChanged(level);
15198         }
15199     }
15200 
15201     public long getAwakeTimeBattery() {
15202         // This previously evaluated to mOnBatteryTimeBase.getUptime(getBatteryUptimeLocked());
15203         // for over a decade, but surely that was a mistake.
15204         return getBatteryUptimeLocked(mClock.uptimeMillis());
15205     }
15206 
15207     public long getAwakeTimePlugged() {
15208         return (mClock.uptimeMillis() * 1000) - getAwakeTimeBattery();
15209     }
15210 
15211     @Override
15212     public long computeUptime(long curTimeUs, int which) {
15213         return mUptimeUs + (curTimeUs - mUptimeStartUs);
15214     }
15215 
15216     @Override
15217     public long computeRealtime(long curTimeUs, int which) {
15218         return mRealtimeUs + (curTimeUs - mRealtimeStartUs);
15219     }
15220 
15221     @Override
15222     public long computeBatteryUptime(long curTimeUs, int which) {
15223         return mOnBatteryTimeBase.computeUptime(curTimeUs, which);
15224     }
15225 
15226     @Override
15227     public long computeBatteryRealtime(long curTimeUs, int which) {
15228         return mOnBatteryTimeBase.computeRealtime(curTimeUs, which);
15229     }
15230 
15231     @Override
15232     public long computeBatteryScreenOffUptime(long curTimeUs, int which) {
15233         return mOnBatteryScreenOffTimeBase.computeUptime(curTimeUs, which);
15234     }
15235 
15236     @Override
15237     public long computeBatteryScreenOffRealtime(long curTimeUs, int which) {
15238         return mOnBatteryScreenOffTimeBase.computeRealtime(curTimeUs, which);
15239     }
15240 
15241     @Override
15242     public long computeBatteryTimeRemaining(long curTime) {
15243         if (!mOnBattery) {
15244             return -1;
15245         }
15246         /* Simple implementation just looks at the average discharge per level across the
15247            entire sample period.
15248         int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
15249         if (discharge < 2) {
15250             return -1;
15251         }
15252         long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
15253         if (duration < 1000*1000) {
15254             return -1;
15255         }
15256         long usPerLevel = duration/discharge;
15257         return usPerLevel * mCurrentBatteryLevel;
15258         */
15259         if (mDischargeStepTracker.mNumStepDurations < 1) {
15260             return -1;
15261         }
15262         long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
15263         if (msPerLevel <= 0) {
15264             return -1;
15265         }
15266         return (msPerLevel * mBatteryLevel) * 1000;
15267     }
15268 
15269     @Override
15270     public LevelStepTracker getDischargeLevelStepTracker() {
15271         return mDischargeStepTracker;
15272     }
15273 
15274     @Override
15275     public LevelStepTracker getDailyDischargeLevelStepTracker() {
15276         return mDailyDischargeStepTracker;
15277     }
15278 
15279     @Override
15280     public long computeChargeTimeRemaining(long curTime) {
15281         if (mOnBattery) {
15282             // Not yet working.
15283             return -1;
15284         }
15285         if (mBatteryTimeToFullSeconds >= 0) {
15286             return mBatteryTimeToFullSeconds * (1000 * 1000); // s to us
15287         }
15288         // Else use algorithmic approach
15289         if (mChargeStepTracker.mNumStepDurations < 1) {
15290             return -1;
15291         }
15292         long msPerLevel = mChargeStepTracker.computeTimePerLevel();
15293         if (msPerLevel <= 0) {
15294             return -1;
15295         }
15296         return (msPerLevel * (100 - mBatteryLevel)) * 1000;
15297     }
15298 
15299     /*@hide */
15300     public CellularBatteryStats getCellularBatteryStats() {
15301         final int which = STATS_SINCE_CHARGED;
15302         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
15303         final ControllerActivityCounter counter = getModemControllerActivity();
15304         final long sleepTimeMs = counter.getSleepTimeCounter().getCountLocked(which);
15305         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
15306         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
15307         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
15308         final long monitoredRailChargeConsumedMaMs =
15309                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
15310         long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
15311         for (int i = 0; i < timeInRatMs.length; i++) {
15312             timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTimeUs, which) / 1000;
15313         }
15314         long[] timeInRxSignalStrengthLevelMs =
15315                 new long[CELL_SIGNAL_STRENGTH_LEVEL_COUNT];
15316         for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
15317             timeInRxSignalStrengthLevelMs[i] =
15318                 getPhoneSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
15319         }
15320         long[] txTimeMs = new long[Math.min(MODEM_TX_POWER_LEVEL_COUNT,
15321             counter.getTxTimeCounters().length)];
15322         long totalTxTimeMs = 0;
15323         for (int i = 0; i < txTimeMs.length; i++) {
15324             txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
15325             totalTxTimeMs += txTimeMs[i];
15326         }
15327 
15328         return new CellularBatteryStats(computeBatteryRealtime(rawRealTimeUs, which) / 1000,
15329                 getMobileRadioActiveTime(rawRealTimeUs, which) / 1000,
15330                 getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which),
15331                 getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which),
15332                 getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which),
15333                 getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which),
15334                 sleepTimeMs, idleTimeMs, rxTimeMs, energyConsumedMaMs, timeInRatMs,
15335                 timeInRxSignalStrengthLevelMs, txTimeMs,
15336                 monitoredRailChargeConsumedMaMs);
15337     }
15338 
15339     /*@hide */
15340     public WifiBatteryStats getWifiBatteryStats() {
15341         final int which = STATS_SINCE_CHARGED;
15342         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
15343         final ControllerActivityCounter counter = getWifiControllerActivity();
15344         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
15345         final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which);
15346         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
15347         final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which);
15348         final long totalControllerActivityTimeMs
15349                 = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000;
15350         final long sleepTimeMs
15351                 = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs);
15352         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
15353         final long monitoredRailChargeConsumedMaMs =
15354                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
15355         long numAppScanRequest = 0;
15356         for (int i = 0; i < mUidStats.size(); i++) {
15357             numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which);
15358         }
15359         long[] timeInStateMs = new long[NUM_WIFI_STATES];
15360         for (int i=0; i<NUM_WIFI_STATES; i++) {
15361             timeInStateMs[i] = getWifiStateTime(i, rawRealTimeUs, which) / 1000;
15362         }
15363         long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES];
15364         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
15365             timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTimeUs, which) / 1000;
15366         }
15367         long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS];
15368         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
15369             timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
15370         }
15371         return new WifiBatteryStats(
15372                 computeBatteryRealtime(rawRealTimeUs, which) / 1000,
15373                 getWifiActiveTime(rawRealTimeUs, which) / 1000,
15374                 getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which),
15375                 getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which),
15376                 getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which),
15377                 getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which),
15378                 sleepTimeMs, scanTimeMs, idleTimeMs, rxTimeMs, txTimeMs, energyConsumedMaMs,
15379                 numAppScanRequest, timeInStateMs, timeSignalStrengthTimeMs, timeInSupplStateMs,
15380                 monitoredRailChargeConsumedMaMs);
15381     }
15382 
15383     /*@hide */
15384     public GpsBatteryStats getGpsBatteryStats() {
15385         GpsBatteryStats s = new GpsBatteryStats();
15386         final int which = STATS_SINCE_CHARGED;
15387         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
15388         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTimeUs, which) / 1000);
15389         s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
15390         long[] time = new long[mGpsSignalQualityTimer.length];
15391         for (int i=0; i<time.length; i++) {
15392             time[i] = getGpsSignalQualityTime(i, rawRealTimeUs, which) / 1000;
15393         }
15394         s.setTimeInGpsSignalQualityLevel(time);
15395         return s;
15396     }
15397 
15398     @Override
15399     public LevelStepTracker getChargeLevelStepTracker() {
15400         return mChargeStepTracker;
15401     }
15402 
15403     @Override
15404     public LevelStepTracker getDailyChargeLevelStepTracker() {
15405         return mDailyChargeStepTracker;
15406     }
15407 
15408     @Override
15409     public ArrayList<PackageChange> getDailyPackageChanges() {
15410         return mDailyPackageChanges;
15411     }
15412 
15413     /**
15414      * @return battery uptime in microseconds
15415      */
15416     protected long getBatteryUptimeLocked(long uptimeMs) {
15417         return mOnBatteryTimeBase.getUptime(uptimeMs * 1000);
15418     }
15419 
15420     @Override
15421     public long getBatteryUptime(long curTimeUs) {
15422         return mOnBatteryTimeBase.getUptime(curTimeUs);
15423     }
15424 
15425     @Override
15426     public long getBatteryRealtime(long curTimeUs) {
15427         return mOnBatteryTimeBase.getRealtime(curTimeUs);
15428     }
15429 
15430     @Override
15431     public int getDischargeStartLevel() {
15432         synchronized(this) {
15433             return getDischargeStartLevelLocked();
15434         }
15435     }
15436 
15437     public int getDischargeStartLevelLocked() {
15438             return mDischargeUnplugLevel;
15439     }
15440 
15441     @Override
15442     public int getDischargeCurrentLevel() {
15443         synchronized(this) {
15444             return getDischargeCurrentLevelLocked();
15445         }
15446     }
15447 
15448     public int getDischargeCurrentLevelLocked() {
15449         return mDischargeCurrentLevel;
15450     }
15451 
15452     @Override
15453     public int getLowDischargeAmountSinceCharge() {
15454         synchronized(this) {
15455             int val = mLowDischargeAmountSinceCharge;
15456             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
15457                 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
15458             }
15459             return val;
15460         }
15461     }
15462 
15463     @Override
15464     public int getHighDischargeAmountSinceCharge() {
15465         synchronized(this) {
15466             int val = mHighDischargeAmountSinceCharge;
15467             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
15468                 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
15469             }
15470             return val;
15471         }
15472     }
15473 
15474     @Override
15475     public int getDischargeAmount(int which) {
15476         int dischargeAmount = which == STATS_SINCE_CHARGED
15477                 ? getHighDischargeAmountSinceCharge()
15478                 : (getDischargeStartLevel() - getDischargeCurrentLevel());
15479         if (dischargeAmount < 0) {
15480             dischargeAmount = 0;
15481         }
15482         return dischargeAmount;
15483     }
15484 
15485     @Override
15486     public int getDischargeAmountScreenOn() {
15487         synchronized(this) {
15488             int val = mDischargeAmountScreenOn;
15489             if (mOnBattery && Display.isOnState(mScreenState)
15490                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
15491                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
15492             }
15493             return val;
15494         }
15495     }
15496 
15497     @Override
15498     public int getDischargeAmountScreenOnSinceCharge() {
15499         synchronized(this) {
15500             int val = mDischargeAmountScreenOnSinceCharge;
15501             if (mOnBattery && Display.isOnState(mScreenState)
15502                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
15503                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
15504             }
15505             return val;
15506         }
15507     }
15508 
15509     @Override
15510     public int getDischargeAmountScreenOff() {
15511         synchronized(this) {
15512             int val = mDischargeAmountScreenOff;
15513             if (mOnBattery && Display.isOffState(mScreenState)
15514                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
15515                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
15516             }
15517             // For backward compatibility, doze discharge is counted into screen off.
15518             return val + getDischargeAmountScreenDoze();
15519         }
15520     }
15521 
15522     @Override
15523     public int getDischargeAmountScreenOffSinceCharge() {
15524         synchronized(this) {
15525             int val = mDischargeAmountScreenOffSinceCharge;
15526             if (mOnBattery && Display.isOffState(mScreenState)
15527                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
15528                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
15529             }
15530             // For backward compatibility, doze discharge is counted into screen off.
15531             return val + getDischargeAmountScreenDozeSinceCharge();
15532         }
15533     }
15534 
15535     @Override
15536     public int getDischargeAmountScreenDoze() {
15537         synchronized(this) {
15538             int val = mDischargeAmountScreenDoze;
15539             if (mOnBattery && Display.isDozeState(mScreenState)
15540                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
15541                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
15542             }
15543             return val;
15544         }
15545     }
15546 
15547     @Override
15548     public int getDischargeAmountScreenDozeSinceCharge() {
15549         synchronized(this) {
15550             int val = mDischargeAmountScreenDozeSinceCharge;
15551             if (mOnBattery && Display.isDozeState(mScreenState)
15552                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
15553                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
15554             }
15555             return val;
15556         }
15557     }
15558 
15559 
15560     /**
15561      * Estimates the time spent by the system server handling incoming binder requests.
15562      */
15563     @Override
15564     public long[] getSystemServiceTimeAtCpuSpeeds() {
15565         if (mBinderThreadCpuTimesUs == null) {
15566             return null;
15567         }
15568 
15569         return mBinderThreadCpuTimesUs.getCountsLocked(BatteryStats.STATS_SINCE_CHARGED);
15570     }
15571 
15572     /**
15573      * Retrieve the statistics object for a particular uid, creating if needed.
15574      */
15575     public Uid getUidStatsLocked(int uid) {
15576         return getUidStatsLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
15577     }
15578 
15579     public Uid getUidStatsLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
15580         Uid u = mUidStats.get(uid);
15581         if (u == null) {
15582             if (Process.isSdkSandboxUid(uid)) {
15583                 Log.wtf(TAG, "Tracking an SDK Sandbox UID");
15584             }
15585             u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
15586             mUidStats.put(uid, u);
15587         }
15588         return u;
15589     }
15590 
15591     /**
15592      * Retrieve the statistics object for a particular uid. Returns null if the object is not
15593      * available.
15594      */
15595     public Uid getAvailableUidStatsLocked(int uid) {
15596         Uid u = mUidStats.get(uid);
15597         return u;
15598     }
15599 
15600     @GuardedBy("this")
15601     public void onCleanupUserLocked(int userId, long elapsedRealtimeMs) {
15602         final int firstUidForUser = UserHandle.getUid(userId, 0);
15603         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
15604         mPendingRemovedUids.add(
15605                 new UidToRemove(firstUidForUser, lastUidForUser, elapsedRealtimeMs));
15606     }
15607 
15608     @GuardedBy("this")
15609     public void onUserRemovedLocked(int userId) {
15610         if (mExternalSync != null) {
15611             // Clear out the removed user's UIDs after a short delay. The delay is needed
15612             // because at the point that this method is called, some activities are still
15613             // being wrapped up by those UIDs
15614             mExternalSync.scheduleCleanupDueToRemovedUser(userId);
15615         }
15616     }
15617 
15618     /**
15619      * Removes battery stats for UIDs corresponding to a removed user.
15620      */
15621     @GuardedBy("this")
15622     public void clearRemovedUserUidsLocked(int userId) {
15623         final int firstUidForUser = UserHandle.getUid(userId, 0);
15624         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
15625         mUidStats.put(firstUidForUser, null);
15626         mUidStats.put(lastUidForUser, null);
15627         final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
15628         final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
15629         for (int i = firstIndex; i <= lastIndex; i++) {
15630             final Uid uid = mUidStats.valueAt(i);
15631             if (uid != null) {
15632                 uid.detachFromTimeBase();
15633             }
15634         }
15635         mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
15636         removeCpuStatsForUidRangeLocked(firstUidForUser, lastUidForUser);
15637     }
15638 
15639     /**
15640      * @see #removeUidStatsLocked(int)
15641      */
15642     @GuardedBy("this")
15643     public void removeUidStatsLocked(int uid, long elapsedRealtimeMs) {
15644         final Uid u = mUidStats.get(uid);
15645         if (u != null) {
15646             u.detachFromTimeBase();
15647         }
15648         mUidStats.remove(uid);
15649         mPendingRemovedUids.add(new UidToRemove(uid, elapsedRealtimeMs));
15650     }
15651 
15652     /**
15653      * Removes the data for the deleted UIDs from the underlying kernel eBPF tables.
15654      */
15655     @GuardedBy("this")
15656     private void removeCpuStatsForUidRangeLocked(int startUid, int endUid) {
15657         if (startUid == endUid) {
15658             mCpuUidUserSysTimeReader.removeUid(startUid);
15659             mCpuUidFreqTimeReader.removeUid(startUid);
15660             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
15661                 mCpuUidActiveTimeReader.removeUid(startUid);
15662                 mCpuUidClusterTimeReader.removeUid(startUid);
15663             }
15664             if (mKernelSingleUidTimeReader != null) {
15665                 mKernelSingleUidTimeReader.removeUid(startUid);
15666             }
15667             mNumUidsRemoved++;
15668         } else if (startUid < endUid) {
15669             mCpuUidFreqTimeReader.removeUidsInRange(startUid, endUid);
15670             mCpuUidUserSysTimeReader.removeUidsInRange(startUid, endUid);
15671             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
15672                 mCpuUidActiveTimeReader.removeUidsInRange(startUid, endUid);
15673                 mCpuUidClusterTimeReader.removeUidsInRange(startUid, endUid);
15674             }
15675             if (mKernelSingleUidTimeReader != null) {
15676                 mKernelSingleUidTimeReader.removeUidsInRange(startUid, endUid);
15677             }
15678             mPowerStatsUidResolver.releaseUidsInRange(startUid, endUid);
15679             // Treat as one. We don't know how many uids there are in between.
15680             mNumUidsRemoved++;
15681         } else {
15682             Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
15683         }
15684     }
15685 
15686     /**
15687      * Retrieve the statistics object for a particular process, creating
15688      * if needed.
15689      */
15690     public Uid.Proc getProcessStatsLocked(int uid, String name,
15691             long elapsedRealtimeMs, long uptimeMs) {
15692         uid = mapUid(uid);
15693         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
15694         return u.getProcessStatsLocked(name);
15695     }
15696 
15697     /**
15698      * Retrieve the statistics object for a particular process, creating
15699      * if needed.
15700      */
15701     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
15702         return getPackageStatsLocked(uid, pkg, mClock.elapsedRealtime(), mClock.uptimeMillis());
15703     }
15704 
15705     /**
15706      * @see getPackageStatsLocked(int, String)
15707      */
15708     public Uid.Pkg getPackageStatsLocked(int uid, String pkg,
15709             long elapsedRealtimeMs, long uptimeMs) {
15710         uid = mapUid(uid);
15711         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
15712         return u.getPackageStatsLocked(pkg);
15713     }
15714 
15715     /**
15716      * Retrieve the statistics object for a particular service, creating
15717      * if needed.
15718      */
15719     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name,
15720             long elapsedRealtimeMs, long uptimeMs) {
15721         uid = mapUid(uid);
15722         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
15723         return u.getServiceStatsLocked(pkg, name);
15724     }
15725 
15726     @GuardedBy("this")
15727     public void shutdownLocked() {
15728         mHistory.recordShutdownEvent(mClock.elapsedRealtime(), mClock.uptimeMillis(),
15729                 mClock.currentTimeMillis());
15730         writeSyncLocked();
15731         mShuttingDown = true;
15732     }
15733 
15734     @Override
15735     public boolean isProcessStateDataAvailable() {
15736         synchronized (this) {
15737             return trackPerProcStateCpuTimes();
15738         }
15739     }
15740 
15741     @GuardedBy("this")
15742     private boolean trackPerProcStateCpuTimes() {
15743         return mCpuUidFreqTimeReader.isFastCpuTimesReader();
15744     }
15745 
15746     /**
15747      * Enables or disables the PowerStatsCollector mode.
15748      */
15749     public void setPowerStatsCollectorEnabled(@BatteryConsumer.PowerComponent int powerComponent,
15750             boolean enabled) {
15751         synchronized (this) {
15752             mPowerStatsCollectorEnabled.put(powerComponent, enabled);
15753         }
15754     }
15755 
15756     @GuardedBy("this")
15757     public void systemServicesReady(Context context) {
15758         mConstants.startObserving(context.getContentResolver());
15759         registerUsbStateReceiver(context);
15760 
15761         synchronized (this) {
15762             mAlarmManager = context.getSystemService(AlarmManager.class);
15763             if (mBatteryPluggedIn) {
15764                 // Already plugged in. Schedule the long plug in alarm.
15765                 scheduleNextResetWhilePluggedInCheck();
15766             }
15767         }
15768     }
15769 
15770     /**
15771      * Initialize the EnergyConsumer stats data structures.
15772      *
15773      * @param supportedStandardBuckets boolean array indicating which {@link StandardPowerBucket}s
15774      *                                 are currently supported. If null, none are supported
15775      *                                 (regardless of customBucketNames).
15776      * @param customBucketNames        names of custom (OTHER) EnergyConsumers on this device
15777      */
15778     @GuardedBy("this")
15779     public void initEnergyConsumerStatsLocked(@Nullable boolean[] supportedStandardBuckets,
15780             String[] customBucketNames) {
15781         final int numDisplays = mPerDisplayBatteryStats.length;
15782         for (int i = 0; i < numDisplays; i++) {
15783             final int screenState = mPerDisplayBatteryStats[i].screenState;
15784             mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState;
15785         }
15786 
15787         if (supportedStandardBuckets != null) {
15788             final EnergyConsumerStats.Config config = new EnergyConsumerStats.Config(
15789                     supportedStandardBuckets, customBucketNames,
15790                     SUPPORTED_PER_PROCESS_STATE_STANDARD_ENERGY_BUCKETS,
15791                     getBatteryConsumerProcessStateNames());
15792 
15793             if (mEnergyConsumerStatsConfig != null
15794                     &&  !mEnergyConsumerStatsConfig.isCompatible(config)) {
15795                 // Supported power buckets changed since last boot.
15796                 // Existing data is no longer reliable.
15797                 resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
15798                         RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE);
15799             }
15800 
15801             mEnergyConsumerStatsConfig = config;
15802             mGlobalEnergyConsumerStats = new EnergyConsumerStats(config);
15803 
15804             if (supportedStandardBuckets[EnergyConsumerStats.POWER_BUCKET_BLUETOOTH]) {
15805                 mBluetoothPowerCalculator = new BluetoothPowerCalculator(mPowerProfile);
15806             }
15807             if (supportedStandardBuckets[EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO]) {
15808                 mMobileRadioPowerCalculator = new MobileRadioPowerCalculator(mPowerProfile);
15809             }
15810             if (supportedStandardBuckets[EnergyConsumerStats.POWER_BUCKET_WIFI]) {
15811                 mWifiPowerCalculator = new WifiPowerCalculator(mPowerProfile);
15812             }
15813         } else {
15814             if (mEnergyConsumerStatsConfig != null) {
15815                 // EnergyConsumer no longer supported, wipe out the existing data.
15816                 resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
15817                         RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE);
15818             }
15819             mEnergyConsumerStatsConfig = null;
15820             mGlobalEnergyConsumerStats = null;
15821         }
15822     }
15823 
15824     @GuardedBy("this")
15825     private boolean isMobileRadioEnergyConsumerSupportedLocked() {
15826         if (mGlobalEnergyConsumerStats == null) return false;
15827         return mGlobalEnergyConsumerStats.isStandardBucketSupported(
15828                 EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO);
15829     }
15830 
15831     @NonNull
15832     private static String[] getBatteryConsumerProcessStateNames() {
15833         String[] procStateNames = new String[BatteryConsumer.PROCESS_STATE_COUNT];
15834         for (int procState = 0; procState < BatteryConsumer.PROCESS_STATE_COUNT; procState++) {
15835             procStateNames[procState] = BatteryConsumer.processStateToString(procState);
15836         }
15837         return procStateNames;
15838     }
15839 
15840     /** Get the last known Battery voltage (in millivolts), returns -1 if unknown */
15841     @GuardedBy("this")
15842     public int getBatteryVoltageMvLocked() {
15843         return mBatteryVoltageMv;
15844     }
15845 
15846     @VisibleForTesting
15847     public final class Constants extends ContentObserver {
15848         public static final String KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME
15849                 = "track_cpu_active_cluster_time";
15850         public static final String KEY_KERNEL_UID_READERS_THROTTLE_TIME
15851                 = "kernel_uid_readers_throttle_time";
15852         public static final String KEY_UID_REMOVE_DELAY_MS
15853                 = "uid_remove_delay_ms";
15854         public static final String KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
15855                 = "external_stats_collection_rate_limit_ms";
15856         public static final String KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS
15857                 = "battery_level_collection_delay_ms";
15858         public static final String KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS =
15859                 "procstate_change_collection_delay_ms";
15860         public static final String KEY_MAX_HISTORY_FILES = "max_history_files";
15861         public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
15862         public static final String KEY_BATTERY_CHARGED_DELAY_MS =
15863                 "battery_charged_delay_ms";
15864         public static final String KEY_BATTERY_CHARGING_ENFORCE_LEVEL =
15865                 "battery_charging_enforce_level";
15866         public static final String KEY_PER_UID_MODEM_POWER_MODEL =
15867                 "per_uid_modem_power_model";
15868         public static final String KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION =
15869                 "phone_on_external_stats_collection";
15870         public static final String KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS =
15871                 "reset_while_plugged_in_minimum_duration_hours";
15872 
15873         public static final String PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME =
15874                 "mobile_radio_active_time";
15875         public static final String PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME =
15876                 "modem_activity_info_rx_tx";
15877 
15878         /** Convert {@link PerUidModemPowerModel} to string */
15879         public String getPerUidModemModelName(@PerUidModemPowerModel int model) {
15880             switch(model) {
15881                 case PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME:
15882                     return PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME;
15883                 case PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX:
15884                     return PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME;
15885                 default:
15886                     Slog.w(TAG, "Unexpected per uid modem model (" + model + ")");
15887                     return "unknown_" + model;
15888             }
15889         }
15890 
15891         /** Convert string to {@link PerUidModemPowerModel} */
15892         @PerUidModemPowerModel
15893         public int getPerUidModemModel(String name) {
15894             switch(name) {
15895                 case PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME:
15896                     return PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME;
15897                 case PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME:
15898                     return PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX;
15899                 default:
15900                     Slog.w(TAG, "Unexpected per uid modem model name (" + name + ")");
15901                     return DEFAULT_PER_UID_MODEM_MODEL;
15902             }
15903         }
15904 
15905         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
15906         private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000;
15907         private static final long DEFAULT_UID_REMOVE_DELAY_MS = 5L * 60L * 1000L;
15908         private static final long DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = 600_000;
15909         private static final long DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS = 300_000;
15910         private static final long DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS = 60_000;
15911         private static final int DEFAULT_MAX_HISTORY_FILES = 32;
15912         private static final int DEFAULT_MAX_HISTORY_BUFFER_KB = 128; /*Kilo Bytes*/
15913         private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64;
15914         private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
15915         private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
15916         private static final int DEFAULT_BATTERY_CHARGING_ENFORCE_LEVEL = 90;
15917         @PerUidModemPowerModel
15918         private static final int DEFAULT_PER_UID_MODEM_MODEL =
15919                 PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX;
15920         private static final boolean DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION = true;
15921         // Little less than 2 days
15922         private static final int DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS = 47;
15923 
15924         public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
15925         /* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
15926          * update when startObserving. */
15927         public long KERNEL_UID_READERS_THROTTLE_TIME;
15928         public long UID_REMOVE_DELAY_MS = DEFAULT_UID_REMOVE_DELAY_MS;
15929         public long EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
15930                 = DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
15931         public long BATTERY_LEVEL_COLLECTION_DELAY_MS
15932                 = DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS;
15933         public long PROC_STATE_CHANGE_COLLECTION_DELAY_MS =
15934                 DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS;
15935         public int MAX_HISTORY_FILES;
15936         public int MAX_HISTORY_BUFFER; /*Bytes*/
15937         public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
15938         public int BATTERY_CHARGING_ENFORCE_LEVEL = DEFAULT_BATTERY_CHARGING_ENFORCE_LEVEL;
15939         public int PER_UID_MODEM_MODEL = DEFAULT_PER_UID_MODEM_MODEL;
15940         public boolean PHONE_ON_EXTERNAL_STATS_COLLECTION =
15941                 DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION;
15942         public int RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS =
15943                 DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS;
15944 
15945         private ContentResolver mResolver;
15946         private final KeyValueListParser mParser = new KeyValueListParser(',');
15947 
15948         public Constants(Handler handler) {
15949             super(handler);
15950             if (isLowRamDevice()) {
15951                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE;
15952                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB * 1024;
15953             } else {
15954                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES;
15955                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_KB * 1024;
15956             }
15957         }
15958 
15959         public void startObserving(ContentResolver resolver) {
15960             mResolver = resolver;
15961             mResolver.registerContentObserver(
15962                     Settings.Global.getUriFor(Settings.Global.BATTERY_STATS_CONSTANTS),
15963                     false /* notifyForDescendants */, this);
15964             mResolver.registerContentObserver(
15965                     Settings.Global.getUriFor(Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY),
15966                     false /* notifyForDescendants */, this);
15967             mResolver.registerContentObserver(Settings.Global.getUriFor(
15968                             Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL),
15969                     false /* notifyForDescendants */, this);
15970             updateConstants();
15971         }
15972 
15973         @Override
15974         public void onChange(boolean selfChange, Uri uri) {
15975             if (uri.equals(
15976                     Settings.Global.getUriFor(
15977                             Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY))) {
15978                 synchronized (BatteryStatsImpl.this) {
15979                     updateBatteryChargedDelayMsLocked();
15980                 }
15981                 return;
15982             } else if (uri.equals(Settings.Global.getUriFor(
15983                     Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL))) {
15984                 synchronized (BatteryStatsImpl.this) {
15985                     updateBatteryChargingEnforceLevelLocked();
15986                 }
15987                 return;
15988             }
15989             updateConstants();
15990         }
15991 
15992         private void updateConstants() {
15993             synchronized (BatteryStatsImpl.this) {
15994                 try {
15995                     mParser.setString(Settings.Global.getString(mResolver,
15996                             Settings.Global.BATTERY_STATS_CONSTANTS));
15997                 } catch (IllegalArgumentException e) {
15998                     // Failed to parse the settings string, log this and move on
15999                     // with defaults.
16000                     Slog.e(TAG, "Bad batterystats settings", e);
16001                 }
16002 
16003                 TRACK_CPU_ACTIVE_CLUSTER_TIME = mParser.getBoolean(
16004                         KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME, DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME);
16005                 updateKernelUidReadersThrottleTime(KERNEL_UID_READERS_THROTTLE_TIME,
16006                         mParser.getLong(KEY_KERNEL_UID_READERS_THROTTLE_TIME,
16007                                 DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME));
16008                 updateUidRemoveDelay(
16009                         mParser.getLong(KEY_UID_REMOVE_DELAY_MS, DEFAULT_UID_REMOVE_DELAY_MS));
16010                 EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = mParser.getLong(
16011                         KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS,
16012                         DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
16013                 BATTERY_LEVEL_COLLECTION_DELAY_MS = mParser.getLong(
16014                         KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS,
16015                         DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS);
16016                 PROC_STATE_CHANGE_COLLECTION_DELAY_MS = mParser.getLong(
16017                         KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS,
16018                         DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
16019                 MAX_HISTORY_FILES = mParser.getInt(KEY_MAX_HISTORY_FILES,
16020                         isLowRamDevice() ? DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE
16021                                 : DEFAULT_MAX_HISTORY_FILES);
16022                 MAX_HISTORY_BUFFER = mParser.getInt(KEY_MAX_HISTORY_BUFFER_KB,
16023                         isLowRamDevice() ? DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB
16024                                 : DEFAULT_MAX_HISTORY_BUFFER_KB)
16025                         * 1024;
16026                 final String perUidModemModel = mParser.getString(KEY_PER_UID_MODEM_POWER_MODEL,
16027                         "");
16028                 PER_UID_MODEM_MODEL = getPerUidModemModel(perUidModemModel);
16029 
16030                 PHONE_ON_EXTERNAL_STATS_COLLECTION = mParser.getBoolean(
16031                         KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION,
16032                         DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION);
16033 
16034                 RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS = mParser.getInt(
16035                         KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS,
16036                         DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS);
16037 
16038                 updateBatteryChargedDelayMsLocked();
16039                 updateBatteryChargingEnforceLevelLocked();
16040 
16041                 onChange();
16042             }
16043         }
16044 
16045         /**
16046          * Propagates changes in constant values.
16047          */
16048         @VisibleForTesting
16049         public void onChange() {
16050             mHistory.setMaxHistoryFiles(MAX_HISTORY_FILES);
16051             mHistory.setMaxHistoryBufferSize(MAX_HISTORY_BUFFER);
16052         }
16053 
16054         private void updateBatteryChargedDelayMsLocked() {
16055             // a negative value indicates that we should ignore this override
16056             final int delay = Settings.Global.getInt(mResolver,
16057                     Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
16058                     -1);
16059 
16060             BATTERY_CHARGED_DELAY_MS = delay >= 0 ? delay : mParser.getInt(
16061                     KEY_BATTERY_CHARGED_DELAY_MS,
16062                     DEFAULT_BATTERY_CHARGED_DELAY_MS);
16063 
16064             if (mHandler.hasCallbacks(mDeferSetCharging)) {
16065                 mHandler.removeCallbacks(mDeferSetCharging);
16066                 mHandler.postDelayed(mDeferSetCharging, BATTERY_CHARGED_DELAY_MS);
16067             }
16068         }
16069 
16070         private void updateBatteryChargingEnforceLevelLocked() {
16071             int lastChargingEnforceLevel = BATTERY_CHARGING_ENFORCE_LEVEL;
16072             final int level = Settings.Global.getInt(mResolver,
16073                     Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL,
16074                     -1);
16075 
16076             BATTERY_CHARGING_ENFORCE_LEVEL = level >= 0 ? level : mParser.getInt(
16077                     KEY_BATTERY_CHARGING_ENFORCE_LEVEL, DEFAULT_BATTERY_CHARGING_ENFORCE_LEVEL);
16078 
16079             if (BATTERY_CHARGING_ENFORCE_LEVEL <= mLastChargeStepLevel
16080                     && mLastChargeStepLevel < lastChargingEnforceLevel) {
16081                 setChargingLocked(true);
16082             }
16083         }
16084 
16085         private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
16086             KERNEL_UID_READERS_THROTTLE_TIME = newTimeMs;
16087             if (oldTimeMs != newTimeMs) {
16088                 mCpuUidUserSysTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
16089                 mCpuUidFreqTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
16090                 mCpuUidActiveTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
16091                 mCpuUidClusterTimeReader
16092                         .setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
16093             }
16094         }
16095 
16096         @GuardedBy("BatteryStatsImpl.this")
16097         private void updateUidRemoveDelay(long newTimeMs) {
16098             UID_REMOVE_DELAY_MS = newTimeMs;
16099             clearPendingRemovedUidsLocked();
16100         }
16101 
16102         public void dumpLocked(PrintWriter pw) {
16103             pw.print(KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME); pw.print("=");
16104             pw.println(TRACK_CPU_ACTIVE_CLUSTER_TIME);
16105             pw.print(KEY_KERNEL_UID_READERS_THROTTLE_TIME); pw.print("=");
16106             pw.println(KERNEL_UID_READERS_THROTTLE_TIME);
16107             pw.print(KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS); pw.print("=");
16108             pw.println(EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
16109             pw.print(KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS); pw.print("=");
16110             pw.println(BATTERY_LEVEL_COLLECTION_DELAY_MS);
16111             pw.print(KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS); pw.print("=");
16112             pw.println(PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
16113             pw.print(KEY_MAX_HISTORY_FILES); pw.print("=");
16114             pw.println(MAX_HISTORY_FILES);
16115             pw.print(KEY_MAX_HISTORY_BUFFER_KB); pw.print("=");
16116             pw.println(MAX_HISTORY_BUFFER/1024);
16117             pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("=");
16118             pw.println(BATTERY_CHARGED_DELAY_MS);
16119             pw.print(KEY_BATTERY_CHARGING_ENFORCE_LEVEL); pw.print("=");
16120             pw.println(BATTERY_CHARGING_ENFORCE_LEVEL);
16121             pw.print(KEY_PER_UID_MODEM_POWER_MODEL); pw.print("=");
16122             pw.println(getPerUidModemModelName(PER_UID_MODEM_MODEL));
16123             pw.print(KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION); pw.print("=");
16124             pw.println(PHONE_ON_EXTERNAL_STATS_COLLECTION);
16125             pw.print(KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS); pw.print("=");
16126             pw.println(RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS);
16127         }
16128     }
16129 
16130     public long getExternalStatsCollectionRateLimitMs() {
16131         synchronized (this) {
16132             return mConstants.EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
16133         }
16134     }
16135 
16136     @GuardedBy("this")
16137     public void dumpConstantsLocked(PrintWriter pw) {
16138         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
16139         iPw.println("BatteryStats constants:");
16140         iPw.increaseIndent();
16141         mConstants.dumpLocked(iPw);
16142         iPw.decreaseIndent();
16143     }
16144 
16145     @GuardedBy("this")
16146     public void dumpCpuStatsLocked(PrintWriter pw) {
16147         int size = mUidStats.size();
16148         pw.println("Per UID CPU user & system time in ms:");
16149         for (int i = 0; i < size; i++) {
16150             int u = mUidStats.keyAt(i);
16151             Uid uid = mUidStats.get(u);
16152             pw.print("  "); pw.print(u); pw.print(": ");
16153             pw.print(uid.getUserCpuTimeUs(STATS_SINCE_CHARGED) / 1000); pw.print(" ");
16154             pw.println(uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED) / 1000);
16155         }
16156 
16157         pw.println("Per UID CPU active time in ms:");
16158         for (int i = 0; i < size; i++) {
16159             int u = mUidStats.keyAt(i);
16160             Uid uid = mUidStats.get(u);
16161             if (uid.getCpuActiveTime() > 0) {
16162                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(uid.getCpuActiveTime());
16163             }
16164         }
16165         pw.println("Per UID CPU cluster time in ms:");
16166         for (int i = 0; i < size; i++) {
16167             int u = mUidStats.keyAt(i);
16168             long[] times = mUidStats.get(u).getCpuClusterTimes();
16169             if (times != null) {
16170                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
16171             }
16172         }
16173         pw.println("Per UID CPU frequency time in ms:");
16174         for (int i = 0; i < size; i++) {
16175             int u = mUidStats.keyAt(i);
16176             long[] times = mUidStats.get(u).getCpuFreqTimes(STATS_SINCE_CHARGED);
16177             if (times != null) {
16178                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
16179             }
16180         }
16181 
16182         if (!Flags.disableSystemServicePowerAttr()) {
16183             updateSystemServiceCallStats();
16184             if (mBinderThreadCpuTimesUs != null) {
16185                 pw.println("Per UID System server binder time in ms:");
16186                 long[] systemServiceTimeAtCpuSpeeds = getSystemServiceTimeAtCpuSpeeds();
16187                 for (int i = 0; i < size; i++) {
16188                     int u = mUidStats.keyAt(i);
16189                     Uid uid = mUidStats.get(u);
16190                     double proportionalSystemServiceUsage = uid.getProportionalSystemServiceUsage();
16191                     long timeUs = 0;
16192                     for (int j = systemServiceTimeAtCpuSpeeds.length - 1; j >= 0; j--) {
16193                         timeUs += systemServiceTimeAtCpuSpeeds[j] * proportionalSystemServiceUsage;
16194                     }
16195 
16196                     pw.print("  ");
16197                     pw.print(u);
16198                     pw.print(": ");
16199                     pw.println(timeUs / 1000);
16200                 }
16201             }
16202         }
16203     }
16204 
16205     /**
16206      * Dump EnergyConsumer stats
16207      */
16208     @GuardedBy("this")
16209     public void dumpEnergyConsumerStatsLocked(PrintWriter pw) {
16210         pw.printf("On-battery energy consumer stats (microcoulombs) \n");
16211         if (mGlobalEnergyConsumerStats == null) {
16212             pw.printf("    Not supported on this device.\n");
16213             return;
16214         }
16215 
16216         dumpEnergyConsumerStatsLocked(pw, "global usage", mGlobalEnergyConsumerStats);
16217 
16218         int size = mUidStats.size();
16219         for (int i = 0; i < size; i++) {
16220             final int u = mUidStats.keyAt(i);
16221             final Uid uid = mUidStats.get(u);
16222             final String name = "uid " + uid.mUid;
16223             dumpEnergyConsumerStatsLocked(pw, name, uid.mUidEnergyConsumerStats);
16224         }
16225     }
16226 
16227     /** Dump EnergyConsumer stats for the given uid */
16228     @GuardedBy("this")
16229     private void dumpEnergyConsumerStatsLocked(PrintWriter pw, String name,
16230             EnergyConsumerStats stats) {
16231         if (stats == null) return;
16232         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
16233         iPw.increaseIndent();
16234         iPw.printf("%s:\n", name);
16235         iPw.increaseIndent();
16236         stats.dump(iPw);
16237         iPw.decreaseIndent();
16238     }
16239 
16240     /**
16241      * Dump Power Profile
16242      */
16243     @GuardedBy("this")
16244     public void dumpPowerProfileLocked(PrintWriter pw) {
16245         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
16246         iPw.printf("Power Profile: \n");
16247         iPw.increaseIndent();
16248         mPowerProfile.dump(iPw);
16249         iPw.decreaseIndent();
16250     }
16251 
16252     /**
16253      * Schedules an immediate (but asynchronous) collection of PowerStats samples.
16254      * Callers will need to wait for the collection to complete on the handler thread.
16255      */
16256     public void schedulePowerStatsSampleCollection() {
16257         mCpuPowerStatsCollector.forceSchedule();
16258         mMobileRadioPowerStatsCollector.forceSchedule();
16259         mWifiPowerStatsCollector.forceSchedule();
16260         mBluetoothPowerStatsCollector.forceSchedule();
16261     }
16262 
16263     /**
16264      * Schedules an immediate collection of PowerStats samples and awaits the result.
16265      */
16266     public void collectPowerStatsSamples() {
16267         schedulePowerStatsSampleCollection();
16268         ConditionVariable done = new ConditionVariable();
16269         mHandler.post(done::open);
16270         done.block();
16271     }
16272 
16273     /**
16274      * Grabs one sample of PowerStats and prints it.
16275      */
16276     public void dumpStatsSample(PrintWriter pw) {
16277         mCpuPowerStatsCollector.collectAndDump(pw);
16278         mMobileRadioPowerStatsCollector.collectAndDump(pw);
16279         mWifiPowerStatsCollector.collectAndDump(pw);
16280         mBluetoothPowerStatsCollector.collectAndDump(pw);
16281     }
16282 
16283     private final Runnable mWriteAsyncRunnable = () -> {
16284         synchronized (BatteryStatsImpl.this) {
16285             writeSyncLocked();
16286         }
16287     };
16288 
16289     @GuardedBy("this")
16290     public void writeAsyncLocked() {
16291         BackgroundThread.getHandler().removeCallbacks(mWriteAsyncRunnable);
16292         BackgroundThread.getHandler().post(mWriteAsyncRunnable);
16293     }
16294 
16295     @GuardedBy("this")
16296     public void writeSyncLocked() {
16297         BackgroundThread.getHandler().removeCallbacks(mWriteAsyncRunnable);
16298         writeStatsLocked();
16299         writeHistoryLocked();
16300     }
16301 
16302     @GuardedBy("this")
16303     private void writeStatsLocked() {
16304         if (mStatsFile == null) {
16305             Slog.w(TAG,
16306                     "writeStatsLocked: no file associated with this instance");
16307             return;
16308         }
16309 
16310         if (mShuttingDown) {
16311             return;
16312         }
16313 
16314         final Parcel p = Parcel.obtain();
16315         try {
16316             final long start = SystemClock.uptimeMillis();
16317             writeSummaryToParcel(p, false/*history is in separate file*/);
16318             if (DEBUG) {
16319                 Slog.d(TAG, "writeSummaryToParcel duration ms:"
16320                         + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
16321             }
16322             mLastWriteTimeMs = mClock.elapsedRealtime();
16323             writeParcelToFileLocked(p, mStatsFile);
16324         } finally {
16325             p.recycle();
16326         }
16327     }
16328 
16329     private void writeHistoryLocked() {
16330         if (mShuttingDown) {
16331             return;
16332         }
16333 
16334         mHistory.writeHistory();
16335     }
16336 
16337     private final ReentrantLock mWriteLock = new ReentrantLock();
16338     private void writeParcelToFileLocked(Parcel p, AtomicFile file) {
16339         mWriteLock.lock();
16340         FileOutputStream fos = null;
16341         try {
16342             final long startTimeMs = SystemClock.uptimeMillis();
16343             fos = file.startWrite();
16344             fos.write(p.marshall());
16345             fos.flush();
16346             file.finishWrite(fos);
16347             if (DEBUG) {
16348                 Slog.d(TAG, "commitPendingDataToDisk file:" + file.getBaseFile().getPath()
16349                         + " duration ms:" + (SystemClock.uptimeMillis() - startTimeMs)
16350                         + " bytes:" + p.dataSize());
16351             }
16352             mFrameworkStatsLogger.writeCommitSysConfigFile(
16353                     "batterystats", SystemClock.uptimeMillis() - startTimeMs);
16354         } catch (IOException e) {
16355             Slog.w(TAG, "Error writing battery statistics", e);
16356             file.failWrite(fos);
16357         } finally {
16358             mWriteLock.unlock();
16359         }
16360     }
16361 
16362     @GuardedBy("this")
16363     public void readLocked() {
16364         if (mDailyFile != null) {
16365             readDailyStatsLocked();
16366         }
16367 
16368         if (mStatsFile == null) {
16369             Slog.w(TAG, "readLocked: no file associated with this instance");
16370             return;
16371         }
16372 
16373         mUidStats.clear();
16374 
16375         Parcel stats = Parcel.obtain();
16376         try {
16377             final long start = SystemClock.uptimeMillis();
16378             if (mStatsFile.exists()) {
16379                 byte[] raw = mStatsFile.readFully();
16380                 stats.unmarshall(raw, 0, raw.length);
16381                 stats.setDataPosition(0);
16382                 readSummaryFromParcel(stats);
16383                 if (DEBUG) {
16384                     Slog.d(TAG, "readLocked stats file:" + mStatsFile.getBaseFile().getPath()
16385                             + " bytes:" + raw.length + " took ms:" + (SystemClock.uptimeMillis()
16386                             - start));
16387                 }
16388             }
16389         } catch (Exception e) {
16390             Slog.e(TAG, "Error reading battery statistics", e);
16391             resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
16392                     RESET_REASON_CORRUPT_FILE);
16393         } finally {
16394             stats.recycle();
16395         }
16396 
16397         if (!mHistory.readSummary()) {
16398             resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
16399                     RESET_REASON_CORRUPT_FILE);
16400         }
16401 
16402         mEndPlatformVersion = Build.ID;
16403 
16404         mMonotonicEndTime = MonotonicClock.UNDEFINED;
16405         mHistory.continueRecordingHistory();
16406 
16407         recordDailyStatsIfNeededLocked(false, mClock.currentTimeMillis());
16408     }
16409 
16410     @GuardedBy("this")
16411     public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
16412         final int version = in.readInt();
16413 
16414         if (version != VERSION) {
16415             Slog.w("BatteryStats", "readFromParcel: version got " + version
16416                 + ", expected " + VERSION + "; erasing old stats");
16417             return;
16418         }
16419 
16420         mHistory.readSummaryFromParcel(in);
16421 
16422         mStartCount = in.readInt();
16423         mUptimeUs = in.readLong();
16424         mRealtimeUs = in.readLong();
16425         mStartClockTimeMs = in.readLong();
16426         mMonotonicStartTime = in.readLong();
16427         mMonotonicEndTime = in.readLong();
16428         mStartPlatformVersion = in.readString();
16429         mEndPlatformVersion = in.readString();
16430         mOnBatteryTimeBase.readSummaryFromParcel(in);
16431         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
16432         mDischargeUnplugLevel = in.readInt();
16433         mDischargePlugLevel = in.readInt();
16434         mDischargeCurrentLevel = in.readInt();
16435         mBatteryLevel = in.readInt();
16436         mEstimatedBatteryCapacityMah = in.readInt();
16437         mLastLearnedBatteryCapacityUah = in.readInt();
16438         mMinLearnedBatteryCapacityUah = in.readInt();
16439         mMaxLearnedBatteryCapacityUah = in.readInt();
16440         mLowDischargeAmountSinceCharge = in.readInt();
16441         mHighDischargeAmountSinceCharge = in.readInt();
16442         mDischargeAmountScreenOnSinceCharge = in.readInt();
16443         mDischargeAmountScreenOffSinceCharge = in.readInt();
16444         mDischargeAmountScreenDozeSinceCharge = in.readInt();
16445         mDischargeStepTracker.readFromParcel(in);
16446         mChargeStepTracker.readFromParcel(in);
16447         mDailyDischargeStepTracker.readFromParcel(in);
16448         mDailyChargeStepTracker.readFromParcel(in);
16449         mDischargeCounter.readSummaryFromParcelLocked(in);
16450         mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
16451         mDischargeScreenDozeCounter.readSummaryFromParcelLocked(in);
16452         mDischargeLightDozeCounter.readSummaryFromParcelLocked(in);
16453         mDischargeDeepDozeCounter.readSummaryFromParcelLocked(in);
16454         int NPKG = in.readInt();
16455         if (NPKG > 0) {
16456             mDailyPackageChanges = new ArrayList<>(NPKG);
16457             while (NPKG > 0) {
16458                 NPKG--;
16459                 PackageChange pc = new PackageChange();
16460                 pc.mPackageName = in.readString();
16461                 pc.mUpdate = in.readInt() != 0;
16462                 pc.mVersionCode = in.readLong();
16463                 mDailyPackageChanges.add(pc);
16464             }
16465         } else {
16466             mDailyPackageChanges = null;
16467         }
16468         mDailyStartTimeMs = in.readLong();
16469         mNextMinDailyDeadlineMs = in.readLong();
16470         mNextMaxDailyDeadlineMs = in.readLong();
16471         mBatteryTimeToFullSeconds = in.readLong();
16472 
16473         final EnergyConsumerStats.Config config = EnergyConsumerStats.Config.createFromParcel(in);
16474         final EnergyConsumerStats energyConsumerStats =
16475                 EnergyConsumerStats.createAndReadSummaryFromParcel(mEnergyConsumerStatsConfig, in);
16476         if (config != null && Arrays.equals(config.getStateNames(),
16477                 getBatteryConsumerProcessStateNames())) {
16478             /**
16479              * WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled
16480              *          later when {@link #initEnergyConsumerStatsLocked} is called.
16481              */
16482             mEnergyConsumerStatsConfig = config;
16483             mGlobalEnergyConsumerStats = energyConsumerStats;
16484         }
16485 
16486         mStartCount++;
16487 
16488         mScreenState = Display.STATE_UNKNOWN;
16489         mScreenOnTimer.readSummaryFromParcelLocked(in);
16490         mScreenDozeTimer.readSummaryFromParcelLocked(in);
16491         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
16492             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
16493         }
16494         final int numDisplays = in.readInt();
16495         for (int i = 0; i < numDisplays; i++) {
16496             mPerDisplayBatteryStats[i].readSummaryFromParcel(in);
16497         }
16498         mInteractive = false;
16499         mInteractiveTimer.readSummaryFromParcelLocked(in);
16500         mPhoneOn = false;
16501         mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
16502         mLongestLightIdleTimeMs = in.readLong();
16503         mLongestFullIdleTimeMs = in.readLong();
16504         mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
16505         mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
16506         mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
16507         mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
16508         mPhoneOnTimer.readSummaryFromParcelLocked(in);
16509         for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
16510             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
16511         }
16512         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
16513         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
16514             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
16515         }
16516         mNrNsaTimer.readSummaryFromParcelLocked(in);
16517         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
16518             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
16519             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
16520         }
16521 
16522         final int numRat = in.readInt();
16523         for (int i = 0; i < numRat; i++) {
16524             if (in.readInt() == 0) continue;
16525             getRatBatteryStatsLocked(i).readSummaryFromParcel(in);
16526         }
16527 
16528         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
16529         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
16530         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
16531         mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
16532         mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
16533         mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
16534         mWifiMulticastWakelockTimer.readSummaryFromParcelLocked(in);
16535         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
16536         mWifiOn = false;
16537         mWifiOnTimer.readSummaryFromParcelLocked(in);
16538         mGlobalWifiRunning = false;
16539         mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
16540         for (int i=0; i<NUM_WIFI_STATES; i++) {
16541             mWifiStateTimer[i].readSummaryFromParcelLocked(in);
16542         }
16543         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
16544             mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
16545         }
16546         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
16547             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
16548         }
16549         mWifiActiveTimer.readSummaryFromParcelLocked(in);
16550         mWifiActivity.readSummaryFromParcel(in);
16551         for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
16552             mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
16553         }
16554         mBluetoothActivity.readSummaryFromParcel(in);
16555         mModemActivity.readSummaryFromParcel(in);
16556         mHasWifiReporting = in.readInt() != 0;
16557         mHasBluetoothReporting = in.readInt() != 0;
16558         mHasModemReporting = in.readInt() != 0;
16559 
16560         mNumConnectivityChange = in.readInt();
16561         mFlashlightOnNesting = 0;
16562         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
16563         mCameraOnNesting = 0;
16564         mCameraOnTimer.readSummaryFromParcelLocked(in);
16565         mBluetoothScanNesting = 0;
16566         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
16567 
16568         int NRPMS = in.readInt();
16569         if (NRPMS > 10000) {
16570             throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS);
16571         }
16572         for (int irpm = 0; irpm < NRPMS; irpm++) {
16573             if (in.readInt() != 0) {
16574                 String rpmName = in.readString();
16575                 getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
16576             }
16577         }
16578         int NSORPMS = in.readInt();
16579         if (NSORPMS > 10000) {
16580             throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS);
16581         }
16582         for (int irpm = 0; irpm < NSORPMS; irpm++) {
16583             if (in.readInt() != 0) {
16584                 String rpmName = in.readString();
16585                 getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
16586             }
16587         }
16588         int NKW = in.readInt();
16589         if (NKW > 10000) {
16590             throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
16591         }
16592         for (int ikw = 0; ikw < NKW; ikw++) {
16593             if (in.readInt() != 0) {
16594                 String kwltName = in.readString();
16595                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
16596             }
16597         }
16598 
16599         int NWR = in.readInt();
16600         if (NWR > 10000) {
16601             throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
16602         }
16603         for (int iwr = 0; iwr < NWR; iwr++) {
16604             if (in.readInt() != 0) {
16605                 String reasonName = in.readString();
16606                 getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
16607             }
16608         }
16609 
16610         int NMS = in.readInt();
16611         for (int ims = 0; ims < NMS; ims++) {
16612             if (in.readInt() != 0) {
16613                 long kmstName = in.readLong();
16614                 getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
16615             }
16616         }
16617 
16618         final int NU = in.readInt();
16619         if (NU > 10000) {
16620             throw new ParcelFormatException("File corrupt: too many uids " + NU);
16621         }
16622         final long elapsedRealtimeMs = mClock.elapsedRealtime();
16623         final long uptimeMs = mClock.uptimeMillis();
16624         for (int iu = 0; iu < NU; iu++) {
16625             int uid = in.readInt();
16626             Uid u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
16627             mUidStats.put(uid, u);
16628 
16629             u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
16630             u.mOnBatteryScreenOffBackgroundTimeBase.readSummaryFromParcel(in);
16631 
16632             u.mWifiRunning = false;
16633             if (in.readInt() != 0) {
16634                 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
16635             }
16636             u.mFullWifiLockOut = false;
16637             if (in.readInt() != 0) {
16638                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
16639             }
16640             u.mWifiScanStarted = false;
16641             if (in.readInt() != 0) {
16642                 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
16643             }
16644             u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
16645             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
16646                 if (in.readInt() != 0) {
16647                     u.makeWifiBatchedScanBin(i, null);
16648                     u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
16649                 }
16650             }
16651             u.mWifiMulticastWakelockCount = 0;
16652             if (in.readInt() != 0) {
16653                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
16654             }
16655             if (in.readInt() != 0) {
16656                 u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
16657             }
16658             if (in.readInt() != 0) {
16659                 u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
16660             }
16661             if (in.readInt() != 0) {
16662                 u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
16663             }
16664             if (in.readInt() != 0) {
16665                 u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
16666             }
16667             if (in.readInt() != 0) {
16668                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
16669             }
16670             if (in.readInt() != 0) {
16671                 u.createForegroundServiceTimerLocked().readSummaryFromParcelLocked(in);
16672             }
16673             if (in.readInt() != 0) {
16674                 u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
16675             }
16676             if (in.readInt() != 0) {
16677                 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
16678             }
16679             if (in.readInt() != 0) {
16680                 u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in);
16681             }
16682             if (in.readInt() != 0) {
16683                 u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
16684             }
16685             if (in.readInt() != 0) {
16686                 u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in);
16687             }
16688             u.mProcessState = Uid.PROCESS_STATE_NONEXISTENT;
16689             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
16690                 if (in.readInt() != 0) {
16691                     u.makeProcessState(i, null);
16692                     u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
16693                 }
16694             }
16695             if (in.readInt() != 0) {
16696                 u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
16697             }
16698 
16699             if (in.readInt() != 0) {
16700                 if (u.mUserActivityCounters == null) {
16701                     u.initUserActivityLocked();
16702                 }
16703                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
16704                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
16705                 }
16706             }
16707 
16708             if (in.readInt() != 0) {
16709                 u.ensureNetworkActivityLocked();
16710                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
16711                     u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
16712                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
16713                 }
16714                 if (in.readBoolean()) {
16715                     u.mMobileRadioActiveTime = TimeMultiStateCounter.readFromParcel(in,
16716                             mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
16717                             elapsedRealtimeMs);
16718                 }
16719                 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
16720             }
16721 
16722             u.mUserCpuTime.readSummaryFromParcelLocked(in);
16723             u.mSystemCpuTime.readSummaryFromParcelLocked(in);
16724 
16725             if (in.readInt() != 0) {
16726                 final int numClusters = in.readInt();
16727                 int[] policies =
16728                         mCpuScalingPolicies != null ? mCpuScalingPolicies.getPolicies() : null;
16729                 if (policies != null && policies.length != numClusters) {
16730                     throw new ParcelFormatException("Incompatible cpu cluster arrangement");
16731                 }
16732                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
16733                 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
16734                 for (int cluster = 0; cluster < numClusters; cluster++) {
16735                     if (in.readInt() != 0) {
16736                         final int NSB = in.readInt();
16737                         if (policies != null
16738                                 && mCpuScalingPolicies.getFrequencies(policies[cluster]).length
16739                                 != NSB) {
16740                             throw new ParcelFormatException("File corrupt: too many speed bins " +
16741                                     NSB);
16742                         }
16743 
16744                         u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[NSB];
16745                         for (int speed = 0; speed < NSB; speed++) {
16746                             if (in.readInt() != 0) {
16747                                 u.mCpuClusterSpeedTimesUs[cluster][speed] = new LongSamplingCounter(
16748                                         mOnBatteryTimeBase);
16749                                 u.mCpuClusterSpeedTimesUs[cluster][speed].readSummaryFromParcelLocked(in);
16750                             }
16751                         }
16752                     } else {
16753                         u.mCpuClusterSpeedTimesUs[cluster] = null;
16754                     }
16755                 }
16756             } else {
16757                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
16758                 u.mCpuClusterSpeedTimesUs = null;
16759             }
16760 
16761             detachIfNotNull(u.mCpuFreqTimeMs);
16762             u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
16763                     in, mOnBatteryTimeBase);
16764             detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
16765             u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
16766                     in, mOnBatteryScreenOffTimeBase);
16767 
16768             int stateCount = in.readInt();
16769             if (stateCount != 0) {
16770                 u.mCpuActiveTimeMs = TimeMultiStateCounter.readFromParcel(in,
16771                         mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
16772                         mClock.elapsedRealtime());
16773             }
16774             u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
16775 
16776             detachIfNotNull(u.mProcStateTimeMs);
16777             u.mProcStateTimeMs = null;
16778 
16779             stateCount = in.readInt();
16780             if (stateCount != 0) {
16781                 detachIfNotNull(u.mProcStateTimeMs);
16782                 u.mProcStateTimeMs = TimeInFreqMultiStateCounter.readFromParcel(in,
16783                         mOnBatteryTimeBase, PROC_STATE_TIME_COUNTER_STATE_COUNT,
16784                         mCpuScalingPolicies.getScalingStepCount(), mClock.elapsedRealtime());
16785             }
16786 
16787             detachIfNotNull(u.mProcStateScreenOffTimeMs);
16788             u.mProcStateScreenOffTimeMs = null;
16789 
16790             stateCount = in.readInt();
16791             if (stateCount != 0) {
16792                 detachIfNotNull(u.mProcStateScreenOffTimeMs);
16793                 u.mProcStateScreenOffTimeMs = TimeInFreqMultiStateCounter.readFromParcel(in,
16794                         mOnBatteryScreenOffTimeBase, PROC_STATE_TIME_COUNTER_STATE_COUNT,
16795                         mCpuScalingPolicies.getScalingStepCount(), mClock.elapsedRealtime());
16796             }
16797 
16798             if (in.readInt() != 0) {
16799                 detachIfNotNull(u.mMobileRadioApWakeupCount);
16800                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
16801                 u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
16802             } else {
16803                 detachIfNotNull(u.mMobileRadioApWakeupCount);
16804                 u.mMobileRadioApWakeupCount = null;
16805             }
16806 
16807             if (in.readInt() != 0) {
16808                 detachIfNotNull(u.mWifiRadioApWakeupCount);
16809                 u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
16810                 u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
16811             } else {
16812                 detachIfNotNull(u.mWifiRadioApWakeupCount);
16813                 u.mWifiRadioApWakeupCount = null;
16814             }
16815 
16816             u.mUidEnergyConsumerStats = EnergyConsumerStats.createAndReadSummaryFromParcel(
16817                     mEnergyConsumerStatsConfig, in);
16818 
16819             int NW = in.readInt();
16820             if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
16821                 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
16822             }
16823             for (int iw = 0; iw < NW; iw++) {
16824                 String wlName = in.readString();
16825                 u.readWakeSummaryFromParcelLocked(wlName, in);
16826             }
16827 
16828             int NS = in.readInt();
16829             if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
16830                 throw new ParcelFormatException("File corrupt: too many syncs " + NS);
16831             }
16832             for (int is = 0; is < NS; is++) {
16833                 String name = in.readString();
16834                 u.readSyncSummaryFromParcelLocked(name, in);
16835             }
16836 
16837             int NJ = in.readInt();
16838             if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
16839                 throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
16840             }
16841             for (int ij = 0; ij < NJ; ij++) {
16842                 String name = in.readString();
16843                 u.readJobSummaryFromParcelLocked(name, in);
16844             }
16845 
16846             u.readJobCompletionsFromParcelLocked(in);
16847 
16848             u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in);
16849             u.mJobsDeferredCount.readSummaryFromParcelLocked(in);
16850             u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in);
16851             detachIfNotNull(u.mJobsFreshnessBuckets);
16852             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
16853                 if (in.readInt() != 0) {
16854                     u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase);
16855                     u.mJobsFreshnessBuckets[i].readSummaryFromParcelLocked(in);
16856                 }
16857             }
16858 
16859             int NP = in.readInt();
16860             if (NP > 1000) {
16861                 throw new ParcelFormatException("File corrupt: too many sensors " + NP);
16862             }
16863             for (int is = 0; is < NP; is++) {
16864                 int seNumber = in.readInt();
16865                 if (in.readInt() != 0) {
16866                     u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
16867                 }
16868             }
16869 
16870             NP = in.readInt();
16871             if (NP > 10000) {
16872                 throw new ParcelFormatException("File corrupt: too many processes " + NP);
16873             }
16874             for (int ip = 0; ip < NP; ip++) {
16875                 String procName = in.readString();
16876                 Uid.Proc p = u.getProcessStatsLocked(procName);
16877                 p.mUserTimeMs = in.readLong();
16878                 p.mSystemTimeMs = in.readLong();
16879                 p.mForegroundTimeMs = in.readLong();
16880                 p.mStarts = in.readInt();
16881                 p.mNumCrashes = in.readInt();
16882                 p.mNumAnrs = in.readInt();
16883                 p.readExcessivePowerFromParcelLocked(in);
16884             }
16885 
16886             NP = in.readInt();
16887             if (NP > 10000) {
16888                 throw new ParcelFormatException("File corrupt: too many packages " + NP);
16889             }
16890             for (int ip = 0; ip < NP; ip++) {
16891                 String pkgName = in.readString();
16892                 detachIfNotNull(u.mPackageStats.get(pkgName));
16893                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
16894                 final int NWA = in.readInt();
16895                 if (NWA > 10000) {
16896                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
16897                 }
16898                 p.mWakeupAlarms.clear();
16899                 for (int iwa = 0; iwa < NWA; iwa++) {
16900                     String tag = in.readString();
16901                     Counter c = new Counter(mOnBatteryScreenOffTimeBase);
16902                     c.readSummaryFromParcelLocked(in);
16903                     p.mWakeupAlarms.put(tag, c);
16904                 }
16905                 NS = in.readInt();
16906                 if (NS > 10000) {
16907                     throw new ParcelFormatException("File corrupt: too many services " + NS);
16908                 }
16909                 for (int is = 0; is < NS; is++) {
16910                     String servName = in.readString();
16911                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
16912                     s.mStartTimeMs = in.readLong();
16913                     s.mStarts = in.readInt();
16914                     s.mLaunches = in.readInt();
16915                 }
16916             }
16917         }
16918 
16919         if (!Flags.disableSystemServicePowerAttr()) {
16920             mBinderThreadCpuTimesUs =
16921                     LongSamplingCounterArray.readSummaryFromParcelLocked(in, mOnBatteryTimeBase);
16922         }
16923     }
16924 
16925     /**
16926      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
16927      * disk.  This format does not allow a lossless round-trip.
16928      *
16929      * @param out the Parcel to be written to.
16930      */
16931     @GuardedBy("this")
16932     public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
16933         pullPendingStateUpdatesLocked();
16934 
16935         // Pull the clock time.  This may update the time and make a new history entry
16936         // if we had originally pulled a time before the RTC was set.
16937         getStartClockTime();
16938 
16939         final long nowUptime = mClock.uptimeMillis() * 1000;
16940         final long nowRealtime = mClock.elapsedRealtime() * 1000;
16941 
16942         out.writeInt(VERSION);
16943 
16944         mHistory.writeSummaryToParcel(out, inclHistory);
16945 
16946         out.writeInt(mStartCount);
16947         out.writeLong(computeUptime(nowUptime, STATS_SINCE_CHARGED));
16948         out.writeLong(computeRealtime(nowRealtime, STATS_SINCE_CHARGED));
16949         out.writeLong(mStartClockTimeMs);
16950         out.writeLong(mMonotonicStartTime);
16951         out.writeLong(mMonotonicClock.monotonicTime());
16952         out.writeString(mStartPlatformVersion);
16953         out.writeString(mEndPlatformVersion);
16954         mOnBatteryTimeBase.writeSummaryToParcel(out, nowUptime, nowRealtime);
16955         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, nowUptime, nowRealtime);
16956         out.writeInt(mDischargeUnplugLevel);
16957         out.writeInt(mDischargePlugLevel);
16958         out.writeInt(mDischargeCurrentLevel);
16959         out.writeInt(mBatteryLevel);
16960         out.writeInt(mEstimatedBatteryCapacityMah);
16961         out.writeInt(mLastLearnedBatteryCapacityUah);
16962         out.writeInt(mMinLearnedBatteryCapacityUah);
16963         out.writeInt(mMaxLearnedBatteryCapacityUah);
16964         out.writeInt(getLowDischargeAmountSinceCharge());
16965         out.writeInt(getHighDischargeAmountSinceCharge());
16966         out.writeInt(getDischargeAmountScreenOnSinceCharge());
16967         out.writeInt(getDischargeAmountScreenOffSinceCharge());
16968         out.writeInt(getDischargeAmountScreenDozeSinceCharge());
16969         mDischargeStepTracker.writeToParcel(out);
16970         mChargeStepTracker.writeToParcel(out);
16971         mDailyDischargeStepTracker.writeToParcel(out);
16972         mDailyChargeStepTracker.writeToParcel(out);
16973         mDischargeCounter.writeSummaryFromParcelLocked(out);
16974         mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
16975         mDischargeScreenDozeCounter.writeSummaryFromParcelLocked(out);
16976         mDischargeLightDozeCounter.writeSummaryFromParcelLocked(out);
16977         mDischargeDeepDozeCounter.writeSummaryFromParcelLocked(out);
16978         if (mDailyPackageChanges != null) {
16979             final int NPKG = mDailyPackageChanges.size();
16980             out.writeInt(NPKG);
16981             for (int i=0; i<NPKG; i++) {
16982                 PackageChange pc = mDailyPackageChanges.get(i);
16983                 out.writeString(pc.mPackageName);
16984                 out.writeInt(pc.mUpdate ? 1 : 0);
16985                 out.writeLong(pc.mVersionCode);
16986             }
16987         } else {
16988             out.writeInt(0);
16989         }
16990         out.writeLong(mDailyStartTimeMs);
16991         out.writeLong(mNextMinDailyDeadlineMs);
16992         out.writeLong(mNextMaxDailyDeadlineMs);
16993         out.writeLong(mBatteryTimeToFullSeconds);
16994 
16995         EnergyConsumerStats.Config.writeToParcel(mEnergyConsumerStatsConfig, out);
16996         EnergyConsumerStats.writeSummaryToParcel(mGlobalEnergyConsumerStats, out);
16997 
16998         mScreenOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16999         mScreenDozeTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17000         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
17001             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17002         }
17003         final int numDisplays = mPerDisplayBatteryStats.length;
17004         out.writeInt(numDisplays);
17005         for (int i = 0; i < numDisplays; i++) {
17006             mPerDisplayBatteryStats[i].writeSummaryToParcel(out, nowRealtime);
17007         }
17008         mInteractiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17009         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17010         out.writeLong(mLongestLightIdleTimeMs);
17011         out.writeLong(mLongestFullIdleTimeMs);
17012         mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17013         mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17014         mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17015         mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17016         mPhoneOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17017         for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
17018             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17019         }
17020         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17021         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
17022             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17023         }
17024         mNrNsaTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17025         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
17026             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
17027             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
17028         }
17029         final int numRat = mPerRatBatteryStats.length;
17030         out.writeInt(numRat);
17031         for (int i = 0; i < numRat; i++) {
17032             final RadioAccessTechnologyBatteryStats ratStat = mPerRatBatteryStats[i];
17033             if (ratStat == null) {
17034                 out.writeInt(0);
17035                 continue;
17036             }
17037             out.writeInt(1);
17038             ratStat.writeSummaryToParcel(out, nowRealtime);
17039         }
17040         mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17041         mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17042         mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
17043         mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
17044         mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
17045         mWifiMulticastWakelockTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17046         mWifiOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17047         mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17048         for (int i=0; i<NUM_WIFI_STATES; i++) {
17049             mWifiStateTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17050         }
17051         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
17052             mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17053         }
17054         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
17055             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17056         }
17057         mWifiActiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17058         mWifiActivity.writeSummaryToParcel(out);
17059         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
17060             mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17061         }
17062         mBluetoothActivity.writeSummaryToParcel(out);
17063         mModemActivity.writeSummaryToParcel(out);
17064         out.writeInt(mHasWifiReporting ? 1 : 0);
17065         out.writeInt(mHasBluetoothReporting ? 1 : 0);
17066         out.writeInt(mHasModemReporting ? 1 : 0);
17067 
17068         out.writeInt(mNumConnectivityChange);
17069         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17070         mCameraOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17071         mBluetoothScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17072 
17073         out.writeInt(mRpmStats.size());
17074         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
17075             Timer rpmt = ent.getValue();
17076             if (rpmt != null) {
17077                 out.writeInt(1);
17078                 out.writeString(ent.getKey());
17079                 rpmt.writeSummaryFromParcelLocked(out, nowRealtime);
17080             } else {
17081                 out.writeInt(0);
17082             }
17083         }
17084         out.writeInt(mScreenOffRpmStats.size());
17085         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
17086             Timer rpmt = ent.getValue();
17087             if (rpmt != null) {
17088                 out.writeInt(1);
17089                 out.writeString(ent.getKey());
17090                 rpmt.writeSummaryFromParcelLocked(out, nowRealtime);
17091             } else {
17092                 out.writeInt(0);
17093             }
17094         }
17095 
17096         out.writeInt(mKernelWakelockStats.size());
17097         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
17098             Timer kwlt = ent.getValue();
17099             if (kwlt != null) {
17100                 out.writeInt(1);
17101                 out.writeString(ent.getKey());
17102                 kwlt.writeSummaryFromParcelLocked(out, nowRealtime);
17103             } else {
17104                 out.writeInt(0);
17105             }
17106         }
17107 
17108         out.writeInt(mWakeupReasonStats.size());
17109         for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
17110             SamplingTimer timer = ent.getValue();
17111             if (timer != null) {
17112                 out.writeInt(1);
17113                 out.writeString(ent.getKey());
17114                 timer.writeSummaryFromParcelLocked(out, nowRealtime);
17115             } else {
17116                 out.writeInt(0);
17117             }
17118         }
17119 
17120         out.writeInt(mKernelMemoryStats.size());
17121         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
17122             Timer kmt = mKernelMemoryStats.valueAt(i);
17123             if (kmt != null) {
17124                 out.writeInt(1);
17125                 out.writeLong(mKernelMemoryStats.keyAt(i));
17126                 kmt.writeSummaryFromParcelLocked(out, nowRealtime);
17127             } else {
17128                 out.writeInt(0);
17129             }
17130         }
17131 
17132         final int NU = mUidStats.size();
17133         out.writeInt(NU);
17134         for (int iu = 0; iu < NU; iu++) {
17135             out.writeInt(mUidStats.keyAt(iu));
17136             Uid u = mUidStats.valueAt(iu);
17137 
17138             u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, nowUptime, nowRealtime);
17139             u.mOnBatteryScreenOffBackgroundTimeBase.writeSummaryToParcel(out, nowUptime,
17140                     nowRealtime);
17141 
17142             if (u.mWifiRunningTimer != null) {
17143                 out.writeInt(1);
17144                 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17145             } else {
17146                 out.writeInt(0);
17147             }
17148             if (u.mFullWifiLockTimer != null) {
17149                 out.writeInt(1);
17150                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17151             } else {
17152                 out.writeInt(0);
17153             }
17154             if (u.mWifiScanTimer != null) {
17155                 out.writeInt(1);
17156                 u.mWifiScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17157             } else {
17158                 out.writeInt(0);
17159             }
17160             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
17161                 if (u.mWifiBatchedScanTimer[i] != null) {
17162                     out.writeInt(1);
17163                     u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17164                 } else {
17165                     out.writeInt(0);
17166                 }
17167             }
17168             if (u.mWifiMulticastTimer != null) {
17169                 out.writeInt(1);
17170                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17171             } else {
17172                 out.writeInt(0);
17173             }
17174             if (u.mAudioTurnedOnTimer != null) {
17175                 out.writeInt(1);
17176                 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17177             } else {
17178                 out.writeInt(0);
17179             }
17180             if (u.mVideoTurnedOnTimer != null) {
17181                 out.writeInt(1);
17182                 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17183             } else {
17184                 out.writeInt(0);
17185             }
17186             if (u.mFlashlightTurnedOnTimer != null) {
17187                 out.writeInt(1);
17188                 u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17189             } else {
17190                 out.writeInt(0);
17191             }
17192             if (u.mCameraTurnedOnTimer != null) {
17193                 out.writeInt(1);
17194                 u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17195             } else {
17196                 out.writeInt(0);
17197             }
17198             if (u.mForegroundActivityTimer != null) {
17199                 out.writeInt(1);
17200                 u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17201             } else {
17202                 out.writeInt(0);
17203             }
17204             if (u.mForegroundServiceTimer != null) {
17205                 out.writeInt(1);
17206                 u.mForegroundServiceTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17207             } else {
17208                 out.writeInt(0);
17209             }
17210             if (u.mAggregatedPartialWakelockTimer != null) {
17211                 out.writeInt(1);
17212                 u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17213             } else {
17214                 out.writeInt(0);
17215             }
17216             if (u.mBluetoothScanTimer != null) {
17217                 out.writeInt(1);
17218                 u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17219             } else {
17220                 out.writeInt(0);
17221             }
17222             if (u.mBluetoothUnoptimizedScanTimer != null) {
17223                 out.writeInt(1);
17224                 u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17225             } else {
17226                 out.writeInt(0);
17227             }
17228             if (u.mBluetoothScanResultCounter != null) {
17229                 out.writeInt(1);
17230                 u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
17231             } else {
17232                 out.writeInt(0);
17233             }
17234             if (u.mBluetoothScanResultBgCounter != null) {
17235                 out.writeInt(1);
17236                 u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out);
17237             } else {
17238                 out.writeInt(0);
17239             }
17240             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
17241                 if (u.mProcessStateTimer[i] != null) {
17242                     out.writeInt(1);
17243                     u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17244                 } else {
17245                     out.writeInt(0);
17246                 }
17247             }
17248             if (u.mVibratorOnTimer != null) {
17249                 out.writeInt(1);
17250                 u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17251             } else {
17252                 out.writeInt(0);
17253             }
17254 
17255             if (u.mUserActivityCounters == null) {
17256                 out.writeInt(0);
17257             } else {
17258                 out.writeInt(1);
17259                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
17260                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
17261                 }
17262             }
17263 
17264             if (u.mNetworkByteActivityCounters == null) {
17265                 out.writeInt(0);
17266             } else {
17267                 out.writeInt(1);
17268                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
17269                     u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
17270                     u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
17271                 }
17272                 if (u.mMobileRadioActiveTime != null) {
17273                     out.writeBoolean(true);
17274                     u.mMobileRadioActiveTime.writeToParcel(out);
17275                 } else {
17276                     out.writeBoolean(false);
17277                 }
17278                 u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
17279             }
17280 
17281             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
17282             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
17283 
17284             if (u.mCpuClusterSpeedTimesUs != null) {
17285                 out.writeInt(1);
17286                 out.writeInt(u.mCpuClusterSpeedTimesUs.length);
17287                 for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeedTimesUs) {
17288                     if (cpuSpeeds != null) {
17289                         out.writeInt(1);
17290                         out.writeInt(cpuSpeeds.length);
17291                         for (LongSamplingCounter c : cpuSpeeds) {
17292                             if (c != null) {
17293                                 out.writeInt(1);
17294                                 c.writeSummaryFromParcelLocked(out);
17295                             } else {
17296                                 out.writeInt(0);
17297                             }
17298                         }
17299                     } else {
17300                         out.writeInt(0);
17301                     }
17302                 }
17303             } else {
17304                 out.writeInt(0);
17305             }
17306 
17307             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
17308             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
17309 
17310             if (u.mCpuActiveTimeMs != null) {
17311                 out.writeInt(u.mCpuActiveTimeMs.getStateCount());
17312                 u.mCpuActiveTimeMs.writeToParcel(out);
17313             } else {
17314                 out.writeInt(0);
17315             }
17316 
17317             u.mCpuClusterTimesMs.writeSummaryToParcelLocked(out);
17318 
17319             if (u.mProcStateTimeMs != null) {
17320                 out.writeInt(u.mProcStateTimeMs.getStateCount());
17321                 u.mProcStateTimeMs.writeToParcel(out);
17322             } else {
17323                 out.writeInt(0);
17324             }
17325 
17326             if (u.mProcStateScreenOffTimeMs != null) {
17327                 out.writeInt(u.mProcStateScreenOffTimeMs.getStateCount());
17328                 u.mProcStateScreenOffTimeMs.writeToParcel(out);
17329             } else {
17330                 out.writeInt(0);
17331             }
17332 
17333             if (u.mMobileRadioApWakeupCount != null) {
17334                 out.writeInt(1);
17335                 u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
17336             } else {
17337                 out.writeInt(0);
17338             }
17339 
17340             if (u.mWifiRadioApWakeupCount != null) {
17341                 out.writeInt(1);
17342                 u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
17343             } else {
17344                 out.writeInt(0);
17345             }
17346 
17347             EnergyConsumerStats.writeSummaryToParcel(u.mUidEnergyConsumerStats, out);
17348 
17349             final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
17350             int NW = wakeStats.size();
17351             out.writeInt(NW);
17352             for (int iw=0; iw<NW; iw++) {
17353                 out.writeString(wakeStats.keyAt(iw));
17354                 Uid.Wakelock wl = wakeStats.valueAt(iw);
17355                 if (wl.mTimerFull != null) {
17356                     out.writeInt(1);
17357                     wl.mTimerFull.writeSummaryFromParcelLocked(out, nowRealtime);
17358                 } else {
17359                     out.writeInt(0);
17360                 }
17361                 if (wl.mTimerPartial != null) {
17362                     out.writeInt(1);
17363                     wl.mTimerPartial.writeSummaryFromParcelLocked(out, nowRealtime);
17364                 } else {
17365                     out.writeInt(0);
17366                 }
17367                 if (wl.mTimerWindow != null) {
17368                     out.writeInt(1);
17369                     wl.mTimerWindow.writeSummaryFromParcelLocked(out, nowRealtime);
17370                 } else {
17371                     out.writeInt(0);
17372                 }
17373                 if (wl.mTimerDraw != null) {
17374                     out.writeInt(1);
17375                     wl.mTimerDraw.writeSummaryFromParcelLocked(out, nowRealtime);
17376                 } else {
17377                     out.writeInt(0);
17378                 }
17379             }
17380 
17381             final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
17382             int NS = syncStats.size();
17383             out.writeInt(NS);
17384             for (int is=0; is<NS; is++) {
17385                 out.writeString(syncStats.keyAt(is));
17386                 syncStats.valueAt(is).writeSummaryFromParcelLocked(out, nowRealtime);
17387             }
17388 
17389             final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
17390             int NJ = jobStats.size();
17391             out.writeInt(NJ);
17392             for (int ij=0; ij<NJ; ij++) {
17393                 out.writeString(jobStats.keyAt(ij));
17394                 jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, nowRealtime);
17395             }
17396 
17397             u.writeJobCompletionsToParcelLocked(out);
17398 
17399             u.mJobsDeferredEventCount.writeSummaryFromParcelLocked(out);
17400             u.mJobsDeferredCount.writeSummaryFromParcelLocked(out);
17401             u.mJobsFreshnessTimeMs.writeSummaryFromParcelLocked(out);
17402             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
17403                 if (u.mJobsFreshnessBuckets[i] != null) {
17404                     out.writeInt(1);
17405                     u.mJobsFreshnessBuckets[i].writeSummaryFromParcelLocked(out);
17406                 } else {
17407                     out.writeInt(0);
17408                 }
17409             }
17410 
17411             int NSE = u.mSensorStats.size();
17412             out.writeInt(NSE);
17413             for (int ise=0; ise<NSE; ise++) {
17414                 out.writeInt(u.mSensorStats.keyAt(ise));
17415                 Uid.Sensor se = u.mSensorStats.valueAt(ise);
17416                 if (se.mTimer != null) {
17417                     out.writeInt(1);
17418                     se.mTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17419                 } else {
17420                     out.writeInt(0);
17421                 }
17422             }
17423 
17424             int NP = u.mProcessStats.size();
17425             out.writeInt(NP);
17426             for (int ip=0; ip<NP; ip++) {
17427                 out.writeString(u.mProcessStats.keyAt(ip));
17428                 Uid.Proc ps = u.mProcessStats.valueAt(ip);
17429                 out.writeLong(ps.mUserTimeMs);
17430                 out.writeLong(ps.mSystemTimeMs);
17431                 out.writeLong(ps.mForegroundTimeMs);
17432                 out.writeInt(ps.mStarts);
17433                 out.writeInt(ps.mNumCrashes);
17434                 out.writeInt(ps.mNumAnrs);
17435                 ps.writeExcessivePowerToParcelLocked(out);
17436             }
17437 
17438             NP = u.mPackageStats.size();
17439             out.writeInt(NP);
17440             if (NP > 0) {
17441                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
17442                     : u.mPackageStats.entrySet()) {
17443                     out.writeString(ent.getKey());
17444                     Uid.Pkg ps = ent.getValue();
17445                     final int NWA = ps.mWakeupAlarms.size();
17446                     out.writeInt(NWA);
17447                     for (int iwa=0; iwa<NWA; iwa++) {
17448                         out.writeString(ps.mWakeupAlarms.keyAt(iwa));
17449                         ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
17450                     }
17451                     NS = ps.mServiceStats.size();
17452                     out.writeInt(NS);
17453                     for (int is=0; is<NS; is++) {
17454                         out.writeString(ps.mServiceStats.keyAt(is));
17455                         BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
17456                         long time = ss.getStartTimeToNowLocked(
17457                                 mOnBatteryTimeBase.getUptime(nowUptime) / 1000);
17458                         out.writeLong(time);
17459                         out.writeInt(ss.mStarts);
17460                         out.writeInt(ss.mLaunches);
17461                     }
17462                 }
17463             }
17464         }
17465 
17466         if (!Flags.disableSystemServicePowerAttr()) {
17467             LongSamplingCounterArray.writeSummaryToParcelLocked(out, mBinderThreadCpuTimesUs);
17468         }
17469     }
17470 
17471     @GuardedBy("this")
17472     public void prepareForDumpLocked() {
17473         // Need to retrieve current kernel wake lock stats before printing.
17474         pullPendingStateUpdatesLocked();
17475 
17476         // Pull the clock time.  This may update the time and make a new history entry
17477         // if we had originally pulled a time before the RTC was set.
17478         getStartClockTime();
17479 
17480         if (!Flags.disableSystemServicePowerAttr()) {
17481             updateSystemServiceCallStats();
17482         }
17483     }
17484 
17485     @GuardedBy("this")
17486     public void dump(Context context, PrintWriter pw, int flags, int reqUid, long histStart,
17487             BatteryStatsDumpHelper dumpHelper) {
17488         if (DEBUG) {
17489             pw.println("mOnBatteryTimeBase:");
17490             mOnBatteryTimeBase.dump(pw, "  ");
17491             pw.println("mOnBatteryScreenOffTimeBase:");
17492             mOnBatteryScreenOffTimeBase.dump(pw, "  ");
17493             Printer pr = new PrintWriterPrinter(pw);
17494             pr.println("*** Screen on timer:");
17495             mScreenOnTimer.logState(pr, "  ");
17496             pr.println("*** Screen doze timer:");
17497             mScreenDozeTimer.logState(pr, "  ");
17498             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
17499                 pr.println("*** Screen brightness #" + i + ":");
17500                 mScreenBrightnessTimer[i].logState(pr, "  ");
17501             }
17502             pr.println("*** Interactive timer:");
17503             mInteractiveTimer.logState(pr, "  ");
17504             pr.println("*** Power save mode timer:");
17505             mPowerSaveModeEnabledTimer.logState(pr, "  ");
17506             pr.println("*** Device idle mode light timer:");
17507             mDeviceIdleModeLightTimer.logState(pr, "  ");
17508             pr.println("*** Device idle mode full timer:");
17509             mDeviceIdleModeFullTimer.logState(pr, "  ");
17510             pr.println("*** Device light idling timer:");
17511             mDeviceLightIdlingTimer.logState(pr, "  ");
17512             pr.println("*** Device idling timer:");
17513             mDeviceIdlingTimer.logState(pr, "  ");
17514             pr.println("*** Phone timer:");
17515             mPhoneOnTimer.logState(pr, "  ");
17516             for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
17517                 pr.println("*** Phone signal strength #" + i + ":");
17518                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
17519             }
17520             pr.println("*** Signal scanning :");
17521             mPhoneSignalScanningTimer.logState(pr, "  ");
17522             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
17523                 pr.println("*** Data connection type #" + i + ":");
17524                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
17525             }
17526             pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
17527             pr.println("*** Mobile network active timer:");
17528             mMobileRadioActiveTimer.logState(pr, "  ");
17529             pr.println("*** Mobile network active adjusted timer:");
17530             mMobileRadioActiveAdjustedTime.logState(pr, "  ");
17531             pr.println("*** Wifi Multicast WakeLock Timer:");
17532             mWifiMulticastWakelockTimer.logState(pr, "  ");
17533             pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
17534             pr.println("*** Wifi timer:");
17535             mWifiOnTimer.logState(pr, "  ");
17536             pr.println("*** WifiRunning timer:");
17537             mGlobalWifiRunningTimer.logState(pr, "  ");
17538             for (int i=0; i<NUM_WIFI_STATES; i++) {
17539                 pr.println("*** Wifi state #" + i + ":");
17540                 mWifiStateTimer[i].logState(pr, "  ");
17541             }
17542             for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
17543                 pr.println("*** Wifi suppl state #" + i + ":");
17544                 mWifiSupplStateTimer[i].logState(pr, "  ");
17545             }
17546             for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
17547                 pr.println("*** Wifi signal strength #" + i + ":");
17548                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
17549             }
17550             for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
17551                 pr.println("*** GPS signal quality #" + i + ":");
17552                 mGpsSignalQualityTimer[i].logState(pr, "  ");
17553             }
17554             pr.println("*** Flashlight timer:");
17555             mFlashlightOnTimer.logState(pr, "  ");
17556             pr.println("*** Camera timer:");
17557             mCameraOnTimer.logState(pr, "  ");
17558         }
17559         super.dump(context, pw, flags, reqUid, histStart, dumpHelper);
17560 
17561         synchronized (this) {
17562             pw.print("Per process state tracking available: ");
17563             pw.println(trackPerProcStateCpuTimes());
17564             pw.print("Total cpu time reads: ");
17565             pw.println(mNumSingleUidCpuTimeReads);
17566             pw.print("Batching Duration (min): ");
17567             pw.println((mClock.uptimeMillis() - mCpuTimeReadsTrackingStartTimeMs) / (60 * 1000));
17568             pw.print("All UID cpu time reads since the later of device start or stats reset: ");
17569             pw.println(mNumAllUidCpuTimeReads);
17570             pw.print("UIDs removed since the later of device start or stats reset: ");
17571             pw.println(mNumUidsRemoved);
17572 
17573             mPowerStatsUidResolver.dump(pw);
17574 
17575             pw.println();
17576             dumpConstantsLocked(pw);
17577 
17578             pw.println();
17579             mCpuPowerStatsCollector.dumpCpuPowerBracketsLocked(pw);
17580 
17581             pw.println();
17582             dumpEnergyConsumerStatsLocked(pw);
17583         }
17584     }
17585 }
17586