• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006-2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.power.stats;
18 
19 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
20 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
21 import static android.os.BatteryStats.Uid.NUM_PROCESS_STATE;
22 import static android.os.BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS;
23 import static android.os.BatteryStatsManager.NUM_WIFI_STATES;
24 import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;
25 
26 import 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 CameraPowerStatsCollector mCameraPowerStatsCollector;
302     private final GnssPowerStatsCollector mGnssPowerStatsCollector;
303     private final SparseBooleanArray mPowerStatsCollectorEnabled = new SparseBooleanArray();
304     private final WifiPowerStatsCollector.WifiStatsRetriever mWifiStatsRetriever =
305             new WifiPowerStatsCollector.WifiStatsRetriever() {
306                 @Override
307                 public void retrieveWifiScanTimes(Callback callback) {
308                     synchronized (BatteryStatsImpl.this) {
309                         retrieveWifiScanTimesLocked(callback);
310                     }
311                 }
312 
313                 @Override
314                 public long getWifiActiveDuration() {
315                     synchronized (BatteryStatsImpl.this) {
316                         return getGlobalWifiRunningTime(mClock.elapsedRealtime() * 1000,
317                                 STATS_SINCE_CHARGED) / 1000;
318                     }
319                 }
320             };
321 
322     private class BluetoothStatsRetrieverImpl implements
323             BluetoothPowerStatsCollector.BluetoothStatsRetriever {
324         private final BluetoothManager mBluetoothManager;
325 
BluetoothStatsRetrieverImpl(BluetoothManager bluetoothManager)326         BluetoothStatsRetrieverImpl(BluetoothManager bluetoothManager) {
327             mBluetoothManager = bluetoothManager;
328         }
329 
330         @Override
retrieveBluetoothScanTimes(Callback callback)331         public void retrieveBluetoothScanTimes(Callback callback) {
332             synchronized (BatteryStatsImpl.this) {
333                 retrieveBluetoothScanTimesLocked(callback);
334             }
335         }
336 
337         @Override
requestControllerActivityEnergyInfo(Executor executor, BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback callback)338         public boolean requestControllerActivityEnergyInfo(Executor executor,
339                 BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback callback) {
340             if (mBluetoothManager == null) {
341                 return false;
342             }
343 
344             BluetoothAdapter adapter = mBluetoothManager.getAdapter();
345             if (adapter == null) {
346                 return false;
347             }
348 
349             adapter.requestControllerActivityEnergyInfo(executor, callback);
350             return true;
351         }
352     }
353 
getKernelMemoryStats()354     public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
355         return mKernelMemoryStats;
356     }
357 
358     private static final int[] SUPPORTED_PER_PROCESS_STATE_STANDARD_ENERGY_BUCKETS = {
359             EnergyConsumerStats.POWER_BUCKET_CPU,
360             EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO,
361             EnergyConsumerStats.POWER_BUCKET_WIFI,
362             EnergyConsumerStats.POWER_BUCKET_BLUETOOTH,
363     };
364 
365     // TimeInState counters need NUM_PROCESS_STATE states in order to accommodate
366     // Uid.PROCESS_STATE_NONEXISTENT, which is outside the range of legitimate proc states.
367     private static final int PROC_STATE_TIME_COUNTER_STATE_COUNT = NUM_PROCESS_STATE + 1;
368 
369     @GuardedBy("this")
370     public boolean mPerProcStateCpuTimesAvailable = true;
371 
372     @GuardedBy("this")
373     private long mNumSingleUidCpuTimeReads;
374     @GuardedBy("this")
375     private long mCpuTimeReadsTrackingStartTimeMs = SystemClock.uptimeMillis();
376     @GuardedBy("this")
377     private int mNumUidsRemoved;
378     @GuardedBy("this")
379     private int mNumAllUidCpuTimeReads;
380 
381     /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
382     private RpmStats mTmpRpmStats = null;
383     /** The soonest the RPM stats can be updated after it was last updated. */
384     private static final long RPM_STATS_UPDATE_FREQ_MS = 1000;
385     /** Last time that RPM stats were updated by updateRpmStatsLocked. */
386     private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
387 
388     /** Container for Rail Energy Data stats. */
389     private RailStats mTmpRailStats;
390 
391     /**
392      * Estimate UID modem power usage based on their estimated mobile radio active time.
393      */
394     public static final int PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME = 1;
395     /**
396      * Estimate UID modem power consumption by proportionally attributing estimated Rx and Tx
397      * power consumption individually.
398      * ModemActivityInfo must be available.
399      */
400     public static final int PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX = 2;
401 
402     @IntDef(flag = true, prefix = "PER_UID_MODEM_MODEL_", value = {
403             PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME,
404             PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX,
405     })
406     @Retention(RetentionPolicy.SOURCE)
407     public @interface PerUidModemPowerModel {
408     }
409 
410     /**
411      * Use a queue to delay removing UIDs from {@link KernelCpuUidUserSysTimeReader},
412      * {@link KernelCpuUidActiveTimeReader}, {@link KernelCpuUidClusterTimeReader},
413      * {@link KernelCpuUidFreqTimeReader} and from the Kernel.
414      *
415      * Isolated and invalid UID info must be removed to conserve memory. However, STATSD and
416      * Batterystats both need to access UID cpu time. To resolve this race condition, only
417      * Batterystats shall remove UIDs, and a delay {@link Constants#UID_REMOVE_DELAY_MS} is
418      * implemented so that STATSD can capture those UID times before they are deleted.
419      */
420     @GuardedBy("this")
421     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
422     protected Queue<UidToRemove> mPendingRemovedUids = new LinkedList<>();
423 
424     @NonNull
getHistory()425     public BatteryStatsHistory getHistory() {
426         return mHistory;
427     }
428 
429     @NonNull
copyHistory()430     BatteryStatsHistory copyHistory() {
431         return mHistory.copy();
432     }
433 
434     @VisibleForTesting
435     public final class UidToRemove {
436         private final int mStartUid;
437         private final int mEndUid;
438         private final long mUidRemovalTimestamp;
439 
440         /** Remove just one UID */
UidToRemove(int uid, long timestamp)441         public UidToRemove(int uid, long timestamp) {
442             this(uid, uid, timestamp);
443         }
444 
445         /** Remove a range of UIDs, startUid must be smaller than endUid. */
UidToRemove(int startUid, int endUid, long timestamp)446         public UidToRemove(int startUid, int endUid, long timestamp) {
447             mStartUid = startUid;
448             mEndUid = endUid;
449             mUidRemovalTimestamp = timestamp;
450         }
451 
getUidRemovalTimestamp()452         public long getUidRemovalTimestamp() {
453             return mUidRemovalTimestamp;
454         }
455 
456         @GuardedBy("BatteryStatsImpl.this")
removeLocked()457         void removeLocked() {
458             removeCpuStatsForUidRangeLocked(mStartUid, mEndUid);
459         }
460     }
461 
462     private boolean mSaveBatteryUsageStatsOnReset;
463     private BatteryUsageStatsProvider mBatteryUsageStatsProvider;
464     private PowerStatsStore mPowerStatsStore;
465 
466     public interface BatteryCallback {
batteryNeedsCpuUpdate()467         public void batteryNeedsCpuUpdate();
batteryPowerChanged(boolean onBattery)468         public void batteryPowerChanged(boolean onBattery);
batterySendBroadcast(Intent intent)469         public void batterySendBroadcast(Intent intent);
batteryStatsReset()470         public void batteryStatsReset();
471     }
472 
473     public interface PlatformIdleStateCallback {
fillLowPowerStats(RpmStats rpmStats)474         public void fillLowPowerStats(RpmStats rpmStats);
getSubsystemLowPowerStats()475         public String getSubsystemLowPowerStats();
476     }
477 
478     /** interface to update rail information for power monitor */
479     public interface EnergyStatsRetriever {
480         /** Function to fill the map for the rail data stats
481          * Used for power monitoring feature
482          * @param railStats
483          */
fillRailDataStats(RailStats railStats)484         void fillRailDataStats(RailStats railStats);
485     }
486 
487     public static abstract class UserInfoProvider {
488         private int[] userIds;
getUserIds()489         protected abstract @Nullable int[] getUserIds();
490         @VisibleForTesting
refreshUserIds()491         public final void refreshUserIds() {
492             userIds = getUserIds();
493         }
494         @VisibleForTesting
exists(int userId)495         public boolean exists(int userId) {
496             return userIds != null ? ArrayUtils.contains(userIds, userId) : true;
497         }
498     }
499 
500     /** Provide BatteryStatsImpl configuration choices */
501     public static class BatteryStatsConfig {
502         static final int RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG = 1 << 0;
503         static final int RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG = 1 << 1;
504 
505         private final int mFlags;
506         private final Long mDefaultPowerStatsThrottlePeriod;
507         private final Map<String, Long> mPowerStatsThrottlePeriods;
508 
509         @VisibleForTesting
BatteryStatsConfig()510         public BatteryStatsConfig() {
511             mFlags = 0;
512             mDefaultPowerStatsThrottlePeriod = 0L;
513             mPowerStatsThrottlePeriods = Map.of();
514         }
515 
BatteryStatsConfig(Builder builder)516         private BatteryStatsConfig(Builder builder) {
517             int flags = 0;
518             if (builder.mResetOnUnplugHighBatteryLevel) {
519                 flags |= RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG;
520             }
521             if (builder.mResetOnUnplugAfterSignificantCharge) {
522                 flags |= RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG;
523             }
524             mFlags = flags;
525             mDefaultPowerStatsThrottlePeriod = builder.mDefaultPowerStatsThrottlePeriod;
526             mPowerStatsThrottlePeriods = builder.mPowerStatsThrottlePeriods;
527         }
528 
529         /**
530          * Returns whether a BatteryStats reset should occur on unplug when the battery level is
531          * high.
532          */
shouldResetOnUnplugHighBatteryLevel()533         public boolean shouldResetOnUnplugHighBatteryLevel() {
534             return (mFlags & RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG)
535                     == RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG;
536         }
537 
538         /**
539          * Returns whether a BatteryStats reset should occur on unplug if the battery charge a
540          * significant amount since it has been plugged in.
541          */
shouldResetOnUnplugAfterSignificantCharge()542         public boolean shouldResetOnUnplugAfterSignificantCharge() {
543             return (mFlags & RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG)
544                     == RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG;
545         }
546 
547         /**
548          * Returns  the minimum amount of time (in millis) to wait between passes
549          * of power stats collection for the specified power component.
550          */
getPowerStatsThrottlePeriod(String powerComponentName)551         public long getPowerStatsThrottlePeriod(String powerComponentName) {
552             return mPowerStatsThrottlePeriods.getOrDefault(powerComponentName,
553                     mDefaultPowerStatsThrottlePeriod);
554         }
555 
556         /**
557          * Builder for BatteryStatsConfig
558          */
559         public static class Builder {
560             private boolean mResetOnUnplugHighBatteryLevel;
561             private boolean mResetOnUnplugAfterSignificantCharge;
562             public static final long DEFAULT_POWER_STATS_THROTTLE_PERIOD =
563                     TimeUnit.HOURS.toMillis(1);
564             public static final long DEFAULT_POWER_STATS_THROTTLE_PERIOD_CPU =
565                     TimeUnit.MINUTES.toMillis(1);
566             private long mDefaultPowerStatsThrottlePeriod = DEFAULT_POWER_STATS_THROTTLE_PERIOD;
567             private final Map<String, Long> mPowerStatsThrottlePeriods = new HashMap<>();
568 
Builder()569             public Builder() {
570                 mResetOnUnplugHighBatteryLevel = true;
571                 mResetOnUnplugAfterSignificantCharge = true;
572                 setPowerStatsThrottlePeriodMillis(BatteryConsumer.powerComponentIdToString(
573                                 BatteryConsumer.POWER_COMPONENT_CPU),
574                         DEFAULT_POWER_STATS_THROTTLE_PERIOD_CPU);
575             }
576 
577             /**
578              * Build the BatteryStatsConfig.
579              */
build()580             public BatteryStatsConfig build() {
581                 return new BatteryStatsConfig(this);
582             }
583 
584             /**
585              * Set whether a BatteryStats reset should occur on unplug when the battery level is
586              * high.
587              */
setResetOnUnplugHighBatteryLevel(boolean reset)588             public Builder setResetOnUnplugHighBatteryLevel(boolean reset) {
589                 mResetOnUnplugHighBatteryLevel = reset;
590                 return this;
591             }
592 
593             /**
594              * Set whether a BatteryStats reset should occur on unplug if the battery charge a
595              * significant amount since it has been plugged in.
596              */
setResetOnUnplugAfterSignificantCharge(boolean reset)597             public Builder setResetOnUnplugAfterSignificantCharge(boolean reset) {
598                 mResetOnUnplugAfterSignificantCharge = reset;
599                 return this;
600             }
601 
602             /**
603              * Sets the minimum amount of time (in millis) to wait between passes
604              * of power stats collection for the specified power component.
605              */
setPowerStatsThrottlePeriodMillis(String powerComponentName, long periodMs)606             public Builder setPowerStatsThrottlePeriodMillis(String powerComponentName,
607                     long periodMs) {
608                 mPowerStatsThrottlePeriods.put(powerComponentName, periodMs);
609                 return this;
610             }
611 
612             /**
613              * Sets the minimum amount of time (in millis) to wait between passes
614              * of power stats collection for any components not configured explicitly.
615              */
setDefaultPowerStatsThrottlePeriodMillis(long periodMs)616             public Builder setDefaultPowerStatsThrottlePeriodMillis(long periodMs) {
617                 mDefaultPowerStatsThrottlePeriod = periodMs;
618                 return this;
619             }
620         }
621     }
622 
623     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
624 
625     private final Runnable mDeferSetCharging = new Runnable() {
626         @Override
627         public void run() {
628             synchronized (BatteryStatsImpl.this) {
629                 if (mOnBattery) {
630                     // if the device gets unplugged in the time between this runnable being
631                     // executed and the lock being taken, we don't want to set charging state
632                     return;
633                 }
634                 boolean changed = setChargingLocked(true);
635                 if (changed) {
636                     final long uptimeMs = mClock.uptimeMillis();
637                     final long elapsedRealtimeMs = mClock.elapsedRealtime();
638                     mHistory.writeHistoryItem(elapsedRealtimeMs, uptimeMs);
639                 }
640             }
641         }
642     };
643 
644     public final EnergyStatsRetriever mEnergyConsumerRetriever;
645 
646     /**
647      * This handler is running on {@link BackgroundThread}.
648      */
649     final class MyHandler extends Handler {
MyHandler(Looper looper)650         public MyHandler(Looper looper) {
651             super(looper, null, true);
652         }
653 
654         @Override
handleMessage(Message msg)655         public void handleMessage(Message msg) {
656             BatteryCallback cb = mCallback;
657             switch (msg.what) {
658                 case MSG_REPORT_CPU_UPDATE_NEEDED:
659                     if (cb != null) {
660                         cb.batteryNeedsCpuUpdate();
661                     }
662                     break;
663                 case MSG_REPORT_POWER_CHANGE:
664                     if (cb != null) {
665                         cb.batteryPowerChanged(msg.arg1 != 0);
666                     }
667                     break;
668                 case MSG_REPORT_CHARGING:
669                     if (cb != null) {
670                         final String action;
671                         synchronized (BatteryStatsImpl.this) {
672                             action = mCharging ? BatteryManager.ACTION_CHARGING
673                                     : BatteryManager.ACTION_DISCHARGING;
674                         }
675                         Intent intent = new Intent(action);
676                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
677                         cb.batterySendBroadcast(intent);
678                     }
679                     break;
680                 case MSG_REPORT_RESET_STATS:
681                     if (cb != null) {
682                         cb.batteryStatsReset();
683                     }
684                 }
685         }
686     }
687 
postBatteryNeedsCpuUpdateMsg()688     public void postBatteryNeedsCpuUpdateMsg() {
689         mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED);
690     }
691 
692     /**
693      * Update per-freq cpu times for the supplied UID.
694      */
695     @GuardedBy("this")
696     @SuppressWarnings("GuardedBy")    // errorprone false positive on getProcStateTimeCounter
697     @VisibleForTesting
updateProcStateCpuTimesLocked(int uid, long elapsedRealtimeMs, long uptimeMs)698     public void updateProcStateCpuTimesLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
699         if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
700             return;
701         }
702 
703         ensureKernelSingleUidTimeReaderLocked();
704 
705         final Uid u = getUidStatsLocked(uid);
706 
707         mNumSingleUidCpuTimeReads++;
708 
709         LongArrayMultiStateCounter onBatteryCounter =
710                 u.getProcStateTimeCounter(elapsedRealtimeMs).getCounter();
711         LongArrayMultiStateCounter onBatteryScreenOffCounter =
712                 u.getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter();
713 
714 
715         mKernelSingleUidTimeReader.addDelta(uid, onBatteryCounter, elapsedRealtimeMs);
716         mKernelSingleUidTimeReader.addDelta(uid, onBatteryScreenOffCounter, elapsedRealtimeMs);
717 
718         if (u.mChildUids != null) {
719             LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
720                     getCpuTimeInFreqContainer();
721             int childUidCount = u.mChildUids.size();
722             for (int j = childUidCount - 1; j >= 0; --j) {
723                 LongArrayMultiStateCounter cpuTimeInFreqCounter =
724                         u.mChildUids.valueAt(j).cpuTimeInFreqCounter;
725                 if (cpuTimeInFreqCounter != null) {
726                     mKernelSingleUidTimeReader.addDelta(u.mChildUids.keyAt(j),
727                             cpuTimeInFreqCounter, elapsedRealtimeMs, deltaContainer);
728                     onBatteryCounter.addCounts(deltaContainer);
729                     onBatteryScreenOffCounter.addCounts(deltaContainer);
730                 }
731             }
732         }
733     }
734 
735     /**
736      * Removes kernel CPU stats for removed UIDs, in the order they were added to the
737      * mPendingRemovedUids queue.
738      */
739     @GuardedBy("this")
740     @SuppressWarnings("GuardedBy")    // errorprone false positive on removeLocked
clearPendingRemovedUidsLocked()741     public void clearPendingRemovedUidsLocked() {
742         long cutOffTimeMs = mClock.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS;
743         while (!mPendingRemovedUids.isEmpty()
744                 && mPendingRemovedUids.peek().getUidRemovalTimestamp() < cutOffTimeMs) {
745             mPendingRemovedUids.poll().removeLocked();
746         }
747     }
748 
749     /**
750      * When the battery/screen state changes, we don't attribute the cpu times to any process
751      * but we still need to take snapshots of all uids to get correct deltas later on.
752      */
753     @SuppressWarnings("GuardedBy")    // errorprone false positive on getProcStateTimeCounter
updateCpuTimesForAllUids()754     public void updateCpuTimesForAllUids() {
755         if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
756             mCpuPowerStatsCollector.schedule();
757             return;
758         }
759 
760         synchronized (BatteryStatsImpl.this) {
761             if (!trackPerProcStateCpuTimes()) {
762                 return;
763             }
764 
765             ensureKernelSingleUidTimeReaderLocked();
766 
767             // TODO(b/197162116): just get a list of UIDs
768             final SparseArray<long[]> allUidCpuFreqTimesMs =
769                     mCpuUidFreqTimeReader.getAllUidCpuFreqTimeMs();
770             for (int i = allUidCpuFreqTimesMs.size() - 1; i >= 0; --i) {
771                 final int uid = allUidCpuFreqTimesMs.keyAt(i);
772                 final int parentUid = mapUid(uid);
773                 final Uid u = getAvailableUidStatsLocked(parentUid);
774                 if (u == null) {
775                     continue;
776                 }
777 
778                 final int procState = u.mProcessState;
779                 if (procState == Uid.PROCESS_STATE_NONEXISTENT) {
780                     continue;
781                 }
782 
783                 final long elapsedRealtimeMs = mClock.elapsedRealtime();
784                 final long uptimeMs = mClock.uptimeMillis();
785                 final LongArrayMultiStateCounter onBatteryCounter =
786                         u.getProcStateTimeCounter(elapsedRealtimeMs).getCounter();
787                 final LongArrayMultiStateCounter onBatteryScreenOffCounter =
788                         u.getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter();
789 
790                 if (uid == parentUid || Process.isSdkSandboxUid(uid)) {
791                     mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryCounter,
792                             elapsedRealtimeMs);
793                     mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryScreenOffCounter,
794                             elapsedRealtimeMs);
795                 } else {
796                     Uid.ChildUid childUid = u.getChildUid(uid);
797                     if (childUid != null) {
798                         final LongArrayMultiStateCounter counter = childUid.cpuTimeInFreqCounter;
799                         if (counter != null) {
800                             final LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
801                                     getCpuTimeInFreqContainer();
802                             mKernelSingleUidTimeReader.addDelta(uid, counter, elapsedRealtimeMs,
803                                     deltaContainer);
804                             onBatteryCounter.addCounts(deltaContainer);
805                             onBatteryScreenOffCounter.addCounts(deltaContainer);
806                         }
807                     }
808                 }
809             }
810         }
811     }
812 
813     @GuardedBy("this")
ensureKernelSingleUidTimeReaderLocked()814     private void ensureKernelSingleUidTimeReaderLocked() {
815         if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)
816                 || mKernelSingleUidTimeReader != null) {
817             return;
818         }
819 
820         mKernelSingleUidTimeReader = new KernelSingleUidTimeReader(
821                 mCpuScalingPolicies.getScalingStepCount());
822         mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.perClusterTimesAvailable()
823                 && mKernelSingleUidTimeReader.singleUidCpuTimesAvailable();
824     }
825 
826     public interface ExternalStatsSync {
827         int UPDATE_CPU = 0x01;
828         int UPDATE_WIFI = 0x02;
829         int UPDATE_RADIO = 0x04;
830         int UPDATE_BT = 0x08;
831         int UPDATE_RPM = 0x10;
832         int UPDATE_DISPLAY = 0x20;
833         int UPDATE_CAMERA = 0x40;
834         int RESET = 0x80;
835 
836         int UPDATE_ALL =
837                 UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM | UPDATE_DISPLAY
838                         | UPDATE_CAMERA;
839 
840         int UPDATE_ON_PROC_STATE_CHANGE = UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
841 
842         int UPDATE_ON_RESET = UPDATE_ALL | RESET;
843 
844         @IntDef(flag = true, prefix = "UPDATE_", value = {
845                 UPDATE_CPU,
846                 UPDATE_WIFI,
847                 UPDATE_RADIO,
848                 UPDATE_BT,
849                 UPDATE_RPM,
850                 UPDATE_DISPLAY,
851                 UPDATE_CAMERA,
852                 UPDATE_ALL,
853         })
854         @Retention(RetentionPolicy.SOURCE)
855         public @interface ExternalUpdateFlag {
856         }
857 
scheduleSync(String reason, int flags)858         Future<?> scheduleSync(String reason, int flags);
scheduleCpuSyncDueToRemovedUid(int uid)859         Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
860 
861         /**
862          * Schedule a sync because of a screen state change.
863          */
scheduleSyncDueToScreenStateChange(int flags, boolean onBattery, boolean onBatteryScreenOff, int screenState, int[] perDisplayScreenStates)864         Future<?> scheduleSyncDueToScreenStateChange(int flags, boolean onBattery,
865                 boolean onBatteryScreenOff, int screenState, int[] perDisplayScreenStates);
scheduleCpuSyncDueToWakelockChange(long delayMillis)866         Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis);
cancelCpuSyncDueToWakelockChange()867         void cancelCpuSyncDueToWakelockChange();
scheduleSyncDueToBatteryLevelChange(long delayMillis)868         Future<?> scheduleSyncDueToBatteryLevelChange(long delayMillis);
869         /** Schedule removal of UIDs corresponding to a removed user */
scheduleCleanupDueToRemovedUser(int userId)870         Future<?> scheduleCleanupDueToRemovedUser(int userId);
871         /** Schedule a sync because of a process state change */
scheduleSyncDueToProcessStateChange(int flags, long delayMillis)872         void scheduleSyncDueToProcessStateChange(int flags, long delayMillis);
873     }
874 
875     public Handler mHandler;
876     private ExternalStatsSync mExternalSync = null;
877     @VisibleForTesting
878     protected UserInfoProvider mUserInfoProvider = null;
879 
880     private BatteryCallback mCallback;
881 
882     /**
883      * Mapping child uids to their parent uid.
884      */
885     @VisibleForTesting
886     protected final PowerStatsUidResolver mPowerStatsUidResolver;
887 
888     /**
889      * The statistics we have collected organized by uids.
890      */
891     private final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
892 
893     // A set of pools of currently active timers.  When a timer is queried, we will divide the
894     // elapsed time by the number of active timers to arrive at that timer's share of the time.
895     // In order to do this, we must refresh each timer whenever the number of active timers
896     // changes.
897     @VisibleForTesting
898     protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
899     private final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
900     private final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
901     private final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
902     private final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
903     private final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
904     private final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
905     private final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
906     private final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
907     private final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers =
908             new SparseArray<>();
909     private final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
910     private final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
911     private final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
912     private final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
913     private final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
914 
915     // Last partial timers we use for distributing CPU usage.
916     @VisibleForTesting
917     protected ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
918 
919     // These are the objects that will want to do something when the device
920     // is unplugged from power.
921     protected final TimeBase mOnBatteryTimeBase = new TimeBase(true);
922 
923     // These are the objects that will want to do something when the device
924     // is unplugged from power *and* the screen is off or doze.
925     protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(true);
926 
927     private boolean mSystemReady;
928     private boolean mShuttingDown;
929 
930     private final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
931     private final HistoryStepDetailsCalculatorImpl mStepDetailsCalculator =
932             new HistoryStepDetailsCalculatorImpl();
933 
934     private boolean mHaveBatteryLevel = false;
935     private boolean mBatteryPluggedIn;
936     private long mBatteryPluggedInRealTimeMs = 0;
937     private int mBatteryStatus;
938     private int mBatteryLevel;
939     private int mBatteryPlugType;
940     private int mBatteryChargeUah;
941     private int mBatteryHealth;
942     private int mBatteryTemperature;
943     private int mBatteryVoltageMv;
944 
945     @NonNull
946     private final BatteryStatsHistory mHistory;
947 
948     int mStartCount;
949 
950     /**
951      * Set to true when a reset occurs, informing us that the next time BatteryExternalStatsWorker
952      * gives us data, we mustn't process it since this data includes pre-reset-period data.
953      */
954     @GuardedBy("this")
955     boolean mIgnoreNextExternalStats = false;
956 
957     long mStartClockTimeMs;
958     String mStartPlatformVersion;
959     String mEndPlatformVersion;
960 
961     long mUptimeUs;
962     long mUptimeStartUs;
963     long mRealtimeUs;
964     long mRealtimeStartUs;
965     long mMonotonicStartTime;
966     long mMonotonicEndTime = MonotonicClock.UNDEFINED;
967 
968     int mWakeLockNesting;
969     boolean mWakeLockImportant;
970     public boolean mRecordAllHistory;
971     boolean mNoAutoReset;
972 
973     /**
974      * Overall screen state. For multidisplay devices, this represents the current highest screen
975      * state of the displays.
976      */
977     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
978     protected int mScreenState = Display.STATE_UNKNOWN;
979     /**
980      * Overall screen on timer. For multidisplay devices, this represents the time spent with at
981      * least one display in the screen on state.
982      */
983     StopwatchTimer mScreenOnTimer;
984     /**
985      * Overall screen doze timer. For multidisplay devices, this represents the time spent with
986      * screen doze being the highest screen state.
987      */
988     StopwatchTimer mScreenDozeTimer;
989     /**
990      * Overall screen brightness bin. For multidisplay devices, this represents the current
991      * brightest screen.
992      */
993     int mScreenBrightnessBin = -1;
994     /**
995      * Overall screen brightness timers. For multidisplay devices, the {@link mScreenBrightnessBin}
996      * timer will be active at any given time
997      */
998     final StopwatchTimer[] mScreenBrightnessTimer =
999             new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
1000 
1001     boolean mPretendScreenOff;
1002 
1003     private static class DisplayBatteryStats {
1004         /**
1005          * Per display screen state.
1006          */
1007         public int screenState = Display.STATE_UNKNOWN;
1008         /**
1009          * Per display screen on timers.
1010          */
1011         public StopwatchTimer screenOnTimer;
1012         /**
1013          * Per display screen doze timers.
1014          */
1015         public StopwatchTimer screenDozeTimer;
1016         /**
1017          * Per display screen brightness bins.
1018          */
1019         public int screenBrightnessBin = -1;
1020         /**
1021          * Per display screen brightness timers.
1022          */
1023         public StopwatchTimer[] screenBrightnessTimers =
1024                 new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
1025         /**
1026          * Per display screen state the last time {@link #updateDisplayEnergyConsumerStatsLocked}
1027          * was called.
1028          */
1029         public int screenStateAtLastEnergyMeasurement = Display.STATE_UNKNOWN;
1030 
DisplayBatteryStats(Clock clock, TimeBase timeBase)1031         DisplayBatteryStats(Clock clock, TimeBase timeBase) {
1032             screenOnTimer = new StopwatchTimer(clock, null, -1, null,
1033                     timeBase);
1034             screenDozeTimer = new StopwatchTimer(clock, null, -1, null,
1035                     timeBase);
1036             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1037                 screenBrightnessTimers[i] = new StopwatchTimer(clock, null, -100 - i, null,
1038                         timeBase);
1039             }
1040         }
1041 
1042         /**
1043          * Reset display timers.
1044          */
reset(long elapsedRealtimeUs)1045         public void reset(long elapsedRealtimeUs) {
1046             screenOnTimer.reset(false, elapsedRealtimeUs);
1047             screenDozeTimer.reset(false, elapsedRealtimeUs);
1048             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1049                 screenBrightnessTimers[i].reset(false, elapsedRealtimeUs);
1050             }
1051         }
1052 
1053         /**
1054          * Write data to summary parcel
1055          */
writeSummaryToParcel(Parcel out, long elapsedRealtimeUs)1056         public void writeSummaryToParcel(Parcel out, long elapsedRealtimeUs) {
1057             screenOnTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
1058             screenDozeTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
1059             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1060                 screenBrightnessTimers[i].writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
1061             }
1062         }
1063 
1064         /**
1065          * Read data from summary parcel
1066          */
readSummaryFromParcel(Parcel in)1067         public void readSummaryFromParcel(Parcel in) {
1068             screenOnTimer.readSummaryFromParcelLocked(in);
1069             screenDozeTimer.readSummaryFromParcelLocked(in);
1070             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1071                 screenBrightnessTimers[i].readSummaryFromParcelLocked(in);
1072             }
1073         }
1074     }
1075 
1076     DisplayBatteryStats[] mPerDisplayBatteryStats;
1077 
1078     private int mDisplayMismatchWtfCount = 0;
1079 
1080     boolean mInteractive;
1081     StopwatchTimer mInteractiveTimer;
1082 
1083     boolean mPowerSaveModeEnabled;
1084     StopwatchTimer mPowerSaveModeEnabledTimer;
1085 
1086     boolean mDeviceIdling;
1087     StopwatchTimer mDeviceIdlingTimer;
1088 
1089     boolean mDeviceLightIdling;
1090     StopwatchTimer mDeviceLightIdlingTimer;
1091 
1092     int mDeviceIdleMode;
1093     long mLastIdleTimeStartMs;
1094     long mLongestLightIdleTimeMs;
1095     long mLongestFullIdleTimeMs;
1096     StopwatchTimer mDeviceIdleModeLightTimer;
1097     StopwatchTimer mDeviceIdleModeFullTimer;
1098 
1099     boolean mPhoneOn;
1100     StopwatchTimer mPhoneOnTimer;
1101 
1102     int mAudioOnNesting;
1103     StopwatchTimer mAudioOnTimer;
1104 
1105     int mVideoOnNesting;
1106     StopwatchTimer mVideoOnTimer;
1107 
1108     int mFlashlightOnNesting;
1109     StopwatchTimer mFlashlightOnTimer;
1110 
1111     int mCameraOnNesting;
1112     StopwatchTimer mCameraOnTimer;
1113 
1114     private static final int USB_DATA_UNKNOWN = 0;
1115     private static final int USB_DATA_DISCONNECTED = 1;
1116     private static final int USB_DATA_CONNECTED = 2;
1117     int mUsbDataState = USB_DATA_UNKNOWN;
1118 
1119     private static final int GPS_SIGNAL_QUALITY_NONE = 2;
1120     int mGpsSignalQualityBin = -1;
1121     final StopwatchTimer[] mGpsSignalQualityTimer =
1122         new StopwatchTimer[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
1123 
1124     int mPhoneSignalStrengthBin = -1;
1125     int mPhoneSignalStrengthBinRaw = -1;
1126     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
1127             new StopwatchTimer[CELL_SIGNAL_STRENGTH_LEVEL_COUNT];
1128 
1129     StopwatchTimer mPhoneSignalScanningTimer;
1130 
1131     int mPhoneDataConnectionType = -1;
1132     final StopwatchTimer[] mPhoneDataConnectionsTimer =
1133             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
1134 
1135     int mNrState = -1;
1136     StopwatchTimer mNrNsaTimer;
1137 
1138     @RadioAccessTechnology
1139     int mActiveRat = RADIO_ACCESS_TECHNOLOGY_OTHER;
1140 
1141     private static class RadioAccessTechnologyBatteryStats {
1142         /**
1143          * This RAT is currently being used.
1144          */
1145         private boolean mActive = false;
1146         /**
1147          * Current active frequency range for this RAT.
1148          */
1149         @ServiceState.FrequencyRange
1150         private int mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
1151         /**
1152          * Current signal strength for this RAT.
1153          */
1154         private int mSignalStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
1155         /**
1156          * Timers for each combination of frequency range and signal strength.
1157          */
1158         public final StopwatchTimer[][] perStateTimers;
1159         /**
1160          * Counters tracking the time (in milliseconds) spent transmitting data in a given state.
1161          */
1162         @Nullable
1163         private LongSamplingCounter[][] mPerStateTxDurationMs = null;
1164         /**
1165          * Counters tracking the time (in milliseconds) spent receiving data in at given frequency.
1166          */
1167         @Nullable
1168         private LongSamplingCounter[] mPerFrequencyRxDurationMs = null;
1169 
RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase)1170         RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase) {
1171             perStateTimers =
1172                     new StopwatchTimer[freqCount][CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS];
1173             for (int i = 0; i < freqCount; i++) {
1174                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1175                     perStateTimers[i][j] = new StopwatchTimer(clock, null, -1, null, timeBase);
1176                 }
1177             }
1178         }
1179 
1180         /**
1181          * Note this RAT is currently being used.
1182          */
noteActive(boolean active, long elapsedRealtimeMs)1183         public void noteActive(boolean active, long elapsedRealtimeMs) {
1184             if (mActive == active) return;
1185             mActive = active;
1186             if (mActive) {
1187                 perStateTimers[mFrequencyRange][mSignalStrength].startRunningLocked(
1188                         elapsedRealtimeMs);
1189             } else {
1190                 perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(
1191                         elapsedRealtimeMs);
1192             }
1193         }
1194 
1195         /**
1196          * Note current frequency range has changed.
1197          */
noteFrequencyRange(@erviceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs)1198         public void noteFrequencyRange(@ServiceState.FrequencyRange int frequencyRange,
1199                 long elapsedRealtimeMs) {
1200             if (mFrequencyRange == frequencyRange) return;
1201 
1202             if (!mActive) {
1203                 // RAT not in use, note the frequency change and move on.
1204                 mFrequencyRange = frequencyRange;
1205                 return;
1206             }
1207             perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(elapsedRealtimeMs);
1208             perStateTimers[frequencyRange][mSignalStrength].startRunningLocked(elapsedRealtimeMs);
1209             mFrequencyRange = frequencyRange;
1210         }
1211 
1212         /**
1213          * Note current signal strength has changed.
1214          */
noteSignalStrength(int signalStrength, long elapsedRealtimeMs)1215         public void noteSignalStrength(int signalStrength, long elapsedRealtimeMs) {
1216             if (mSignalStrength == signalStrength) return;
1217 
1218             if (!mActive) {
1219                 // RAT not in use, note the signal strength change and move on.
1220                 mSignalStrength = signalStrength;
1221                 return;
1222             }
1223             perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(elapsedRealtimeMs);
1224             perStateTimers[mFrequencyRange][signalStrength].startRunningLocked(elapsedRealtimeMs);
1225             mSignalStrength = signalStrength;
1226         }
1227 
1228         /**
1229          * Returns the duration in milliseconds spent in a given state since the last mark.
1230          */
getTimeSinceMark(@erviceState.FrequencyRange int frequencyRange, int signalStrength, long elapsedRealtimeMs)1231         public long getTimeSinceMark(@ServiceState.FrequencyRange int frequencyRange,
1232                 int signalStrength, long elapsedRealtimeMs) {
1233             return perStateTimers[frequencyRange][signalStrength].getTimeSinceMarkLocked(
1234                     elapsedRealtimeMs * 1000) / 1000;
1235         }
1236 
1237         /**
1238          * Set mark for all timers.
1239          */
setMark(long elapsedRealtimeMs)1240         public void setMark(long elapsedRealtimeMs) {
1241             final int size = perStateTimers.length;
1242             for (int i = 0; i < size; i++) {
1243                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1244                     perStateTimers[i][j].setMark(elapsedRealtimeMs);
1245                 }
1246             }
1247         }
1248 
1249         /**
1250          * Returns numbers of frequencies tracked for this RAT.
1251          */
getFrequencyRangeCount()1252         public int getFrequencyRangeCount() {
1253             return perStateTimers.length;
1254         }
1255 
1256         /**
1257          * Add TX time for a given state.
1258          */
incrementTxDuration(@erviceState.FrequencyRange int frequencyRange, int signalStrength, long durationMs)1259         public void incrementTxDuration(@ServiceState.FrequencyRange int frequencyRange,
1260                 int signalStrength, long durationMs) {
1261             getTxDurationCounter(frequencyRange, signalStrength, true).addCountLocked(durationMs);
1262         }
1263 
1264         /**
1265          * Add TX time for a given frequency.
1266          */
incrementRxDuration(@erviceState.FrequencyRange int frequencyRange, long durationMs)1267         public void incrementRxDuration(@ServiceState.FrequencyRange int frequencyRange,
1268                 long durationMs) {
1269             getRxDurationCounter(frequencyRange, true).addCountLocked(durationMs);
1270         }
1271 
1272         /**
1273          * Reset radio access technology timers and counts.
1274          */
reset(long elapsedRealtimeUs)1275         public void reset(long elapsedRealtimeUs) {
1276             final int size = perStateTimers.length;
1277             for (int i = 0; i < size; i++) {
1278                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1279                     perStateTimers[i][j].reset(false, elapsedRealtimeUs);
1280                     if (mPerStateTxDurationMs == null) continue;
1281                     mPerStateTxDurationMs[i][j].reset(false, elapsedRealtimeUs);
1282                 }
1283                 if (mPerFrequencyRxDurationMs == null) continue;
1284                 mPerFrequencyRxDurationMs[i].reset(false, elapsedRealtimeUs);
1285             }
1286         }
1287 
1288         /**
1289          * Write data to summary parcel
1290          */
writeSummaryToParcel(Parcel out, long elapsedRealtimeUs)1291         public void writeSummaryToParcel(Parcel out, long elapsedRealtimeUs) {
1292             final int freqCount = perStateTimers.length;
1293             out.writeInt(freqCount);
1294             out.writeInt(CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS);
1295             for (int i = 0; i < freqCount; i++) {
1296                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1297                     perStateTimers[i][j].writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
1298                 }
1299             }
1300 
1301             if (mPerStateTxDurationMs == null) {
1302                 out.writeInt(0);
1303             } else {
1304                 out.writeInt(1);
1305                 for (int i = 0; i < freqCount; i++) {
1306                     for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1307                         mPerStateTxDurationMs[i][j].writeSummaryFromParcelLocked(out);
1308                     }
1309                 }
1310             }
1311 
1312             if (mPerFrequencyRxDurationMs == null) {
1313                 out.writeInt(0);
1314             } else {
1315                 out.writeInt(1);
1316                 for (int i = 0; i < freqCount; i++) {
1317                     mPerFrequencyRxDurationMs[i].writeSummaryFromParcelLocked(out);
1318                 }
1319             }
1320         }
1321 
1322         /**
1323          * Read data from summary parcel
1324          */
readSummaryFromParcel(Parcel in)1325         public void readSummaryFromParcel(Parcel in) {
1326             final int oldFreqCount = in.readInt();
1327             final int oldSignalStrengthCount = in.readInt();
1328             final int currFreqCount = perStateTimers.length;
1329             final int currSignalStrengthCount = CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS;
1330 
1331             for (int freq = 0; freq < oldFreqCount; freq++) {
1332                 for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
1333                     if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
1334                         // Mismatch with the summary parcel. Consume the data but don't use it.
1335                         final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
1336                                 new TimeBase());
1337                         // Consume perStateTimers data.
1338                         temp.readSummaryFromParcelLocked(in);
1339                     } else {
1340                         perStateTimers[freq][strength].readSummaryFromParcelLocked(in);
1341                     }
1342                 }
1343             }
1344 
1345             if (in.readInt() == 1) {
1346                 for (int freq = 0; freq < oldFreqCount; freq++) {
1347                     for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
1348                         if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
1349                             // Mismatch with the summary parcel. Consume the data but don't use it.
1350                             final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
1351                                     new TimeBase());
1352                             // Consume mPerStateTxDurationMs data.
1353                             temp.readSummaryFromParcelLocked(in);
1354                         }
1355                         getTxDurationCounter(freq, strength, true).readSummaryFromParcelLocked(in);
1356                     }
1357                 }
1358             }
1359 
1360             if (in.readInt() == 1) {
1361                 for (int freq = 0; freq < oldFreqCount; freq++) {
1362                     if (freq >= currFreqCount) {
1363                         // Mismatch with the summary parcel. Consume the data but don't use it.
1364                         final StopwatchTimer
1365                                 temp = new StopwatchTimer(null, null, -1, null, new TimeBase());
1366                         // Consume mPerFrequencyRxDurationMs data.
1367                         temp.readSummaryFromParcelLocked(in);
1368                         continue;
1369                     }
1370                     getRxDurationCounter(freq, true).readSummaryFromParcelLocked(in);
1371                 }
1372             }
1373         }
1374 
getTxDurationCounter( @erviceState.FrequencyRange int frequencyRange, int signalStrength, boolean make)1375         private LongSamplingCounter getTxDurationCounter(
1376                 @ServiceState.FrequencyRange int frequencyRange, int signalStrength, boolean make) {
1377             if (mPerStateTxDurationMs == null) {
1378                 if (!make) return null;
1379 
1380                 final int freqCount = getFrequencyRangeCount();
1381                 final int signalStrengthCount = perStateTimers[0].length;
1382                 final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
1383                 mPerStateTxDurationMs = new LongSamplingCounter[freqCount][signalStrengthCount];
1384                 for (int freq = 0; freq < freqCount; freq++) {
1385                     for (int strength = 0; strength < signalStrengthCount; strength++) {
1386                         mPerStateTxDurationMs[freq][strength] = new LongSamplingCounter(timeBase);
1387                     }
1388                 }
1389             }
1390             if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
1391                 Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
1392                         + ") requested in getTxDurationCounter");
1393                 return null;
1394             }
1395             if (signalStrength < 0 || signalStrength >= perStateTimers[0].length) {
1396                 Slog.w(TAG, "Unexpected signal strength (" + signalStrength
1397                         + ") requested in getTxDurationCounter");
1398                 return null;
1399             }
1400             return mPerStateTxDurationMs[frequencyRange][signalStrength];
1401         }
1402 
getRxDurationCounter( @erviceState.FrequencyRange int frequencyRange, boolean make)1403         private LongSamplingCounter getRxDurationCounter(
1404                 @ServiceState.FrequencyRange int frequencyRange, boolean make) {
1405             if (mPerFrequencyRxDurationMs == null) {
1406                 if (!make) return null;
1407 
1408                 final int freqCount = getFrequencyRangeCount();
1409                 final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
1410                 mPerFrequencyRxDurationMs = new LongSamplingCounter[freqCount];
1411                 for (int freq = 0; freq < freqCount; freq++) {
1412                     mPerFrequencyRxDurationMs[freq] = new LongSamplingCounter(timeBase);
1413                 }
1414             }
1415             if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
1416                 Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
1417                         + ") requested in getRxDurationCounter");
1418                 return null;
1419             }
1420             return mPerFrequencyRxDurationMs[frequencyRange];
1421         }
1422     }
1423 
1424     /**
1425      * Number of frequency ranges, keep in sync with {@link ServiceState.FrequencyRange}
1426      */
1427     private static final int NR_FREQUENCY_COUNT = 5;
1428 
1429     RadioAccessTechnologyBatteryStats[] mPerRatBatteryStats =
1430             new RadioAccessTechnologyBatteryStats[RADIO_ACCESS_TECHNOLOGY_COUNT];
1431 
1432     @GuardedBy("this")
getRatBatteryStatsLocked( @adioAccessTechnology int rat)1433     private RadioAccessTechnologyBatteryStats getRatBatteryStatsLocked(
1434             @RadioAccessTechnology int rat) {
1435         RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
1436         if (stats == null) {
1437             final int freqCount = rat == RADIO_ACCESS_TECHNOLOGY_NR ? NR_FREQUENCY_COUNT : 1;
1438             stats = new RadioAccessTechnologyBatteryStats(freqCount, mClock, mOnBatteryTimeBase);
1439             mPerRatBatteryStats[rat] = stats;
1440         }
1441         return stats;
1442     }
1443 
1444     final LongSamplingCounter[] mNetworkByteActivityCounters =
1445             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
1446 
1447     final LongSamplingCounter[] mNetworkPacketActivityCounters =
1448             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
1449 
1450     /**
1451      * The WiFi Overall wakelock timer
1452      * This timer tracks the actual aggregate time for which MC wakelocks are enabled
1453      * since addition of per UID timers would not result in an accurate value due to overlapp of
1454      * per uid wakelock timers
1455      */
1456     StopwatchTimer mWifiMulticastWakelockTimer;
1457 
1458     /**
1459      * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
1460      */
1461     ControllerActivityCounterImpl mWifiActivity;
1462 
1463     /**
1464      * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
1465      */
1466     ControllerActivityCounterImpl mBluetoothActivity;
1467 
1468     /**
1469      * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
1470      */
1471     ControllerActivityCounterImpl mModemActivity;
1472 
1473     /**
1474      * Whether the device supports WiFi controller energy reporting. This is set to true on
1475      * the first WiFi energy report. See {@link #mWifiActivity}.
1476      */
1477     boolean mHasWifiReporting = false;
1478 
1479     /**
1480      * Whether the device supports Bluetooth controller energy reporting. This is set to true on
1481      * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
1482      */
1483     boolean mHasBluetoothReporting = false;
1484 
1485     /**
1486      * Whether the device supports Modem controller energy reporting. This is set to true on
1487      * the first Modem energy report. See {@link #mModemActivity}.
1488      */
1489     boolean mHasModemReporting = false;
1490 
1491     boolean mWifiOn;
1492     StopwatchTimer mWifiOnTimer;
1493 
1494     boolean mGlobalWifiRunning;
1495     StopwatchTimer mGlobalWifiRunningTimer;
1496 
1497     int mWifiState = -1;
1498     final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
1499 
1500     int mWifiSupplState = -1;
1501     final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
1502 
1503     int mWifiSignalStrengthBin = -1;
1504     final StopwatchTimer[] mWifiSignalStrengthsTimer =
1505             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
1506 
1507     StopwatchTimer mWifiActiveTimer;
1508 
1509     int mBluetoothScanNesting;
1510     StopwatchTimer mBluetoothScanTimer;
1511 
1512     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
1513     long mMobileRadioActiveStartTimeMs;
1514     StopwatchTimer mMobileRadioActiveTimer;
1515     StopwatchTimer mMobileRadioActivePerAppTimer;
1516     LongSamplingCounter mMobileRadioActiveAdjustedTime;
1517     LongSamplingCounter mMobileRadioActiveUnknownTime;
1518     LongSamplingCounter mMobileRadioActiveUnknownCount;
1519 
1520     /**
1521      * The soonest the Mobile Radio stats can be updated due to a mobile radio power state change
1522      * after it was last updated.
1523      */
1524     @VisibleForTesting
1525     protected static final long MOBILE_RADIO_POWER_STATE_UPDATE_FREQ_MS = 1000 * 60 * 10;
1526 
1527     int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
1528 
1529     @GuardedBy("this")
1530     @VisibleForTesting
1531     protected @Nullable EnergyConsumerStats.Config mEnergyConsumerStatsConfig;
1532 
1533     /**
1534      * Accumulated global (generally, device-wide total) charge consumption of various consumers
1535      * while on battery.
1536      * Its '<b>custom</b> power buckets' correspond to the
1537      * {@link android.hardware.power.stats.EnergyConsumer.ordinal}s of (custom) energy consumer
1538      * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
1539      *
1540      * If energy consumer data is completely unavailable this will be null.
1541      */
1542     @GuardedBy("this")
1543     @VisibleForTesting
1544     @Nullable
1545     protected EnergyConsumerStats mGlobalEnergyConsumerStats;
1546     /** Bluetooth Power calculator for attributing bluetooth EnergyConsumer to uids */
1547     @Nullable BluetoothPowerCalculator mBluetoothPowerCalculator = null;
1548     /** Cpu Power calculator for attributing cpu EnergyConsumer to uids */
1549     @Nullable CpuPowerCalculator mCpuPowerCalculator = null;
1550     /** Mobile Radio Power calculator for attributing radio EnergyConsumer to uids */
1551     @Nullable MobileRadioPowerCalculator mMobileRadioPowerCalculator = null;
1552     /** Wifi Power calculator for attributing wifi EnergyConsumer to uids */
1553     @Nullable WifiPowerCalculator mWifiPowerCalculator = null;
1554 
1555     /**
1556      * These provide time bases that discount the time the device is plugged
1557      * in to power.
1558      */
1559     boolean mOnBattery;
1560     @VisibleForTesting
1561     protected boolean mOnBatteryInternal;
1562 
1563     /**
1564      * External reporting of whether the device is actually charging.
1565      */
1566     boolean mCharging = true;
1567 
1568     /*
1569      * These keep track of battery levels (1-100) at the last unplug event.
1570      */
1571     int mDischargeUnplugLevel;
1572     int mDischargePlugLevel;
1573     int mDischargeCurrentLevel;
1574     int mLowDischargeAmountSinceCharge;
1575     int mHighDischargeAmountSinceCharge;
1576     int mDischargeScreenOnUnplugLevel;
1577     int mDischargeScreenOffUnplugLevel;
1578     int mDischargeScreenDozeUnplugLevel;
1579     int mDischargeAmountScreenOn;
1580     int mDischargeAmountScreenOnSinceCharge;
1581     int mDischargeAmountScreenOff;
1582     int mDischargeAmountScreenOffSinceCharge;
1583     int mDischargeAmountScreenDoze;
1584     int mDischargeAmountScreenDozeSinceCharge;
1585 
1586     private LongSamplingCounter mDischargeScreenOffCounter;
1587     private LongSamplingCounter mDischargeScreenDozeCounter;
1588     private LongSamplingCounter mDischargeCounter;
1589     private LongSamplingCounter mDischargeLightDozeCounter;
1590     private LongSamplingCounter mDischargeDeepDozeCounter;
1591 
1592     static final int MAX_LEVEL_STEPS = 200;
1593 
1594     int mInitStepMode = 0;
1595     int mCurStepMode = 0;
1596     int mModStepMode = 0;
1597 
1598     int mLastDischargeStepLevel;
1599     int mMinDischargeStepLevel;
1600     final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
1601     final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
1602     ArrayList<PackageChange> mDailyPackageChanges;
1603 
1604     int mLastChargeStepLevel;
1605     int mMaxChargeStepLevel;
1606     final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
1607     final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
1608 
1609     static final int MAX_DAILY_ITEMS = 10;
1610 
1611     long mDailyStartTimeMs = 0;
1612     long mNextMinDailyDeadlineMs = 0;
1613     long mNextMaxDailyDeadlineMs = 0;
1614 
1615     final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
1616 
1617     long mLastWriteTimeMs = 0; // Milliseconds
1618 
1619     private int mPhoneServiceState = -1;
1620     private int mPhoneServiceStateRaw = -1;
1621     private int mPhoneSimStateRaw = -1;
1622 
1623     private int mNumConnectivityChange;
1624 
1625     private int mEstimatedBatteryCapacityMah = -1;
1626 
1627     private int mLastLearnedBatteryCapacityUah = -1;
1628     private int mMinLearnedBatteryCapacityUah = -1;
1629     private int mMaxLearnedBatteryCapacityUah = -1;
1630 
1631     private long mBatteryTimeToFullSeconds = -1;
1632 
1633     private LongArrayMultiStateCounter.LongArrayContainer mTmpCpuTimeInFreq;
1634 
1635     /**
1636      * Times spent by the system server threads handling incoming binder requests.
1637      */
1638     private LongSamplingCounterArray mBinderThreadCpuTimesUs;
1639 
1640     @VisibleForTesting
1641     protected PowerProfile mPowerProfile;
1642 
1643     @VisibleForTesting
1644     @GuardedBy("this")
1645     protected final Constants mConstants;
1646 
1647     @VisibleForTesting
1648     protected final BatteryStatsConfig mBatteryStatsConfig;
1649 
1650     @GuardedBy("this")
1651     private AlarmManager mAlarmManager = null;
1652 
1653     private final AlarmManager.OnAlarmListener mLongPlugInAlarmHandler = () ->
1654             mHandler.post(() -> {
1655                 synchronized (BatteryStatsImpl.this) {
1656                     maybeResetWhilePluggedInLocked();
1657                 }
1658             });
1659 
1660     /*
1661      * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
1662      * recording their times when on-battery (regardless of screen state).
1663      */
1664     private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>();
1665     /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */
1666     private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>();
1667 
1668     @Override
getRpmStats()1669     public Map<String, ? extends Timer> getRpmStats() {
1670         return mRpmStats;
1671     }
1672 
1673     // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED.
1674     @Override
getScreenOffRpmStats()1675     public Map<String, ? extends Timer> getScreenOffRpmStats() {
1676         return mScreenOffRpmStats;
1677     }
1678 
1679     /*
1680      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
1681      */
1682     private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
1683 
getKernelWakelockStats()1684     public Map<String, ? extends Timer> getKernelWakelockStats() {
1685         return mKernelWakelockStats;
1686     }
1687 
1688     @Override
getWakeLockStats()1689     public WakeLockStats getWakeLockStats() {
1690         final long realtimeMs = mClock.elapsedRealtime();
1691         List<WakeLockStats.WakeLock> uidWakeLockStats = new ArrayList<>();
1692         List<WakeLockStats.WakeLock> uidAggregatedWakeLockStats = new ArrayList<>();
1693         for (int i = mUidStats.size() - 1; i >= 0; i--) {
1694             final Uid uid = mUidStats.valueAt(i);
1695 
1696             // Converts unaggregated wakelocks.
1697             final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats =
1698                     uid.mWakelockStats.getMap();
1699             for (int j = wakelockStats.size() - 1; j >= 0; j--) {
1700                 final String name = wakelockStats.keyAt(j);
1701                 final Uid.Wakelock wakelock = (Uid.Wakelock) wakelockStats.valueAt(j);
1702                 final WakeLockStats.WakeLock wakeLockItem =
1703                         createWakeLock(uid, name, /* isAggregated= */ false, wakelock.mTimerPartial,
1704                                 realtimeMs);
1705                 if (wakeLockItem != null) {
1706                     uidWakeLockStats.add(wakeLockItem);
1707                 }
1708             }
1709 
1710             // Converts aggregated wakelocks.
1711             final WakeLockStats.WakeLock aggregatedWakeLockItem =
1712                     createWakeLock(
1713                     uid,
1714                     WakeLockStats.WakeLock.NAME_AGGREGATED,
1715                     /* isAggregated= */ true,
1716                     uid.mAggregatedPartialWakelockTimer,
1717                     realtimeMs);
1718             if (aggregatedWakeLockItem != null) {
1719                 uidAggregatedWakeLockStats.add(aggregatedWakeLockItem);
1720             }
1721         }
1722         return new WakeLockStats(uidWakeLockStats, uidAggregatedWakeLockStats);
1723     }
1724 
1725     // Returns a valid {@code WakeLockStats.WakeLock} or null.
createWakeLock( Uid uid, String name, boolean isAggregated, DualTimer timer, final long realtimeMs)1726     private WakeLockStats.WakeLock createWakeLock(
1727             Uid uid, String name, boolean isAggregated, DualTimer timer, final long realtimeMs) {
1728         if (timer == null) {
1729             return null;
1730         }
1731         // Uses the primary timer for total wakelock data and used the sub timer for background
1732         // wakelock data.
1733         final WakeLockStats.WakeLockData totalWakeLockData = createWakeLockData(timer, realtimeMs);
1734         final WakeLockStats.WakeLockData backgroundWakeLockData =
1735                 createWakeLockData(timer.getSubTimer(), realtimeMs);
1736 
1737         return WakeLockStats.WakeLock.isDataValid(totalWakeLockData, backgroundWakeLockData)
1738                 ? new WakeLockStats.WakeLock(
1739                 uid.getUid(),
1740                 name,
1741                 isAggregated,
1742                 totalWakeLockData,
1743                 backgroundWakeLockData) : null;
1744     }
1745 
1746     @NonNull
createWakeLockData( DurationTimer timer, final long realtimeMs)1747     private WakeLockStats.WakeLockData createWakeLockData(
1748             DurationTimer timer, final long realtimeMs) {
1749         if (timer == null) {
1750             return WakeLockStats.WakeLockData.EMPTY;
1751         }
1752         final long totalTimeLockHeldMs =
1753                 timer.getTotalTimeLocked(realtimeMs * 1000, STATS_SINCE_CHARGED) / 1000;
1754         if (totalTimeLockHeldMs == 0) {
1755             return WakeLockStats.WakeLockData.EMPTY;
1756         }
1757         return new WakeLockStats.WakeLockData(
1758             timer.getCountLocked(STATS_SINCE_CHARGED),
1759             totalTimeLockHeldMs,
1760             timer.isRunningLocked() ? timer.getCurrentDurationMsLocked(realtimeMs) : 0);
1761     }
1762 
1763     @Override
1764     @GuardedBy("this")
getBluetoothBatteryStats()1765     public BluetoothBatteryStats getBluetoothBatteryStats() {
1766         final long elapsedRealtimeUs = mClock.elapsedRealtime() * 1000;
1767         ArrayList<BluetoothBatteryStats.UidStats> uidStats = new ArrayList<>();
1768         for (int i = mUidStats.size() - 1; i >= 0; i--) {
1769             final Uid uid = mUidStats.valueAt(i);
1770             final Timer scanTimer = uid.getBluetoothScanTimer();
1771             final long scanTimeMs =
1772                     scanTimer != null ? scanTimer.getTotalTimeLocked(
1773                             elapsedRealtimeUs, STATS_SINCE_CHARGED) / 1000 : 0;
1774 
1775             final Timer unoptimizedScanTimer = uid.getBluetoothUnoptimizedScanTimer();
1776             final long unoptimizedScanTimeMs =
1777                     unoptimizedScanTimer != null ? unoptimizedScanTimer.getTotalTimeLocked(
1778                             elapsedRealtimeUs, STATS_SINCE_CHARGED) / 1000 : 0;
1779 
1780             final Counter scanResultCounter = uid.getBluetoothScanResultCounter();
1781             final int scanResultCount =
1782                     scanResultCounter != null ? scanResultCounter.getCountLocked(
1783                             STATS_SINCE_CHARGED) : 0;
1784 
1785             final ControllerActivityCounter counter = uid.getBluetoothControllerActivity();
1786             final long rxTimeMs =  counter != null ? counter.getRxTimeCounter().getCountLocked(
1787                     STATS_SINCE_CHARGED) : 0;
1788             final long txTimeMs =  counter != null ? counter.getTxTimeCounters()[0].getCountLocked(
1789                     STATS_SINCE_CHARGED) : 0;
1790 
1791             if (scanTimeMs != 0 || unoptimizedScanTimeMs != 0 || scanResultCount != 0
1792                     || rxTimeMs != 0 || txTimeMs != 0) {
1793                 uidStats.add(new BluetoothBatteryStats.UidStats(uid.getUid(),
1794                         scanTimeMs,
1795                         unoptimizedScanTimeMs,
1796                         scanResultCount,
1797                         rxTimeMs,
1798                         txTimeMs));
1799             }
1800         }
1801 
1802         return new BluetoothBatteryStats(uidStats);
1803     }
1804 
1805     String mLastWakeupReason = null;
1806     long mLastWakeupUptimeMs = 0;
1807     long mLastWakeupElapsedTimeMs = 0;
1808     private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
1809 
getWakeupReasonStats()1810     public Map<String, ? extends Timer> getWakeupReasonStats() {
1811         return mWakeupReasonStats;
1812     }
1813 
1814     @Override
getUahDischarge(int which)1815     public long getUahDischarge(int which) {
1816         return mDischargeCounter.getCountLocked(which);
1817     }
1818 
1819     @Override
getUahDischargeScreenOff(int which)1820     public long getUahDischargeScreenOff(int which) {
1821         return mDischargeScreenOffCounter.getCountLocked(which);
1822     }
1823 
1824     @Override
getUahDischargeScreenDoze(int which)1825     public long getUahDischargeScreenDoze(int which) {
1826         return mDischargeScreenDozeCounter.getCountLocked(which);
1827     }
1828 
1829     @Override
getUahDischargeLightDoze(int which)1830     public long getUahDischargeLightDoze(int which) {
1831         return mDischargeLightDozeCounter.getCountLocked(which);
1832     }
1833 
1834     @Override
getUahDischargeDeepDoze(int which)1835     public long getUahDischargeDeepDoze(int which) {
1836         return mDischargeDeepDozeCounter.getCountLocked(which);
1837     }
1838 
1839     @Override
getEstimatedBatteryCapacity()1840     public int getEstimatedBatteryCapacity() {
1841         return mEstimatedBatteryCapacityMah;
1842     }
1843 
1844     @Override
getLearnedBatteryCapacity()1845     public int getLearnedBatteryCapacity() {
1846         return mLastLearnedBatteryCapacityUah;
1847     }
1848 
1849     @Override
getMinLearnedBatteryCapacity()1850     public int getMinLearnedBatteryCapacity() {
1851         return mMinLearnedBatteryCapacityUah;
1852     }
1853 
1854     @Override
getMaxLearnedBatteryCapacity()1855     public int getMaxLearnedBatteryCapacity() {
1856         return mMaxLearnedBatteryCapacityUah;
1857     }
1858 
1859     public static class FrameworkStatsLogger {
uidProcessStateChanged(int uid, int state)1860         public void uidProcessStateChanged(int uid, int state) {
1861             // TODO(b/155216561): It is possible for isolated uids to be in a higher
1862             // state than its parent uid. We should track the highest state within the union of host
1863             // and isolated uids rather than only the parent uid.
1864             FrameworkStatsLog.write(FrameworkStatsLog.UID_PROCESS_STATE_CHANGED, uid,
1865                     ActivityManager.processStateAmToProto(state));
1866         }
1867 
wakelockStateChanged(int uid, WorkChain wc, String name, int procState, boolean acquired, int powerManagerWakeLockLevel)1868         public void wakelockStateChanged(int uid, WorkChain wc, String name,
1869                 int procState, boolean acquired, int powerManagerWakeLockLevel) {
1870             int event = acquired
1871                     ? FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE
1872                     : FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE;
1873             if (wc != null) {
1874                 FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(),
1875                         wc.getTags(), powerManagerWakeLockLevel, name, event, procState);
1876             } else {
1877                 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, uid,
1878                         null, powerManagerWakeLockLevel, name, event, procState);
1879             }
1880         }
1881 
kernelWakeupReported(long deltaUptimeUs, String lastWakeupReason, long lastWakeupElapsedTimeMs)1882         public void kernelWakeupReported(long deltaUptimeUs, String lastWakeupReason,
1883                 long lastWakeupElapsedTimeMs) {
1884             FrameworkStatsLog.write(FrameworkStatsLog.KERNEL_WAKEUP_REPORTED, lastWakeupReason,
1885                     /* duration_usec */ deltaUptimeUs, lastWakeupElapsedTimeMs);
1886         }
1887 
gpsScanStateChanged(int uid, WorkChain workChain, boolean stateOn)1888         public void gpsScanStateChanged(int uid, WorkChain workChain, boolean stateOn) {
1889             int event = stateOn
1890                     ? FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON
1891                     : FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF;
1892             if (workChain != null) {
1893                 FrameworkStatsLog.write(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
1894                         workChain.getUids(), workChain.getTags(), event);
1895             } else {
1896                 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
1897                         uid, null, event);
1898             }
1899         }
1900 
batterySaverModeChanged(boolean enabled)1901         public void batterySaverModeChanged(boolean enabled) {
1902             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
1903                     enabled
1904                             ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
1905                             : FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
1906         }
1907 
deviceIdlingModeStateChanged(int mode)1908         public void deviceIdlingModeStateChanged(int mode) {
1909             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLING_MODE_STATE_CHANGED, mode);
1910         }
1911 
deviceIdleModeStateChanged(int mode)1912         public void deviceIdleModeStateChanged(int mode) {
1913             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mode);
1914         }
1915 
chargingStateChanged(int status)1916         public void chargingStateChanged(int status) {
1917             FrameworkStatsLog.write(FrameworkStatsLog.CHARGING_STATE_CHANGED, status);
1918         }
1919 
pluggedStateChanged(int plugType)1920         public void pluggedStateChanged(int plugType) {
1921             FrameworkStatsLog.write(FrameworkStatsLog.PLUGGED_STATE_CHANGED, plugType);
1922         }
1923 
batteryLevelChanged(int level)1924         public void batteryLevelChanged(int level) {
1925             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_LEVEL_CHANGED, level);
1926         }
1927 
phoneServiceStateChanged(int state, int simState, int strengthBin)1928         public void phoneServiceStateChanged(int state, int simState, int strengthBin) {
1929             FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
1930                     simState, strengthBin);
1931         }
1932 
phoneSignalStrengthChanged(int strengthBin)1933         public void phoneSignalStrengthChanged(int strengthBin) {
1934             FrameworkStatsLog.write(
1935                     FrameworkStatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
1936         }
1937 
1938         /**
1939          * Records a statsd event when the batterystats config file is written to disk.
1940          */
writeCommitSysConfigFile(String fileName, long durationMs)1941         public void writeCommitSysConfigFile(String fileName, long durationMs) {
1942             com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(fileName,
1943                     durationMs);
1944         }
1945     }
1946 
1947     private final FrameworkStatsLogger mFrameworkStatsLogger;
1948 
initKernelStatsReaders()1949     private void initKernelStatsReaders() {
1950         if (!isKernelStatsAvailable()) {
1951             return;
1952         }
1953 
1954         mCpuUidUserSysTimeReader = new KernelCpuUidUserSysTimeReader(true, mClock);
1955         mCpuUidFreqTimeReader = new KernelCpuUidFreqTimeReader(true, mClock);
1956         mCpuUidActiveTimeReader = new KernelCpuUidActiveTimeReader(true, mClock);
1957         mCpuUidClusterTimeReader = new KernelCpuUidClusterTimeReader(true, mClock);
1958         mKernelWakelockReader = new KernelWakelockReader();
1959         if (!Flags.disableSystemServicePowerAttr()) {
1960             mSystemServerCpuThreadReader = SystemServerCpuThreadReader.create();
1961         }
1962         mKernelMemoryBandwidthStats = new KernelMemoryBandwidthStats();
1963         mTmpRailStats = new RailStats();
1964     }
1965 
1966     private class PowerStatsCollectorInjector implements CpuPowerStatsCollector.Injector,
1967             MobileRadioPowerStatsCollector.Injector, WifiPowerStatsCollector.Injector,
1968             BluetoothPowerStatsCollector.Injector, EnergyConsumerPowerStatsCollector.Injector {
1969         private PackageManager mPackageManager;
1970         private PowerStatsCollector.ConsumedEnergyRetriever mConsumedEnergyRetriever;
1971         private NetworkStatsManager mNetworkStatsManager;
1972         private TelephonyManager mTelephonyManager;
1973         private WifiManager mWifiManager;
1974         private BluetoothPowerStatsCollector.BluetoothStatsRetriever mBluetoothStatsRetriever;
1975 
setContext(Context context)1976         void setContext(Context context) {
1977             mPackageManager = context.getPackageManager();
1978             mConsumedEnergyRetriever = new PowerStatsCollector.ConsumedEnergyRetrieverImpl(
1979                     LocalServices.getService(PowerStatsInternal.class));
1980             mNetworkStatsManager = context.getSystemService(NetworkStatsManager.class);
1981             mTelephonyManager = context.getSystemService(TelephonyManager.class);
1982             mWifiManager = context.getSystemService(WifiManager.class);
1983             mBluetoothStatsRetriever = new BluetoothStatsRetrieverImpl(
1984                     context.getSystemService(BluetoothManager.class));
1985         }
1986 
1987         @Override
getHandler()1988         public Handler getHandler() {
1989             return mHandler;
1990         }
1991 
1992         @Override
getClock()1993         public Clock getClock() {
1994             return mClock;
1995         }
1996 
1997         @Override
getPowerStatsCollectionThrottlePeriod(String powerComponentName)1998         public long getPowerStatsCollectionThrottlePeriod(String powerComponentName) {
1999             return mBatteryStatsConfig.getPowerStatsThrottlePeriod(powerComponentName);
2000         }
2001 
2002         @Override
getUidResolver()2003         public PowerStatsUidResolver getUidResolver() {
2004             return mPowerStatsUidResolver;
2005         }
2006 
2007         @Override
getCpuScalingPolicies()2008         public CpuScalingPolicies getCpuScalingPolicies() {
2009             return mCpuScalingPolicies;
2010         }
2011 
2012         @Override
getPowerProfile()2013         public PowerProfile getPowerProfile() {
2014             return mPowerProfile;
2015         }
2016 
2017         @Override
getKernelCpuStatsReader()2018         public CpuPowerStatsCollector.KernelCpuStatsReader getKernelCpuStatsReader() {
2019             return new CpuPowerStatsCollector.KernelCpuStatsReader();
2020         }
2021 
2022         @Override
getPackageManager()2023         public PackageManager getPackageManager() {
2024             return mPackageManager;
2025         }
2026 
2027         @Override
getConsumedEnergyRetriever()2028         public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
2029             return mConsumedEnergyRetriever;
2030         }
2031 
2032         @Override
getVoltageSupplier()2033         public IntSupplier getVoltageSupplier() {
2034             return () -> mBatteryVoltageMv;
2035         }
2036 
2037         @Override
getMobileNetworkStatsSupplier()2038         public Supplier<NetworkStats> getMobileNetworkStatsSupplier() {
2039             return () -> readMobileNetworkStatsLocked(mNetworkStatsManager);
2040         }
2041 
2042         @Override
getWifiNetworkStatsSupplier()2043         public Supplier<NetworkStats> getWifiNetworkStatsSupplier() {
2044             return () -> readWifiNetworkStatsLocked(mNetworkStatsManager);
2045         }
2046 
2047         @Override
getWifiStatsRetriever()2048         public WifiPowerStatsCollector.WifiStatsRetriever getWifiStatsRetriever() {
2049             return mWifiStatsRetriever;
2050         }
2051 
2052         @Override
getTelephonyManager()2053         public TelephonyManager getTelephonyManager() {
2054             return mTelephonyManager;
2055         }
2056 
2057         @Override
getWifiManager()2058         public WifiManager getWifiManager() {
2059             return mWifiManager;
2060         }
2061 
2062         @Override
getBluetoothStatsRetriever()2063         public BluetoothPowerStatsCollector.BluetoothStatsRetriever getBluetoothStatsRetriever() {
2064             return mBluetoothStatsRetriever;
2065         }
2066 
2067         @Override
getCallDurationSupplier()2068         public LongSupplier getCallDurationSupplier() {
2069             return () -> mPhoneOnTimer.getTotalTimeLocked(mClock.elapsedRealtime() * 1000,
2070                     STATS_SINCE_CHARGED);
2071         }
2072 
2073         @Override
getPhoneSignalScanDurationSupplier()2074         public LongSupplier getPhoneSignalScanDurationSupplier() {
2075             return () -> mPhoneSignalScanningTimer.getTotalTimeLocked(
2076                     mClock.elapsedRealtime() * 1000, STATS_SINCE_CHARGED);
2077         }
2078     }
2079 
2080     private final PowerStatsCollectorInjector mPowerStatsCollectorInjector =
2081             new PowerStatsCollectorInjector();
2082 
2083     /**
2084      * TimeBase observer.
2085      */
2086     public interface TimeBaseObs {
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2087         void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs);
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2088         void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs);
2089 
2090         /**
2091          * Reset the observer's state, returns true if the timer/counter is inactive
2092          * so it can be destroyed.
2093          * @param detachIfReset detach if true, no-op if false.
2094          * @return Returns true if the timer/counter is inactive and can be destroyed.
2095          */
reset(boolean detachIfReset)2096         default boolean reset(boolean detachIfReset) {
2097             return reset(detachIfReset, SystemClock.elapsedRealtime() * 1000);
2098         }
2099 
2100         /**
2101          * @see #reset(boolean)
2102          * @param detachIfReset detach if true, no-op if false.
2103          * @param elapsedRealtimeUs the timestamp when this reset is actually reequested
2104          * @return Returns true if the timer/counter is inactive and can be destroyed.
2105          */
reset(boolean detachIfReset, long elapsedRealtimeUs)2106         boolean reset(boolean detachIfReset, long elapsedRealtimeUs);
2107 
2108         /**
2109          * Detach the observer from TimeBase.
2110          */
detach()2111         void detach();
2112     }
2113 
2114     // methods are protected not private to be VisibleForTesting
2115     public static class TimeBase {
2116         protected final Collection<TimeBaseObs> mObservers;
2117 
2118         // All below time metrics are in microseconds.
2119         protected long mUptimeUs;
2120         protected long mRealtimeUs;
2121 
2122         protected boolean mRunning;
2123 
2124         protected long mPastUptimeUs;
2125         protected long mUptimeStartUs;
2126         protected long mPastRealtimeUs;
2127         protected long mRealtimeStartUs;
2128         protected long mUnpluggedUptimeUs;
2129         protected long mUnpluggedRealtimeUs;
2130 
dump(PrintWriter pw, String prefix)2131         public void dump(PrintWriter pw, String prefix) {
2132             StringBuilder sb = new StringBuilder(128);
2133             pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
2134             sb.setLength(0);
2135             sb.append(prefix);
2136                     sb.append("mUptime=");
2137                     formatTimeMs(sb, mUptimeUs / 1000);
2138             pw.println(sb.toString());
2139             sb.setLength(0);
2140             sb.append(prefix);
2141                     sb.append("mRealtime=");
2142                     formatTimeMs(sb, mRealtimeUs / 1000);
2143             pw.println(sb.toString());
2144             sb.setLength(0);
2145             sb.append(prefix);
2146                     sb.append("mPastUptime=");
2147                     formatTimeMs(sb, mPastUptimeUs / 1000); sb.append("mUptimeStart=");
2148                     formatTimeMs(sb, mUptimeStartUs / 1000);
2149                     sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptimeUs / 1000);
2150             pw.println(sb.toString());
2151             sb.setLength(0);
2152             sb.append(prefix);
2153                     sb.append("mPastRealtime=");
2154                     formatTimeMs(sb, mPastRealtimeUs / 1000); sb.append("mRealtimeStart=");
2155                     formatTimeMs(sb, mRealtimeStartUs / 1000);
2156                     sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtimeUs / 1000);
2157             pw.println(sb.toString());
2158         }
2159         /**
2160          * The mObservers of TimeBase in BatteryStatsImpl object can contain up to 20k entries.
2161          * The mObservers of TimeBase in BatteryStatsImpl.Uid object only contains a few or tens of
2162          * entries.
2163          * mObservers must have good performance on add(), remove(), also be memory efficient.
2164          * This is why we provide isLongList parameter for long and short list user cases.
2165          * @param isLongList If true, use HashSet for mObservers list.
2166          *                   If false, use ArrayList for mObservers list.
2167         */
TimeBase(boolean isLongList)2168         public TimeBase(boolean isLongList) {
2169             mObservers = isLongList ? new HashSet<>() : new ArrayList<>();
2170         }
2171 
TimeBase()2172         public TimeBase() {
2173             this(false);
2174         }
2175 
add(TimeBaseObs observer)2176         public void add(TimeBaseObs observer) {
2177             mObservers.add(observer);
2178         }
2179 
remove(TimeBaseObs observer)2180         public void remove(TimeBaseObs observer) {
2181             mObservers.remove(observer);
2182         }
2183 
hasObserver(TimeBaseObs observer)2184         public boolean hasObserver(TimeBaseObs observer) {
2185             return mObservers.contains(observer);
2186         }
2187 
init(long uptimeUs, long elapsedRealtimeUs)2188         public void init(long uptimeUs, long elapsedRealtimeUs) {
2189             mRealtimeUs = 0;
2190             mUptimeUs = 0;
2191             mPastUptimeUs = 0;
2192             mPastRealtimeUs = 0;
2193             mUptimeStartUs = uptimeUs;
2194             mRealtimeStartUs = elapsedRealtimeUs;
2195             mUnpluggedUptimeUs = getUptime(mUptimeStartUs);
2196             mUnpluggedRealtimeUs = getRealtime(mRealtimeStartUs);
2197         }
2198 
reset(long uptimeUs, long elapsedRealtimeUs)2199         public void reset(long uptimeUs, long elapsedRealtimeUs) {
2200             if (!mRunning) {
2201                 mPastUptimeUs = 0;
2202                 mPastRealtimeUs = 0;
2203             } else {
2204                 mUptimeStartUs = uptimeUs;
2205                 mRealtimeStartUs = elapsedRealtimeUs;
2206                 // TODO: Since mUptimeStartUs was just reset and we are running, getUptime will
2207                 // just return mPastUptimeUs. Also, are we sure we don't want to reset that?
2208                 mUnpluggedUptimeUs = getUptime(uptimeUs);
2209                 // TODO: likewise.
2210                 mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs);
2211             }
2212         }
2213 
computeUptime(long curTimeUs, int which)2214         public long computeUptime(long curTimeUs, int which) {
2215             return mUptimeUs + getUptime(curTimeUs);
2216         }
2217 
computeRealtime(long curTimeUs, int which)2218         public long computeRealtime(long curTimeUs, int which) {
2219             return mRealtimeUs + getRealtime(curTimeUs);
2220         }
2221 
getUptime(long curTimeUs)2222         public long getUptime(long curTimeUs) {
2223             long time = mPastUptimeUs;
2224             if (mRunning) {
2225                 time += curTimeUs - mUptimeStartUs;
2226             }
2227             return time;
2228         }
2229 
getRealtime(long curTimeUs)2230         public long getRealtime(long curTimeUs) {
2231             long time = mPastRealtimeUs;
2232             if (mRunning) {
2233                 time += curTimeUs - mRealtimeStartUs;
2234             }
2235             return time;
2236         }
2237 
getUptimeStart()2238         public long getUptimeStart() {
2239             return mUptimeStartUs;
2240         }
2241 
getRealtimeStart()2242         public long getRealtimeStart() {
2243             return mRealtimeStartUs;
2244         }
2245 
isRunning()2246         public boolean isRunning() {
2247             return mRunning;
2248         }
2249 
setRunning(boolean running, long uptimeUs, long elapsedRealtimeUs)2250         public boolean setRunning(boolean running, long uptimeUs, long elapsedRealtimeUs) {
2251             if (mRunning != running) {
2252                 mRunning = running;
2253                 if (running) {
2254                     mUptimeStartUs = uptimeUs;
2255                     mRealtimeStartUs = elapsedRealtimeUs;
2256                     long batteryUptimeUs = mUnpluggedUptimeUs = getUptime(uptimeUs);
2257                     long batteryRealtimeUs = mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs);
2258                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
2259                     // Iterator object, here is an exception because mObservers' type is Collection
2260                     // instead of list.
2261                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
2262                     while (iter.hasNext()) {
2263                         iter.next().onTimeStarted(
2264                                 elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs);
2265                     }
2266                 } else {
2267                     mPastUptimeUs += uptimeUs - mUptimeStartUs;
2268                     mPastRealtimeUs += elapsedRealtimeUs - mRealtimeStartUs;
2269                     long batteryUptimeUs = getUptime(uptimeUs);
2270                     long batteryRealtimeUs = getRealtime(elapsedRealtimeUs);
2271                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
2272                     // Iterator object, here is an exception because mObservers' type is Collection
2273                     // instead of list.
2274                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
2275                     while (iter.hasNext()) {
2276                         iter.next().onTimeStopped(
2277                                 elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs);
2278                     }
2279                 }
2280                 return true;
2281             }
2282             return false;
2283         }
2284 
readSummaryFromParcel(Parcel in)2285         public void readSummaryFromParcel(Parcel in) {
2286             mUptimeUs = in.readLong();
2287             mRealtimeUs = in.readLong();
2288         }
2289 
writeSummaryToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs)2290         public void writeSummaryToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
2291             out.writeLong(computeUptime(uptimeUs, STATS_SINCE_CHARGED));
2292             out.writeLong(computeRealtime(elapsedRealtimeUs, STATS_SINCE_CHARGED));
2293         }
2294 
readFromParcel(Parcel in)2295         public void readFromParcel(Parcel in) {
2296             mRunning = false;
2297             mUptimeUs = in.readLong();
2298             mPastUptimeUs = in.readLong();
2299             mUptimeStartUs = in.readLong();
2300             mRealtimeUs = in.readLong();
2301             mPastRealtimeUs = in.readLong();
2302             mRealtimeStartUs = in.readLong();
2303             mUnpluggedUptimeUs = in.readLong();
2304             mUnpluggedRealtimeUs = in.readLong();
2305         }
2306 
writeToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs)2307         public void writeToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
2308             final long runningUptime = getUptime(uptimeUs);
2309             final long runningRealtime = getRealtime(elapsedRealtimeUs);
2310             out.writeLong(mUptimeUs);
2311             out.writeLong(runningUptime);
2312             out.writeLong(mUptimeStartUs);
2313             out.writeLong(mRealtimeUs);
2314             out.writeLong(runningRealtime);
2315             out.writeLong(mRealtimeStartUs);
2316             out.writeLong(mUnpluggedUptimeUs);
2317             out.writeLong(mUnpluggedRealtimeUs);
2318         }
2319     }
2320 
2321     /**
2322      * State for keeping track of counting information.
2323      */
2324     public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
2325         final AtomicInteger mCount = new AtomicInteger();
2326         final TimeBase mTimeBase;
2327 
Counter(TimeBase timeBase, Parcel in)2328         public Counter(TimeBase timeBase, Parcel in) {
2329             mTimeBase = timeBase;
2330             mCount.set(in.readInt());
2331             timeBase.add(this);
2332         }
2333 
Counter(TimeBase timeBase)2334         public Counter(TimeBase timeBase) {
2335             mTimeBase = timeBase;
2336             timeBase.add(this);
2337         }
2338 
writeToParcel(Parcel out)2339         public void writeToParcel(Parcel out) {
2340             out.writeInt(mCount.get());
2341         }
2342 
2343         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2344         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2345         }
2346 
2347         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2348         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2349         }
2350 
2351         @Override
getCountLocked(int which)2352         public int getCountLocked(int which) {
2353             return mCount.get();
2354         }
2355 
logState(Printer pw, String prefix)2356         public void logState(Printer pw, String prefix) {
2357             pw.println(prefix + "mCount=" + mCount.get());
2358         }
2359 
2360         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
stepAtomic()2361         public void stepAtomic() {
2362             if (mTimeBase.isRunning()) {
2363                 mCount.incrementAndGet();
2364             }
2365         }
2366 
addAtomic(int delta)2367         void addAtomic(int delta) {
2368             if (mTimeBase.isRunning()) {
2369                 mCount.addAndGet(delta);
2370             }
2371         }
2372 
2373         /**
2374          * Clear state of this counter.
2375          */
2376         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2377         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2378             mCount.set(0);
2379             if (detachIfReset) {
2380                 detach();
2381             }
2382             return true;
2383         }
2384 
2385         @Override
detach()2386         public void detach() {
2387             mTimeBase.remove(this);
2388         }
2389 
2390         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
writeSummaryFromParcelLocked(Parcel out)2391         public void writeSummaryFromParcelLocked(Parcel out) {
2392             out.writeInt(mCount.get());
2393         }
2394 
2395         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
readSummaryFromParcelLocked(Parcel in)2396         public void readSummaryFromParcelLocked(Parcel in) {
2397             mCount.set(in.readInt());
2398         }
2399     }
2400 
2401     @VisibleForTesting
2402     public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
2403         final TimeBase mTimeBase;
2404         public long[] mCounts;
2405 
LongSamplingCounterArray(TimeBase timeBase, Parcel in)2406         private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
2407             mTimeBase = timeBase;
2408             mCounts = in.createLongArray();
2409             timeBase.add(this);
2410         }
2411 
LongSamplingCounterArray(TimeBase timeBase)2412         public LongSamplingCounterArray(TimeBase timeBase) {
2413             mTimeBase = timeBase;
2414             timeBase.add(this);
2415         }
2416 
writeToParcel(Parcel out)2417         private void writeToParcel(Parcel out) {
2418             out.writeLongArray(mCounts);
2419         }
2420 
2421         @Override
onTimeStarted(long elapsedRealTimeUs, long baseUptimeUs, long baseRealtimeUs)2422         public void onTimeStarted(long elapsedRealTimeUs, long baseUptimeUs, long baseRealtimeUs) {
2423         }
2424 
2425         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2426         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2427         }
2428 
2429         @Override
getCountsLocked(int which)2430         public long[] getCountsLocked(int which) {
2431             return mCounts == null ? null : Arrays.copyOf(mCounts, mCounts.length);
2432         }
2433 
2434         @Override
logState(Printer pw, String prefix)2435         public void logState(Printer pw, String prefix) {
2436             pw.println(prefix + "mCounts=" + Arrays.toString(mCounts));
2437         }
2438 
addCountLocked(long[] counts)2439         public void addCountLocked(long[] counts) {
2440             addCountLocked(counts, mTimeBase.isRunning());
2441         }
2442 
addCountLocked(long[] counts, boolean isRunning)2443         public void addCountLocked(long[] counts, boolean isRunning) {
2444             if (counts == null) {
2445                 return;
2446             }
2447             if (isRunning) {
2448                 if (mCounts == null) {
2449                     mCounts = new long[counts.length];
2450                 }
2451                 for (int i = 0; i < counts.length; ++i) {
2452                     mCounts[i] += counts[i];
2453                 }
2454             }
2455         }
2456 
getSize()2457         public int getSize() {
2458             return mCounts == null ? 0 : mCounts.length;
2459         }
2460 
2461         /**
2462          * Clear state of this counter.
2463          */
2464         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2465         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2466             if (mCounts != null) {
2467                 Arrays.fill(mCounts, 0);
2468             }
2469             if (detachIfReset) {
2470                 detach();
2471             }
2472             return true;
2473         }
2474 
2475         @Override
detach()2476         public void detach() {
2477             mTimeBase.remove(this);
2478         }
2479 
writeSummaryToParcelLocked(Parcel out)2480         private void writeSummaryToParcelLocked(Parcel out) {
2481             out.writeLongArray(mCounts);
2482         }
2483 
readSummaryFromParcelLocked(Parcel in)2484         private void readSummaryFromParcelLocked(Parcel in) {
2485             mCounts = in.createLongArray();
2486         }
2487 
writeToParcel(Parcel out, LongSamplingCounterArray counterArray)2488         public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
2489             if (counterArray != null) {
2490                 out.writeInt(1);
2491                 counterArray.writeToParcel(out);
2492             } else {
2493                 out.writeInt(0);
2494             }
2495         }
2496 
readFromParcel(Parcel in, TimeBase timeBase)2497         public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
2498             if (in.readInt() != 0) {
2499                 return new LongSamplingCounterArray(timeBase, in);
2500             } else {
2501                 return null;
2502             }
2503         }
2504 
writeSummaryToParcelLocked(Parcel out, LongSamplingCounterArray counterArray)2505         public static void writeSummaryToParcelLocked(Parcel out,
2506                 LongSamplingCounterArray counterArray) {
2507             if (counterArray != null) {
2508                 out.writeInt(1);
2509                 counterArray.writeSummaryToParcelLocked(out);
2510             } else {
2511                 out.writeInt(0);
2512             }
2513         }
2514 
readSummaryFromParcelLocked(Parcel in, TimeBase timeBase)2515         public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
2516                 TimeBase timeBase) {
2517             if (in.readInt() != 0) {
2518                 final LongSamplingCounterArray counterArray
2519                         = new LongSamplingCounterArray(timeBase);
2520                 counterArray.readSummaryFromParcelLocked(in);
2521                 return counterArray;
2522             } else {
2523                 return null;
2524             }
2525         }
2526     }
2527 
2528     private static class TimeMultiStateCounter extends LongCounter implements TimeBaseObs {
2529         private final TimeBase mTimeBase;
2530         private final LongMultiStateCounter mCounter;
2531 
TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs)2532         private TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs) {
2533             this(timeBase, new LongMultiStateCounter(stateCount), timestampMs);
2534         }
2535 
TimeMultiStateCounter(TimeBase timeBase, LongMultiStateCounter counter, long timestampMs)2536         private TimeMultiStateCounter(TimeBase timeBase, LongMultiStateCounter counter,
2537                 long timestampMs) {
2538             mTimeBase = timeBase;
2539             mCounter = counter;
2540             mCounter.setEnabled(mTimeBase.isRunning(), timestampMs);
2541             timeBase.add(this);
2542         }
2543 
2544         @Nullable
readFromParcel(Parcel in, TimeBase timeBase, int stateCount, long timestampMs)2545         private static TimeMultiStateCounter readFromParcel(Parcel in, TimeBase timeBase,
2546                 int stateCount, long timestampMs) {
2547             LongMultiStateCounter counter = LongMultiStateCounter.CREATOR.createFromParcel(in);
2548             if (counter.getStateCount() != stateCount) {
2549                 return null;
2550             }
2551             return new TimeMultiStateCounter(timeBase, counter, timestampMs);
2552         }
2553 
writeToParcel(Parcel out)2554         private void writeToParcel(Parcel out) {
2555             mCounter.writeToParcel(out, 0);
2556         }
2557 
2558         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2559         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2560             mCounter.setEnabled(true, elapsedRealtimeUs / 1000);
2561         }
2562 
2563         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2564         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2565             mCounter.setEnabled(false, elapsedRealtimeUs / 1000);
2566         }
2567 
getStateCount()2568         public int getStateCount() {
2569             return mCounter.getStateCount();
2570         }
2571 
setState(@atteryConsumer.ProcessState int processState, long elapsedRealtimeMs)2572         private void setState(@BatteryConsumer.ProcessState int processState,
2573                 long elapsedRealtimeMs) {
2574             mCounter.setState(processState, elapsedRealtimeMs);
2575         }
2576 
update(long value, long timestampMs)2577         private long update(long value, long timestampMs) {
2578             return mCounter.updateValue(value, timestampMs);
2579         }
2580 
increment(long increment, long timestampMs)2581         private void increment(long increment, long timestampMs) {
2582             mCounter.incrementValue(increment, timestampMs);
2583         }
2584 
2585         /**
2586          * Returns accumulated count for the specified state.
2587          */
getCountForProcessState(@atteryConsumer.ProcessState int procState)2588         public long getCountForProcessState(@BatteryConsumer.ProcessState int procState) {
2589             return mCounter.getCount(procState);
2590         }
2591 
getTotalCountLocked()2592         public long getTotalCountLocked() {
2593             return mCounter.getTotalCount();
2594         }
2595 
2596         @Override
getCountLocked(int statsType)2597         public long getCountLocked(int statsType) {
2598             return getTotalCountLocked();
2599         }
2600 
2601         @Override
logState(Printer pw, String prefix)2602         public void logState(Printer pw, String prefix) {
2603             pw.println(prefix + "mCounter=" + mCounter);
2604         }
2605 
2606         /**
2607          * Clears state of this counter.
2608          */
2609         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2610         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2611             mCounter.reset();
2612             if (detachIfReset) {
2613                 detach();
2614             }
2615             return true;
2616         }
2617 
2618         @Override
detach()2619         public void detach() {
2620             mTimeBase.remove(this);
2621         }
2622     }
2623 
2624     private static class TimeInFreqMultiStateCounter implements TimeBaseObs {
2625         private final TimeBase mTimeBase;
2626         private final LongArrayMultiStateCounter mCounter;
2627 
TimeInFreqMultiStateCounter(TimeBase timeBase, int stateCount, int cpuFreqCount, long timestampMs)2628         private TimeInFreqMultiStateCounter(TimeBase timeBase, int stateCount, int cpuFreqCount,
2629                 long timestampMs) {
2630             this(timeBase, new LongArrayMultiStateCounter(stateCount, cpuFreqCount), timestampMs);
2631         }
2632 
TimeInFreqMultiStateCounter(TimeBase timeBase, LongArrayMultiStateCounter counter, long timestampMs)2633         private TimeInFreqMultiStateCounter(TimeBase timeBase, LongArrayMultiStateCounter counter,
2634                 long timestampMs) {
2635             mTimeBase = timeBase;
2636             mCounter = counter;
2637             mCounter.setEnabled(mTimeBase.isRunning(), timestampMs);
2638             timeBase.add(this);
2639         }
2640 
writeToParcel(Parcel out)2641         private void writeToParcel(Parcel out) {
2642             mCounter.writeToParcel(out, 0);
2643         }
2644 
2645         @Nullable
readFromParcel(Parcel in, TimeBase timeBase, int stateCount, int cpuFreqCount, long timestampMs)2646         private static TimeInFreqMultiStateCounter readFromParcel(Parcel in, TimeBase timeBase,
2647                 int stateCount, int cpuFreqCount, long timestampMs) {
2648             // Read the object from the Parcel, whether it's usable or not
2649             LongArrayMultiStateCounter counter =
2650                     LongArrayMultiStateCounter.CREATOR.createFromParcel(in);
2651             if (counter.getStateCount() != stateCount
2652                     || counter.getArrayLength() != cpuFreqCount) {
2653                 return null;
2654             }
2655             return new TimeInFreqMultiStateCounter(timeBase, counter, timestampMs);
2656         }
2657 
2658         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2659         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2660             mCounter.setEnabled(true, elapsedRealtimeUs / 1000);
2661         }
2662 
2663         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2664         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2665             mCounter.setEnabled(false, elapsedRealtimeUs / 1000);
2666         }
2667 
getCounter()2668         public LongArrayMultiStateCounter getCounter() {
2669             return mCounter;
2670         }
2671 
getStateCount()2672         public int getStateCount() {
2673             return mCounter.getStateCount();
2674         }
2675 
setTrackingEnabled(boolean enabled, long timestampMs)2676         public void setTrackingEnabled(boolean enabled, long timestampMs) {
2677             mCounter.setEnabled(enabled && mTimeBase.isRunning(), timestampMs);
2678         }
2679 
setState(int uidRunningState, long elapsedRealtimeMs)2680         private void setState(int uidRunningState, long elapsedRealtimeMs) {
2681             mCounter.setState(uidRunningState, elapsedRealtimeMs);
2682         }
2683 
2684         /**
2685          * Returns accumulated counts for the specified state, or false if all counts are zero.
2686          */
getCountsLocked(long[] counts, int procState)2687         public boolean getCountsLocked(long[] counts, int procState) {
2688             if (counts.length != mCounter.getArrayLength()) {
2689                 return false;
2690             }
2691 
2692             mCounter.getCounts(counts, procState);
2693 
2694             // Return counts only if at least one of the elements is non-zero.
2695             for (int i = counts.length - 1; i >= 0; --i) {
2696                 if (counts[i] != 0) {
2697                     return true;
2698                 }
2699             }
2700             return false;
2701         }
2702 
logState(Printer pw, String prefix)2703         public void logState(Printer pw, String prefix) {
2704             pw.println(prefix + "mCounter=" + mCounter);
2705         }
2706 
2707         /**
2708          * Clears state of this counter.
2709          */
2710         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2711         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2712             mCounter.reset();
2713             if (detachIfReset) {
2714                 detach();
2715             }
2716             return true;
2717         }
2718 
2719         @Override
detach()2720         public void detach() {
2721             mTimeBase.remove(this);
2722         }
2723     }
2724 
2725     @VisibleForTesting
2726     public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
2727         final TimeBase mTimeBase;
2728         private long mCount;
2729 
LongSamplingCounter(TimeBase timeBase, Parcel in)2730         public LongSamplingCounter(TimeBase timeBase, Parcel in) {
2731             mTimeBase = timeBase;
2732             mCount = in.readLong();
2733             timeBase.add(this);
2734         }
2735 
LongSamplingCounter(TimeBase timeBase)2736         public LongSamplingCounter(TimeBase timeBase) {
2737             mTimeBase = timeBase;
2738             timeBase.add(this);
2739         }
2740 
writeToParcel(Parcel out)2741         public void writeToParcel(Parcel out) {
2742             out.writeLong(mCount);
2743         }
2744 
2745         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2746         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2747         }
2748 
2749         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2750         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2751         }
2752 
getCountLocked(int which)2753         public long getCountLocked(int which) {
2754             return mCount;
2755         }
2756 
2757         @Override
getCountForProcessState(int procState)2758         public long getCountForProcessState(int procState) {
2759             if (procState == BatteryConsumer.PROCESS_STATE_ANY) {
2760                 return getCountLocked(STATS_SINCE_CHARGED);
2761             }
2762             return 0;
2763         }
2764 
2765         @Override
logState(Printer pw, String prefix)2766         public void logState(Printer pw, String prefix) {
2767             pw.println(prefix + "mCount=" + mCount);
2768         }
2769 
addCountLocked(long count)2770         public void addCountLocked(long count) {
2771             addCountLocked(count, mTimeBase.isRunning());
2772         }
2773 
addCountLocked(long count, boolean isRunning)2774         public void addCountLocked(long count, boolean isRunning) {
2775             if (isRunning) {
2776                 mCount += count;
2777             }
2778         }
2779 
2780         /**
2781          * Clear state of this counter.
2782          */
2783         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2784         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2785             mCount = 0;
2786             if (detachIfReset) {
2787                 detach();
2788             }
2789             return true;
2790         }
2791 
2792         @Override
detach()2793         public void detach() {
2794             mTimeBase.remove(this);
2795         }
2796 
writeSummaryFromParcelLocked(Parcel out)2797         public void writeSummaryFromParcelLocked(Parcel out) {
2798             out.writeLong(mCount);
2799         }
2800 
readSummaryFromParcelLocked(Parcel in)2801         public void readSummaryFromParcelLocked(Parcel in) {
2802             mCount = in.readLong();
2803         }
2804     }
2805 
2806     /**
2807      * State for keeping track of timing information.
2808      */
2809     public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
2810         protected final Clock mClock;
2811         protected final int mType;
2812         protected final TimeBase mTimeBase;
2813 
2814         protected int mCount;
2815 
2816         // Times are in microseconds for better accuracy when dividing by the
2817         // lock count, and are in "battery realtime" units.
2818 
2819         /**
2820          * The total time we have accumulated since the start of the original
2821          * boot, to the last time something interesting happened in the
2822          * current run.
2823          */
2824         protected long mTotalTimeUs;
2825 
2826         /**
2827          * The total time this timer has been running until the latest mark has been set.
2828          * Subtract this from mTotalTimeUs to get the time spent running since the mark was set.
2829          */
2830         protected long mTimeBeforeMarkUs;
2831 
2832         /**
2833          * Constructs from a parcel.
2834          * @param type
2835          * @param timeBase
2836          * @param in
2837          */
Timer(Clock clock, int type, TimeBase timeBase, Parcel in)2838         public Timer(Clock clock, int type, TimeBase timeBase, Parcel in) {
2839             mClock = clock;
2840             mType = type;
2841             mTimeBase = timeBase;
2842 
2843             mCount = in.readInt();
2844             mTotalTimeUs = in.readLong();
2845             mTimeBeforeMarkUs = in.readLong();
2846             timeBase.add(this);
2847             if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTimeUs);
2848         }
2849 
Timer(Clock clock, int type, TimeBase timeBase)2850         public Timer(Clock clock, int type, TimeBase timeBase) {
2851             mClock = clock;
2852             mType = type;
2853             mTimeBase = timeBase;
2854             timeBase.add(this);
2855         }
2856 
writeToParcel(Parcel out, long elapsedRealtimeUs)2857         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2858             if (DEBUG) {
2859                 Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
2860                         + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2861                                 elapsedRealtimeUs));
2862             }
2863             out.writeInt(computeCurrentCountLocked());
2864             out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2865                         elapsedRealtimeUs));
2866             out.writeLong(mTimeBeforeMarkUs);
2867         }
2868 
computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs)2869         protected abstract long computeRunTimeLocked(long curBatteryRealtime,
2870                 long elapsedRealtimeUs);
2871 
computeCurrentCountLocked()2872         protected abstract int computeCurrentCountLocked();
2873 
2874         /**
2875          * Clear state of this timer.  Returns true if the timer is inactive
2876          * so can be completely dropped.
2877          */
2878         @Override
reset(boolean detachIfReset)2879         public boolean reset(boolean detachIfReset) {
2880             return reset(detachIfReset, mClock.elapsedRealtime() * 1000);
2881         }
2882 
2883         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2884         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2885             mTotalTimeUs = mTimeBeforeMarkUs = 0;
2886             mCount = 0;
2887             if (detachIfReset) {
2888                 detach();
2889             }
2890             return true;
2891         }
2892 
2893         @Override
detach()2894         public void detach() {
2895             mTimeBase.remove(this);
2896         }
2897 
2898         @Override
onTimeStarted(long elapsedRealtimeUs, long timeBaseUptimeUs, long baseRealtimeUs)2899         public void onTimeStarted(long elapsedRealtimeUs, long timeBaseUptimeUs,
2900                 long baseRealtimeUs) {
2901         }
2902 
2903         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2904         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2905             if (DEBUG && mType < 0) {
2906                 Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtimeUs
2907                         + " old mTotalTime=" + mTotalTimeUs);
2908             }
2909             mTotalTimeUs = computeRunTimeLocked(baseRealtimeUs, elapsedRealtimeUs);
2910             mCount = computeCurrentCountLocked();
2911             if (DEBUG && mType < 0) {
2912                 Log.v(TAG, "plug #" + mType + ": new mTotalTime=" + mTotalTimeUs);
2913             }
2914         }
2915 
2916         /**
2917          * Writes a possibly null Timer to a Parcel.
2918          *
2919          * @param out the Parcel to be written to.
2920          * @param timer a Timer, or null.
2921          */
writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs)2922         public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
2923             if (timer == null) {
2924                 out.writeInt(0); // indicates null
2925                 return;
2926             }
2927             out.writeInt(1); // indicates non-null
2928             timer.writeToParcel(out, elapsedRealtimeUs);
2929         }
2930 
2931         @Override
getTotalTimeLocked(long elapsedRealtimeUs, int which)2932         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
2933             return computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2934                     elapsedRealtimeUs);
2935         }
2936 
2937         @Override
getCountLocked(int which)2938         public int getCountLocked(int which) {
2939             return computeCurrentCountLocked();
2940         }
2941 
2942         @Override
getTimeSinceMarkLocked(long elapsedRealtimeUs)2943         public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
2944             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2945                     elapsedRealtimeUs);
2946             return val - mTimeBeforeMarkUs;
2947         }
2948 
2949         @Override
logState(Printer pw, String prefix)2950         public void logState(Printer pw, String prefix) {
2951             pw.println(prefix + "mCount=" + mCount);
2952             pw.println(prefix + "mTotalTime=" + mTotalTimeUs);
2953         }
2954 
2955 
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2956         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2957             long runTimeUs = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2958                     elapsedRealtimeUs);
2959             out.writeLong(runTimeUs);
2960             out.writeInt(computeCurrentCountLocked());
2961         }
2962 
readSummaryFromParcelLocked(Parcel in)2963         public void readSummaryFromParcelLocked(Parcel in) {
2964             // Multiply by 1000 for backwards compatibility
2965             mTotalTimeUs = in.readLong();
2966             mCount = in.readInt();
2967             // When reading the summary, we set the mark to be the latest information.
2968             mTimeBeforeMarkUs = mTotalTimeUs;
2969         }
2970     }
2971 
2972     /**
2973      * A counter meant to accept monotonically increasing values to its {@link #update(long, int)}
2974      * method. The state of the timer according to its {@link TimeBase} will determine how much
2975      * of the value is recorded.
2976      *
2977      * If the value being recorded resets, {@link #endSample()} can be called in order to
2978      * account for the change. If the value passed in to {@link #update(long, int)} decreased
2979      * between calls, the {@link #endSample()} is automatically called and the new value is
2980      * expected to increase monotonically from that point on.
2981      */
2982     public static class SamplingTimer extends Timer {
2983 
2984         /**
2985          * The most recent reported count from /proc/wakelocks.
2986          */
2987         int mCurrentReportedCount;
2988 
2989         /**
2990          * The reported count from /proc/wakelocks when unplug() was last
2991          * called.
2992          */
2993         int mBaseReportedCount;
2994 
2995         /**
2996          * The most recent reported total_time from /proc/wakelocks.
2997          */
2998         long mCurrentReportedTotalTimeUs;
2999 
3000         /**
3001          * The reported total_time from /proc/wakelocks when unplug() was last
3002          * called.
3003          */
3004         long mBaseReportedTotalTimeUs;
3005 
3006         /**
3007          * Whether we are currently in a discharge cycle.
3008          */
3009         boolean mTimeBaseRunning;
3010 
3011         /**
3012          * Whether we are currently recording reported values.
3013          */
3014         boolean mTrackingReportedValues;
3015 
3016         /*
3017          * A sequence counter, incremented once for each update of the stats.
3018          */
3019         int mUpdateVersion;
3020 
3021         @VisibleForTesting
SamplingTimer(Clock clock, TimeBase timeBase, Parcel in)3022         public SamplingTimer(Clock clock, TimeBase timeBase, Parcel in) {
3023             super(clock, 0, timeBase, in);
3024             mCurrentReportedCount = in.readInt();
3025             mBaseReportedCount = in.readInt();
3026             mCurrentReportedTotalTimeUs = in.readLong();
3027             mBaseReportedTotalTimeUs = in.readLong();
3028             mTrackingReportedValues = in.readInt() == 1;
3029             mTimeBaseRunning = timeBase.isRunning();
3030         }
3031 
3032         @VisibleForTesting
SamplingTimer(Clock clock, TimeBase timeBase)3033         public SamplingTimer(Clock clock, TimeBase timeBase) {
3034             super(clock, 0, timeBase);
3035             mTrackingReportedValues = false;
3036             mTimeBaseRunning = timeBase.isRunning();
3037         }
3038 
3039         /**
3040          * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to
3041          * be less than the values used for a previous invocation.
3042          */
endSample()3043         public void endSample() {
3044             endSample(mClock.elapsedRealtime() * 1000);
3045         }
3046 
3047         /**
3048          * @see #endSample()
3049          */
endSample(long elapsedRealtimeUs)3050         public void endSample(long elapsedRealtimeUs) {
3051             mTotalTimeUs = computeRunTimeLocked(0 /* unused by us */, elapsedRealtimeUs);
3052             mCount = computeCurrentCountLocked();
3053             mBaseReportedTotalTimeUs = mCurrentReportedTotalTimeUs = 0;
3054             mBaseReportedCount = mCurrentReportedCount = 0;
3055             mTrackingReportedValues = false;
3056         }
3057 
setUpdateVersion(int version)3058         public void setUpdateVersion(int version) {
3059             mUpdateVersion = version;
3060         }
3061 
getUpdateVersion()3062         public int getUpdateVersion() {
3063             return mUpdateVersion;
3064         }
3065 
3066         /**
3067          * Updates the current recorded values. These are meant to be monotonically increasing
3068          * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}.
3069          *
3070          * If the values being recorded have been reset, the monotonically increasing requirement
3071          * will be broken. In this case, {@link #endSample()} is automatically called and
3072          * the total value of totalTimeUs and count are recorded, starting a new monotonically
3073          * increasing sample.
3074          *
3075          * @param totalTimeUs total time of sample in microseconds.
3076          * @param count total number of times the event being sampled occurred.
3077          */
update(long totalTimeUs, int count, long elapsedRealtimeUs)3078         public void update(long totalTimeUs, int count, long elapsedRealtimeUs) {
3079             update(totalTimeUs, 0, count, elapsedRealtimeUs);
3080         }
3081 
3082         /**
3083          * Updates the current recorded values. See {@link #update(long, int, long)}
3084          *
3085          * @param activeTimeUs Time that the currently active wake lock has been held.
3086          */
update(long totalTimeUs, long activeTimeUs, int count, long elapsedRealtimeUs)3087         public void update(long totalTimeUs, long activeTimeUs, int count,
3088                 long elapsedRealtimeUs) {
3089             if (mTimeBaseRunning && !mTrackingReportedValues) {
3090                 // Updating the reported value for the first time. If the wake lock is currently
3091                 // active, mark the time it was acquired as the base timestamp.
3092                 mBaseReportedTotalTimeUs = totalTimeUs - activeTimeUs;
3093                 mBaseReportedCount = activeTimeUs == 0 ? count : count - 1;
3094             }
3095 
3096             mTrackingReportedValues = true;
3097 
3098             if (totalTimeUs < mCurrentReportedTotalTimeUs || count < mCurrentReportedCount) {
3099                 endSample(elapsedRealtimeUs);
3100             }
3101 
3102             mCurrentReportedTotalTimeUs = totalTimeUs;
3103             mCurrentReportedCount = count;
3104         }
3105 
3106         /**
3107          * Adds deltaTime and deltaCount to the current sample.
3108          *
3109          * @param deltaTime additional time recorded since the last sampled event, in microseconds.
3110          * @param deltaCount additional number of times the event being sampled occurred.
3111          */
add(long deltaTimeUs, int deltaCount)3112         public void add(long deltaTimeUs, int deltaCount) {
3113             add(deltaTimeUs, deltaCount, mClock.elapsedRealtime() * 1000);
3114         }
3115 
3116         /**
3117          * @see #add(long, int)
3118          */
add(long deltaTimeUs, int deltaCount, long elapsedRealtimeUs)3119         public void add(long deltaTimeUs, int deltaCount, long elapsedRealtimeUs) {
3120             update(mCurrentReportedTotalTimeUs + deltaTimeUs, mCurrentReportedCount + deltaCount,
3121                     elapsedRealtimeUs);
3122         }
3123 
3124         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3125         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3126             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3127             if (mTrackingReportedValues) {
3128                 mBaseReportedTotalTimeUs = mCurrentReportedTotalTimeUs;
3129                 mBaseReportedCount = mCurrentReportedCount;
3130             }
3131             mTimeBaseRunning = true;
3132         }
3133 
3134         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3135         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3136             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3137             mTimeBaseRunning = false;
3138         }
3139 
3140         @Override
logState(Printer pw, String prefix)3141         public void logState(Printer pw, String prefix) {
3142             super.logState(pw, prefix);
3143             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
3144                     + " mBaseReportedCount=" + mBaseReportedCount
3145                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTimeUs
3146                     + " mBaseReportedTotalTimeUs=" + mBaseReportedTotalTimeUs);
3147         }
3148 
3149         @Override
computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs)3150         protected long computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs) {
3151             return mTotalTimeUs + (mTimeBaseRunning && mTrackingReportedValues
3152                     ? mCurrentReportedTotalTimeUs - mBaseReportedTotalTimeUs : 0);
3153         }
3154 
3155         @Override
computeCurrentCountLocked()3156         protected int computeCurrentCountLocked() {
3157             return mCount + (mTimeBaseRunning && mTrackingReportedValues
3158                     ? mCurrentReportedCount - mBaseReportedCount : 0);
3159         }
3160 
3161         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)3162         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3163             super.writeToParcel(out, elapsedRealtimeUs);
3164             out.writeInt(mCurrentReportedCount);
3165             out.writeInt(mBaseReportedCount);
3166             out.writeLong(mCurrentReportedTotalTimeUs);
3167             out.writeLong(mBaseReportedTotalTimeUs);
3168             out.writeInt(mTrackingReportedValues ? 1 : 0);
3169         }
3170 
3171         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3172         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3173             super.reset(detachIfReset, elapsedRealtimeUs);
3174             mTrackingReportedValues = false;
3175             mBaseReportedTotalTimeUs = 0;
3176             mBaseReportedCount = 0;
3177             return true;
3178         }
3179     }
3180 
3181     /**
3182      * A timer that increments in batches.  It does not run for durations, but just jumps
3183      * for a pre-determined amount.
3184      */
3185     public static class BatchTimer extends Timer {
3186         final Uid mUid;
3187 
3188         /**
3189          * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
3190          */
3191         long mLastAddedTimeUs;
3192 
3193         /**
3194          * The last duration that we added to the timer.  This is in microseconds.
3195          */
3196         long mLastAddedDurationUs;
3197 
3198         /**
3199          * Whether we are currently in a discharge cycle.
3200          */
3201         boolean mInDischarge;
3202 
BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase, Parcel in)3203         BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase, Parcel in) {
3204             super(clock, type, timeBase, in);
3205             mUid = uid;
3206             mLastAddedTimeUs = in.readLong();
3207             mLastAddedDurationUs = in.readLong();
3208             mInDischarge = timeBase.isRunning();
3209         }
3210 
BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase)3211         BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase) {
3212             super(clock, type, timeBase);
3213             mUid = uid;
3214             mInDischarge = timeBase.isRunning();
3215         }
3216 
3217         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)3218         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3219             super.writeToParcel(out, elapsedRealtimeUs);
3220             out.writeLong(mLastAddedTimeUs);
3221             out.writeLong(mLastAddedDurationUs);
3222         }
3223 
3224         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3225         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3226             recomputeLastDuration(elapsedRealtimeUs, false);
3227             mInDischarge = false;
3228             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3229         }
3230 
3231         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3232         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3233             recomputeLastDuration(elapsedRealtimeUs, false);
3234             mInDischarge = true;
3235             // If we are still within the last added duration, then re-added whatever remains.
3236             if (mLastAddedTimeUs == elapsedRealtimeUs) {
3237                 mTotalTimeUs += mLastAddedDurationUs;
3238             }
3239             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3240         }
3241 
3242         @Override
logState(Printer pw, String prefix)3243         public void logState(Printer pw, String prefix) {
3244             super.logState(pw, prefix);
3245             pw.println(prefix + "mLastAddedTime=" + mLastAddedTimeUs
3246                     + " mLastAddedDuration=" + mLastAddedDurationUs);
3247         }
3248 
computeOverage(long curTimeUs)3249         private long computeOverage(long curTimeUs) {
3250             if (mLastAddedTimeUs > 0) {
3251                 return mLastAddedDurationUs - curTimeUs;
3252             }
3253             return 0;
3254         }
3255 
recomputeLastDuration(long curTimeUs, boolean abort)3256         private void recomputeLastDuration(long curTimeUs, boolean abort) {
3257             final long overage = computeOverage(curTimeUs);
3258             if (overage > 0) {
3259                 // Aborting before the duration ran out -- roll back the remaining
3260                 // duration.  Only do this if currently discharging; otherwise we didn't
3261                 // actually add the time.
3262                 if (mInDischarge) {
3263                     mTotalTimeUs -= overage;
3264                 }
3265                 if (abort) {
3266                     mLastAddedTimeUs = 0;
3267                 } else {
3268                     mLastAddedTimeUs = curTimeUs;
3269                     mLastAddedDurationUs -= overage;
3270                 }
3271             }
3272         }
3273 
addDuration(long durationMs, long elapsedRealtimeMs)3274         public void addDuration(long durationMs, long elapsedRealtimeMs) {
3275             final long nowUs = elapsedRealtimeMs * 1000;
3276             recomputeLastDuration(nowUs, true);
3277             mLastAddedTimeUs = nowUs;
3278             mLastAddedDurationUs = durationMs * 1000;
3279             if (mInDischarge) {
3280                 mTotalTimeUs += mLastAddedDurationUs;
3281                 mCount++;
3282             }
3283         }
3284 
abortLastDuration(long elapsedRealtimeMs)3285         public void abortLastDuration(long elapsedRealtimeMs) {
3286             final long nowUs = elapsedRealtimeMs * 1000;
3287             recomputeLastDuration(nowUs, true);
3288         }
3289 
3290         @Override
computeCurrentCountLocked()3291         protected int computeCurrentCountLocked() {
3292             return mCount;
3293         }
3294 
3295         @Override
computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs)3296         protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) {
3297             final long overage = computeOverage(elapsedRealtimeUs);
3298             if (overage > 0) {
3299                 return mTotalTimeUs = overage;
3300             }
3301             return mTotalTimeUs;
3302         }
3303 
3304         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3305         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3306             recomputeLastDuration(elapsedRealtimeUs, true);
3307             boolean stillActive = mLastAddedTimeUs == elapsedRealtimeUs;
3308             super.reset(!stillActive && detachIfReset, elapsedRealtimeUs);
3309             return !stillActive;
3310         }
3311     }
3312 
3313 
3314     /**
3315      * A StopwatchTimer that also tracks the total and max individual
3316      * time spent active according to the given timebase.  Whereas
3317      * StopwatchTimer apportions the time amongst all in the pool,
3318      * the total and max durations are not apportioned.
3319      */
3320     public static class DurationTimer extends StopwatchTimer {
3321         /**
3322          * The time (in ms) that the timer was last acquired or the time base
3323          * last (re-)started. Increasing the nesting depth does not reset this time.
3324          *
3325          * -1 if the timer is currently not running or the time base is not running.
3326          *
3327          * If written to a parcel, the start time is reset, as is mNesting in the base class
3328          * StopwatchTimer.
3329          */
3330         long mStartTimeMs = -1;
3331 
3332         /**
3333          * The longest time period (in ms) that the timer has been active. Not pooled.
3334          */
3335         long mMaxDurationMs;
3336 
3337         /**
3338          * The time (in ms) that that the timer has been active since most recent
3339          * stopRunningLocked() or reset(). Not pooled.
3340          */
3341         long mCurrentDurationMs;
3342 
3343         /**
3344          * The total time (in ms) that that the timer has been active since most recent reset()
3345          * prior to the current startRunningLocked. This is the sum of all past currentDurations
3346          * (but not including the present currentDuration) since reset. Not pooled.
3347          */
3348         long mTotalDurationMs;
3349 
DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)3350         public DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3351                 TimeBase timeBase, Parcel in) {
3352             super(clock, uid, type, timerPool, timeBase, in);
3353             mMaxDurationMs = in.readLong();
3354             mTotalDurationMs = in.readLong();
3355             mCurrentDurationMs = in.readLong();
3356         }
3357 
DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)3358         public DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3359                 TimeBase timeBase) {
3360             super(clock, uid, type, timerPool, timeBase);
3361         }
3362 
3363         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)3364         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3365             super.writeToParcel(out, elapsedRealtimeUs);
3366             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
3367             out.writeLong(mTotalDurationMs);
3368             out.writeLong(getCurrentDurationMsLocked(elapsedRealtimeUs / 1000));
3369         }
3370 
3371         /**
3372          * Write the summary to the parcel.
3373          *
3374          * Since the time base is probably meaningless after we come back, reading
3375          * from this will have the effect of stopping the timer. So here all we write
3376          * is the max and total durations.
3377          */
3378         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)3379         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
3380             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
3381             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
3382             out.writeLong(getTotalDurationMsLocked(elapsedRealtimeUs / 1000));
3383         }
3384 
3385         /**
3386          * Read the summary parcel.
3387          *
3388          * Has the side effect of stopping the timer.
3389          */
3390         @Override
readSummaryFromParcelLocked(Parcel in)3391         public void readSummaryFromParcelLocked(Parcel in) {
3392             super.readSummaryFromParcelLocked(in);
3393             mMaxDurationMs = in.readLong();
3394             mTotalDurationMs = in.readLong();
3395             mStartTimeMs = -1;
3396             mCurrentDurationMs = 0;
3397         }
3398 
3399         /**
3400          * The TimeBase time started (again).
3401          *
3402          * If the timer is also running, store the start time.
3403          */
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3404         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3405             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3406             if (mNesting > 0) {
3407                 mStartTimeMs = baseRealtimeUs / 1000;
3408             }
3409         }
3410 
3411         /**
3412          * The TimeBase stopped running.
3413          *
3414          * If the timer is running, add the duration into mCurrentDurationMs.
3415          */
3416         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3417         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3418             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3419             if (mNesting > 0) {
3420                 // baseRealtimeUs has already been converted to the timebase's realtime.
3421                 mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
3422             }
3423             mStartTimeMs = -1;
3424         }
3425 
3426         @Override
logState(Printer pw, String prefix)3427         public void logState(Printer pw, String prefix) {
3428             super.logState(pw, prefix);
3429         }
3430 
3431         @Override
startRunningLocked(long elapsedRealtimeMs)3432         public void startRunningLocked(long elapsedRealtimeMs) {
3433             super.startRunningLocked(elapsedRealtimeMs);
3434             if (mNesting == 1 && mTimeBase.isRunning()) {
3435                 // Just started
3436                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000;
3437             }
3438         }
3439 
3440         /**
3441          * Decrements the mNesting ref-count on this timer.
3442          *
3443          * If it actually stopped (mNesting went to 0), then possibly update
3444          * mMaxDuration if the current duration was the longest ever.
3445          */
3446         @Override
stopRunningLocked(long elapsedRealtimeMs)3447         public void stopRunningLocked(long elapsedRealtimeMs) {
3448             if (mNesting == 1) {
3449                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
3450                 mTotalDurationMs += durationMs;
3451                 if (durationMs > mMaxDurationMs) {
3452                     mMaxDurationMs = durationMs;
3453                 }
3454                 mStartTimeMs = -1;
3455                 mCurrentDurationMs = 0;
3456             }
3457             // super method decrements mNesting, which getCurrentDurationMsLocked relies on,
3458             // so call super.stopRunningLocked after calling getCurrentDurationMsLocked.
3459             super.stopRunningLocked(elapsedRealtimeMs);
3460         }
3461 
3462         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3463         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3464             boolean result = super.reset(detachIfReset, elapsedRealtimeUs);
3465             mMaxDurationMs = 0;
3466             mTotalDurationMs = 0;
3467             mCurrentDurationMs = 0;
3468             if (mNesting > 0) {
3469                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeUs) / 1000;
3470             } else {
3471                 mStartTimeMs = -1;
3472             }
3473             return result;
3474         }
3475 
3476         /**
3477          * Returns the max duration that this timer has ever seen.
3478          *
3479          * Note that this time is NOT split between the timers in the timer group that
3480          * this timer is attached to.  It is the TOTAL time.
3481          */
3482         @Override
getMaxDurationMsLocked(long elapsedRealtimeMs)3483         public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
3484             if (mNesting > 0) {
3485                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
3486                 if (durationMs > mMaxDurationMs) {
3487                     return durationMs;
3488                 }
3489             }
3490             return mMaxDurationMs;
3491         }
3492 
3493         /**
3494          * Returns the time since the timer was started.
3495          * Returns 0 if the timer is not currently running.
3496          *
3497          * Note that this time is NOT split between the timers in the timer group that
3498          * this timer is attached to.  It is the TOTAL time.
3499          *
3500          * Note that if running timer is parceled and unparceled, this method will return
3501          * current duration value at the time of parceling even though timer may not be
3502          * currently running.
3503          */
3504         @Override
getCurrentDurationMsLocked(long elapsedRealtimeMs)3505         public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
3506             long durationMs = mCurrentDurationMs;
3507             if (mNesting > 0 && mTimeBase.isRunning()) {
3508                 durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000)
3509                         - mStartTimeMs;
3510             }
3511             return durationMs;
3512         }
3513 
3514         /**
3515          * Returns the total cumulative duration that this timer has been on since reset().
3516          * If mTimerPool == null, this should be the same
3517          * as getTotalTimeLocked(elapsedRealtimeMs*1000, STATS_SINCE_CHARGED)/1000.
3518          *
3519          * Note that this time is NOT split between the timers in the timer group that
3520          * this timer is attached to.  It is the TOTAL time. For this reason, if mTimerPool != null,
3521          * the result will not be equivalent to getTotalTimeLocked.
3522          */
3523         @Override
getTotalDurationMsLocked(long elapsedRealtimeMs)3524         public long getTotalDurationMsLocked(long elapsedRealtimeMs) {
3525             return mTotalDurationMs + getCurrentDurationMsLocked(elapsedRealtimeMs);
3526         }
3527     }
3528 
3529     /**
3530      * State for keeping track of timing information.
3531      */
3532     public static class StopwatchTimer extends Timer {
3533         final Uid mUid;
3534         final ArrayList<StopwatchTimer> mTimerPool;
3535 
3536         int mNesting;
3537 
3538         /**
3539          * The last time at which we updated the timer.  If mNesting is > 0,
3540          * subtract this from the current battery time to find the amount of
3541          * time we have been running since we last computed an update.
3542          */
3543         long mUpdateTimeUs;
3544 
3545         /**
3546          * The total time at which the timer was acquired, to determine if it
3547          * was actually held for an interesting duration. If time base was not running when timer
3548          * was acquired, will be -1.
3549          */
3550         long mAcquireTimeUs = -1;
3551 
3552         long mTimeoutUs;
3553 
3554         /**
3555          * For partial wake locks, keep track of whether we are in the list
3556          * to consume CPU cycles.
3557          */
3558         @VisibleForTesting
3559         public boolean mInList;
3560 
StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)3561         public StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3562                 TimeBase timeBase, Parcel in) {
3563             super(clock, type, timeBase, in);
3564             mUid = uid;
3565             mTimerPool = timerPool;
3566             mUpdateTimeUs = in.readLong();
3567         }
3568 
StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)3569         public StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3570                 TimeBase timeBase) {
3571             super(clock, type, timeBase);
3572             mUid = uid;
3573             mTimerPool = timerPool;
3574         }
3575 
setTimeout(long timeoutUs)3576         public void setTimeout(long timeoutUs) {
3577             mTimeoutUs = timeoutUs;
3578         }
3579 
writeToParcel(Parcel out, long elapsedRealtimeUs)3580         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3581             super.writeToParcel(out, elapsedRealtimeUs);
3582             out.writeLong(mUpdateTimeUs);
3583         }
3584 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3585         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3586             if (mNesting > 0) {
3587                 if (DEBUG && mType < 0) {
3588                     Log.v(TAG, "old mUpdateTime=" + mUpdateTimeUs);
3589                 }
3590                 super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3591                 mUpdateTimeUs = baseRealtimeUs;
3592                 if (DEBUG && mType < 0) {
3593                     Log.v(TAG, "new mUpdateTime=" + mUpdateTimeUs);
3594                 }
3595             }
3596         }
3597 
logState(Printer pw, String prefix)3598         public void logState(Printer pw, String prefix) {
3599             super.logState(pw, prefix);
3600             pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTimeUs
3601                     + " mAcquireTime=" + mAcquireTimeUs);
3602         }
3603 
startRunningLocked(long elapsedRealtimeMs)3604         public void startRunningLocked(long elapsedRealtimeMs) {
3605             if (mNesting++ == 0) {
3606                 final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
3607                 mUpdateTimeUs = batteryRealtimeUs;
3608                 if (mTimerPool != null) {
3609                     // Accumulate time to all currently active timers before adding
3610                     // this new one to the pool.
3611                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, null);
3612                     // Add this timer to the active pool
3613                     mTimerPool.add(this);
3614                 }
3615                 if (mTimeBase.isRunning()) {
3616                     // Increment the count
3617                     mCount++;
3618                     mAcquireTimeUs = mTotalTimeUs;
3619                 } else {
3620                     mAcquireTimeUs = -1;
3621                 }
3622                 if (DEBUG && mType < 0) {
3623                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTimeUs
3624                             + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount
3625                             + " mAcquireTime=" + mAcquireTimeUs);
3626                 }
3627             }
3628         }
3629 
isRunningLocked()3630         public boolean isRunningLocked() {
3631             return mNesting > 0;
3632         }
3633 
stopRunningLocked(long elapsedRealtimeMs)3634         public void stopRunningLocked(long elapsedRealtimeMs) {
3635             // Ignore attempt to stop a timer that isn't running
3636             if (mNesting == 0) {
3637                 return;
3638             }
3639             if (--mNesting == 0) {
3640                 final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
3641                 if (mTimerPool != null) {
3642                     // Accumulate time to all active counters, scaled by the total
3643                     // active in the pool, before taking this one out of the pool.
3644                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, null);
3645                     // Remove this timer from the active pool
3646                     mTimerPool.remove(this);
3647                 } else {
3648                     mNesting = 1;
3649                     mTotalTimeUs = computeRunTimeLocked(batteryRealtimeUs,
3650                             elapsedRealtimeMs * 1000);
3651                     mNesting = 0;
3652                 }
3653 
3654                 if (DEBUG && mType < 0) {
3655                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTimeUs
3656                             + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount
3657                             + " mAcquireTime=" + mAcquireTimeUs);
3658                 }
3659 
3660                 if (mAcquireTimeUs >= 0 && mTotalTimeUs == mAcquireTimeUs) {
3661                     // If there was no change in the time, then discard this
3662                     // count.  A somewhat cheezy strategy, but hey.
3663                     mCount--;
3664                 }
3665             }
3666         }
3667 
stopAllRunningLocked(long elapsedRealtimeMs)3668         public void stopAllRunningLocked(long elapsedRealtimeMs) {
3669             if (mNesting > 0) {
3670                 mNesting = 1;
3671                 stopRunningLocked(elapsedRealtimeMs);
3672             }
3673         }
3674 
3675         // Update the total time for all other running Timers with the same type as this Timer
3676         // due to a change in timer count
refreshTimersLocked(long batteryRealtimeUs, final ArrayList<StopwatchTimer> pool, StopwatchTimer self)3677         private static long refreshTimersLocked(long batteryRealtimeUs,
3678                 final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
3679             long selfTimeUs = 0;
3680             final int N = pool.size();
3681             for (int i=N-1; i>= 0; i--) {
3682                 final StopwatchTimer t = pool.get(i);
3683                 long heldTimeUs = batteryRealtimeUs - t.mUpdateTimeUs;
3684                 if (heldTimeUs > 0) {
3685                     final long myTimeUs = heldTimeUs / N;
3686                     if (t == self) {
3687                         selfTimeUs = myTimeUs;
3688                     }
3689                     t.mTotalTimeUs += myTimeUs;
3690                 }
3691                 t.mUpdateTimeUs = batteryRealtimeUs;
3692             }
3693             return selfTimeUs;
3694         }
3695 
3696         @Override
computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs)3697         protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) {
3698             if (mTimeoutUs > 0 && curBatteryRealtimeUs > mUpdateTimeUs + mTimeoutUs) {
3699                 curBatteryRealtimeUs = mUpdateTimeUs + mTimeoutUs;
3700             }
3701             return mTotalTimeUs + (mNesting > 0
3702                     ? (curBatteryRealtimeUs - mUpdateTimeUs)
3703                             / (mTimerPool != null && mTimerPool.size() > 0 ? mTimerPool.size() : 1)
3704                     : 0);
3705         }
3706 
3707         @Override
computeCurrentCountLocked()3708         protected int computeCurrentCountLocked() {
3709             return mCount;
3710         }
3711 
3712         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3713         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3714             boolean canDetach = mNesting <= 0;
3715             super.reset(canDetach && detachIfReset, elapsedRealtimeUs);
3716             if (mNesting > 0) {
3717                 mUpdateTimeUs = mTimeBase.getRealtime(elapsedRealtimeUs);
3718             }
3719             // To ensure mCount isn't decreased to -1 if timer is stopped later.
3720             mAcquireTimeUs = -1;
3721             return canDetach;
3722         }
3723 
3724         @Override
detach()3725         public void detach() {
3726             super.detach();
3727             if (mTimerPool != null) {
3728                 mTimerPool.remove(this);
3729             }
3730         }
3731 
3732         @Override
readSummaryFromParcelLocked(Parcel in)3733         public void readSummaryFromParcelLocked(Parcel in) {
3734             super.readSummaryFromParcelLocked(in);
3735             mNesting = 0;
3736         }
3737 
3738         /**
3739          * Set the mark so that we can query later for the total time the timer has
3740          * accumulated since this point. The timer can be running or not.
3741          *
3742          * @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
3743          */
setMark(long elapsedRealtimeMs)3744         public void setMark(long elapsedRealtimeMs) {
3745             final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
3746             if (mNesting > 0) {
3747                 // We are running.
3748                 if (mTimerPool != null) {
3749                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, this);
3750                 } else {
3751                     mTotalTimeUs += batteryRealtimeUs - mUpdateTimeUs;
3752                     mUpdateTimeUs = batteryRealtimeUs;
3753                 }
3754             }
3755             mTimeBeforeMarkUs = mTotalTimeUs;
3756         }
3757     }
3758 
3759     /**
3760      * State for keeping track of two DurationTimers with different TimeBases, presumably where one
3761      * TimeBase is effectively a subset of the other.
3762      */
3763     public static class DualTimer extends DurationTimer {
3764         // This class both is a DurationTimer and also holds a second DurationTimer.
3765         // The main timer (this) typically tracks the total time. It may be pooled (but since it's a
3766         // durationTimer, it also has the unpooled getTotalDurationMsLocked() for
3767         // STATS_SINCE_CHARGED).
3768         // mSubTimer typically tracks only part of the total time, such as background time, as
3769         // determined by a subTimeBase. It is NOT pooled.
3770         private final DurationTimer mSubTimer;
3771 
3772         /**
3773          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
3774          * The main timer (this) is based on the given timeBase and timerPool.
3775          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
3776          * the main timer is.
3777          */
DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase, Parcel in)3778         public DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3779                 TimeBase timeBase, TimeBase subTimeBase, Parcel in) {
3780             super(clock, uid, type, timerPool, timeBase, in);
3781             mSubTimer = new DurationTimer(clock, uid, type, null, subTimeBase, in);
3782         }
3783 
3784         /**
3785          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
3786          * The main timer (this) is based on the given timeBase and timerPool.
3787          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
3788          * the main timer is.
3789          */
DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase)3790         public DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3791                 TimeBase timeBase, TimeBase subTimeBase) {
3792             super(clock, uid, type, timerPool, timeBase);
3793             mSubTimer = new DurationTimer(clock, uid, type, null, subTimeBase);
3794         }
3795 
3796         /** Get the secondary timer. */
3797         @Override
getSubTimer()3798         public DurationTimer getSubTimer() {
3799             return mSubTimer;
3800         }
3801 
3802         @Override
startRunningLocked(long elapsedRealtimeMs)3803         public void startRunningLocked(long elapsedRealtimeMs) {
3804             super.startRunningLocked(elapsedRealtimeMs);
3805             mSubTimer.startRunningLocked(elapsedRealtimeMs);
3806         }
3807 
3808         @Override
stopRunningLocked(long elapsedRealtimeMs)3809         public void stopRunningLocked(long elapsedRealtimeMs) {
3810             super.stopRunningLocked(elapsedRealtimeMs);
3811             mSubTimer.stopRunningLocked(elapsedRealtimeMs);
3812         }
3813 
3814         @Override
stopAllRunningLocked(long elapsedRealtimeMs)3815         public void stopAllRunningLocked(long elapsedRealtimeMs) {
3816             super.stopAllRunningLocked(elapsedRealtimeMs);
3817             mSubTimer.stopAllRunningLocked(elapsedRealtimeMs);
3818         }
3819 
3820         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3821         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3822             boolean active = false;
3823             // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
3824             active |= !mSubTimer.reset(false, elapsedRealtimeUs);
3825             active |= !super.reset(detachIfReset, elapsedRealtimeUs);
3826             return !active;
3827         }
3828 
3829         @Override
detach()3830         public void detach() {
3831             mSubTimer.detach();
3832             super.detach();
3833         }
3834 
3835         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)3836         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3837             super.writeToParcel(out, elapsedRealtimeUs);
3838             mSubTimer.writeToParcel(out, elapsedRealtimeUs);
3839         }
3840 
3841         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)3842         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
3843             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
3844             mSubTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
3845         }
3846 
3847         @Override
readSummaryFromParcelLocked(Parcel in)3848         public void readSummaryFromParcelLocked(Parcel in) {
3849             super.readSummaryFromParcelLocked(in);
3850             mSubTimer.readSummaryFromParcelLocked(in);
3851         }
3852     }
3853 
3854 
3855     public abstract class OverflowArrayMap<T> {
3856         private static final String OVERFLOW_NAME = "*overflow*";
3857 
3858         final int mUid;
3859         final ArrayMap<String, T> mMap = new ArrayMap<>();
3860         T mCurOverflow;
3861         ArrayMap<String, MutableInt> mActiveOverflow;
3862         long mLastOverflowTimeMs;
3863         long mLastOverflowFinishTimeMs;
3864         long mLastClearTimeMs;
3865         long mLastCleanupTimeMs;
3866 
OverflowArrayMap(int uid)3867         public OverflowArrayMap(int uid) {
3868             mUid = uid;
3869         }
3870 
getMap()3871         public ArrayMap<String, T> getMap() {
3872             return mMap;
3873         }
3874 
clear()3875         public void clear() {
3876             mLastClearTimeMs = SystemClock.elapsedRealtime();
3877             mMap.clear();
3878             mCurOverflow = null;
3879             mActiveOverflow = null;
3880         }
3881 
add(String name, T obj)3882         public void add(String name, T obj) {
3883             if (name == null) {
3884                 name = "";
3885             }
3886             mMap.put(name, obj);
3887             if (OVERFLOW_NAME.equals(name)) {
3888                 mCurOverflow = obj;
3889             }
3890         }
3891 
cleanup(long elapsedRealtimeMs)3892         public void cleanup(long elapsedRealtimeMs) {
3893             mLastCleanupTimeMs = elapsedRealtimeMs;
3894             if (mActiveOverflow != null) {
3895                 if (mActiveOverflow.size() == 0) {
3896                     mActiveOverflow = null;
3897                 }
3898             }
3899             if (mActiveOverflow == null) {
3900                 // There is no currently active overflow, so we should no longer have
3901                 // an overflow entry.
3902                 if (mMap.containsKey(OVERFLOW_NAME)) {
3903                     Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
3904                             + mMap.get(OVERFLOW_NAME));
3905                     mMap.remove(OVERFLOW_NAME);
3906                 }
3907                 mCurOverflow = null;
3908             } else {
3909                 // There is currently active overflow, so we should still have an overflow entry.
3910                 if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
3911                     Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
3912                             + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
3913                 }
3914             }
3915         }
3916 
startObject(String name, long elapsedRealtimeMs)3917         public T startObject(String name, long elapsedRealtimeMs) {
3918             if (name == null) {
3919                 name = "";
3920             }
3921             T obj = mMap.get(name);
3922             if (obj != null) {
3923                 return obj;
3924             }
3925 
3926             // No object exists for the given name, but do we currently have it
3927             // running as part of the overflow?
3928             if (mActiveOverflow != null) {
3929                 MutableInt over = mActiveOverflow.get(name);
3930                 if (over != null) {
3931                     // We are already actively counting this name in the overflow object.
3932                     obj = mCurOverflow;
3933                     if (obj == null) {
3934                         // Shouldn't be here, but we'll try to recover.
3935                         Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
3936                         obj = mCurOverflow = instantiateObject();
3937                         mMap.put(OVERFLOW_NAME, obj);
3938                     }
3939                     over.value++;
3940                     return obj;
3941                 }
3942             }
3943 
3944             // No object exists for given name nor in the overflow; we need to make
3945             // a new one.
3946             final int N = mMap.size();
3947             if (N >= MAX_WAKELOCKS_PER_UID) {
3948                 // Went over the limit on number of objects to track; this one goes
3949                 // in to the overflow.
3950                 obj = mCurOverflow;
3951                 if (obj == null) {
3952                     // Need to start overflow now...
3953                     obj = mCurOverflow = instantiateObject();
3954                     mMap.put(OVERFLOW_NAME, obj);
3955                 }
3956                 if (mActiveOverflow == null) {
3957                     mActiveOverflow = new ArrayMap<>();
3958                 }
3959                 mActiveOverflow.put(name, new MutableInt(1));
3960                 mLastOverflowTimeMs = elapsedRealtimeMs;
3961                 return obj;
3962             }
3963 
3964             // Normal case where we just need to make a new object.
3965             obj = instantiateObject();
3966             mMap.put(name, obj);
3967             return obj;
3968         }
3969 
stopObject(String name, long elapsedRealtimeMs)3970         public T stopObject(String name, long elapsedRealtimeMs) {
3971             if (name == null) {
3972                 name = "";
3973             }
3974             T obj = mMap.get(name);
3975             if (obj != null) {
3976                 return obj;
3977             }
3978 
3979             // No object exists for the given name, but do we currently have it
3980             // running as part of the overflow?
3981             if (mActiveOverflow != null) {
3982                 MutableInt over = mActiveOverflow.get(name);
3983                 if (over != null) {
3984                     // We are already actively counting this name in the overflow object.
3985                     obj = mCurOverflow;
3986                     if (obj != null) {
3987                         over.value--;
3988                         if (over.value <= 0) {
3989                             mActiveOverflow.remove(name);
3990                             mLastOverflowFinishTimeMs = elapsedRealtimeMs;
3991                         }
3992                         return obj;
3993                     }
3994                 }
3995             }
3996 
3997             // Huh, they are stopping an active operation but we can't find one!
3998             // That's not good.
3999             StringBuilder sb = new StringBuilder();
4000             sb.append("Unable to find object for ");
4001             sb.append(name);
4002             sb.append(" in uid ");
4003             sb.append(mUid);
4004             sb.append(" mapsize=");
4005             sb.append(mMap.size());
4006             sb.append(" activeoverflow=");
4007             sb.append(mActiveOverflow);
4008             sb.append(" curoverflow=");
4009             sb.append(mCurOverflow);
4010             long now = elapsedRealtimeMs;
4011             if (mLastOverflowTimeMs != 0) {
4012                 sb.append(" lastOverflowTime=");
4013                 TimeUtils.formatDuration(mLastOverflowTimeMs - now, sb);
4014             }
4015             if (mLastOverflowFinishTimeMs != 0) {
4016                 sb.append(" lastOverflowFinishTime=");
4017                 TimeUtils.formatDuration(mLastOverflowFinishTimeMs - now, sb);
4018             }
4019             if (mLastClearTimeMs != 0) {
4020                 sb.append(" lastClearTime=");
4021                 TimeUtils.formatDuration(mLastClearTimeMs - now, sb);
4022             }
4023             if (mLastCleanupTimeMs != 0) {
4024                 sb.append(" lastCleanupTime=");
4025                 TimeUtils.formatDuration(mLastCleanupTimeMs - now, sb);
4026             }
4027             Slog.wtf(TAG, sb.toString());
4028             return null;
4029         }
4030 
instantiateObject()4031         public abstract T instantiateObject();
4032     }
4033 
4034     @SuppressWarnings("ParcelableCreator")
4035     public static class ControllerActivityCounterImpl extends ControllerActivityCounter
4036             implements Parcelable {
4037         private final Clock mClock;
4038         private final TimeBase mTimeBase;
4039         private int mNumTxStates;
4040         private int mProcessState;
4041         private TimeMultiStateCounter mIdleTimeMillis;
4042         private final LongSamplingCounter mScanTimeMillis;
4043         private final LongSamplingCounter mSleepTimeMillis;
4044         private TimeMultiStateCounter mRxTimeMillis;
4045         private TimeMultiStateCounter[] mTxTimeMillis;
4046         private final LongSamplingCounter mPowerDrainMaMs;
4047         private final LongSamplingCounter mMonitoredRailChargeConsumedMaMs;
4048 
ControllerActivityCounterImpl(Clock clock, TimeBase timeBase, int numTxStates)4049         public ControllerActivityCounterImpl(Clock clock, TimeBase timeBase, int numTxStates) {
4050             mClock = clock;
4051             mTimeBase = timeBase;
4052             mNumTxStates = numTxStates;
4053             mScanTimeMillis = new LongSamplingCounter(timeBase);
4054             mSleepTimeMillis = new LongSamplingCounter(timeBase);
4055             mPowerDrainMaMs = new LongSamplingCounter(timeBase);
4056             mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase);
4057         }
4058 
readSummaryFromParcel(Parcel in)4059         public void readSummaryFromParcel(Parcel in) {
4060             mIdleTimeMillis = readTimeMultiStateCounter(in, mTimeBase);
4061             mScanTimeMillis.readSummaryFromParcelLocked(in);
4062             mSleepTimeMillis.readSummaryFromParcelLocked(in);
4063             mRxTimeMillis = readTimeMultiStateCounter(in, mTimeBase);
4064             mTxTimeMillis = readTimeMultiStateCounters(in, mTimeBase, mNumTxStates);
4065 
4066             mPowerDrainMaMs.readSummaryFromParcelLocked(in);
4067             mMonitoredRailChargeConsumedMaMs.readSummaryFromParcelLocked(in);
4068         }
4069 
4070         @Override
describeContents()4071         public int describeContents() {
4072             return 0;
4073         }
4074 
writeSummaryToParcel(Parcel dest)4075         public void writeSummaryToParcel(Parcel dest) {
4076             writeTimeMultiStateCounter(dest, mIdleTimeMillis);
4077             mScanTimeMillis.writeSummaryFromParcelLocked(dest);
4078             mSleepTimeMillis.writeSummaryFromParcelLocked(dest);
4079             writeTimeMultiStateCounter(dest, mRxTimeMillis);
4080             writeTimeMultiStateCounters(dest, mTxTimeMillis);
4081             mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
4082             mMonitoredRailChargeConsumedMaMs.writeSummaryFromParcelLocked(dest);
4083         }
4084 
4085         @Override
writeToParcel(Parcel dest, int flags)4086         public void writeToParcel(Parcel dest, int flags) {
4087             writeTimeMultiStateCounter(dest, mIdleTimeMillis);
4088             mScanTimeMillis.writeToParcel(dest);
4089             mSleepTimeMillis.writeToParcel(dest);
4090             writeTimeMultiStateCounter(dest, mRxTimeMillis);
4091             writeTimeMultiStateCounters(dest, mTxTimeMillis);
4092             mPowerDrainMaMs.writeToParcel(dest);
4093             mMonitoredRailChargeConsumedMaMs.writeToParcel(dest);
4094         }
4095 
readTimeMultiStateCounter(Parcel in, TimeBase timeBase)4096         private TimeMultiStateCounter readTimeMultiStateCounter(Parcel in, TimeBase timeBase) {
4097             if (in.readBoolean()) {
4098                 return TimeMultiStateCounter.readFromParcel(in, timeBase,
4099                         BatteryConsumer.PROCESS_STATE_COUNT, mClock.elapsedRealtime());
4100             }
4101             return null;
4102         }
4103 
writeTimeMultiStateCounter(Parcel dest, TimeMultiStateCounter counter)4104         private void writeTimeMultiStateCounter(Parcel dest, TimeMultiStateCounter counter) {
4105             if (counter != null) {
4106                 dest.writeBoolean(true);
4107                 counter.writeToParcel(dest);
4108             } else {
4109                 dest.writeBoolean(false);
4110             }
4111         }
4112 
readTimeMultiStateCounters(Parcel in, TimeBase timeBase, int expectedNumCounters)4113         private TimeMultiStateCounter[] readTimeMultiStateCounters(Parcel in, TimeBase timeBase,
4114                 int expectedNumCounters) {
4115             if (in.readBoolean()) {
4116                 final int numCounters = in.readInt();
4117                 boolean valid = (numCounters == expectedNumCounters);
4118                 // Need to read counters out of the Parcel, even if all or some of them are
4119                 // invalid.
4120                 TimeMultiStateCounter[] counters = new TimeMultiStateCounter[numCounters];
4121                 for (int i = 0; i < numCounters; i++) {
4122                     final TimeMultiStateCounter counter = TimeMultiStateCounter.readFromParcel(in,
4123                             timeBase, BatteryConsumer.PROCESS_STATE_COUNT,
4124                             mClock.elapsedRealtime());
4125                     if (counter != null) {
4126                         counters[i] = counter;
4127                     } else {
4128                         valid = false;
4129                     }
4130                 }
4131                 if (valid) {
4132                     return counters;
4133                 }
4134             }
4135             return null;
4136         }
4137 
writeTimeMultiStateCounters(Parcel dest, TimeMultiStateCounter[] counters)4138         private void writeTimeMultiStateCounters(Parcel dest, TimeMultiStateCounter[] counters) {
4139             if (counters != null) {
4140                 dest.writeBoolean(true);
4141                 dest.writeInt(counters.length);
4142                 for (TimeMultiStateCounter counter : counters) {
4143                     counter.writeToParcel(dest);
4144                 }
4145             } else {
4146                 dest.writeBoolean(false);
4147             }
4148         }
4149 
reset(boolean detachIfReset, long elapsedRealtimeUs)4150         public void reset(boolean detachIfReset, long elapsedRealtimeUs) {
4151             resetIfNotNull(mIdleTimeMillis, detachIfReset, elapsedRealtimeUs);
4152             mScanTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
4153             mSleepTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
4154             resetIfNotNull(mRxTimeMillis, detachIfReset, elapsedRealtimeUs);
4155             resetIfNotNull(mTxTimeMillis, detachIfReset, elapsedRealtimeUs);
4156             mPowerDrainMaMs.reset(detachIfReset, elapsedRealtimeUs);
4157             mMonitoredRailChargeConsumedMaMs.reset(detachIfReset, elapsedRealtimeUs);
4158         }
4159 
detach()4160         public void detach() {
4161             detachIfNotNull(mIdleTimeMillis);
4162             mScanTimeMillis.detach();
4163             mSleepTimeMillis.detach();
4164             detachIfNotNull(mRxTimeMillis);
4165             detachIfNotNull(mTxTimeMillis);
4166             mPowerDrainMaMs.detach();
4167             mMonitoredRailChargeConsumedMaMs.detach();
4168         }
4169 
4170         /**
4171          * @return a LongSamplingCounter, measuring time spent in the idle state in
4172          * milliseconds.
4173          */
4174         @Override
getIdleTimeCounter()4175         public LongCounter getIdleTimeCounter() {
4176             if (mIdleTimeMillis == null) {
4177                 return ZERO_LONG_COUNTER;
4178             }
4179             return mIdleTimeMillis;
4180         }
4181 
getOrCreateIdleTimeCounter()4182         private TimeMultiStateCounter getOrCreateIdleTimeCounter() {
4183             if (mIdleTimeMillis == null) {
4184                 mIdleTimeMillis = createTimeMultiStateCounter();
4185             }
4186             return mIdleTimeMillis;
4187         }
4188 
4189         /**
4190          * @return a LongSamplingCounter, measuring time spent in the scan state in
4191          * milliseconds.
4192          */
4193         @Override
getScanTimeCounter()4194         public LongSamplingCounter getScanTimeCounter() {
4195             return mScanTimeMillis;
4196         }
4197 
4198         /**
4199          * @return a LongSamplingCounter, measuring time spent in the sleep state in
4200          * milliseconds.
4201          */
4202         @Override
getSleepTimeCounter()4203         public LongSamplingCounter getSleepTimeCounter() {
4204             return mSleepTimeMillis;
4205         }
4206 
4207         /**
4208          * @return a LongSamplingCounter, measuring time spent in the receive state in
4209          * milliseconds.
4210          */
4211         @Override
getRxTimeCounter()4212         public LongCounter getRxTimeCounter() {
4213             if (mRxTimeMillis == null) {
4214                 return ZERO_LONG_COUNTER;
4215             }
4216             return mRxTimeMillis;
4217         }
4218 
getOrCreateRxTimeCounter()4219         private TimeMultiStateCounter getOrCreateRxTimeCounter() {
4220             if (mRxTimeMillis == null) {
4221                 mRxTimeMillis = createTimeMultiStateCounter();
4222             }
4223             return mRxTimeMillis;
4224         }
4225 
4226         /**
4227          * @return a LongSamplingCounter[], measuring time spent in various transmit states in
4228          * milliseconds.
4229          */
4230         @Override
getTxTimeCounters()4231         public LongCounter[] getTxTimeCounters() {
4232             if (mTxTimeMillis == null) {
4233                 return ZERO_LONG_COUNTER_ARRAY;
4234             }
4235             return mTxTimeMillis;
4236         }
4237 
getOrCreateTxTimeCounters()4238         private TimeMultiStateCounter[] getOrCreateTxTimeCounters() {
4239             if (mTxTimeMillis == null) {
4240                 mTxTimeMillis = new TimeMultiStateCounter[mNumTxStates];
4241                 for (int i = 0; i < mNumTxStates; i++) {
4242                     mTxTimeMillis[i] = createTimeMultiStateCounter();
4243                 }
4244             }
4245             return mTxTimeMillis;
4246         }
4247 
createTimeMultiStateCounter()4248         private TimeMultiStateCounter createTimeMultiStateCounter() {
4249             final long timestampMs = mClock.elapsedRealtime();
4250             TimeMultiStateCounter counter = new TimeMultiStateCounter(mTimeBase,
4251                     BatteryConsumer.PROCESS_STATE_COUNT, timestampMs);
4252             counter.setState(mapUidProcessStateToBatteryConsumerProcessState(mProcessState),
4253                     timestampMs);
4254             counter.update(0, timestampMs);
4255             return counter;
4256         }
4257 
4258         /**
4259          * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
4260          */
4261         @Override
getPowerCounter()4262         public LongSamplingCounter getPowerCounter() {
4263             return mPowerDrainMaMs;
4264         }
4265 
4266         /**
4267          * @return a LongSamplingCounter, measuring actual monitored rail energy consumed
4268          * milli-ampere milli-seconds (mAmS).
4269          */
4270         @Override
getMonitoredRailChargeConsumedMaMs()4271         public LongSamplingCounter getMonitoredRailChargeConsumedMaMs() {
4272             return mMonitoredRailChargeConsumedMaMs;
4273         }
4274 
setState(int processState, long elapsedTimeMs)4275         private void setState(int processState, long elapsedTimeMs) {
4276             mProcessState = processState;
4277             if (mIdleTimeMillis != null) {
4278                 mIdleTimeMillis.setState(processState, elapsedTimeMs);
4279             }
4280             if (mRxTimeMillis != null) {
4281                 mRxTimeMillis.setState(processState, elapsedTimeMs);
4282             }
4283             if (mTxTimeMillis != null) {
4284                 for (int i = 0; i < mTxTimeMillis.length; i++) {
4285                     mTxTimeMillis[i].setState(processState, elapsedTimeMs);
4286                 }
4287             }
4288         }
4289     }
4290 
4291     /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */
getRpmTimerLocked(String name)4292     public SamplingTimer getRpmTimerLocked(String name) {
4293         SamplingTimer rpmt = mRpmStats.get(name);
4294         if (rpmt == null) {
4295             rpmt = new SamplingTimer(mClock, mOnBatteryTimeBase);
4296             mRpmStats.put(name, rpmt);
4297         }
4298         return rpmt;
4299     }
4300 
4301     /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */
getScreenOffRpmTimerLocked(String name)4302     public SamplingTimer getScreenOffRpmTimerLocked(String name) {
4303         SamplingTimer rpmt = mScreenOffRpmStats.get(name);
4304         if (rpmt == null) {
4305             rpmt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase);
4306             mScreenOffRpmStats.put(name, rpmt);
4307         }
4308         return rpmt;
4309     }
4310 
4311     /*
4312      * Get the wakeup reason counter, and create a new one if one
4313      * doesn't already exist.
4314      */
getWakeupReasonTimerLocked(String name)4315     public SamplingTimer getWakeupReasonTimerLocked(String name) {
4316         SamplingTimer timer = mWakeupReasonStats.get(name);
4317         if (timer == null) {
4318             timer = new SamplingTimer(mClock, mOnBatteryTimeBase);
4319             mWakeupReasonStats.put(name, timer);
4320         }
4321         return timer;
4322     }
4323 
4324     /*
4325      * Get the KernelWakelockTimer associated with name, and create a new one if one
4326      * doesn't already exist.
4327      */
getKernelWakelockTimerLocked(String name)4328     public SamplingTimer getKernelWakelockTimerLocked(String name) {
4329         SamplingTimer kwlt = mKernelWakelockStats.get(name);
4330         if (kwlt == null) {
4331             kwlt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase);
4332             mKernelWakelockStats.put(name, kwlt);
4333         }
4334         return kwlt;
4335     }
4336 
getKernelMemoryTimerLocked(long bucket)4337     public SamplingTimer getKernelMemoryTimerLocked(long bucket) {
4338         SamplingTimer kmt = mKernelMemoryStats.get(bucket);
4339         if (kmt == null) {
4340             kmt = new SamplingTimer(mClock, mOnBatteryTimeBase);
4341             mKernelMemoryStats.put(bucket, kmt);
4342         }
4343         return kmt;
4344     }
4345 
4346     private class HistoryStepDetailsCalculatorImpl implements HistoryStepDetailsCalculator {
4347         private final HistoryStepDetails mDetails = new HistoryStepDetails();
4348 
4349         private boolean mHasHistoryStepDetails;
4350         private boolean mUpdateRequested;
4351 
4352         /**
4353          * Total time (in milliseconds) spent executing in user code.
4354          */
4355         private long mLastStepCpuUserTimeMs;
4356         private long mCurStepCpuUserTimeMs;
4357         /**
4358          * Total time (in milliseconds) spent executing in kernel code.
4359          */
4360         private long mLastStepCpuSystemTimeMs;
4361         private long mCurStepCpuSystemTimeMs;
4362         /**
4363          * Times from /proc/stat (but measured in milliseconds).
4364          */
4365         private long mLastStepStatUserTimeMs;
4366         private long mLastStepStatSystemTimeMs;
4367         private long mLastStepStatIOWaitTimeMs;
4368         private long mLastStepStatIrqTimeMs;
4369         private long mLastStepStatSoftIrqTimeMs;
4370         private long mLastStepStatIdleTimeMs;
4371         private long mCurStepStatUserTimeMs;
4372         private long mCurStepStatSystemTimeMs;
4373         private long mCurStepStatIOWaitTimeMs;
4374         private long mCurStepStatIrqTimeMs;
4375         private long mCurStepStatSoftIrqTimeMs;
4376         private long mCurStepStatIdleTimeMs;
4377 
4378         @Override
getHistoryStepDetails()4379         public HistoryStepDetails getHistoryStepDetails() {
4380             if (!mUpdateRequested) {
4381                 mUpdateRequested = true;
4382                 // Perform a CPU update right after we do this collection, so we have started
4383                 // collecting good data for the next step.
4384                 requestImmediateCpuUpdate();
4385 
4386                 if (mPlatformIdleStateCallback != null) {
4387                     mDetails.statSubsystemPowerState =
4388                             mPlatformIdleStateCallback.getSubsystemLowPowerStats();
4389                     if (DEBUG) {
4390                         Slog.i(TAG,
4391                                 "WRITE SubsystemPowerState:" + mDetails.statSubsystemPowerState);
4392                     }
4393                 }
4394             }
4395 
4396             if (!mHasHistoryStepDetails) {
4397                 // We are not generating a delta, so all we need to do is reset the stats
4398                 // we will later be doing a delta from.
4399                 final int uidCount = mUidStats.size();
4400                 for (int i = 0; i < uidCount; i++) {
4401                     final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4402                     uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
4403                     uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
4404                 }
4405                 mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
4406                 mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
4407                 mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
4408                 mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
4409                 mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
4410                 mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
4411                 mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
4412                 mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
4413                 return null;
4414             } else {
4415                 if (DEBUG) {
4416                     Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTimeMs + " sys="
4417                             + mLastStepStatSystemTimeMs + " io=" + mLastStepStatIOWaitTimeMs
4418                             + " irq=" + mLastStepStatIrqTimeMs + " sirq="
4419                             + mLastStepStatSoftIrqTimeMs + " idle=" + mLastStepStatIdleTimeMs);
4420                     Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTimeMs + " sys="
4421                             + mCurStepStatSystemTimeMs + " io=" + mCurStepStatIOWaitTimeMs
4422                             + " irq=" + mCurStepStatIrqTimeMs + " sirq="
4423                             + mCurStepStatSoftIrqTimeMs + " idle=" + mCurStepStatIdleTimeMs);
4424                 }
4425                 mDetails.userTime = (int) (mCurStepCpuUserTimeMs - mLastStepCpuUserTimeMs);
4426                 mDetails.systemTime = (int) (mCurStepCpuSystemTimeMs - mLastStepCpuSystemTimeMs);
4427                 mDetails.statUserTime = (int) (mCurStepStatUserTimeMs - mLastStepStatUserTimeMs);
4428                 mDetails.statSystemTime =
4429                         (int) (mCurStepStatSystemTimeMs - mLastStepStatSystemTimeMs);
4430                 mDetails.statIOWaitTime =
4431                         (int) (mCurStepStatIOWaitTimeMs - mLastStepStatIOWaitTimeMs);
4432                 mDetails.statIrqTime = (int) (mCurStepStatIrqTimeMs - mLastStepStatIrqTimeMs);
4433                 mDetails.statSoftIrqTime =
4434                         (int) (mCurStepStatSoftIrqTimeMs - mLastStepStatSoftIrqTimeMs);
4435                 mDetails.statIdlTime = (int) (mCurStepStatIdleTimeMs - mLastStepStatIdleTimeMs);
4436                 mDetails.appCpuUid1 = mDetails.appCpuUid2 = mDetails.appCpuUid3 = -1;
4437                 mDetails.appCpuUTime1 = mDetails.appCpuUTime2 = mDetails.appCpuUTime3 = 0;
4438                 mDetails.appCpuSTime1 = mDetails.appCpuSTime2 = mDetails.appCpuSTime3 = 0;
4439                 final int uidCount = mUidStats.size();
4440                 for (int i = 0; i < uidCount; i++) {
4441                     final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4442                     final int totalUTimeMs =
4443                             (int) (uid.mCurStepUserTimeMs - uid.mLastStepUserTimeMs);
4444                     final int totalSTimeMs =
4445                             (int) (uid.mCurStepSystemTimeMs - uid.mLastStepSystemTimeMs);
4446                     final int totalTimeMs = totalUTimeMs + totalSTimeMs;
4447                     uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
4448                     uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
4449                     if (totalTimeMs <= (mDetails.appCpuUTime3 + mDetails.appCpuSTime3)) {
4450                         continue;
4451                     }
4452                     if (totalTimeMs <= (mDetails.appCpuUTime2 + mDetails.appCpuSTime2)) {
4453                         mDetails.appCpuUid3 = uid.mUid;
4454                         mDetails.appCpuUTime3 = totalUTimeMs;
4455                         mDetails.appCpuSTime3 = totalSTimeMs;
4456                     } else {
4457                         mDetails.appCpuUid3 = mDetails.appCpuUid2;
4458                         mDetails.appCpuUTime3 = mDetails.appCpuUTime2;
4459                         mDetails.appCpuSTime3 = mDetails.appCpuSTime2;
4460                         if (totalTimeMs <= (mDetails.appCpuUTime1 + mDetails.appCpuSTime1)) {
4461                             mDetails.appCpuUid2 = uid.mUid;
4462                             mDetails.appCpuUTime2 = totalUTimeMs;
4463                             mDetails.appCpuSTime2 = totalSTimeMs;
4464                         } else {
4465                             mDetails.appCpuUid2 = mDetails.appCpuUid1;
4466                             mDetails.appCpuUTime2 = mDetails.appCpuUTime1;
4467                             mDetails.appCpuSTime2 = mDetails.appCpuSTime1;
4468                             mDetails.appCpuUid1 = uid.mUid;
4469                             mDetails.appCpuUTime1 = totalUTimeMs;
4470                             mDetails.appCpuSTime1 = totalSTimeMs;
4471                         }
4472                     }
4473                 }
4474                 mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
4475                 mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
4476                 mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
4477                 mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
4478                 mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
4479                 mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
4480                 mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
4481                 mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
4482                 return mDetails;
4483             }
4484         }
4485 
addCpuStats(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs, int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs, int statSoftIrqTimeMs, int statIdleTimeMs)4486         public void addCpuStats(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs,
4487                 int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
4488                 int statSoftIrqTimeMs, int statIdleTimeMs) {
4489             if (DEBUG) {
4490                 Slog.d(TAG, "Adding cpu: tuser=" + totalUTimeMs + " tsys=" + totalSTimeMs
4491                         + " user=" + statUserTimeMs + " sys=" + statSystemTimeMs
4492                         + " io=" + statIOWaitTimeMs + " irq=" + statIrqTimeMs
4493                         + " sirq=" + statSoftIrqTimeMs + " idle=" + statIdleTimeMs);
4494             }
4495             mCurStepCpuUserTimeMs += totalUTimeMs;
4496             mCurStepCpuSystemTimeMs += totalSTimeMs;
4497             mCurStepStatUserTimeMs += statUserTimeMs;
4498             mCurStepStatSystemTimeMs += statSystemTimeMs;
4499             mCurStepStatIOWaitTimeMs += statIOWaitTimeMs;
4500             mCurStepStatIrqTimeMs += statIrqTimeMs;
4501             mCurStepStatSoftIrqTimeMs += statSoftIrqTimeMs;
4502             mCurStepStatIdleTimeMs += statIdleTimeMs;
4503         }
4504 
finishAddingCpuLocked()4505         public void finishAddingCpuLocked() {
4506             mHasHistoryStepDetails = true;
4507             mUpdateRequested = false;
4508         }
4509 
4510         @Override
clear()4511         public void clear() {
4512             mHasHistoryStepDetails = false;
4513             mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs = 0;
4514             mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs = 0;
4515             mLastStepStatUserTimeMs = mCurStepStatUserTimeMs = 0;
4516             mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs = 0;
4517             mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs = 0;
4518             mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs = 0;
4519             mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs = 0;
4520             mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs = 0;
4521         }
4522     }
4523 
4524     @GuardedBy("this")
4525     @Override
commitCurrentHistoryBatchLocked()4526     public void commitCurrentHistoryBatchLocked() {
4527         mHistory.commitCurrentHistoryBatchLocked();
4528     }
4529 
4530     @GuardedBy("this")
createFakeHistoryEvents(long numEvents)4531     public void createFakeHistoryEvents(long numEvents) {
4532         final long elapsedRealtimeMs = mClock.elapsedRealtime();
4533         final long uptimeMs = mClock.uptimeMillis();
4534         for(long i = 0; i < numEvents; i++) {
4535             noteLongPartialWakelockStart("name1", "historyName1", 1000,
4536                     elapsedRealtimeMs, uptimeMs);
4537             noteLongPartialWakelockFinish("name1", "historyName1", 1000,
4538                     elapsedRealtimeMs, uptimeMs);
4539         }
4540     }
4541 
4542     @GuardedBy("this")
recordHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code, String name, int uid)4543     public void recordHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
4544             String name, int uid) {
4545         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, code, name, uid);
4546     }
4547 
4548     @GuardedBy("this")
updateTimeBasesLocked(boolean unplugged, int screenState, long uptimeUs, long realtimeUs)4549     public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptimeUs,
4550             long realtimeUs) {
4551         final boolean screenOff = !Display.isOnState(screenState);
4552         final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
4553         final boolean updateOnBatteryScreenOffTimeBase =
4554                 (unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
4555 
4556         if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) {
4557             if (updateOnBatteryScreenOffTimeBase) {
4558                 updateKernelWakelocksLocked(realtimeUs);
4559                 updateBatteryPropertiesLocked();
4560             }
4561             // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
4562             // updateRpmStatsLocked is too slow to run each screen change. When the speed is
4563             // improved, remove the surrounding if{}.
4564             if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
4565                 // if either OnBattery or OnBatteryScreenOfftimebase changes.
4566                 updateRpmStatsLocked(realtimeUs);
4567             }
4568             if (DEBUG_ENERGY_CPU) {
4569                 Slog.d(TAG, "Updating cpu time because screen is now "
4570                         + Display.stateToString(screenState)
4571                         + " and battery is " + (unplugged ? "on" : "off"));
4572             }
4573 
4574             mOnBatteryTimeBase.setRunning(unplugged, uptimeUs, realtimeUs);
4575             if (updateOnBatteryTimeBase) {
4576                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
4577                     mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptimeUs, realtimeUs);
4578                 }
4579             }
4580             if (updateOnBatteryScreenOffTimeBase) {
4581                 mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff,
4582                         uptimeUs, realtimeUs);
4583                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
4584                     mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptimeUs, realtimeUs);
4585                 }
4586             }
4587         }
4588     }
4589 
4590     @GuardedBy("this")
updateBatteryPropertiesLocked()4591     protected void updateBatteryPropertiesLocked() {
4592         try {
4593             IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
4594                     ServiceManager.getService("batteryproperties"));
4595             if (registrar != null) {
4596                 registrar.scheduleUpdate();
4597             }
4598         } catch (RemoteException e) {
4599             // Ignore.
4600         }
4601     }
4602 
onIsolatedUidAdded(int isolatedUid, int parentUid)4603     private void onIsolatedUidAdded(int isolatedUid, int parentUid) {
4604         long realtime = mClock.elapsedRealtime();
4605         long uptime = mClock.uptimeMillis();
4606         synchronized (this) {
4607             getUidStatsLocked(parentUid, realtime, uptime).addIsolatedUid(isolatedUid);
4608         }
4609     }
4610 
onBeforeIsolatedUidRemoved(int isolatedUid, int parentUid)4611     private void onBeforeIsolatedUidRemoved(int isolatedUid, int parentUid) {
4612         long realtime = mClock.elapsedRealtime();
4613         mPowerStatsUidResolver.retainIsolatedUid(isolatedUid);
4614         synchronized (this) {
4615             mPendingRemovedUids.add(new UidToRemove(isolatedUid, realtime));
4616         }
4617         if (mExternalSync != null) {
4618             mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
4619         }
4620     }
4621 
onAfterIsolatedUidRemoved(int isolatedUid, int parentUid)4622     private void onAfterIsolatedUidRemoved(int isolatedUid, int parentUid) {
4623         long realtime = mClock.elapsedRealtime();
4624         long uptime = mClock.uptimeMillis();
4625         synchronized (this) {
4626             getUidStatsLocked(parentUid, realtime, uptime).removeIsolatedUid(isolatedUid);
4627         }
4628     }
4629 
4630     /**
4631      * Isolated uid should only be removed after all wakelocks associated with the uid are stopped
4632      * and the cpu time-in-state has been read one last time for the uid.
4633      */
4634     @GuardedBy("this")
releaseIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs, long uptimeMs)4635     public void releaseIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs, long uptimeMs) {
4636         mPowerStatsUidResolver.releaseIsolatedUid(isolatedUid);
4637     }
4638 
mapUid(int uid)4639     private int mapUid(int uid) {
4640         if (Process.isSdkSandboxUid(uid)) {
4641             return Process.getAppUidForSdkSandboxUid(uid);
4642         }
4643         return mPowerStatsUidResolver.mapUid(uid);
4644     }
4645 
mapIsolatedUid(int uid)4646     private int mapIsolatedUid(int uid) {
4647         return mPowerStatsUidResolver.mapUid(uid);
4648     }
4649 
4650     @GuardedBy("this")
noteEventLocked(int code, String name, int uid, long elapsedRealtimeMs, long uptimeMs)4651     public void noteEventLocked(int code, String name, int uid,
4652             long elapsedRealtimeMs, long uptimeMs) {
4653         uid = mapUid(uid);
4654         if (!mActiveEvents.updateState(code, name, uid, 0)) {
4655             return;
4656         }
4657         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, code, name, uid);
4658     }
4659 
4660     @GuardedBy("this")
noteCurrentTimeChangedLocked(long currentTimeMs, long elapsedRealtimeMs, long uptimeMs)4661     public void noteCurrentTimeChangedLocked(long currentTimeMs,
4662             long elapsedRealtimeMs, long uptimeMs) {
4663         mHistory.recordCurrentTimeChange(elapsedRealtimeMs, uptimeMs, currentTimeMs);
4664         adjustStartClockTime(currentTimeMs);
4665     }
4666 
adjustStartClockTime(long currentTimeMs)4667     private void adjustStartClockTime(long currentTimeMs) {
4668         mStartClockTimeMs =
4669                 currentTimeMs - (mClock.elapsedRealtime() - (mRealtimeStartUs / 1000));
4670     }
4671 
4672     @GuardedBy("this")
noteProcessStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4673     public void noteProcessStartLocked(String name, int uid,
4674             long elapsedRealtimeMs, long uptimeMs) {
4675         uid = mapUid(uid);
4676         if (isOnBattery()) {
4677             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4678             u.getProcessStatsLocked(name).incStartsLocked();
4679         }
4680         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
4681             return;
4682         }
4683         if (!mRecordAllHistory) {
4684             return;
4685         }
4686         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid);
4687     }
4688 
4689     @GuardedBy("this")
noteProcessCrashLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4690     public void noteProcessCrashLocked(String name, int uid,
4691             long elapsedRealtimeMs, long uptimeMs) {
4692         uid = mapUid(uid);
4693         if (isOnBattery()) {
4694             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4695             u.getProcessStatsLocked(name).incNumCrashesLocked();
4696         }
4697     }
4698 
4699     @GuardedBy("this")
noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4700     public void noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4701         uid = mapUid(uid);
4702         if (isOnBattery()) {
4703             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4704             u.getProcessStatsLocked(name).incNumAnrsLocked();
4705         }
4706     }
4707 
4708     @GuardedBy("this")
noteUidProcessStateLocked(int uid, int state)4709     public void noteUidProcessStateLocked(int uid, int state) {
4710         noteUidProcessStateLocked(uid, state, mClock.elapsedRealtime(), mClock.uptimeMillis());
4711     }
4712 
4713     @GuardedBy("this")
4714     @SuppressWarnings("GuardedBy")   // errorprone false positive on u.updateUidProcessStateLocked
noteUidProcessStateLocked(int uid, int state, long elapsedRealtimeMs, long uptimeMs)4715     public void noteUidProcessStateLocked(int uid, int state,
4716             long elapsedRealtimeMs, long uptimeMs) {
4717         int parentUid = mapUid(uid);
4718         if (uid != parentUid) {
4719             if (Process.isIsolated(uid)) {
4720                 // Isolated UIDs process state is already rolled up into parent, so no need to track
4721                 // Otherwise the parent's process state will get downgraded incorrectly
4722                 return;
4723             }
4724         }
4725         mFrameworkStatsLogger.uidProcessStateChanged(uid, state);
4726         getUidStatsLocked(parentUid, elapsedRealtimeMs, uptimeMs)
4727                 .updateUidProcessStateLocked(state, elapsedRealtimeMs, uptimeMs);
4728     }
4729 
4730     @GuardedBy("this")
noteProcessFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4731     public void noteProcessFinishLocked(String name, int uid,
4732             long elapsedRealtimeMs, long uptimeMs) {
4733         uid = mapUid(uid);
4734         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
4735             return;
4736         }
4737         if (!mRecordAllHistory) {
4738             return;
4739         }
4740         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH, name, uid);
4741     }
4742 
4743     @GuardedBy("this")
noteSyncStartLocked(String name, int uid)4744     public void noteSyncStartLocked(String name, int uid) {
4745         noteSyncStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4746     }
4747 
4748     @GuardedBy("this")
noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4749     public void noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4750         uid = mapUid(uid);
4751         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4752                 .noteStartSyncLocked(name, elapsedRealtimeMs);
4753         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
4754             return;
4755         }
4756         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid);
4757     }
4758 
4759     @GuardedBy("this")
noteSyncFinishLocked(String name, int uid)4760     public void noteSyncFinishLocked(String name, int uid) {
4761         noteSyncFinishLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4762     }
4763 
4764     @GuardedBy("this")
noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4765     public void noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4766         uid = mapUid(uid);
4767         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4768                 .noteStopSyncLocked(name, elapsedRealtimeMs);
4769         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
4770             return;
4771         }
4772         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH, name, uid);
4773     }
4774 
4775     @GuardedBy("this")
noteJobStartLocked(String name, int uid)4776     public void noteJobStartLocked(String name, int uid) {
4777         noteJobStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4778     }
4779 
4780     @GuardedBy("this")
noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4781     public void noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4782         uid = mapUid(uid);
4783         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4784                 .noteStartJobLocked(name, elapsedRealtimeMs);
4785         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
4786             return;
4787         }
4788         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid);
4789     }
4790 
4791     @GuardedBy("this")
noteJobFinishLocked(String name, int uid, int stopReason)4792     public void noteJobFinishLocked(String name, int uid, int stopReason) {
4793         noteJobFinishLocked(name, uid, stopReason,
4794                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4795     }
4796 
4797     @GuardedBy("this")
noteJobFinishLocked(String name, int uid, int stopReason, long elapsedRealtimeMs, long uptimeMs)4798     public void noteJobFinishLocked(String name, int uid, int stopReason,
4799             long elapsedRealtimeMs, long uptimeMs) {
4800         uid = mapUid(uid);
4801         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4802                 .noteStopJobLocked(name, elapsedRealtimeMs, stopReason);
4803         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
4804             return;
4805         }
4806         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid);
4807     }
4808 
4809     @GuardedBy("this")
noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast, long elapsedRealtimeMs, long uptimeMs)4810     public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast,
4811             long elapsedRealtimeMs, long uptimeMs) {
4812         uid = mapUid(uid);
4813         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4814                 .noteJobsDeferredLocked(numDeferred, sinceLast);
4815     }
4816 
4817     @GuardedBy("this")
noteAlarmStartLocked(String name, WorkSource workSource, int uid)4818     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
4819         noteAlarmStartLocked(name, workSource, uid,
4820                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4821     }
4822 
4823     @GuardedBy("this")
noteAlarmStartLocked(String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4824     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid,
4825             long elapsedRealtimeMs, long uptimeMs) {
4826         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid,
4827                 elapsedRealtimeMs, uptimeMs);
4828     }
4829 
4830     @GuardedBy("this")
noteAlarmFinishLocked(String name, WorkSource workSource, int uid)4831     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
4832         noteAlarmFinishLocked(name, workSource, uid,
4833                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4834     }
4835 
4836     @GuardedBy("this")
noteAlarmFinishLocked(String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4837     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid,
4838             long elapsedRealtimeMs, long uptimeMs) {
4839         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid,
4840                 elapsedRealtimeMs, uptimeMs);
4841     }
4842 
4843     @GuardedBy("this")
noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4844     private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
4845             int uid, long elapsedRealtimeMs, long uptimeMs) {
4846         if (!mRecordAllHistory) {
4847             return;
4848         }
4849 
4850         if (workSource != null) {
4851             for (int i = 0; i < workSource.size(); ++i) {
4852                 uid = mapUid(workSource.getUid(i));
4853                 if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4854                     mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4855                 }
4856             }
4857 
4858             List<WorkChain> workChains = workSource.getWorkChains();
4859             if (workChains != null) {
4860                 for (int i = 0; i < workChains.size(); ++i) {
4861                     uid = mapUid(workChains.get(i).getAttributionUid());
4862                     if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4863                         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4864                     }
4865                 }
4866             }
4867         } else {
4868             uid = mapUid(uid);
4869 
4870             if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4871                 mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4872             }
4873         }
4874     }
4875 
4876     @GuardedBy("this")
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag)4877     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4878             String tag) {
4879         noteWakupAlarmLocked(packageName, uid, workSource, tag,
4880                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4881     }
4882 
4883     @GuardedBy("this")
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag, long elapsedRealtimeMs, long uptimeMs)4884     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4885             String tag, long elapsedRealtimeMs, long uptimeMs) {
4886         if (workSource != null) {
4887             for (int i = 0; i < workSource.size(); ++i) {
4888                 uid = workSource.getUid(i);
4889                 final String workSourceName = workSource.getPackageName(i);
4890 
4891                 if (isOnBattery()) {
4892                     BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
4893                             workSourceName != null ? workSourceName : packageName,
4894                             elapsedRealtimeMs, uptimeMs);
4895                     pkg.noteWakeupAlarmLocked(tag);
4896                 }
4897             }
4898 
4899             List<WorkChain> workChains = workSource.getWorkChains();
4900             if (workChains != null) {
4901                 for (int i = 0; i < workChains.size(); ++i) {
4902                     final WorkChain wc = workChains.get(i);
4903                     uid = wc.getAttributionUid();
4904 
4905                     if (isOnBattery()) {
4906                         BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName,
4907                                 elapsedRealtimeMs, uptimeMs);
4908                         pkg.noteWakeupAlarmLocked(tag);
4909                     }
4910                 }
4911             }
4912         } else {
4913             if (isOnBattery()) {
4914                 BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName,
4915                         elapsedRealtimeMs, uptimeMs);
4916                 pkg.noteWakeupAlarmLocked(tag);
4917             }
4918         }
4919     }
4920 
requestWakelockCpuUpdate()4921     private void requestWakelockCpuUpdate() {
4922         mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS);
4923     }
4924 
requestImmediateCpuUpdate()4925     private void requestImmediateCpuUpdate() {
4926         mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
4927     }
4928 
4929     @GuardedBy("this")
setRecordAllHistoryLocked(boolean enabled)4930     public void setRecordAllHistoryLocked(boolean enabled) {
4931         mRecordAllHistory = enabled;
4932         if (!enabled) {
4933             // Clear out any existing state.
4934             mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
4935             mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
4936             // Record the currently running processes as stopping, now that we are no
4937             // longer tracking them.
4938             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4939                     HistoryItem.EVENT_PROC);
4940             if (active != null) {
4941                 long mSecRealtime = mClock.elapsedRealtime();
4942                 final long mSecUptime = mClock.uptimeMillis();
4943                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4944                     SparseIntArray uids = ent.getValue();
4945                     for (int j=0; j<uids.size(); j++) {
4946                         mHistory.recordEvent(mSecRealtime, mSecUptime,
4947                                 HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
4948                     }
4949                 }
4950             }
4951         } else {
4952             // Record the currently running processes as starting, now that we are tracking them.
4953             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4954                     HistoryItem.EVENT_PROC);
4955             if (active != null) {
4956                 long mSecRealtime = mClock.elapsedRealtime();
4957                 final long mSecUptime = mClock.uptimeMillis();
4958                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4959                     SparseIntArray uids = ent.getValue();
4960                     for (int j=0; j<uids.size(); j++) {
4961                         mHistory.recordEvent(mSecRealtime, mSecUptime, HistoryItem.EVENT_PROC_START,
4962                                 ent.getKey(), uids.keyAt(j));
4963                     }
4964                 }
4965             }
4966         }
4967     }
4968 
setNoAutoReset(boolean enabled)4969     public void setNoAutoReset(boolean enabled) {
4970         mNoAutoReset = enabled;
4971     }
4972 
4973     @GuardedBy("this")
setPretendScreenOff(boolean pretendScreenOff)4974     public void setPretendScreenOff(boolean pretendScreenOff) {
4975         if (mPretendScreenOff != pretendScreenOff) {
4976             mPretendScreenOff = pretendScreenOff;
4977             final int primaryScreenState = mPerDisplayBatteryStats[0].screenState;
4978             noteScreenStateLocked(0, primaryScreenState,
4979                     mClock.elapsedRealtime(), mClock.uptimeMillis(),
4980                     mClock.currentTimeMillis());
4981         }
4982     }
4983 
4984     @GuardedBy("this")
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging)4985     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4986             int type, boolean unimportantForLogging) {
4987         noteStartWakeLocked(uid, pid, wc, name, historyName, type, unimportantForLogging,
4988                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4989     }
4990 
4991     @GuardedBy("this")
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs)4992     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4993             int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs) {
4994         final int mappedUid = mapUid(uid);
4995         if (type == WAKE_TYPE_PARTIAL) {
4996             // Only care about partial wake locks, since full wake locks
4997             // will be canceled when the user puts the screen to sleep.
4998             if (historyName == null) {
4999                 historyName = name;
5000             }
5001             if (mRecordAllHistory) {
5002                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
5003                         mappedUid, 0)) {
5004                     mHistory.recordEvent(elapsedRealtimeMs, uptimeMs,
5005                             HistoryItem.EVENT_WAKE_LOCK_START, historyName, mappedUid);
5006                 }
5007             }
5008             if (mWakeLockNesting == 0) {
5009                 mWakeLockImportant = !unimportantForLogging;
5010                 mHistory.recordWakelockStartEvent(elapsedRealtimeMs, uptimeMs, historyName,
5011                         mappedUid);
5012             } else if (!mWakeLockImportant && !unimportantForLogging) {
5013                 if (mHistory.maybeUpdateWakelockTag(elapsedRealtimeMs, uptimeMs, historyName,
5014                         mappedUid)) {
5015                     mWakeLockImportant = true;
5016                 }
5017             }
5018             mWakeLockNesting++;
5019         }
5020         if (mappedUid >= 0) {
5021             if (mappedUid != uid) {
5022                 // Prevent the isolated uid mapping from being removed while the wakelock is
5023                 // being held.
5024                 mPowerStatsUidResolver.retainIsolatedUid(uid);
5025             }
5026             if (mOnBatteryScreenOffTimeBase.isRunning()) {
5027                 // We only update the cpu time when a wake lock is acquired if the screen is off.
5028                 // If the screen is on, we don't distribute the power amongst partial wakelocks.
5029                 if (DEBUG_ENERGY_CPU) {
5030                     Slog.d(TAG, "Updating cpu time because of +wake_lock");
5031                 }
5032                 requestWakelockCpuUpdate();
5033             }
5034 
5035             Uid uidStats = getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs);
5036             uidStats.noteStartWakeLocked(pid, name, type, elapsedRealtimeMs);
5037 
5038             mFrameworkStatsLogger.wakelockStateChanged(mapIsolatedUid(uid), wc, name,
5039                     uidStats.mProcessState, true /* acquired */,
5040                     getPowerManagerWakeLockLevel(type));
5041         }
5042     }
5043 
5044     @GuardedBy("this")
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type)5045     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
5046             int type) {
5047         noteStopWakeLocked(uid, pid, wc, name, historyName, type,
5048                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5049     }
5050 
5051     @GuardedBy("this")
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs)5052     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
5053             int type, long elapsedRealtimeMs, long uptimeMs) {
5054         final int mappedUid = mapUid(uid);
5055         if (type == WAKE_TYPE_PARTIAL) {
5056             mWakeLockNesting--;
5057             if (historyName == null) {
5058                 historyName = name;
5059             }
5060             if (mRecordAllHistory) {
5061                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
5062                         mappedUid, 0)) {
5063                     mHistory.recordEvent(elapsedRealtimeMs, uptimeMs,
5064                             HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, mappedUid);
5065                 }
5066             }
5067             if (mWakeLockNesting == 0) {
5068                 mHistory.recordWakelockStopEvent(elapsedRealtimeMs, uptimeMs, historyName,
5069                         mappedUid);
5070             }
5071         }
5072         if (mappedUid >= 0) {
5073             if (mOnBatteryScreenOffTimeBase.isRunning()) {
5074                 if (DEBUG_ENERGY_CPU) {
5075                     Slog.d(TAG, "Updating cpu time because of -wake_lock");
5076                 }
5077                 requestWakelockCpuUpdate();
5078             }
5079 
5080             Uid uidStats = getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs);
5081             uidStats.noteStopWakeLocked(pid, name, type, elapsedRealtimeMs);
5082 
5083             mFrameworkStatsLogger.wakelockStateChanged(mapIsolatedUid(uid), wc, name,
5084                     uidStats.mProcessState, false/* acquired */,
5085                     getPowerManagerWakeLockLevel(type));
5086 
5087             if (mappedUid != uid) {
5088                 // Decrement the ref count for the isolated uid and delete the mapping if uneeded.
5089                 releaseIsolatedUidLocked(uid, elapsedRealtimeMs, uptimeMs);
5090             }
5091         }
5092     }
5093 
5094     /**
5095      * Converts BatteryStats wakelock types back into PowerManager wakelock levels.
5096      * This is the inverse map of Notifier.getBatteryStatsWakeLockMonitorType().
5097      * These are estimations, since batterystats loses some of the original data.
5098      * TODO: Delete this. Instead, FrameworkStatsLog.write should be called from
5099      * PowerManager's Notifier.
5100      */
getPowerManagerWakeLockLevel(int batteryStatsWakelockType)5101     private int getPowerManagerWakeLockLevel(int batteryStatsWakelockType) {
5102         switch (batteryStatsWakelockType) {
5103             // PowerManager.PARTIAL_WAKE_LOCK or PROXIMITY_SCREEN_OFF_WAKE_LOCK
5104             case BatteryStats.WAKE_TYPE_PARTIAL:
5105                 return PowerManager.PARTIAL_WAKE_LOCK;
5106 
5107             // PowerManager.SCREEN_DIM_WAKE_LOCK or SCREEN_BRIGHT_WAKE_LOCK
5108             case BatteryStats.WAKE_TYPE_FULL:
5109                 return PowerManager.FULL_WAKE_LOCK;
5110 
5111             case BatteryStats.WAKE_TYPE_DRAW:
5112                 return PowerManager.DRAW_WAKE_LOCK;
5113 
5114             // It appears that nothing can ever make a Window and PowerManager lacks an equivalent.
5115             case BatteryStats.WAKE_TYPE_WINDOW:
5116                 Slog.e(TAG, "Illegal window wakelock type observed in batterystats.");
5117                 return -1;
5118 
5119             default:
5120                 Slog.e(TAG, "Illegal wakelock type in batterystats: " + batteryStatsWakelockType);
5121                 return -1;
5122         }
5123     }
5124 
5125     @GuardedBy("this")
noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs)5126     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
5127             String historyName, int type, boolean unimportantForLogging,
5128             long elapsedRealtimeMs, long uptimeMs) {
5129         final int N = ws.size();
5130         for (int i=0; i<N; i++) {
5131             noteStartWakeLocked(ws.getUid(i), pid, null, name, historyName, type,
5132                     unimportantForLogging, elapsedRealtimeMs, uptimeMs);
5133         }
5134 
5135         List<WorkChain> wcs = ws.getWorkChains();
5136         if (wcs != null) {
5137             for (int i = 0; i < wcs.size(); ++i) {
5138                 final WorkChain wc = wcs.get(i);
5139                 noteStartWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
5140                         unimportantForLogging, elapsedRealtimeMs, uptimeMs);
5141             }
5142         }
5143     }
5144 
5145     @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)5146     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
5147             String historyName, int type, WorkSource newWs, int newPid, String newName,
5148             String newHistoryName, int newType, boolean newUnimportantForLogging,
5149             long elapsedRealtimeMs, long uptimeMs) {
5150         List<WorkChain>[] wcs = WorkSource.diffChains(ws, newWs);
5151 
5152         // For correct semantics, we start the need worksources first, so that we won't
5153         // make inappropriate history items as if all wake locks went away and new ones
5154         // appeared.  This is okay because tracking of wake locks allows nesting.
5155         //
5156         // First the starts :
5157         final int NN = newWs.size();
5158         for (int i=0; i<NN; i++) {
5159             noteStartWakeLocked(newWs.getUid(i), newPid, null, newName, newHistoryName, newType,
5160                     newUnimportantForLogging, elapsedRealtimeMs, uptimeMs);
5161         }
5162         if (wcs != null) {
5163             List<WorkChain> newChains = wcs[0];
5164             if (newChains != null) {
5165                 for (int i = 0; i < newChains.size(); ++i) {
5166                     final WorkChain newChain = newChains.get(i);
5167                     noteStartWakeLocked(newChain.getAttributionUid(), newPid, newChain, newName,
5168                             newHistoryName, newType, newUnimportantForLogging, elapsedRealtimeMs,
5169                             uptimeMs);
5170                 }
5171             }
5172         }
5173 
5174         // Then the stops :
5175         final int NO = ws.size();
5176         for (int i=0; i<NO; i++) {
5177             noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs,
5178                     uptimeMs);
5179         }
5180         if (wcs != null) {
5181             List<WorkChain> goneChains = wcs[1];
5182             if (goneChains != null) {
5183                 for (int i = 0; i < goneChains.size(); ++i) {
5184                     final WorkChain goneChain = goneChains.get(i);
5185                     noteStopWakeLocked(goneChain.getAttributionUid(), pid, goneChain, name,
5186                             historyName, type, elapsedRealtimeMs, uptimeMs);
5187                 }
5188             }
5189         }
5190     }
5191 
5192     @GuardedBy("this")
noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs)5193     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
5194             String historyName, int type, long elapsedRealtimeMs, long uptimeMs) {
5195         final int N = ws.size();
5196         for (int i=0; i<N; i++) {
5197             noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs,
5198                     uptimeMs);
5199         }
5200 
5201         List<WorkChain> wcs = ws.getWorkChains();
5202         if (wcs != null) {
5203             for (int i = 0; i < wcs.size(); ++i) {
5204                 final WorkChain wc = wcs.get(i);
5205                 noteStopWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
5206                         elapsedRealtimeMs, uptimeMs);
5207             }
5208         }
5209     }
5210 
5211     @GuardedBy("this")
noteLongPartialWakelockStart(String name, String historyName, int uid)5212     public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
5213         noteLongPartialWakelockStart(name, historyName, uid,
5214                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5215     }
5216 
5217     @GuardedBy("this")
noteLongPartialWakelockStart(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5218     public void noteLongPartialWakelockStart(String name, String historyName, int uid,
5219             long elapsedRealtimeMs, long uptimeMs) {
5220         noteLongPartialWakeLockStartInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
5221     }
5222 
5223     @GuardedBy("this")
noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource, long elapsedRealtimeMs, long uptimeMs)5224     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
5225             WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
5226         final int N = workSource.size();
5227         for (int i = 0; i < N; ++i) {
5228             final int uid = mapUid(workSource.getUid(i));
5229             noteLongPartialWakeLockStartInternal(name, historyName, uid,
5230                     elapsedRealtimeMs, uptimeMs);
5231         }
5232 
5233         final List<WorkChain> workChains = workSource.getWorkChains();
5234         if (workChains != null) {
5235             for (int i = 0; i < workChains.size(); ++i) {
5236                 final WorkChain workChain = workChains.get(i);
5237                 final int uid = workChain.getAttributionUid();
5238                 noteLongPartialWakeLockStartInternal(name, historyName, uid,
5239                         elapsedRealtimeMs, uptimeMs);
5240             }
5241         }
5242     }
5243 
5244     @GuardedBy("this")
noteLongPartialWakeLockStartInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5245     private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid,
5246             long elapsedRealtimeMs, long uptimeMs) {
5247         final int mappedUid = mapUid(uid);
5248         if (historyName == null) {
5249             historyName = name;
5250         }
5251         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName,
5252                 mappedUid, 0)) {
5253             return;
5254         }
5255         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
5256                 historyName, mappedUid);
5257         if (mappedUid != uid) {
5258             // Prevent the isolated uid mapping from being removed while the wakelock is
5259             // being held.
5260             mPowerStatsUidResolver.retainIsolatedUid(uid);
5261         }
5262     }
5263 
5264     @GuardedBy("this")
noteLongPartialWakelockFinish(String name, String historyName, int uid)5265     public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
5266         noteLongPartialWakelockFinish(name, historyName, uid,
5267                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5268     }
5269 
5270     @GuardedBy("this")
noteLongPartialWakelockFinish(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5271     public void noteLongPartialWakelockFinish(String name, String historyName, int uid,
5272             long elapsedRealtimeMs, long uptimeMs) {
5273         noteLongPartialWakeLockFinishInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
5274     }
5275 
5276     @GuardedBy("this")
noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource, long elapsedRealtimeMs, long uptimeMs)5277     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
5278             WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
5279         final int N = workSource.size();
5280         for (int i = 0; i < N; ++i) {
5281             final int uid = mapUid(workSource.getUid(i));
5282             noteLongPartialWakeLockFinishInternal(name, historyName, uid,
5283                     elapsedRealtimeMs, uptimeMs);
5284         }
5285 
5286         final List<WorkChain> workChains = workSource.getWorkChains();
5287         if (workChains != null) {
5288             for (int i = 0; i < workChains.size(); ++i) {
5289                 final WorkChain workChain = workChains.get(i);
5290                 final int uid = workChain.getAttributionUid();
5291                 noteLongPartialWakeLockFinishInternal(name, historyName, uid,
5292                         elapsedRealtimeMs, uptimeMs);
5293             }
5294         }
5295     }
5296 
5297     @GuardedBy("this")
noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5298     private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid,
5299             long elapsedRealtimeMs, long uptimeMs) {
5300         final int mappedUid = mapUid(uid);
5301         if (historyName == null) {
5302             historyName = name;
5303         }
5304         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName,
5305                 mappedUid, 0)) {
5306             return;
5307         }
5308         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
5309                 historyName, mappedUid);
5310         if (mappedUid != uid) {
5311             // Decrement the ref count for the isolated uid and delete the mapping if uneeded.
5312             releaseIsolatedUidLocked(uid, elapsedRealtimeMs, uptimeMs);
5313         }
5314     }
5315 
5316     @GuardedBy("this")
noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs)5317     public void noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs) {
5318         if (mLastWakeupReason != null) {
5319             long deltaUptimeMs = uptimeMs - mLastWakeupUptimeMs;
5320             SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
5321             timer.add(deltaUptimeMs * 1000, 1, elapsedRealtimeMs); // time in in microseconds
5322             mFrameworkStatsLogger.kernelWakeupReported(deltaUptimeMs * 1000, mLastWakeupReason,
5323                     mLastWakeupElapsedTimeMs);
5324         }
5325         mHistory.recordWakeupEvent(elapsedRealtimeMs, uptimeMs, reason);
5326         mLastWakeupReason = reason;
5327         mLastWakeupUptimeMs = uptimeMs;
5328         mLastWakeupElapsedTimeMs = elapsedRealtimeMs;
5329     }
5330 
5331     @GuardedBy("this")
startAddingCpuStatsLocked()5332     public boolean startAddingCpuStatsLocked() {
5333         mExternalSync.cancelCpuSyncDueToWakelockChange();
5334         return mOnBatteryInternal;
5335     }
5336 
5337     @GuardedBy("this")
addCpuStatsLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs, int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs, int statSoftIrqTimeMs, int statIdleTimeMs)5338     public void addCpuStatsLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs,
5339             int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
5340             int statSoftIrqTimeMs, int statIdleTimeMs) {
5341         mStepDetailsCalculator.addCpuStats(totalUTimeMs, totalSTimeMs, statUserTimeMs,
5342                 statSystemTimeMs, statIOWaitTimeMs, statIrqTimeMs,
5343                 statSoftIrqTimeMs, statIdleTimeMs);
5344     }
5345 
5346     /**
5347      * Called after {@link #addCpuStatsLocked} has been invoked for all active apps.
5348      */
5349     @GuardedBy("this")
finishAddingCpuStatsLocked()5350     public void finishAddingCpuStatsLocked() {
5351         mStepDetailsCalculator.finishAddingCpuLocked();
5352     }
5353 
noteProcessDiedLocked(int uid, int pid)5354     public void noteProcessDiedLocked(int uid, int pid) {
5355         uid = mapUid(uid);
5356         Uid u = mUidStats.get(uid);
5357         if (u != null) {
5358             u.mPids.remove(pid);
5359         }
5360     }
5361 
reportExcessiveCpuLocked(int uid, String proc, long overTimeMs, long usedTimeMs)5362     public void reportExcessiveCpuLocked(int uid, String proc, long overTimeMs, long usedTimeMs) {
5363         uid = mapUid(uid);
5364         Uid u = mUidStats.get(uid);
5365         if (u != null) {
5366             u.reportExcessiveCpuLocked(proc, overTimeMs, usedTimeMs);
5367         }
5368     }
5369 
5370     int mSensorNesting;
5371 
5372     @GuardedBy("this")
noteStartSensorLocked(int uid, int sensor)5373     public void noteStartSensorLocked(int uid, int sensor) {
5374         noteStartSensorLocked(uid, sensor, mClock.elapsedRealtime(), mClock.uptimeMillis());
5375     }
5376 
5377     @GuardedBy("this")
noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs)5378     public void noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
5379         uid = mapUid(uid);
5380         if (mSensorNesting == 0) {
5381             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
5382                     HistoryItem.STATE_SENSOR_ON_FLAG);
5383         }
5384         mSensorNesting++;
5385         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5386                 .noteStartSensor(sensor, elapsedRealtimeMs);
5387     }
5388 
5389     @GuardedBy("this")
noteStopSensorLocked(int uid, int sensor)5390     public void noteStopSensorLocked(int uid, int sensor) {
5391         noteStopSensorLocked(uid, sensor, mClock.elapsedRealtime(), mClock.uptimeMillis());
5392     }
5393 
5394     @GuardedBy("this")
noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs)5395     public void noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
5396         uid = mapUid(uid);
5397         mSensorNesting--;
5398         if (mSensorNesting == 0) {
5399             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
5400                     HistoryItem.STATE_SENSOR_ON_FLAG);
5401         }
5402         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5403                 .noteStopSensor(sensor, elapsedRealtimeMs);
5404     }
5405 
5406     int mGpsNesting;
5407 
5408     @GuardedBy("this")
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs)5409     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
5410         noteGpsChangedLocked(oldWs, newWs, mClock.elapsedRealtime(), mClock.uptimeMillis());
5411     }
5412 
5413     @GuardedBy("this")
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs, long elapsedRealtimeMs, long uptimeMs)5414     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs,
5415             long elapsedRealtimeMs, long uptimeMs) {
5416         for (int i = 0; i < newWs.size(); ++i) {
5417             noteStartGpsLocked(newWs.getUid(i), null, elapsedRealtimeMs, uptimeMs);
5418         }
5419 
5420         for (int i = 0; i < oldWs.size(); ++i) {
5421             noteStopGpsLocked((oldWs.getUid(i)), null, elapsedRealtimeMs, uptimeMs);
5422         }
5423 
5424         List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
5425         if (wcs != null) {
5426             if (wcs[0] != null) {
5427                 final List<WorkChain> newChains = wcs[0];
5428                 for (int i = 0; i < newChains.size(); ++i) {
5429                     noteStartGpsLocked(-1, newChains.get(i), elapsedRealtimeMs, uptimeMs);
5430                 }
5431             }
5432 
5433             if (wcs[1] != null) {
5434                 final List<WorkChain> goneChains = wcs[1];
5435                 for (int i = 0; i < goneChains.size(); ++i) {
5436                     noteStopGpsLocked(-1, goneChains.get(i), elapsedRealtimeMs, uptimeMs);
5437                 }
5438             }
5439         }
5440     }
5441 
5442     @GuardedBy("this")
noteStartGpsLocked(int uid, WorkChain workChain, long elapsedRealtimeMs, long uptimeMs)5443     private void noteStartGpsLocked(int uid, WorkChain workChain,
5444             long elapsedRealtimeMs, long uptimeMs) {
5445         if (workChain != null) {
5446             uid = workChain.getAttributionUid();
5447         }
5448         final int mappedUid = mapUid(uid);
5449         if (mGpsNesting == 0) {
5450             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
5451                     HistoryItem.STATE_GPS_ON_FLAG, uid, "gnss");
5452             if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_GNSS)) {
5453                 mGnssPowerStatsCollector.schedule();
5454             }
5455         }
5456         mGpsNesting++;
5457 
5458         mFrameworkStatsLogger.gpsScanStateChanged(mapIsolatedUid(uid), workChain, /* on */true);
5459 
5460         getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs).noteStartGps(elapsedRealtimeMs);
5461     }
5462 
5463     @GuardedBy("this")
noteStopGpsLocked(int uid, WorkChain workChain, long elapsedRealtimeMs, long uptimeMs)5464     private void noteStopGpsLocked(int uid, WorkChain workChain,
5465             long elapsedRealtimeMs, long uptimeMs) {
5466         if (workChain != null) {
5467             uid = workChain.getAttributionUid();
5468         }
5469         final int mappedUid = mapUid(uid);
5470         mGpsNesting--;
5471         if (mGpsNesting == 0) {
5472             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
5473                     HistoryItem.STATE_GPS_ON_FLAG, uid, "gnss");
5474             mHistory.recordGpsSignalQualityEvent(elapsedRealtimeMs, uptimeMs,
5475                     GPS_SIGNAL_QUALITY_NONE);
5476             stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
5477             mGpsSignalQualityBin = -1;
5478             if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_GNSS)) {
5479                 mGnssPowerStatsCollector.schedule();
5480             }
5481         }
5482 
5483         mFrameworkStatsLogger.gpsScanStateChanged(mapIsolatedUid(uid), workChain, /* on */ false);
5484 
5485         getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs).noteStopGps(elapsedRealtimeMs);
5486     }
5487 
5488     @GuardedBy("this")
noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs)5489     public void noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs) {
5490         if (mGpsNesting == 0) {
5491             return;
5492         }
5493         if (signalLevel < 0 || signalLevel >= mGpsSignalQualityTimer.length) {
5494             stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
5495             return;
5496         }
5497         if (mGpsSignalQualityBin != signalLevel) {
5498             if (mGpsSignalQualityBin >= 0) {
5499                 mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtimeMs);
5500             }
5501             if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
5502                 mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtimeMs);
5503             }
5504             mHistory.recordGpsSignalQualityEvent(elapsedRealtimeMs, uptimeMs, signalLevel);
5505             mGpsSignalQualityBin = signalLevel;
5506         }
5507     }
5508 
5509     @GuardedBy("this")
noteScreenStateLocked(int display, int state)5510     public void noteScreenStateLocked(int display, int state) {
5511         noteScreenStateLocked(display, state, mClock.elapsedRealtime(), mClock.uptimeMillis(),
5512                 mClock.currentTimeMillis());
5513     }
5514 
5515     @GuardedBy("this")
noteScreenStateLocked(int display, int displayState, long elapsedRealtimeMs, long uptimeMs, long currentTimeMs)5516     public void noteScreenStateLocked(int display, int displayState,
5517             long elapsedRealtimeMs, long uptimeMs, long currentTimeMs) {
5518         // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
5519         // original 4 are mapped to one of the originals.
5520         if (displayState > MAX_TRACKED_SCREEN_STATE) {
5521             if (Display.isOnState(displayState)) {
5522                 displayState = Display.STATE_ON;
5523             } else if (Display.isDozeState(displayState)) {
5524                 if (Display.isSuspendedState(displayState)) {
5525                     displayState = Display.STATE_DOZE_SUSPEND;
5526                 } else {
5527                     displayState = Display.STATE_DOZE;
5528                 }
5529             } else if (Display.isOffState(displayState)) {
5530                 displayState = Display.STATE_OFF;
5531             } else {
5532                 Slog.wtf(TAG, "Unknown screen state (not mapped): " + displayState);
5533                 displayState = Display.STATE_UNKNOWN;
5534             }
5535         }
5536         // As of this point, displayState should be mapped to one of:
5537         //  - Display.STATE_ON,
5538         //  - Display.STATE_DOZE
5539         //  - Display.STATE_DOZE_SUSPEND
5540         //  - Display.STATE_OFF
5541         //  - Display.STATE_UNKNOWN
5542 
5543         int state;
5544         int overallBin = mScreenBrightnessBin;
5545         int externalUpdateFlag = 0;
5546         boolean shouldScheduleSync = false;
5547         final int numDisplay = mPerDisplayBatteryStats.length;
5548         if (display < 0 || display >= numDisplay) {
5549             Slog.wtf(TAG, "Unexpected note screen state for display " + display + " (only "
5550                     + mPerDisplayBatteryStats.length + " displays exist...)");
5551             return;
5552         }
5553         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
5554         final int oldDisplayState = displayStats.screenState;
5555 
5556         if (oldDisplayState == displayState) {
5557             // Nothing changed
5558             state = mScreenState;
5559         } else {
5560             displayStats.screenState = displayState;
5561 
5562             // Stop timer for previous display state.
5563             switch (oldDisplayState) {
5564                 case Display.STATE_ON:
5565                     displayStats.screenOnTimer.stopRunningLocked(elapsedRealtimeMs);
5566                     final int bin = displayStats.screenBrightnessBin;
5567                     if (bin >= 0) {
5568                         displayStats.screenBrightnessTimers[bin].stopRunningLocked(
5569                                 elapsedRealtimeMs);
5570                     }
5571                     overallBin = evaluateOverallScreenBrightnessBinLocked();
5572                     shouldScheduleSync = true;
5573                     break;
5574                 case Display.STATE_DOZE:
5575                     // Transition from doze to doze suspend can be ignored.
5576                     if (displayState == Display.STATE_DOZE_SUSPEND) break;
5577                     displayStats.screenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5578                     shouldScheduleSync = true;
5579                     break;
5580                 case Display.STATE_DOZE_SUSPEND:
5581                     // Transition from doze suspend to doze can be ignored.
5582                     if (displayState == Display.STATE_DOZE) break;
5583                     displayStats.screenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5584                     shouldScheduleSync = true;
5585                     break;
5586                 case Display.STATE_OFF: // fallthrough
5587                 case Display.STATE_UNKNOWN:
5588                     // Not tracked by timers.
5589                     break;
5590                 default:
5591                     Slog.wtf(TAG,
5592                             "Attempted to stop timer for unexpected display state " + display);
5593             }
5594 
5595             // Start timer for new display state.
5596             switch (displayState) {
5597                 case Display.STATE_ON:
5598                     displayStats.screenOnTimer.startRunningLocked(elapsedRealtimeMs);
5599                     final int bin = displayStats.screenBrightnessBin;
5600                     if (bin >= 0) {
5601                         displayStats.screenBrightnessTimers[bin].startRunningLocked(
5602                                 elapsedRealtimeMs);
5603                     }
5604                     overallBin = evaluateOverallScreenBrightnessBinLocked();
5605                     shouldScheduleSync = true;
5606                     break;
5607                 case Display.STATE_DOZE:
5608                     // Transition from doze suspend to doze can be ignored.
5609                     if (oldDisplayState == Display.STATE_DOZE_SUSPEND) break;
5610                     displayStats.screenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5611                     shouldScheduleSync = true;
5612                     break;
5613                 case Display.STATE_DOZE_SUSPEND:
5614                     // Transition from doze to doze suspend can be ignored.
5615                     if (oldDisplayState == Display.STATE_DOZE) break;
5616                     displayStats.screenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5617                     shouldScheduleSync = true;
5618                     break;
5619                 case Display.STATE_OFF: // fallthrough
5620                 case Display.STATE_UNKNOWN:
5621                     // Not tracked by timers.
5622                     break;
5623                 default:
5624                     Slog.wtf(TAG,
5625                             "Attempted to start timer for unexpected display state " + displayState
5626                                     + " for display " + display);
5627             }
5628 
5629             if (shouldScheduleSync
5630                     && mGlobalEnergyConsumerStats != null
5631                     && mGlobalEnergyConsumerStats.isStandardBucketSupported(
5632                     EnergyConsumerStats.POWER_BUCKET_SCREEN_ON)) {
5633                 // Display energy consumption stats is available. Prepare to schedule an
5634                 // external sync.
5635                 externalUpdateFlag |= ExternalStatsSync.UPDATE_DISPLAY;
5636             }
5637 
5638             // Reevaluate most important display screen state.
5639             state = Display.STATE_UNKNOWN;
5640             for (int i = 0; i < numDisplay; i++) {
5641                 final int tempState = mPerDisplayBatteryStats[i].screenState;
5642                 if (tempState == Display.STATE_ON
5643                         || state == Display.STATE_ON) {
5644                     state = Display.STATE_ON;
5645                 } else if (tempState == Display.STATE_DOZE
5646                         || state == Display.STATE_DOZE) {
5647                     state = Display.STATE_DOZE;
5648                 } else if (tempState == Display.STATE_DOZE_SUSPEND
5649                         || state == Display.STATE_DOZE_SUSPEND) {
5650                     state = Display.STATE_DOZE_SUSPEND;
5651                 } else if (tempState == Display.STATE_OFF
5652                         || state == Display.STATE_OFF) {
5653                     state = Display.STATE_OFF;
5654                 }
5655             }
5656         }
5657 
5658         final boolean batteryRunning = mOnBatteryTimeBase.isRunning();
5659         final boolean batteryScreenOffRunning = mOnBatteryScreenOffTimeBase.isRunning();
5660 
5661         state = mPretendScreenOff ? Display.STATE_OFF : state;
5662         if (mScreenState != state) {
5663             recordDailyStatsIfNeededLocked(true, currentTimeMs);
5664             final int oldState = mScreenState;
5665             mScreenState = state;
5666             if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
5667                     + ", newState=" + Display.stateToString(state));
5668 
5669             if (state != Display.STATE_UNKNOWN) {
5670                 int stepState = state-1;
5671                 if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
5672                     mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
5673                     mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
5674                 } else {
5675                     Slog.wtf(TAG, "Unexpected screen state: " + state);
5676                 }
5677             }
5678 
5679             int startStates = 0;
5680             int stopStates = 0;
5681             if (Display.isDozeState(state) && !Display.isDozeState(oldState)) {
5682                 startStates |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
5683                 mScreenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5684             } else if (Display.isDozeState(oldState) && !Display.isDozeState(state)) {
5685                 stopStates |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
5686                 mScreenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5687             }
5688             if (Display.isOnState(state)) {
5689                 startStates |= HistoryItem.STATE_SCREEN_ON_FLAG;
5690                 mScreenOnTimer.startRunningLocked(elapsedRealtimeMs);
5691                 if (mScreenBrightnessBin >= 0) {
5692                     mScreenBrightnessTimer[mScreenBrightnessBin]
5693                             .startRunningLocked(elapsedRealtimeMs);
5694                 }
5695             } else if (Display.isOnState(oldState)) {
5696                 stopStates |= HistoryItem.STATE_SCREEN_ON_FLAG;
5697                 mScreenOnTimer.stopRunningLocked(elapsedRealtimeMs);
5698                 if (mScreenBrightnessBin >= 0) {
5699                     mScreenBrightnessTimer[mScreenBrightnessBin]
5700                             .stopRunningLocked(elapsedRealtimeMs);
5701                 }
5702             }
5703             if (startStates != 0 || stopStates != 0) {
5704                 mHistory.recordStateChangeEvent(elapsedRealtimeMs, uptimeMs, startStates,
5705                         stopStates);
5706             }
5707 
5708             // Per screen state Cpu stats needed. Prepare to schedule an external sync.
5709             externalUpdateFlag |= ExternalStatsSync.UPDATE_CPU;
5710             shouldScheduleSync = true;
5711 
5712             if (Display.isOnState(state)) {
5713                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
5714                         uptimeMs * 1000, elapsedRealtimeMs * 1000);
5715                 // Fake a wake lock, so we consider the device waked as long as the screen is on.
5716                 noteStartWakeLocked(-1, -1, null, "screen", null, WAKE_TYPE_PARTIAL, false,
5717                         elapsedRealtimeMs, uptimeMs);
5718             } else if (Display.isOnState(oldState)) {
5719                 noteStopWakeLocked(-1, -1, null, "screen", "screen", WAKE_TYPE_PARTIAL,
5720                         elapsedRealtimeMs, uptimeMs);
5721                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
5722                         uptimeMs * 1000, elapsedRealtimeMs * 1000);
5723             }
5724             // Update discharge amounts.
5725             if (mOnBatteryInternal) {
5726                 updateDischargeScreenLevelsLocked(oldState, state);
5727             }
5728         }
5729 
5730         // Changing display states might have changed the screen used to determine the overall
5731         // brightness.
5732         maybeUpdateOverallScreenBrightness(overallBin, elapsedRealtimeMs, uptimeMs);
5733 
5734         if (shouldScheduleSync) {
5735             final int numDisplays = mPerDisplayBatteryStats.length;
5736             final int[] displayStates = new int[numDisplays];
5737             for (int i = 0; i < numDisplays; i++) {
5738                 displayStates[i] = mPerDisplayBatteryStats[i].screenState;
5739             }
5740             mExternalSync.scheduleSyncDueToScreenStateChange(externalUpdateFlag,
5741                     batteryRunning, batteryScreenOffRunning, state, displayStates);
5742         }
5743     }
5744 
5745     /**
5746      * Note screen brightness change for a display.
5747      */
5748     @GuardedBy("this")
noteScreenBrightnessLocked(int display, int brightness)5749     public void noteScreenBrightnessLocked(int display, int brightness) {
5750         noteScreenBrightnessLocked(display, brightness, mClock.elapsedRealtime(),
5751                 mClock.uptimeMillis());
5752     }
5753 
5754 
5755     /**
5756      * Note screen brightness change for a display.
5757      */
5758     @GuardedBy("this")
noteScreenBrightnessLocked(int display, int brightness, long elapsedRealtimeMs, long uptimeMs)5759     public void noteScreenBrightnessLocked(int display, int brightness, long elapsedRealtimeMs,
5760             long uptimeMs) {
5761         // Bin the brightness.
5762         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
5763         if (bin < 0) bin = 0;
5764         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
5765 
5766         final int overallBin;
5767 
5768         final int numDisplays = mPerDisplayBatteryStats.length;
5769         if (display < 0 || display >= numDisplays) {
5770             Slog.wtf(TAG, "Unexpected note screen brightness for display " + display + " (only "
5771                     + mPerDisplayBatteryStats.length + " displays exist...)");
5772             return;
5773         }
5774 
5775         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
5776         final int oldBin = displayStats.screenBrightnessBin;
5777         if (oldBin == bin) {
5778             // Nothing changed
5779             overallBin = mScreenBrightnessBin;
5780         } else {
5781             displayStats.screenBrightnessBin = bin;
5782             if (displayStats.screenState == Display.STATE_ON) {
5783                 if (oldBin >= 0) {
5784                     displayStats.screenBrightnessTimers[oldBin].stopRunningLocked(
5785                             elapsedRealtimeMs);
5786                 }
5787                 displayStats.screenBrightnessTimers[bin].startRunningLocked(
5788                         elapsedRealtimeMs);
5789             }
5790             overallBin = evaluateOverallScreenBrightnessBinLocked();
5791         }
5792 
5793         maybeUpdateOverallScreenBrightness(overallBin, elapsedRealtimeMs, uptimeMs);
5794     }
5795 
5796     @GuardedBy("this")
evaluateOverallScreenBrightnessBinLocked()5797     private int evaluateOverallScreenBrightnessBinLocked() {
5798         int overallBin = -1;
5799         final int numDisplays = getDisplayCount();
5800         for (int display = 0; display < numDisplays; display++) {
5801             final int displayBrightnessBin;
5802             if (mPerDisplayBatteryStats[display].screenState == Display.STATE_ON) {
5803                 displayBrightnessBin = mPerDisplayBatteryStats[display].screenBrightnessBin;
5804             } else {
5805                 displayBrightnessBin = -1;
5806             }
5807             if (displayBrightnessBin > overallBin) {
5808                 overallBin = displayBrightnessBin;
5809             }
5810         }
5811         return overallBin;
5812     }
5813 
5814     @GuardedBy("this")
maybeUpdateOverallScreenBrightness(int overallBin, long elapsedRealtimeMs, long uptimeMs)5815     private void maybeUpdateOverallScreenBrightness(int overallBin, long elapsedRealtimeMs,
5816             long uptimeMs) {
5817         if (mScreenBrightnessBin != overallBin) {
5818             if (overallBin >= 0) {
5819                 mHistory.recordScreenBrightnessEvent(elapsedRealtimeMs, uptimeMs, overallBin);
5820             }
5821             if (mScreenState == Display.STATE_ON) {
5822                 if (mScreenBrightnessBin >= 0) {
5823                     mScreenBrightnessTimer[mScreenBrightnessBin]
5824                             .stopRunningLocked(elapsedRealtimeMs);
5825                 }
5826                 if (overallBin >= 0) {
5827                     mScreenBrightnessTimer[overallBin]
5828                             .startRunningLocked(elapsedRealtimeMs);
5829                 }
5830             }
5831             mScreenBrightnessBin = overallBin;
5832         }
5833     }
5834 
5835     @GuardedBy("this")
noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event, long elapsedRealtimeMs, long uptimeMs)5836     public void noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event,
5837             long elapsedRealtimeMs, long uptimeMs) {
5838         if (mOnBatteryInternal) {
5839             uid = mapUid(uid);
5840             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteUserActivityLocked(event);
5841         }
5842     }
5843 
5844     @GuardedBy("this")
noteWakeUpLocked(String reason, int reasonUid, long elapsedRealtimeMs, long uptimeMs)5845     public void noteWakeUpLocked(String reason, int reasonUid,
5846             long elapsedRealtimeMs, long uptimeMs) {
5847         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP, reason,
5848                 reasonUid);
5849     }
5850 
5851     @GuardedBy("this")
noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs)5852     public void noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs) {
5853         if (mInteractive != interactive) {
5854             mInteractive = interactive;
5855             if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
5856             if (interactive) {
5857                 mInteractiveTimer.startRunningLocked(elapsedRealtimeMs);
5858             } else {
5859                 mInteractiveTimer.stopRunningLocked(elapsedRealtimeMs);
5860             }
5861         }
5862     }
5863 
5864     @GuardedBy("this")
noteConnectivityChangedLocked(int type, String extra, long elapsedRealtimeMs, long uptimeMs)5865     public void noteConnectivityChangedLocked(int type, String extra,
5866             long elapsedRealtimeMs, long uptimeMs) {
5867         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
5868                 extra, type);
5869         mNumConnectivityChange++;
5870     }
5871 
5872     @GuardedBy("this")
noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)5873     private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
5874             final long uptimeMillis, int uid) {
5875         uid = mapUid(uid);
5876         mHistory.recordEvent(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
5877                 uid);
5878         getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteMobileRadioApWakeupLocked();
5879     }
5880 
5881     /**
5882      * Updates the radio power state and returns true if an external stats collection should occur.
5883      */
5884     @GuardedBy("this")
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid)5885     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
5886         return noteMobileRadioPowerStateLocked(powerState, timestampNs, uid,
5887                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5888     }
5889 
5890     @GuardedBy("this")
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid, long elapsedRealtimeMs, long uptimeMs)5891     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid,
5892             long elapsedRealtimeMs, long uptimeMs) {
5893         if (mMobileRadioPowerState != powerState) {
5894             long realElapsedRealtimeMs;
5895             final boolean active = isActiveRadioPowerState(powerState);
5896             if (active) {
5897                 if (uid > 0) {
5898                     noteMobileRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
5899                 }
5900 
5901                 mMobileRadioActiveStartTimeMs = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
5902                 mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
5903                         HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG);
5904             } else {
5905                 realElapsedRealtimeMs = timestampNs / (1000*1000);
5906                 long lastUpdateTimeMs = mMobileRadioActiveStartTimeMs;
5907                 if (realElapsedRealtimeMs < lastUpdateTimeMs) {
5908                     Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
5909                             + " is before start time " + lastUpdateTimeMs);
5910                     realElapsedRealtimeMs = elapsedRealtimeMs;
5911                 } else if (realElapsedRealtimeMs < elapsedRealtimeMs) {
5912                     mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtimeMs
5913                             - realElapsedRealtimeMs);
5914                 }
5915                 mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
5916                         HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG);
5917             }
5918             mMobileRadioPowerState = powerState;
5919 
5920             // Inform current RatBatteryStats that the modem active state might have changed.
5921             getRatBatteryStatsLocked(mActiveRat).noteActive(active, elapsedRealtimeMs);
5922 
5923             if (active) {
5924                 mMobileRadioActiveTimer.startRunningLocked(elapsedRealtimeMs);
5925                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtimeMs);
5926             } else {
5927                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
5928                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
5929 
5930                 if (mMobileRadioPowerStatsCollector.isEnabled()) {
5931                     mMobileRadioPowerStatsCollector.schedule();
5932                 } else {
5933                     // Check if modem Activity info has been collected recently, don't bother
5934                     // triggering another update.
5935                     if (mLastModemActivityInfo == null
5936                             || elapsedRealtimeMs >= mLastModemActivityInfo.getTimestampMillis()
5937                             + MOBILE_RADIO_POWER_STATE_UPDATE_FREQ_MS) {
5938                         mExternalSync.scheduleSync("modem-data",
5939                                 BatteryExternalStatsWorker.UPDATE_RADIO);
5940                         return true;
5941                     }
5942                 }
5943             }
5944         }
5945         return false;
5946     }
5947 
isActiveRadioPowerState(int powerState)5948     private static boolean isActiveRadioPowerState(int powerState) {
5949         return powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
5950                 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
5951     }
5952 
5953     /**
5954      * Toggles the power save mode state.
5955      */
5956     @GuardedBy("this")
notePowerSaveModeLockedInit(boolean enabled, long elapsedRealtimeMs, long uptimeMs)5957     public void notePowerSaveModeLockedInit(boolean enabled, long elapsedRealtimeMs,
5958             long uptimeMs) {
5959         if (mPowerSaveModeEnabled != enabled) {
5960             notePowerSaveModeLocked(enabled, elapsedRealtimeMs, uptimeMs);
5961         } else {
5962             // Log an initial value for BATTERY_SAVER_MODE_STATE_CHANGED in order to
5963             // allow the atom to read all future state changes.
5964             mFrameworkStatsLogger.batterySaverModeChanged(enabled);
5965         }
5966     }
5967 
5968     @GuardedBy("this")
notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs)5969     public void notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs) {
5970         if (mPowerSaveModeEnabled != enabled) {
5971             int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
5972             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
5973             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
5974             mPowerSaveModeEnabled = enabled;
5975             if (enabled) {
5976                 mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
5977                         HistoryItem.STATE2_POWER_SAVE_FLAG);
5978                 mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtimeMs);
5979             } else {
5980                 mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
5981                         HistoryItem.STATE2_POWER_SAVE_FLAG);
5982                 mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtimeMs);
5983             }
5984             mFrameworkStatsLogger.batterySaverModeChanged(enabled);
5985         }
5986     }
5987 
5988     @GuardedBy("this")
noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid, long elapsedRealtimeMs, long uptimeMs)5989     public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid,
5990             long elapsedRealtimeMs, long uptimeMs) {
5991         boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
5992         if (mDeviceIdling && !nowIdling && activeReason == null) {
5993             // We don't go out of general idling mode until explicitly taken out of
5994             // device idle through going active or significant motion.
5995             nowIdling = true;
5996         }
5997         boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
5998         if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
5999             // We don't go out of general light idling mode until explicitly taken out of
6000             // device idle through going active or significant motion.
6001             nowLightIdling = true;
6002         }
6003         if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
6004             mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE,
6005                     activeReason, activeUid);
6006         }
6007         if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
6008             int statsmode;
6009             if (nowIdling)           statsmode = DEVICE_IDLE_MODE_DEEP;
6010             else if (nowLightIdling) statsmode = DEVICE_IDLE_MODE_LIGHT;
6011             else                     statsmode = DEVICE_IDLE_MODE_OFF;
6012             mFrameworkStatsLogger.deviceIdlingModeStateChanged(statsmode);
6013         }
6014         if (mDeviceIdling != nowIdling) {
6015             mDeviceIdling = nowIdling;
6016             int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
6017             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
6018             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
6019             if (nowIdling) {
6020                 mDeviceIdlingTimer.startRunningLocked(elapsedRealtimeMs);
6021             } else {
6022                 mDeviceIdlingTimer.stopRunningLocked(elapsedRealtimeMs);
6023             }
6024         }
6025         if (mDeviceLightIdling != nowLightIdling) {
6026             mDeviceLightIdling = nowLightIdling;
6027             if (nowLightIdling) {
6028                 mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtimeMs);
6029             } else {
6030                 mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtimeMs);
6031             }
6032         }
6033         if (mDeviceIdleMode != mode) {
6034             mHistory.recordDeviceIdleEvent(elapsedRealtimeMs, uptimeMs, mode);
6035             long lastDuration = elapsedRealtimeMs - mLastIdleTimeStartMs;
6036             mLastIdleTimeStartMs = elapsedRealtimeMs;
6037             if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
6038                 if (lastDuration > mLongestLightIdleTimeMs) {
6039                     mLongestLightIdleTimeMs = lastDuration;
6040                 }
6041                 mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtimeMs);
6042             } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
6043                 if (lastDuration > mLongestFullIdleTimeMs) {
6044                     mLongestFullIdleTimeMs = lastDuration;
6045                 }
6046                 mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtimeMs);
6047             }
6048             if (mode == DEVICE_IDLE_MODE_LIGHT) {
6049                 mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtimeMs);
6050             } else if (mode == DEVICE_IDLE_MODE_DEEP) {
6051                 mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtimeMs);
6052             }
6053             mDeviceIdleMode = mode;
6054             mFrameworkStatsLogger.deviceIdleModeStateChanged(mode);
6055         }
6056     }
6057 
6058     @GuardedBy("this")
notePackageInstalledLocked(String pkgName, long versionCode, long elapsedRealtimeMs, long uptimeMs)6059     public void notePackageInstalledLocked(String pkgName, long versionCode,
6060             long elapsedRealtimeMs, long uptimeMs) {
6061         // XXX need to figure out what to do with long version codes.
6062         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED,
6063                 pkgName, (int)versionCode);
6064         PackageChange pc = new PackageChange();
6065         pc.mPackageName = pkgName;
6066         pc.mUpdate = true;
6067         pc.mVersionCode = versionCode;
6068         addPackageChange(pc);
6069     }
6070 
6071     @GuardedBy("this")
notePackageUninstalledLocked(String pkgName, long elapsedRealtimeMs, long uptimeMs)6072     public void notePackageUninstalledLocked(String pkgName,
6073             long elapsedRealtimeMs, long uptimeMs) {
6074         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
6075                 pkgName, 0);
6076         PackageChange pc = new PackageChange();
6077         pc.mPackageName = pkgName;
6078         pc.mUpdate = true;
6079         addPackageChange(pc);
6080     }
6081 
addPackageChange(PackageChange pc)6082     private void addPackageChange(PackageChange pc) {
6083         if (mDailyPackageChanges == null) {
6084             mDailyPackageChanges = new ArrayList<>();
6085         }
6086         mDailyPackageChanges.add(pc);
6087     }
6088 
6089     @GuardedBy("this")
stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs)6090     void stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs) {
6091         for (int i = 0; i < mGpsSignalQualityTimer.length; i++) {
6092             if (i == except) {
6093                 continue;
6094             }
6095             while (mGpsSignalQualityTimer[i].isRunningLocked()) {
6096                 mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtimeMs);
6097             }
6098         }
6099     }
6100 
6101     @GuardedBy("this")
notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs)6102     public void notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs) {
6103         if (!mPhoneOn) {
6104             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6105                     HistoryItem.STATE2_PHONE_IN_CALL_FLAG);
6106             mPhoneOn = true;
6107             mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs);
6108             if (mConstants.PHONE_ON_EXTERNAL_STATS_COLLECTION) {
6109                 scheduleSyncExternalStatsLocked("phone-on", ExternalStatsSync.UPDATE_RADIO);
6110                 mMobileRadioPowerStatsCollector.schedule();
6111             }
6112         }
6113     }
6114 
6115     @GuardedBy("this")
notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs)6116     public void notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs) {
6117         if (mPhoneOn) {
6118             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6119                     HistoryItem.STATE2_PHONE_IN_CALL_FLAG);
6120             mPhoneOn = false;
6121             mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs);
6122             scheduleSyncExternalStatsLocked("phone-off", ExternalStatsSync.UPDATE_RADIO);
6123             mMobileRadioPowerStatsCollector.schedule();
6124         }
6125     }
6126 
6127     @GuardedBy("this")
registerUsbStateReceiver(Context context)6128     private void registerUsbStateReceiver(Context context) {
6129         final IntentFilter usbStateFilter = new IntentFilter();
6130         usbStateFilter.addAction(UsbManager.ACTION_USB_STATE);
6131         context.registerReceiver(new BroadcastReceiver() {
6132             @Override
6133             public void onReceive(Context context, Intent intent) {
6134                 final boolean state = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
6135                 synchronized (BatteryStatsImpl.this) {
6136                     noteUsbConnectionStateLocked(state, mClock.elapsedRealtime(),
6137                             mClock.uptimeMillis());
6138                 }
6139             }
6140         }, usbStateFilter);
6141         synchronized (this) {
6142             if (mUsbDataState == USB_DATA_UNKNOWN) {
6143                 final Intent usbState = context.registerReceiver(null, usbStateFilter);
6144                 final boolean initState = usbState != null && usbState.getBooleanExtra(
6145                         UsbManager.USB_CONNECTED, false);
6146                 noteUsbConnectionStateLocked(initState, mClock.elapsedRealtime(),
6147                         mClock.uptimeMillis());
6148             }
6149         }
6150     }
6151 
6152     @GuardedBy("this")
noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs, long uptimeMs)6153     private void noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs,
6154             long uptimeMs) {
6155         int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED;
6156         if (mUsbDataState != newState) {
6157             mUsbDataState = newState;
6158             if (connected) {
6159                 mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6160                         HistoryItem.STATE2_USB_DATA_LINK_FLAG);
6161             } else {
6162                 mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6163                         HistoryItem.STATE2_USB_DATA_LINK_FLAG);
6164             }
6165         }
6166     }
6167 
6168     @GuardedBy("this")
stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs)6169     void stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
6170         for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
6171             if (i == except) {
6172                 continue;
6173             }
6174             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
6175                 mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs);
6176             }
6177         }
6178     }
6179 
6180     @GuardedBy("this")
updateAllPhoneStateLocked(int state, int simState, int strengthBin, long elapsedRealtimeMs, long uptimeMs)6181     private void updateAllPhoneStateLocked(int state, int simState, int strengthBin,
6182             long elapsedRealtimeMs, long uptimeMs) {
6183         boolean scanning = false;
6184         boolean newHistory = false;
6185         int addStateFlag = 0;
6186         int removeStateFlag = 0;
6187         int newState = -1;
6188         int newSignalStrength = -1;
6189 
6190         mPhoneServiceStateRaw = state;
6191         mPhoneSimStateRaw = simState;
6192         mPhoneSignalStrengthBinRaw = strengthBin;
6193 
6194         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
6195             // In this case we will always be STATE_OUT_OF_SERVICE, so need
6196             // to infer that we are scanning from other data.
6197             if (state == ServiceState.STATE_OUT_OF_SERVICE
6198                     && strengthBin > CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
6199                 state = ServiceState.STATE_IN_SERVICE;
6200             }
6201         }
6202 
6203         // If the phone is powered off, stop all timers.
6204         if (state == ServiceState.STATE_POWER_OFF) {
6205             strengthBin = -1;
6206 
6207         // If we are in service, make sure the correct signal string timer is running.
6208         } else if (state == ServiceState.STATE_IN_SERVICE) {
6209             // Bin will be changed below.
6210 
6211         // If we're out of service, we are in the lowest signal strength
6212         // bin and have the scanning bit set.
6213         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
6214             scanning = true;
6215             strengthBin = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
6216             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
6217                 addStateFlag = HistoryItem.STATE_PHONE_SCANNING_FLAG;
6218                 newHistory = true;
6219                 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtimeMs);
6220                 mFrameworkStatsLogger.phoneServiceStateChanged(state, simState, strengthBin);
6221             }
6222         }
6223 
6224         if (!scanning) {
6225             // If we are no longer scanning, then stop the scanning timer.
6226             if (mPhoneSignalScanningTimer.isRunningLocked()) {
6227                 removeStateFlag = HistoryItem.STATE_PHONE_SCANNING_FLAG;
6228                 newHistory = true;
6229                 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtimeMs);
6230                 mFrameworkStatsLogger.phoneServiceStateChanged(state, simState, strengthBin);
6231             }
6232         }
6233 
6234         if (mPhoneServiceState != state) {
6235             newState = state;
6236             newHistory = true;
6237             mPhoneServiceState = state;
6238         }
6239 
6240         if (mPhoneSignalStrengthBin != strengthBin) {
6241             if (mPhoneSignalStrengthBin >= 0) {
6242                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
6243                         elapsedRealtimeMs);
6244             }
6245             if (strengthBin >= 0) {
6246                 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
6247                     mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
6248                 }
6249                 newSignalStrength = strengthBin;
6250                 newHistory = true;
6251                 mFrameworkStatsLogger.phoneSignalStrengthChanged(strengthBin);
6252             } else {
6253                 stopAllPhoneSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
6254             }
6255             mPhoneSignalStrengthBin = strengthBin;
6256         }
6257 
6258         if (newHistory) {
6259             mHistory.recordPhoneStateChangeEvent(elapsedRealtimeMs, uptimeMs,
6260                     addStateFlag, removeStateFlag, newState, newSignalStrength);
6261         }
6262     }
6263 
6264     @GuardedBy("this")
notePhoneStateLocked(int state, int simState, long elapsedRealtimeMs, long uptimeMs)6265     public void notePhoneStateLocked(int state, int simState,
6266             long elapsedRealtimeMs, long uptimeMs) {
6267         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw,
6268                 elapsedRealtimeMs, uptimeMs);
6269     }
6270 
6271     @GuardedBy("this")
notePhoneSignalStrengthLocked(SignalStrength signalStrength, long elapsedRealtimeMs, long uptimeMs)6272     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength,
6273             long elapsedRealtimeMs, long uptimeMs) {
6274         final int overallSignalStrength = signalStrength.getLevel();
6275         final SparseIntArray perRatSignalStrength = new SparseIntArray(
6276                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT);
6277 
6278         // Extract signal strength level for each RAT.
6279         final List<CellSignalStrength> cellSignalStrengths =
6280                 signalStrength.getCellSignalStrengths();
6281         final int size = cellSignalStrengths.size();
6282         for (int i = 0; i < size; i++) {
6283             CellSignalStrength cellSignalStrength = cellSignalStrengths.get(i);
6284             // Map each CellSignalStrength to a BatteryStats.RadioAccessTechnology
6285             final int ratType;
6286             final int level;
6287             if (cellSignalStrength instanceof CellSignalStrengthNr) {
6288                 ratType = RADIO_ACCESS_TECHNOLOGY_NR;
6289                 level = cellSignalStrength.getLevel();
6290             } else if (cellSignalStrength instanceof CellSignalStrengthLte) {
6291                 ratType = RADIO_ACCESS_TECHNOLOGY_LTE;
6292                 level = cellSignalStrength.getLevel();
6293             } else {
6294                 ratType = RADIO_ACCESS_TECHNOLOGY_OTHER;
6295                 level = cellSignalStrength.getLevel();
6296             }
6297 
6298             // According to SignalStrength#getCellSignalStrengths(), multiple of the same
6299             // cellSignalStrength can be present. Just take the highest level one for each RAT.
6300             if (perRatSignalStrength.get(ratType, -1) < level) {
6301                 perRatSignalStrength.put(ratType, level);
6302             }
6303         }
6304 
6305         notePhoneSignalStrengthLocked(overallSignalStrength, perRatSignalStrength,
6306                 elapsedRealtimeMs, uptimeMs);
6307     }
6308 
6309     /**
6310      * Note phone signal strength change, including per RAT signal strength.
6311      *
6312      * @param signalStrength overall signal strength {@see SignalStrength#getLevel()}
6313      * @param perRatSignalStrength signal strength of available RATs
6314      */
6315     @GuardedBy("this")
notePhoneSignalStrengthLocked(int signalStrength, SparseIntArray perRatSignalStrength)6316     public void notePhoneSignalStrengthLocked(int signalStrength,
6317             SparseIntArray perRatSignalStrength) {
6318         notePhoneSignalStrengthLocked(signalStrength, perRatSignalStrength,
6319                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6320     }
6321 
6322     /**
6323      * Note phone signal strength change, including per RAT signal strength.
6324      *
6325      * @param signalStrength overall signal strength {@see SignalStrength#getLevel()}
6326      * @param perRatSignalStrength signal strength of available RATs
6327      */
6328     @GuardedBy("this")
notePhoneSignalStrengthLocked(int signalStrength, SparseIntArray perRatSignalStrength, long elapsedRealtimeMs, long uptimeMs)6329     public void notePhoneSignalStrengthLocked(int signalStrength,
6330             SparseIntArray perRatSignalStrength,
6331             long elapsedRealtimeMs, long uptimeMs) {
6332         // Note each RAT's signal strength.
6333         final int size = perRatSignalStrength.size();
6334         for (int i = 0; i < size; i++) {
6335             final int rat = perRatSignalStrength.keyAt(i);
6336             final int ratSignalStrength = perRatSignalStrength.valueAt(i);
6337             getRatBatteryStatsLocked(rat).noteSignalStrength(ratSignalStrength, elapsedRealtimeMs);
6338         }
6339         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, signalStrength,
6340                 elapsedRealtimeMs, uptimeMs);
6341     }
6342 
6343     @GuardedBy("this")
notePhoneDataConnectionStateLocked(@etworkType int dataType, boolean hasData, @RegState int serviceType, @NetworkRegistrationInfo.NRState int nrState, @ServiceState.FrequencyRange int nrFrequency)6344     public void notePhoneDataConnectionStateLocked(@NetworkType int dataType, boolean hasData,
6345             @RegState int serviceType, @NetworkRegistrationInfo.NRState int nrState,
6346             @ServiceState.FrequencyRange int nrFrequency) {
6347         notePhoneDataConnectionStateLocked(dataType, hasData, serviceType, nrState, nrFrequency,
6348                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6349     }
6350 
6351     @GuardedBy("this")
notePhoneDataConnectionStateLocked(@etworkType int dataType, boolean hasData, @RegState int serviceType, @NetworkRegistrationInfo.NRState int nrState, @ServiceState.FrequencyRange int nrFrequency, long elapsedRealtimeMs, long uptimeMs)6352     public void notePhoneDataConnectionStateLocked(@NetworkType int dataType, boolean hasData,
6353             @RegState int serviceType, @NetworkRegistrationInfo.NRState int nrState,
6354             @ServiceState.FrequencyRange int nrFrequency, long elapsedRealtimeMs, long uptimeMs) {
6355         // BatteryStats uses 0 to represent no network type.
6356         // Telephony does not have a concept of no network type, and uses 0 to represent unknown.
6357         // Unknown is included in DATA_CONNECTION_OTHER.
6358         int bin = DATA_CONNECTION_OUT_OF_SERVICE;
6359         if (hasData) {
6360             if (dataType > 0 && dataType <= NUM_ALL_NETWORK_TYPES) {
6361                 bin = dataType;
6362             } else {
6363                 switch (serviceType) {
6364                     case ServiceState.STATE_OUT_OF_SERVICE:
6365                         bin = DATA_CONNECTION_OUT_OF_SERVICE;
6366                         break;
6367                     case ServiceState.STATE_EMERGENCY_ONLY:
6368                         bin = DATA_CONNECTION_EMERGENCY_SERVICE;
6369                         break;
6370                     default:
6371                         bin = DATA_CONNECTION_OTHER;
6372                         break;
6373                 }
6374             }
6375         }
6376 
6377 
6378 
6379         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
6380         if (mPhoneDataConnectionType != bin) {
6381             mHistory.recordDataConnectionTypeChangeEvent(elapsedRealtimeMs, uptimeMs, bin);
6382             if (mPhoneDataConnectionType >= 0) {
6383                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
6384                         elapsedRealtimeMs);
6385             }
6386             mPhoneDataConnectionType = bin;
6387             mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtimeMs);
6388         }
6389 
6390         if (mNrState != nrState) {
6391             mHistory.recordNrStateChangeEvent(elapsedRealtimeMs, uptimeMs, nrState);
6392             mNrState = nrState;
6393         }
6394 
6395         final boolean newNrNsaActive = isNrNsa(bin, nrState);
6396         final boolean nrNsaActive = mNrNsaTimer.isRunningLocked();
6397         if (newNrNsaActive != nrNsaActive) {
6398             if (newNrNsaActive) {
6399                 mNrNsaTimer.startRunningLocked(elapsedRealtimeMs);
6400             } else {
6401                 mNrNsaTimer.stopRunningLocked(elapsedRealtimeMs);
6402             }
6403         }
6404 
6405         final int newRat = mapNetworkTypeToRadioAccessTechnology(bin, nrState);
6406         if (newRat == RADIO_ACCESS_TECHNOLOGY_NR) {
6407             // Note possible frequency change for the NR RAT.
6408             getRatBatteryStatsLocked(newRat).noteFrequencyRange(nrFrequency, elapsedRealtimeMs);
6409         }
6410         if (mActiveRat != newRat) {
6411             getRatBatteryStatsLocked(mActiveRat).noteActive(false, elapsedRealtimeMs);
6412             mActiveRat = newRat;
6413         }
6414         final boolean modemActive = mMobileRadioActiveTimer.isRunningLocked();
6415         getRatBatteryStatsLocked(newRat).noteActive(modemActive, elapsedRealtimeMs);
6416     }
6417 
6418     /**
6419      * Non-standalone (NSA) mode for 5G NR will have an LTE network type. If NR state is
6420      * connected while on an LTE network, the device is in NR NSA mode.
6421      */
isNrNsa(@etworkType int dataType, @NetworkRegistrationInfo.NRState int nrState)6422     private static boolean isNrNsa(@NetworkType int dataType,
6423             @NetworkRegistrationInfo.NRState int nrState) {
6424         return dataType == TelephonyManager.NETWORK_TYPE_LTE
6425                 && nrState == NetworkRegistrationInfo.NR_STATE_CONNECTED;
6426     }
6427 
6428     @RadioAccessTechnology
mapNetworkTypeToRadioAccessTechnology(@etworkType int dataType, @NetworkRegistrationInfo.NRState int nrState)6429     private static int mapNetworkTypeToRadioAccessTechnology(@NetworkType int dataType,
6430             @NetworkRegistrationInfo.NRState int nrState) {
6431         if (isNrNsa(dataType, nrState)) {
6432             // Treat an NR NSA connection as RADIO_ACCESS_TECHNOLOGY_NR
6433             return RADIO_ACCESS_TECHNOLOGY_NR;
6434         }
6435 
6436         switch (dataType) {
6437             case TelephonyManager.NETWORK_TYPE_NR:
6438                 return RADIO_ACCESS_TECHNOLOGY_NR;
6439             case TelephonyManager.NETWORK_TYPE_LTE:
6440                 return RADIO_ACCESS_TECHNOLOGY_LTE;
6441             case TelephonyManager.NETWORK_TYPE_UNKNOWN: //fallthrough
6442             case TelephonyManager.NETWORK_TYPE_GPRS: //fallthrough
6443             case TelephonyManager.NETWORK_TYPE_EDGE: //fallthrough
6444             case TelephonyManager.NETWORK_TYPE_UMTS: //fallthrough
6445             case TelephonyManager.NETWORK_TYPE_CDMA: //fallthrough
6446             case TelephonyManager.NETWORK_TYPE_EVDO_0: //fallthrough
6447             case TelephonyManager.NETWORK_TYPE_EVDO_A: //fallthrough
6448             case TelephonyManager.NETWORK_TYPE_1xRTT: //fallthrough
6449             case TelephonyManager.NETWORK_TYPE_HSDPA: //fallthrough
6450             case TelephonyManager.NETWORK_TYPE_HSUPA: //fallthrough
6451             case TelephonyManager.NETWORK_TYPE_HSPA: //fallthrough
6452             case TelephonyManager.NETWORK_TYPE_IDEN: //fallthrough
6453             case TelephonyManager.NETWORK_TYPE_EVDO_B: //fallthrough
6454             case TelephonyManager.NETWORK_TYPE_EHRPD: //fallthrough
6455             case TelephonyManager.NETWORK_TYPE_HSPAP: //fallthrough
6456             case TelephonyManager.NETWORK_TYPE_GSM: //fallthrough
6457             case TelephonyManager.NETWORK_TYPE_TD_SCDMA: //fallthrough
6458             case TelephonyManager.NETWORK_TYPE_IWLAN: //fallthrough
6459                 return RADIO_ACCESS_TECHNOLOGY_OTHER;
6460             default:
6461                 Slog.w(TAG, "Unhandled NetworkType (" + dataType + "), mapping to OTHER");
6462                 return RADIO_ACCESS_TECHNOLOGY_OTHER;
6463         }
6464     }
6465 
6466     @GuardedBy("this")
noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs)6467     public void noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs) {
6468         if (!mWifiOn) {
6469             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6470                     HistoryItem.STATE2_WIFI_ON_FLAG);
6471             mWifiOn = true;
6472             mWifiOnTimer.startRunningLocked(elapsedRealtimeMs);
6473             if (mWifiPowerStatsCollector.isEnabled()) {
6474                 mWifiPowerStatsCollector.schedule();
6475             } else {
6476                 scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
6477             }
6478         }
6479     }
6480 
6481     @GuardedBy("this")
noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs)6482     public void noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs) {
6483         if (mWifiOn) {
6484             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6485                     HistoryItem.STATE2_WIFI_ON_FLAG);
6486             mWifiOn = false;
6487             mWifiOnTimer.stopRunningLocked(elapsedRealtimeMs);
6488             if (mWifiPowerStatsCollector.isEnabled()) {
6489                 mWifiPowerStatsCollector.schedule();
6490             } else {
6491                 scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
6492             }
6493         }
6494     }
6495 
6496     @GuardedBy("this")
noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6497     public void noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6498         uid = mapUid(uid);
6499         if (mAudioOnNesting == 0) {
6500             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
6501                     HistoryItem.STATE_AUDIO_ON_FLAG, uid, "audio");
6502             mAudioOnTimer.startRunningLocked(elapsedRealtimeMs);
6503         }
6504         mAudioOnNesting++;
6505         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_AUDIO)) {
6506             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6507                     .noteAudioTurnedOnLocked(elapsedRealtimeMs);
6508         }
6509     }
6510 
6511     @GuardedBy("this")
noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6512     public void noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6513         if (mAudioOnNesting == 0) {
6514             return;
6515         }
6516         uid = mapUid(uid);
6517         if (--mAudioOnNesting == 0) {
6518             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
6519                     HistoryItem.STATE_AUDIO_ON_FLAG, uid, "audio");
6520             mAudioOnTimer.stopRunningLocked(elapsedRealtimeMs);
6521         }
6522         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_AUDIO)) {
6523             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6524                     .noteAudioTurnedOffLocked(elapsedRealtimeMs);
6525         }
6526     }
6527 
6528     @GuardedBy("this")
noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6529     public void noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6530         uid = mapUid(uid);
6531         if (mVideoOnNesting == 0) {
6532             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6533                     HistoryItem.STATE2_VIDEO_ON_FLAG, uid, "video");
6534             mVideoOnTimer.startRunningLocked(elapsedRealtimeMs);
6535         }
6536         mVideoOnNesting++;
6537         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_VIDEO)) {
6538             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6539                     .noteVideoTurnedOnLocked(elapsedRealtimeMs);
6540         }
6541     }
6542 
6543     @GuardedBy("this")
noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6544     public void noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6545         if (mVideoOnNesting == 0) {
6546             return;
6547         }
6548         uid = mapUid(uid);
6549         if (--mVideoOnNesting == 0) {
6550             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6551                     HistoryItem.STATE2_VIDEO_ON_FLAG, uid, "video");
6552             mVideoOnTimer.stopRunningLocked(elapsedRealtimeMs);
6553         }
6554         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_VIDEO)) {
6555             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6556                     .noteVideoTurnedOffLocked(elapsedRealtimeMs);
6557         }
6558     }
6559 
6560     @GuardedBy("this")
noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs)6561     public void noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs) {
6562         if (mAudioOnNesting > 0) {
6563             mAudioOnNesting = 0;
6564             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
6565                     HistoryItem.STATE_AUDIO_ON_FLAG);
6566             mAudioOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6567             for (int i=0; i<mUidStats.size(); i++) {
6568                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6569                 uid.noteResetAudioLocked(elapsedRealtimeMs);
6570             }
6571         }
6572     }
6573 
6574     @GuardedBy("this")
noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs)6575     public void noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs) {
6576         if (mVideoOnNesting > 0) {
6577             mVideoOnNesting = 0;
6578             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6579                     HistoryItem.STATE2_VIDEO_ON_FLAG);
6580             mVideoOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6581             for (int i=0; i<mUidStats.size(); i++) {
6582                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6583                 uid.noteResetVideoLocked(elapsedRealtimeMs);
6584             }
6585         }
6586     }
6587 
6588     @GuardedBy("this")
noteActivityResumedLocked(int uid)6589     public void noteActivityResumedLocked(int uid) {
6590         noteActivityResumedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
6591     }
6592 
6593     @GuardedBy("this")
noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6594     public void noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6595         uid = mapUid(uid);
6596         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6597                 .noteActivityResumedLocked(elapsedRealtimeMs);
6598     }
6599 
6600     @GuardedBy("this")
noteActivityPausedLocked(int uid)6601     public void noteActivityPausedLocked(int uid) {
6602         noteActivityPausedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
6603     }
6604 
6605     @GuardedBy("this")
noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6606     public void noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6607         uid = mapUid(uid);
6608         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6609                 .noteActivityPausedLocked(elapsedRealtimeMs);
6610     }
6611 
6612     @GuardedBy("this")
noteVibratorOnLocked(int uid, long durationMillis, long elapsedRealtimeMs, long uptimeMs)6613     public void noteVibratorOnLocked(int uid, long durationMillis,
6614             long elapsedRealtimeMs, long uptimeMs) {
6615         uid = mapUid(uid);
6616         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6617                 .noteVibratorOnLocked(durationMillis, elapsedRealtimeMs);
6618     }
6619 
6620     @GuardedBy("this")
noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6621     public void noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6622         uid = mapUid(uid);
6623         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6624                 .noteVibratorOffLocked(elapsedRealtimeMs);
6625     }
6626 
6627     @GuardedBy("this")
noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6628     public void noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6629         uid = mapUid(uid);
6630         if (mFlashlightOnNesting++ == 0) {
6631             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6632                     HistoryItem.STATE2_FLASHLIGHT_FLAG, uid, "flashlight");
6633             mFlashlightOnTimer.startRunningLocked(elapsedRealtimeMs);
6634         }
6635         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT)) {
6636             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6637                     .noteFlashlightTurnedOnLocked(elapsedRealtimeMs);
6638         }
6639     }
6640 
6641     @GuardedBy("this")
noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6642     public void noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6643         if (mFlashlightOnNesting == 0) {
6644             return;
6645         }
6646         uid = mapUid(uid);
6647         if (--mFlashlightOnNesting == 0) {
6648             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6649                     HistoryItem.STATE2_FLASHLIGHT_FLAG, uid, "flashlight");
6650             mFlashlightOnTimer.stopRunningLocked(elapsedRealtimeMs);
6651         }
6652         if (!mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT)) {
6653             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6654                     .noteFlashlightTurnedOffLocked(elapsedRealtimeMs);
6655         }
6656     }
6657 
6658     @GuardedBy("this")
noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6659     public void noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6660         uid = mapUid(uid);
6661         if (mCameraOnNesting++ == 0) {
6662             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6663                     HistoryItem.STATE2_CAMERA_FLAG, uid, "camera");
6664             mCameraOnTimer.startRunningLocked(elapsedRealtimeMs);
6665         }
6666         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6667                 .noteCameraTurnedOnLocked(elapsedRealtimeMs);
6668 
6669         if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CAMERA)) {
6670             mCameraPowerStatsCollector.schedule();
6671         } else {
6672             scheduleSyncExternalStatsLocked("camera-on", ExternalStatsSync.UPDATE_CAMERA);
6673         }
6674     }
6675 
6676     @GuardedBy("this")
noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6677     public void noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6678         if (mCameraOnNesting == 0) {
6679             return;
6680         }
6681         uid = mapUid(uid);
6682         if (--mCameraOnNesting == 0) {
6683             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6684                     HistoryItem.STATE2_CAMERA_FLAG, uid, "camera");
6685             mCameraOnTimer.stopRunningLocked(elapsedRealtimeMs);
6686         }
6687         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6688                 .noteCameraTurnedOffLocked(elapsedRealtimeMs);
6689 
6690         if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CAMERA)) {
6691             mCameraPowerStatsCollector.schedule();
6692         } else {
6693             scheduleSyncExternalStatsLocked("camera-off", ExternalStatsSync.UPDATE_CAMERA);
6694         }
6695     }
6696 
6697     @GuardedBy("this")
noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs)6698     public void noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs) {
6699         if (mCameraOnNesting > 0) {
6700             mCameraOnNesting = 0;
6701             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6702                     HistoryItem.STATE2_CAMERA_FLAG);
6703             mCameraOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6704             for (int i=0; i<mUidStats.size(); i++) {
6705                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6706                 uid.noteResetCameraLocked(elapsedRealtimeMs);
6707             }
6708         }
6709 
6710         scheduleSyncExternalStatsLocked("camera-reset", ExternalStatsSync.UPDATE_CAMERA);
6711     }
6712 
6713     @GuardedBy("this")
noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs)6714     public void noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs) {
6715         if (mFlashlightOnNesting > 0) {
6716             mFlashlightOnNesting = 0;
6717             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6718                     HistoryItem.STATE2_FLASHLIGHT_FLAG);
6719             mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6720             for (int i=0; i<mUidStats.size(); i++) {
6721                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6722                 uid.noteResetFlashlightLocked(elapsedRealtimeMs);
6723             }
6724         }
6725     }
6726 
6727     @GuardedBy("this")
noteBluetoothScanStartedLocked(WorkChain workChain, int uid, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6728     private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
6729             boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
6730         if (workChain != null) {
6731             uid = workChain.getAttributionUid();
6732         }
6733         uid = mapUid(uid);
6734         if (mBluetoothScanNesting == 0) {
6735             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6736                     HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
6737             mBluetoothScanTimer.startRunningLocked(elapsedRealtimeMs);
6738         }
6739         mBluetoothScanNesting++;
6740         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6741                 .noteBluetoothScanStartedLocked(elapsedRealtimeMs, isUnoptimized);
6742     }
6743 
6744     @GuardedBy("this")
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized)6745     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
6746         noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized,
6747                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6748     }
6749 
6750     @GuardedBy("this")
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6751     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
6752             long elapsedRealtimeMs, long uptimeMs) {
6753         final int N = ws.size();
6754         for (int i = 0; i < N; i++) {
6755             noteBluetoothScanStartedLocked(null, ws.getUid(i), isUnoptimized,
6756                     elapsedRealtimeMs, uptimeMs);
6757         }
6758 
6759         final List<WorkChain> workChains = ws.getWorkChains();
6760         if (workChains != null) {
6761             for (int i = 0; i < workChains.size(); ++i) {
6762                 noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized,
6763                         elapsedRealtimeMs, uptimeMs);
6764             }
6765         }
6766     }
6767 
6768     @GuardedBy("this")
noteBluetoothScanStoppedLocked(WorkChain workChain, int uid, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6769     private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
6770             boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
6771         if (workChain != null) {
6772             uid = workChain.getAttributionUid();
6773         }
6774         uid = mapUid(uid);
6775         mBluetoothScanNesting--;
6776         if (mBluetoothScanNesting == 0) {
6777             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6778                     HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
6779             mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
6780         }
6781         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6782                 .noteBluetoothScanStoppedLocked(elapsedRealtimeMs, isUnoptimized);
6783     }
6784 
6785     @GuardedBy("this")
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized)6786     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
6787         noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized,
6788                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6789     }
6790 
6791     @GuardedBy("this")
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6792     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
6793             long elapsedRealtimeMs, long uptimeMs) {
6794         final int N = ws.size();
6795         for (int i = 0; i < N; i++) {
6796             noteBluetoothScanStoppedLocked(null, ws.getUid(i), isUnoptimized,
6797                     elapsedRealtimeMs, uptimeMs);
6798         }
6799 
6800         final List<WorkChain> workChains = ws.getWorkChains();
6801         if (workChains != null) {
6802             for (int i = 0; i < workChains.size(); ++i) {
6803                 noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized,
6804                         elapsedRealtimeMs, uptimeMs);
6805             }
6806         }
6807     }
6808 
6809     @GuardedBy("this")
noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs)6810     public void noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs) {
6811         if (mBluetoothScanNesting > 0) {
6812             mBluetoothScanNesting = 0;
6813             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6814                     HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
6815             mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
6816             for (int i=0; i<mUidStats.size(); i++) {
6817                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6818                 uid.noteResetBluetoothScanLocked(elapsedRealtimeMs);
6819             }
6820         }
6821     }
6822 
6823     @GuardedBy("this")
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults)6824     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
6825         noteBluetoothScanResultsFromSourceLocked(ws, numNewResults,
6826                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6827     }
6828 
6829     @GuardedBy("this")
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults, long elapsedRealtimeMs, long uptimeMs)6830     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults,
6831             long elapsedRealtimeMs, long uptimeMs) {
6832         final int N = ws.size();
6833         for (int i = 0; i < N; i++) {
6834             int uid = mapUid(ws.getUid(i));
6835             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6836                     .noteBluetoothScanResultsLocked(numNewResults);
6837         }
6838 
6839         final List<WorkChain> workChains = ws.getWorkChains();
6840         if (workChains != null) {
6841             for (int i = 0; i < workChains.size(); ++i) {
6842                 final WorkChain wc = workChains.get(i);
6843                 int uid = mapUid(wc.getAttributionUid());
6844                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6845                         .noteBluetoothScanResultsLocked(numNewResults);
6846             }
6847         }
6848     }
6849 
retrieveBluetoothScanTimesLocked( BluetoothPowerStatsCollector.BluetoothStatsRetriever.Callback callback)6850     private void retrieveBluetoothScanTimesLocked(
6851             BluetoothPowerStatsCollector.BluetoothStatsRetriever.Callback callback) {
6852         long elapsedTimeUs = mClock.elapsedRealtime() * 1000;
6853         for (int i = mUidStats.size() - 1; i >= 0; i--) {
6854             Uid uidStats = mUidStats.valueAt(i);
6855             if (uidStats.mBluetoothScanTimer == null) {
6856                 continue;
6857             }
6858 
6859             long scanTimeUs = mBluetoothScanTimer.getTotalTimeLocked(elapsedTimeUs,
6860                     STATS_SINCE_CHARGED);
6861             if (scanTimeUs != 0) {
6862                 int uid = mUidStats.keyAt(i);
6863                 callback.onBluetoothScanTime(uid, (scanTimeUs + 500) / 1000);
6864             }
6865         }
6866     }
6867 
6868     @GuardedBy("this")
noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)6869     private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
6870             final long uptimeMillis, int uid) {
6871         uid = mapUid(uid);
6872         mHistory.recordEvent(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
6873                 uid);
6874         getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteWifiRadioApWakeupLocked();
6875     }
6876 
6877     @GuardedBy("this")
noteWifiRadioPowerState(int powerState, long timestampNs, int uid, long elapsedRealtimeMs, long uptimeMs)6878     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid,
6879             long elapsedRealtimeMs, long uptimeMs) {
6880         if (mWifiRadioPowerState != powerState) {
6881             final boolean active =
6882                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
6883                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
6884             if (active) {
6885                 if (uid > 0) {
6886                     noteWifiRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
6887                 }
6888                 mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
6889                         HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG);
6890                 mWifiActiveTimer.startRunningLocked(elapsedRealtimeMs);
6891             } else {
6892                 mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
6893                         HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG);
6894                 mWifiActiveTimer.stopRunningLocked(timestampNs / (1000 * 1000));
6895             }
6896             mWifiRadioPowerState = powerState;
6897         }
6898     }
6899 
6900     @GuardedBy("this")
noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6901     public void noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
6902         if (!mGlobalWifiRunning) {
6903             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6904                     HistoryItem.STATE2_WIFI_RUNNING_FLAG);
6905             mGlobalWifiRunning = true;
6906             mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
6907             int N = ws.size();
6908             for (int i=0; i<N; i++) {
6909                 int uid = mapUid(ws.getUid(i));
6910                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6911                         .noteWifiRunningLocked(elapsedRealtimeMs);
6912             }
6913 
6914             List<WorkChain> workChains = ws.getWorkChains();
6915             if (workChains != null) {
6916                 for (int i = 0; i < workChains.size(); ++i) {
6917                     int uid = mapUid(workChains.get(i).getAttributionUid());
6918                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6919                             .noteWifiRunningLocked(elapsedRealtimeMs);
6920                 }
6921             }
6922             if (mWifiPowerStatsCollector.isEnabled()) {
6923                 mWifiPowerStatsCollector.schedule();
6924             } else {
6925                 scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
6926             }
6927         } else {
6928             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
6929         }
6930     }
6931 
6932     @GuardedBy("this")
noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs, long elapsedRealtimeMs, long uptimeMs)6933     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs,
6934             long elapsedRealtimeMs, long uptimeMs) {
6935         if (mGlobalWifiRunning) {
6936             int N = oldWs.size();
6937             for (int i=0; i<N; i++) {
6938                 int uid = mapUid(oldWs.getUid(i));
6939                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6940                         .noteWifiStoppedLocked(elapsedRealtimeMs);
6941             }
6942 
6943             List<WorkChain> workChains = oldWs.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                             .noteWifiStoppedLocked(elapsedRealtimeMs);
6949                 }
6950             }
6951 
6952             N = newWs.size();
6953             for (int i=0; i<N; i++) {
6954                 int uid = mapUid(newWs.getUid(i));
6955                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6956                         .noteWifiRunningLocked(elapsedRealtimeMs);
6957             }
6958 
6959             workChains = newWs.getWorkChains();
6960             if (workChains != null) {
6961                 for (int i = 0; i < workChains.size(); ++i) {
6962                     int uid = mapUid(workChains.get(i).getAttributionUid());
6963                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6964                             .noteWifiRunningLocked(elapsedRealtimeMs);
6965                 }
6966             }
6967         } else {
6968             Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
6969         }
6970     }
6971 
6972     @GuardedBy("this")
noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6973     public void noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
6974         if (mGlobalWifiRunning) {
6975             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6976                     HistoryItem.STATE2_WIFI_RUNNING_FLAG);
6977             mGlobalWifiRunning = false;
6978             mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
6979             int N = ws.size();
6980             for (int i=0; i<N; i++) {
6981                 int uid = mapUid(ws.getUid(i));
6982                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6983                         .noteWifiStoppedLocked(elapsedRealtimeMs);
6984             }
6985 
6986             List<WorkChain> workChains = ws.getWorkChains();
6987             if (workChains != null) {
6988                 for (int i = 0; i < workChains.size(); ++i) {
6989                     int uid = mapUid(workChains.get(i).getAttributionUid());
6990                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6991                             .noteWifiStoppedLocked(elapsedRealtimeMs);
6992                 }
6993             }
6994 
6995             if (mWifiPowerStatsCollector.isEnabled()) {
6996                 mWifiPowerStatsCollector.schedule();
6997             } else {
6998                 scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
6999             }
7000         } else {
7001             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
7002         }
7003     }
7004 
7005     @GuardedBy("this")
noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs)7006     public void noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs) {
7007         if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
7008         if (mWifiState != wifiState) {
7009             if (mWifiState >= 0) {
7010                 mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtimeMs);
7011             }
7012             mWifiState = wifiState;
7013             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtimeMs);
7014             if (mWifiPowerStatsCollector.isEnabled()) {
7015                 mWifiPowerStatsCollector.schedule();
7016             } else {
7017                 scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
7018             }
7019         }
7020     }
7021 
7022     @GuardedBy("this")
noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth, long elapsedRealtimeMs, long uptimeMs)7023     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth,
7024             long elapsedRealtimeMs, long uptimeMs) {
7025         if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
7026         if (mWifiSupplState != supplState) {
7027             if (mWifiSupplState >= 0) {
7028                 mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtimeMs);
7029             }
7030             mWifiSupplState = supplState;
7031             mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtimeMs);
7032             mHistory.recordWifiSupplicantStateChangeEvent(elapsedRealtimeMs, uptimeMs, supplState);
7033         }
7034     }
7035 
7036     @GuardedBy("this")
stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs)7037     void stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
7038         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
7039             if (i == except) {
7040                 continue;
7041             }
7042             while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
7043                 mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs);
7044             }
7045         }
7046     }
7047 
7048     @GuardedBy("this")
noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs)7049     public void noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs) {
7050         int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
7051         if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
7052         if (mWifiSignalStrengthBin != strengthBin) {
7053             if (mWifiSignalStrengthBin >= 0) {
7054                 mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
7055                         elapsedRealtimeMs);
7056             }
7057             if (strengthBin >= 0) {
7058                 if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
7059                     mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
7060                 }
7061                 mHistory.recordWifiSignalStrengthChangeEvent(elapsedRealtimeMs, uptimeMs,
7062                         strengthBin);
7063             } else {
7064                 stopAllWifiSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
7065             }
7066             mWifiSignalStrengthBin = strengthBin;
7067         }
7068     }
7069 
7070     private int mWifiFullLockNesting = 0;
7071 
7072     @GuardedBy("this")
noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7073     public void noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7074         if (mWifiFullLockNesting == 0) {
7075             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
7076                     HistoryItem.STATE_WIFI_FULL_LOCK_FLAG);
7077         }
7078         mWifiFullLockNesting++;
7079         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7080                 .noteFullWifiLockAcquiredLocked(elapsedRealtimeMs);
7081     }
7082 
7083     @GuardedBy("this")
noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7084     public void noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7085         mWifiFullLockNesting--;
7086         if (mWifiFullLockNesting == 0) {
7087             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
7088                     HistoryItem.STATE_WIFI_FULL_LOCK_FLAG);
7089         }
7090         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7091                 .noteFullWifiLockReleasedLocked(elapsedRealtimeMs);
7092     }
7093 
7094     int mWifiScanNesting = 0;
7095 
7096     @GuardedBy("this")
noteWifiScanStartedLocked(int uid)7097     public void noteWifiScanStartedLocked(int uid) {
7098         noteWifiScanStartedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7099     }
7100 
7101     @GuardedBy("this")
noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7102     public void noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7103         if (mWifiScanNesting == 0) {
7104             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
7105                     HistoryItem.STATE_WIFI_SCAN_FLAG);
7106         }
7107         mWifiScanNesting++;
7108         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7109                 .noteWifiScanStartedLocked(elapsedRealtimeMs);
7110     }
7111 
7112     @GuardedBy("this")
noteWifiScanStoppedLocked(int uid)7113     public void noteWifiScanStoppedLocked(int uid) {
7114         noteWifiScanStoppedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
7115     }
7116 
7117     @GuardedBy("this")
noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7118     public void noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7119         mWifiScanNesting--;
7120         if (mWifiScanNesting == 0) {
7121             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
7122                     HistoryItem.STATE_WIFI_SCAN_FLAG);
7123         }
7124         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7125                 .noteWifiScanStoppedLocked(elapsedRealtimeMs);
7126     }
7127 
noteWifiBatchedScanStartedLocked(int uid, int csph, long elapsedRealtimeMs, long uptimeMs)7128     public void noteWifiBatchedScanStartedLocked(int uid, int csph,
7129             long elapsedRealtimeMs, long uptimeMs) {
7130         uid = mapUid(uid);
7131         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7132                 .noteWifiBatchedScanStartedLocked(csph, elapsedRealtimeMs);
7133     }
7134 
noteWifiBatchedScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7135     public void noteWifiBatchedScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7136         uid = mapUid(uid);
7137         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7138                 .noteWifiBatchedScanStoppedLocked(elapsedRealtimeMs);
7139     }
7140 
retrieveWifiScanTimesLocked( WifiPowerStatsCollector.WifiStatsRetriever.Callback callback)7141     private void retrieveWifiScanTimesLocked(
7142             WifiPowerStatsCollector.WifiStatsRetriever.Callback callback) {
7143         long elapsedTimeUs = mClock.elapsedRealtime() * 1000;
7144         for (int i = mUidStats.size() - 1; i >= 0; i--) {
7145             int uid = mUidStats.keyAt(i);
7146             Uid uidStats = mUidStats.valueAt(i);
7147             long scanTimeUs = uidStats.getWifiScanTime(elapsedTimeUs, STATS_SINCE_CHARGED);
7148             long batchScanTimeUs = 0;
7149             for (int bucket = 0; bucket < NUM_WIFI_BATCHED_SCAN_BINS; bucket++) {
7150                 batchScanTimeUs += uidStats.getWifiBatchedScanTime(bucket, elapsedTimeUs,
7151                         STATS_SINCE_CHARGED);
7152             }
7153             if (scanTimeUs != 0 || batchScanTimeUs != 0) {
7154                 callback.onWifiScanTime(uid, (scanTimeUs + 500) / 1000,
7155                         (batchScanTimeUs + 500) / 1000);
7156             }
7157         }
7158     }
7159 
7160     private int mWifiMulticastNesting = 0;
7161 
7162     @GuardedBy("this")
noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7163     public void noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7164         uid = mapUid(uid);
7165         if (mWifiMulticastNesting == 0) {
7166             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
7167                     HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG);
7168             // Start Wifi Multicast overall timer
7169             if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
7170                 mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtimeMs);
7171             }
7172         }
7173         mWifiMulticastNesting++;
7174         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7175                 .noteWifiMulticastEnabledLocked(elapsedRealtimeMs);
7176     }
7177 
7178     @GuardedBy("this")
noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs)7179     public void noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
7180         uid = mapUid(uid);
7181         mWifiMulticastNesting--;
7182         if (mWifiMulticastNesting == 0) {
7183             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
7184                     HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG);
7185 
7186             // Stop Wifi Multicast overall timer
7187             if (mWifiMulticastWakelockTimer.isRunningLocked()) {
7188                 if (DEBUG) Slog.v(TAG, "Multicast Overall Timer Stopped");
7189                 mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
7190             }
7191         }
7192         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
7193                 .noteWifiMulticastDisabledLocked(elapsedRealtimeMs);
7194     }
7195 
7196     @GuardedBy("this")
noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7197     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws,
7198             long elapsedRealtimeMs, long uptimeMs) {
7199         int N = ws.size();
7200         for (int i=0; i<N; i++) {
7201             final int uid = mapUid(ws.getUid(i));
7202             noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs);
7203         }
7204 
7205         final List<WorkChain> workChains = ws.getWorkChains();
7206         if (workChains != null) {
7207             for (int i = 0; i < workChains.size(); ++i) {
7208                 final WorkChain workChain = workChains.get(i);
7209                 final int uid = mapUid(workChain.getAttributionUid());
7210                 noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs);
7211             }
7212         }
7213     }
7214 
7215     @GuardedBy("this")
noteFullWifiLockReleasedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7216     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws,
7217             long elapsedRealtimeMs, long uptimeMs) {
7218         int N = ws.size();
7219         for (int i=0; i<N; i++) {
7220             final int uid = mapUid(ws.getUid(i));
7221             noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs);
7222         }
7223 
7224         final List<WorkChain> workChains = ws.getWorkChains();
7225         if (workChains != null) {
7226             for (int i = 0; i < workChains.size(); ++i) {
7227                 final WorkChain workChain = workChains.get(i);
7228                 final int uid = mapUid(workChain.getAttributionUid());
7229                 noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs);
7230             }
7231         }
7232     }
7233 
7234     @GuardedBy("this")
noteWifiScanStartedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7235     public void noteWifiScanStartedFromSourceLocked(WorkSource ws,
7236             long elapsedRealtimeMs, long uptimeMs) {
7237         int N = ws.size();
7238         for (int i=0; i<N; i++) {
7239             final int uid = mapUid(ws.getUid(i));
7240             noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs);
7241         }
7242 
7243         final List<WorkChain> workChains = ws.getWorkChains();
7244         if (workChains != null) {
7245             for (int i = 0; i < workChains.size(); ++i) {
7246                 final WorkChain workChain = workChains.get(i);
7247                 final int uid = mapUid(workChain.getAttributionUid());
7248                 noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs);
7249             }
7250         }
7251     }
7252 
7253     @GuardedBy("this")
noteWifiScanStoppedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7254     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws,
7255             long elapsedRealtimeMs, long uptimeMs) {
7256         int N = ws.size();
7257         for (int i=0; i<N; i++) {
7258             final int uid = mapUid(ws.getUid(i));
7259             noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs);
7260         }
7261 
7262         final List<WorkChain> workChains = ws.getWorkChains();
7263         if (workChains != null) {
7264             for (int i = 0; i < workChains.size(); ++i) {
7265                 final WorkChain workChain = workChains.get(i);
7266                 final int uid = mapUid(workChain.getAttributionUid());
7267                 noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs);
7268             }
7269         }
7270     }
7271 
7272     @GuardedBy("this")
noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph, long elapsedRealtimeMs, long uptimeMs)7273     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph,
7274             long elapsedRealtimeMs, long uptimeMs) {
7275         int N = ws.size();
7276         for (int i=0; i<N; i++) {
7277             noteWifiBatchedScanStartedLocked(ws.getUid(i), csph, elapsedRealtimeMs, uptimeMs);
7278         }
7279 
7280         final List<WorkChain> workChains = ws.getWorkChains();
7281         if (workChains != null) {
7282             for (int i = 0; i < workChains.size(); ++i) {
7283                 noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph,
7284                         elapsedRealtimeMs, uptimeMs);
7285             }
7286         }
7287     }
7288 
7289     @GuardedBy("this")
noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)7290     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws,
7291             long elapsedRealtimeMs, long uptimeMs) {
7292         int N = ws.size();
7293         for (int i=0; i<N; i++) {
7294             noteWifiBatchedScanStoppedLocked(ws.getUid(i), elapsedRealtimeMs, uptimeMs);
7295         }
7296 
7297         final List<WorkChain> workChains = ws.getWorkChains();
7298         if (workChains != null) {
7299             for (int i = 0; i < workChains.size(); ++i) {
7300                 noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid(),
7301                         elapsedRealtimeMs, uptimeMs);
7302             }
7303         }
7304     }
7305 
includeInStringArray(String[] array, String str)7306     private static String[] includeInStringArray(String[] array, String str) {
7307         if (ArrayUtils.indexOf(array, str) >= 0) {
7308             return array;
7309         }
7310         String[] newArray = new String[array.length+1];
7311         System.arraycopy(array, 0, newArray, 0, array.length);
7312         newArray[array.length] = str;
7313         return newArray;
7314     }
7315 
excludeFromStringArray(String[] array, String str)7316     private static String[] excludeFromStringArray(String[] array, String str) {
7317         int index = ArrayUtils.indexOf(array, str);
7318         if (index >= 0) {
7319             String[] newArray = new String[array.length-1];
7320             if (index > 0) {
7321                 System.arraycopy(array, 0, newArray, 0, index);
7322             }
7323             if (index < array.length-1) {
7324                 System.arraycopy(array, index+1, newArray, index, array.length-index-1);
7325             }
7326             return newArray;
7327         }
7328         return array;
7329     }
7330 
7331     /** @hide */
noteNetworkInterfaceForTransports(String iface, int[] transportTypes)7332     public void noteNetworkInterfaceForTransports(String iface, int[] transportTypes) {
7333         if (TextUtils.isEmpty(iface)) return;
7334         final int displayTransport = getDisplayTransport(transportTypes);
7335 
7336         synchronized (mModemNetworkLock) {
7337             if (displayTransport == TRANSPORT_CELLULAR) {
7338                 mModemIfaces = includeInStringArray(mModemIfaces, iface);
7339                 if (DEBUG) {
7340                     Slog.d(TAG, "Note mobile iface " + iface + ": "
7341                             + Arrays.toString(mModemIfaces));
7342                 }
7343             } else {
7344                 mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
7345                 if (DEBUG) {
7346                     Slog.d(TAG, "Note non-mobile iface " + iface + ": "
7347                             + Arrays.toString(mModemIfaces));
7348                 }
7349             }
7350         }
7351 
7352         synchronized (mWifiNetworkLock) {
7353             if (displayTransport == TRANSPORT_WIFI) {
7354                 mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
7355                 if (DEBUG) {
7356                     Slog.d(TAG, "Note wifi iface " + iface + ": " + Arrays.toString(mWifiIfaces));
7357                 }
7358             } else {
7359                 mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
7360                 if (DEBUG) {
7361                     Slog.d(TAG, "Note non-wifi iface " + iface + ": "
7362                             + Arrays.toString(mWifiIfaces));
7363                 }
7364             }
7365         }
7366     }
7367 
7368     /**
7369      * Records timing data related to an incoming Binder call in order to attribute
7370      * the power consumption to the calling app.
7371      */
noteBinderCallStats(int workSourceUid, long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats)7372     public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
7373             Collection<BinderCallsStats.CallStat> callStats) {
7374         noteBinderCallStats(workSourceUid, incrementalCallCount, callStats,
7375                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7376     }
7377 
noteBinderCallStats(int workSourceUid, long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats, long elapsedRealtimeMs, long uptimeMs)7378     public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
7379             Collection<BinderCallsStats.CallStat> callStats,
7380             long elapsedRealtimeMs, long uptimeMs) {
7381         synchronized (this) {
7382             getUidStatsLocked(workSourceUid, elapsedRealtimeMs, uptimeMs)
7383                     .noteBinderCallStatsLocked(incrementalCallCount, callStats);
7384         }
7385     }
7386 
7387     /**
7388      * Takes note of native IDs of threads taking incoming binder calls. The CPU time
7389      * of these threads is attributed to the apps making those binder calls.
7390      */
noteBinderThreadNativeIds(int[] binderThreadNativeTids)7391     public void noteBinderThreadNativeIds(int[] binderThreadNativeTids) {
7392         mSystemServerCpuThreadReader.setBinderThreadNativeTids(binderThreadNativeTids);
7393     }
7394 
7395     /**
7396      * Estimates the proportion of system server CPU activity handling incoming binder calls
7397      * that can be attributed to each app
7398      */
7399     @VisibleForTesting
updateSystemServiceCallStats()7400     public void updateSystemServiceCallStats() {
7401         // Start off by computing the average duration of recorded binder calls,
7402         // regardless of which binder or transaction. We will use this as a fallback
7403         // for calls that were not sampled at all.
7404         int totalRecordedCallCount = 0;
7405         long totalRecordedCallTimeMicros = 0;
7406         for (int i = 0; i < mUidStats.size(); i++) {
7407             Uid uid = mUidStats.valueAt(i);
7408             ArraySet<BinderCallStats> binderCallStats = uid.mBinderCallStats;
7409             for (int j = binderCallStats.size() - 1; j >= 0; j--) {
7410                 BinderCallStats stats = binderCallStats.valueAt(j);
7411                 totalRecordedCallCount += stats.recordedCallCount;
7412                 totalRecordedCallTimeMicros += stats.recordedCpuTimeMicros;
7413             }
7414         }
7415 
7416         long totalSystemServiceTimeMicros = 0;
7417 
7418         // For every UID, use recorded durations of sampled binder calls to estimate
7419         // the total time the system server spent handling requests from this UID.
7420         for (int i = 0; i < mUidStats.size(); i++) {
7421             Uid uid = mUidStats.valueAt(i);
7422 
7423             long totalTimeForUidUs = 0;
7424             int totalCallCountForUid = 0;
7425             ArraySet<BinderCallStats> binderCallStats = uid.mBinderCallStats;
7426             for (int j = binderCallStats.size() - 1; j >= 0; j--) {
7427                 BinderCallStats stats = binderCallStats.valueAt(j);
7428                 totalCallCountForUid += stats.callCount;
7429                 if (stats.recordedCallCount > 0) {
7430                     totalTimeForUidUs +=
7431                             stats.callCount * stats.recordedCpuTimeMicros / stats.recordedCallCount;
7432                 } else if (totalRecordedCallCount > 0) {
7433                     totalTimeForUidUs +=
7434                             stats.callCount * totalRecordedCallTimeMicros / totalRecordedCallCount;
7435                 }
7436             }
7437 
7438             if (totalCallCountForUid < uid.mBinderCallCount && totalRecordedCallCount > 0) {
7439                 // Estimate remaining calls, which were not tracked because of binder call
7440                 // stats sampling
7441                 totalTimeForUidUs +=
7442                         (uid.mBinderCallCount - totalCallCountForUid) * totalRecordedCallTimeMicros
7443                                 / totalRecordedCallCount;
7444             }
7445 
7446             uid.mSystemServiceTimeUs = totalTimeForUidUs;
7447             totalSystemServiceTimeMicros += totalTimeForUidUs;
7448         }
7449 
7450         for (int i = 0; i < mUidStats.size(); i++) {
7451             Uid uid = mUidStats.valueAt(i);
7452             if (totalSystemServiceTimeMicros > 0) {
7453                 uid.mProportionalSystemServiceUsage =
7454                         (double) uid.mSystemServiceTimeUs / totalSystemServiceTimeMicros;
7455             } else {
7456                 uid.mProportionalSystemServiceUsage = 0;
7457             }
7458         }
7459     }
7460 
getWifiIfaces()7461     public String[] getWifiIfaces() {
7462         synchronized (mWifiNetworkLock) {
7463             return mWifiIfaces;
7464         }
7465     }
7466 
getMobileIfaces()7467     public String[] getMobileIfaces() {
7468         synchronized (mModemNetworkLock) {
7469             return mModemIfaces;
7470         }
7471     }
7472 
getScreenOnTime(long elapsedRealtimeUs, int which)7473     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
7474         return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7475     }
7476 
getScreenOnCount(int which)7477     @Override public int getScreenOnCount(int which) {
7478         return mScreenOnTimer.getCountLocked(which);
7479     }
7480 
getScreenDozeTime(long elapsedRealtimeUs, int which)7481     @Override public long getScreenDozeTime(long elapsedRealtimeUs, int which) {
7482         return mScreenDozeTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7483     }
7484 
getScreenDozeCount(int which)7485     @Override public int getScreenDozeCount(int which) {
7486         return mScreenDozeTimer.getCountLocked(which);
7487     }
7488 
getScreenBrightnessTime(int brightnessBin, long elapsedRealtimeUs, int which)7489     @Override public long getScreenBrightnessTime(int brightnessBin,
7490             long elapsedRealtimeUs, int which) {
7491         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
7492                 elapsedRealtimeUs, which);
7493     }
7494 
getScreenBrightnessTimer(int brightnessBin)7495     @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
7496         return mScreenBrightnessTimer[brightnessBin];
7497     }
7498 
7499     @Override
getDisplayCount()7500     public int getDisplayCount() {
7501         return mPerDisplayBatteryStats.length;
7502     }
7503 
7504     @Override
getDisplayScreenOnTime(int display, long elapsedRealtimeUs)7505     public long getDisplayScreenOnTime(int display, long elapsedRealtimeUs) {
7506         return mPerDisplayBatteryStats[display].screenOnTimer.getTotalTimeLocked(elapsedRealtimeUs,
7507                 STATS_SINCE_CHARGED);
7508     }
7509 
7510     @Override
getDisplayScreenDozeTime(int display, long elapsedRealtimeUs)7511     public long getDisplayScreenDozeTime(int display, long elapsedRealtimeUs) {
7512         return mPerDisplayBatteryStats[display].screenDozeTimer.getTotalTimeLocked(
7513                 elapsedRealtimeUs, STATS_SINCE_CHARGED);
7514     }
7515 
7516     @Override
getDisplayScreenBrightnessTime(int display, int brightnessBin, long elapsedRealtimeUs)7517     public long getDisplayScreenBrightnessTime(int display, int brightnessBin,
7518             long elapsedRealtimeUs) {
7519         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
7520         return displayStats.screenBrightnessTimers[brightnessBin].getTotalTimeLocked(
7521                 elapsedRealtimeUs, STATS_SINCE_CHARGED);
7522     }
7523 
getInteractiveTime(long elapsedRealtimeUs, int which)7524     @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
7525         return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7526     }
7527 
getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which)7528     @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
7529         return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7530     }
7531 
getPowerSaveModeEnabledCount(int which)7532     @Override public int getPowerSaveModeEnabledCount(int which) {
7533         return mPowerSaveModeEnabledTimer.getCountLocked(which);
7534     }
7535 
getDeviceIdleModeTime(int mode, long elapsedRealtimeUs, int which)7536     @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
7537             int which) {
7538         switch (mode) {
7539             case DEVICE_IDLE_MODE_LIGHT:
7540                 return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7541             case DEVICE_IDLE_MODE_DEEP:
7542                 return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7543         }
7544         return 0;
7545     }
7546 
getDeviceIdleModeCount(int mode, int which)7547     @Override public int getDeviceIdleModeCount(int mode, int which) {
7548         switch (mode) {
7549             case DEVICE_IDLE_MODE_LIGHT:
7550                 return mDeviceIdleModeLightTimer.getCountLocked(which);
7551             case DEVICE_IDLE_MODE_DEEP:
7552                 return mDeviceIdleModeFullTimer.getCountLocked(which);
7553         }
7554         return 0;
7555     }
7556 
getLongestDeviceIdleModeTime(int mode)7557     @Override public long getLongestDeviceIdleModeTime(int mode) {
7558         switch (mode) {
7559             case DEVICE_IDLE_MODE_LIGHT:
7560                 return mLongestLightIdleTimeMs;
7561             case DEVICE_IDLE_MODE_DEEP:
7562                 return mLongestFullIdleTimeMs;
7563         }
7564         return 0;
7565     }
7566 
getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which)7567     @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
7568         switch (mode) {
7569             case DEVICE_IDLE_MODE_LIGHT:
7570                 return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7571             case DEVICE_IDLE_MODE_DEEP:
7572                 return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7573         }
7574         return 0;
7575     }
7576 
getDeviceIdlingCount(int mode, int which)7577     @Override public int getDeviceIdlingCount(int mode, int which) {
7578         switch (mode) {
7579             case DEVICE_IDLE_MODE_LIGHT:
7580                 return mDeviceLightIdlingTimer.getCountLocked(which);
7581             case DEVICE_IDLE_MODE_DEEP:
7582                 return mDeviceIdlingTimer.getCountLocked(which);
7583         }
7584         return 0;
7585     }
7586 
getNumConnectivityChange(int which)7587     @Override public int getNumConnectivityChange(int which) {
7588         return mNumConnectivityChange;
7589     }
7590 
getGpsSignalQualityTime(int strengthBin, long elapsedRealtimeUs, int which)7591     @Override public long getGpsSignalQualityTime(int strengthBin,
7592             long elapsedRealtimeUs, int which) {
7593         if (strengthBin < 0 || strengthBin >= mGpsSignalQualityTimer.length) {
7594             return 0;
7595         }
7596         return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
7597                 elapsedRealtimeUs, which);
7598     }
7599 
getGpsBatteryDrainMaMs()7600     @Override public long getGpsBatteryDrainMaMs() {
7601         final double opVolt = mPowerProfile.getAveragePower(
7602             PowerProfile.POWER_GPS_OPERATING_VOLTAGE) / 1000.0;
7603         if (opVolt == 0) {
7604             return 0;
7605         }
7606         double energyUsedMaMs = 0.0;
7607         final int which = STATS_SINCE_CHARGED;
7608         final long rawRealtimeUs = SystemClock.elapsedRealtime() * 1000;
7609         for(int i=0; i < mGpsSignalQualityTimer.length; i++) {
7610             energyUsedMaMs
7611                     += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
7612                     * (getGpsSignalQualityTime(i, rawRealtimeUs, which) / 1000);
7613         }
7614         return (long) energyUsedMaMs;
7615     }
7616 
getPhoneOnTime(long elapsedRealtimeUs, int which)7617     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
7618         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7619     }
7620 
getPhoneOnCount(int which)7621     @Override public int getPhoneOnCount(int which) {
7622         return mPhoneOnTimer.getCountLocked(which);
7623     }
7624 
getPhoneSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)7625     @Override public long getPhoneSignalStrengthTime(int strengthBin,
7626             long elapsedRealtimeUs, int which) {
7627         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
7628                 elapsedRealtimeUs, which);
7629     }
7630 
getPhoneSignalScanningTime( long elapsedRealtimeUs, int which)7631     @Override public long getPhoneSignalScanningTime(
7632             long elapsedRealtimeUs, int which) {
7633         return mPhoneSignalScanningTimer.getTotalTimeLocked(
7634                 elapsedRealtimeUs, which);
7635     }
7636 
getPhoneSignalScanningTimer()7637     @Override public Timer getPhoneSignalScanningTimer() {
7638         return mPhoneSignalScanningTimer;
7639     }
7640 
getPhoneSignalStrengthCount(int strengthBin, int which)7641     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
7642         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
7643     }
7644 
getPhoneSignalStrengthTimer(int strengthBin)7645     @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
7646         return mPhoneSignalStrengthsTimer[strengthBin];
7647     }
7648 
getPhoneDataConnectionTime(int dataType, long elapsedRealtimeUs, int which)7649     @Override public long getPhoneDataConnectionTime(int dataType,
7650             long elapsedRealtimeUs, int which) {
7651         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
7652                 elapsedRealtimeUs, which);
7653     }
7654 
getPhoneDataConnectionCount(int dataType, int which)7655     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
7656         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
7657     }
7658 
getPhoneDataConnectionTimer(int dataType)7659     @Override public Timer getPhoneDataConnectionTimer(int dataType) {
7660         return mPhoneDataConnectionsTimer[dataType];
7661     }
7662 
getNrNsaTime(long elapsedRealtimeUs)7663     @Override public long getNrNsaTime(long elapsedRealtimeUs) {
7664         return mNrNsaTimer.getTotalTimeLocked(elapsedRealtimeUs, STATS_SINCE_CHARGED);
7665     }
7666 
getActiveRadioDurationMs(@adioAccessTechnology int rat, @ServiceState.FrequencyRange int frequencyRange, int signalStrength, long elapsedRealtimeMs)7667     @Override public long getActiveRadioDurationMs(@RadioAccessTechnology int rat,
7668             @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
7669             long elapsedRealtimeMs) {
7670         final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
7671         if (stats == null) return 0L;
7672 
7673         final int freqCount = stats.perStateTimers.length;
7674         if (frequencyRange < 0 || frequencyRange >= freqCount) return 0L;
7675 
7676         final StopwatchTimer[] strengthTimers = stats.perStateTimers[frequencyRange];
7677         final int strengthCount = strengthTimers.length;
7678         if (signalStrength < 0 || signalStrength >= strengthCount) return 0L;
7679 
7680         return stats.perStateTimers[frequencyRange][signalStrength].getTotalTimeLocked(
7681                 elapsedRealtimeMs * 1000, STATS_SINCE_CHARGED) / 1000;
7682     }
7683 
7684     @Override
getActiveTxRadioDurationMs(@adioAccessTechnology int rat, @ServiceState.FrequencyRange int frequencyRange, int signalStrength, long elapsedRealtimeMs)7685     public long getActiveTxRadioDurationMs(@RadioAccessTechnology int rat,
7686             @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
7687             long elapsedRealtimeMs) {
7688         final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
7689         if (stats == null) return DURATION_UNAVAILABLE;
7690 
7691         final LongSamplingCounter counter = stats.getTxDurationCounter(frequencyRange,
7692                 signalStrength, false);
7693         if (counter == null) return DURATION_UNAVAILABLE;
7694 
7695         return counter.getCountLocked(STATS_SINCE_CHARGED);
7696     }
7697 
7698     @Override
getActiveRxRadioDurationMs(@adioAccessTechnology int rat, @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs)7699     public long getActiveRxRadioDurationMs(@RadioAccessTechnology int rat,
7700             @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs) {
7701         final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
7702         if (stats == null) return DURATION_UNAVAILABLE;
7703 
7704         final LongSamplingCounter counter = stats.getRxDurationCounter(frequencyRange, false);
7705         if (counter == null) return DURATION_UNAVAILABLE;
7706 
7707         return counter.getCountLocked(STATS_SINCE_CHARGED);
7708     }
7709 
getMobileRadioActiveTime(long elapsedRealtimeUs, int which)7710     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
7711         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7712     }
7713 
getMobileRadioActiveCount(int which)7714     @Override public int getMobileRadioActiveCount(int which) {
7715         return mMobileRadioActiveTimer.getCountLocked(which);
7716     }
7717 
getMobileRadioActiveAdjustedTime(int which)7718     @Override public long getMobileRadioActiveAdjustedTime(int which) {
7719         return mMobileRadioActiveAdjustedTime.getCountLocked(which);
7720     }
7721 
getMobileRadioActiveUnknownTime(int which)7722     @Override public long getMobileRadioActiveUnknownTime(int which) {
7723         return mMobileRadioActiveUnknownTime.getCountLocked(which);
7724     }
7725 
getMobileRadioActiveUnknownCount(int which)7726     @Override public int getMobileRadioActiveUnknownCount(int which) {
7727         return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
7728     }
7729 
getWifiMulticastWakelockTime( long elapsedRealtimeUs, int which)7730     @Override public long getWifiMulticastWakelockTime(
7731             long elapsedRealtimeUs, int which) {
7732         return mWifiMulticastWakelockTimer.getTotalTimeLocked(
7733                 elapsedRealtimeUs, which);
7734     }
7735 
getWifiMulticastWakelockCount(int which)7736     @Override public int getWifiMulticastWakelockCount(int which) {
7737         return mWifiMulticastWakelockTimer.getCountLocked(which);
7738     }
7739 
getWifiOnTime(long elapsedRealtimeUs, int which)7740     @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
7741         return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7742     }
7743 
getWifiActiveTime(long elapsedRealtimeUs, int which)7744     @Override public long getWifiActiveTime(long elapsedRealtimeUs, int which) {
7745         return mWifiActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7746     }
7747 
getGlobalWifiRunningTime(long elapsedRealtimeUs, int which)7748     @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
7749         return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7750     }
7751 
getWifiStateTime(int wifiState, long elapsedRealtimeUs, int which)7752     @Override public long getWifiStateTime(int wifiState,
7753             long elapsedRealtimeUs, int which) {
7754         return mWifiStateTimer[wifiState].getTotalTimeLocked(
7755                 elapsedRealtimeUs, which);
7756     }
7757 
getWifiStateCount(int wifiState, int which)7758     @Override public int getWifiStateCount(int wifiState, int which) {
7759         return mWifiStateTimer[wifiState].getCountLocked(which);
7760     }
7761 
getWifiStateTimer(int wifiState)7762     @Override public Timer getWifiStateTimer(int wifiState) {
7763         return mWifiStateTimer[wifiState];
7764     }
7765 
getWifiSupplStateTime(int state, long elapsedRealtimeUs, int which)7766     @Override public long getWifiSupplStateTime(int state,
7767             long elapsedRealtimeUs, int which) {
7768         return mWifiSupplStateTimer[state].getTotalTimeLocked(
7769                 elapsedRealtimeUs, which);
7770     }
7771 
getWifiSupplStateCount(int state, int which)7772     @Override public int getWifiSupplStateCount(int state, int which) {
7773         return mWifiSupplStateTimer[state].getCountLocked(which);
7774     }
7775 
getWifiSupplStateTimer(int state)7776     @Override public Timer getWifiSupplStateTimer(int state) {
7777         return mWifiSupplStateTimer[state];
7778     }
7779 
getWifiSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)7780     @Override public long getWifiSignalStrengthTime(int strengthBin,
7781             long elapsedRealtimeUs, int which) {
7782         return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
7783                 elapsedRealtimeUs, which);
7784     }
7785 
getWifiSignalStrengthCount(int strengthBin, int which)7786     @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
7787         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
7788     }
7789 
getWifiSignalStrengthTimer(int strengthBin)7790     @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
7791         return mWifiSignalStrengthsTimer[strengthBin];
7792     }
7793 
7794     @Override
getBluetoothControllerActivity()7795     public ControllerActivityCounter getBluetoothControllerActivity() {
7796         return mBluetoothActivity;
7797     }
7798 
7799     @Override
getWifiControllerActivity()7800     public ControllerActivityCounter getWifiControllerActivity() {
7801         return mWifiActivity;
7802     }
7803 
7804     @Override
getModemControllerActivity()7805     public ControllerActivityCounter getModemControllerActivity() {
7806         return mModemActivity;
7807     }
7808 
7809     @Override
hasBluetoothActivityReporting()7810     public boolean hasBluetoothActivityReporting() {
7811         return mHasBluetoothReporting;
7812     }
7813 
7814     @Override
hasWifiActivityReporting()7815     public boolean hasWifiActivityReporting() {
7816         return mHasWifiReporting;
7817     }
7818 
7819     @Override
hasModemActivityReporting()7820     public boolean hasModemActivityReporting() {
7821         return mHasModemReporting;
7822     }
7823 
7824     @Override
getFlashlightOnTime(long elapsedRealtimeUs, int which)7825     public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
7826         return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7827     }
7828 
7829     @Override
getFlashlightOnCount(int which)7830     public long getFlashlightOnCount(int which) {
7831         return mFlashlightOnTimer.getCountLocked(which);
7832     }
7833 
7834     @Override
getCameraOnTime(long elapsedRealtimeUs, int which)7835     public long getCameraOnTime(long elapsedRealtimeUs, int which) {
7836         return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7837     }
7838 
7839     @Override
getBluetoothScanTime(long elapsedRealtimeUs, int which)7840     public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
7841         return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7842     }
7843 
7844     @Override
getNetworkActivityBytes(int type, int which)7845     public long getNetworkActivityBytes(int type, int which) {
7846         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
7847             return mNetworkByteActivityCounters[type].getCountLocked(which);
7848         } else {
7849             return 0;
7850         }
7851     }
7852 
7853     @Override
getNetworkActivityPackets(int type, int which)7854     public long getNetworkActivityPackets(int type, int which) {
7855         if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
7856             return mNetworkPacketActivityCounters[type].getCountLocked(which);
7857         } else {
7858             return 0;
7859         }
7860     }
7861 
7862     @GuardedBy("this")
7863     @Override
getBluetoothEnergyConsumptionUC()7864     public long getBluetoothEnergyConsumptionUC() {
7865         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_BLUETOOTH);
7866     }
7867 
7868     @GuardedBy("this")
7869     @Override
getCpuEnergyConsumptionUC()7870     public long getCpuEnergyConsumptionUC() {
7871         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CPU);
7872     }
7873 
7874     @GuardedBy("this")
7875     @Override
getGnssEnergyConsumptionUC()7876     public long getGnssEnergyConsumptionUC() {
7877         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_GNSS);
7878     }
7879 
7880     @GuardedBy("this")
7881     @Override
getMobileRadioEnergyConsumptionUC()7882     public long getMobileRadioEnergyConsumptionUC() {
7883         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO);
7884     }
7885 
7886     @GuardedBy("this")
7887     @Override
getPhoneEnergyConsumptionUC()7888     public long getPhoneEnergyConsumptionUC() {
7889         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_PHONE);
7890     }
7891 
7892     @GuardedBy("this")
7893     @Override
getScreenOnEnergyConsumptionUC()7894     public long getScreenOnEnergyConsumptionUC() {
7895         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_SCREEN_ON);
7896     }
7897 
7898     @GuardedBy("this")
7899     @Override
getScreenDozeEnergyConsumptionUC()7900     public long getScreenDozeEnergyConsumptionUC() {
7901         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_SCREEN_DOZE);
7902     }
7903 
7904     @GuardedBy("this")
7905     @Override
getWifiEnergyConsumptionUC()7906     public long getWifiEnergyConsumptionUC() {
7907         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_WIFI);
7908     }
7909 
7910     @GuardedBy("this")
7911     @Override
getCameraEnergyConsumptionUC()7912     public long getCameraEnergyConsumptionUC() {
7913         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CAMERA);
7914     }
7915 
7916     /**
7917      * Returns the consumption (in microcoulombs) that the given standard power bucket consumed.
7918      * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable
7919      *
7920      * @param bucket standard power bucket of interest
7921      * @return charge (in microcoulombs) used for this power bucket
7922      */
7923     @GuardedBy("this")
getPowerBucketConsumptionUC(@tandardPowerBucket int bucket)7924     private long getPowerBucketConsumptionUC(@StandardPowerBucket int bucket) {
7925         if (mGlobalEnergyConsumerStats == null) {
7926             return POWER_DATA_UNAVAILABLE;
7927         }
7928         return mGlobalEnergyConsumerStats.getAccumulatedStandardBucketCharge(bucket);
7929     }
7930 
7931     @GuardedBy("this")
7932     @Override
getCustomEnergyConsumerBatteryConsumptionUC()7933     public @Nullable long[] getCustomEnergyConsumerBatteryConsumptionUC() {
7934         if (mGlobalEnergyConsumerStats == null) {
7935             return null;
7936         }
7937         return mGlobalEnergyConsumerStats.getAccumulatedCustomBucketCharges();
7938     }
7939 
7940     /**
7941      * Returns the names of custom power components.
7942      */
7943     @Override
getCustomEnergyConsumerNames()7944     public @NonNull String[] getCustomEnergyConsumerNames() {
7945         synchronized (this) {
7946             if (mEnergyConsumerStatsConfig == null) {
7947                 return new String[0];
7948             }
7949             final String[] names = mEnergyConsumerStatsConfig.getCustomBucketNames();
7950             for (int i = 0; i < names.length; i++) {
7951                 if (TextUtils.isEmpty(names[i])) {
7952                     names[i] = "CUSTOM_" + BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + i;
7953                 }
7954             }
7955             return names;
7956         }
7957     }
7958 
7959     @Override
getStartClockTime()7960     public long getStartClockTime() {
7961         synchronized (this) {
7962             final long currentTimeMs = mClock.currentTimeMillis();
7963             if ((currentTimeMs > MILLISECONDS_IN_YEAR
7964                     && mStartClockTimeMs < (currentTimeMs - MILLISECONDS_IN_YEAR))
7965                 || (mStartClockTimeMs > currentTimeMs)) {
7966                 // If the start clock time has changed by more than a year, then presumably
7967                 // the previous time was completely bogus.  So we are going to figure out a
7968                 // new time based on how much time has elapsed since we started counting.
7969                 mHistory.recordCurrentTimeChange(mClock.elapsedRealtime(), mClock.uptimeMillis(),
7970                         currentTimeMs);
7971                 adjustStartClockTime(currentTimeMs);
7972             }
7973             return mStartClockTimeMs;
7974         }
7975     }
7976 
7977     /**
7978      * Returns the monotonic time when the BatteryStats session started.
7979      */
getMonotonicStartTime()7980     public long getMonotonicStartTime() {
7981         return mMonotonicStartTime;
7982     }
7983 
7984     /**
7985      * Returns the monotonic time when the BatteryStats session ended, or
7986      * {@link MonotonicClock#UNDEFINED} if the session is still ongoing.
7987      */
getMonotonicEndTime()7988     public long getMonotonicEndTime() {
7989         return mMonotonicEndTime;
7990     }
7991 
getStartPlatformVersion()7992     @Override public String getStartPlatformVersion() {
7993         return mStartPlatformVersion;
7994     }
7995 
getEndPlatformVersion()7996     @Override public String getEndPlatformVersion() {
7997         return mEndPlatformVersion;
7998     }
7999 
getParcelVersion()8000     @Override public int getParcelVersion() {
8001         return VERSION;
8002     }
8003 
getIsOnBattery()8004     @Override public boolean getIsOnBattery() {
8005         return mOnBattery;
8006     }
8007 
getStatsStartRealtime()8008     @Override public long getStatsStartRealtime() {
8009         return mRealtimeStartUs;
8010     }
8011 
getUidStats()8012     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
8013         return mUidStats;
8014     }
8015 
resetIfNotNull(T t, boolean detachIfReset, long elapsedRealtimeUs)8016     private static <T extends TimeBaseObs> boolean resetIfNotNull(T t, boolean detachIfReset,
8017             long elapsedRealtimeUs) {
8018         if (t != null) {
8019             return t.reset(detachIfReset, elapsedRealtimeUs);
8020         }
8021         return true;
8022     }
8023 
resetIfNotNull(T[] t, boolean detachIfReset, long elapsedRealtimeUs)8024     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[] t, boolean detachIfReset,
8025             long elapsedRealtimeUs) {
8026         if (t != null) {
8027             boolean ret = true;
8028             for (int i = 0; i < t.length; i++) {
8029                 ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs);
8030             }
8031             return ret;
8032         }
8033         return true;
8034     }
8035 
resetIfNotNull(T[][] t, boolean detachIfReset, long elapsedRealtimeUs)8036     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[][] t, boolean detachIfReset,
8037             long elapsedRealtimeUs) {
8038         if (t != null) {
8039             boolean ret = true;
8040             for (int i = 0; i < t.length; i++) {
8041                 ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs);
8042             }
8043             return ret;
8044         }
8045         return true;
8046     }
8047 
resetIfNotNull(ControllerActivityCounterImpl counter, boolean detachIfReset, long elapsedRealtimeUs)8048     private static boolean resetIfNotNull(ControllerActivityCounterImpl counter,
8049             boolean detachIfReset, long elapsedRealtimeUs) {
8050         if (counter != null) {
8051             counter.reset(detachIfReset, elapsedRealtimeUs);
8052         }
8053         return true;
8054     }
8055 
detachIfNotNull(T t)8056     private static <T extends TimeBaseObs> void detachIfNotNull(T t) {
8057         if (t != null) {
8058             t.detach();
8059         }
8060     }
8061 
detachIfNotNull(T[] t)8062     private static <T extends TimeBaseObs> void detachIfNotNull(T[] t) {
8063         if (t != null) {
8064             for (int i = 0; i < t.length; i++) {
8065                 detachIfNotNull(t[i]);
8066             }
8067         }
8068     }
8069 
detachIfNotNull(T[][] t)8070     private static <T extends TimeBaseObs> void detachIfNotNull(T[][] t) {
8071         if (t != null) {
8072             for (int i = 0; i < t.length; i++) {
8073                 detachIfNotNull(t[i]);
8074             }
8075         }
8076     }
8077 
detachIfNotNull(ControllerActivityCounterImpl counter)8078     private static void detachIfNotNull(ControllerActivityCounterImpl counter) {
8079         if (counter != null) {
8080             counter.detach();
8081         }
8082     }
8083 
8084     /**
8085      * Accumulates stats for a specific binder transaction.
8086      */
8087     @VisibleForTesting
8088     protected static class BinderCallStats {
8089         public Class<? extends Binder> binderClass;
8090         public int transactionCode;
8091         public String methodName;
8092 
8093         public long callCount;
8094         public long recordedCallCount;
8095         public long recordedCpuTimeMicros;
8096 
8097 
8098         @Override
hashCode()8099         public int hashCode() {
8100             return binderClass.hashCode() * 31 + transactionCode;
8101         }
8102 
8103         @Override
equals(Object obj)8104         public boolean equals(Object obj) {
8105             if (!(obj instanceof BinderCallStats)) {
8106                 return false;
8107             }
8108             BinderCallStats bcsk = (BinderCallStats) obj;
8109             return binderClass.equals(bcsk.binderClass) && transactionCode == bcsk.transactionCode;
8110         }
8111 
getClassName()8112         public String getClassName() {
8113             return binderClass.getName();
8114         }
8115 
getMethodName()8116         public String getMethodName() {
8117             return methodName;
8118         }
8119 
8120         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
ensureMethodName(BinderTransactionNameResolver resolver)8121         public void ensureMethodName(BinderTransactionNameResolver resolver) {
8122             if (methodName == null) {
8123                 methodName = resolver.getMethodName(binderClass, transactionCode);
8124             }
8125         }
8126 
8127         @Override
toString()8128         public String toString() {
8129             return "BinderCallStats{"
8130                     + binderClass
8131                     + " transaction=" + transactionCode
8132                     + " callCount=" + callCount
8133                     + " recordedCallCount=" + recordedCallCount
8134                     + " recorderCpuTimeMicros=" + recordedCpuTimeMicros
8135                     + "}";
8136         }
8137     }
8138 
8139     /**
8140      * The statistics associated with a particular uid.
8141      */
8142     public static class Uid extends BatteryStats.Uid {
8143         /**
8144          * BatteryStatsImpl that we are associated with.
8145          */
8146         protected BatteryStatsImpl mBsi;
8147 
8148         final int mUid;
8149 
8150         /** TimeBase for when uid is in background and device is on battery. */
8151         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
8152         public final TimeBase mOnBatteryBackgroundTimeBase;
8153         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
8154         public final TimeBase mOnBatteryScreenOffBackgroundTimeBase;
8155 
8156         boolean mWifiRunning;
8157         StopwatchTimer mWifiRunningTimer;
8158 
8159         boolean mFullWifiLockOut;
8160         StopwatchTimer mFullWifiLockTimer;
8161 
8162         boolean mWifiScanStarted;
8163         DualTimer mWifiScanTimer;
8164 
8165         static final int NO_BATCHED_SCAN_STARTED = -1;
8166         int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
8167         StopwatchTimer[] mWifiBatchedScanTimer;
8168 
8169         int mWifiMulticastWakelockCount;
8170         StopwatchTimer mWifiMulticastTimer;
8171 
8172         StopwatchTimer mAudioTurnedOnTimer;
8173         StopwatchTimer mVideoTurnedOnTimer;
8174         StopwatchTimer mFlashlightTurnedOnTimer;
8175         StopwatchTimer mCameraTurnedOnTimer;
8176         StopwatchTimer mForegroundActivityTimer;
8177         StopwatchTimer mForegroundServiceTimer;
8178         /** Total time spent by the uid holding any partial wakelocks. */
8179         DualTimer mAggregatedPartialWakelockTimer;
8180         DualTimer mBluetoothScanTimer;
8181         DualTimer mBluetoothUnoptimizedScanTimer;
8182         Counter mBluetoothScanResultCounter;
8183         Counter mBluetoothScanResultBgCounter;
8184 
8185         int mProcessState = Uid.PROCESS_STATE_NONEXISTENT;
8186         StopwatchTimer[] mProcessStateTimer;
8187 
8188         boolean mInForegroundService = false;
8189 
8190         BatchTimer mVibratorOnTimer;
8191 
8192         Counter[] mUserActivityCounters;
8193 
8194         LongSamplingCounter[] mNetworkByteActivityCounters;
8195         LongSamplingCounter[] mNetworkPacketActivityCounters;
8196         TimeMultiStateCounter mMobileRadioActiveTime;
8197         LongSamplingCounter mMobileRadioActiveCount;
8198 
8199         /**
8200          * How many times this UID woke up the Application Processor due to a Mobile radio packet.
8201          */
8202         private LongSamplingCounter mMobileRadioApWakeupCount;
8203 
8204         /**
8205          * How many times this UID woke up the Application Processor due to a Wifi packet.
8206          */
8207         private LongSamplingCounter mWifiRadioApWakeupCount;
8208 
8209         /**
8210          * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
8211          * Can be null if the UID has had no such activity.
8212          */
8213         private ControllerActivityCounterImpl mWifiControllerActivity;
8214 
8215         /**
8216          * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
8217          * Can be null if the UID has had no such activity.
8218          */
8219         private ControllerActivityCounterImpl mBluetoothControllerActivity;
8220 
8221         /**
8222          * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
8223          * Can be null if the UID has had no such activity.
8224          */
8225         private ControllerActivityCounterImpl mModemControllerActivity;
8226 
8227         /**
8228          * The CPU times we had at the last history details update.
8229          */
8230         long mLastStepUserTimeMs;
8231         long mLastStepSystemTimeMs;
8232         long mCurStepUserTimeMs;
8233         long mCurStepSystemTimeMs;
8234 
8235         LongSamplingCounter mUserCpuTime;
8236         LongSamplingCounter mSystemCpuTime;
8237         LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
8238         TimeMultiStateCounter mCpuActiveTimeMs;
8239 
8240         LongSamplingCounterArray mCpuFreqTimeMs;
8241         LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
8242         LongSamplingCounterArray mCpuClusterTimesMs;
8243 
8244         TimeInFreqMultiStateCounter mProcStateTimeMs;
8245         TimeInFreqMultiStateCounter mProcStateScreenOffTimeMs;
8246 
8247         SparseArray<ChildUid> mChildUids;
8248 
8249         /**
8250          * The statistics we have collected for this uid's wake locks.
8251          */
8252         final OverflowArrayMap<Wakelock> mWakelockStats;
8253 
8254         /**
8255          * The statistics we have collected for this uid's syncs.
8256          */
8257         final OverflowArrayMap<DualTimer> mSyncStats;
8258 
8259         /**
8260          * The statistics we have collected for this uid's jobs.
8261          */
8262         final OverflowArrayMap<DualTimer> mJobStats;
8263 
8264         /**
8265          * Count of the jobs that have completed and the reasons why they completed.
8266          */
8267         final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
8268 
8269         /**
8270          * Count of app launch events that had associated deferred job counts or info about
8271          * last time a job was run.
8272          */
8273         Counter mJobsDeferredEventCount;
8274 
8275         /**
8276          * Count of deferred jobs that were pending when the app was launched or brought to
8277          * the foreground through a user interaction.
8278          */
8279         Counter mJobsDeferredCount;
8280 
8281         /**
8282          * Sum of time since the last time a job was run for this app before it was launched.
8283          */
8284         LongSamplingCounter mJobsFreshnessTimeMs;
8285 
8286         /**
8287          * Array of counts of instances where the time since the last job was run for the app
8288          * fell within one of the thresholds in {@link #JOB_FRESHNESS_BUCKETS}.
8289          */
8290         final Counter[] mJobsFreshnessBuckets;
8291 
8292         /**
8293          * The statistics we have collected for this uid's sensor activations.
8294          */
8295         final SparseArray<Sensor> mSensorStats = new SparseArray<>();
8296 
8297         /**
8298          * The statistics we have collected for this uid's processes.
8299          */
8300         final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
8301 
8302         /**
8303          * The statistics we have collected for this uid's processes.
8304          */
8305         final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
8306 
8307         /**
8308          * The transient wake stats we have collected for this uid's pids.
8309          */
8310         final SparseArray<Pid> mPids = new SparseArray<>();
8311 
8312         /**
8313          * Grand total of system server binder calls made by this uid.
8314          */
8315         private long mBinderCallCount;
8316 
8317         /**
8318          * Detailed information about system server binder calls made by this uid.
8319          */
8320         private final ArraySet<BinderCallStats> mBinderCallStats = new ArraySet<>();
8321 
8322         /**
8323          * EnergyConsumer consumption by this uid while on battery.
8324          * Its '<b>custom</b> power buckets' correspond to the
8325          * {@link android.hardware.power.stats.EnergyConsumer.ordinal}s of (custom) energy consumer
8326          * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
8327          *
8328          * Will be null if energy consumer data is completely unavailable (in which case
8329          * {@link #mGlobalEnergyConsumerStats} will also be null) or if the power usage by this uid
8330          * is 0 for every bucket.
8331          */
8332         private EnergyConsumerStats mUidEnergyConsumerStats;
8333 
8334         /**
8335          * Estimated total time spent by the system server handling requests from this uid.
8336          */
8337         private long mSystemServiceTimeUs;
8338 
8339         /**
8340          * Estimated proportion of system server binder call CPU cost for this uid.
8341          */
8342         private double mProportionalSystemServiceUsage;
8343 
Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs)8344         public Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs) {
8345             mBsi = bsi;
8346             mUid = uid;
8347 
8348             /* Observer list of TimeBase object in Uid is short */
8349             mOnBatteryBackgroundTimeBase = new TimeBase(false);
8350             mOnBatteryBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
8351             /* Observer list of TimeBase object in Uid is short */
8352             mOnBatteryScreenOffBackgroundTimeBase = new TimeBase(false);
8353             mOnBatteryScreenOffBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
8354 
8355             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8356             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8357             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase);
8358 
8359             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
8360                 @Override public Wakelock instantiateObject() {
8361                     return new Wakelock(mBsi, Uid.this);
8362                 }
8363             };
8364             mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
8365                 @Override public DualTimer instantiateObject() {
8366                     return new DualTimer(mBsi.mClock, Uid.this, SYNC, null,
8367                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8368                 }
8369             };
8370             mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
8371                 @Override public DualTimer instantiateObject() {
8372                     return new DualTimer(mBsi.mClock, Uid.this, JOB, null,
8373                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8374                 }
8375             };
8376 
8377             mWifiRunningTimer = new StopwatchTimer(mBsi.mClock, this, WIFI_RUNNING,
8378                     mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
8379             mFullWifiLockTimer = new StopwatchTimer(mBsi.mClock, this, FULL_WIFI_LOCK,
8380                     mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
8381             mWifiScanTimer = new DualTimer(mBsi.mClock, this, WIFI_SCAN,
8382                     mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8383             mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
8384             mWifiMulticastTimer = new StopwatchTimer(mBsi.mClock, this, WIFI_MULTICAST_ENABLED,
8385                     mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
8386             mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
8387             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase);
8388             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase);
8389             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8390             mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length];
8391         }
8392 
8393         @GuardedBy("mBsi")
8394         @VisibleForTesting
setProcessStateForTest(int procState, long elapsedTimeMs)8395         public void setProcessStateForTest(int procState, long elapsedTimeMs) {
8396             mProcessState = procState;
8397             getProcStateTimeCounter(elapsedTimeMs).setState(procState, elapsedTimeMs);
8398             getProcStateScreenOffTimeCounter(elapsedTimeMs).setState(procState, elapsedTimeMs);
8399             final int batteryConsumerProcessState =
8400                     mapUidProcessStateToBatteryConsumerProcessState(procState);
8401             getCpuActiveTimeCounter().setState(batteryConsumerProcessState, elapsedTimeMs);
8402             getMobileRadioActiveTimeCounter().setState(batteryConsumerProcessState, elapsedTimeMs);
8403             final ControllerActivityCounterImpl wifiControllerActivity =
8404                     getWifiControllerActivity();
8405             if (wifiControllerActivity != null) {
8406                 wifiControllerActivity.setState(batteryConsumerProcessState, elapsedTimeMs);
8407             }
8408             final ControllerActivityCounterImpl bluetoothControllerActivity =
8409                     getBluetoothControllerActivity();
8410             if (bluetoothControllerActivity != null) {
8411                 bluetoothControllerActivity.setState(batteryConsumerProcessState, elapsedTimeMs);
8412             }
8413             final EnergyConsumerStats energyStats =
8414                     getOrCreateEnergyConsumerStatsIfSupportedLocked();
8415             if (energyStats != null) {
8416                 energyStats.setState(batteryConsumerProcessState, elapsedTimeMs);
8417             }
8418         }
8419 
8420         @Override
getCpuFreqTimes(int which)8421         public long[] getCpuFreqTimes(int which) {
8422             return nullIfAllZeros(mCpuFreqTimeMs, which);
8423         }
8424 
8425         @Override
getScreenOffCpuFreqTimes(int which)8426         public long[] getScreenOffCpuFreqTimes(int which) {
8427             return nullIfAllZeros(mScreenOffCpuFreqTimeMs, which);
8428         }
8429 
getCpuActiveTimeCounter()8430         private TimeMultiStateCounter getCpuActiveTimeCounter() {
8431             if (mCpuActiveTimeMs == null) {
8432                 final long timestampMs = mBsi.mClock.elapsedRealtime();
8433                 mCpuActiveTimeMs = new TimeMultiStateCounter(mBsi.mOnBatteryTimeBase,
8434                         BatteryConsumer.PROCESS_STATE_COUNT, timestampMs);
8435                 mCpuActiveTimeMs.setState(
8436                         mapUidProcessStateToBatteryConsumerProcessState(mProcessState),
8437                         timestampMs);
8438             }
8439             return mCpuActiveTimeMs;
8440         }
8441 
8442         @Override
getCpuActiveTime()8443         public long getCpuActiveTime() {
8444             if (mCpuActiveTimeMs == null) {
8445                 return 0;
8446             }
8447 
8448             long activeTime = 0;
8449             for (int procState = 0; procState < BatteryConsumer.PROCESS_STATE_COUNT; procState++) {
8450                 activeTime += mCpuActiveTimeMs.getCountForProcessState(procState);
8451             }
8452             return activeTime;
8453         }
8454 
8455         @Override
getCpuActiveTime(int procState)8456         public long getCpuActiveTime(int procState) {
8457             if (mCpuActiveTimeMs == null
8458                     || procState < 0 || procState >= BatteryConsumer.PROCESS_STATE_COUNT) {
8459                 return 0;
8460             }
8461 
8462             return mCpuActiveTimeMs.getCountForProcessState(procState);
8463         }
8464 
8465         @Override
getCpuClusterTimes()8466         public long[] getCpuClusterTimes() {
8467             return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
8468         }
8469 
8470         @GuardedBy("mBsi")
8471         @Override
getCpuFreqTimes(long[] timesInFreqMs, int procState)8472         public boolean getCpuFreqTimes(long[] timesInFreqMs, int procState) {
8473             if (procState < 0 || procState >= NUM_PROCESS_STATE) {
8474                 return false;
8475             }
8476             if (mProcStateTimeMs == null) {
8477                 return false;
8478             }
8479             if (!mBsi.mPerProcStateCpuTimesAvailable) {
8480                 mProcStateTimeMs = null;
8481                 return false;
8482             }
8483             return mProcStateTimeMs.getCountsLocked(timesInFreqMs, procState);
8484         }
8485 
8486         @GuardedBy("mBsi")
8487         @Override
getScreenOffCpuFreqTimes(long[] timesInFreqMs, int procState)8488         public boolean getScreenOffCpuFreqTimes(long[] timesInFreqMs, int procState) {
8489             if (procState < 0 || procState >= NUM_PROCESS_STATE) {
8490                 return false;
8491             }
8492             if (mProcStateScreenOffTimeMs == null) {
8493                 return false;
8494             }
8495             if (!mBsi.mPerProcStateCpuTimesAvailable) {
8496                 mProcStateScreenOffTimeMs = null;
8497                 return false;
8498             }
8499             return mProcStateScreenOffTimeMs.getCountsLocked(timesInFreqMs, procState);
8500         }
8501 
getBinderCallCount()8502         public long getBinderCallCount() {
8503             return mBinderCallCount;
8504         }
8505 
8506         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
getBinderCallStats()8507         public ArraySet<BinderCallStats> getBinderCallStats() {
8508             return mBinderCallStats;
8509         }
8510 
8511         @Override
getProportionalSystemServiceUsage()8512         public  double getProportionalSystemServiceUsage() {
8513             return mProportionalSystemServiceUsage;
8514         }
8515 
8516         /**
8517          * Adds isolated UID to the list of children.
8518          */
addIsolatedUid(int isolatedUid)8519         public void addIsolatedUid(int isolatedUid) {
8520             if (mChildUids == null) {
8521                 mChildUids = new SparseArray<>();
8522             } else if (mChildUids.indexOfKey(isolatedUid) >= 0) {
8523                 return;
8524             }
8525             mChildUids.put(isolatedUid, new ChildUid());
8526         }
8527 
8528         /**
8529          * Removes isolated UID from the list of children.
8530          */
removeIsolatedUid(int isolatedUid)8531         public void removeIsolatedUid(int isolatedUid) {
8532             final int idx = mChildUids == null ? -1 : mChildUids.indexOfKey(isolatedUid);
8533             if (idx < 0) {
8534                 return;
8535             }
8536             mChildUids.remove(idx);
8537         }
8538 
8539         @GuardedBy("mBsi")
getChildUid(int childUid)8540         ChildUid getChildUid(int childUid) {
8541             return mChildUids == null ? null : mChildUids.get(childUid);
8542         }
8543 
nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which)8544         private long[] nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which) {
8545             if (cpuTimesMs == null) {
8546                 return null;
8547             }
8548             final long[] counts = cpuTimesMs.getCountsLocked(which);
8549             if (counts == null) {
8550                 return null;
8551             }
8552             // Return counts only if at least one of the elements is non-zero.
8553             for (int i = counts.length - 1; i >= 0; --i) {
8554                 if (counts[i] != 0) {
8555                     return counts;
8556                 }
8557             }
8558             return null;
8559         }
8560 
8561         @GuardedBy("mBsi")
ensureMultiStateCounters(long timestampMs)8562         private void ensureMultiStateCounters(long timestampMs) {
8563             if (mBsi.mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
8564                 throw new IllegalStateException("Multi-state counters used in streamlined mode");
8565             }
8566 
8567             if (mProcStateTimeMs == null) {
8568                 mProcStateTimeMs =
8569                         new TimeInFreqMultiStateCounter(mBsi.mOnBatteryTimeBase,
8570                                 PROC_STATE_TIME_COUNTER_STATE_COUNT,
8571                                 mBsi.mCpuScalingPolicies.getScalingStepCount(),
8572                                 timestampMs);
8573             }
8574             if (mProcStateScreenOffTimeMs == null) {
8575                 mProcStateScreenOffTimeMs =
8576                         new TimeInFreqMultiStateCounter(mBsi.mOnBatteryScreenOffTimeBase,
8577                                 PROC_STATE_TIME_COUNTER_STATE_COUNT,
8578                                 mBsi.mCpuScalingPolicies.getScalingStepCount(),
8579                                 timestampMs);
8580             }
8581         }
8582 
8583         @GuardedBy("mBsi")
getProcStateTimeCounter(long timestampMs)8584         private TimeInFreqMultiStateCounter getProcStateTimeCounter(long timestampMs) {
8585             ensureMultiStateCounters(timestampMs);
8586             return mProcStateTimeMs;
8587         }
8588 
8589         @GuardedBy("mBsi")
getProcStateScreenOffTimeCounter(long timestampMs)8590         private TimeInFreqMultiStateCounter getProcStateScreenOffTimeCounter(long timestampMs) {
8591             ensureMultiStateCounters(timestampMs);
8592             return mProcStateScreenOffTimeMs;
8593         }
8594 
8595         @Override
getAggregatedPartialWakelockTimer()8596         public Timer getAggregatedPartialWakelockTimer() {
8597             return mAggregatedPartialWakelockTimer;
8598         }
8599 
8600         @Override
getWakelockStats()8601         public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
8602             return mWakelockStats.getMap();
8603         }
8604 
8605         @Override
getMulticastWakelockStats()8606         public Timer getMulticastWakelockStats() {
8607             return mWifiMulticastTimer;
8608         }
8609 
8610         @Override
getSyncStats()8611         public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
8612             return mSyncStats.getMap();
8613         }
8614 
8615         @Override
getJobStats()8616         public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
8617             return mJobStats.getMap();
8618         }
8619 
8620         @Override
getJobCompletionStats()8621         public ArrayMap<String, SparseIntArray> getJobCompletionStats() {
8622             return mJobCompletions;
8623         }
8624 
8625         @Override
getSensorStats()8626         public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
8627             return mSensorStats;
8628         }
8629 
8630         @Override
getProcessStats()8631         public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
8632             return mProcessStats;
8633         }
8634 
8635         @Override
getPackageStats()8636         public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
8637             return mPackageStats;
8638         }
8639 
8640         @Override
getUid()8641         public int getUid() {
8642             return mUid;
8643         }
8644 
8645         @Override
noteWifiRunningLocked(long elapsedRealtimeMs)8646         public void noteWifiRunningLocked(long elapsedRealtimeMs) {
8647             if (!mWifiRunning) {
8648                 mWifiRunning = true;
8649                 if (mWifiRunningTimer == null) {
8650                     mWifiRunningTimer = new StopwatchTimer(mBsi.mClock, Uid.this, WIFI_RUNNING,
8651                             mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
8652                 }
8653                 mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
8654             }
8655         }
8656 
8657         @Override
noteWifiStoppedLocked(long elapsedRealtimeMs)8658         public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
8659             if (mWifiRunning) {
8660                 mWifiRunning = false;
8661                 mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
8662             }
8663         }
8664 
8665         @Override
noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs)8666         public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
8667             if (!mFullWifiLockOut) {
8668                 mFullWifiLockOut = true;
8669                 if (mFullWifiLockTimer == null) {
8670                     mFullWifiLockTimer = new StopwatchTimer(mBsi.mClock, Uid.this, FULL_WIFI_LOCK,
8671                             mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
8672                 }
8673                 mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
8674             }
8675         }
8676 
8677         @Override
noteFullWifiLockReleasedLocked(long elapsedRealtimeMs)8678         public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
8679             if (mFullWifiLockOut) {
8680                 mFullWifiLockOut = false;
8681                 mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
8682             }
8683         }
8684 
8685         @Override
noteWifiScanStartedLocked(long elapsedRealtimeMs)8686         public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
8687             if (!mWifiScanStarted) {
8688                 mWifiScanStarted = true;
8689                 if (mWifiScanTimer == null) {
8690                     mWifiScanTimer = new DualTimer(mBsi.mClock, Uid.this, WIFI_SCAN,
8691                             mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase,
8692                             mOnBatteryBackgroundTimeBase);
8693                 }
8694                 mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
8695             }
8696         }
8697 
8698         @Override
noteWifiScanStoppedLocked(long elapsedRealtimeMs)8699         public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
8700             if (mWifiScanStarted) {
8701                 mWifiScanStarted = false;
8702                 mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
8703             }
8704         }
8705 
8706         @Override
noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs)8707         public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
8708             int bin = 0;
8709             while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
8710                 csph = csph >> 3;
8711                 bin++;
8712             }
8713 
8714             if (mWifiBatchedScanBinStarted == bin) return;
8715 
8716             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
8717                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
8718                         stopRunningLocked(elapsedRealtimeMs);
8719             }
8720             mWifiBatchedScanBinStarted = bin;
8721             if (mWifiBatchedScanTimer[bin] == null) {
8722                 makeWifiBatchedScanBin(bin, null);
8723             }
8724             mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
8725         }
8726 
8727         @Override
noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs)8728         public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
8729             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
8730                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
8731                         stopRunningLocked(elapsedRealtimeMs);
8732                 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
8733             }
8734         }
8735 
8736         @Override
noteWifiMulticastEnabledLocked(long elapsedRealtimeMs)8737         public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
8738             if (mWifiMulticastWakelockCount == 0) {
8739                 if (mWifiMulticastTimer == null) {
8740                     mWifiMulticastTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
8741                             WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
8742                 }
8743                 mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
8744             }
8745             mWifiMulticastWakelockCount++;
8746         }
8747 
8748         @Override
noteWifiMulticastDisabledLocked(long elapsedRealtimeMs)8749         public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
8750             if (mWifiMulticastWakelockCount == 0) {
8751                 return;
8752             }
8753 
8754             mWifiMulticastWakelockCount--;
8755             if (mWifiMulticastWakelockCount == 0) {
8756                 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
8757             }
8758         }
8759 
8760         @Override
getWifiControllerActivity()8761         public ControllerActivityCounterImpl getWifiControllerActivity() {
8762             return mWifiControllerActivity;
8763         }
8764 
8765         @Override
getBluetoothControllerActivity()8766         public ControllerActivityCounterImpl getBluetoothControllerActivity() {
8767             return mBluetoothControllerActivity;
8768         }
8769 
8770         @Override
getModemControllerActivity()8771         public ControllerActivityCounter getModemControllerActivity() {
8772             return mModemControllerActivity;
8773         }
8774 
getOrCreateWifiControllerActivityLocked()8775         public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
8776             if (mWifiControllerActivity == null) {
8777                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
8778                         mBsi.mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
8779             }
8780             return mWifiControllerActivity;
8781         }
8782 
getOrCreateBluetoothControllerActivityLocked()8783         public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
8784             if (mBluetoothControllerActivity == null) {
8785                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
8786                         mBsi.mOnBatteryTimeBase, NUM_BT_TX_LEVELS);
8787             }
8788             return mBluetoothControllerActivity;
8789         }
8790 
getOrCreateModemControllerActivityLocked()8791         public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
8792             if (mModemControllerActivity == null) {
8793                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
8794                         mBsi.mOnBatteryTimeBase, mBsi.MODEM_TX_POWER_LEVEL_COUNT);
8795             }
8796             return mModemControllerActivity;
8797         }
8798 
8799         @GuardedBy("mBsi")
getOrCreateEnergyConsumerStatsLocked()8800         private EnergyConsumerStats getOrCreateEnergyConsumerStatsLocked() {
8801             if (mUidEnergyConsumerStats == null) {
8802                 mUidEnergyConsumerStats = new EnergyConsumerStats(mBsi.mEnergyConsumerStatsConfig);
8803             }
8804             return mUidEnergyConsumerStats;
8805         }
8806 
8807         @GuardedBy("mBsi")
getOrCreateEnergyConsumerStatsIfSupportedLocked()8808         private EnergyConsumerStats getOrCreateEnergyConsumerStatsIfSupportedLocked() {
8809             if (mUidEnergyConsumerStats == null && mBsi.mEnergyConsumerStatsConfig != null) {
8810                 mUidEnergyConsumerStats = new EnergyConsumerStats(mBsi.mEnergyConsumerStatsConfig);
8811             }
8812             return mUidEnergyConsumerStats;
8813         }
8814 
8815         /** Adds the given charge to the given standard power bucket for this uid. */
8816         @GuardedBy("mBsi")
addChargeToStandardBucketLocked(long chargeDeltaUC, @StandardPowerBucket int powerBucket, long timestampMs)8817         private void addChargeToStandardBucketLocked(long chargeDeltaUC,
8818                 @StandardPowerBucket int powerBucket, long timestampMs) {
8819             final EnergyConsumerStats energyConsumerStats =
8820                     getOrCreateEnergyConsumerStatsLocked();
8821             energyConsumerStats.updateStandardBucket(powerBucket, chargeDeltaUC, timestampMs);
8822         }
8823 
8824         /** Adds the given charge to the given custom power bucket for this uid. */
8825         @GuardedBy("mBsi")
addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket)8826         private void addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket) {
8827             getOrCreateEnergyConsumerStatsLocked().updateCustomBucket(powerBucket, chargeDeltaUC,
8828                     mBsi.mClock.elapsedRealtime());
8829         }
8830 
8831         /**
8832          * Returns the battery consumption (in microcoulomb) of this uid for a standard power bucket
8833          * of interest.
8834          * @param bucket standard power bucket of interest
8835          * @return consumption (in microcolombs) used by this uid for this power bucket
8836          */
8837         @GuardedBy("mBsi")
getEnergyConsumptionUC(@tandardPowerBucket int bucket)8838         public long getEnergyConsumptionUC(@StandardPowerBucket int bucket) {
8839             if (mBsi.mGlobalEnergyConsumerStats == null
8840                     || !mBsi.mGlobalEnergyConsumerStats.isStandardBucketSupported(bucket)) {
8841                 return POWER_DATA_UNAVAILABLE;
8842             }
8843             if (mUidEnergyConsumerStats == null) {
8844                 return 0L; // It is supported, but was never filled, so it must be 0
8845             }
8846             return mUidEnergyConsumerStats.getAccumulatedStandardBucketCharge(bucket);
8847         }
8848 
8849         /**
8850          * Returns the battery consumption (in microcoulombs) of this uid for a standard power
8851          * bucket and a process state, such as Uid.PROCESS_STATE_TOP.
8852          */
8853         @GuardedBy("mBsi")
getEnergyConsumptionUC(@tandardPowerBucket int bucket, int processState)8854         public long getEnergyConsumptionUC(@StandardPowerBucket int bucket,
8855                 int processState) {
8856             if (mBsi.mGlobalEnergyConsumerStats == null
8857                     || !mBsi.mGlobalEnergyConsumerStats.isStandardBucketSupported(bucket)) {
8858                 return POWER_DATA_UNAVAILABLE;
8859             }
8860             if (mUidEnergyConsumerStats == null) {
8861                 return 0L; // It is supported, but was never filled, so it must be 0
8862             }
8863             return mUidEnergyConsumerStats.getAccumulatedStandardBucketCharge(bucket, processState);
8864         }
8865 
8866         @GuardedBy("mBsi")
8867         @Override
getCustomEnergyConsumerBatteryConsumptionUC()8868         public long[] getCustomEnergyConsumerBatteryConsumptionUC() {
8869             if (mBsi.mGlobalEnergyConsumerStats == null) {
8870                 return null;
8871             }
8872             if (mUidEnergyConsumerStats == null) {
8873                 // Custom buckets may exist. But all values for this uid are 0 so we report all 0s.
8874                 return new long[mBsi.mGlobalEnergyConsumerStats.getNumberCustomPowerBuckets()];
8875             }
8876             return mUidEnergyConsumerStats.getAccumulatedCustomBucketCharges();
8877         }
8878 
8879         @GuardedBy("mBsi")
8880         @Override
getBluetoothEnergyConsumptionUC()8881         public long getBluetoothEnergyConsumptionUC() {
8882             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_BLUETOOTH);
8883         }
8884 
8885         @GuardedBy("mBsi")
8886         @Override
getBluetoothEnergyConsumptionUC( @atteryConsumer.ProcessState int processState)8887         public long getBluetoothEnergyConsumptionUC(
8888                 @BatteryConsumer.ProcessState int processState) {
8889             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_BLUETOOTH,
8890                     processState);
8891         }
8892 
8893         @GuardedBy("mBsi")
8894         @Override
getCpuEnergyConsumptionUC()8895         public long getCpuEnergyConsumptionUC() {
8896             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CPU);
8897         }
8898 
8899         @GuardedBy("mBsi")
8900         @Override
getCpuEnergyConsumptionUC( @atteryConsumer.ProcessState int processState)8901         public long getCpuEnergyConsumptionUC(
8902                 @BatteryConsumer.ProcessState int processState) {
8903             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CPU,
8904                     processState);
8905         }
8906 
8907         @GuardedBy("mBsi")
8908         @Override
getGnssEnergyConsumptionUC()8909         public long getGnssEnergyConsumptionUC() {
8910             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_GNSS);
8911         }
8912 
8913         @GuardedBy("mBsi")
8914         @Override
getMobileRadioEnergyConsumptionUC()8915         public long getMobileRadioEnergyConsumptionUC() {
8916             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO);
8917         }
8918 
8919         @GuardedBy("mBsi")
8920         @Override
getMobileRadioEnergyConsumptionUC(int processState)8921         public long getMobileRadioEnergyConsumptionUC(int processState) {
8922             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO,
8923                     processState);
8924         }
8925 
8926         @GuardedBy("mBsi")
8927         @Override
getScreenOnEnergyConsumptionUC()8928         public long getScreenOnEnergyConsumptionUC() {
8929             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_SCREEN_ON);
8930         }
8931 
8932         @GuardedBy("mBsi")
8933         @Override
getWifiEnergyConsumptionUC()8934         public long getWifiEnergyConsumptionUC() {
8935             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_WIFI);
8936         }
8937 
8938         @GuardedBy("mBsi")
8939         @Override
getWifiEnergyConsumptionUC(int processState)8940         public long getWifiEnergyConsumptionUC(int processState) {
8941             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_WIFI,
8942                     processState);
8943         }
8944 
8945         @GuardedBy("mBsi")
8946         @Override
getCameraEnergyConsumptionUC()8947         public long getCameraEnergyConsumptionUC() {
8948             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CAMERA);
8949         }
8950 
8951         /**
8952          * Gets the minimum of the uid's foreground activity time and its PROCESS_STATE_TOP time
8953          * since last marked. Also sets the mark time for both these timers.
8954          *
8955          * @see CpuPowerCalculator
8956          *
8957          * @param doCalc if true, then calculate the minimum; else don't bother and return 0. Either
8958          *               way, the mark is set.
8959          */
markProcessForegroundTimeUs(long elapsedRealtimeMs, boolean doCalc)8960         private long markProcessForegroundTimeUs(long elapsedRealtimeMs,
8961                 boolean doCalc) {
8962             long fgTimeUs = 0;
8963             final StopwatchTimer fgTimer = mForegroundActivityTimer;
8964             if (fgTimer != null) {
8965                 if (doCalc) fgTimeUs = fgTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
8966                 fgTimer.setMark(elapsedRealtimeMs);
8967             }
8968 
8969             long topTimeUs = 0;
8970             final StopwatchTimer topTimer = mProcessStateTimer[PROCESS_STATE_TOP];
8971             if (topTimer != null) {
8972                 if (doCalc) topTimeUs = topTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
8973                 topTimer.setMark(elapsedRealtimeMs);
8974             }
8975 
8976             // Return the min of the two
8977             return (topTimeUs < fgTimeUs) ? topTimeUs : fgTimeUs;
8978         }
8979 
8980 
8981         /**
8982          * Gets the uid's time spent using the GNSS since last marked. Also sets the mark time for
8983          * the GNSS timer.
8984          */
markGnssTimeUs(long elapsedRealtimeMs)8985         private long markGnssTimeUs(long elapsedRealtimeMs) {
8986             final Sensor sensor = mSensorStats.get(Sensor.GPS);
8987             if (sensor == null) {
8988                 return 0;
8989             }
8990 
8991             final StopwatchTimer timer = sensor.mTimer;
8992             if (timer == null) {
8993                 return 0;
8994             }
8995 
8996             final long gnssTimeUs = timer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
8997             timer.setMark(elapsedRealtimeMs);
8998             return gnssTimeUs;
8999         }
9000 
9001         /**
9002          * Gets the uid's time spent using the camera since last marked. Also sets the mark time for
9003          * the camera timer.
9004          */
markCameraTimeUs(long elapsedRealtimeMs)9005         private long markCameraTimeUs(long elapsedRealtimeMs) {
9006             final StopwatchTimer timer = mCameraTurnedOnTimer;
9007             if (timer == null) {
9008                 return 0;
9009             }
9010             final long cameraTimeUs = timer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
9011             timer.setMark(elapsedRealtimeMs);
9012             return cameraTimeUs;
9013         }
9014 
createAudioTurnedOnTimerLocked()9015         public StopwatchTimer createAudioTurnedOnTimerLocked() {
9016             if (mAudioTurnedOnTimer == null) {
9017                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, AUDIO_TURNED_ON,
9018                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
9019             }
9020             return mAudioTurnedOnTimer;
9021         }
9022 
noteAudioTurnedOnLocked(long elapsedRealtimeMs)9023         public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
9024             createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
9025         }
9026 
noteAudioTurnedOffLocked(long elapsedRealtimeMs)9027         public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
9028             if (mAudioTurnedOnTimer != null) {
9029                 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
9030             }
9031         }
9032 
noteResetAudioLocked(long elapsedRealtimeMs)9033         public void noteResetAudioLocked(long elapsedRealtimeMs) {
9034             if (mAudioTurnedOnTimer != null) {
9035                 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
9036             }
9037         }
9038 
createVideoTurnedOnTimerLocked()9039         public StopwatchTimer createVideoTurnedOnTimerLocked() {
9040             if (mVideoTurnedOnTimer == null) {
9041                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, VIDEO_TURNED_ON,
9042                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
9043             }
9044             return mVideoTurnedOnTimer;
9045         }
9046 
noteVideoTurnedOnLocked(long elapsedRealtimeMs)9047         public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
9048             createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
9049         }
9050 
noteVideoTurnedOffLocked(long elapsedRealtimeMs)9051         public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
9052             if (mVideoTurnedOnTimer != null) {
9053                 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
9054             }
9055         }
9056 
noteResetVideoLocked(long elapsedRealtimeMs)9057         public void noteResetVideoLocked(long elapsedRealtimeMs) {
9058             if (mVideoTurnedOnTimer != null) {
9059                 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
9060             }
9061         }
9062 
createFlashlightTurnedOnTimerLocked()9063         public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
9064             if (mFlashlightTurnedOnTimer == null) {
9065                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
9066                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
9067             }
9068             return mFlashlightTurnedOnTimer;
9069         }
9070 
noteFlashlightTurnedOnLocked(long elapsedRealtimeMs)9071         public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
9072             createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
9073         }
9074 
noteFlashlightTurnedOffLocked(long elapsedRealtimeMs)9075         public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
9076             if (mFlashlightTurnedOnTimer != null) {
9077                 mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
9078             }
9079         }
9080 
noteResetFlashlightLocked(long elapsedRealtimeMs)9081         public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
9082             if (mFlashlightTurnedOnTimer != null) {
9083                 mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
9084             }
9085         }
9086 
createCameraTurnedOnTimerLocked()9087         public StopwatchTimer createCameraTurnedOnTimerLocked() {
9088             if (mCameraTurnedOnTimer == null) {
9089                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, CAMERA_TURNED_ON,
9090                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
9091             }
9092             return mCameraTurnedOnTimer;
9093         }
9094 
noteCameraTurnedOnLocked(long elapsedRealtimeMs)9095         public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
9096             createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
9097         }
9098 
noteCameraTurnedOffLocked(long elapsedRealtimeMs)9099         public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
9100             if (mCameraTurnedOnTimer != null) {
9101                 mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
9102             }
9103         }
9104 
noteResetCameraLocked(long elapsedRealtimeMs)9105         public void noteResetCameraLocked(long elapsedRealtimeMs) {
9106             if (mCameraTurnedOnTimer != null) {
9107                 mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
9108             }
9109         }
9110 
createForegroundActivityTimerLocked()9111         public StopwatchTimer createForegroundActivityTimerLocked() {
9112             if (mForegroundActivityTimer == null) {
9113                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
9114                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
9115             }
9116             return mForegroundActivityTimer;
9117         }
9118 
createForegroundServiceTimerLocked()9119         public StopwatchTimer createForegroundServiceTimerLocked() {
9120             if (mForegroundServiceTimer == null) {
9121                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
9122                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase);
9123             }
9124             return mForegroundServiceTimer;
9125         }
9126 
createAggregatedPartialWakelockTimerLocked()9127         public DualTimer createAggregatedPartialWakelockTimerLocked() {
9128             if (mAggregatedPartialWakelockTimer == null) {
9129                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClock, this,
9130                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
9131                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase);
9132             }
9133             return mAggregatedPartialWakelockTimer;
9134         }
9135 
createBluetoothScanTimerLocked()9136         public DualTimer createBluetoothScanTimerLocked() {
9137             if (mBluetoothScanTimer == null) {
9138                 mBluetoothScanTimer = new DualTimer(mBsi.mClock, Uid.this, BLUETOOTH_SCAN_ON,
9139                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
9140                         mOnBatteryBackgroundTimeBase);
9141             }
9142             return mBluetoothScanTimer;
9143         }
9144 
createBluetoothUnoptimizedScanTimerLocked()9145         public DualTimer createBluetoothUnoptimizedScanTimerLocked() {
9146             if (mBluetoothUnoptimizedScanTimer == null) {
9147                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClock, Uid.this,
9148                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
9149                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
9150             }
9151             return mBluetoothUnoptimizedScanTimer;
9152         }
9153 
noteBluetoothScanStartedLocked(long elapsedRealtimeMs, boolean isUnoptimized)9154         public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs,
9155                 boolean isUnoptimized) {
9156             createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
9157             if (isUnoptimized) {
9158                 createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
9159             }
9160         }
9161 
noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized)9162         public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
9163             if (mBluetoothScanTimer != null) {
9164                 mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
9165             }
9166             if (isUnoptimized && mBluetoothUnoptimizedScanTimer != null) {
9167                 mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs);
9168             }
9169         }
9170 
noteResetBluetoothScanLocked(long elapsedRealtimeMs)9171         public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
9172             if (mBluetoothScanTimer != null) {
9173                 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
9174             }
9175             if (mBluetoothUnoptimizedScanTimer != null) {
9176                 mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
9177             }
9178         }
9179 
createBluetoothScanResultCounterLocked()9180         public Counter createBluetoothScanResultCounterLocked() {
9181             if (mBluetoothScanResultCounter == null) {
9182                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase);
9183             }
9184             return mBluetoothScanResultCounter;
9185         }
9186 
createBluetoothScanResultBgCounterLocked()9187         public Counter createBluetoothScanResultBgCounterLocked() {
9188             if (mBluetoothScanResultBgCounter == null) {
9189                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase);
9190             }
9191             return mBluetoothScanResultBgCounter;
9192         }
9193 
noteBluetoothScanResultsLocked(int numNewResults)9194         public void noteBluetoothScanResultsLocked(int numNewResults) {
9195             createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
9196             // Uses background timebase, so the count will only be incremented if uid in background.
9197             createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults);
9198         }
9199 
9200         @Override
noteActivityResumedLocked(long elapsedRealtimeMs)9201         public void noteActivityResumedLocked(long elapsedRealtimeMs) {
9202             // We always start, since we want multiple foreground PIDs to nest
9203             createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
9204         }
9205 
9206         @Override
noteActivityPausedLocked(long elapsedRealtimeMs)9207         public void noteActivityPausedLocked(long elapsedRealtimeMs) {
9208             if (mForegroundActivityTimer != null) {
9209                 mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
9210             }
9211         }
9212 
noteForegroundServiceResumedLocked(long elapsedRealtimeMs)9213         public void noteForegroundServiceResumedLocked(long elapsedRealtimeMs) {
9214             createForegroundServiceTimerLocked().startRunningLocked(elapsedRealtimeMs);
9215         }
9216 
noteForegroundServicePausedLocked(long elapsedRealtimeMs)9217         public void noteForegroundServicePausedLocked(long elapsedRealtimeMs) {
9218             if (mForegroundServiceTimer != null) {
9219                 mForegroundServiceTimer.stopRunningLocked(elapsedRealtimeMs);
9220             }
9221         }
9222 
createVibratorOnTimerLocked()9223         public BatchTimer createVibratorOnTimerLocked() {
9224             if (mVibratorOnTimer == null) {
9225                 mVibratorOnTimer = new BatchTimer(mBsi.mClock, Uid.this, VIBRATOR_ON,
9226                         mBsi.mOnBatteryTimeBase);
9227             }
9228             return mVibratorOnTimer;
9229         }
9230 
noteVibratorOnLocked(long durationMillis, long elapsedRealtimeMs)9231         public void noteVibratorOnLocked(long durationMillis, long elapsedRealtimeMs) {
9232             createVibratorOnTimerLocked().addDuration(durationMillis, elapsedRealtimeMs);
9233         }
9234 
noteVibratorOffLocked(long elapsedRealtimeMs)9235         public void noteVibratorOffLocked(long elapsedRealtimeMs) {
9236             if (mVibratorOnTimer != null) {
9237                 mVibratorOnTimer.abortLastDuration(elapsedRealtimeMs);
9238             }
9239         }
9240 
9241         @Override
getWifiRunningTime(long elapsedRealtimeUs, int which)9242         public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
9243             if (mWifiRunningTimer == null) {
9244                 return 0;
9245             }
9246             return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
9247         }
9248 
9249         @Override
getFullWifiLockTime(long elapsedRealtimeUs, int which)9250         public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
9251             if (mFullWifiLockTimer == null) {
9252                 return 0;
9253             }
9254             return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
9255         }
9256 
9257         @Override
getWifiScanTime(long elapsedRealtimeUs, int which)9258         public long getWifiScanTime(long elapsedRealtimeUs, int which) {
9259             if (mWifiScanTimer == null) {
9260                 return 0;
9261             }
9262             return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
9263         }
9264 
9265         @Override
getWifiScanCount(int which)9266         public int getWifiScanCount(int which) {
9267             if (mWifiScanTimer == null) {
9268                 return 0;
9269             }
9270             return mWifiScanTimer.getCountLocked(which);
9271         }
9272 
9273         @Override
getWifiScanTimer()9274         public Timer getWifiScanTimer() {
9275             return mWifiScanTimer;
9276         }
9277 
9278         @Override
getWifiScanBackgroundCount(int which)9279         public int getWifiScanBackgroundCount(int which) {
9280             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
9281                 return 0;
9282             }
9283             return mWifiScanTimer.getSubTimer().getCountLocked(which);
9284         }
9285 
9286         @Override
getWifiScanActualTime(final long elapsedRealtimeUs)9287         public long getWifiScanActualTime(final long elapsedRealtimeUs) {
9288             if (mWifiScanTimer == null) {
9289                 return 0;
9290             }
9291             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
9292             return mWifiScanTimer.getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
9293         }
9294 
9295         @Override
getWifiScanBackgroundTime(final long elapsedRealtimeUs)9296         public long getWifiScanBackgroundTime(final long elapsedRealtimeUs) {
9297             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
9298                 return 0;
9299             }
9300             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
9301             return mWifiScanTimer.getSubTimer().getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
9302         }
9303 
9304         @Override
getWifiScanBackgroundTimer()9305         public Timer getWifiScanBackgroundTimer() {
9306             if (mWifiScanTimer == null) {
9307                 return null;
9308             }
9309             return mWifiScanTimer.getSubTimer();
9310         }
9311 
9312         @Override
getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which)9313         public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
9314             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
9315             if (mWifiBatchedScanTimer[csphBin] == null) {
9316                 return 0;
9317             }
9318             return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
9319         }
9320 
9321         @Override
getWifiBatchedScanCount(int csphBin, int which)9322         public int getWifiBatchedScanCount(int csphBin, int which) {
9323             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
9324             if (mWifiBatchedScanTimer[csphBin] == null) {
9325                 return 0;
9326             }
9327             return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
9328         }
9329 
9330         @Override
getWifiMulticastTime(long elapsedRealtimeUs, int which)9331         public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
9332             if (mWifiMulticastTimer == null) {
9333                 return 0;
9334             }
9335             return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
9336         }
9337 
9338         @Override
getAudioTurnedOnTimer()9339         public Timer getAudioTurnedOnTimer() {
9340             return mAudioTurnedOnTimer;
9341         }
9342 
9343         @Override
getVideoTurnedOnTimer()9344         public Timer getVideoTurnedOnTimer() {
9345             return mVideoTurnedOnTimer;
9346         }
9347 
9348         @Override
getFlashlightTurnedOnTimer()9349         public Timer getFlashlightTurnedOnTimer() {
9350             return mFlashlightTurnedOnTimer;
9351         }
9352 
9353         @Override
getCameraTurnedOnTimer()9354         public Timer getCameraTurnedOnTimer() {
9355             return mCameraTurnedOnTimer;
9356         }
9357 
9358         @Override
getForegroundActivityTimer()9359         public Timer getForegroundActivityTimer() {
9360             return mForegroundActivityTimer;
9361         }
9362 
9363         @Override
getForegroundServiceTimer()9364         public Timer getForegroundServiceTimer() {
9365             return mForegroundServiceTimer;
9366         }
9367 
9368         @Override
getBluetoothScanTimer()9369         public Timer getBluetoothScanTimer() {
9370             return mBluetoothScanTimer;
9371         }
9372 
9373         @Override
getBluetoothScanBackgroundTimer()9374         public Timer getBluetoothScanBackgroundTimer() {
9375             if (mBluetoothScanTimer == null) {
9376                 return null;
9377             }
9378             return mBluetoothScanTimer.getSubTimer();
9379         }
9380 
9381         @Override
getBluetoothUnoptimizedScanTimer()9382         public Timer getBluetoothUnoptimizedScanTimer() {
9383             return mBluetoothUnoptimizedScanTimer;
9384         }
9385 
9386         @Override
getBluetoothUnoptimizedScanBackgroundTimer()9387         public Timer getBluetoothUnoptimizedScanBackgroundTimer() {
9388             if (mBluetoothUnoptimizedScanTimer == null) {
9389                 return null;
9390             }
9391             return mBluetoothUnoptimizedScanTimer.getSubTimer();
9392         }
9393 
9394         @Override
getBluetoothScanResultCounter()9395         public Counter getBluetoothScanResultCounter() {
9396             return mBluetoothScanResultCounter;
9397         }
9398 
9399         @Override
getBluetoothScanResultBgCounter()9400         public Counter getBluetoothScanResultBgCounter() {
9401             return mBluetoothScanResultBgCounter;
9402         }
9403 
makeProcessState(int i, Parcel in)9404         void makeProcessState(int i, Parcel in) {
9405             if (i < 0 || i >= NUM_PROCESS_STATE) return;
9406 
9407             detachIfNotNull(mProcessStateTimer[i]);
9408             if (in == null) {
9409                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClock, this, PROCESS_STATE, null,
9410                         mBsi.mOnBatteryTimeBase);
9411             } else {
9412                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClock, this, PROCESS_STATE, null,
9413                         mBsi.mOnBatteryTimeBase, in);
9414             }
9415         }
9416 
9417         @Override
getProcessStateTime(int state, long elapsedRealtimeUs, int which)9418         public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
9419             if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
9420             if (mProcessStateTimer[state] == null) {
9421                 return 0;
9422             }
9423             return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
9424         }
9425 
9426         @Override
getProcessStateTimer(int state)9427         public Timer getProcessStateTimer(int state) {
9428             if (state < 0 || state >= NUM_PROCESS_STATE) return null;
9429             return mProcessStateTimer[state];
9430         }
9431 
9432         @Override
getVibratorOnTimer()9433         public Timer getVibratorOnTimer() {
9434             return mVibratorOnTimer;
9435         }
9436 
9437         @Override
noteUserActivityLocked(@owerManager.UserActivityEvent int event)9438         public void noteUserActivityLocked(@PowerManager.UserActivityEvent int event) {
9439             if (mUserActivityCounters == null) {
9440                 initUserActivityLocked();
9441             }
9442             if (event >= 0 && event < NUM_USER_ACTIVITY_TYPES) {
9443                 mUserActivityCounters[event].stepAtomic();
9444             } else {
9445                 Slog.w(TAG, "Unknown user activity type " + event + " was specified.",
9446                         new Throwable());
9447             }
9448         }
9449 
9450         @Override
hasUserActivity()9451         public boolean hasUserActivity() {
9452             return mUserActivityCounters != null;
9453         }
9454 
9455         @Override
getUserActivityCount(int type, int which)9456         public int getUserActivityCount(int type, int which) {
9457             if (mUserActivityCounters == null) {
9458                 return 0;
9459             }
9460             return mUserActivityCounters[type].getCountLocked(which);
9461         }
9462 
makeWifiBatchedScanBin(int i, Parcel in)9463         void makeWifiBatchedScanBin(int i, Parcel in) {
9464             if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
9465 
9466             ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
9467             if (collected == null) {
9468                 collected = new ArrayList<StopwatchTimer>();
9469                 mBsi.mWifiBatchedScanTimers.put(i, collected);
9470             }
9471             detachIfNotNull(mWifiBatchedScanTimer[i]);
9472             if (in == null) {
9473                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClock, this, WIFI_BATCHED_SCAN,
9474                         collected, mBsi.mOnBatteryTimeBase);
9475             } else {
9476                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClock, this, WIFI_BATCHED_SCAN,
9477                         collected, mBsi.mOnBatteryTimeBase, in);
9478             }
9479         }
9480 
9481 
initUserActivityLocked()9482         void initUserActivityLocked() {
9483             detachIfNotNull(mUserActivityCounters);
9484             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
9485             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
9486                 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
9487             }
9488         }
9489 
noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets)9490         void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
9491             ensureNetworkActivityLocked();
9492             if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
9493                 mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
9494                 mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
9495             } else {
9496                 Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
9497                         new Throwable());
9498             }
9499         }
9500 
noteMobileRadioActiveTimeLocked(long batteryUptimeDeltaUs, long elapsedTimeMs)9501         void noteMobileRadioActiveTimeLocked(long batteryUptimeDeltaUs, long elapsedTimeMs) {
9502             ensureNetworkActivityLocked();
9503             getMobileRadioActiveTimeCounter().increment(batteryUptimeDeltaUs, elapsedTimeMs);
9504             mMobileRadioActiveCount.addCountLocked(1);
9505         }
9506 
getMobileRadioActiveTimeCounter()9507         private TimeMultiStateCounter getMobileRadioActiveTimeCounter() {
9508             if (mMobileRadioActiveTime == null) {
9509                 final long timestampMs = mBsi.mClock.elapsedRealtime();
9510                 mMobileRadioActiveTime = new TimeMultiStateCounter(
9511                         mBsi.mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT, timestampMs);
9512                 mMobileRadioActiveTime.setState(
9513                         mapUidProcessStateToBatteryConsumerProcessState(mProcessState),
9514                         timestampMs);
9515                 mMobileRadioActiveTime.update(0, timestampMs);
9516             }
9517             return mMobileRadioActiveTime;
9518         }
9519 
9520         @Override
hasNetworkActivity()9521         public boolean hasNetworkActivity() {
9522             return mNetworkByteActivityCounters != null;
9523         }
9524 
9525         @Override
getNetworkActivityBytes(int type, int which)9526         public long getNetworkActivityBytes(int type, int which) {
9527             if (mNetworkByteActivityCounters != null && type >= 0
9528                     && type < mNetworkByteActivityCounters.length) {
9529                 return mNetworkByteActivityCounters[type].getCountLocked(which);
9530             } else {
9531                 return 0;
9532             }
9533         }
9534 
9535         @Override
getNetworkActivityPackets(int type, int which)9536         public long getNetworkActivityPackets(int type, int which) {
9537             if (mNetworkPacketActivityCounters != null && type >= 0
9538                     && type < mNetworkPacketActivityCounters.length) {
9539                 return mNetworkPacketActivityCounters[type].getCountLocked(which);
9540             } else {
9541                 return 0;
9542             }
9543         }
9544 
9545         @Override
getMobileRadioActiveTime(int which)9546         public long getMobileRadioActiveTime(int which) {
9547             return getMobileRadioActiveTimeInProcessState(BatteryConsumer.PROCESS_STATE_ANY);
9548         }
9549 
9550         @Override
getMobileRadioActiveTimeInProcessState( @atteryConsumer.ProcessState int processState)9551         public long getMobileRadioActiveTimeInProcessState(
9552                 @BatteryConsumer.ProcessState int processState) {
9553             if (mMobileRadioActiveTime == null) {
9554                 return 0;
9555             }
9556             if (processState == BatteryConsumer.PROCESS_STATE_ANY) {
9557                 return mMobileRadioActiveTime.getTotalCountLocked();
9558             } else {
9559                 return mMobileRadioActiveTime.getCountForProcessState(processState);
9560             }
9561         }
9562 
9563         @Override
getMobileRadioActiveCount(int which)9564         public int getMobileRadioActiveCount(int which) {
9565             return mMobileRadioActiveCount != null
9566                     ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
9567         }
9568 
9569         @Override
getUserCpuTimeUs(int which)9570         public long getUserCpuTimeUs(int which) {
9571             return mUserCpuTime.getCountLocked(which);
9572         }
9573 
9574         @Override
getSystemCpuTimeUs(int which)9575         public long getSystemCpuTimeUs(int which) {
9576             return mSystemCpuTime.getCountLocked(which);
9577         }
9578 
9579         @Override
9580         @Deprecated
getTimeAtCpuSpeed(int cluster, int step, int which)9581         public long getTimeAtCpuSpeed(int cluster, int step, int which) {
9582             if (mCpuClusterSpeedTimesUs != null) {
9583                 if (cluster >= 0 && cluster < mCpuClusterSpeedTimesUs.length) {
9584                     final LongSamplingCounter[] cpuSpeedTimesUs = mCpuClusterSpeedTimesUs[cluster];
9585                     if (cpuSpeedTimesUs != null) {
9586                         if (step >= 0 && step < cpuSpeedTimesUs.length) {
9587                             final LongSamplingCounter c = cpuSpeedTimesUs[step];
9588                             if (c != null) {
9589                                 return c.getCountLocked(which);
9590                             }
9591                         }
9592                     }
9593                 }
9594             }
9595             return 0;
9596         }
9597 
noteMobileRadioApWakeupLocked()9598         public void noteMobileRadioApWakeupLocked() {
9599             if (mMobileRadioApWakeupCount == null) {
9600                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9601             }
9602             mMobileRadioApWakeupCount.addCountLocked(1);
9603         }
9604 
9605         @Override
getMobileRadioApWakeupCount(int which)9606         public long getMobileRadioApWakeupCount(int which) {
9607             if (mMobileRadioApWakeupCount != null) {
9608                 return mMobileRadioApWakeupCount.getCountLocked(which);
9609             }
9610             return 0;
9611         }
9612 
noteWifiRadioApWakeupLocked()9613         public void noteWifiRadioApWakeupLocked() {
9614             if (mWifiRadioApWakeupCount == null) {
9615                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9616             }
9617             mWifiRadioApWakeupCount.addCountLocked(1);
9618         }
9619 
9620         @Override
getWifiRadioApWakeupCount(int which)9621         public long getWifiRadioApWakeupCount(int which) {
9622             if (mWifiRadioApWakeupCount != null) {
9623                 return mWifiRadioApWakeupCount.getCountLocked(which);
9624             }
9625             return 0;
9626         }
9627 
9628         @Override
getDeferredJobsCheckinLineLocked(StringBuilder sb, int which)9629         public void getDeferredJobsCheckinLineLocked(StringBuilder sb, int which) {
9630             sb.setLength(0);
9631             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
9632             if (deferredEventCount == 0) {
9633                 return;
9634             }
9635             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
9636             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
9637             sb.append(deferredEventCount); sb.append(',');
9638             sb.append(deferredCount); sb.append(',');
9639             sb.append(totalLatency);
9640             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
9641                 if (mJobsFreshnessBuckets[i] == null) {
9642                     sb.append(",0");
9643                 } else {
9644                     sb.append(",");
9645                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
9646                 }
9647             }
9648         }
9649 
9650         @Override
getDeferredJobsLineLocked(StringBuilder sb, int which)9651         public void getDeferredJobsLineLocked(StringBuilder sb, int which) {
9652             sb.setLength(0);
9653             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
9654             if (deferredEventCount == 0) {
9655                 return;
9656             }
9657             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
9658             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
9659             sb.append("times="); sb.append(deferredEventCount); sb.append(", ");
9660             sb.append("count="); sb.append(deferredCount); sb.append(", ");
9661             sb.append("totalLatencyMs="); sb.append(totalLatency); sb.append(", ");
9662             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
9663                 sb.append("<"); sb.append(JOB_FRESHNESS_BUCKETS[i]); sb.append("ms=");
9664                 if (mJobsFreshnessBuckets[i] == null) {
9665                     sb.append("0");
9666                 } else {
9667                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
9668                 }
9669                 sb.append(" ");
9670             }
9671         }
9672 
ensureNetworkActivityLocked()9673         void ensureNetworkActivityLocked() {
9674             if (mNetworkByteActivityCounters != null) {
9675                 return;
9676             }
9677 
9678             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
9679             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
9680             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9681                 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9682                 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9683             }
9684             mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9685         }
9686 
9687         /**
9688          * Clear all stats for this uid.  Returns true if the uid is completely
9689          * inactive so can be dropped.
9690          */
9691         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
reset(long uptimeUs, long realtimeUs, int resetReason)9692         public boolean reset(long uptimeUs, long realtimeUs, int resetReason) {
9693             boolean active = false;
9694 
9695             mOnBatteryBackgroundTimeBase.init(uptimeUs, realtimeUs);
9696             mOnBatteryScreenOffBackgroundTimeBase.init(uptimeUs, realtimeUs);
9697 
9698             if (mWifiRunningTimer != null) {
9699                 active |= !mWifiRunningTimer.reset(false, realtimeUs);
9700                 active |= mWifiRunning;
9701             }
9702             if (mFullWifiLockTimer != null) {
9703                 active |= !mFullWifiLockTimer.reset(false, realtimeUs);
9704                 active |= mFullWifiLockOut;
9705             }
9706             if (mWifiScanTimer != null) {
9707                 active |= !mWifiScanTimer.reset(false, realtimeUs);
9708                 active |= mWifiScanStarted;
9709             }
9710             if (mWifiBatchedScanTimer != null) {
9711                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
9712                     if (mWifiBatchedScanTimer[i] != null) {
9713                         active |= !mWifiBatchedScanTimer[i].reset(false, realtimeUs);
9714                     }
9715                 }
9716                 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
9717             }
9718             if (mWifiMulticastTimer != null) {
9719                 active |= !mWifiMulticastTimer.reset(false, realtimeUs);
9720                 active |= (mWifiMulticastWakelockCount > 0);
9721             }
9722 
9723             active |= !resetIfNotNull(mAudioTurnedOnTimer, false, realtimeUs);
9724             active |= !resetIfNotNull(mVideoTurnedOnTimer, false, realtimeUs);
9725             active |= !resetIfNotNull(mFlashlightTurnedOnTimer, false, realtimeUs);
9726             active |= !resetIfNotNull(mCameraTurnedOnTimer, false, realtimeUs);
9727             active |= !resetIfNotNull(mForegroundActivityTimer, false, realtimeUs);
9728             active |= !resetIfNotNull(mForegroundServiceTimer, false, realtimeUs);
9729             active |= !resetIfNotNull(mAggregatedPartialWakelockTimer, false, realtimeUs);
9730             active |= !resetIfNotNull(mBluetoothScanTimer, false, realtimeUs);
9731             active |= !resetIfNotNull(mBluetoothUnoptimizedScanTimer, false, realtimeUs);
9732 
9733             resetIfNotNull(mBluetoothScanResultCounter, false, realtimeUs);
9734             resetIfNotNull(mBluetoothScanResultBgCounter, false, realtimeUs);
9735 
9736             if (mProcessStateTimer != null) {
9737                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
9738                     active |= !resetIfNotNull(mProcessStateTimer[i], false, realtimeUs);
9739                 }
9740                 active |= (mProcessState != Uid.PROCESS_STATE_NONEXISTENT);
9741             }
9742             if (mVibratorOnTimer != null) {
9743                 if (mVibratorOnTimer.reset(false, realtimeUs)) {
9744                     mVibratorOnTimer.detach();
9745                     mVibratorOnTimer = null;
9746                 } else {
9747                     active = true;
9748                 }
9749             }
9750 
9751             resetIfNotNull(mUserActivityCounters, false, realtimeUs);
9752 
9753             resetIfNotNull(mNetworkByteActivityCounters, false, realtimeUs);
9754             resetIfNotNull(mNetworkPacketActivityCounters, false, realtimeUs);
9755             resetIfNotNull(mMobileRadioActiveTime, false, realtimeUs);
9756             resetIfNotNull(mMobileRadioActiveCount, false, realtimeUs);
9757 
9758             resetIfNotNull(mWifiControllerActivity, false, realtimeUs);
9759             resetIfNotNull(mBluetoothControllerActivity, false, realtimeUs);
9760             resetIfNotNull(mModemControllerActivity, false, realtimeUs);
9761 
9762             if (resetReason == RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE) {
9763                 mUidEnergyConsumerStats = null;
9764             } else {
9765                 EnergyConsumerStats.resetIfNotNull(mUidEnergyConsumerStats);
9766             }
9767 
9768             resetIfNotNull(mUserCpuTime, false, realtimeUs);
9769             resetIfNotNull(mSystemCpuTime, false, realtimeUs);
9770 
9771             resetIfNotNull(mCpuClusterSpeedTimesUs, false, realtimeUs);
9772 
9773             resetIfNotNull(mCpuFreqTimeMs, false, realtimeUs /* unused */);
9774             resetIfNotNull(mScreenOffCpuFreqTimeMs, false, realtimeUs /* unused */);
9775 
9776 
9777             resetIfNotNull(mCpuActiveTimeMs, false, realtimeUs /* unused */);
9778             resetIfNotNull(mCpuClusterTimesMs, false, realtimeUs /* unused */);
9779 
9780             resetIfNotNull(mProcStateTimeMs, false, realtimeUs /* unused */);
9781 
9782             resetIfNotNull(mProcStateScreenOffTimeMs, false, realtimeUs /* unused */);
9783 
9784             resetIfNotNull(mMobileRadioApWakeupCount, false, realtimeUs);
9785 
9786             resetIfNotNull(mWifiRadioApWakeupCount, false, realtimeUs);
9787 
9788 
9789             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
9790             for (int iw=wakeStats.size()-1; iw>=0; iw--) {
9791                 Wakelock wl = wakeStats.valueAt(iw);
9792                 if (wl.reset(realtimeUs)) {
9793                     wakeStats.removeAt(iw);
9794                 } else {
9795                     active = true;
9796                 }
9797             }
9798             final long realtimeMs = realtimeUs / 1000;
9799             mWakelockStats.cleanup(realtimeMs);
9800             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
9801             for (int is=syncStats.size()-1; is>=0; is--) {
9802                 DualTimer timer = syncStats.valueAt(is);
9803                 if (timer.reset(false, realtimeUs)) {
9804                     syncStats.removeAt(is);
9805                     timer.detach();
9806                 } else {
9807                     active = true;
9808                 }
9809             }
9810             mSyncStats.cleanup(realtimeMs);
9811             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
9812             for (int ij=jobStats.size()-1; ij>=0; ij--) {
9813                 DualTimer timer = jobStats.valueAt(ij);
9814                 if (timer.reset(false, realtimeUs)) {
9815                     jobStats.removeAt(ij);
9816                     timer.detach();
9817                 } else {
9818                     active = true;
9819                 }
9820             }
9821             mJobStats.cleanup(realtimeMs);
9822             mJobCompletions.clear();
9823 
9824             resetIfNotNull(mJobsDeferredEventCount, false, realtimeUs);
9825             resetIfNotNull(mJobsDeferredCount, false, realtimeUs);
9826             resetIfNotNull(mJobsFreshnessTimeMs, false, realtimeUs /* unused */);
9827             resetIfNotNull(mJobsFreshnessBuckets, false, realtimeUs);
9828 
9829             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
9830                 Sensor s = mSensorStats.valueAt(ise);
9831                 if (s.reset(realtimeUs)) {
9832                     mSensorStats.removeAt(ise);
9833                 } else {
9834                     active = true;
9835                 }
9836             }
9837 
9838             for (int ip = mProcessStats.size() - 1; ip >= 0; ip--) {
9839                 Proc proc = mProcessStats.valueAt(ip);
9840                 proc.detach();
9841             }
9842             mProcessStats.clear();
9843 
9844             for (int i = mPids.size() - 1; i >= 0; i--) {
9845                 Pid pid = mPids.valueAt(i);
9846                 if (pid.mWakeNesting > 0) {
9847                     active = true;
9848                 } else {
9849                     mPids.removeAt(i);
9850                 }
9851             }
9852 
9853 
9854             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
9855                 Pkg p = mPackageStats.valueAt(i);
9856                 p.detach();
9857             }
9858             mPackageStats.clear();
9859 
9860             mBinderCallCount = 0;
9861             mBinderCallStats.clear();
9862 
9863             mProportionalSystemServiceUsage = 0;
9864 
9865             mLastStepUserTimeMs = mLastStepSystemTimeMs = 0;
9866             mCurStepUserTimeMs = mCurStepSystemTimeMs = 0;
9867 
9868 
9869             return !active;
9870         }
9871 
9872         /**
9873          * This method MUST be called whenever the Uid object is destructed, otherwise it is a
9874          * memory leak in {@link TimeBase#mObservers} list.
9875          * Typically the Uid object is destructed when it is removed from
9876          * {@link BatteryStatsImpl#mUidStats}
9877          */
detachFromTimeBase()9878         void detachFromTimeBase() {
9879             detachIfNotNull(mWifiRunningTimer);
9880             detachIfNotNull(mFullWifiLockTimer);
9881             detachIfNotNull(mWifiScanTimer);
9882             detachIfNotNull(mWifiBatchedScanTimer);
9883             detachIfNotNull(mWifiMulticastTimer);
9884             detachIfNotNull(mAudioTurnedOnTimer);
9885             detachIfNotNull(mVideoTurnedOnTimer);
9886             detachIfNotNull(mFlashlightTurnedOnTimer);
9887 
9888             detachIfNotNull(mCameraTurnedOnTimer);
9889             detachIfNotNull(mForegroundActivityTimer);
9890             detachIfNotNull(mForegroundServiceTimer);
9891 
9892             detachIfNotNull(mAggregatedPartialWakelockTimer);
9893 
9894             detachIfNotNull(mBluetoothScanTimer);
9895             detachIfNotNull(mBluetoothUnoptimizedScanTimer);
9896             detachIfNotNull(mBluetoothScanResultCounter);
9897             detachIfNotNull(mBluetoothScanResultBgCounter);
9898 
9899             detachIfNotNull(mProcessStateTimer);
9900 
9901             detachIfNotNull(mVibratorOnTimer);
9902 
9903             detachIfNotNull(mUserActivityCounters);
9904 
9905             detachIfNotNull(mNetworkByteActivityCounters);
9906             detachIfNotNull(mNetworkPacketActivityCounters);
9907 
9908             detachIfNotNull(mMobileRadioActiveTime);
9909             detachIfNotNull(mMobileRadioActiveCount);
9910             detachIfNotNull(mMobileRadioApWakeupCount);
9911             detachIfNotNull(mWifiRadioApWakeupCount);
9912 
9913             detachIfNotNull(mWifiControllerActivity);
9914             detachIfNotNull(mBluetoothControllerActivity);
9915             detachIfNotNull(mModemControllerActivity);
9916 
9917             mPids.clear();
9918 
9919             detachIfNotNull(mUserCpuTime);
9920             detachIfNotNull(mSystemCpuTime);
9921 
9922             detachIfNotNull(mCpuClusterSpeedTimesUs);
9923 
9924             detachIfNotNull(mCpuActiveTimeMs);
9925             detachIfNotNull(mCpuFreqTimeMs);
9926 
9927             detachIfNotNull(mScreenOffCpuFreqTimeMs);
9928 
9929             detachIfNotNull(mCpuClusterTimesMs);
9930 
9931             detachIfNotNull(mProcStateTimeMs);
9932 
9933             detachIfNotNull(mProcStateScreenOffTimeMs);
9934 
9935             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
9936             for (int iw = wakeStats.size() - 1; iw >= 0; iw--) {
9937                 Wakelock wl = wakeStats.valueAt(iw);
9938                 wl.detachFromTimeBase();
9939             }
9940             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
9941             for (int is = syncStats.size() - 1; is >= 0; is--) {
9942                 DualTimer timer = syncStats.valueAt(is);
9943                 detachIfNotNull(timer);
9944             }
9945             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
9946             for (int ij = jobStats.size() - 1; ij >= 0; ij--) {
9947                 DualTimer timer = jobStats.valueAt(ij);
9948                 detachIfNotNull(timer);
9949             }
9950 
9951             detachIfNotNull(mJobsDeferredEventCount);
9952             detachIfNotNull(mJobsDeferredCount);
9953             detachIfNotNull(mJobsFreshnessTimeMs);
9954             detachIfNotNull(mJobsFreshnessBuckets);
9955 
9956 
9957             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
9958                 Sensor s = mSensorStats.valueAt(ise);
9959                 s.detachFromTimeBase();
9960             }
9961 
9962             for (int ip= mProcessStats.size() - 1; ip >= 0; ip--) {
9963                 Proc proc = mProcessStats.valueAt(ip);
9964                 proc.detach();
9965             }
9966             mProcessStats.clear();
9967 
9968             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
9969                 Pkg p = mPackageStats.valueAt(i);
9970                 p.detach();
9971             }
9972             mPackageStats.clear();
9973         }
9974 
writeJobCompletionsToParcelLocked(Parcel out)9975         void writeJobCompletionsToParcelLocked(Parcel out) {
9976             int NJC = mJobCompletions.size();
9977             out.writeInt(NJC);
9978             for (int ijc=0; ijc<NJC; ijc++) {
9979                 out.writeString(mJobCompletions.keyAt(ijc));
9980                 SparseIntArray types = mJobCompletions.valueAt(ijc);
9981                 int NT = types.size();
9982                 out.writeInt(NT);
9983                 for (int it=0; it<NT; it++) {
9984                     out.writeInt(types.keyAt(it));
9985                     out.writeInt(types.valueAt(it));
9986                 }
9987             }
9988         }
9989 
readJobCompletionsFromParcelLocked(Parcel in)9990         void readJobCompletionsFromParcelLocked(Parcel in) {
9991             int numJobCompletions = in.readInt();
9992             mJobCompletions.clear();
9993             for (int j = 0; j < numJobCompletions; j++) {
9994                 String jobName = in.readString();
9995                 int numTypes = in.readInt();
9996                 if (numTypes > 0) {
9997                     SparseIntArray types = new SparseIntArray();
9998                     for (int k = 0; k < numTypes; k++) {
9999                         int type = in.readInt();
10000                         int count = in.readInt();
10001                         types.put(type, count);
10002                     }
10003                     mJobCompletions.put(jobName, types);
10004                 }
10005             }
10006         }
10007 
noteJobsDeferredLocked(int numDeferred, long sinceLast)10008         public void noteJobsDeferredLocked(int numDeferred, long sinceLast) {
10009             mJobsDeferredEventCount.addAtomic(1);
10010             mJobsDeferredCount.addAtomic(numDeferred);
10011             if (sinceLast != 0) {
10012                 // Add the total time, which can be divided by the event count to get an average
10013                 mJobsFreshnessTimeMs.addCountLocked(sinceLast);
10014                 // Also keep track of how many times there were in these different buckets.
10015                 for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
10016                     if (sinceLast < JOB_FRESHNESS_BUCKETS[i]) {
10017                         if (mJobsFreshnessBuckets[i] == null) {
10018                             mJobsFreshnessBuckets[i] = new Counter(
10019                                     mBsi.mOnBatteryTimeBase);
10020                         }
10021                         mJobsFreshnessBuckets[i].addAtomic(1);
10022                         break;
10023                     }
10024                 }
10025             }
10026         }
10027 
10028         // Reusable object used as a key to lookup values in mBinderCallStats
10029         private static BinderCallStats sTempBinderCallStats = new BinderCallStats();
10030 
10031         /**
10032          * Notes incoming binder call stats associated with this work source UID.
10033          */
noteBinderCallStatsLocked(long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats)10034         public void noteBinderCallStatsLocked(long incrementalCallCount,
10035                 Collection<BinderCallsStats.CallStat> callStats) {
10036             if (DEBUG) {
10037                 Slog.d(TAG, "noteBinderCalls() workSourceUid = [" + mUid + "], "
10038                         + " incrementalCallCount: " + incrementalCallCount + " callStats = ["
10039                         + new ArrayList<>(callStats) + "]");
10040             }
10041             mBinderCallCount += incrementalCallCount;
10042             for (BinderCallsStats.CallStat stat : callStats) {
10043                 BinderCallStats bcs;
10044                 sTempBinderCallStats.binderClass = stat.binderClass;
10045                 sTempBinderCallStats.transactionCode = stat.transactionCode;
10046                 int index = mBinderCallStats.indexOf(sTempBinderCallStats);
10047                 if (index >= 0) {
10048                     bcs = mBinderCallStats.valueAt(index);
10049                 } else {
10050                     bcs = new BinderCallStats();
10051                     bcs.binderClass = stat.binderClass;
10052                     bcs.transactionCode = stat.transactionCode;
10053                     mBinderCallStats.add(bcs);
10054                 }
10055 
10056                 bcs.callCount += stat.incrementalCallCount;
10057                 bcs.recordedCallCount = stat.recordedCallCount;
10058                 bcs.recordedCpuTimeMicros = stat.cpuTimeMicros;
10059             }
10060         }
10061 
10062         /**
10063          * The statistics associated with a particular wake lock.
10064          */
10065         public static class Wakelock extends BatteryStats.Uid.Wakelock {
10066             /**
10067              * BatteryStatsImpl that we are associated with.
10068              */
10069             protected BatteryStatsImpl mBsi;
10070 
10071             /**
10072              * BatteryStatsImpl that we are associated with.
10073              */
10074             protected Uid mUid;
10075 
10076             /**
10077              * How long (in ms) this uid has been keeping the device partially awake.
10078              * Tracks both the total time and the time while the app was in the background.
10079              */
10080             DualTimer mTimerPartial;
10081 
10082             /**
10083              * How long (in ms) this uid has been keeping the device fully awake.
10084              */
10085             StopwatchTimer mTimerFull;
10086 
10087             /**
10088              * How long (in ms) this uid has had a window keeping the device awake.
10089              */
10090             StopwatchTimer mTimerWindow;
10091 
10092             /**
10093              * How long (in ms) this uid has had a draw wake lock.
10094              */
10095             StopwatchTimer mTimerDraw;
10096 
Wakelock(BatteryStatsImpl bsi, Uid uid)10097             public Wakelock(BatteryStatsImpl bsi, Uid uid) {
10098                 mBsi = bsi;
10099                 mUid = uid;
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              */
readStopwatchTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in)10109             private StopwatchTimer readStopwatchTimerFromParcel(int type,
10110                     ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
10111                 if (in.readInt() == 0) {
10112                     return null;
10113                 }
10114 
10115                 return new StopwatchTimer(mBsi.mClock, mUid, type, pool, timeBase, in);
10116             }
10117 
10118             /**
10119              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
10120              * proper timer pool from the given BatteryStatsImpl object.
10121              *
10122              * @param in the Parcel to be read from.
10123              * return a new Timer, or null.
10124              */
readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, TimeBase bgTimeBase, Parcel in)10125             private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
10126                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
10127                 if (in.readInt() == 0) {
10128                     return null;
10129                 }
10130 
10131                 return new DualTimer(mBsi.mClock, mUid, type, pool, timeBase, bgTimeBase, in);
10132             }
10133 
reset(long elapsedRealtimeUs)10134             boolean reset(long elapsedRealtimeUs) {
10135                 boolean wlactive = false;
10136 
10137                 wlactive |= !resetIfNotNull(mTimerFull, false, elapsedRealtimeUs);
10138                 wlactive |= !resetIfNotNull(mTimerPartial, false, elapsedRealtimeUs);
10139                 wlactive |= !resetIfNotNull(mTimerWindow, false, elapsedRealtimeUs);
10140                 wlactive |= !resetIfNotNull(mTimerDraw, false, elapsedRealtimeUs);
10141 
10142                 if (!wlactive) {
10143                     detachIfNotNull(mTimerFull);
10144                     mTimerFull = null;
10145 
10146                     detachIfNotNull(mTimerPartial);
10147                     mTimerPartial = null;
10148 
10149                     detachIfNotNull(mTimerWindow);
10150                     mTimerWindow = null;
10151 
10152                     detachIfNotNull(mTimerDraw);
10153                     mTimerDraw = null;
10154                 }
10155                 return !wlactive;
10156             }
10157 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, TimeBase screenOffBgTimeBase, Parcel in)10158             void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase,
10159                     TimeBase screenOffBgTimeBase, Parcel in) {
10160                 mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL,
10161                         mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in);
10162                 mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
10163                         mBsi.mFullTimers, timeBase, in);
10164                 mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
10165                         mBsi.mWindowTimers, timeBase, in);
10166                 mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
10167                         mBsi.mDrawTimers, timeBase, in);
10168             }
10169 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)10170             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
10171                 Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
10172                 Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
10173                 Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
10174                 Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
10175             }
10176 
10177             @Override
getWakeTime(int type)10178             public Timer getWakeTime(int type) {
10179                 switch (type) {
10180                 case WAKE_TYPE_FULL: return mTimerFull;
10181                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
10182                 case WAKE_TYPE_WINDOW: return mTimerWindow;
10183                 case WAKE_TYPE_DRAW: return mTimerDraw;
10184                 default: throw new IllegalArgumentException("type = " + type);
10185                 }
10186             }
10187 
detachFromTimeBase()10188             public void detachFromTimeBase() {
10189                 detachIfNotNull(mTimerPartial);
10190                 detachIfNotNull(mTimerFull);
10191                 detachIfNotNull(mTimerWindow);
10192                 detachIfNotNull(mTimerDraw);
10193             }
10194         }
10195 
10196         public static class Sensor extends BatteryStats.Uid.Sensor {
10197             /**
10198              * BatteryStatsImpl that we are associated with.
10199              */
10200             protected BatteryStatsImpl mBsi;
10201 
10202             /**
10203              * Uid that we are associated with.
10204              */
10205             protected Uid mUid;
10206 
10207             final int mHandle;
10208             DualTimer mTimer;
10209 
Sensor(BatteryStatsImpl bsi, Uid uid, int handle)10210             public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
10211                 mBsi = bsi;
10212                 mUid = uid;
10213                 mHandle = handle;
10214             }
10215 
readTimersFromParcel( TimeBase timeBase, TimeBase bgTimeBase, Parcel in)10216             private DualTimer readTimersFromParcel(
10217                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
10218                 if (in.readInt() == 0) {
10219                     return null;
10220                 }
10221 
10222                 ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
10223                 if (pool == null) {
10224                     pool = new ArrayList<StopwatchTimer>();
10225                     mBsi.mSensorTimers.put(mHandle, pool);
10226                 }
10227                 return new DualTimer(mBsi.mClock, mUid, 0, pool, timeBase, bgTimeBase, in);
10228             }
10229 
reset(long elapsedRealtimeUs)10230             boolean reset(long elapsedRealtimeUs) {
10231                 if (mTimer.reset(true, elapsedRealtimeUs)) {
10232                     mTimer = null;
10233                     return true;
10234                 }
10235                 return false;
10236             }
10237 
readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in)10238             void readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
10239                 mTimer = readTimersFromParcel(timeBase, bgTimeBase, in);
10240             }
10241 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)10242             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
10243                 Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
10244             }
10245 
10246             @Override
getSensorTime()10247             public Timer getSensorTime() {
10248                 return mTimer;
10249             }
10250 
10251             @Override
getSensorBackgroundTime()10252             public Timer getSensorBackgroundTime() {
10253                 if (mTimer == null) {
10254                     return null;
10255                 }
10256                 return mTimer.getSubTimer();
10257             }
10258 
10259             @Override
getHandle()10260             public int getHandle() {
10261                 return mHandle;
10262             }
10263 
detachFromTimeBase()10264             public void  detachFromTimeBase() {
10265                 detachIfNotNull(mTimer);
10266             }
10267         }
10268 
10269         /**
10270          * The statistics associated with a particular process.
10271          */
10272         public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
10273             /**
10274              * BatteryStatsImpl that we are associated with.
10275              */
10276             protected BatteryStatsImpl mBsi;
10277 
10278             /**
10279              * The name of this process.
10280              */
10281             final String mName;
10282 
10283             /**
10284              * Remains true until removed from the stats.
10285              */
10286             boolean mActive = true;
10287 
10288             /**
10289              * Total time (in ms) spent executing in user code.
10290              */
10291             long mUserTimeMs;
10292 
10293             /**
10294              * Total time (in ms) spent executing in kernel code.
10295              */
10296             long mSystemTimeMs;
10297 
10298             /**
10299              * Amount of time (in ms) the process was running in the foreground.
10300              */
10301             long mForegroundTimeMs;
10302 
10303             /**
10304              * Number of times the process has been started.
10305              */
10306             int mStarts;
10307 
10308             /**
10309              * Number of times the process has crashed.
10310              */
10311             int mNumCrashes;
10312 
10313             /**
10314              * Number of times the process has had an ANR.
10315              */
10316             int mNumAnrs;
10317 
10318             ArrayList<ExcessivePower> mExcessivePower;
10319 
Proc(BatteryStatsImpl bsi, String name)10320             public Proc(BatteryStatsImpl bsi, String name) {
10321                 mBsi = bsi;
10322                 mName = name;
10323                 mBsi.mOnBatteryTimeBase.add(this);
10324             }
10325 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10326             public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
10327                     long baseRealtimeUs) {
10328             }
10329 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10330             public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
10331                     long baseRealtimeUs) {
10332             }
10333 
10334             @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)10335             public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
10336                 if (detachIfReset) {
10337                     this.detach();
10338                 }
10339                 return true;
10340             }
10341 
10342             @Override
detach()10343             public void detach() {
10344                 mActive = false;
10345                 mBsi.mOnBatteryTimeBase.remove(this);
10346             }
10347 
countExcessivePowers()10348             public int countExcessivePowers() {
10349                 return mExcessivePower != null ? mExcessivePower.size() : 0;
10350             }
10351 
getExcessivePower(int i)10352             public ExcessivePower getExcessivePower(int i) {
10353                 if (mExcessivePower != null) {
10354                     return mExcessivePower.get(i);
10355                 }
10356                 return null;
10357             }
10358 
addExcessiveCpu(long overTimeMs, long usedTimeMs)10359             public void addExcessiveCpu(long overTimeMs, long usedTimeMs) {
10360                 if (mExcessivePower == null) {
10361                     mExcessivePower = new ArrayList<ExcessivePower>();
10362                 }
10363                 ExcessivePower ew = new ExcessivePower();
10364                 ew.type = ExcessivePower.TYPE_CPU;
10365                 ew.overTime = overTimeMs;
10366                 ew.usedTime = usedTimeMs;
10367                 mExcessivePower.add(ew);
10368             }
10369 
writeExcessivePowerToParcelLocked(Parcel out)10370             void writeExcessivePowerToParcelLocked(Parcel out) {
10371                 if (mExcessivePower == null) {
10372                     out.writeInt(0);
10373                     return;
10374                 }
10375 
10376                 final int N = mExcessivePower.size();
10377                 out.writeInt(N);
10378                 for (int i=0; i<N; i++) {
10379                     ExcessivePower ew = mExcessivePower.get(i);
10380                     out.writeInt(ew.type);
10381                     out.writeLong(ew.overTime);
10382                     out.writeLong(ew.usedTime);
10383                 }
10384             }
10385 
readExcessivePowerFromParcelLocked(Parcel in)10386             void readExcessivePowerFromParcelLocked(Parcel in) {
10387                 final int N = in.readInt();
10388                 if (N == 0) {
10389                     mExcessivePower = null;
10390                     return;
10391                 }
10392 
10393                 if (N > 10000) {
10394                     throw new ParcelFormatException(
10395                             "File corrupt: too many excessive power entries " + N);
10396                 }
10397 
10398                 mExcessivePower = new ArrayList<>();
10399                 for (int i=0; i<N; i++) {
10400                     ExcessivePower ew = new ExcessivePower();
10401                     ew.type = in.readInt();
10402                     ew.overTime = in.readLong();
10403                     ew.usedTime = in.readLong();
10404                     mExcessivePower.add(ew);
10405                 }
10406             }
10407 
writeToParcelLocked(Parcel out)10408             void writeToParcelLocked(Parcel out) {
10409                 out.writeLong(mUserTimeMs);
10410                 out.writeLong(mSystemTimeMs);
10411                 out.writeLong(mForegroundTimeMs);
10412                 out.writeInt(mStarts);
10413                 out.writeInt(mNumCrashes);
10414                 out.writeInt(mNumAnrs);
10415                 writeExcessivePowerToParcelLocked(out);
10416             }
10417 
readFromParcelLocked(Parcel in)10418             void readFromParcelLocked(Parcel in) {
10419                 mUserTimeMs = in.readLong();
10420                 mSystemTimeMs = in.readLong();
10421                 mForegroundTimeMs = in.readLong();
10422                 mStarts = in.readInt();
10423                 mNumCrashes = in.readInt();
10424                 mNumAnrs = in.readInt();
10425                 readExcessivePowerFromParcelLocked(in);
10426             }
10427 
addCpuTimeLocked(int utimeMs, int stimeMs)10428             public void addCpuTimeLocked(int utimeMs, int stimeMs) {
10429                 addCpuTimeLocked(utimeMs, stimeMs, mBsi.mOnBatteryTimeBase.isRunning());
10430             }
10431 
addCpuTimeLocked(int utimeMs, int stimeMs, boolean isRunning)10432             public void addCpuTimeLocked(int utimeMs, int stimeMs, boolean isRunning) {
10433                 if (isRunning) {
10434                     mUserTimeMs += utimeMs;
10435                     mSystemTimeMs += stimeMs;
10436                 }
10437             }
10438 
addForegroundTimeLocked(long ttimeMs)10439             public void addForegroundTimeLocked(long ttimeMs) {
10440                 mForegroundTimeMs += ttimeMs;
10441             }
10442 
incStartsLocked()10443             public void incStartsLocked() {
10444                 mStarts++;
10445             }
10446 
incNumCrashesLocked()10447             public void incNumCrashesLocked() {
10448                 mNumCrashes++;
10449             }
10450 
incNumAnrsLocked()10451             public void incNumAnrsLocked() {
10452                 mNumAnrs++;
10453             }
10454 
10455             @Override
isActive()10456             public boolean isActive() {
10457                 return mActive;
10458             }
10459 
10460             @Override
getUserTime(int which)10461             public long getUserTime(int which) {
10462                 return mUserTimeMs;
10463             }
10464 
10465             @Override
getSystemTime(int which)10466             public long getSystemTime(int which) {
10467                 return mSystemTimeMs;
10468             }
10469 
10470             @Override
getForegroundTime(int which)10471             public long getForegroundTime(int which) {
10472                 return mForegroundTimeMs;
10473             }
10474 
10475             @Override
getStarts(int which)10476             public int getStarts(int which) {
10477                 return mStarts;
10478             }
10479 
10480             @Override
getNumCrashes(int which)10481             public int getNumCrashes(int which) {
10482                 return mNumCrashes;
10483             }
10484 
10485             @Override
getNumAnrs(int which)10486             public int getNumAnrs(int which) {
10487                 return mNumAnrs;
10488             }
10489         }
10490 
10491         /**
10492          * The statistics associated with a particular package.
10493          */
10494         public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
10495             /**
10496              * BatteryStatsImpl that we are associated with.
10497              */
10498             protected BatteryStatsImpl mBsi;
10499 
10500             /**
10501              * Number of times wakeup alarms have occurred for this app.
10502              * On screen-off timebase starting in report v25.
10503              */
10504             ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
10505 
10506             /**
10507              * The statics we have collected for this package's services.
10508              */
10509             final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
10510 
Pkg(BatteryStatsImpl bsi)10511             public Pkg(BatteryStatsImpl bsi) {
10512                 mBsi = bsi;
10513                 mBsi.mOnBatteryScreenOffTimeBase.add(this);
10514             }
10515 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10516             public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
10517                     long baseRealtimeUs) {
10518             }
10519 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10520             public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
10521                     long baseRealtimeUs) {
10522             }
10523 
10524             @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)10525             public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
10526                 if (detachIfReset) {
10527                     this.detach();
10528                 }
10529                 return true;
10530             }
10531 
10532             @Override
detach()10533             public void detach() {
10534                 mBsi.mOnBatteryScreenOffTimeBase.remove(this);
10535                 for (int j = mWakeupAlarms.size() - 1; j >= 0; j--) {
10536                     detachIfNotNull(mWakeupAlarms.valueAt(j));
10537                 }
10538                 for (int j = mServiceStats.size() - 1; j >= 0; j--) {
10539                     detachIfNotNull(mServiceStats.valueAt(j));
10540                 }
10541             }
10542 
readFromParcelLocked(Parcel in)10543             void readFromParcelLocked(Parcel in) {
10544                 int numWA = in.readInt();
10545                 mWakeupAlarms.clear();
10546                 for (int i=0; i<numWA; i++) {
10547                     String tag = in.readString();
10548                     mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryScreenOffTimeBase, in));
10549                 }
10550 
10551                 int numServs = in.readInt();
10552                 mServiceStats.clear();
10553                 for (int m = 0; m < numServs; m++) {
10554                     String serviceName = in.readString();
10555                     Uid.Pkg.Serv serv = new Serv(mBsi);
10556                     mServiceStats.put(serviceName, serv);
10557 
10558                     serv.readFromParcelLocked(in);
10559                 }
10560             }
10561 
writeToParcelLocked(Parcel out)10562             void writeToParcelLocked(Parcel out) {
10563                 int numWA = mWakeupAlarms.size();
10564                 out.writeInt(numWA);
10565                 for (int i=0; i<numWA; i++) {
10566                     out.writeString(mWakeupAlarms.keyAt(i));
10567                     mWakeupAlarms.valueAt(i).writeToParcel(out);
10568                 }
10569 
10570                 final int NS = mServiceStats.size();
10571                 out.writeInt(NS);
10572                 for (int i=0; i<NS; i++) {
10573                     out.writeString(mServiceStats.keyAt(i));
10574                     Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
10575                     serv.writeToParcelLocked(out);
10576                 }
10577             }
10578 
10579             @Override
getWakeupAlarmStats()10580             public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
10581                 return mWakeupAlarms;
10582             }
10583 
noteWakeupAlarmLocked(String tag)10584             public void noteWakeupAlarmLocked(String tag) {
10585                 Counter c = mWakeupAlarms.get(tag);
10586                 if (c == null) {
10587                     c = new Counter(mBsi.mOnBatteryScreenOffTimeBase);
10588                     mWakeupAlarms.put(tag, c);
10589                 }
10590                 c.stepAtomic();
10591             }
10592 
10593             @Override
getServiceStats()10594             public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
10595                 return mServiceStats;
10596             }
10597 
10598             /**
10599              * The statistics associated with a particular service.
10600              */
10601             public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
10602                 /**
10603                  * BatteryStatsImpl that we are associated with.
10604                  */
10605                 protected BatteryStatsImpl mBsi;
10606 
10607                 /**
10608                  * The android package in which this service resides.
10609                  */
10610                 protected Pkg mPkg;
10611 
10612                 /**
10613                  * Total time (ms in battery uptime) the service has been left started.
10614                  */
10615                 protected long mStartTimeMs;
10616 
10617                 /**
10618                  * If service has been started and not yet stopped, this is
10619                  * when it was started.
10620                  */
10621                 protected long mRunningSinceMs;
10622 
10623                 /**
10624                  * True if we are currently running.
10625                  */
10626                 protected boolean mRunning;
10627 
10628                 /**
10629                  * Total number of times startService() has been called.
10630                  */
10631                 protected int mStarts;
10632 
10633                 /**
10634                  * Total time (ms in battery uptime) the service has been left launched.
10635                  */
10636                 protected long mLaunchedTimeMs;
10637 
10638                 /**
10639                  * If service has been launched and not yet exited, this is
10640                  * when it was launched (ms in battery uptime).
10641                  */
10642                 protected long mLaunchedSinceMs;
10643 
10644                 /**
10645                  * True if we are currently launched.
10646                  */
10647                 protected boolean mLaunched;
10648 
10649                 /**
10650                  * Total number times the service has been launched.
10651                  */
10652                 protected int mLaunches;
10653 
10654                 /**
10655                  * Construct a Serv. Also adds it to the on-battery time base as a listener.
10656                  */
Serv(BatteryStatsImpl bsi)10657                 public Serv(BatteryStatsImpl bsi) {
10658                     mBsi = bsi;
10659                     mBsi.mOnBatteryTimeBase.add(this);
10660                 }
10661 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10662                 public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
10663                         long baseRealtimeUs) {
10664                 }
10665 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10666                 public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
10667                         long baseRealtimeUs) {
10668                 }
10669 
10670                 @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)10671                 public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
10672                     if (detachIfReset) {
10673                         this.detach();
10674                     }
10675                     return true;
10676                 }
10677 
10678                 /**
10679                  * Remove this Serv as a listener from the time base.
10680                  Ms*/
10681                 @Override
detach()10682                 public void detach() {
10683                     mBsi.mOnBatteryTimeBase.remove(this);
10684                 }
10685 
readFromParcelLocked(Parcel in)10686                 public void readFromParcelLocked(Parcel in) {
10687                     mStartTimeMs = in.readLong();
10688                     mRunningSinceMs = in.readLong();
10689                     mRunning = in.readInt() != 0;
10690                     mStarts = in.readInt();
10691                     mLaunchedTimeMs = in.readLong();
10692                     mLaunchedSinceMs = in.readLong();
10693                     mLaunched = in.readInt() != 0;
10694                     mLaunches = in.readInt();
10695                 }
10696 
writeToParcelLocked(Parcel out)10697                 public void writeToParcelLocked(Parcel out) {
10698                     out.writeLong(mStartTimeMs);
10699                     out.writeLong(mRunningSinceMs);
10700                     out.writeInt(mRunning ? 1 : 0);
10701                     out.writeInt(mStarts);
10702                     out.writeLong(mLaunchedTimeMs);
10703                     out.writeLong(mLaunchedSinceMs);
10704                     out.writeInt(mLaunched ? 1 : 0);
10705                     out.writeInt(mLaunches);
10706                 }
10707 
getLaunchTimeToNowLocked(long batteryUptimeMs)10708                 public long getLaunchTimeToNowLocked(long batteryUptimeMs) {
10709                     if (!mLaunched) return mLaunchedTimeMs;
10710                     return mLaunchedTimeMs + batteryUptimeMs - mLaunchedSinceMs;
10711                 }
10712 
getStartTimeToNowLocked(long batteryUptimeMs)10713                 public long getStartTimeToNowLocked(long batteryUptimeMs) {
10714                     if (!mRunning) return mStartTimeMs;
10715                     return mStartTimeMs + batteryUptimeMs - mRunningSinceMs;
10716                 }
10717 
startLaunchedLocked()10718                 public void startLaunchedLocked() {
10719                     startLaunchedLocked(mBsi.mClock.uptimeMillis());
10720                 }
10721 
startLaunchedLocked(long uptimeMs)10722                 public void startLaunchedLocked(long uptimeMs) {
10723                     if (!mLaunched) {
10724                         mLaunches++;
10725                         mLaunchedSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000;
10726                         mLaunched = true;
10727                     }
10728                 }
10729 
stopLaunchedLocked()10730                 public void stopLaunchedLocked() {
10731                     stopLaunchedLocked(mBsi.mClock.uptimeMillis());
10732                 }
10733 
stopLaunchedLocked(long uptimeMs)10734                 public void stopLaunchedLocked(long uptimeMs) {
10735                     if (mLaunched) {
10736                         long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000
10737                                 - mLaunchedSinceMs;
10738                         if (timeMs > 0) {
10739                             mLaunchedTimeMs += timeMs;
10740                         } else {
10741                             mLaunches--;
10742                         }
10743                         mLaunched = false;
10744                     }
10745                 }
10746 
startRunningLocked()10747                 public void startRunningLocked() {
10748                     startRunningLocked(mBsi.mClock.uptimeMillis());
10749                 }
10750 
startRunningLocked(long uptimeMs)10751                 public void startRunningLocked(long uptimeMs) {
10752                     if (!mRunning) {
10753                         mStarts++;
10754                         mRunningSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000;
10755                         mRunning = true;
10756                     }
10757                 }
10758 
stopRunningLocked()10759                 public void stopRunningLocked() {
10760                     stopRunningLocked(mBsi.mClock.uptimeMillis());
10761                 }
10762 
stopRunningLocked(long uptimeMs)10763                 public void stopRunningLocked(long uptimeMs) {
10764                     if (mRunning) {
10765                         long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000
10766                                 - mRunningSinceMs;
10767                         if (timeMs > 0) {
10768                             mStartTimeMs += timeMs;
10769                         } else {
10770                             mStarts--;
10771                         }
10772                         mRunning = false;
10773                     }
10774                 }
10775 
getBatteryStats()10776                 public BatteryStatsImpl getBatteryStats() {
10777                     return mBsi;
10778                 }
10779 
10780                 @Override
getLaunches(int which)10781                 public int getLaunches(int which) {
10782                     return mLaunches;
10783                 }
10784 
10785                 @Override
getStartTime(long now, int which)10786                 public long getStartTime(long now, int which) {
10787                     return getStartTimeToNowLocked(now);
10788                 }
10789 
10790                 @Override
getStarts(int which)10791                 public int getStarts(int which) {
10792                     return mStarts;
10793                 }
10794             }
10795 
newServiceStatsLocked()10796             final Serv newServiceStatsLocked() {
10797                 return new Serv(mBsi);
10798             }
10799         }
10800 
10801         private class ChildUid {
10802             public final TimeMultiStateCounter cpuActiveCounter;
10803             public final LongArrayMultiStateCounter cpuTimeInFreqCounter;
10804 
ChildUid()10805             ChildUid() {
10806                 final long timestampMs = mBsi.mClock.elapsedRealtime();
10807                 cpuActiveCounter =
10808                         new TimeMultiStateCounter(mBsi.mOnBatteryTimeBase, 1, timestampMs);
10809                 cpuActiveCounter.setState(0, timestampMs);
10810 
10811                 if (mBsi.trackPerProcStateCpuTimes()) {
10812                     final int cpuFreqCount = mBsi.mCpuScalingPolicies.getScalingStepCount();
10813 
10814                     cpuTimeInFreqCounter = new LongArrayMultiStateCounter(1, cpuFreqCount);
10815 
10816                     // Set initial values to all 0. This is a child UID and we want to include
10817                     // the entirety of its CPU time-in-freq stats into the parent's stats.
10818                     cpuTimeInFreqCounter.updateValues(
10819                             new LongArrayMultiStateCounter.LongArrayContainer(cpuFreqCount),
10820                             timestampMs);
10821                 } else {
10822                     cpuTimeInFreqCounter = null;
10823                 }
10824             }
10825         }
10826 
10827         /**
10828          * Retrieve the statistics object for a particular process, creating
10829          * if needed.
10830          */
getProcessStatsLocked(String name)10831         public Proc getProcessStatsLocked(String name) {
10832             Proc ps = mProcessStats.get(name);
10833             if (ps == null) {
10834                 ps = new Proc(mBsi, name);
10835                 mProcessStats.put(name, ps);
10836             }
10837 
10838             return ps;
10839         }
10840 
10841         @GuardedBy("mBsi")
updateUidProcessStateLocked(int procState, long elapsedRealtimeMs, long uptimeMs)10842         public void updateUidProcessStateLocked(int procState,
10843                 long elapsedRealtimeMs, long uptimeMs) {
10844             int uidRunningState;
10845             // Make special note of Foreground Services
10846             final boolean userAwareService = ActivityManager.isForegroundService(procState);
10847             uidRunningState = BatteryStats.mapToInternalProcessState(procState);
10848 
10849             if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
10850                 return;
10851             }
10852 
10853             if (mProcessState != uidRunningState) {
10854                 if (mProcessState != Uid.PROCESS_STATE_NONEXISTENT) {
10855                     mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
10856                 }
10857                 if (uidRunningState != Uid.PROCESS_STATE_NONEXISTENT) {
10858                     if (mProcessStateTimer[uidRunningState] == null) {
10859                         makeProcessState(uidRunningState, null);
10860                     }
10861                     mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
10862                 }
10863 
10864                 if (!mBsi.mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)
10865                         && mBsi.trackPerProcStateCpuTimes()) {
10866                     mBsi.updateProcStateCpuTimesLocked(mUid, elapsedRealtimeMs, uptimeMs);
10867 
10868                     LongArrayMultiStateCounter onBatteryCounter =
10869                             getProcStateTimeCounter(elapsedRealtimeMs).getCounter();
10870                     LongArrayMultiStateCounter onBatteryScreenOffCounter =
10871                             getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter();
10872 
10873                     onBatteryCounter.setState(uidRunningState, elapsedRealtimeMs);
10874                     onBatteryScreenOffCounter.setState(uidRunningState, elapsedRealtimeMs);
10875                 }
10876 
10877                 final int prevBatteryConsumerProcessState =
10878                         mapUidProcessStateToBatteryConsumerProcessState(mProcessState);
10879 
10880                 mProcessState = uidRunningState;
10881 
10882                 updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
10883                 updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
10884 
10885                 final int batteryConsumerProcessState =
10886                         mapUidProcessStateToBatteryConsumerProcessState(uidRunningState);
10887                 if (mBsi.mSystemReady && mBsi.mPowerStatsCollectorEnabled.get(
10888                         BatteryConsumer.POWER_COMPONENT_CPU)) {
10889                     mBsi.mHistory.recordProcessStateChange(elapsedRealtimeMs, uptimeMs, mUid,
10890                             batteryConsumerProcessState);
10891                 }
10892                 getCpuActiveTimeCounter().setState(batteryConsumerProcessState, elapsedRealtimeMs);
10893 
10894                 getMobileRadioActiveTimeCounter()
10895                         .setState(batteryConsumerProcessState, elapsedRealtimeMs);
10896 
10897                 final ControllerActivityCounterImpl wifiControllerActivity =
10898                         getWifiControllerActivity();
10899                 if (wifiControllerActivity != null) {
10900                     wifiControllerActivity.setState(batteryConsumerProcessState, elapsedRealtimeMs);
10901                 }
10902 
10903                 final ControllerActivityCounterImpl bluetoothControllerActivity =
10904                         getBluetoothControllerActivity();
10905                 if (bluetoothControllerActivity != null) {
10906                     bluetoothControllerActivity.setState(batteryConsumerProcessState,
10907                             elapsedRealtimeMs);
10908                 }
10909 
10910                 final EnergyConsumerStats energyStats =
10911                         getOrCreateEnergyConsumerStatsIfSupportedLocked();
10912                 if (energyStats != null) {
10913                     energyStats.setState(batteryConsumerProcessState, elapsedRealtimeMs);
10914                 }
10915                 maybeScheduleExternalStatsSync(prevBatteryConsumerProcessState,
10916                         batteryConsumerProcessState);
10917             }
10918 
10919             if (userAwareService != mInForegroundService) {
10920                 if (userAwareService) {
10921                     noteForegroundServiceResumedLocked(elapsedRealtimeMs);
10922                 } else {
10923                     noteForegroundServicePausedLocked(elapsedRealtimeMs);
10924                 }
10925                 mInForegroundService = userAwareService;
10926             }
10927         }
10928 
10929         @GuardedBy("mBsi")
maybeScheduleExternalStatsSync( @atteryConsumer.ProcessState int oldProcessState, @BatteryConsumer.ProcessState int newProcessState)10930         private void maybeScheduleExternalStatsSync(
10931                 @BatteryConsumer.ProcessState int oldProcessState,
10932                 @BatteryConsumer.ProcessState int newProcessState) {
10933             if (oldProcessState == newProcessState) {
10934                 return;
10935             }
10936             // Transitions between BACKGROUND and such non-foreground states like cached
10937             // or nonexistent do not warrant doing a sync.  If some of the stats for those
10938             // proc states bleed into the PROCESS_STATE_BACKGROUND, that's ok.
10939             if ((oldProcessState == BatteryConsumer.PROCESS_STATE_UNSPECIFIED
10940                     && newProcessState == BatteryConsumer.PROCESS_STATE_BACKGROUND)
10941                     || (oldProcessState == BatteryConsumer.PROCESS_STATE_BACKGROUND
10942                     && newProcessState == BatteryConsumer.PROCESS_STATE_UNSPECIFIED)) {
10943                 return;
10944             }
10945 
10946             int flags = ExternalStatsSync.UPDATE_ON_PROC_STATE_CHANGE;
10947             // Skip querying for inactive radio, where power usage is probably negligible.
10948             if (!BatteryStatsImpl.isActiveRadioPowerState(mBsi.mMobileRadioPowerState)) {
10949                 flags &= ~ExternalStatsSync.UPDATE_RADIO;
10950             }
10951 
10952             mBsi.mExternalSync.scheduleSyncDueToProcessStateChange(flags,
10953                     mBsi.mConstants.PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
10954         }
10955 
10956         /** Whether to consider Uid to be in the background for background timebase purposes. */
isInBackground()10957         public boolean isInBackground() {
10958             // Note that PROCESS_STATE_CACHED and Uid.PROCESS_STATE_NONEXISTENT is
10959             // also considered to be 'background' for our purposes, because it's not foreground.
10960             return mProcessState >= PROCESS_STATE_BACKGROUND;
10961         }
10962 
updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs)10963         public boolean updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs) {
10964             boolean on = mBsi.mOnBatteryTimeBase.isRunning() && isInBackground();
10965             return mOnBatteryBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
10966         }
10967 
updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs)10968         public boolean updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs) {
10969             boolean on = mBsi.mOnBatteryScreenOffTimeBase.isRunning() && isInBackground();
10970             return mOnBatteryScreenOffBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
10971         }
10972 
getPidStats()10973         public SparseArray<? extends Pid> getPidStats() {
10974             return mPids;
10975         }
10976 
getPidStatsLocked(int pid)10977         public Pid getPidStatsLocked(int pid) {
10978             Pid p = mPids.get(pid);
10979             if (p == null) {
10980                 p = new Pid();
10981                 mPids.put(pid, p);
10982             }
10983             return p;
10984         }
10985 
10986         /**
10987          * Retrieve the statistics object for a particular service, creating
10988          * if needed.
10989          */
getPackageStatsLocked(String name)10990         public Pkg getPackageStatsLocked(String name) {
10991             Pkg ps = mPackageStats.get(name);
10992             if (ps == null) {
10993                 ps = new Pkg(mBsi);
10994                 mPackageStats.put(name, ps);
10995             }
10996 
10997             return ps;
10998         }
10999 
11000         /**
11001          * Retrieve the statistics object for a particular service, creating
11002          * if needed.
11003          */
getServiceStatsLocked(String pkg, String serv)11004         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
11005             Pkg ps = getPackageStatsLocked(pkg);
11006             Pkg.Serv ss = ps.mServiceStats.get(serv);
11007             if (ss == null) {
11008                 ss = ps.newServiceStatsLocked();
11009                 ps.mServiceStats.put(serv, ss);
11010             }
11011 
11012             return ss;
11013         }
11014 
readSyncSummaryFromParcelLocked(String name, Parcel in)11015         public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
11016             DualTimer timer = mSyncStats.instantiateObject();
11017             timer.readSummaryFromParcelLocked(in);
11018             mSyncStats.add(name, timer);
11019         }
11020 
readJobSummaryFromParcelLocked(String name, Parcel in)11021         public void readJobSummaryFromParcelLocked(String name, Parcel in) {
11022             DualTimer timer = mJobStats.instantiateObject();
11023             timer.readSummaryFromParcelLocked(in);
11024             mJobStats.add(name, timer);
11025         }
11026 
readWakeSummaryFromParcelLocked(String wlName, Parcel in)11027         public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
11028             Wakelock wl = new Wakelock(mBsi, this);
11029             mWakelockStats.add(wlName, wl);
11030             if (in.readInt() != 0) {
11031                 getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
11032             }
11033             if (in.readInt() != 0) {
11034                 getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
11035             }
11036             if (in.readInt() != 0) {
11037                 getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
11038             }
11039             if (in.readInt() != 0) {
11040                 getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
11041             }
11042         }
11043 
getSensorTimerLocked(int sensor, boolean create)11044         public DualTimer getSensorTimerLocked(int sensor, boolean create) {
11045             Sensor se = mSensorStats.get(sensor);
11046             if (se == null) {
11047                 if (!create) {
11048                     return null;
11049                 }
11050                 se = new Sensor(mBsi, this, sensor);
11051                 mSensorStats.put(sensor, se);
11052             }
11053             DualTimer t = se.mTimer;
11054             if (t != null) {
11055                 return t;
11056             }
11057             ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
11058             if (timers == null) {
11059                 timers = new ArrayList<StopwatchTimer>();
11060                 mBsi.mSensorTimers.put(sensor, timers);
11061             }
11062             t = new DualTimer(mBsi.mClock, this, BatteryStats.SENSOR, timers,
11063                     mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
11064             se.mTimer = t;
11065             return t;
11066         }
11067 
noteStartSyncLocked(String name, long elapsedRealtimeMs)11068         public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
11069             DualTimer t = mSyncStats.startObject(name, elapsedRealtimeMs);
11070             if (t != null) {
11071                 t.startRunningLocked(elapsedRealtimeMs);
11072             }
11073         }
11074 
noteStopSyncLocked(String name, long elapsedRealtimeMs)11075         public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
11076             DualTimer t = mSyncStats.stopObject(name, elapsedRealtimeMs);
11077             if (t != null) {
11078                 t.stopRunningLocked(elapsedRealtimeMs);
11079             }
11080         }
11081 
noteStartJobLocked(String name, long elapsedRealtimeMs)11082         public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
11083             DualTimer t = mJobStats.startObject(name, elapsedRealtimeMs);
11084             if (t != null) {
11085                 t.startRunningLocked(elapsedRealtimeMs);
11086             }
11087         }
11088 
noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason)11089         public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
11090             DualTimer t = mJobStats.stopObject(name, elapsedRealtimeMs);
11091             if (t != null) {
11092                 t.stopRunningLocked(elapsedRealtimeMs);
11093             }
11094             if (mBsi.mOnBatteryTimeBase.isRunning()) {
11095                 SparseIntArray types = mJobCompletions.get(name);
11096                 if (types == null) {
11097                     types = new SparseIntArray();
11098                     mJobCompletions.put(name, types);
11099                 }
11100                 int last = types.get(stopReason, 0);
11101                 types.put(stopReason, last + 1);
11102             }
11103         }
11104 
getWakelockTimerLocked(Wakelock wl, int type)11105         public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
11106             if (wl == null) {
11107                 return null;
11108             }
11109             switch (type) {
11110                 case WAKE_TYPE_PARTIAL: {
11111                     DualTimer t = wl.mTimerPartial;
11112                     if (t == null) {
11113                         t = new DualTimer(mBsi.mClock, this, WAKE_TYPE_PARTIAL,
11114                                 mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase,
11115                                 mOnBatteryScreenOffBackgroundTimeBase);
11116                         wl.mTimerPartial = t;
11117                     }
11118                     return t;
11119                 }
11120                 case WAKE_TYPE_FULL: {
11121                     StopwatchTimer t = wl.mTimerFull;
11122                     if (t == null) {
11123                         t = new StopwatchTimer(mBsi.mClock, this, WAKE_TYPE_FULL,
11124                                 mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
11125                         wl.mTimerFull = t;
11126                     }
11127                     return t;
11128                 }
11129                 case WAKE_TYPE_WINDOW: {
11130                     StopwatchTimer t = wl.mTimerWindow;
11131                     if (t == null) {
11132                         t = new StopwatchTimer(mBsi.mClock, this, WAKE_TYPE_WINDOW,
11133                                 mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
11134                         wl.mTimerWindow = t;
11135                     }
11136                     return t;
11137                 }
11138                 case WAKE_TYPE_DRAW: {
11139                     StopwatchTimer t = wl.mTimerDraw;
11140                     if (t == null) {
11141                         t = new StopwatchTimer(mBsi.mClock, this, WAKE_TYPE_DRAW,
11142                                 mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
11143                         wl.mTimerDraw = t;
11144                     }
11145                     return t;
11146                 }
11147                 default:
11148                     throw new IllegalArgumentException("type=" + type);
11149             }
11150         }
11151 
noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)11152         public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
11153             Wakelock wl = mWakelockStats.startObject(name, elapsedRealtimeMs);
11154             if (wl != null) {
11155                 getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
11156             }
11157             if (type == WAKE_TYPE_PARTIAL) {
11158                 createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
11159                 if (pid >= 0) {
11160                     Pid p = getPidStatsLocked(pid);
11161                     if (p.mWakeNesting++ == 0) {
11162                         p.mWakeStartMs = elapsedRealtimeMs;
11163                     }
11164                 }
11165             }
11166         }
11167 
noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)11168         public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
11169             Wakelock wl = mWakelockStats.stopObject(name, elapsedRealtimeMs);
11170             if (wl != null) {
11171                 StopwatchTimer wlt = getWakelockTimerLocked(wl, type);
11172                 wlt.stopRunningLocked(elapsedRealtimeMs);
11173             }
11174             if (type == WAKE_TYPE_PARTIAL) {
11175                 if (mAggregatedPartialWakelockTimer != null) {
11176                     mAggregatedPartialWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
11177                 }
11178                 if (pid >= 0) {
11179                     Pid p = mPids.get(pid);
11180                     if (p != null && p.mWakeNesting > 0) {
11181                         if (p.mWakeNesting-- == 1) {
11182                             p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
11183                             p.mWakeStartMs = 0;
11184                         }
11185                     }
11186                 }
11187             }
11188         }
11189 
reportExcessiveCpuLocked(String proc, long overTimeMs, long usedTimeMs)11190         public void reportExcessiveCpuLocked(String proc, long overTimeMs, long usedTimeMs) {
11191             Proc p = getProcessStatsLocked(proc);
11192             if (p != null) {
11193                 p.addExcessiveCpu(overTimeMs, usedTimeMs);
11194             }
11195         }
11196 
noteStartSensor(int sensor, long elapsedRealtimeMs)11197         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
11198             DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
11199             t.startRunningLocked(elapsedRealtimeMs);
11200         }
11201 
noteStopSensor(int sensor, long elapsedRealtimeMs)11202         public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
11203             // Don't create a timer if one doesn't already exist
11204             DualTimer t = getSensorTimerLocked(sensor, false);
11205             if (t != null) {
11206                 t.stopRunningLocked(elapsedRealtimeMs);
11207             }
11208         }
11209 
noteStartGps(long elapsedRealtimeMs)11210         public void noteStartGps(long elapsedRealtimeMs) {
11211             noteStartSensor(Sensor.GPS, elapsedRealtimeMs);
11212         }
11213 
noteStopGps(long elapsedRealtimeMs)11214         public void noteStopGps(long elapsedRealtimeMs) {
11215             noteStopSensor(Sensor.GPS, elapsedRealtimeMs);
11216         }
11217     }
11218 
11219     @GuardedBy("this")
getCpuScalingPolicies()11220     public CpuScalingPolicies getCpuScalingPolicies() {
11221         return mCpuScalingPolicies;
11222     }
11223 
11224     @GuardedBy("this")
getCpuTimeInFreqContainer()11225     private LongArrayMultiStateCounter.LongArrayContainer getCpuTimeInFreqContainer() {
11226         if (mTmpCpuTimeInFreq == null) {
11227             mTmpCpuTimeInFreq =
11228                     new LongArrayMultiStateCounter.LongArrayContainer(
11229                             mCpuScalingPolicies.getScalingStepCount());
11230         }
11231         return mTmpCpuTimeInFreq;
11232     }
11233 
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)11234     public BatteryStatsImpl(@NonNull BatteryStatsConfig config, @NonNull Clock clock,
11235             @NonNull MonotonicClock monotonicClock, @Nullable File systemDir,
11236             @NonNull Handler handler, @Nullable PlatformIdleStateCallback platformIdleStateCallback,
11237             @Nullable EnergyStatsRetriever energyStatsRetriever,
11238             @NonNull UserInfoProvider userInfoProvider, @NonNull PowerProfile powerProfile,
11239             @NonNull CpuScalingPolicies cpuScalingPolicies,
11240             @NonNull PowerStatsUidResolver powerStatsUidResolver) {
11241         this(config, clock, monotonicClock, systemDir, handler, platformIdleStateCallback,
11242                 energyStatsRetriever, userInfoProvider, powerProfile, cpuScalingPolicies,
11243                 powerStatsUidResolver, new FrameworkStatsLogger(),
11244                 new BatteryStatsHistory.TraceDelegate(), new BatteryStatsHistory.EventLogger());
11245     }
11246 
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)11247     public BatteryStatsImpl(@NonNull BatteryStatsConfig config, @NonNull Clock clock,
11248             @NonNull MonotonicClock monotonicClock, @Nullable File systemDir,
11249             @NonNull Handler handler, @Nullable PlatformIdleStateCallback platformIdleStateCallback,
11250             @Nullable EnergyStatsRetriever energyStatsRetriever,
11251             @NonNull UserInfoProvider userInfoProvider, @NonNull PowerProfile powerProfile,
11252             @NonNull CpuScalingPolicies cpuScalingPolicies,
11253             @NonNull PowerStatsUidResolver powerStatsUidResolver,
11254             @NonNull FrameworkStatsLogger frameworkStatsLogger,
11255             @NonNull BatteryStatsHistory.TraceDelegate traceDelegate,
11256             @NonNull BatteryStatsHistory.EventLogger eventLogger) {
11257         mClock = clock;
11258         initKernelStatsReaders();
11259 
11260         mBatteryStatsConfig = config;
11261         mMonotonicClock = monotonicClock;
11262         mHandler = new MyHandler(handler.getLooper());
11263         mConstants = new Constants(mHandler);
11264 
11265         mPowerProfile = powerProfile;
11266         mCpuScalingPolicies = cpuScalingPolicies;
11267         mPowerStatsUidResolver = powerStatsUidResolver;
11268         mFrameworkStatsLogger = frameworkStatsLogger;
11269 
11270         initPowerProfile();
11271 
11272         if (systemDir != null) {
11273             mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
11274             mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
11275             mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
11276         } else {
11277             mStatsFile = null;
11278             mCheckinFile = null;
11279             mDailyFile = null;
11280         }
11281 
11282         mHistory = new BatteryStatsHistory(null /* historyBuffer */, systemDir,
11283                 mConstants.MAX_HISTORY_FILES, mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator,
11284                 mClock, mMonotonicClock, traceDelegate, eventLogger);
11285 
11286         mCpuPowerStatsCollector = new CpuPowerStatsCollector(mPowerStatsCollectorInjector);
11287         mCpuPowerStatsCollector.addConsumer(this::recordPowerStats);
11288 
11289         mMobileRadioPowerStatsCollector = new MobileRadioPowerStatsCollector(
11290                 mPowerStatsCollectorInjector);
11291         mMobileRadioPowerStatsCollector.addConsumer(this::recordPowerStats);
11292 
11293         mWifiPowerStatsCollector = new WifiPowerStatsCollector(mPowerStatsCollectorInjector);
11294         mWifiPowerStatsCollector.addConsumer(this::recordPowerStats);
11295 
11296         mBluetoothPowerStatsCollector = new BluetoothPowerStatsCollector(
11297                 mPowerStatsCollectorInjector);
11298         mBluetoothPowerStatsCollector.addConsumer(this::recordPowerStats);
11299 
11300         mCameraPowerStatsCollector = new CameraPowerStatsCollector(mPowerStatsCollectorInjector);
11301         mCameraPowerStatsCollector.addConsumer(this::recordPowerStats);
11302 
11303         mGnssPowerStatsCollector = new GnssPowerStatsCollector(mPowerStatsCollectorInjector);
11304         mGnssPowerStatsCollector.addConsumer(this::recordPowerStats);
11305 
11306         mStartCount++;
11307         initTimersAndCounters();
11308         mOnBattery = mOnBatteryInternal = false;
11309         long uptimeUs = mClock.uptimeMillis() * 1000;
11310         long realtimeUs = mClock.elapsedRealtime() * 1000;
11311         initTimes(uptimeUs, realtimeUs);
11312         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
11313         initDischarge(realtimeUs);
11314         updateDailyDeadlineLocked();
11315         mPlatformIdleStateCallback = platformIdleStateCallback;
11316         mEnergyConsumerRetriever = energyStatsRetriever;
11317         mUserInfoProvider = userInfoProvider;
11318 
11319         mPowerStatsUidResolver.addListener(new PowerStatsUidResolver.Listener() {
11320             @Override
11321             public void onIsolatedUidAdded(int isolatedUid, int parentUid) {
11322                 BatteryStatsImpl.this.onIsolatedUidAdded(isolatedUid, parentUid);
11323             }
11324 
11325             @Override
11326             public void onBeforeIsolatedUidRemoved(int isolatedUid, int parentUid) {
11327                 BatteryStatsImpl.this.onBeforeIsolatedUidRemoved(isolatedUid, parentUid);
11328             }
11329 
11330             @Override
11331             public void onAfterIsolatedUidRemoved(int isolatedUid, int parentUid) {
11332                 BatteryStatsImpl.this.onAfterIsolatedUidRemoved(isolatedUid, parentUid);
11333             }
11334         });
11335 
11336         // Notify statsd that the system is initially not in doze.
11337         mDeviceIdleMode = DEVICE_IDLE_MODE_OFF;
11338         mFrameworkStatsLogger.deviceIdleModeStateChanged(mDeviceIdleMode);
11339     }
11340 
recordPowerStats(PowerStats stats)11341     private void recordPowerStats(PowerStats stats) {
11342         if (stats.durationMs > 0) {
11343             synchronized (this) {
11344                 mHistory.recordPowerStats(mClock.elapsedRealtime(), mClock.uptimeMillis(), stats);
11345             }
11346         }
11347     }
11348 
11349     @VisibleForTesting
initTimersAndCounters()11350     protected void initTimersAndCounters() {
11351         mScreenOnTimer = new StopwatchTimer(mClock, null, -1, null, mOnBatteryTimeBase);
11352         mScreenDozeTimer = new StopwatchTimer(mClock, null, -1, null, mOnBatteryTimeBase);
11353         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11354             mScreenBrightnessTimer[i] = new StopwatchTimer(mClock, null, -100 - i, null,
11355                     mOnBatteryTimeBase);
11356         }
11357 
11358         mPerDisplayBatteryStats = new DisplayBatteryStats[1];
11359         mPerDisplayBatteryStats[0] = new DisplayBatteryStats(mClock, mOnBatteryTimeBase);
11360 
11361         mInteractiveTimer = new StopwatchTimer(mClock, null, -10, null, mOnBatteryTimeBase);
11362         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClock, null, -2, null,
11363                 mOnBatteryTimeBase);
11364         mDeviceIdleModeLightTimer = new StopwatchTimer(mClock, null, -11, null,
11365                 mOnBatteryTimeBase);
11366         mDeviceIdleModeFullTimer = new StopwatchTimer(mClock, null, -14, null, mOnBatteryTimeBase);
11367         mDeviceLightIdlingTimer = new StopwatchTimer(mClock, null, -15, null, mOnBatteryTimeBase);
11368         mDeviceIdlingTimer = new StopwatchTimer(mClock, null, -12, null, mOnBatteryTimeBase);
11369         mPhoneOnTimer = new StopwatchTimer(mClock, null, -3, null, mOnBatteryTimeBase);
11370         for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
11371             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClock, null, -200 - i, null,
11372                     mOnBatteryTimeBase);
11373         }
11374         mPhoneSignalScanningTimer = new StopwatchTimer(mClock, null, -200 + 1, null,
11375                 mOnBatteryTimeBase);
11376         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11377             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClock, null, -300 - i, null,
11378                     mOnBatteryTimeBase);
11379         }
11380         mNrNsaTimer = new StopwatchTimer(mClock, null, -200 + 2, null, mOnBatteryTimeBase);
11381         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11382             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
11383             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
11384         }
11385         mWifiActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
11386                 NUM_WIFI_TX_LEVELS);
11387         mBluetoothActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
11388                 NUM_BT_TX_LEVELS);
11389         mModemActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
11390                 MODEM_TX_POWER_LEVEL_COUNT);
11391         mMobileRadioActiveTimer = new StopwatchTimer(mClock, null, -400, null, mOnBatteryTimeBase);
11392         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClock, null, -401, null,
11393                 mOnBatteryTimeBase);
11394         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
11395         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
11396         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
11397         mWifiMulticastWakelockTimer = new StopwatchTimer(mClock, null,
11398                 WIFI_AGGREGATE_MULTICAST_ENABLED, null, mOnBatteryTimeBase);
11399         mWifiOnTimer = new StopwatchTimer(mClock, null, -4, null, mOnBatteryTimeBase);
11400         mGlobalWifiRunningTimer = new StopwatchTimer(mClock, null, -5, null, mOnBatteryTimeBase);
11401         for (int i=0; i<NUM_WIFI_STATES; i++) {
11402             mWifiStateTimer[i] = new StopwatchTimer(mClock, null, -600 - i, null,
11403                     mOnBatteryTimeBase);
11404         }
11405         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11406             mWifiSupplStateTimer[i] = new StopwatchTimer(mClock, null, -700 - i, null,
11407                     mOnBatteryTimeBase);
11408         }
11409         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11410             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClock, null, -800 - i, null,
11411                     mOnBatteryTimeBase);
11412         }
11413         mWifiActiveTimer = new StopwatchTimer(mClock, null, -900, null, mOnBatteryTimeBase);
11414         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
11415             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClock, null, -1000 - i, null,
11416                     mOnBatteryTimeBase);
11417         }
11418         mAudioOnTimer = new StopwatchTimer(mClock, null, -7, null, mOnBatteryTimeBase);
11419         mVideoOnTimer = new StopwatchTimer(mClock, null, -8, null, mOnBatteryTimeBase);
11420         mFlashlightOnTimer = new StopwatchTimer(mClock, null, -9, null, mOnBatteryTimeBase);
11421         mCameraOnTimer = new StopwatchTimer(mClock, null, -13, null, mOnBatteryTimeBase);
11422         mBluetoothScanTimer = new StopwatchTimer(mClock, null, -14, null, mOnBatteryTimeBase);
11423         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
11424         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
11425         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
11426         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
11427         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
11428         mDischargeUnplugLevel = 0;
11429         mDischargePlugLevel = -1;
11430         mDischargeCurrentLevel = 0;
11431         mBatteryLevel = 0;
11432     }
11433 
initPowerProfile()11434     private void initPowerProfile() {
11435         int[] policies = mCpuScalingPolicies.getPolicies();
11436         mKernelCpuSpeedReaders = new KernelCpuSpeedReader[policies.length];
11437         for (int i = 0; i < policies.length; i++) {
11438             int[] cpus = mCpuScalingPolicies.getRelatedCpus(policies[i]);
11439             int[] freqs = mCpuScalingPolicies.getFrequencies(policies[i]);
11440             // We need to initialize the KernelCpuSpeedReaders to read from
11441             // the first cpu of each core. Once we have the CpuScalingPolicy, we have access to this
11442             // information.
11443             mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(cpus[0], freqs.length);
11444         }
11445 
11446         // Initialize CPU power bracket map, which combines CPU states (cluster/freq pairs)
11447         // into a small number of brackets
11448         mCpuPowerBracketMap = new int[mCpuScalingPolicies.getScalingStepCount()];
11449         int index = 0;
11450         for (int policy : policies) {
11451             int steps = mCpuScalingPolicies.getFrequencies(policy).length;
11452             for (int step = 0; step < steps; step++) {
11453                 mCpuPowerBracketMap[index++] =
11454                         mPowerProfile.getCpuPowerBracketForScalingStep(policy, step);
11455             }
11456         }
11457 
11458         if (mEstimatedBatteryCapacityMah == -1) {
11459             // Initialize the estimated battery capacity to a known preset one.
11460             mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
11461         }
11462 
11463         setDisplayCountLocked(mPowerProfile.getNumDisplays());
11464     }
11465 
getPowerProfile()11466     PowerProfile getPowerProfile() {
11467         return mPowerProfile;
11468     }
11469 
11470     /**
11471      * Starts tracking CPU time-in-state for threads of the system server process,
11472      * keeping a separate account of threads receiving incoming binder calls.
11473      */
startTrackingSystemServerCpuTime()11474     public void startTrackingSystemServerCpuTime() {
11475         mSystemServerCpuThreadReader.startTrackingThreadCpuTime();
11476     }
11477 
getSystemServiceCpuThreadTimes()11478     public SystemServiceCpuThreadTimes getSystemServiceCpuThreadTimes() {
11479         return mSystemServerCpuThreadReader.readAbsolute();
11480     }
11481 
setCallback(BatteryCallback cb)11482     public void setCallback(BatteryCallback cb) {
11483         mCallback = cb;
11484     }
11485 
setRadioScanningTimeoutLocked(long timeoutUs)11486     public void setRadioScanningTimeoutLocked(long timeoutUs) {
11487         if (mPhoneSignalScanningTimer != null) {
11488             mPhoneSignalScanningTimer.setTimeout(timeoutUs);
11489         }
11490     }
11491 
setExternalStatsSyncLocked(ExternalStatsSync sync)11492     public void setExternalStatsSyncLocked(ExternalStatsSync sync) {
11493         mExternalSync = sync;
11494     }
11495 
11496     /**
11497      * Initialize and set multi display timers and states.
11498      */
setDisplayCountLocked(int numDisplays)11499     public void setDisplayCountLocked(int numDisplays) {
11500         mPerDisplayBatteryStats = new DisplayBatteryStats[numDisplays];
11501         for (int i = 0; i < numDisplays; i++) {
11502             mPerDisplayBatteryStats[i] = new DisplayBatteryStats(mClock, mOnBatteryTimeBase);
11503         }
11504     }
11505 
updateDailyDeadlineLocked()11506     public void updateDailyDeadlineLocked() {
11507         // Get the current time.
11508         long currentTimeMs = mDailyStartTimeMs = mClock.currentTimeMillis();
11509         Calendar calDeadline = Calendar.getInstance();
11510         calDeadline.setTimeInMillis(currentTimeMs);
11511 
11512         // Move time up to the next day, ranging from 1am to 3pm.
11513         calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
11514         calDeadline.set(Calendar.MILLISECOND, 0);
11515         calDeadline.set(Calendar.SECOND, 0);
11516         calDeadline.set(Calendar.MINUTE, 0);
11517         calDeadline.set(Calendar.HOUR_OF_DAY, 1);
11518         mNextMinDailyDeadlineMs = calDeadline.getTimeInMillis();
11519         calDeadline.set(Calendar.HOUR_OF_DAY, 3);
11520         mNextMaxDailyDeadlineMs = calDeadline.getTimeInMillis();
11521     }
11522 
recordDailyStatsIfNeededLocked(boolean settled, long currentTimeMs)11523     public void recordDailyStatsIfNeededLocked(boolean settled, long currentTimeMs) {
11524         if (currentTimeMs >= mNextMaxDailyDeadlineMs) {
11525             recordDailyStatsLocked();
11526         } else if (settled && currentTimeMs >= mNextMinDailyDeadlineMs) {
11527             recordDailyStatsLocked();
11528         } else if (currentTimeMs < (mDailyStartTimeMs - (1000 * 60 * 60 * 24))) {
11529             recordDailyStatsLocked();
11530         }
11531     }
11532 
recordDailyStatsLocked()11533     public void recordDailyStatsLocked() {
11534         DailyItem item = new DailyItem();
11535         item.mStartTime = mDailyStartTimeMs;
11536         item.mEndTime = mClock.currentTimeMillis();
11537         boolean hasData = false;
11538         if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
11539             hasData = true;
11540             item.mDischargeSteps = new LevelStepTracker(
11541                     mDailyDischargeStepTracker.mNumStepDurations,
11542                     mDailyDischargeStepTracker.mStepDurations);
11543         }
11544         if (mDailyChargeStepTracker.mNumStepDurations > 0) {
11545             hasData = true;
11546             item.mChargeSteps = new LevelStepTracker(
11547                     mDailyChargeStepTracker.mNumStepDurations,
11548                     mDailyChargeStepTracker.mStepDurations);
11549         }
11550         if (mDailyPackageChanges != null) {
11551             hasData = true;
11552             item.mPackageChanges = mDailyPackageChanges;
11553             mDailyPackageChanges = null;
11554         }
11555         mDailyDischargeStepTracker.init();
11556         mDailyChargeStepTracker.init();
11557         updateDailyDeadlineLocked();
11558 
11559         if (hasData) {
11560             final long startTimeMs = SystemClock.uptimeMillis();
11561             mDailyItems.add(item);
11562             while (mDailyItems.size() > MAX_DAILY_ITEMS) {
11563                 mDailyItems.remove(0);
11564             }
11565             final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
11566             try {
11567                 TypedXmlSerializer out = Xml.resolveSerializer(memStream);
11568                 writeDailyItemsLocked(out);
11569                 final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs;
11570                 BackgroundThread.getHandler().post(new Runnable() {
11571                     @Override
11572                     public void run() {
11573                         synchronized (mCheckinFile) {
11574                             final long startTimeMs2 = SystemClock.uptimeMillis();
11575                             FileOutputStream stream = null;
11576                             try {
11577                                 stream = mDailyFile.startWrite();
11578                                 memStream.writeTo(stream);
11579                                 stream.flush();
11580                                 mDailyFile.finishWrite(stream);
11581                                 mFrameworkStatsLogger.writeCommitSysConfigFile("batterystats-daily",
11582                                         initialTimeMs + SystemClock.uptimeMillis() - startTimeMs2);
11583                             } catch (IOException e) {
11584                                 Slog.w("BatteryStats",
11585                                         "Error writing battery daily items", e);
11586                                 mDailyFile.failWrite(stream);
11587                             }
11588                         }
11589                     }
11590                 });
11591             } catch (IOException e) {
11592             }
11593         }
11594     }
11595 
writeDailyItemsLocked(TypedXmlSerializer out)11596     private void writeDailyItemsLocked(TypedXmlSerializer out) throws IOException {
11597         StringBuilder sb = new StringBuilder(64);
11598         out.startDocument(null, true);
11599         out.startTag(null, "daily-items");
11600         for (int i=0; i<mDailyItems.size(); i++) {
11601             final DailyItem dit = mDailyItems.get(i);
11602             out.startTag(null, "item");
11603             out.attributeLong(null, "start", dit.mStartTime);
11604             out.attributeLong(null, "end", dit.mEndTime);
11605             writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
11606             writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
11607             if (dit.mPackageChanges != null) {
11608                 for (int j=0; j<dit.mPackageChanges.size(); j++) {
11609                     PackageChange pc = dit.mPackageChanges.get(j);
11610                     if (pc.mUpdate) {
11611                         out.startTag(null, "upd");
11612                         out.attribute(null, "pkg", pc.mPackageName);
11613                         out.attributeLong(null, "ver", pc.mVersionCode);
11614                         out.endTag(null, "upd");
11615                     } else {
11616                         out.startTag(null, "rem");
11617                         out.attribute(null, "pkg", pc.mPackageName);
11618                         out.endTag(null, "rem");
11619                     }
11620                 }
11621             }
11622             out.endTag(null, "item");
11623         }
11624         out.endTag(null, "daily-items");
11625         out.endDocument();
11626     }
11627 
writeDailyLevelSteps(TypedXmlSerializer out, String tag, LevelStepTracker steps, StringBuilder tmpBuilder)11628     private void writeDailyLevelSteps(TypedXmlSerializer out, String tag, LevelStepTracker steps,
11629             StringBuilder tmpBuilder) throws IOException {
11630         if (steps != null) {
11631             out.startTag(null, tag);
11632             out.attributeInt(null, "n", steps.mNumStepDurations);
11633             for (int i=0; i<steps.mNumStepDurations; i++) {
11634                 out.startTag(null, "s");
11635                 tmpBuilder.setLength(0);
11636                 steps.encodeEntryAt(i, tmpBuilder);
11637                 out.attribute(null, "v", tmpBuilder.toString());
11638                 out.endTag(null, "s");
11639             }
11640             out.endTag(null, tag);
11641         }
11642     }
11643 
11644     @GuardedBy("this")
readDailyStatsLocked()11645     public void readDailyStatsLocked() {
11646         Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
11647         mDailyItems.clear();
11648         FileInputStream stream;
11649         try {
11650             stream = mDailyFile.openRead();
11651         } catch (FileNotFoundException e) {
11652             return;
11653         }
11654         try {
11655             TypedXmlPullParser parser = Xml.resolvePullParser(stream);
11656             readDailyItemsLocked(parser);
11657         } catch (IOException e) {
11658         } finally {
11659             try {
11660                 stream.close();
11661             } catch (IOException e) {
11662             }
11663         }
11664     }
11665 
readDailyItemsLocked(TypedXmlPullParser parser)11666     private void readDailyItemsLocked(TypedXmlPullParser parser) {
11667         try {
11668             int type;
11669             while ((type = parser.next()) != XmlPullParser.START_TAG
11670                     && type != XmlPullParser.END_DOCUMENT) {
11671                 ;
11672             }
11673 
11674             if (type != XmlPullParser.START_TAG) {
11675                 throw new IllegalStateException("no start tag found");
11676             }
11677 
11678             int outerDepth = parser.getDepth();
11679             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11680                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11681                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11682                     continue;
11683                 }
11684 
11685                 String tagName = parser.getName();
11686                 if (tagName.equals("item")) {
11687                     readDailyItemTagLocked(parser);
11688                 } else {
11689                     Slog.w(TAG, "Unknown element under <daily-items>: "
11690                             + parser.getName());
11691                     XmlUtils.skipCurrentTag(parser);
11692                 }
11693             }
11694 
11695         } catch (IllegalStateException e) {
11696             Slog.w(TAG, "Failed parsing daily " + e);
11697         } catch (NullPointerException e) {
11698             Slog.w(TAG, "Failed parsing daily " + e);
11699         } catch (NumberFormatException e) {
11700             Slog.w(TAG, "Failed parsing daily " + e);
11701         } catch (XmlPullParserException e) {
11702             Slog.w(TAG, "Failed parsing daily " + e);
11703         } catch (IOException e) {
11704             Slog.w(TAG, "Failed parsing daily " + e);
11705         } catch (IndexOutOfBoundsException e) {
11706             Slog.w(TAG, "Failed parsing daily " + e);
11707         }
11708     }
11709 
readDailyItemTagLocked(TypedXmlPullParser parser)11710     void readDailyItemTagLocked(TypedXmlPullParser parser) throws NumberFormatException,
11711             XmlPullParserException, IOException {
11712         DailyItem dit = new DailyItem();
11713         dit.mStartTime = parser.getAttributeLong(null, "start", 0);
11714         dit.mEndTime = parser.getAttributeLong(null, "end", 0);
11715         int outerDepth = parser.getDepth();
11716         int type;
11717         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11718                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11719             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11720                 continue;
11721             }
11722 
11723             String tagName = parser.getName();
11724             if (tagName.equals("dis")) {
11725                 readDailyItemTagDetailsLocked(parser, dit, false, "dis");
11726             } else if (tagName.equals("chg")) {
11727                 readDailyItemTagDetailsLocked(parser, dit, true, "chg");
11728             } else if (tagName.equals("upd")) {
11729                 if (dit.mPackageChanges == null) {
11730                     dit.mPackageChanges = new ArrayList<>();
11731                 }
11732                 PackageChange pc = new PackageChange();
11733                 pc.mUpdate = true;
11734                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
11735                 pc.mVersionCode = parser.getAttributeLong(null, "ver", 0);
11736                 dit.mPackageChanges.add(pc);
11737                 XmlUtils.skipCurrentTag(parser);
11738             } else if (tagName.equals("rem")) {
11739                 if (dit.mPackageChanges == null) {
11740                     dit.mPackageChanges = new ArrayList<>();
11741                 }
11742                 PackageChange pc = new PackageChange();
11743                 pc.mUpdate = false;
11744                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
11745                 dit.mPackageChanges.add(pc);
11746                 XmlUtils.skipCurrentTag(parser);
11747             } else {
11748                 Slog.w(TAG, "Unknown element under <item>: "
11749                         + parser.getName());
11750                 XmlUtils.skipCurrentTag(parser);
11751             }
11752         }
11753         mDailyItems.add(dit);
11754     }
11755 
readDailyItemTagDetailsLocked(TypedXmlPullParser parser, DailyItem dit, boolean isCharge, String tag)11756     void readDailyItemTagDetailsLocked(TypedXmlPullParser parser, DailyItem dit, boolean isCharge,
11757             String tag)
11758             throws NumberFormatException, XmlPullParserException, IOException {
11759         final int num = parser.getAttributeInt(null, "n", -1);
11760         if (num == -1) {
11761             Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
11762             XmlUtils.skipCurrentTag(parser);
11763             return;
11764         }
11765         LevelStepTracker steps = new LevelStepTracker(num);
11766         if (isCharge) {
11767             dit.mChargeSteps = steps;
11768         } else {
11769             dit.mDischargeSteps = steps;
11770         }
11771         int i = 0;
11772         int outerDepth = parser.getDepth();
11773         int type;
11774         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11775                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11776             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11777                 continue;
11778             }
11779 
11780             String tagName = parser.getName();
11781             if ("s".equals(tagName)) {
11782                 if (i < num) {
11783                     String valueAttr = parser.getAttributeValue(null, "v");
11784                     if (valueAttr != null) {
11785                         steps.decodeEntryAt(i, valueAttr);
11786                         i++;
11787                     }
11788                 }
11789             } else {
11790                 Slog.w(TAG, "Unknown element under <" + tag + ">: "
11791                         + parser.getName());
11792                 XmlUtils.skipCurrentTag(parser);
11793             }
11794         }
11795         steps.mNumStepDurations = i;
11796     }
11797 
11798     @Override
getDailyItemLocked(int daysAgo)11799     public DailyItem getDailyItemLocked(int daysAgo) {
11800         int index = mDailyItems.size()-1-daysAgo;
11801         return index >= 0 ? mDailyItems.get(index) : null;
11802     }
11803 
11804     @Override
getCurrentDailyStartTime()11805     public long getCurrentDailyStartTime() {
11806         return mDailyStartTimeMs;
11807     }
11808 
11809     @Override
getNextMinDailyDeadline()11810     public long getNextMinDailyDeadline() {
11811         return mNextMinDailyDeadlineMs;
11812     }
11813 
11814     @Override
getNextMaxDailyDeadline()11815     public long getNextMaxDailyDeadline() {
11816         return mNextMaxDailyDeadlineMs;
11817     }
11818 
11819     @GuardedBy("this")
getHistoryTotalSize()11820     public int getHistoryTotalSize() {
11821         return mConstants.MAX_HISTORY_BUFFER * mConstants.MAX_HISTORY_FILES;
11822     }
11823 
getHistoryUsedSize()11824     public int getHistoryUsedSize() {
11825         return mHistory.getHistoryUsedSize();
11826     }
11827 
11828     /**
11829      * Creates an iterator for battery stats history.
11830      */
11831     @Override
iterateBatteryStatsHistory(long startTimeMs, long endTimeMs)11832     public BatteryStatsHistoryIterator iterateBatteryStatsHistory(long startTimeMs,
11833             long endTimeMs) {
11834         return mHistory.iterate(startTimeMs, endTimeMs);
11835     }
11836 
11837     @Override
getHistoryStringPoolSize()11838     public int getHistoryStringPoolSize() {
11839         return mHistory.getHistoryStringPoolSize();
11840     }
11841 
11842     @Override
getHistoryStringPoolBytes()11843     public int getHistoryStringPoolBytes() {
11844         return mHistory.getHistoryStringPoolBytes();
11845     }
11846 
11847     @Override
getHistoryTagPoolString(int index)11848     public String getHistoryTagPoolString(int index) {
11849         return mHistory.getHistoryTagPoolString(index);
11850     }
11851 
11852     @Override
getHistoryTagPoolUid(int index)11853     public int getHistoryTagPoolUid(int index) {
11854         return mHistory.getHistoryTagPoolUid(index);
11855     }
11856 
11857     @Override
getStartCount()11858     public int getStartCount() {
11859         return mStartCount;
11860     }
11861 
isOnBattery()11862     public boolean isOnBattery() {
11863         return mOnBattery;
11864     }
11865 
isCharging()11866     public boolean isCharging() {
11867         return mCharging;
11868     }
11869 
initTimes(long uptimeUs, long realtimeUs)11870     void initTimes(long uptimeUs, long realtimeUs) {
11871         mStartClockTimeMs = mClock.currentTimeMillis();
11872         mOnBatteryTimeBase.init(uptimeUs, realtimeUs);
11873         mOnBatteryScreenOffTimeBase.init(uptimeUs, realtimeUs);
11874         mRealtimeUs = 0;
11875         mUptimeUs = 0;
11876         mRealtimeStartUs = realtimeUs;
11877         mUptimeStartUs = uptimeUs;
11878         mMonotonicStartTime = mMonotonicClock.monotonicTime();
11879     }
11880 
initDischarge(long elapsedRealtimeUs)11881     void initDischarge(long elapsedRealtimeUs) {
11882         mLowDischargeAmountSinceCharge = 0;
11883         mHighDischargeAmountSinceCharge = 0;
11884         mDischargeAmountScreenOn = 0;
11885         mDischargeAmountScreenOnSinceCharge = 0;
11886         mDischargeAmountScreenOff = 0;
11887         mDischargeAmountScreenOffSinceCharge = 0;
11888         mDischargeAmountScreenDoze = 0;
11889         mDischargeAmountScreenDozeSinceCharge = 0;
11890         mDischargeStepTracker.init();
11891         mChargeStepTracker.init();
11892         mDischargeScreenOffCounter.reset(false, elapsedRealtimeUs);
11893         mDischargeScreenDozeCounter.reset(false, elapsedRealtimeUs);
11894         mDischargeLightDozeCounter.reset(false, elapsedRealtimeUs);
11895         mDischargeDeepDozeCounter.reset(false, elapsedRealtimeUs);
11896         mDischargeCounter.reset(false, elapsedRealtimeUs);
11897     }
11898 
11899     /**
11900      * Associates the BatteryStatsImpl object with a BatteryUsageStatsProvider and PowerStatsStore
11901      * to allow for a snapshot of battery usage stats to be taken and stored just before battery
11902      * reset.
11903      */
saveBatteryUsageStatsOnReset( @onNull BatteryUsageStatsProvider batteryUsageStatsProvider, @NonNull PowerStatsStore powerStatsStore)11904     public void saveBatteryUsageStatsOnReset(
11905             @NonNull BatteryUsageStatsProvider batteryUsageStatsProvider,
11906             @NonNull PowerStatsStore powerStatsStore) {
11907         mSaveBatteryUsageStatsOnReset = true;
11908         mBatteryUsageStatsProvider = batteryUsageStatsProvider;
11909         mPowerStatsStore = powerStatsStore;
11910     }
11911 
11912     @GuardedBy("this")
resetAllStatsAndHistoryLocked(int reason)11913     public void resetAllStatsAndHistoryLocked(int reason) {
11914         final long mSecUptime = mClock.uptimeMillis();
11915         long uptimeUs = mSecUptime * 1000;
11916         long mSecRealtime = mClock.elapsedRealtime();
11917         long realtimeUs = mSecRealtime * 1000;
11918         resetAllStatsLocked(mSecUptime, mSecRealtime, reason);
11919         pullPendingStateUpdatesLocked();
11920         mHistory.writeHistoryItem(mSecRealtime, mSecUptime);
11921         mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel = mBatteryLevel;
11922         mOnBatteryTimeBase.reset(uptimeUs, realtimeUs);
11923         mOnBatteryScreenOffTimeBase.reset(uptimeUs, realtimeUs);
11924         if (!mBatteryPluggedIn) {
11925             if (Display.isOnState(mScreenState)) {
11926                 mDischargeScreenOnUnplugLevel = mBatteryLevel;
11927                 mDischargeScreenDozeUnplugLevel = 0;
11928                 mDischargeScreenOffUnplugLevel = 0;
11929             } else if (Display.isDozeState(mScreenState)) {
11930                 mDischargeScreenOnUnplugLevel = 0;
11931                 mDischargeScreenDozeUnplugLevel = mBatteryLevel;
11932                 mDischargeScreenOffUnplugLevel = 0;
11933             } else {
11934                 mDischargeScreenOnUnplugLevel = 0;
11935                 mDischargeScreenDozeUnplugLevel = 0;
11936                 mDischargeScreenOffUnplugLevel = mBatteryLevel;
11937             }
11938             mDischargeAmountScreenOn = 0;
11939             mDischargeAmountScreenOff = 0;
11940             mDischargeAmountScreenDoze = 0;
11941         }
11942         initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
11943     }
11944 
11945     @GuardedBy("this")
resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis, int resetReason)11946     private void resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis,
11947             int resetReason) {
11948         saveBatteryUsageStatsOnReset(resetReason);
11949 
11950         final long uptimeUs = uptimeMillis * 1000;
11951         final long elapsedRealtimeUs = elapsedRealtimeMillis * 1000;
11952         mStartCount = 0;
11953         initTimes(uptimeUs, elapsedRealtimeUs);
11954         mScreenOnTimer.reset(false, elapsedRealtimeUs);
11955         mScreenDozeTimer.reset(false, elapsedRealtimeUs);
11956         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11957             mScreenBrightnessTimer[i].reset(false, elapsedRealtimeUs);
11958         }
11959 
11960         final int numDisplays = mPerDisplayBatteryStats.length;
11961         for (int i = 0; i < numDisplays; i++) {
11962             mPerDisplayBatteryStats[i].reset(elapsedRealtimeUs);
11963         }
11964 
11965         if (mPowerProfile != null) {
11966             mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
11967         } else {
11968             mEstimatedBatteryCapacityMah = -1;
11969         }
11970         mLastLearnedBatteryCapacityUah = -1;
11971         mMinLearnedBatteryCapacityUah = -1;
11972         mMaxLearnedBatteryCapacityUah = -1;
11973         mInteractiveTimer.reset(false, elapsedRealtimeUs);
11974         mPowerSaveModeEnabledTimer.reset(false, elapsedRealtimeUs);
11975         mLastIdleTimeStartMs = elapsedRealtimeMillis;
11976         mLongestLightIdleTimeMs = 0;
11977         mLongestFullIdleTimeMs = 0;
11978         mDeviceIdleModeLightTimer.reset(false, elapsedRealtimeUs);
11979         mDeviceIdleModeFullTimer.reset(false, elapsedRealtimeUs);
11980         mDeviceLightIdlingTimer.reset(false, elapsedRealtimeUs);
11981         mDeviceIdlingTimer.reset(false, elapsedRealtimeUs);
11982         mPhoneOnTimer.reset(false, elapsedRealtimeUs);
11983         mAudioOnTimer.reset(false, elapsedRealtimeUs);
11984         mVideoOnTimer.reset(false, elapsedRealtimeUs);
11985         mFlashlightOnTimer.reset(false, elapsedRealtimeUs);
11986         mCameraOnTimer.reset(false, elapsedRealtimeUs);
11987         mBluetoothScanTimer.reset(false, elapsedRealtimeUs);
11988         for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
11989             mPhoneSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs);
11990         }
11991         mPhoneSignalScanningTimer.reset(false, elapsedRealtimeUs);
11992         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11993             mPhoneDataConnectionsTimer[i].reset(false, elapsedRealtimeUs);
11994         }
11995         mNrNsaTimer.reset(false, elapsedRealtimeUs);
11996         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11997             mNetworkByteActivityCounters[i].reset(false, elapsedRealtimeUs);
11998             mNetworkPacketActivityCounters[i].reset(false, elapsedRealtimeUs);
11999         }
12000         for (int i = 0; i < RADIO_ACCESS_TECHNOLOGY_COUNT; i++) {
12001             final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[i];
12002             if (stats == null) continue;
12003             stats.reset(elapsedRealtimeUs);
12004         }
12005         mMobileRadioActiveTimer.reset(false, elapsedRealtimeUs);
12006         mMobileRadioActivePerAppTimer.reset(false, elapsedRealtimeUs);
12007         mMobileRadioActiveAdjustedTime.reset(false, elapsedRealtimeUs);
12008         mMobileRadioActiveUnknownTime.reset(false, elapsedRealtimeUs);
12009         mMobileRadioActiveUnknownCount.reset(false, elapsedRealtimeUs);
12010         mWifiOnTimer.reset(false, elapsedRealtimeUs);
12011         mGlobalWifiRunningTimer.reset(false, elapsedRealtimeUs);
12012         for (int i=0; i<NUM_WIFI_STATES; i++) {
12013             mWifiStateTimer[i].reset(false, elapsedRealtimeUs);
12014         }
12015         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
12016             mWifiSupplStateTimer[i].reset(false, elapsedRealtimeUs);
12017         }
12018         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
12019             mWifiSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs);
12020         }
12021         mWifiMulticastWakelockTimer.reset(false, elapsedRealtimeUs);
12022         mWifiActiveTimer.reset(false, elapsedRealtimeUs);
12023         mWifiActivity.reset(false, elapsedRealtimeUs);
12024         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
12025             mGpsSignalQualityTimer[i].reset(false, elapsedRealtimeUs);
12026         }
12027         mBluetoothActivity.reset(false, elapsedRealtimeUs);
12028         mModemActivity.reset(false, elapsedRealtimeUs);
12029         mNumConnectivityChange = 0;
12030 
12031         for (int i=0; i<mUidStats.size(); i++) {
12032             if (mUidStats.valueAt(i).reset(uptimeUs, elapsedRealtimeUs, resetReason)) {
12033                 mUidStats.valueAt(i).detachFromTimeBase();
12034                 mUidStats.remove(mUidStats.keyAt(i));
12035                 i--;
12036             }
12037         }
12038 
12039         if (mRpmStats.size() > 0) {
12040             for (SamplingTimer timer : mRpmStats.values()) {
12041                 mOnBatteryTimeBase.remove(timer);
12042             }
12043             mRpmStats.clear();
12044         }
12045         if (mScreenOffRpmStats.size() > 0) {
12046             for (SamplingTimer timer : mScreenOffRpmStats.values()) {
12047                 mOnBatteryScreenOffTimeBase.remove(timer);
12048             }
12049             mScreenOffRpmStats.clear();
12050         }
12051 
12052         if (mKernelWakelockStats.size() > 0) {
12053             for (SamplingTimer timer : mKernelWakelockStats.values()) {
12054                 mOnBatteryScreenOffTimeBase.remove(timer);
12055             }
12056             mKernelWakelockStats.clear();
12057         }
12058 
12059         if (mKernelMemoryStats.size() > 0) {
12060             for (int i = 0; i < mKernelMemoryStats.size(); i++) {
12061                 mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i));
12062             }
12063             mKernelMemoryStats.clear();
12064         }
12065 
12066         if (mWakeupReasonStats.size() > 0) {
12067             for (SamplingTimer timer : mWakeupReasonStats.values()) {
12068                 mOnBatteryTimeBase.remove(timer);
12069             }
12070             mWakeupReasonStats.clear();
12071         }
12072 
12073         if (mTmpRailStats != null) {
12074             mTmpRailStats.reset();
12075         }
12076 
12077         EnergyConsumerStats.resetIfNotNull(mGlobalEnergyConsumerStats);
12078 
12079         if (!Flags.disableSystemServicePowerAttr()) {
12080             resetIfNotNull(mBinderThreadCpuTimesUs, false, elapsedRealtimeUs);
12081         }
12082 
12083         mNumAllUidCpuTimeReads = 0;
12084         mNumUidsRemoved = 0;
12085 
12086         initDischarge(elapsedRealtimeUs);
12087 
12088         mHistory.reset();
12089 
12090         // Store the empty state to disk to ensure consistency
12091         writeSyncLocked();
12092 
12093         if (mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
12094             schedulePowerStatsSampleCollection();
12095         }
12096 
12097         // Flush external data, gathering snapshots, but don't process it since it is pre-reset data
12098         mIgnoreNextExternalStats = true;
12099         mExternalSync.scheduleSync("reset", ExternalStatsSync.UPDATE_ON_RESET);
12100 
12101         mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
12102     }
12103 
saveBatteryUsageStatsOnReset(int resetReason)12104     private void saveBatteryUsageStatsOnReset(int resetReason) {
12105         if (!mSaveBatteryUsageStatsOnReset
12106                 || resetReason == BatteryStatsImpl.RESET_REASON_CORRUPT_FILE) {
12107             return;
12108         }
12109 
12110         final BatteryUsageStats batteryUsageStats;
12111         synchronized (this) {
12112             batteryUsageStats = mBatteryUsageStatsProvider.getBatteryUsageStats(this,
12113                     new BatteryUsageStatsQuery.Builder()
12114                             .setMaxStatsAgeMs(0)
12115                             .includePowerModels()
12116                             .includeProcessStateData()
12117                             .build());
12118         }
12119 
12120         // TODO(b/188068523): BatteryUsageStats should use monotonic time for start and end
12121         // Once that change is made, we will be able to use the BatteryUsageStats' monotonic
12122         // start time
12123         long monotonicStartTime =
12124                 mMonotonicClock.monotonicTime() - batteryUsageStats.getStatsDuration();
12125         mHandler.post(() -> {
12126             mPowerStatsStore.storeBatteryUsageStats(monotonicStartTime, batteryUsageStats);
12127             try {
12128                 batteryUsageStats.close();
12129             } catch (IOException e) {
12130                 Log.e(TAG, "Cannot close BatteryUsageStats", e);
12131             }
12132         });
12133     }
12134 
12135     @GuardedBy("this")
initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs)12136     private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
12137         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
12138             if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
12139                 // Not recording process starts/stops.
12140                 continue;
12141             }
12142             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
12143             if (active == null) {
12144                 continue;
12145             }
12146             for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
12147                 SparseIntArray uids = ent.getValue();
12148                 for (int j=0; j<uids.size(); j++) {
12149                     mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
12150                             uids.keyAt(j));
12151                 }
12152             }
12153         }
12154     }
12155 
12156     @GuardedBy("this")
updateDischargeScreenLevelsLocked(int oldState, int newState)12157     void updateDischargeScreenLevelsLocked(int oldState, int newState) {
12158         updateOldDischargeScreenLevelLocked(oldState);
12159         updateNewDischargeScreenLevelLocked(newState);
12160     }
12161 
12162     @GuardedBy("this")
updateOldDischargeScreenLevelLocked(int state)12163     private void updateOldDischargeScreenLevelLocked(int state) {
12164         if (Display.isOnState(state)) {
12165             int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
12166             if (diff > 0) {
12167                 mDischargeAmountScreenOn += diff;
12168                 mDischargeAmountScreenOnSinceCharge += diff;
12169             }
12170         } else if (Display.isDozeState(state)) {
12171             int diff = mDischargeScreenDozeUnplugLevel - mDischargeCurrentLevel;
12172             if (diff > 0) {
12173                 mDischargeAmountScreenDoze += diff;
12174                 mDischargeAmountScreenDozeSinceCharge += diff;
12175             }
12176         } else if (Display.isOffState(state)) {
12177             int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
12178             if (diff > 0) {
12179                 mDischargeAmountScreenOff += diff;
12180                 mDischargeAmountScreenOffSinceCharge += diff;
12181             }
12182         }
12183     }
12184 
12185     @GuardedBy("this")
updateNewDischargeScreenLevelLocked(int state)12186     private void updateNewDischargeScreenLevelLocked(int state) {
12187         if (Display.isOnState(state)) {
12188             mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
12189             mDischargeScreenOffUnplugLevel = 0;
12190             mDischargeScreenDozeUnplugLevel = 0;
12191         } else if (Display.isDozeState(state)) {
12192             mDischargeScreenOnUnplugLevel = 0;
12193             mDischargeScreenDozeUnplugLevel = mDischargeCurrentLevel;
12194             mDischargeScreenOffUnplugLevel = 0;
12195         } else if (Display.isOffState(state)) {
12196             mDischargeScreenOnUnplugLevel = 0;
12197             mDischargeScreenDozeUnplugLevel = 0;
12198             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
12199         }
12200     }
12201 
12202     @GuardedBy("this")
pullPendingStateUpdatesLocked()12203     public void pullPendingStateUpdatesLocked() {
12204         if (mOnBatteryInternal) {
12205             updateDischargeScreenLevelsLocked(mScreenState, mScreenState);
12206         }
12207     }
12208 
12209     private final Object mWifiNetworkLock = new Object();
12210 
12211     @GuardedBy("mWifiNetworkLock")
12212     private String[] mWifiIfaces = EmptyArray.STRING;
12213 
12214     @GuardedBy("mWifiNetworkLock")
12215     private NetworkStats mLastWifiNetworkStats;
12216 
12217     private final Object mModemNetworkLock = new Object();
12218 
12219     @GuardedBy("mModemNetworkLock")
12220     private String[] mModemIfaces = EmptyArray.STRING;
12221 
12222     @GuardedBy("mModemNetworkLock")
12223     private NetworkStats mLastModemNetworkStats;
12224 
12225     @VisibleForTesting
readMobileNetworkStatsLocked( @onNull NetworkStatsManager networkStatsManager)12226     protected NetworkStats readMobileNetworkStatsLocked(
12227             @NonNull NetworkStatsManager networkStatsManager) {
12228         return networkStatsManager.getMobileUidStats();
12229     }
12230 
12231     @VisibleForTesting
readWifiNetworkStatsLocked( @onNull NetworkStatsManager networkStatsManager)12232     protected NetworkStats readWifiNetworkStatsLocked(
12233             @NonNull NetworkStatsManager networkStatsManager) {
12234         return networkStatsManager.getWifiUidStats();
12235     }
12236 
12237     static class NetworkStatsDelta {
12238         int mUid;
12239         int mSet;
12240         long mRxBytes;
12241         long mRxPackets;
12242         long mTxBytes;
12243         long mTxPackets;
12244 
getUid()12245         public int getUid() {
12246             return mUid;
12247         }
12248 
12249 
getSet()12250         public int getSet() {
12251             return mSet;
12252         }
12253 
getRxBytes()12254         public long getRxBytes() {
12255             return mRxBytes;
12256         }
12257 
getRxPackets()12258         public long getRxPackets() {
12259             return mRxPackets;
12260         }
12261 
getTxBytes()12262         public long getTxBytes() {
12263             return mTxBytes;
12264         }
12265 
getTxPackets()12266         public long getTxPackets() {
12267             return mTxPackets;
12268         }
12269 
12270         @Override
toString()12271         public String toString() {
12272             return "NetworkStatsDelta{mUid=" + mUid + ", mSet=" + mSet + ", mRxBytes=" + mRxBytes
12273                     + ", mRxPackets=" + mRxPackets + ", mTxBytes=" + mTxBytes + ", mTxPackets="
12274                     + mTxPackets + '}';
12275         }
12276     }
12277 
computeDelta(NetworkStats currentStats, NetworkStats lastStats)12278     static List<NetworkStatsDelta> computeDelta(NetworkStats currentStats,
12279             NetworkStats lastStats) {
12280         List<NetworkStatsDelta> deltaList = new ArrayList<>();
12281         for (NetworkStats.Entry entry : currentStats) {
12282             NetworkStatsDelta delta = new NetworkStatsDelta();
12283             delta.mUid = entry.getUid();
12284             delta.mSet = entry.getSet();
12285             NetworkStats.Entry lastEntry = null;
12286             if (lastStats != null) {
12287                 for (NetworkStats.Entry e : lastStats) {
12288                     if (e.getUid() == entry.getUid() && e.getSet() == entry.getSet()
12289                             && e.getTag() == entry.getTag()
12290                             && e.getMetered() == entry.getMetered()
12291                             && e.getRoaming() == entry.getRoaming()
12292                             && e.getDefaultNetwork() == entry.getDefaultNetwork()
12293                             /*&& Objects.equals(e.getIface(), entry.getIface())*/) {
12294                         lastEntry = e;
12295                         break;
12296                     }
12297                 }
12298             }
12299             if (lastEntry != null) {
12300                 delta.mRxBytes = Math.max(0, entry.getRxBytes() - lastEntry.getRxBytes());
12301                 delta.mRxPackets = Math.max(0, entry.getRxPackets() - lastEntry.getRxPackets());
12302                 delta.mTxBytes = Math.max(0, entry.getTxBytes() - lastEntry.getTxBytes());
12303                 delta.mTxPackets = Math.max(0, entry.getTxPackets() - lastEntry.getTxPackets());
12304             } else {
12305                 delta.mRxBytes = entry.getRxBytes();
12306                 delta.mRxPackets = entry.getRxPackets();
12307                 delta.mTxBytes = entry.getTxBytes();
12308                 delta.mTxPackets = entry.getTxPackets();
12309             }
12310             deltaList.add(delta);
12311         }
12312 
12313         return deltaList;
12314     }
12315 
12316     /**
12317      * Distribute WiFi energy info and network traffic to apps.
12318      * @param info The energy information from the WiFi controller.
12319      */
12320     @GuardedBy("this")
updateWifiState(@ullable final WifiActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs, @NonNull NetworkStatsManager networkStatsManager)12321     public void updateWifiState(@Nullable final WifiActivityEnergyInfo info,
12322             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs,
12323             @NonNull NetworkStatsManager networkStatsManager) {
12324         if (mWifiPowerStatsCollector.isEnabled()) {
12325             return;
12326         }
12327 
12328         if (DEBUG_ENERGY) {
12329             synchronized (mWifiNetworkLock) {
12330                 Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
12331             }
12332         }
12333 
12334         // Grab a separate lock to acquire the network stats, which may do I/O.
12335         List<NetworkStatsDelta> delta;
12336         synchronized (mWifiNetworkLock) {
12337             final NetworkStats latestStats = readWifiNetworkStatsLocked(networkStatsManager);
12338             if (latestStats != null) {
12339                 delta = computeDelta(latestStats, mLastWifiNetworkStats);
12340                 mLastWifiNetworkStats = latestStats;
12341             } else {
12342                 delta = null;
12343             }
12344         }
12345 
12346         synchronized (this) {
12347             if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
12348                 if (mIgnoreNextExternalStats) {
12349                     // TODO: Strictly speaking, we should re-mark all 5 timers for each uid (and the
12350                     //  global one) here like we do for display. But I'm not sure it's worth the
12351                     //  complicated code for a codepath that shouldn't ever actually happen in real
12352                     //  life.
12353                 }
12354                 return;
12355             }
12356 
12357             final SparseDoubleArray uidEstimatedConsumptionMah =
12358                     (mGlobalEnergyConsumerStats != null
12359                             && mWifiPowerCalculator != null && consumedChargeUC > 0) ?
12360                             new SparseDoubleArray() : null;
12361             double totalEstimatedConsumptionMah = 0;
12362 
12363             SparseLongArray rxPackets = new SparseLongArray();
12364             SparseLongArray txPackets = new SparseLongArray();
12365             SparseLongArray rxTimesMs = new SparseLongArray();
12366             SparseLongArray txTimesMs = new SparseLongArray();
12367             long totalTxPackets = 0;
12368             long totalRxPackets = 0;
12369             if (delta != null) {
12370                 for (NetworkStatsDelta entry : delta) {
12371                     if (DEBUG_ENERGY) {
12372                         Slog.d(TAG, "Wifi uid " + entry.getUid()
12373                                 + ": delta rx=" + entry.getRxBytes()
12374                                 + " tx=" + entry.getTxBytes()
12375                                 + " rxPackets=" + entry.getRxPackets()
12376                                 + " txPackets=" + entry.getTxPackets());
12377                     }
12378 
12379                     if (entry.getRxBytes() == 0 && entry.getTxBytes() == 0) {
12380                         // Skip the lookup below since there is no work to do.
12381                         continue;
12382                     }
12383 
12384                     final int uid = mapUid(entry.getUid());
12385                     final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
12386                     if (entry.getRxBytes() != 0) {
12387                         u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.getRxBytes(),
12388                                 entry.getRxPackets());
12389                         if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
12390                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.getRxBytes(),
12391                                     entry.getRxPackets());
12392                         }
12393                         mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
12394                                 entry.getRxBytes());
12395                         mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
12396                                 entry.getRxPackets());
12397 
12398                         rxPackets.incrementValue(uid, entry.getRxPackets());
12399 
12400                         // Sum the total number of packets so that the Rx Power can
12401                         // be evenly distributed amongst the apps.
12402                         totalRxPackets += entry.getRxPackets();
12403                     }
12404 
12405                     if (entry.getTxBytes() != 0) {
12406                         u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.getTxBytes(),
12407                                 entry.getTxPackets());
12408                         if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
12409                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.getTxBytes(),
12410                                     entry.getTxPackets());
12411                         }
12412                         mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
12413                                 entry.getTxBytes());
12414                         mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
12415                                 entry.getTxPackets());
12416 
12417                         txPackets.incrementValue(uid, entry.getTxPackets());
12418 
12419                         // Sum the total number of packets so that the Tx Power can
12420                         // be evenly distributed amongst the apps.
12421                         totalTxPackets += entry.getTxPackets();
12422                     }
12423 
12424                     // Calculate consumed energy for this uid. Only do so if WifiReporting isn't
12425                     // enabled (if it is, we'll do it later instead using info).
12426                     if (uidEstimatedConsumptionMah != null && info == null && !mHasWifiReporting) {
12427                         final long uidRunningMs = u.mWifiRunningTimer
12428                                 .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12429                         if (uidRunningMs > 0) u.mWifiRunningTimer.setMark(elapsedRealtimeMs);
12430 
12431                         final long uidScanMs = u.mWifiScanTimer
12432                                 .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12433                         if (uidScanMs > 0) u.mWifiScanTimer.setMark(elapsedRealtimeMs);
12434 
12435                         long uidBatchScanMs = 0;
12436                         for (int bn = 0; bn < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bn++) {
12437                             if (u.mWifiBatchedScanTimer[bn] != null) {
12438                                 long bnMs = u.mWifiBatchedScanTimer[bn]
12439                                         .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12440                                 if (bnMs > 0) {
12441                                     u.mWifiBatchedScanTimer[bn].setMark(elapsedRealtimeMs);
12442                                 }
12443                                 uidBatchScanMs += bnMs;
12444                             }
12445                         }
12446 
12447                         uidEstimatedConsumptionMah.incrementValue(u.getUid(),
12448                                 mWifiPowerCalculator.calcPowerWithoutControllerDataMah(
12449                                         entry.getRxPackets(), entry.getTxPackets(),
12450                                         uidRunningMs, uidScanMs, uidBatchScanMs));
12451                     }
12452                 }
12453                 delta = null;
12454             }
12455 
12456             if (info != null) {
12457                 mHasWifiReporting = true;
12458 
12459                 // Measured in mAms
12460                 final long txTimeMs = info.getControllerTxDurationMillis();
12461                 final long rxTimeMs = info.getControllerRxDurationMillis();
12462                 final long scanTimeMs = info.getControllerScanDurationMillis();
12463                 final long idleTimeMs = info.getControllerIdleDurationMillis();
12464                 final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
12465 
12466                 long leftOverRxTimeMs = rxTimeMs;
12467                 long leftOverTxTimeMs = txTimeMs;
12468 
12469                 if (DEBUG_ENERGY) {
12470                     Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
12471                     Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
12472                     Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
12473                     Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
12474                     Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
12475                     Slog.d(TAG, "  Scan Time:  " + scanTimeMs + " ms");
12476                 }
12477 
12478                 long totalWifiLockTimeMs = 0;
12479                 long totalScanTimeMs = 0;
12480 
12481                 // On the first pass, collect some totals so that we can normalize power
12482                 // calculations if we need to.
12483                 final int uidStatsSize = mUidStats.size();
12484                 for (int i = 0; i < uidStatsSize; i++) {
12485                     final Uid uid = mUidStats.valueAt(i);
12486 
12487                     // Sum the total scan power for all apps.
12488                     totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
12489                             elapsedRealtimeMs * 1000) / 1000;
12490 
12491                     // Sum the total time holding wifi lock for all apps.
12492                     totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
12493                             elapsedRealtimeMs * 1000) / 1000;
12494                 }
12495 
12496                 if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
12497                     Slog.d(TAG,
12498                             "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
12499                                     + rxTimeMs + " ms). Normalizing scan time.");
12500                 }
12501                 if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
12502                     Slog.d(TAG,
12503                             "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
12504                                     + txTimeMs + " ms). Normalizing scan time.");
12505                 }
12506 
12507                 // Actually assign and distribute power usage to apps.
12508                 for (int i = 0; i < uidStatsSize; i++) {
12509                     final Uid uid = mUidStats.valueAt(i);
12510 
12511                     final long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
12512                             elapsedRealtimeMs * 1000) / 1000;
12513                     long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
12514                     long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
12515                     if (scanTimeSinceMarkMs > 0) {
12516                         // Set the new mark so that next time we get new data since this point.
12517                         uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
12518 
12519                         // Our total scan time is more than the reported Tx/Rx time.
12520                         // This is possible because the cost of a scan is approximate.
12521                         // Let's normalize the result so that we evenly blame each app
12522                         // scanning.
12523                         //
12524                         // This means that we may have apps that transmitted/received packets not be
12525                         // blamed for this, but this is fine as scans are relatively more expensive.
12526                         if (totalScanTimeMs > rxTimeMs) {
12527                             scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
12528                                     totalScanTimeMs;
12529                         }
12530                         if (totalScanTimeMs > txTimeMs) {
12531                             scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
12532                                     totalScanTimeMs;
12533                         }
12534 
12535                         if (DEBUG_ENERGY) {
12536                             Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
12537                                     + scanRxTimeSinceMarkMs + " ms  Tx:"
12538                                     + scanTxTimeSinceMarkMs + " ms)");
12539                         }
12540 
12541                         rxTimesMs.incrementValue(uid.getUid(), scanRxTimeSinceMarkMs);
12542                         txTimesMs.incrementValue(uid.getUid(), scanTxTimeSinceMarkMs);
12543 
12544                         leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
12545                         leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
12546                     }
12547 
12548                     // Distribute evenly the power consumed while Idle to each app holding a WiFi
12549                     // lock.
12550                     long myIdleTimeMs = 0;
12551                     final long wifiLockTimeSinceMarkMs =
12552                             uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
12553                                     elapsedRealtimeMs * 1000) / 1000;
12554                     if (wifiLockTimeSinceMarkMs > 0) {
12555                         // Set the new mark so that next time we get new data since this point.
12556                         uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
12557 
12558                         myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs) / totalWifiLockTimeMs;
12559                         if (DEBUG_ENERGY) {
12560                             Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
12561                                     + myIdleTimeMs + " ms");
12562                         }
12563                         uid.getOrCreateWifiControllerActivityLocked().getOrCreateIdleTimeCounter()
12564                                 .increment(myIdleTimeMs, elapsedRealtimeMs);
12565                     }
12566 
12567                     if (uidEstimatedConsumptionMah != null) {
12568                         double uidEstMah = mWifiPowerCalculator.calcPowerFromControllerDataMah(
12569                                 scanRxTimeSinceMarkMs, scanTxTimeSinceMarkMs, myIdleTimeMs);
12570                         uidEstimatedConsumptionMah.incrementValue(uid.getUid(), uidEstMah);
12571                     }
12572                 }
12573 
12574                 if (DEBUG_ENERGY) {
12575                     Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
12576                     Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
12577                 }
12578 
12579                 // Distribute the remaining Tx power appropriately between all apps that transmitted
12580                 // packets.
12581                 for (int i = 0; i < txPackets.size(); i++) {
12582                     final int uid = txPackets.keyAt(i);
12583                     final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
12584                             / totalTxPackets;
12585                     txTimesMs.incrementValue(uid, myTxTimeMs);
12586                 }
12587 
12588                 // Distribute the remaining Rx power appropriately between all apps that received
12589                 // packets.
12590                 for (int i = 0; i < rxPackets.size(); i++) {
12591                     final int uid = rxPackets.keyAt(i);
12592                     final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
12593                             / totalRxPackets;
12594                     rxTimesMs.incrementValue(uid, myRxTimeMs);
12595                 }
12596 
12597                 for (int i = 0; i < txTimesMs.size(); i++) {
12598                     final int uid = txTimesMs.keyAt(i);
12599                     final long myTxTimeMs = txTimesMs.valueAt(i);
12600                     if (DEBUG_ENERGY) {
12601                         Slog.d(TAG, "  TxTime for UID " + uid + ": " + myTxTimeMs + " ms");
12602                     }
12603                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
12604                             .getOrCreateWifiControllerActivityLocked()
12605                             .getOrCreateTxTimeCounters()[0]
12606                             .increment(myTxTimeMs, elapsedRealtimeMs);
12607                     if (uidEstimatedConsumptionMah != null) {
12608                         uidEstimatedConsumptionMah.incrementValue(uid,
12609                                 mWifiPowerCalculator.calcPowerFromControllerDataMah(
12610                                         0, myTxTimeMs, 0));
12611                     }
12612                 }
12613 
12614                 for (int i = 0; i < rxTimesMs.size(); i++) {
12615                     final int uid = rxTimesMs.keyAt(i);
12616                     final long myRxTimeMs = rxTimesMs.valueAt(i);
12617                     if (DEBUG_ENERGY) {
12618                         Slog.d(TAG, "  RxTime for UID " + uid + ": " + myRxTimeMs + " ms");
12619                     }
12620 
12621                     getUidStatsLocked(rxTimesMs.keyAt(i), elapsedRealtimeMs, uptimeMs)
12622                             .getOrCreateWifiControllerActivityLocked()
12623                             .getOrCreateRxTimeCounter()
12624                             .increment(myRxTimeMs, elapsedRealtimeMs);
12625                     if (uidEstimatedConsumptionMah != null) {
12626                         uidEstimatedConsumptionMah.incrementValue(uid,
12627                                 mWifiPowerCalculator.calcPowerFromControllerDataMah(
12628                                         myRxTimeMs, 0, 0));
12629                     }
12630                 }
12631 
12632                 // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
12633 
12634                 // Update WiFi controller stats.
12635                 mWifiActivity.getOrCreateRxTimeCounter().increment(
12636                         info.getControllerRxDurationMillis(), elapsedRealtimeMs);
12637                 mWifiActivity.getOrCreateTxTimeCounters()[0].increment(
12638                         info.getControllerTxDurationMillis(), elapsedRealtimeMs);
12639                 mWifiActivity.getScanTimeCounter().addCountLocked(
12640                         info.getControllerScanDurationMillis());
12641                 mWifiActivity.getOrCreateIdleTimeCounter().increment(
12642                         info.getControllerIdleDurationMillis(), elapsedRealtimeMs);
12643 
12644                 // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
12645                 final double opVolt = mPowerProfile.getAveragePower(
12646                         PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
12647                 double controllerMaMs = 0;
12648                 if (opVolt != 0) {
12649                     // We store the power drain as mAms.
12650                     controllerMaMs = info.getControllerEnergyUsedMicroJoules() / opVolt;
12651                     mWifiActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
12652                 }
12653                 // Converting uWs to mAms.
12654                 // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
12655                 long monitoredRailChargeConsumedMaMs = mTmpRailStats != null
12656                         ? (long) (mTmpRailStats.getWifiTotalEnergyUseduWs() / opVolt)
12657                         : 0L;
12658                 mWifiActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
12659                         monitoredRailChargeConsumedMaMs);
12660                 mHistory.recordWifiConsumedCharge(elapsedRealtimeMs, uptimeMs,
12661                         (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR));
12662                 if (mTmpRailStats != null) {
12663                     mTmpRailStats.resetWifiTotalEnergyUsed();
12664                 }
12665 
12666                 if (uidEstimatedConsumptionMah != null) {
12667                     totalEstimatedConsumptionMah = Math.max(controllerMaMs / MILLISECONDS_IN_HOUR,
12668                             mWifiPowerCalculator.calcPowerFromControllerDataMah(
12669                                     rxTimeMs, txTimeMs, idleTimeMs));
12670                 }
12671             }
12672 
12673             // Update the EnergyConsumerStats information.
12674             if (uidEstimatedConsumptionMah != null) {
12675                 mGlobalEnergyConsumerStats.updateStandardBucket(
12676                         EnergyConsumerStats.POWER_BUCKET_WIFI, consumedChargeUC);
12677 
12678                 // Now calculate the consumption for each uid, according to its proportional usage.
12679                 if (!mHasWifiReporting) {
12680                     final long globalTimeMs = mGlobalWifiRunningTimer
12681                             .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12682                     mGlobalWifiRunningTimer.setMark(elapsedRealtimeMs);
12683                     totalEstimatedConsumptionMah = mWifiPowerCalculator
12684                             .calcGlobalPowerWithoutControllerDataMah(globalTimeMs);
12685                 }
12686                 distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_WIFI,
12687                         consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedConsumptionMah,
12688                         elapsedRealtimeMs);
12689             }
12690         }
12691     }
12692 
12693     private ModemActivityInfo mLastModemActivityInfo = null;
12694 
12695     /**
12696      * Distribute Cell radio energy info and network traffic to apps.
12697      */
noteModemControllerActivity(@ullable final ModemActivityInfo activityInfo, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs, @NonNull NetworkStatsManager networkStatsManager)12698     public void noteModemControllerActivity(@Nullable final ModemActivityInfo activityInfo,
12699             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs,
12700             @NonNull NetworkStatsManager networkStatsManager) {
12701         if (DEBUG_ENERGY) {
12702             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
12703         }
12704         ModemActivityInfo deltaInfo = mLastModemActivityInfo == null
12705                 ? (activityInfo == null ? null : activityInfo.getDelta(activityInfo))
12706                 : mLastModemActivityInfo.getDelta(activityInfo);
12707         mLastModemActivityInfo = activityInfo;
12708 
12709         // Add modem tx power to history.
12710         addModemTxPowerToHistory(deltaInfo, elapsedRealtimeMs, uptimeMs);
12711 
12712         // Grab a separate lock to acquire the network stats, which may do I/O.
12713         List<NetworkStatsDelta> delta = null;
12714         synchronized (mModemNetworkLock) {
12715             final NetworkStats latestStats = readMobileNetworkStatsLocked(networkStatsManager);
12716             if (latestStats != null) {
12717                 delta = computeDelta(latestStats, mLastModemNetworkStats);
12718                 mLastModemNetworkStats = latestStats;
12719             }
12720         }
12721 
12722         synchronized (this) {
12723             final long totalRadioDurationMs =
12724                     mMobileRadioActiveTimer.getTimeSinceMarkLocked(
12725                             elapsedRealtimeMs * 1000) / 1000;
12726             mMobileRadioActiveTimer.setMark(elapsedRealtimeMs);
12727             final long phoneOnDurationMs = Math.min(totalRadioDurationMs,
12728                     mPhoneOnTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000);
12729             mPhoneOnTimer.setMark(elapsedRealtimeMs);
12730 
12731             if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
12732                 return;
12733             }
12734 
12735             final SparseDoubleArray uidEstimatedConsumptionMah;
12736             final long dataConsumedChargeUC;
12737             if (consumedChargeUC > 0 && isMobileRadioEnergyConsumerSupportedLocked()) {
12738                 final long phoneConsumedChargeUC;
12739                 if (totalRadioDurationMs == 0) {
12740                     phoneConsumedChargeUC = 0;
12741                 } else {
12742                     // Crudely attribute power consumption. Added (totalRadioDurationMs / 2) to the
12743                     // numerator for long rounding.
12744                     phoneConsumedChargeUC =
12745                             (consumedChargeUC * phoneOnDurationMs + totalRadioDurationMs / 2)
12746                                     / totalRadioDurationMs;
12747                 }
12748                 dataConsumedChargeUC = consumedChargeUC - phoneConsumedChargeUC;
12749 
12750                 mGlobalEnergyConsumerStats.updateStandardBucket(
12751                         EnergyConsumerStats.POWER_BUCKET_PHONE, phoneConsumedChargeUC);
12752                 mGlobalEnergyConsumerStats.updateStandardBucket(
12753                         EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO, dataConsumedChargeUC);
12754                 uidEstimatedConsumptionMah = new SparseDoubleArray();
12755             } else {
12756                 uidEstimatedConsumptionMah = null;
12757                 dataConsumedChargeUC = POWER_DATA_UNAVAILABLE;
12758             }
12759 
12760             RxTxConsumption rxTxConsumption = null;
12761             boolean attributeWithModemActivityInfo = false;
12762             if (deltaInfo != null) {
12763                 mHasModemReporting = true;
12764                 mModemActivity.getOrCreateIdleTimeCounter()
12765                         .increment(deltaInfo.getIdleTimeMillis(), elapsedRealtimeMs);
12766                 mModemActivity.getSleepTimeCounter().addCountLocked(
12767                         deltaInfo.getSleepTimeMillis());
12768                 mModemActivity.getOrCreateRxTimeCounter()
12769                         .increment(deltaInfo.getReceiveTimeMillis(), elapsedRealtimeMs);
12770                 for (int lvl = 0; lvl < MODEM_TX_POWER_LEVEL_COUNT; lvl++) {
12771                     mModemActivity.getOrCreateTxTimeCounters()[lvl]
12772                             .increment(deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl),
12773                                     elapsedRealtimeMs);
12774                 }
12775 
12776                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
12777                 final double opVolt = mPowerProfile.getAveragePower(
12778                     PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
12779                 if (opVolt != 0) {
12780                     double energyUsed =
12781                             deltaInfo.getSleepTimeMillis() *
12782                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
12783                             + deltaInfo.getIdleTimeMillis() *
12784                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
12785                             + deltaInfo.getReceiveTimeMillis() *
12786                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
12787                     for (int i = 0; i < Math.min(MODEM_TX_POWER_LEVEL_COUNT,
12788                             CELL_SIGNAL_STRENGTH_LEVEL_COUNT); i++) {
12789                         energyUsed += deltaInfo.getTransmitDurationMillisAtPowerLevel(i)
12790                                 * mPowerProfile.getAveragePower(
12791                                         PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
12792                     }
12793 
12794                     // We store the power drain as mAms.
12795                     mModemActivity.getPowerCounter().addCountLocked((long) energyUsed);
12796                     // Converting uWs to mAms.
12797                     // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
12798                     long monitoredRailChargeConsumedMaMs =
12799                             (long) (mTmpRailStats.getCellularTotalEnergyUseduWs() / opVolt);
12800                     mModemActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
12801                             monitoredRailChargeConsumedMaMs);
12802                     mHistory.recordWifiConsumedCharge(elapsedRealtimeMs, uptimeMs,
12803                             (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR));
12804                     mTmpRailStats.resetCellularTotalEnergyUsed();
12805                 }
12806 
12807                 rxTxConsumption = incrementPerRatDataLocked(deltaInfo, elapsedRealtimeMs);
12808 
12809                 attributeWithModemActivityInfo = mConstants.PER_UID_MODEM_MODEL
12810                         == PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX
12811                         && rxTxConsumption != null;
12812             }
12813             long totalAppRadioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
12814                     elapsedRealtimeMs * 1000);
12815             mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
12816 
12817             long totalRxPackets = 0;
12818             long totalTxPackets = 0;
12819             if (delta != null) {
12820                 for (NetworkStatsDelta entry : delta) {
12821                     if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
12822                         continue;
12823                     }
12824 
12825                     if (DEBUG_ENERGY) {
12826                         Slog.d(TAG, "Mobile uid " + entry.getUid() + ": delta rx="
12827                                 + entry.getRxBytes() + " tx=" + entry.getTxBytes()
12828                                 + " rxPackets=" + entry.getRxPackets()
12829                                 + " txPackets=" + entry.getTxPackets());
12830                     }
12831 
12832                     totalRxPackets += entry.getRxPackets();
12833                     totalTxPackets += entry.getTxPackets();
12834 
12835                     final Uid u = getUidStatsLocked(
12836                             mapUid(entry.getUid()), elapsedRealtimeMs, uptimeMs);
12837                     u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.getRxBytes(),
12838                             entry.getRxPackets());
12839                     u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.getTxBytes(),
12840                             entry.getTxPackets());
12841                     if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
12842                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
12843                                 entry.getRxBytes(), entry.getRxPackets());
12844                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
12845                                 entry.getTxBytes(), entry.getTxPackets());
12846                     }
12847 
12848                     mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
12849                             entry.getRxBytes());
12850                     mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
12851                             entry.getTxBytes());
12852                     mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
12853                             entry.getRxPackets());
12854                     mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
12855                             entry.getTxPackets());
12856                 }
12857 
12858                 // Now distribute proportional blame to the apps that did networking.
12859                 long totalPackets = totalRxPackets + totalTxPackets;
12860                 if (totalPackets > 0) {
12861                     for (NetworkStatsDelta entry : delta) {
12862                         if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
12863                             continue;
12864                         }
12865 
12866                         final Uid u = getUidStatsLocked(mapUid(entry.getUid()),
12867                                 elapsedRealtimeMs, uptimeMs);
12868 
12869                         // Distribute total radio active time in to this app.
12870                         final long appPackets = entry.getRxPackets() + entry.getTxPackets();
12871                         final long appRadioTimeUs =
12872                                 (totalAppRadioTimeUs * appPackets) / totalPackets;
12873                         u.noteMobileRadioActiveTimeLocked(appRadioTimeUs, elapsedRealtimeMs);
12874 
12875                         if (uidEstimatedConsumptionMah != null) {
12876                             final double uidConsumptionMah;
12877                             if (attributeWithModemActivityInfo) {
12878                                 // Distribute measured mobile radio charge consumption based on
12879                                 // rx/tx packets and estimated rx/tx charge consumption.
12880                                 uidConsumptionMah = smearModemActivityInfoRxTxConsumptionMah(
12881                                         rxTxConsumption, entry.getRxPackets(), entry.getTxPackets(),
12882                                         totalRxPackets, totalTxPackets);
12883                             } else {
12884                                 // Distribute mobile radio charge consumption based on app radio
12885                                 // active time
12886                                 uidConsumptionMah =
12887                                     mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
12888                                                 appRadioTimeUs / 1000);
12889                             }
12890                             uidEstimatedConsumptionMah.incrementValue(u.getUid(),
12891                                     uidConsumptionMah);
12892                         }
12893 
12894                         // Remove this app from the totals, so that we don't lose any time
12895                         // due to rounding.
12896                         totalAppRadioTimeUs -= appRadioTimeUs;
12897                         totalPackets -= appPackets;
12898 
12899                         if (deltaInfo != null) {
12900                             ControllerActivityCounterImpl activityCounter =
12901                                     u.getOrCreateModemControllerActivityLocked();
12902                             if (totalRxPackets > 0 && entry.getRxPackets() > 0) {
12903                                 final long rxMs = (entry.getRxPackets()
12904                                     * deltaInfo.getReceiveTimeMillis()) / totalRxPackets;
12905                                 activityCounter.getOrCreateRxTimeCounter()
12906                                         .increment(rxMs, elapsedRealtimeMs);
12907                             }
12908 
12909                             if (totalTxPackets > 0 && entry.getTxPackets() > 0) {
12910                                 for (int lvl = 0; lvl < MODEM_TX_POWER_LEVEL_COUNT;
12911                                         lvl++) {
12912                                     long txMs = entry.getTxPackets()
12913                                             * deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl);
12914                                     txMs /= totalTxPackets;
12915                                     activityCounter.getOrCreateTxTimeCounters()[lvl]
12916                                             .increment(txMs, elapsedRealtimeMs);
12917                                 }
12918                             }
12919                         }
12920                     }
12921                 }
12922 
12923                 if (totalAppRadioTimeUs > 0) {
12924                     // Whoops, there is some radio time we can't blame on an app!
12925                     mMobileRadioActiveUnknownTime.addCountLocked(totalAppRadioTimeUs);
12926                     mMobileRadioActiveUnknownCount.addCountLocked(1);
12927                 }
12928 
12929                 // Update the EnergyConsumerStats information.
12930                 if (uidEstimatedConsumptionMah != null) {
12931                     double totalEstimatedConsumptionMah = 0.0;
12932                     if (attributeWithModemActivityInfo) {
12933                         // Estimate inactive modem power consumption and combine with previously
12934                         // estimated active power consumption for an estimate of total modem
12935                         // power consumption.
12936                         final long sleepTimeMs = deltaInfo.getSleepTimeMillis();
12937                         final long idleTimeMs = deltaInfo.getIdleTimeMillis();
12938                         final double inactiveConsumptionMah =
12939                                 mMobileRadioPowerCalculator.calcInactiveStatePowerMah(sleepTimeMs,
12940                                         idleTimeMs);
12941                         totalEstimatedConsumptionMah += inactiveConsumptionMah;
12942                         totalEstimatedConsumptionMah += rxTxConsumption.rxConsumptionMah;
12943                         totalEstimatedConsumptionMah += rxTxConsumption.txConsumptionMah;
12944                     } else {
12945                         // Estimate total active radio power consumption since last mark.
12946                         totalEstimatedConsumptionMah +=
12947                                 mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
12948                                         totalRadioDurationMs);
12949 
12950                         // Estimate idle power consumption at each signal strength level
12951                         final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length;
12952                         for (int lvl = 0; lvl < numSignalStrengthLevels; lvl++) {
12953                             final long strengthLevelDurationMs =
12954                                     mPhoneSignalStrengthsTimer[lvl].getTimeSinceMarkLocked(
12955                                             elapsedRealtimeMs * 1000) / 1000;
12956                             mPhoneSignalStrengthsTimer[lvl].setMark(elapsedRealtimeMs);
12957 
12958                             totalEstimatedConsumptionMah +=
12959                                     mMobileRadioPowerCalculator.calcIdlePowerAtSignalStrengthMah(
12960                                             strengthLevelDurationMs, lvl);
12961                         }
12962 
12963                         // Estimate total active radio power consumption since last mark.
12964                         final long scanTimeMs = mPhoneSignalScanningTimer.getTimeSinceMarkLocked(
12965                                 elapsedRealtimeMs * 1000) / 1000;
12966                         mPhoneSignalScanningTimer.setMark(elapsedRealtimeMs);
12967                         totalEstimatedConsumptionMah +=
12968                                 mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs);
12969                     }
12970                     distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO,
12971                             dataConsumedChargeUC, uidEstimatedConsumptionMah,
12972                             totalEstimatedConsumptionMah, elapsedRealtimeMs);
12973                 }
12974             }
12975         }
12976     }
12977 
12978     private static class RxTxConsumption {
12979         public final double rxConsumptionMah;
12980         public final long rxDurationMs;
12981         public final double txConsumptionMah;
12982         public final long txDurationMs;
12983 
12984         /**
12985          * Represents the ratio between time spent transmitting and the total active time.
12986          */
12987         public final double txToTotalRatio;
12988 
RxTxConsumption(double rxMah, long rxMs, double txMah, long txMs)12989         RxTxConsumption(double rxMah, long rxMs, double txMah, long txMs) {
12990             rxConsumptionMah = rxMah;
12991             rxDurationMs = rxMs;
12992             txConsumptionMah = txMah;
12993             txDurationMs = txMs;
12994 
12995             final long activeDurationMs = txDurationMs + rxDurationMs;
12996             if (activeDurationMs == 0) {
12997                 txToTotalRatio = 0.0;
12998             } else {
12999                 txToTotalRatio = ((double) txDurationMs) / activeDurationMs;
13000             }
13001         }
13002     }
13003 
13004     @GuardedBy("this")
13005     @Nullable
incrementPerRatDataLocked(ModemActivityInfo deltaInfo, long elapsedRealtimeMs)13006     private RxTxConsumption incrementPerRatDataLocked(ModemActivityInfo deltaInfo,
13007             long elapsedRealtimeMs) {
13008         double rxConsumptionMah = 0.0;
13009         long rxDurationMs = 0;
13010         double txConsumptionMah = 0.0;
13011         long txDurationMs = 0;
13012 
13013         final int infoSize = deltaInfo.getSpecificInfoLength();
13014         if (infoSize == 1 && deltaInfo.getSpecificInfoRat(0)
13015                 == AccessNetworkConstants.AccessNetworkType.UNKNOWN
13016                 && deltaInfo.getSpecificInfoFrequencyRange(0)
13017                 == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
13018             // Specific info data unavailable. Proportionally smear Rx and Tx times across each RAT.
13019             final int levelCount = CELL_SIGNAL_STRENGTH_LEVEL_COUNT;
13020             long[] perSignalStrengthActiveTimeMs = new long[levelCount];
13021             long totalActiveTimeMs = 0;
13022 
13023             for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
13024                 final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
13025                 if (ratStats == null) continue;
13026 
13027                 final int freqCount = ratStats.getFrequencyRangeCount();
13028                 for (int freq = 0; freq < freqCount; freq++) {
13029                     for (int level = 0; level < levelCount; level++) {
13030                         final long durationMs = ratStats.getTimeSinceMark(freq, level,
13031                                 elapsedRealtimeMs);
13032                         perSignalStrengthActiveTimeMs[level] += durationMs;
13033                         totalActiveTimeMs += durationMs;
13034                     }
13035                 }
13036             }
13037             if (totalActiveTimeMs != 0) {
13038                 // Smear the provided Tx/Rx durations across each RAT, frequency, and signal
13039                 // strength.
13040                 for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
13041                     final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
13042                     if (ratStats == null) continue;
13043 
13044                     final int freqCount = ratStats.getFrequencyRangeCount();
13045                     for (int freq = 0; freq < freqCount; freq++) {
13046                         long frequencyDurationMs = 0;
13047                         for (int level = 0; level < levelCount; level++) {
13048                             final long durationMs = ratStats.getTimeSinceMark(freq, level,
13049                                     elapsedRealtimeMs);
13050                             final long totalLvlDurationMs =
13051                                     perSignalStrengthActiveTimeMs[level];
13052                             if (totalLvlDurationMs == 0) continue;
13053                             final long totalTxLvlDurations =
13054                                     deltaInfo.getTransmitDurationMillisAtPowerLevel(level);
13055                             // Smear HAL provided Tx power level duration based on active modem
13056                             // duration in a given state. (Add totalLvlDurationMs / 2 before
13057                             // the integer division with totalLvlDurationMs for rounding.)
13058                             final long proportionalTxDurationMs =
13059                                     (durationMs * totalTxLvlDurations
13060                                             + (totalLvlDurationMs / 2)) / totalLvlDurationMs;
13061                             ratStats.incrementTxDuration(freq, level, proportionalTxDurationMs);
13062                             frequencyDurationMs += durationMs;
13063 
13064                             if (isMobileRadioEnergyConsumerSupportedLocked()) {
13065                                 // Accumulate the power cost of time spent transmitting in a
13066                                 // particular state.
13067                                 final double txStatePowerConsumptionMah =
13068                                         mMobileRadioPowerCalculator.calcTxStatePowerMah(rat, freq,
13069                                                 level, proportionalTxDurationMs);
13070                                 txConsumptionMah += txStatePowerConsumptionMah;
13071                                 txDurationMs += proportionalTxDurationMs;
13072                             }
13073                         }
13074                         final long totalRxDuration = deltaInfo.getReceiveTimeMillis();
13075                         // Smear HAL provided Rx power duration based on active modem
13076                         // duration in a given state.  (Add totalActiveTimeMs / 2 before the
13077                         // integer division with totalActiveTimeMs for rounding.)
13078                         final long proportionalRxDurationMs =
13079                                 (frequencyDurationMs * totalRxDuration + (totalActiveTimeMs
13080                                         / 2)) / totalActiveTimeMs;
13081                         ratStats.incrementRxDuration(freq, proportionalRxDurationMs);
13082 
13083                         if (isMobileRadioEnergyConsumerSupportedLocked()) {
13084                             // Accumulate the power cost of time spent receiving in a particular
13085                             // state.
13086                             final double rxStatePowerConsumptionMah =
13087                                     mMobileRadioPowerCalculator.calcRxStatePowerMah(rat, freq,
13088                                             proportionalRxDurationMs);
13089                             rxConsumptionMah += rxStatePowerConsumptionMah;
13090                             rxDurationMs += proportionalRxDurationMs;
13091                         }
13092                     }
13093 
13094                 }
13095             }
13096         } else {
13097             // Specific data available.
13098             for (int index = 0; index < infoSize; index++) {
13099                 final int rat = deltaInfo.getSpecificInfoRat(index);
13100                 final int freq = deltaInfo.getSpecificInfoFrequencyRange(index);
13101 
13102                 // Map RadioAccessNetworkType to course grain RadioAccessTechnology.
13103                 final int ratBucket = mapRadioAccessNetworkTypeToRadioAccessTechnology(rat);
13104                 final RadioAccessTechnologyBatteryStats ratStats = getRatBatteryStatsLocked(
13105                         ratBucket);
13106 
13107                 final long rxTimeMs = deltaInfo.getReceiveTimeMillis(rat, freq);
13108                 final int[] txTimesMs = deltaInfo.getTransmitTimeMillis(rat, freq);
13109 
13110                 ratStats.incrementRxDuration(freq, rxTimeMs);
13111                 if (isMobileRadioEnergyConsumerSupportedLocked()) {
13112                     // Accumulate the power cost of time spent receiving in a particular state.
13113                     final double rxStatePowerConsumptionMah =
13114                             mMobileRadioPowerCalculator.calcRxStatePowerMah(ratBucket, freq,
13115                                     rxTimeMs);
13116                     rxConsumptionMah += rxStatePowerConsumptionMah;
13117                     rxDurationMs += rxTimeMs;
13118                 }
13119 
13120                 final int numTxLvl = txTimesMs.length;
13121                 for (int lvl = 0; lvl < numTxLvl; lvl++) {
13122                     final long txTimeMs = txTimesMs[lvl];
13123                     ratStats.incrementTxDuration(freq, lvl, txTimeMs);
13124                     if (isMobileRadioEnergyConsumerSupportedLocked()) {
13125                         // Accumulate the power cost of time spent transmitting in a particular
13126                         // state.
13127                         final double txStatePowerConsumptionMah =
13128                                 mMobileRadioPowerCalculator.calcTxStatePowerMah(ratBucket, freq,
13129                                         lvl, txTimeMs);
13130                         txConsumptionMah += txStatePowerConsumptionMah;
13131                         txDurationMs += txTimeMs;
13132                     }
13133                 }
13134             }
13135         }
13136 
13137         for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
13138             final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
13139             if (ratStats == null) continue;
13140             ratStats.setMark(elapsedRealtimeMs);
13141         }
13142 
13143         if (isMobileRadioEnergyConsumerSupportedLocked()) {
13144             return new RxTxConsumption(rxConsumptionMah, rxDurationMs, txConsumptionMah,
13145                     txDurationMs);
13146         } else {
13147             return null;
13148         }
13149     }
13150 
13151     /**
13152      * Smear modem Rx/Tx power consumption calculated from {@link ModemActivityInfo} using Rx/Tx
13153      * packets.
13154      *
13155      * @return the combine Rx/Tx smeared power consumption in milliamp-hours.
13156      */
smearModemActivityInfoRxTxConsumptionMah(RxTxConsumption rxTxConsumption, long rxPackets, long txPackets, long totalRxPackets, long totalTxPackets)13157     private double smearModemActivityInfoRxTxConsumptionMah(RxTxConsumption rxTxConsumption,
13158             long rxPackets, long txPackets, long totalRxPackets, long totalTxPackets) {
13159         // Distribute measured mobile radio charge consumption based on
13160         // rx/tx packets and estimated rx/tx charge consumption.
13161         double consumptionMah = 0.0;
13162         if (totalRxPackets != 0) {
13163             // Proportionally distribute receive battery consumption.
13164             consumptionMah += rxTxConsumption.rxConsumptionMah * rxPackets
13165                     / totalRxPackets;
13166         }
13167         if (totalTxPackets != 0 || (totalRxPackets != 0 && rxTxConsumption.txToTotalRatio != 0.0)) {
13168             // ModemActivityInfo Tx time represents time spent both transmitting and receiving.
13169             // There is currently no way to distinguish how many Rx packets were received during
13170             // Rx time vs Tx time.
13171             // Assumption: The number of packets received while transmitting is proportional
13172             // to the time spent transmitting over total active time.
13173             final double totalPacketsDuringTxTime =
13174                     totalTxPackets + rxTxConsumption.txToTotalRatio * totalRxPackets;
13175             final double packetsDuringTxTime =
13176                     txPackets + rxTxConsumption.txToTotalRatio * rxPackets;
13177             consumptionMah += rxTxConsumption.txConsumptionMah * packetsDuringTxTime
13178                     / totalPacketsDuringTxTime;
13179         }
13180         return consumptionMah;
13181     }
13182 
13183     /**
13184      * Add modem tx power to history
13185      * Device is said to be in high cellular transmit power when it has spent most of the transmit
13186      * time at the highest power level.
13187      * @param activityInfo
13188      */
addModemTxPowerToHistory(final ModemActivityInfo activityInfo, long elapsedRealtimeMs, long uptimeMs)13189     private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo,
13190             long elapsedRealtimeMs, long uptimeMs) {
13191         if (activityInfo == null) {
13192             return;
13193         }
13194         int levelMaxTimeSpent = 0;
13195         for (int i = 1; i < MODEM_TX_POWER_LEVEL_COUNT; i++) {
13196             if (activityInfo.getTransmitDurationMillisAtPowerLevel(i)
13197                     > activityInfo.getTransmitDurationMillisAtPowerLevel(levelMaxTimeSpent)) {
13198                 levelMaxTimeSpent = i;
13199             }
13200         }
13201         if (levelMaxTimeSpent == MODEM_TX_POWER_LEVEL_COUNT - 1) {
13202             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
13203                     HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG);
13204         }
13205     }
13206 
13207     private final class BluetoothActivityInfoCache {
13208         long idleTimeMs;
13209         long rxTimeMs;
13210         long txTimeMs;
13211         long energy;
13212 
13213         SparseLongArray uidRxBytes = new SparseLongArray();
13214         SparseLongArray uidTxBytes = new SparseLongArray();
13215 
set(BluetoothActivityEnergyInfo info)13216         void set(BluetoothActivityEnergyInfo info) {
13217             idleTimeMs = info.getControllerIdleTimeMillis();
13218             rxTimeMs = info.getControllerRxTimeMillis();
13219             txTimeMs = info.getControllerTxTimeMillis();
13220             energy = info.getControllerEnergyUsed();
13221             if (!info.getUidTraffic().isEmpty()) {
13222                 for (UidTraffic traffic : info.getUidTraffic()) {
13223                     uidRxBytes.put(traffic.getUid(), traffic.getRxBytes());
13224                     uidTxBytes.put(traffic.getUid(), traffic.getTxBytes());
13225                 }
13226             }
13227         }
13228 
reset()13229         void reset() {
13230             idleTimeMs = 0;
13231             rxTimeMs = 0;
13232             txTimeMs = 0;
13233             energy = 0;
13234             uidRxBytes.clear();
13235             uidTxBytes.clear();
13236         }
13237     }
13238 
13239     private final BluetoothActivityInfoCache mLastBluetoothActivityInfo
13240             = new BluetoothActivityInfoCache();
13241 
13242     /**
13243      * Distribute Bluetooth energy info and network traffic to apps.
13244      *
13245      * @param info The accumulated energy information from the bluetooth controller.
13246      */
13247     @GuardedBy("this")
updateBluetoothStateLocked(@ullable final BluetoothActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs)13248     public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info,
13249             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
13250         if (mBluetoothPowerStatsCollector.isEnabled()) {
13251             return;
13252         }
13253 
13254         if (DEBUG_ENERGY) {
13255             Slog.d(TAG, "Updating bluetooth stats: " + info);
13256         }
13257 
13258         if (info == null) {
13259             return;
13260         }
13261 
13262         if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
13263             mLastBluetoothActivityInfo.set(info);
13264             return;
13265         }
13266 
13267         mHasBluetoothReporting = true;
13268 
13269         if (info.getControllerRxTimeMillis() < mLastBluetoothActivityInfo.rxTimeMs
13270                 || info.getControllerTxTimeMillis() < mLastBluetoothActivityInfo.txTimeMs
13271                 || info.getControllerIdleTimeMillis() < mLastBluetoothActivityInfo.idleTimeMs
13272                 || info.getControllerEnergyUsed() < mLastBluetoothActivityInfo.energy) {
13273             // A drop in accumulated Bluetooth stats is a sign of a Bluetooth crash.
13274             // Reset the preserved previous snapshot in order to restart accumulating deltas.
13275             mLastBluetoothActivityInfo.reset();
13276         }
13277 
13278         final long rxTimeMs =
13279                 info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs;
13280         final long txTimeMs =
13281                 info.getControllerTxTimeMillis() - mLastBluetoothActivityInfo.txTimeMs;
13282         final long idleTimeMs =
13283                 info.getControllerIdleTimeMillis() - mLastBluetoothActivityInfo.idleTimeMs;
13284 
13285         if (DEBUG_ENERGY) {
13286             Slog.d(TAG, "------ BEGIN BLE power blaming ------");
13287             Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
13288             Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
13289             Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
13290         }
13291 
13292         final SparseDoubleArray uidEstimatedConsumptionMah =
13293                 (mGlobalEnergyConsumerStats != null
13294                         && mBluetoothPowerCalculator != null && consumedChargeUC > 0) ?
13295                         new SparseDoubleArray() : null;
13296         long totalScanTimeMs = 0;
13297 
13298         final int uidCount = mUidStats.size();
13299         for (int i = 0; i < uidCount; i++) {
13300             final Uid u = mUidStats.valueAt(i);
13301             if (u.mBluetoothScanTimer == null) {
13302                 continue;
13303             }
13304 
13305             totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
13306                     elapsedRealtimeMs * 1000) / 1000;
13307         }
13308 
13309         final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
13310         final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
13311 
13312         if (DEBUG_ENERGY) {
13313             Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
13314                     + " TX=" + normalizeScanTxTime);
13315         }
13316 
13317         long leftOverRxTimeMs = rxTimeMs;
13318         long leftOverTxTimeMs = txTimeMs;
13319 
13320         final SparseLongArray rxTimesMs = new SparseLongArray(uidCount);
13321         final SparseLongArray txTimesMs = new SparseLongArray(uidCount);
13322 
13323         for (int i = 0; i < uidCount; i++) {
13324             final Uid u = mUidStats.valueAt(i);
13325             if (u.mBluetoothScanTimer == null) {
13326                 continue;
13327             }
13328 
13329             long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
13330                     elapsedRealtimeMs * 1000) / 1000;
13331             if (scanTimeSinceMarkMs > 0) {
13332                 // Set the new mark so that next time we get new data since this point.
13333                 u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
13334 
13335                 long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
13336                 long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
13337 
13338                 if (normalizeScanRxTime) {
13339                     // Scan time is longer than the total rx time in the controller,
13340                     // so distribute the scan time proportionately. This means regular traffic
13341                     // will not blamed, but scans are more expensive anyways.
13342                     scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
13343                 }
13344 
13345                 if (normalizeScanTxTime) {
13346                     // Scan time is longer than the total tx time in the controller,
13347                     // so distribute the scan time proportionately. This means regular traffic
13348                     // will not blamed, but scans are more expensive anyways.
13349                     scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
13350                 }
13351 
13352                 rxTimesMs.incrementValue(u.getUid(), scanTimeRxSinceMarkMs);
13353                 txTimesMs.incrementValue(u.getUid(), scanTimeTxSinceMarkMs);
13354 
13355                 if (uidEstimatedConsumptionMah != null) {
13356                     uidEstimatedConsumptionMah.incrementValue(u.getUid(),
13357                             mBluetoothPowerCalculator.calculatePowerMah(
13358                                     scanTimeRxSinceMarkMs, scanTimeTxSinceMarkMs, 0));
13359                 }
13360 
13361                 leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
13362                 leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
13363             }
13364         }
13365 
13366         if (DEBUG_ENERGY) {
13367             Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX="
13368                     + leftOverTxTimeMs);
13369         }
13370 
13371         //
13372         // Now distribute blame to apps that did bluetooth traffic.
13373         //
13374 
13375         long totalTxBytes = 0;
13376         long totalRxBytes = 0;
13377 
13378         final List<UidTraffic> uidTraffic = info.getUidTraffic();
13379         final int numUids = uidTraffic.size();
13380         for (int i = 0; i < numUids; i++) {
13381             final UidTraffic traffic = uidTraffic.get(i);
13382             final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(
13383                     traffic.getUid());
13384             final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(
13385                     traffic.getUid());
13386 
13387             // Add to the global counters.
13388             mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(rxBytes);
13389             mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes);
13390 
13391             // Add to the UID counters.
13392             final Uid u = getUidStatsLocked(mapUid(traffic.getUid()), elapsedRealtimeMs, uptimeMs);
13393             u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0);
13394             u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0);
13395 
13396             // Calculate the total traffic.
13397             totalRxBytes += rxBytes;
13398             totalTxBytes += txBytes;
13399         }
13400 
13401         if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0
13402                 || leftOverTxTimeMs != 0)) {
13403             for (int i = 0; i < numUids; i++) {
13404                 final UidTraffic traffic = uidTraffic.get(i);
13405                 final int uid = traffic.getUid();
13406                 final long rxBytes =
13407                         traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid);
13408                 final long txBytes =
13409                         traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid);
13410 
13411                 final Uid u = getUidStatsLocked(mapUid(uid), elapsedRealtimeMs, uptimeMs);
13412                 final ControllerActivityCounterImpl counter =
13413                         u.getOrCreateBluetoothControllerActivityLocked();
13414 
13415                 if (totalRxBytes > 0 && rxBytes > 0) {
13416                     final long timeRxMs = (leftOverRxTimeMs * rxBytes) / totalRxBytes;
13417                     rxTimesMs.incrementValue(uid, timeRxMs);
13418                 }
13419 
13420                 if (totalTxBytes > 0 && txBytes > 0) {
13421                     final long timeTxMs = (leftOverTxTimeMs * txBytes) / totalTxBytes;
13422                     txTimesMs.incrementValue(uid, timeTxMs);
13423                 }
13424             }
13425 
13426             for (int i = 0; i < txTimesMs.size(); i++) {
13427                 final int uid = txTimesMs.keyAt(i);
13428                 final long myTxTimeMs = txTimesMs.valueAt(i);
13429                 if (DEBUG_ENERGY) {
13430                     Slog.d(TAG, "  TxTime for UID " + uid + ": " + myTxTimeMs + " ms");
13431                 }
13432                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
13433                         .getOrCreateBluetoothControllerActivityLocked()
13434                         .getOrCreateTxTimeCounters()[0]
13435                         .increment(myTxTimeMs, elapsedRealtimeMs);
13436                 if (uidEstimatedConsumptionMah != null) {
13437                     uidEstimatedConsumptionMah.incrementValue(uid,
13438                             mBluetoothPowerCalculator.calculatePowerMah(0, myTxTimeMs, 0));
13439                 }
13440             }
13441 
13442             for (int i = 0; i < rxTimesMs.size(); i++) {
13443                 final int uid = rxTimesMs.keyAt(i);
13444                 final long myRxTimeMs = rxTimesMs.valueAt(i);
13445                 if (DEBUG_ENERGY) {
13446                     Slog.d(TAG, "  RxTime for UID " + uid + ": " + myRxTimeMs + " ms");
13447                 }
13448 
13449                 getUidStatsLocked(rxTimesMs.keyAt(i), elapsedRealtimeMs, uptimeMs)
13450                         .getOrCreateBluetoothControllerActivityLocked()
13451                         .getOrCreateRxTimeCounter()
13452                         .increment(myRxTimeMs, elapsedRealtimeMs);
13453                 if (uidEstimatedConsumptionMah != null) {
13454                     uidEstimatedConsumptionMah.incrementValue(uid,
13455                             mBluetoothPowerCalculator.calculatePowerMah(myRxTimeMs, 0, 0));
13456                 }
13457             }
13458         }
13459 
13460         mBluetoothActivity.getOrCreateRxTimeCounter().increment(rxTimeMs, elapsedRealtimeMs);
13461         mBluetoothActivity.getOrCreateTxTimeCounters()[0].increment(txTimeMs, elapsedRealtimeMs);
13462         mBluetoothActivity.getOrCreateIdleTimeCounter().increment(idleTimeMs, elapsedRealtimeMs);
13463 
13464         // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
13465         final double opVolt = mPowerProfile.getAveragePower(
13466                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
13467         double controllerMaMs = 0;
13468         if (opVolt != 0) {
13469             controllerMaMs = (info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
13470                     / opVolt;
13471             // We store the power drain as mAms.
13472             mBluetoothActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
13473         }
13474 
13475         // Update the EnergyConsumerStats information.
13476         if (uidEstimatedConsumptionMah != null) {
13477             mGlobalEnergyConsumerStats.updateStandardBucket(
13478                     EnergyConsumerStats.POWER_BUCKET_BLUETOOTH, consumedChargeUC);
13479 
13480             double totalEstimatedMah
13481                     = mBluetoothPowerCalculator.calculatePowerMah(rxTimeMs, txTimeMs, idleTimeMs);
13482             totalEstimatedMah = Math.max(totalEstimatedMah, controllerMaMs / MILLISECONDS_IN_HOUR);
13483             distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_BLUETOOTH,
13484                     consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedMah,
13485                     elapsedRealtimeMs);
13486         }
13487 
13488         mLastBluetoothActivityInfo.set(info);
13489     }
13490     /**
13491      * Read Resource Power Manager (RPM) state and voter times.
13492      * If RPM stats were fetched more recently than RPM_STATS_UPDATE_FREQ_MS ago, uses the old data
13493      * instead of fetching it anew.
13494      *
13495      * Note: This should be called without synchronizing this BatteryStatsImpl object
13496      */
fillLowPowerStats()13497     public void fillLowPowerStats() {
13498         if (mPlatformIdleStateCallback == null) return;
13499 
13500         RpmStats rpmStats = new RpmStats();
13501         long now = SystemClock.elapsedRealtime();
13502         if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
13503             mPlatformIdleStateCallback.fillLowPowerStats(rpmStats);
13504             synchronized (this) {
13505                 mTmpRpmStats = rpmStats;
13506                 mLastRpmStatsUpdateTimeMs = now;
13507             }
13508         }
13509     }
13510 
13511     /**
13512      * Record Resource Power Manager (RPM) state and voter times.
13513      * TODO(b/185252376): Remove this logging. PowerStatsService logs the same data more
13514      * efficiently.
13515      */
updateRpmStatsLocked(long elapsedRealtimeUs)13516     public void updateRpmStatsLocked(long elapsedRealtimeUs) {
13517         if (mTmpRpmStats == null) return;
13518 
13519         for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate
13520                 : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) {
13521 
13522             // Update values for this platform state.
13523             final String pName = pstate.getKey();
13524             final long pTimeUs = pstate.getValue().mTimeMs * 1000;
13525             final int pCount = pstate.getValue().mCount;
13526             getRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs);
13527             if (SCREEN_OFF_RPM_STATS_ENABLED) {
13528                 getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs);
13529             }
13530 
13531             // Update values for each voter of this platform state.
13532             for (Map.Entry<String, RpmStats.PowerStateElement> voter
13533                     : pstate.getValue().mVoters.entrySet()) {
13534                 final String vName = pName + "." + voter.getKey();
13535                 final long vTimeUs = voter.getValue().mTimeMs * 1000;
13536                 final int vCount = voter.getValue().mCount;
13537                 getRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs);
13538                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
13539                     getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs);
13540                 }
13541             }
13542         }
13543 
13544         for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys
13545                 : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) {
13546 
13547             final String subsysName = subsys.getKey();
13548             for (Map.Entry<String, RpmStats.PowerStateElement> sstate
13549                     : subsys.getValue().mStates.entrySet()) {
13550                 final String name = subsysName + "." + sstate.getKey();
13551                 final long timeUs = sstate.getValue().mTimeMs * 1000;
13552                 final int count = sstate.getValue().mCount;
13553                 getRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs);
13554                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
13555                     getScreenOffRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs);
13556                 }
13557             }
13558         }
13559     }
13560 
13561     /**
13562      * Accumulate Cpu charge consumption and distribute it to the correct state and the apps.
13563      * Only call if device is on battery.
13564      *
13565      * @param clusterChargeUC amount of charge (microcoulombs) consumed by each Cpu Cluster
13566      * @param accumulator collection of calculated uid cpu power consumption to smear
13567      *                    clusterChargeUC against.
13568      */
13569     @GuardedBy("this")
13570     @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToStandardBucketLocked
updateCpuEnergyConsumerStatsLocked(@onNull long[] clusterChargeUC, @NonNull CpuDeltaPowerAccumulator accumulator)13571     private void updateCpuEnergyConsumerStatsLocked(@NonNull long[] clusterChargeUC,
13572             @NonNull CpuDeltaPowerAccumulator accumulator) {
13573         if (DEBUG_ENERGY) {
13574             Slog.d(TAG, "Updating cpu cluster stats: " + Arrays.toString(clusterChargeUC));
13575         }
13576         if (mGlobalEnergyConsumerStats == null) {
13577             return;
13578         }
13579 
13580         final int numClusters = clusterChargeUC.length;
13581         long totalCpuChargeUC = 0;
13582         for (int i = 0; i < numClusters; i++) {
13583             totalCpuChargeUC += clusterChargeUC[i];
13584         }
13585         if (totalCpuChargeUC <= 0) return;
13586 
13587         final long timestampMs = mClock.elapsedRealtime();
13588 
13589         mGlobalEnergyConsumerStats.updateStandardBucket(EnergyConsumerStats.POWER_BUCKET_CPU,
13590                 totalCpuChargeUC, timestampMs);
13591 
13592         // Calculate the microcoulombs/milliamp-hour charge ratio for each
13593         // cluster to normalize  each uid's estimated power usage against actual power usage for
13594         // a given cluster.
13595         final double[] clusterChargeRatio = new double[numClusters];
13596         for (int cluster = 0; cluster < numClusters; cluster++) {
13597 
13598             final double totalClusterChargeMah = accumulator.totalClusterChargesMah[cluster];
13599             if (totalClusterChargeMah <= 0.0) {
13600                 // This cluster did not have any work on it, since last update.
13601                 // Avoid dividing by zero.
13602                 clusterChargeRatio[cluster] = 0.0;
13603             } else {
13604                 clusterChargeRatio[cluster] =
13605                         clusterChargeUC[cluster] / accumulator.totalClusterChargesMah[cluster];
13606             }
13607         }
13608 
13609         // Assign and distribute power usage to apps based on their calculated cpu cluster charge.
13610         final long uidChargeArraySize = accumulator.perUidCpuClusterChargesMah.size();
13611         for (int i = 0; i < uidChargeArraySize; i++) {
13612             final Uid uid = accumulator.perUidCpuClusterChargesMah.keyAt(i);
13613             final double[] uidClusterChargesMah = accumulator.perUidCpuClusterChargesMah.valueAt(i);
13614 
13615             // Iterate each cpu cluster and sum the proportional cpu cluster charge to
13616             // get the total cpu charge consumed by a uid.
13617             long uidCpuChargeUC = 0;
13618             for (int cluster = 0; cluster < numClusters; cluster++) {
13619                 final double uidClusterChargeMah = uidClusterChargesMah[cluster];
13620 
13621                 // Proportionally allocate the cpu cluster charge to a uid using the
13622                 // cluster charge/charge ratio. Add 0.5 to round the proportional
13623                 // charge double to the nearest long value.
13624                 final long uidClusterChargeUC =
13625                         (long) (uidClusterChargeMah * clusterChargeRatio[cluster]
13626                                 + 0.5);
13627 
13628                 uidCpuChargeUC += uidClusterChargeUC;
13629             }
13630 
13631             if (uidCpuChargeUC < 0) {
13632                 Slog.wtf(TAG, "Unexpected proportional EnergyConsumer charge "
13633                         + "(" + uidCpuChargeUC + ") for uid " + uid.mUid);
13634                 continue;
13635             }
13636 
13637             uid.addChargeToStandardBucketLocked(uidCpuChargeUC,
13638                     EnergyConsumerStats.POWER_BUCKET_CPU, timestampMs);
13639         }
13640     }
13641 
13642     /**
13643      * Accumulate Display charge consumption and distribute it to the correct state and the apps.
13644      *
13645      * NOTE: The algorithm used makes the strong assumption that app foreground activity time
13646      * is always 0 when the screen is not "ON" and whenever the rail energy is 0 (if supported).
13647      * To the extent that those assumptions are violated, the algorithm will err.
13648      *
13649      * @param chargesUC amount of charge (microcoulombs) used by each Display since this was last
13650      *                 called.
13651      * @param screenStates each screen state at the time this data collection was scheduled
13652      */
13653     @GuardedBy("this")
updateDisplayEnergyConsumerStatsLocked(long[] chargesUC, int[] screenStates, long elapsedRealtimeMs)13654     public void updateDisplayEnergyConsumerStatsLocked(long[] chargesUC, int[] screenStates,
13655             long elapsedRealtimeMs) {
13656         if (DEBUG_ENERGY) Slog.d(TAG, "Updating display stats: " + Arrays.toString(chargesUC));
13657         if (mGlobalEnergyConsumerStats == null) {
13658             return;
13659         }
13660 
13661         final int numDisplays;
13662         if (mPerDisplayBatteryStats.length == screenStates.length) {
13663             numDisplays = screenStates.length;
13664         } else {
13665             // if this point is reached, it will be reached every display state change.
13666             // Rate limit the wtf logging to once every 100 display updates.
13667             if (mDisplayMismatchWtfCount++ % 100 == 0) {
13668                 Slog.wtf(TAG, "Mismatch between PowerProfile reported display count ("
13669                         + mPerDisplayBatteryStats.length
13670                         + ") and PowerStatsHal reported display count (" + screenStates.length
13671                         + ")");
13672             }
13673             // Keep the show going, use the shorter of the two.
13674             numDisplays = mPerDisplayBatteryStats.length < screenStates.length
13675                     ? mPerDisplayBatteryStats.length : screenStates.length;
13676         }
13677 
13678         final int[] oldScreenStates = new int[numDisplays];
13679         for (int i = 0; i < numDisplays; i++) {
13680             final int screenState = screenStates[i];
13681             oldScreenStates[i] = mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement;
13682             mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState;
13683         }
13684 
13685         if (!mOnBatteryInternal) {
13686             // There's nothing further to update.
13687             return;
13688         }
13689         if (mIgnoreNextExternalStats) {
13690             // Although under ordinary resets we won't get here, and typically a new sync will
13691             // happen right after the reset, strictly speaking we need to set all mark times to now.
13692             final int uidStatsSize = mUidStats.size();
13693             for (int i = 0; i < uidStatsSize; i++) {
13694                 final Uid uid = mUidStats.valueAt(i);
13695                 uid.markProcessForegroundTimeUs(elapsedRealtimeMs, false);
13696             }
13697             return;
13698         }
13699 
13700         long totalScreenOnChargeUC = 0;
13701         for (int i = 0; i < numDisplays; i++) {
13702             final long chargeUC = chargesUC[i];
13703             if (chargeUC <= 0) {
13704                 // There's nothing further to update.
13705                 continue;
13706             }
13707 
13708             final @StandardPowerBucket int powerBucket =
13709                     EnergyConsumerStats.getDisplayPowerBucket(oldScreenStates[i]);
13710             mGlobalEnergyConsumerStats.updateStandardBucket(powerBucket, chargeUC);
13711             if (powerBucket == EnergyConsumerStats.POWER_BUCKET_SCREEN_ON) {
13712                 totalScreenOnChargeUC += chargeUC;
13713             }
13714         }
13715 
13716         // Now we blame individual apps, but only if the display was ON.
13717         if (totalScreenOnChargeUC <= 0) {
13718             return;
13719         }
13720         // TODO(b/175726779): Consider unifying the code with the non-rail display power blaming.
13721 
13722         // NOTE: fg time is NOT pooled. If two uids are both somehow in fg, then that time is
13723         // 'double counted' and will simply exceed the realtime that elapsed.
13724         // TODO(b/175726779): collect per display uid visibility for display power attribution.
13725 
13726         // Collect total time since mark so that we can normalize power.
13727         final SparseDoubleArray fgTimeUsArray = new SparseDoubleArray();
13728         final long elapsedRealtimeUs = elapsedRealtimeMs * 1000;
13729         // TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
13730         final int uidStatsSize = mUidStats.size();
13731         for (int i = 0; i < uidStatsSize; i++) {
13732             final Uid uid = mUidStats.valueAt(i);
13733             final long fgTimeUs = uid.markProcessForegroundTimeUs(elapsedRealtimeMs, true);
13734             if (fgTimeUs == 0) continue;
13735             fgTimeUsArray.put(uid.getUid(), (double) fgTimeUs);
13736         }
13737         distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_SCREEN_ON,
13738                 totalScreenOnChargeUC, fgTimeUsArray, 0, elapsedRealtimeMs);
13739     }
13740 
13741     /**
13742      * Accumulate GNSS charge consumption and distribute it to the correct state and the apps.
13743      *
13744      * @param chargeUC amount of charge (microcoulombs) used by GNSS since this was last called.
13745      */
13746     @GuardedBy("this")
13747     public void updateGnssEnergyConsumerStatsLocked(long chargeUC, long elapsedRealtimeMs) {
13748         if (DEBUG_ENERGY) Slog.d(TAG, "Updating gnss stats: " + chargeUC);
13749         if (mGlobalEnergyConsumerStats == null) {
13750             return;
13751         }
13752 
13753         if (!mOnBatteryInternal || chargeUC <= 0) {
13754             // There's nothing further to update.
13755             return;
13756         }
13757         if (mIgnoreNextExternalStats) {
13758             // Although under ordinary resets we won't get here, and typically a new sync will
13759             // happen right after the reset, strictly speaking we need to set all mark times to now.
13760             final int uidStatsSize = mUidStats.size();
13761             for (int i = 0; i < uidStatsSize; i++) {
13762                 final Uid uid = mUidStats.valueAt(i);
13763                 uid.markGnssTimeUs(elapsedRealtimeMs);
13764             }
13765             return;
13766         }
13767 
13768         mGlobalEnergyConsumerStats.updateStandardBucket(EnergyConsumerStats.POWER_BUCKET_GNSS,
13769                 chargeUC);
13770 
13771         // Collect the per uid time since mark so that we can normalize power.
13772         final SparseDoubleArray gnssTimeUsArray = new SparseDoubleArray();
13773         // TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
13774         final int uidStatsSize = mUidStats.size();
13775         for (int i = 0; i < uidStatsSize; i++) {
13776             final Uid uid = mUidStats.valueAt(i);
13777             final long gnssTimeUs = uid.markGnssTimeUs(elapsedRealtimeMs);
13778             if (gnssTimeUs == 0) continue;
13779             gnssTimeUsArray.put(uid.getUid(), (double) gnssTimeUs);
13780         }
13781         distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_GNSS, chargeUC,
13782                 gnssTimeUsArray, 0, elapsedRealtimeMs);
13783     }
13784 
13785     /**
13786      * Accumulate camera charge consumption and distribute it to the correct state and the apps.
13787      *
13788      * @param chargeUC amount of charge (microcoulombs) used by the camera since this was last
13789      *         called.
13790      */
13791     @GuardedBy("this")
13792     public void updateCameraEnergyConsumerStatsLocked(long chargeUC, long elapsedRealtimeMs) {
13793         if (DEBUG_ENERGY) Slog.d(TAG, "Updating camera stats: " + chargeUC);
13794         if (mGlobalEnergyConsumerStats == null) {
13795             return;
13796         }
13797 
13798         if (!mOnBatteryInternal || chargeUC <= 0) {
13799             // There's nothing further to update.
13800             return;
13801         }
13802 
13803         if (mIgnoreNextExternalStats) {
13804             // Although under ordinary resets we won't get here, and typically a new sync will
13805             // happen right after the reset, strictly speaking we need to set all mark times to now.
13806             final int uidStatsSize = mUidStats.size();
13807             for (int i = 0; i < uidStatsSize; i++) {
13808                 final Uid uid = mUidStats.valueAt(i);
13809                 uid.markCameraTimeUs(elapsedRealtimeMs);
13810             }
13811             return;
13812         }
13813 
13814         mGlobalEnergyConsumerStats.updateStandardBucket(
13815                 EnergyConsumerStats.POWER_BUCKET_CAMERA, chargeUC);
13816 
13817         // Collect the per uid time since mark so that we can normalize power.
13818         final SparseDoubleArray cameraTimeUsArray = new SparseDoubleArray();
13819 
13820         // Note: Iterating over all UIDs may be suboptimal.
13821         final int uidStatsSize = mUidStats.size();
13822         for (int i = 0; i < uidStatsSize; i++) {
13823             final Uid uid = mUidStats.valueAt(i);
13824             final long cameraTimeUs = uid.markCameraTimeUs(elapsedRealtimeMs);
13825             if (cameraTimeUs == 0) continue;
13826             cameraTimeUsArray.put(uid.getUid(), (double) cameraTimeUs);
13827         }
13828         distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_CAMERA, chargeUC,
13829                 cameraTimeUsArray, 0, elapsedRealtimeMs);
13830     }
13831 
13832     /**
13833      * Accumulate Custom power bucket charge, globally and for each app.
13834      *
13835      * @param totalChargeUC charge (microcoulombs) used for this bucket since this was last called.
13836      * @param uidCharges map of uid->charge (microcoulombs) for this bucket since last called.
13837      *                    Data inside uidCharges will not be modified (treated immutable).
13838      *                    Uids not already known to BatteryStats will be ignored.
13839      */
13840     @GuardedBy("this")
13841     @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToCustomBucketLocked
13842     public void updateCustomEnergyConsumerStatsLocked(int customPowerBucket,
13843             long totalChargeUC, @Nullable SparseLongArray uidCharges) {
13844         if (DEBUG_ENERGY) {
13845             Slog.d(TAG, "Updating attributed EnergyConsumer stats for custom bucket "
13846                     + customPowerBucket
13847                     + " with total charge " + totalChargeUC
13848                     + " and uid charges " + uidCharges);
13849         }
13850         if (mGlobalEnergyConsumerStats == null) return;
13851         if (!mOnBatteryInternal || mIgnoreNextExternalStats || totalChargeUC <= 0) return;
13852 
13853         mGlobalEnergyConsumerStats.updateCustomBucket(customPowerBucket, totalChargeUC,
13854                 mClock.elapsedRealtime());
13855 
13856         if (uidCharges == null) return;
13857         final int numUids = uidCharges.size();
13858         for (int i = 0; i < numUids; i++) {
13859             final int uidInt = mapUid(uidCharges.keyAt(i));
13860             final long uidChargeUC = uidCharges.valueAt(i);
13861             if (uidChargeUC == 0) continue;
13862 
13863             final Uid uidObj = getAvailableUidStatsLocked(uidInt);
13864             if (uidObj != null) {
13865                 uidObj.addChargeToCustomBucketLocked(uidChargeUC, customPowerBucket);
13866             } else {
13867                 // Ignore any uid not already known to BatteryStats, rather than creating a new Uid.
13868                 // Otherwise we could end up reviving dead Uids. Note that the CPU data is updated
13869                 // first, so any uid that has used any CPU should already be known to BatteryStats.
13870                 // Recently removed uids (especially common for isolated uids) can reach this path
13871                 // and are ignored.
13872                 if (!Process.isIsolated(uidInt)) {
13873                     Slog.w(TAG, "Received EnergyConsumer charge " + totalChargeUC
13874                             + " for custom bucket " + customPowerBucket + " for non-existent uid "
13875                             + uidInt);
13876                 }
13877             }
13878         }
13879     }
13880 
13881     /**
13882      * Attributes energy (for the given bucket) to each uid according to the following formula:
13883      *     blamedEnergy[uid] = totalEnergy * ratioNumerators[uid] / ratioDenominator;
13884      * <p>Does nothing if ratioDenominator is 0.
13885      *
13886      * <p>Here, ratioDenominator = max(sumOfAllRatioNumerators, minRatioDenominator),
13887      * so if given minRatioDenominator <= 0, then sumOfAllRatioNumerators will be used implicitly.
13888      *
13889      * <p>Note that ratioNumerators and minRatioDenominator must use the same units, but need not
13890      * use the same units as totalConsumedChargeUC (which must be in microcoulombs).
13891      *
13892      * <p>A consequence of minRatioDenominator is that the sum over all uids might be less than
13893      * totalConsumedChargeUC. This is intentional; the remainder is purposefully unnaccounted rather
13894      * than incorrectly blamed on uids, and implies unknown (non-uid) sources of drain.
13895      *
13896      * <p>All uids in ratioNumerators must exist in mUidStats already.
13897      */
13898     @GuardedBy("this")
13899     @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToStandardBucketLocked
13900     private void distributeEnergyToUidsLocked(@StandardPowerBucket int bucket,
13901             long totalConsumedChargeUC, SparseDoubleArray ratioNumerators,
13902             double minRatioDenominator, long timestampMs) {
13903 
13904         // If the sum of all app usage was greater than the total, use that instead:
13905         double sumRatioNumerators = 0;
13906         for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
13907             sumRatioNumerators += ratioNumerators.valueAt(i);
13908         }
13909         final double ratioDenominator = Math.max(sumRatioNumerators, minRatioDenominator);
13910         if (ratioDenominator <= 0) return;
13911 
13912         for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
13913             final Uid uid = getAvailableUidStatsLocked(ratioNumerators.keyAt(i));
13914             final double ratioNumerator = ratioNumerators.valueAt(i);
13915             final long uidActualUC
13916                     = (long) (totalConsumedChargeUC * ratioNumerator / ratioDenominator + 0.5);
13917             uid.addChargeToStandardBucketLocked(uidActualUC, bucket, timestampMs);
13918         }
13919     }
13920 
13921     /**
13922      * Read and record Rail Energy data.
13923      */
13924     public void updateRailStatsLocked() {
13925         if (mEnergyConsumerRetriever == null || !mTmpRailStats.isRailStatsAvailable()) {
13926             return;
13927         }
13928         mEnergyConsumerRetriever.fillRailDataStats(mTmpRailStats);
13929     }
13930 
13931     /** Informs that external stats data has been completely flushed. */
13932     public void informThatAllExternalStatsAreFlushed() {
13933         synchronized (this) {
13934             // Any data from the pre-reset era is flushed, so we can henceforth process future data.
13935             mIgnoreNextExternalStats = false;
13936         }
13937     }
13938 
13939     /**
13940      * Read and distribute kernel wake lock use across apps.
13941      */
13942     public void updateKernelWakelocksLocked(long elapsedRealtimeUs) {
13943         if (mKernelWakelockReader == null) {
13944             return;
13945         }
13946 
13947         final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
13948                 mTmpWakelockStats);
13949         if (wakelockStats == null) {
13950             // Not crashing might make board bringup easier.
13951             Slog.w(TAG, "Couldn't get kernel wake lock stats");
13952             return;
13953         }
13954 
13955         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
13956             String name = ent.getKey();
13957             KernelWakelockStats.Entry kws = ent.getValue();
13958 
13959             SamplingTimer kwlt = mKernelWakelockStats.get(name);
13960             if (kwlt == null) {
13961                 kwlt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase);
13962                 mKernelWakelockStats.put(name, kwlt);
13963             }
13964 
13965             kwlt.update(kws.totalTimeUs, kws.activeTimeUs, kws.count, elapsedRealtimeUs);
13966             kwlt.setUpdateVersion(kws.version);
13967         }
13968 
13969         int numWakelocksSetStale = 0;
13970         // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
13971         // this time.
13972         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
13973             SamplingTimer st = ent.getValue();
13974             if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
13975                 st.endSample(elapsedRealtimeUs);
13976                 numWakelocksSetStale++;
13977             }
13978         }
13979 
13980         if (DEBUG) {
13981             // Record whether we've seen a non-zero time (for debugging b/22716723).
13982             if (wakelockStats.isEmpty()) {
13983                 Slog.wtf(TAG, "All kernel wakelocks had time of zero");
13984             }
13985 
13986             if (numWakelocksSetStale == mKernelWakelockStats.size()) {
13987                 Slog.wtf(TAG, "All kernel wakelocks were set stale. new version="
13988                         + wakelockStats.kernelWakelockVersion);
13989             }
13990         }
13991     }
13992 
13993     // We use an anonymous class to access these variables,
13994     // so they can't live on the stack or they'd have to be
13995     // final MutableLong objects (more allocations).
13996     // Used in updateCpuTimeLocked().
13997     long mTempTotalCpuUserTimeUs;
13998     long mTempTotalCpuSystemTimeUs;
13999     long[][] mWakeLockAllocationsUs;
14000 
14001     /**
14002      * Reads the newest memory stats from the kernel.
14003      */
14004     public void updateKernelMemoryBandwidthLocked(long elapsedRealtimeUs) {
14005         mKernelMemoryBandwidthStats.updateStats();
14006         LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
14007         final int bandwidthEntryCount = bandwidthEntries.size();
14008         int index;
14009         for (int i = 0; i < bandwidthEntryCount; i++) {
14010             SamplingTimer timer;
14011             if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) {
14012                 timer = mKernelMemoryStats.valueAt(index);
14013             } else {
14014                 timer = new SamplingTimer(mClock, mOnBatteryTimeBase);
14015                 mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
14016             }
14017             timer.update(bandwidthEntries.valueAt(i), 1, elapsedRealtimeUs);
14018             if (DEBUG_MEMORY) {
14019                 Slog.d(TAG, String.format("Added entry %d and updated timer to: "
14020                         + "mUnpluggedReportedTotalTimeUs %d size %d", bandwidthEntries.keyAt(i),
14021                         mKernelMemoryStats.get(
14022                                 bandwidthEntries.keyAt(i)).mBaseReportedTotalTimeUs,
14023                         mKernelMemoryStats.size()));
14024             }
14025         }
14026     }
14027 
14028     public boolean isOnBatteryLocked() {
14029         return mOnBatteryTimeBase.isRunning();
14030     }
14031 
14032     public boolean isOnBatteryScreenOffLocked() {
14033         return mOnBatteryScreenOffTimeBase.isRunning();
14034     }
14035 
14036     /**
14037      * Object for calculating and accumulating the estimated cpu power used while reading the
14038      * various cpu kernel files.
14039      */
14040     @VisibleForTesting
14041     public static class CpuDeltaPowerAccumulator {
14042         // Keeps track of total charge used per cluster.
14043         public final double[] totalClusterChargesMah;
14044         // Keeps track of charge used per cluster per uid.
14045         public final ArrayMap<Uid, double[]> perUidCpuClusterChargesMah;
14046 
14047         private final CpuPowerCalculator mCalculator;
14048         private Uid mCachedUid = null;
14049         private double[] mUidClusterCache = null;
14050 
14051         CpuDeltaPowerAccumulator(CpuPowerCalculator calculator, int nClusters) {
14052             mCalculator = calculator;
14053             totalClusterChargesMah = new double[nClusters];
14054             perUidCpuClusterChargesMah = new ArrayMap<>();
14055         }
14056 
14057         /** Add per cpu cluster durations to the currently cached uid. */
14058         public void addCpuClusterDurationsMs(Uid uid, long[] durationsMs) {
14059             final double[] uidChargesMah = getOrCreateUidCpuClusterCharges(uid);
14060             for (int cluster = 0; cluster < durationsMs.length; cluster++) {
14061                 final double estimatedDeltaMah = mCalculator.calculatePerCpuClusterPowerMah(cluster,
14062                         durationsMs[cluster]);
14063                 uidChargesMah[cluster] += estimatedDeltaMah;
14064                 totalClusterChargesMah[cluster] += estimatedDeltaMah;
14065             }
14066         }
14067 
14068         /** Add per speed per cpu cluster durations to the currently cached uid. */
14069         public void addCpuClusterSpeedDurationsMs(Uid uid, int cluster, int speed,
14070                 long durationsMs) {
14071             final double[] uidChargesMah = getOrCreateUidCpuClusterCharges(uid);
14072             final double estimatedDeltaMah = mCalculator.calculatePerCpuFreqPowerMah(cluster, speed,
14073                     durationsMs);
14074             uidChargesMah[cluster] += estimatedDeltaMah;
14075             totalClusterChargesMah[cluster] += estimatedDeltaMah;
14076         }
14077 
14078         private double[] getOrCreateUidCpuClusterCharges(Uid uid) {
14079             // Repeated additions on the same uid is very likely.
14080             // Skip a lookup if getting the same uid as the last get.
14081             if (uid == mCachedUid) return mUidClusterCache;
14082 
14083             double[] uidChargesMah = perUidCpuClusterChargesMah.get(uid);
14084             if (uidChargesMah == null) {
14085                 uidChargesMah = new double[totalClusterChargesMah.length];
14086                 perUidCpuClusterChargesMah.put(uid, uidChargesMah);
14087             }
14088             mCachedUid = uid;
14089             mUidClusterCache = uidChargesMah;
14090             return uidChargesMah;
14091         }
14092     }
14093 
14094     /**
14095      * Read and distribute CPU usage across apps. If their are partial wakelocks being held
14096      * and we are on battery with screen off, we give more of the cpu time to those apps holding
14097      * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
14098      * It's possible this will be invoked after the internal battery/screen states are updated, so
14099      * passing the appropriate battery/screen states to try attribute the cpu times to correct
14100      * buckets.
14101      */
14102     @GuardedBy("this")
14103     public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff,
14104             long[] cpuClusterChargeUC) {
14105         if (DEBUG_ENERGY_CPU) {
14106             Slog.d(TAG, "!Cpu updating!");
14107         }
14108 
14109         // Calculate the wakelocks we have to distribute amongst. The system is excluded as it is
14110         // usually holding the wakelock on behalf of an app.
14111         // And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
14112         ArrayList<StopwatchTimer> partialTimersToConsider = null;
14113         if (onBatteryScreenOff) {
14114             partialTimersToConsider = new ArrayList<>();
14115             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
14116                 final StopwatchTimer timer = mPartialTimers.get(i);
14117                 // Since the collection and blaming of wakelocks can be scheduled to run after
14118                 // some delay, the mPartialTimers list may have new entries. We can't blame
14119                 // the newly added timer for past cpu time, so we only consider timers that
14120                 // were present for one round of collection. Once a timer has gone through
14121                 // a round of collection, its mInList field is set to true.
14122                 if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
14123                     partialTimersToConsider.add(timer);
14124                 }
14125             }
14126         }
14127         markPartialTimersAsEligible();
14128 
14129         // When the battery is not on, we don't attribute the cpu times to any timers but we still
14130         // need to take the snapshots.
14131         if (!onBattery) {
14132             mCpuUidUserSysTimeReader.readDelta(false, null);
14133             mCpuUidFreqTimeReader.readDelta(false, null);
14134             mNumAllUidCpuTimeReads += 2;
14135             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
14136                 mCpuUidActiveTimeReader.readDelta(false, null);
14137                 mCpuUidClusterTimeReader.readDelta(false, null);
14138                 mNumAllUidCpuTimeReads += 2;
14139             }
14140             for (int i = mKernelCpuSpeedReaders.length - 1; i >= 0; --i) {
14141                 if (mKernelCpuSpeedReaders[i] != null) {
14142                     mKernelCpuSpeedReaders[i].readDelta();
14143                 }
14144             }
14145             if (!Flags.disableSystemServicePowerAttr()) {
14146                 mSystemServerCpuThreadReader.readDelta();
14147             }
14148             return;
14149         }
14150 
14151         mUserInfoProvider.refreshUserIds();
14152         final SparseLongArray updatedUids = mCpuUidFreqTimeReader.allUidTimesAvailable()
14153                 ? null : new SparseLongArray();
14154 
14155         final CpuDeltaPowerAccumulator powerAccumulator;
14156         if (mGlobalEnergyConsumerStats != null
14157                 && mGlobalEnergyConsumerStats.isStandardBucketSupported(
14158                 EnergyConsumerStats.POWER_BUCKET_CPU)) {
14159             if (cpuClusterChargeUC == null) {
14160                 Slog.wtf(TAG,
14161                         "POWER_BUCKET_CPU supported but no EnergyConsumer Cpu Cluster charge "
14162                                 + "reported on updateCpuTimeLocked!");
14163                 powerAccumulator = null;
14164             } else {
14165                 if (mCpuPowerCalculator == null) {
14166                     mCpuPowerCalculator = new CpuPowerCalculator(mCpuScalingPolicies,
14167                             mPowerProfile);
14168                 }
14169                 // Cpu EnergyConsumer is supported, create an object to accumulate the estimated
14170                 // charge consumption since the last cpu update
14171                 powerAccumulator = new CpuDeltaPowerAccumulator(mCpuPowerCalculator,
14172                         mCpuScalingPolicies.getPolicies().length);
14173             }
14174         } else {
14175             powerAccumulator = null;
14176         }
14177 
14178         readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
14179         // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
14180         // freqs, so no need to approximate these values.
14181         if (updatedUids != null) {
14182             updateClusterSpeedTimes(updatedUids, onBattery, powerAccumulator);
14183         }
14184         readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff,
14185                 powerAccumulator);
14186         mNumAllUidCpuTimeReads += 2;
14187         if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
14188             // Cpu Active times do not get any info ony how to attribute Cpu Cluster
14189             // charge, so not need to provide the powerAccumulator
14190             readKernelUidCpuActiveTimesLocked(onBattery);
14191             readKernelUidCpuClusterTimesLocked(onBattery, powerAccumulator);
14192             mNumAllUidCpuTimeReads += 2;
14193         }
14194 
14195         if (!Flags.disableSystemServicePowerAttr()) {
14196             updateSystemServerThreadStats();
14197         }
14198 
14199         if (powerAccumulator != null) {
14200             updateCpuEnergyConsumerStatsLocked(cpuClusterChargeUC, powerAccumulator);
14201         }
14202     }
14203 
14204     /**
14205      * Estimates the proportion of the System Server CPU activity (per cluster per speed)
14206      * spent on handling incoming binder calls.
14207      */
14208     @VisibleForTesting
14209     public void updateSystemServerThreadStats() {
14210         // There are some simplifying assumptions made in this algorithm
14211         // 1) We assume that if a thread handles incoming binder calls, all of its activity
14212         //    is spent doing that.  Most incoming calls are handled by threads allocated
14213         //    by the native layer in the binder thread pool, so this assumption is reasonable.
14214         // 2) We use the aggregate CPU time spent in different threads as a proxy for the CPU
14215         //    cost. In reality, in multi-core CPUs, the CPU cost may not be linearly
14216         //    affected by additional threads.
14217 
14218         SystemServerCpuThreadReader.SystemServiceCpuThreadTimes systemServiceCpuThreadTimes =
14219                     mSystemServerCpuThreadReader.readDelta();
14220         if (systemServiceCpuThreadTimes == null) {
14221             return;
14222         }
14223 
14224         if (mBinderThreadCpuTimesUs == null) {
14225             mBinderThreadCpuTimesUs = new LongSamplingCounterArray(mOnBatteryTimeBase);
14226         }
14227         mBinderThreadCpuTimesUs.addCountLocked(systemServiceCpuThreadTimes.binderThreadCpuTimesUs);
14228 
14229         if (DEBUG_BINDER_STATS) {
14230             Slog.d(TAG, "System server threads per CPU cluster (incoming binder threads)");
14231             long binderThreadTimeMs = 0;
14232             final long[] binderThreadCpuTimesUs = mBinderThreadCpuTimesUs.getCountsLocked(
14233                     BatteryStats.STATS_SINCE_CHARGED);
14234             int index = 0;
14235             int[] policies = mCpuScalingPolicies.getPolicies();
14236             for (int policy : policies) {
14237                 StringBuilder sb = new StringBuilder();
14238                 sb.append("policy").append(policy).append(": [");
14239                 int numSpeeds = mCpuScalingPolicies.getFrequencies(policy).length;
14240                 for (int speed = 0; speed < numSpeeds; speed++) {
14241                     if (speed != 0) {
14242                         sb.append(", ");
14243                     }
14244                     long binderCountMs = binderThreadCpuTimesUs[index] / 1000;
14245                     sb.append(TextUtils.formatSimple("%10d", binderCountMs));
14246 
14247                     binderThreadTimeMs += binderCountMs;
14248                     index++;
14249                 }
14250                 Slog.d(TAG, sb.toString());
14251             }
14252         }
14253     }
14254 
14255     /**
14256      * Mark the current partial timers as gone through a collection so that they will be
14257      * considered in the next cpu times distribution to wakelock holders.
14258      */
14259     @VisibleForTesting
14260     public void markPartialTimersAsEligible() {
14261         if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
14262             // No difference, so each timer is now considered for the next collection.
14263             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
14264                 mPartialTimers.get(i).mInList = true;
14265             }
14266         } else {
14267             // The lists are different, meaning we added (or removed a timer) since the last
14268             // collection.
14269             for (int i = mLastPartialTimers.size() - 1; i >= 0; --i) {
14270                 mLastPartialTimers.get(i).mInList = false;
14271             }
14272             mLastPartialTimers.clear();
14273 
14274             // Mark the current timers as gone through a collection.
14275             final int numPartialTimers = mPartialTimers.size();
14276             for (int i = 0; i < numPartialTimers; ++i) {
14277                 final StopwatchTimer timer = mPartialTimers.get(i);
14278                 timer.mInList = true;
14279                 mLastPartialTimers.add(timer);
14280             }
14281         }
14282     }
14283 
14284     /**
14285      * Take snapshot of cpu times (aggregated over all uids) at different frequencies and
14286      * calculate cpu times spent by each uid at different frequencies. Will also add estimated
14287      * power consumptions, if powerAccumulator data structure is provided.
14288      *
14289      * @param updatedUids  The uids for which times spent at different frequencies are calculated.
14290      * @param onBattery whether or not this is onBattery
14291      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
14292      */
14293     @VisibleForTesting
14294     public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery,
14295             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
14296         long totalCpuClustersTimeMs = 0;
14297         // Read the time spent for each cluster at various cpu frequencies.
14298         final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
14299         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
14300             if (mKernelCpuSpeedReaders[cluster] != null) {
14301                 clusterSpeedTimesMs[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
14302                 if (clusterSpeedTimesMs[cluster] != null) {
14303                     for (int speed = clusterSpeedTimesMs[cluster].length - 1; speed >= 0; --speed) {
14304                         totalCpuClustersTimeMs += clusterSpeedTimesMs[cluster][speed];
14305                     }
14306                 }
14307             }
14308         }
14309         if (totalCpuClustersTimeMs != 0) {
14310             // We have cpu times per freq aggregated over all uids but we need the times per uid.
14311             // So, we distribute total time spent by an uid to different cpu freqs based on the
14312             // amount of time cpu was running at that freq.
14313             final int updatedUidsCount = updatedUids.size();
14314             final long elapsedRealtimeMs = mClock.elapsedRealtime();
14315             final long uptimeMs = mClock.uptimeMillis();
14316             for (int i = 0; i < updatedUidsCount; ++i) {
14317                 final Uid u = getUidStatsLocked(updatedUids.keyAt(i), elapsedRealtimeMs, uptimeMs);
14318                 final long appCpuTimeUs = updatedUids.valueAt(i);
14319                 // Add the cpu speeds to this UID.
14320                 int[] policies = mCpuScalingPolicies.getPolicies();
14321                 if (u.mCpuClusterSpeedTimesUs == null ||
14322                         u.mCpuClusterSpeedTimesUs.length != policies.length) {
14323                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[policies.length][];
14324                 }
14325 
14326                 for (int cluster = 0; cluster < policies.length; cluster++) {
14327                     final int speedsInCluster = clusterSpeedTimesMs[cluster].length;
14328                     if (u.mCpuClusterSpeedTimesUs[cluster] == null || speedsInCluster !=
14329                             u.mCpuClusterSpeedTimesUs[cluster].length) {
14330                         u.mCpuClusterSpeedTimesUs[cluster]
14331                                 = new LongSamplingCounter[speedsInCluster];
14332                     }
14333 
14334                     final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeedTimesUs[cluster];
14335                     for (int speed = 0; speed < speedsInCluster; speed++) {
14336                         if (cpuSpeeds[speed] == null) {
14337                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
14338                         }
14339                         final long deltaSpeedCount = appCpuTimeUs
14340                                 * clusterSpeedTimesMs[cluster][speed]
14341                                 / totalCpuClustersTimeMs;
14342                         cpuSpeeds[speed].addCountLocked(deltaSpeedCount, onBattery);
14343 
14344                         if (powerAccumulator != null) {
14345                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
14346                                     speed, deltaSpeedCount);
14347                         }
14348                     }
14349                 }
14350             }
14351         }
14352     }
14353 
14354     /**
14355      * Take a snapshot of the cpu times spent by each uid and update the corresponding counters.
14356      * If {@param partialTimers} is not null and empty, then we assign a portion of cpu times to
14357      * wakelock holders.
14358      *
14359      * @param partialTimers The wakelock holders among which the cpu times will be distributed.
14360      * @param updatedUids If not null, then the uids found in the snapshot will be added to this.
14361      */
14362     @VisibleForTesting
14363     public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
14364             @Nullable SparseLongArray updatedUids, boolean onBattery) {
14365         mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
14366         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
14367         final long startTimeMs = mClock.uptimeMillis();
14368         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14369 
14370         mCpuUidUserSysTimeReader.readDelta(false, (uid, timesUs) -> {
14371             long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
14372 
14373             uid = mapUid(uid);
14374             if (Process.isIsolated(uid)) {
14375                 // This could happen if the isolated uid mapping was removed before that process
14376                 // was actually killed.
14377                 if (DEBUG) Slog.d(TAG, "Got readings for an isolated uid: " + uid);
14378                 return;
14379             }
14380             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
14381                 if (DEBUG) Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
14382                 return;
14383             }
14384             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
14385 
14386             // Accumulate the total system and user time.
14387             mTempTotalCpuUserTimeUs += userTimeUs;
14388             mTempTotalCpuSystemTimeUs += systemTimeUs;
14389 
14390             StringBuilder sb = null;
14391             if (DEBUG_ENERGY_CPU) {
14392                 sb = new StringBuilder();
14393                 sb.append("  got time for uid=").append(u.mUid).append(": u=");
14394                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
14395                 sb.append(" s=");
14396                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
14397                 sb.append("\n");
14398             }
14399 
14400             if (numWakelocks > 0) {
14401                 // We have wakelocks being held, so only give a portion of the
14402                 // time to the process. The rest will be distributed among wakelock
14403                 // holders.
14404                 userTimeUs = (userTimeUs * WAKE_LOCK_WEIGHT) / 100;
14405                 systemTimeUs = (systemTimeUs * WAKE_LOCK_WEIGHT) / 100;
14406             }
14407 
14408             if (sb != null) {
14409                 sb.append("  adding to uid=").append(u.mUid).append(": u=");
14410                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
14411                 sb.append(" s=");
14412                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
14413                 Slog.d(TAG, sb.toString());
14414             }
14415 
14416             u.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
14417             u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
14418             if (updatedUids != null) {
14419                 updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
14420             }
14421         });
14422 
14423         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
14424         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
14425             Slog.d(TAG, "Reading cpu stats took " + elapsedTimeMs + "ms");
14426         }
14427 
14428         if (numWakelocks > 0) {
14429             // Distribute a portion of the total cpu time to wakelock holders.
14430             mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
14431             mTempTotalCpuSystemTimeUs =
14432                     (mTempTotalCpuSystemTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
14433 
14434             for (int i = 0; i < numWakelocks; ++i) {
14435                 final StopwatchTimer timer = partialTimers.get(i);
14436                 final int userTimeUs = (int) (mTempTotalCpuUserTimeUs / (numWakelocks - i));
14437                 final int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / (numWakelocks - i));
14438 
14439                 if (DEBUG_ENERGY_CPU) {
14440                     final StringBuilder sb = new StringBuilder();
14441                     sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
14442                             .append(": u=");
14443                     TimeUtils.formatDuration(userTimeUs / 1000, sb);
14444                     sb.append(" s=");
14445                     TimeUtils.formatDuration(systemTimeUs / 1000, sb);
14446                     Slog.d(TAG, sb.toString());
14447                 }
14448 
14449                 timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
14450                 timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
14451                 if (updatedUids != null) {
14452                     final int uid = timer.mUid.getUid();
14453                     updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
14454                 }
14455 
14456                 final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
14457                 proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery);
14458 
14459                 mTempTotalCpuUserTimeUs -= userTimeUs;
14460                 mTempTotalCpuSystemTimeUs -= systemTimeUs;
14461             }
14462         }
14463     }
14464 
14465     /**
14466      * Take a snapshot of the cpu times spent by each uid in each freq and update the
14467      * corresponding counters.  Will also add estimated power consumptions, if powerAccumulator
14468      * data structure is provided.
14469      *
14470      * @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
14471      * @param onBattery whether or not this is onBattery
14472      * @param onBatteryScreenOff whether or not this is onBattery with the screen off.
14473      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
14474      */
14475     @VisibleForTesting
14476     public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
14477             boolean onBattery, boolean onBatteryScreenOff,
14478             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
14479         final boolean perClusterTimesAvailable =
14480                 mCpuUidFreqTimeReader.perClusterTimesAvailable();
14481         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
14482         final int[] policies = mCpuScalingPolicies.getPolicies();
14483         final int numClusters = policies.length;
14484         mWakeLockAllocationsUs = null;
14485         final long startTimeMs = mClock.uptimeMillis();
14486         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14487         // If power is being accumulated for attribution, data needs to be read immediately.
14488         final boolean forceRead = powerAccumulator != null;
14489         mCpuUidFreqTimeReader.readDelta(forceRead, (uid, cpuFreqTimeMs) -> {
14490             uid = mapUid(uid);
14491             if (Process.isIsolated(uid)) {
14492                 if (DEBUG) Slog.d(TAG, "Got freq readings for an isolated uid: " + uid);
14493                 return;
14494             }
14495             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
14496                 if (DEBUG) Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
14497                 return;
14498             }
14499             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
14500             if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
14501                 detachIfNotNull(u.mCpuFreqTimeMs);
14502                 u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
14503             }
14504             u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
14505             if (u.mScreenOffCpuFreqTimeMs == null ||
14506                     u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
14507                 detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
14508                 u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
14509                         mOnBatteryScreenOffTimeBase);
14510             }
14511             u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff);
14512 
14513             if (perClusterTimesAvailable) {
14514                 if (u.mCpuClusterSpeedTimesUs == null ||
14515                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
14516                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
14517                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
14518                 }
14519                 if (numWakelocks > 0 && mWakeLockAllocationsUs == null) {
14520                     mWakeLockAllocationsUs = new long[numClusters][];
14521                 }
14522 
14523                 int freqIndex = 0;
14524                 for (int cluster = 0; cluster < numClusters; cluster++) {
14525                     final int[] freqs = mCpuScalingPolicies.getFrequencies(policies[cluster]);
14526                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
14527                             u.mCpuClusterSpeedTimesUs[cluster].length != freqs.length) {
14528                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
14529                         u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[freqs.length];
14530                     }
14531                     if (numWakelocks > 0 && mWakeLockAllocationsUs[cluster] == null) {
14532                         mWakeLockAllocationsUs[cluster] = new long[freqs.length];
14533                     }
14534                     final LongSamplingCounter[] cpuTimesUs = u.mCpuClusterSpeedTimesUs[cluster];
14535                     for (int speed = 0; speed < freqs.length; ++speed) {
14536                         if (cpuTimesUs[speed] == null) {
14537                             cpuTimesUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
14538                         }
14539                         final long appAllocationUs;
14540                         if (mWakeLockAllocationsUs != null) {
14541                             appAllocationUs =
14542                                     (cpuFreqTimeMs[freqIndex] * 1000 * WAKE_LOCK_WEIGHT) / 100;
14543                             mWakeLockAllocationsUs[cluster][speed] +=
14544                                     (cpuFreqTimeMs[freqIndex] * 1000 - appAllocationUs);
14545                         } else {
14546                             appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
14547                         }
14548                         cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
14549 
14550                         if (powerAccumulator != null) {
14551                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
14552                                     speed, appAllocationUs / 1000);
14553                         }
14554                         freqIndex++;
14555                     }
14556                 }
14557             }
14558         });
14559 
14560         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
14561         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
14562             Slog.d(TAG, "Reading cpu freq times took " + elapsedTimeMs + "ms");
14563         }
14564 
14565         if (mWakeLockAllocationsUs != null) {
14566             for (int i = 0; i < numWakelocks; ++i) {
14567                 final Uid u = partialTimers.get(i).mUid;
14568                 if (u.mCpuClusterSpeedTimesUs == null ||
14569                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
14570                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
14571                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
14572                 }
14573 
14574                 for (int cluster = 0; cluster < numClusters; ++cluster) {
14575                     final int speedsInCluster =
14576                             mCpuScalingPolicies.getFrequencies(policies[cluster]).length;
14577                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
14578                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
14579                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
14580                         u.mCpuClusterSpeedTimesUs[cluster]
14581                                 = new LongSamplingCounter[speedsInCluster];
14582                     }
14583                     final LongSamplingCounter[] cpuTimeUs = u.mCpuClusterSpeedTimesUs[cluster];
14584                     for (int speed = 0; speed < speedsInCluster; ++speed) {
14585                         if (cpuTimeUs[speed] == null) {
14586                             cpuTimeUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
14587                         }
14588                         final long allocationUs =
14589                                 mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
14590                         cpuTimeUs[speed].addCountLocked(allocationUs, onBattery);
14591                         mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
14592 
14593                         if (powerAccumulator != null) {
14594                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
14595                                     speed, allocationUs / 1000);
14596                         }
14597                     }
14598                 }
14599             }
14600         }
14601     }
14602 
14603     /**
14604      * Take a snapshot of the cpu active times spent by each uid and update the corresponding
14605      * counters.
14606      */
14607     @VisibleForTesting
14608     public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
14609         final long startTimeMs = mClock.uptimeMillis();
14610         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14611         mCpuUidActiveTimeReader.readAbsolute((uid, cpuActiveTimesMs) -> {
14612             final int parentUid = mapUid(uid);
14613             if (Process.isIsolated(parentUid)) {
14614                 if (DEBUG) Slog.w(TAG, "Got active times for an isolated uid: " + uid);
14615                 return;
14616             }
14617             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
14618                 if (DEBUG) Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
14619                 return;
14620             }
14621             final Uid u = getUidStatsLocked(parentUid, elapsedRealtimeMs, startTimeMs);
14622             if (parentUid == uid) {
14623                 u.getCpuActiveTimeCounter().update(cpuActiveTimesMs, elapsedRealtimeMs);
14624             } else {
14625                 final SparseArray<Uid.ChildUid> childUids = u.mChildUids;
14626                 if (childUids == null) {
14627                     return;
14628                 }
14629 
14630                 Uid.ChildUid childUid = childUids.get(uid);
14631                 if (childUid != null) {
14632                     final long delta =
14633                             childUid.cpuActiveCounter.update(cpuActiveTimesMs, elapsedRealtimeMs);
14634                     u.getCpuActiveTimeCounter().increment(delta, elapsedRealtimeMs);
14635                 }
14636             }
14637         });
14638 
14639         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
14640         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
14641             Slog.d(TAG, "Reading cpu active times took " + elapsedTimeMs + "ms");
14642         }
14643     }
14644 
14645     /**
14646      * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding
14647      * counters. Will also add estimated power consumptions, if powerAccumulator data structure
14648      * is provided.
14649      *
14650      * @param onBattery whether or not this is onBattery
14651      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
14652      */
14653     @VisibleForTesting
14654     public void readKernelUidCpuClusterTimesLocked(boolean onBattery,
14655             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
14656         final long startTimeMs = mClock.uptimeMillis();
14657         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14658         // If power is being accumulated for attribution, data needs to be read immediately.
14659         final boolean forceRead = powerAccumulator != null;
14660         mCpuUidClusterTimeReader.readDelta(forceRead, (uid, cpuClusterTimesMs) -> {
14661             uid = mapUid(uid);
14662             if (Process.isIsolated(uid)) {
14663                 if (DEBUG) Slog.w(TAG, "Got cluster times for an isolated uid: " + uid);
14664                 return;
14665             }
14666             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
14667                 if (DEBUG) Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
14668                 return;
14669             }
14670             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
14671             u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesMs, onBattery);
14672 
14673             if (powerAccumulator != null) {
14674                 powerAccumulator.addCpuClusterDurationsMs(u, cpuClusterTimesMs);
14675             }
14676         });
14677 
14678         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
14679         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
14680             Slog.d(TAG, "Reading cpu cluster times took " + elapsedTimeMs + "ms");
14681         }
14682     }
14683 
14684     boolean setChargingLocked(boolean charging) {
14685         // if the device is no longer charging, remove the callback
14686         // if the device is now charging, it means that this is either called
14687         // 1. directly when level >= 90
14688         // 2. or from within the runnable that we deferred
14689         // For 1. if we have an existing callback, remove it, since we will immediately send a
14690         // ACTION_CHARGING
14691         // For 2. we remove existing callback so we don't send multiple ACTION_CHARGING
14692         mHandler.removeCallbacks(mDeferSetCharging);
14693         if (mCharging != charging) {
14694             mCharging = charging;
14695             mHistory.setChargingState(charging);
14696             mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
14697             return true;
14698         }
14699         return false;
14700     }
14701 
14702     /**
14703      * Notifies BatteryStatsImpl that the system server is ready.
14704      */
14705     public void onSystemReady(Context context) {
14706         if (mCpuUidFreqTimeReader != null) {
14707             mCpuUidFreqTimeReader.onSystemReady();
14708         }
14709 
14710         mPowerStatsCollectorInjector.setContext(context);
14711 
14712         mCpuPowerStatsCollector.setEnabled(
14713                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU));
14714         mCpuPowerStatsCollector.schedule();
14715 
14716         mMobileRadioPowerStatsCollector.setEnabled(
14717                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO));
14718         mMobileRadioPowerStatsCollector.schedule();
14719 
14720         mWifiPowerStatsCollector.setEnabled(
14721                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_WIFI));
14722         mWifiPowerStatsCollector.schedule();
14723 
14724         mBluetoothPowerStatsCollector.setEnabled(
14725                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_BLUETOOTH));
14726         mBluetoothPowerStatsCollector.schedule();
14727 
14728         mCameraPowerStatsCollector.setEnabled(
14729                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_CAMERA));
14730         mCameraPowerStatsCollector.schedule();
14731 
14732         mGnssPowerStatsCollector.setEnabled(
14733                 mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_GNSS));
14734         mGnssPowerStatsCollector.schedule();
14735 
14736         mSystemReady = true;
14737     }
14738 
14739     /**
14740      * Returns a PowerStatsCollector for the specified power component or null if unavailable.
14741      */
14742     @Nullable
14743     PowerStatsCollector getPowerStatsCollector(
14744             @BatteryConsumer.PowerComponent int powerComponent) {
14745         switch (powerComponent) {
14746             case BatteryConsumer.POWER_COMPONENT_CPU:
14747                 return mCpuPowerStatsCollector;
14748             case BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO:
14749                 return mMobileRadioPowerStatsCollector;
14750             case BatteryConsumer.POWER_COMPONENT_WIFI:
14751                 return mWifiPowerStatsCollector;
14752             case BatteryConsumer.POWER_COMPONENT_BLUETOOTH:
14753                 return mBluetoothPowerStatsCollector;
14754             case BatteryConsumer.POWER_COMPONENT_CAMERA:
14755                 return mCameraPowerStatsCollector;
14756             case BatteryConsumer.POWER_COMPONENT_GNSS:
14757                 return mGnssPowerStatsCollector;
14758         }
14759         return null;
14760     }
14761 
14762 
14763     /**
14764      * Force recording of all history events regardless of the "charging" state.
14765      */
14766     @VisibleForTesting
14767     public void forceRecordAllHistory() {
14768         mHistory.forceRecordAllHistory();
14769         mRecordAllHistory = true;
14770     }
14771 
14772     /**
14773      * Might reset battery stats if conditions are met. Assumed the device is currently plugged in.
14774      */
14775     @VisibleForTesting
14776     @GuardedBy("this")
14777     public void maybeResetWhilePluggedInLocked() {
14778         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14779         if (shouldResetWhilePluggedInLocked(elapsedRealtimeMs)) {
14780             Slog.i(TAG,
14781                     "Resetting due to long plug in duration. elapsed time = " + elapsedRealtimeMs
14782                             + " ms, last plug in time = " + mBatteryPluggedInRealTimeMs
14783                             + " ms, last reset time = " + mRealtimeStartUs / 1000);
14784             resetAllStatsAndHistoryLocked(RESET_REASON_PLUGGED_IN_FOR_LONG_DURATION);
14785         }
14786 
14787         scheduleNextResetWhilePluggedInCheck();
14788     }
14789 
14790     @GuardedBy("this")
14791     private void scheduleNextResetWhilePluggedInCheck() {
14792         if (mAlarmManager == null) return;
14793         final long timeoutMs = mClock.currentTimeMillis()
14794                 + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
14795                 * DateUtils.HOUR_IN_MILLIS;
14796         Calendar nextAlarm = Calendar.getInstance();
14797         nextAlarm.setTimeInMillis(timeoutMs);
14798 
14799         // Find the 2 AM the same day as the end of the minimum duration.
14800         // This logic does not handle a Daylight Savings transition, or a timezone change
14801         // while the alarm has been set. The need to reset after a long period while plugged
14802         // in is not strict enough to warrant a well architected out solution.
14803         nextAlarm.set(Calendar.MILLISECOND, 0);
14804         nextAlarm.set(Calendar.SECOND, 0);
14805         nextAlarm.set(Calendar.MINUTE, 0);
14806         nextAlarm.set(Calendar.HOUR_OF_DAY, 2);
14807         long possibleNextTimeMs = nextAlarm.getTimeInMillis();
14808         if (possibleNextTimeMs < timeoutMs) {
14809             // The 2AM on the day of the timeout, move on the next day.
14810             possibleNextTimeMs += DateUtils.DAY_IN_MILLIS;
14811         }
14812         final long nextTimeMs = possibleNextTimeMs;
14813         final AlarmManager am = mAlarmManager;
14814         mHandler.post(() -> am.setWindow(AlarmManager.RTC, nextTimeMs,
14815                 DateUtils.HOUR_IN_MILLIS,
14816                 TAG, mLongPlugInAlarmHandler, mHandler));
14817     }
14818 
14819 
14820     @GuardedBy("this")
14821     private boolean shouldResetWhilePluggedInLocked(long elapsedRealtimeMs) {
14822         if (mNoAutoReset) return false;
14823         if (!mSystemReady) return false;
14824         if (!mHistory.isResetEnabled()) return false;
14825 
14826         final long pluggedInThresholdMs = mBatteryPluggedInRealTimeMs
14827                 + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
14828                 * DateUtils.HOUR_IN_MILLIS;
14829         if (elapsedRealtimeMs >= pluggedInThresholdMs) {
14830             // The device has been plugged in for a long time.
14831             final long resetThresholdMs = mRealtimeStartUs / 1000
14832                     + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
14833                     * DateUtils.HOUR_IN_MILLIS;
14834             if (elapsedRealtimeMs >= resetThresholdMs) {
14835                 // And it has been a long time since the last reset.
14836                 return true;
14837             }
14838         }
14839 
14840         return false;
14841     }
14842 
14843     @GuardedBy("this")
14844     private boolean shouldResetOnUnplugLocked(int batteryStatus, int batteryLevel) {
14845         if (mNoAutoReset) return false;
14846         if (!mSystemReady) return false;
14847         if (!mHistory.isResetEnabled()) return false;
14848         if (mBatteryStatsConfig.shouldResetOnUnplugHighBatteryLevel()) {
14849             // Allow resetting due to currently being at high battery level
14850             if (batteryStatus == BatteryManager.BATTERY_STATUS_FULL) return true;
14851             if (batteryLevel >= 90) return true;
14852         }
14853         if (mBatteryStatsConfig.shouldResetOnUnplugAfterSignificantCharge()) {
14854             // Allow resetting after a significant charge (from a very low level to a now very
14855             // high level).
14856             if (mDischargePlugLevel < 20 && batteryLevel >= 80) return true;
14857         }
14858         if (getHighDischargeAmountSinceCharge() >= 200) {
14859             // Reset the stats if battery got partially charged and discharged repeatedly without
14860             // ever reaching the full charge.
14861             // This reset is done in order to prevent stats sessions from going on forever.
14862             // Exceedingly long battery sessions would lead to an overflow of
14863             // data structures such as mWakeupReasonStats.
14864             return true;
14865         }
14866 
14867         return false;
14868     }
14869 
14870     @GuardedBy("this")
14871     protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
14872             final boolean onBattery, final int oldStatus, final int level, final int chargeUah) {
14873         boolean doWrite = false;
14874         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
14875         m.arg1 = onBattery ? 1 : 0;
14876         mHandler.sendMessage(m);
14877 
14878         final long uptimeUs = mSecUptime * 1000;
14879         final long realtimeUs = mSecRealtime * 1000;
14880         final int screenState = mScreenState;
14881         if (onBattery) {
14882             boolean reset = false;
14883             if (shouldResetOnUnplugLocked(oldStatus, level)) {
14884                 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
14885                         + " dischargeLevel=" + mDischargePlugLevel
14886                         + " lowAmount=" + getLowDischargeAmountSinceCharge()
14887                         + " highAmount=" + getHighDischargeAmountSinceCharge());
14888                 // Before we write, collect a snapshot of the final aggregated
14889                 // stats to be reported in the next checkin.  Only do this if we have
14890                 // a sufficient amount of data to make it interesting.
14891                 if (getLowDischargeAmountSinceCharge() >= 20) {
14892                     final long startTimeMs = SystemClock.uptimeMillis();
14893                     final Parcel parcel = Parcel.obtain();
14894                     writeSummaryToParcel(parcel, true);
14895                     final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs;
14896                     BackgroundThread.getHandler().post(new Runnable() {
14897                         @Override public void run() {
14898                             synchronized (mCheckinFile) {
14899                                 final long startTimeMs2 = SystemClock.uptimeMillis();
14900                                 FileOutputStream stream = null;
14901                                 try {
14902                                     stream = mCheckinFile.startWrite();
14903                                     stream.write(parcel.marshall());
14904                                     stream.flush();
14905                                     mCheckinFile.finishWrite(stream);
14906                                     mFrameworkStatsLogger.writeCommitSysConfigFile(
14907                                             "batterystats-checkin",
14908                                             initialTimeMs + SystemClock.uptimeMillis()
14909                                                     - startTimeMs2);
14910                                 } catch (IOException e) {
14911                                     Slog.w("BatteryStats",
14912                                             "Error writing checkin battery statistics", e);
14913                                     mCheckinFile.failWrite(stream);
14914                                 } finally {
14915                                     parcel.recycle();
14916                                 }
14917                             }
14918                         }
14919                     });
14920                 }
14921                 doWrite = true;
14922                 resetAllStatsLocked(mSecUptime, mSecRealtime, RESET_REASON_FULL_CHARGE);
14923                 if (chargeUah > 0 && level > 0) {
14924                     // Only use the reported coulomb charge value if it is supported and reported.
14925                     mEstimatedBatteryCapacityMah = (int) ((chargeUah / 1000) / (level / 100.0));
14926                 }
14927                 reset = true;
14928                 mDischargeStepTracker.init();
14929             }
14930             if (mCharging) {
14931                 setChargingLocked(false);
14932             }
14933             mOnBattery = mOnBatteryInternal = true;
14934             mLastDischargeStepLevel = level;
14935             mMinDischargeStepLevel = level;
14936             mDischargeStepTracker.clearTime();
14937             mDailyDischargeStepTracker.clearTime();
14938             mInitStepMode = mCurStepMode;
14939             mModStepMode = 0;
14940             pullPendingStateUpdatesLocked();
14941             if (reset) {
14942                 mHistory.startRecordingHistory(mSecRealtime, mSecUptime, reset);
14943                 initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
14944             }
14945             mBatteryPluggedIn = false;
14946             if (mAlarmManager != null) {
14947                 final AlarmManager am = mAlarmManager;
14948                 mHandler.post(() -> {
14949                     // No longer plugged in. Cancel the long plug in alarm.
14950                     am.cancel(mLongPlugInAlarmHandler);
14951                 });
14952             }
14953             mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
14954             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
14955             if (Display.isOnState(screenState)) {
14956                 mDischargeScreenOnUnplugLevel = level;
14957                 mDischargeScreenDozeUnplugLevel = 0;
14958                 mDischargeScreenOffUnplugLevel = 0;
14959             } else if (Display.isDozeState(screenState)) {
14960                 mDischargeScreenOnUnplugLevel = 0;
14961                 mDischargeScreenDozeUnplugLevel = level;
14962                 mDischargeScreenOffUnplugLevel = 0;
14963             } else {
14964                 mDischargeScreenOnUnplugLevel = 0;
14965                 mDischargeScreenDozeUnplugLevel = 0;
14966                 mDischargeScreenOffUnplugLevel = level;
14967             }
14968             mDischargeAmountScreenOn = 0;
14969             mDischargeAmountScreenDoze = 0;
14970             mDischargeAmountScreenOff = 0;
14971             updateTimeBasesLocked(true, screenState, uptimeUs, realtimeUs);
14972         } else {
14973             mOnBattery = mOnBatteryInternal = false;
14974             pullPendingStateUpdatesLocked();
14975             mBatteryPluggedIn = true;
14976             mBatteryPluggedInRealTimeMs = mSecRealtime;
14977             mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
14978             mDischargeCurrentLevel = mDischargePlugLevel = level;
14979             if (level < mDischargeUnplugLevel) {
14980                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
14981                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
14982             }
14983             updateDischargeScreenLevelsLocked(screenState, screenState);
14984             updateTimeBasesLocked(false, screenState, uptimeUs, realtimeUs);
14985             mChargeStepTracker.init();
14986             mLastChargeStepLevel = level;
14987             mMaxChargeStepLevel = level;
14988             mInitStepMode = mCurStepMode;
14989             mModStepMode = 0;
14990             scheduleNextResetWhilePluggedInCheck();
14991         }
14992         if (doWrite || (mLastWriteTimeMs + (60 * 1000)) < mSecRealtime) {
14993             if (mStatsFile != null && !mHistory.isReadOnly()) {
14994                 writeAsyncLocked();
14995             }
14996         }
14997     }
14998 
14999     private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
15000         if (mExternalSync != null) {
15001             mExternalSync.scheduleSync(reason, updateFlags);
15002         }
15003     }
15004 
15005     // This should probably be exposed in the API, though it's not critical
15006     public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
15007 
15008     @GuardedBy("this")
15009     public void setBatteryStateLocked(final int status, final int health, final int plugType,
15010             final int level, /* not final */ int temp, final int voltageMv, final int chargeUah,
15011             final int chargeFullUah, final long chargeTimeToFullSeconds,
15012             final long elapsedRealtimeMs, final long uptimeMs, final long currentTimeMs) {
15013 
15014         // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
15015         temp = Math.max(0, temp);
15016 
15017         reportChangesToStatsLog(status, plugType, level);
15018 
15019         final boolean onBattery = isOnBattery(plugType, status);
15020         if (!mHaveBatteryLevel) {
15021             mHaveBatteryLevel = true;
15022             // We start out assuming that the device is plugged in (not
15023             // on battery).  If our first report is now that we are indeed
15024             // plugged in, then twiddle our state to correctly reflect that
15025             // since we won't be going through the full setOnBattery().
15026             if (onBattery == mOnBattery) {
15027                 mHistory.setPluggedInState(!onBattery);
15028             }
15029             mBatteryStatus = status;
15030             mBatteryLevel = level;
15031             mBatteryChargeUah = chargeUah;
15032 
15033             // Always start out assuming charging, that will be updated later.
15034             mHistory.setBatteryState(true /* charging */, status, level, chargeUah);
15035 
15036             mMaxChargeStepLevel = mMinDischargeStepLevel =
15037                     mLastChargeStepLevel = mLastDischargeStepLevel = level;
15038         } else if (mBatteryLevel != level || mOnBattery != onBattery) {
15039             recordDailyStatsIfNeededLocked(level >= 100 && onBattery, currentTimeMs);
15040         }
15041         int oldStatus = mBatteryStatus;
15042         if (onBattery) {
15043             mDischargeCurrentLevel = level;
15044             if (!mHistory.isRecordingHistory()) {
15045                 mHistory.startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
15046             }
15047         } else if (level < 96 &&
15048                 status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
15049             if (!mHistory.isRecordingHistory()) {
15050                 mHistory.startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
15051             }
15052         }
15053         if (mDischargePlugLevel < 0) {
15054             mDischargePlugLevel = level;
15055         }
15056 
15057         if (onBattery != mOnBattery) {
15058             mBatteryLevel = level;
15059             mBatteryStatus = status;
15060             mBatteryHealth = health;
15061             mBatteryPlugType = plugType;
15062             mBatteryTemperature = temp;
15063             mBatteryVoltageMv = voltageMv;
15064             mHistory.setBatteryState(status, level, health, plugType, temp, voltageMv, chargeUah);
15065             if (chargeUah < mBatteryChargeUah) {
15066                 // Only record discharges
15067                 final long chargeDiff = (long) mBatteryChargeUah - chargeUah;
15068                 mDischargeCounter.addCountLocked(chargeDiff);
15069                 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
15070                 if (Display.isDozeState(mScreenState)) {
15071                     mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
15072                 }
15073                 if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
15074                     mDischargeLightDozeCounter.addCountLocked(chargeDiff);
15075                 } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
15076                     mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
15077                 }
15078             }
15079             mBatteryChargeUah = chargeUah;
15080             setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUah);
15081         } else {
15082             boolean changed = false;
15083             if (mBatteryLevel != level) {
15084                 mBatteryLevel = level;
15085                 changed = true;
15086 
15087                 // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
15088                 // which will pull external stats.
15089                 mExternalSync.scheduleSyncDueToBatteryLevelChange(
15090                         mConstants.BATTERY_LEVEL_COLLECTION_DELAY_MS);
15091             }
15092             if (mBatteryStatus != status) {
15093                 mBatteryStatus = status;
15094                 changed = true;
15095             }
15096             if (mBatteryHealth != health) {
15097                 mBatteryHealth = health;
15098                 changed = true;
15099             }
15100             if (mBatteryPlugType != plugType) {
15101                 mBatteryPlugType = plugType;
15102                 changed = true;
15103             }
15104             if (temp >= (mBatteryTemperature + 10)
15105                     || temp <= (mBatteryTemperature - 10)) {
15106                 mBatteryTemperature = temp;
15107                 changed = true;
15108             }
15109             if (voltageMv > (mBatteryVoltageMv + 20)
15110                     || voltageMv < (mBatteryVoltageMv - 20)) {
15111                 mBatteryVoltageMv = voltageMv;
15112                 changed = true;
15113             }
15114             if (chargeUah >= (mBatteryChargeUah + 10)
15115                     || chargeUah <= (mBatteryChargeUah - 10)) {
15116                 if (chargeUah < mBatteryChargeUah) {
15117                     // Only record discharges
15118                     final long chargeDiff = (long) mBatteryChargeUah - chargeUah;
15119                     mDischargeCounter.addCountLocked(chargeDiff);
15120                     mDischargeScreenOffCounter.addCountLocked(chargeDiff);
15121                     if (Display.isDozeState(mScreenState)) {
15122                         mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
15123                     }
15124                     if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
15125                         mDischargeLightDozeCounter.addCountLocked(chargeDiff);
15126                     } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
15127                         mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
15128                     }
15129                 }
15130                 mBatteryChargeUah = chargeUah;
15131                 changed = true;
15132             }
15133 
15134             long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
15135                     | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
15136                     | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
15137             if (onBattery) {
15138                 changed |= setChargingLocked(false);
15139                 if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
15140                     mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
15141                             modeBits, elapsedRealtimeMs);
15142                     mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
15143                             modeBits, elapsedRealtimeMs);
15144                     mLastDischargeStepLevel = level;
15145                     mMinDischargeStepLevel = level;
15146                     mInitStepMode = mCurStepMode;
15147                     mModStepMode = 0;
15148                 }
15149             } else {
15150                 if (level >= mConstants.BATTERY_CHARGING_ENFORCE_LEVEL) {
15151                     // If the battery level is at least Constants.BATTERY_CHARGING_ENFORCE_LEVEL,
15152                     // always consider the device to be charging even if it happens to go down a
15153                     // level.
15154                     changed |= setChargingLocked(true);
15155                 } else if (!mCharging) {
15156                     if (mLastChargeStepLevel < level) {
15157                         // We have not reported that we are charging, but the level has gone up,
15158                         // but we would like to not have tons of activity from charging-constraint
15159                         // jobs, so instead of reporting ACTION_CHARGING immediately, we defer it.
15160                         if (!mHandler.hasCallbacks(mDeferSetCharging)) {
15161                             mHandler.postDelayed(
15162                                     mDeferSetCharging,
15163                                     mConstants.BATTERY_CHARGED_DELAY_MS);
15164                         }
15165                     } else if (mLastChargeStepLevel > level) {
15166                         // if we had deferred a runnable due to charge level increasing, but then
15167                         // later the charge level drops (could be due to thermal issues), we don't
15168                         // want to trigger the deferred runnable, so remove it here
15169                         mHandler.removeCallbacks(mDeferSetCharging);
15170                     }
15171                 } else {
15172                     if (mLastChargeStepLevel > level) {
15173                         // We had reported that the device was charging, but here we are with
15174                         // power connected and the level going down.  Looks like the current
15175                         // power supplied isn't enough, so consider the device to now be
15176                         // discharging.
15177                         changed |= setChargingLocked(false);
15178                     }
15179                 }
15180                 if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
15181                     mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
15182                             modeBits, elapsedRealtimeMs);
15183                     mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
15184                             modeBits, elapsedRealtimeMs);
15185                     mMaxChargeStepLevel = level;
15186                     mInitStepMode = mCurStepMode;
15187                     mModStepMode = 0;
15188                 }
15189                 mLastChargeStepLevel = level;
15190             }
15191             if (changed) {
15192                 mHistory.setBatteryState(mBatteryStatus, mBatteryLevel, mBatteryHealth,
15193                         mBatteryPlugType, mBatteryTemperature, mBatteryVoltageMv,
15194                         mBatteryChargeUah);
15195                 mHistory.writeHistoryItem(elapsedRealtimeMs, uptimeMs);
15196             }
15197         }
15198         if (!onBattery &&
15199                 (status == BatteryManager.BATTERY_STATUS_FULL ||
15200                         status == BatteryManager.BATTERY_STATUS_UNKNOWN)) {
15201             // We don't record history while we are plugged in and fully charged
15202             // (or when battery is not present).  The next time we are
15203             // unplugged, history will be cleared.
15204             mHistory.setHistoryRecordingEnabled(DEBUG);
15205         }
15206 
15207         mLastLearnedBatteryCapacityUah = chargeFullUah;
15208         if (mMinLearnedBatteryCapacityUah == -1) {
15209             mMinLearnedBatteryCapacityUah = chargeFullUah;
15210         } else {
15211             mMinLearnedBatteryCapacityUah = Math.min(mMinLearnedBatteryCapacityUah, chargeFullUah);
15212         }
15213         mMaxLearnedBatteryCapacityUah = Math.max(mMaxLearnedBatteryCapacityUah, chargeFullUah);
15214 
15215         mBatteryTimeToFullSeconds = chargeTimeToFullSeconds;
15216     }
15217 
15218     public static boolean isOnBattery(int plugType, int status) {
15219         return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN;
15220     }
15221 
15222     // Inform StatsLog of setBatteryState changes.
15223     private void reportChangesToStatsLog(final int status, final int plugType, final int level) {
15224         if (!mHaveBatteryLevel || mBatteryStatus != status) {
15225             mFrameworkStatsLogger.chargingStateChanged(status);
15226         }
15227         if (!mHaveBatteryLevel || mBatteryPlugType != plugType) {
15228             mFrameworkStatsLogger.pluggedStateChanged(plugType);
15229         }
15230         if (!mHaveBatteryLevel || mBatteryLevel != level) {
15231             mFrameworkStatsLogger.batteryLevelChanged(level);
15232         }
15233     }
15234 
15235     public long getAwakeTimeBattery() {
15236         // This previously evaluated to mOnBatteryTimeBase.getUptime(getBatteryUptimeLocked());
15237         // for over a decade, but surely that was a mistake.
15238         return getBatteryUptimeLocked(mClock.uptimeMillis());
15239     }
15240 
15241     public long getAwakeTimePlugged() {
15242         return (mClock.uptimeMillis() * 1000) - getAwakeTimeBattery();
15243     }
15244 
15245     @Override
15246     public long computeUptime(long curTimeUs, int which) {
15247         return mUptimeUs + (curTimeUs - mUptimeStartUs);
15248     }
15249 
15250     @Override
15251     public long computeRealtime(long curTimeUs, int which) {
15252         return mRealtimeUs + (curTimeUs - mRealtimeStartUs);
15253     }
15254 
15255     @Override
15256     public long computeBatteryUptime(long curTimeUs, int which) {
15257         return mOnBatteryTimeBase.computeUptime(curTimeUs, which);
15258     }
15259 
15260     @Override
15261     public long computeBatteryRealtime(long curTimeUs, int which) {
15262         return mOnBatteryTimeBase.computeRealtime(curTimeUs, which);
15263     }
15264 
15265     @Override
15266     public long computeBatteryScreenOffUptime(long curTimeUs, int which) {
15267         return mOnBatteryScreenOffTimeBase.computeUptime(curTimeUs, which);
15268     }
15269 
15270     @Override
15271     public long computeBatteryScreenOffRealtime(long curTimeUs, int which) {
15272         return mOnBatteryScreenOffTimeBase.computeRealtime(curTimeUs, which);
15273     }
15274 
15275     @Override
15276     public long computeBatteryTimeRemaining(long curTime) {
15277         if (!mOnBattery) {
15278             return -1;
15279         }
15280         /* Simple implementation just looks at the average discharge per level across the
15281            entire sample period.
15282         int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
15283         if (discharge < 2) {
15284             return -1;
15285         }
15286         long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
15287         if (duration < 1000*1000) {
15288             return -1;
15289         }
15290         long usPerLevel = duration/discharge;
15291         return usPerLevel * mCurrentBatteryLevel;
15292         */
15293         if (mDischargeStepTracker.mNumStepDurations < 1) {
15294             return -1;
15295         }
15296         long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
15297         if (msPerLevel <= 0) {
15298             return -1;
15299         }
15300         return (msPerLevel * mBatteryLevel) * 1000;
15301     }
15302 
15303     @Override
15304     public LevelStepTracker getDischargeLevelStepTracker() {
15305         return mDischargeStepTracker;
15306     }
15307 
15308     @Override
15309     public LevelStepTracker getDailyDischargeLevelStepTracker() {
15310         return mDailyDischargeStepTracker;
15311     }
15312 
15313     @Override
15314     public long computeChargeTimeRemaining(long curTime) {
15315         if (mOnBattery) {
15316             // Not yet working.
15317             return -1;
15318         }
15319         if (mBatteryTimeToFullSeconds >= 0) {
15320             return mBatteryTimeToFullSeconds * (1000 * 1000); // s to us
15321         }
15322         // Else use algorithmic approach
15323         if (mChargeStepTracker.mNumStepDurations < 1) {
15324             return -1;
15325         }
15326         long msPerLevel = mChargeStepTracker.computeTimePerLevel();
15327         if (msPerLevel <= 0) {
15328             return -1;
15329         }
15330         return (msPerLevel * (100 - mBatteryLevel)) * 1000;
15331     }
15332 
15333     /*@hide */
15334     public CellularBatteryStats getCellularBatteryStats() {
15335         final int which = STATS_SINCE_CHARGED;
15336         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
15337         final ControllerActivityCounter counter = getModemControllerActivity();
15338         final long sleepTimeMs = counter.getSleepTimeCounter().getCountLocked(which);
15339         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
15340         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
15341         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
15342         final long monitoredRailChargeConsumedMaMs =
15343                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
15344         long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
15345         for (int i = 0; i < timeInRatMs.length; i++) {
15346             timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTimeUs, which) / 1000;
15347         }
15348         long[] timeInRxSignalStrengthLevelMs =
15349                 new long[CELL_SIGNAL_STRENGTH_LEVEL_COUNT];
15350         for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
15351             timeInRxSignalStrengthLevelMs[i] =
15352                 getPhoneSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
15353         }
15354         long[] txTimeMs = new long[Math.min(MODEM_TX_POWER_LEVEL_COUNT,
15355             counter.getTxTimeCounters().length)];
15356         long totalTxTimeMs = 0;
15357         for (int i = 0; i < txTimeMs.length; i++) {
15358             txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
15359             totalTxTimeMs += txTimeMs[i];
15360         }
15361 
15362         return new CellularBatteryStats(computeBatteryRealtime(rawRealTimeUs, which) / 1000,
15363                 getMobileRadioActiveTime(rawRealTimeUs, which) / 1000,
15364                 getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which),
15365                 getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which),
15366                 getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which),
15367                 getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which),
15368                 sleepTimeMs, idleTimeMs, rxTimeMs, energyConsumedMaMs, timeInRatMs,
15369                 timeInRxSignalStrengthLevelMs, txTimeMs,
15370                 monitoredRailChargeConsumedMaMs);
15371     }
15372 
15373     /*@hide */
15374     public WifiBatteryStats getWifiBatteryStats() {
15375         final int which = STATS_SINCE_CHARGED;
15376         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
15377         final ControllerActivityCounter counter = getWifiControllerActivity();
15378         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
15379         final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which);
15380         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
15381         final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which);
15382         final long totalControllerActivityTimeMs
15383                 = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000;
15384         final long sleepTimeMs
15385                 = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs);
15386         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
15387         final long monitoredRailChargeConsumedMaMs =
15388                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
15389         long numAppScanRequest = 0;
15390         for (int i = 0; i < mUidStats.size(); i++) {
15391             numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which);
15392         }
15393         long[] timeInStateMs = new long[NUM_WIFI_STATES];
15394         for (int i=0; i<NUM_WIFI_STATES; i++) {
15395             timeInStateMs[i] = getWifiStateTime(i, rawRealTimeUs, which) / 1000;
15396         }
15397         long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES];
15398         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
15399             timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTimeUs, which) / 1000;
15400         }
15401         long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS];
15402         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
15403             timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
15404         }
15405         return new WifiBatteryStats(
15406                 computeBatteryRealtime(rawRealTimeUs, which) / 1000,
15407                 getWifiActiveTime(rawRealTimeUs, which) / 1000,
15408                 getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which),
15409                 getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which),
15410                 getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which),
15411                 getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which),
15412                 sleepTimeMs, scanTimeMs, idleTimeMs, rxTimeMs, txTimeMs, energyConsumedMaMs,
15413                 numAppScanRequest, timeInStateMs, timeSignalStrengthTimeMs, timeInSupplStateMs,
15414                 monitoredRailChargeConsumedMaMs);
15415     }
15416 
15417     /*@hide */
15418     public GpsBatteryStats getGpsBatteryStats() {
15419         GpsBatteryStats s = new GpsBatteryStats();
15420         final int which = STATS_SINCE_CHARGED;
15421         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
15422         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTimeUs, which) / 1000);
15423         s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
15424         long[] time = new long[mGpsSignalQualityTimer.length];
15425         for (int i=0; i<time.length; i++) {
15426             time[i] = getGpsSignalQualityTime(i, rawRealTimeUs, which) / 1000;
15427         }
15428         s.setTimeInGpsSignalQualityLevel(time);
15429         return s;
15430     }
15431 
15432     @Override
15433     public LevelStepTracker getChargeLevelStepTracker() {
15434         return mChargeStepTracker;
15435     }
15436 
15437     @Override
15438     public LevelStepTracker getDailyChargeLevelStepTracker() {
15439         return mDailyChargeStepTracker;
15440     }
15441 
15442     @Override
15443     public ArrayList<PackageChange> getDailyPackageChanges() {
15444         return mDailyPackageChanges;
15445     }
15446 
15447     /**
15448      * @return battery uptime in microseconds
15449      */
15450     protected long getBatteryUptimeLocked(long uptimeMs) {
15451         return mOnBatteryTimeBase.getUptime(uptimeMs * 1000);
15452     }
15453 
15454     @Override
15455     public long getBatteryUptime(long curTimeUs) {
15456         return mOnBatteryTimeBase.getUptime(curTimeUs);
15457     }
15458 
15459     @Override
15460     public long getBatteryRealtime(long curTimeUs) {
15461         return mOnBatteryTimeBase.getRealtime(curTimeUs);
15462     }
15463 
15464     @Override
15465     public int getDischargeStartLevel() {
15466         synchronized(this) {
15467             return getDischargeStartLevelLocked();
15468         }
15469     }
15470 
15471     public int getDischargeStartLevelLocked() {
15472             return mDischargeUnplugLevel;
15473     }
15474 
15475     @Override
15476     public int getDischargeCurrentLevel() {
15477         synchronized(this) {
15478             return getDischargeCurrentLevelLocked();
15479         }
15480     }
15481 
15482     public int getDischargeCurrentLevelLocked() {
15483         return mDischargeCurrentLevel;
15484     }
15485 
15486     @Override
15487     public int getLowDischargeAmountSinceCharge() {
15488         synchronized(this) {
15489             int val = mLowDischargeAmountSinceCharge;
15490             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
15491                 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
15492             }
15493             return val;
15494         }
15495     }
15496 
15497     @Override
15498     public int getHighDischargeAmountSinceCharge() {
15499         synchronized(this) {
15500             int val = mHighDischargeAmountSinceCharge;
15501             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
15502                 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
15503             }
15504             return val;
15505         }
15506     }
15507 
15508     @Override
15509     public int getDischargeAmount(int which) {
15510         int dischargeAmount = which == STATS_SINCE_CHARGED
15511                 ? getHighDischargeAmountSinceCharge()
15512                 : (getDischargeStartLevel() - getDischargeCurrentLevel());
15513         if (dischargeAmount < 0) {
15514             dischargeAmount = 0;
15515         }
15516         return dischargeAmount;
15517     }
15518 
15519     @Override
15520     public int getDischargeAmountScreenOn() {
15521         synchronized(this) {
15522             int val = mDischargeAmountScreenOn;
15523             if (mOnBattery && Display.isOnState(mScreenState)
15524                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
15525                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
15526             }
15527             return val;
15528         }
15529     }
15530 
15531     @Override
15532     public int getDischargeAmountScreenOnSinceCharge() {
15533         synchronized(this) {
15534             int val = mDischargeAmountScreenOnSinceCharge;
15535             if (mOnBattery && Display.isOnState(mScreenState)
15536                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
15537                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
15538             }
15539             return val;
15540         }
15541     }
15542 
15543     @Override
15544     public int getDischargeAmountScreenOff() {
15545         synchronized(this) {
15546             int val = mDischargeAmountScreenOff;
15547             if (mOnBattery && Display.isOffState(mScreenState)
15548                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
15549                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
15550             }
15551             // For backward compatibility, doze discharge is counted into screen off.
15552             return val + getDischargeAmountScreenDoze();
15553         }
15554     }
15555 
15556     @Override
15557     public int getDischargeAmountScreenOffSinceCharge() {
15558         synchronized(this) {
15559             int val = mDischargeAmountScreenOffSinceCharge;
15560             if (mOnBattery && Display.isOffState(mScreenState)
15561                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
15562                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
15563             }
15564             // For backward compatibility, doze discharge is counted into screen off.
15565             return val + getDischargeAmountScreenDozeSinceCharge();
15566         }
15567     }
15568 
15569     @Override
15570     public int getDischargeAmountScreenDoze() {
15571         synchronized(this) {
15572             int val = mDischargeAmountScreenDoze;
15573             if (mOnBattery && Display.isDozeState(mScreenState)
15574                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
15575                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
15576             }
15577             return val;
15578         }
15579     }
15580 
15581     @Override
15582     public int getDischargeAmountScreenDozeSinceCharge() {
15583         synchronized(this) {
15584             int val = mDischargeAmountScreenDozeSinceCharge;
15585             if (mOnBattery && Display.isDozeState(mScreenState)
15586                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
15587                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
15588             }
15589             return val;
15590         }
15591     }
15592 
15593 
15594     /**
15595      * Estimates the time spent by the system server handling incoming binder requests.
15596      */
15597     @Override
15598     public long[] getSystemServiceTimeAtCpuSpeeds() {
15599         if (mBinderThreadCpuTimesUs == null) {
15600             return null;
15601         }
15602 
15603         return mBinderThreadCpuTimesUs.getCountsLocked(BatteryStats.STATS_SINCE_CHARGED);
15604     }
15605 
15606     /**
15607      * Retrieve the statistics object for a particular uid, creating if needed.
15608      */
15609     public Uid getUidStatsLocked(int uid) {
15610         return getUidStatsLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
15611     }
15612 
15613     public Uid getUidStatsLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
15614         Uid u = mUidStats.get(uid);
15615         if (u == null) {
15616             if (Process.isSdkSandboxUid(uid)) {
15617                 Log.wtf(TAG, "Tracking an SDK Sandbox UID");
15618             }
15619             u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
15620             mUidStats.put(uid, u);
15621         }
15622         return u;
15623     }
15624 
15625     /**
15626      * Retrieve the statistics object for a particular uid. Returns null if the object is not
15627      * available.
15628      */
15629     public Uid getAvailableUidStatsLocked(int uid) {
15630         Uid u = mUidStats.get(uid);
15631         return u;
15632     }
15633 
15634     @GuardedBy("this")
15635     public void onCleanupUserLocked(int userId, long elapsedRealtimeMs) {
15636         final int firstUidForUser = UserHandle.getUid(userId, 0);
15637         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
15638         mPendingRemovedUids.add(
15639                 new UidToRemove(firstUidForUser, lastUidForUser, elapsedRealtimeMs));
15640     }
15641 
15642     @GuardedBy("this")
15643     public void onUserRemovedLocked(int userId) {
15644         if (mExternalSync != null) {
15645             // Clear out the removed user's UIDs after a short delay. The delay is needed
15646             // because at the point that this method is called, some activities are still
15647             // being wrapped up by those UIDs
15648             mExternalSync.scheduleCleanupDueToRemovedUser(userId);
15649         }
15650     }
15651 
15652     /**
15653      * Removes battery stats for UIDs corresponding to a removed user.
15654      */
15655     @GuardedBy("this")
15656     public void clearRemovedUserUidsLocked(int userId) {
15657         final int firstUidForUser = UserHandle.getUid(userId, 0);
15658         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
15659         mUidStats.put(firstUidForUser, null);
15660         mUidStats.put(lastUidForUser, null);
15661         final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
15662         final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
15663         for (int i = firstIndex; i <= lastIndex; i++) {
15664             final Uid uid = mUidStats.valueAt(i);
15665             if (uid != null) {
15666                 uid.detachFromTimeBase();
15667             }
15668         }
15669         mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
15670         removeCpuStatsForUidRangeLocked(firstUidForUser, lastUidForUser);
15671     }
15672 
15673     /**
15674      * @see #removeUidStatsLocked(int)
15675      */
15676     @GuardedBy("this")
15677     public void removeUidStatsLocked(int uid, long elapsedRealtimeMs) {
15678         final Uid u = mUidStats.get(uid);
15679         if (u != null) {
15680             u.detachFromTimeBase();
15681         }
15682         mUidStats.remove(uid);
15683         mPendingRemovedUids.add(new UidToRemove(uid, elapsedRealtimeMs));
15684     }
15685 
15686     /**
15687      * Removes the data for the deleted UIDs from the underlying kernel eBPF tables.
15688      */
15689     @GuardedBy("this")
15690     private void removeCpuStatsForUidRangeLocked(int startUid, int endUid) {
15691         if (startUid == endUid) {
15692             mCpuUidUserSysTimeReader.removeUid(startUid);
15693             mCpuUidFreqTimeReader.removeUid(startUid);
15694             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
15695                 mCpuUidActiveTimeReader.removeUid(startUid);
15696                 mCpuUidClusterTimeReader.removeUid(startUid);
15697             }
15698             if (mKernelSingleUidTimeReader != null) {
15699                 mKernelSingleUidTimeReader.removeUid(startUid);
15700             }
15701             mNumUidsRemoved++;
15702         } else if (startUid < endUid) {
15703             mCpuUidFreqTimeReader.removeUidsInRange(startUid, endUid);
15704             mCpuUidUserSysTimeReader.removeUidsInRange(startUid, endUid);
15705             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
15706                 mCpuUidActiveTimeReader.removeUidsInRange(startUid, endUid);
15707                 mCpuUidClusterTimeReader.removeUidsInRange(startUid, endUid);
15708             }
15709             if (mKernelSingleUidTimeReader != null) {
15710                 mKernelSingleUidTimeReader.removeUidsInRange(startUid, endUid);
15711             }
15712             mPowerStatsUidResolver.releaseUidsInRange(startUid, endUid);
15713             // Treat as one. We don't know how many uids there are in between.
15714             mNumUidsRemoved++;
15715         } else {
15716             Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
15717         }
15718     }
15719 
15720     /**
15721      * Retrieve the statistics object for a particular process, creating
15722      * if needed.
15723      */
15724     public Uid.Proc getProcessStatsLocked(int uid, String name,
15725             long elapsedRealtimeMs, long uptimeMs) {
15726         uid = mapUid(uid);
15727         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
15728         return u.getProcessStatsLocked(name);
15729     }
15730 
15731     /**
15732      * Retrieve the statistics object for a particular process, creating
15733      * if needed.
15734      */
15735     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
15736         return getPackageStatsLocked(uid, pkg, mClock.elapsedRealtime(), mClock.uptimeMillis());
15737     }
15738 
15739     /**
15740      * @see getPackageStatsLocked(int, String)
15741      */
15742     public Uid.Pkg getPackageStatsLocked(int uid, String pkg,
15743             long elapsedRealtimeMs, long uptimeMs) {
15744         uid = mapUid(uid);
15745         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
15746         return u.getPackageStatsLocked(pkg);
15747     }
15748 
15749     /**
15750      * Retrieve the statistics object for a particular service, creating
15751      * if needed.
15752      */
15753     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name,
15754             long elapsedRealtimeMs, long uptimeMs) {
15755         uid = mapUid(uid);
15756         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
15757         return u.getServiceStatsLocked(pkg, name);
15758     }
15759 
15760     @GuardedBy("this")
15761     public void shutdownLocked() {
15762         mHistory.recordShutdownEvent(mClock.elapsedRealtime(), mClock.uptimeMillis(),
15763                 mClock.currentTimeMillis());
15764         writeSyncLocked();
15765         mShuttingDown = true;
15766     }
15767 
15768     @Override
15769     public boolean isProcessStateDataAvailable() {
15770         synchronized (this) {
15771             return trackPerProcStateCpuTimes();
15772         }
15773     }
15774 
15775     @GuardedBy("this")
15776     private boolean trackPerProcStateCpuTimes() {
15777         return mCpuUidFreqTimeReader.isFastCpuTimesReader();
15778     }
15779 
15780     /**
15781      * Enables or disables the PowerStatsCollector mode.
15782      */
15783     public void setPowerStatsCollectorEnabled(@BatteryConsumer.PowerComponent int powerComponent,
15784             boolean enabled) {
15785         synchronized (this) {
15786             mPowerStatsCollectorEnabled.put(powerComponent, enabled);
15787         }
15788     }
15789 
15790     @GuardedBy("this")
15791     public void systemServicesReady(Context context) {
15792         mConstants.startObserving(context.getContentResolver());
15793         registerUsbStateReceiver(context);
15794 
15795         synchronized (this) {
15796             mAlarmManager = context.getSystemService(AlarmManager.class);
15797             if (mBatteryPluggedIn) {
15798                 // Already plugged in. Schedule the long plug in alarm.
15799                 scheduleNextResetWhilePluggedInCheck();
15800             }
15801         }
15802     }
15803 
15804     /**
15805      * Initialize the EnergyConsumer stats data structures.
15806      *
15807      * @param supportedStandardBuckets boolean array indicating which {@link StandardPowerBucket}s
15808      *                                 are currently supported. If null, none are supported
15809      *                                 (regardless of customBucketNames).
15810      * @param customBucketNames        names of custom (OTHER) EnergyConsumers on this device
15811      */
15812     @GuardedBy("this")
15813     public void initEnergyConsumerStatsLocked(@Nullable boolean[] supportedStandardBuckets,
15814             String[] customBucketNames) {
15815         final int numDisplays = mPerDisplayBatteryStats.length;
15816         for (int i = 0; i < numDisplays; i++) {
15817             final int screenState = mPerDisplayBatteryStats[i].screenState;
15818             mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState;
15819         }
15820 
15821         if (supportedStandardBuckets != null) {
15822             final EnergyConsumerStats.Config config = new EnergyConsumerStats.Config(
15823                     supportedStandardBuckets, customBucketNames,
15824                     SUPPORTED_PER_PROCESS_STATE_STANDARD_ENERGY_BUCKETS,
15825                     getBatteryConsumerProcessStateNames());
15826 
15827             if (mEnergyConsumerStatsConfig != null
15828                     &&  !mEnergyConsumerStatsConfig.isCompatible(config)) {
15829                 // Supported power buckets changed since last boot.
15830                 // Existing data is no longer reliable.
15831                 resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
15832                         RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE);
15833             }
15834 
15835             mEnergyConsumerStatsConfig = config;
15836             mGlobalEnergyConsumerStats = new EnergyConsumerStats(config);
15837 
15838             if (supportedStandardBuckets[EnergyConsumerStats.POWER_BUCKET_BLUETOOTH]) {
15839                 mBluetoothPowerCalculator = new BluetoothPowerCalculator(mPowerProfile);
15840             }
15841             if (supportedStandardBuckets[EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO]) {
15842                 mMobileRadioPowerCalculator = new MobileRadioPowerCalculator(mPowerProfile);
15843             }
15844             if (supportedStandardBuckets[EnergyConsumerStats.POWER_BUCKET_WIFI]) {
15845                 mWifiPowerCalculator = new WifiPowerCalculator(mPowerProfile);
15846             }
15847         } else {
15848             if (mEnergyConsumerStatsConfig != null) {
15849                 // EnergyConsumer no longer supported, wipe out the existing data.
15850                 resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
15851                         RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE);
15852             }
15853             mEnergyConsumerStatsConfig = null;
15854             mGlobalEnergyConsumerStats = null;
15855         }
15856     }
15857 
15858     @GuardedBy("this")
15859     private boolean isMobileRadioEnergyConsumerSupportedLocked() {
15860         if (mGlobalEnergyConsumerStats == null) return false;
15861         return mGlobalEnergyConsumerStats.isStandardBucketSupported(
15862                 EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO);
15863     }
15864 
15865     @NonNull
15866     private static String[] getBatteryConsumerProcessStateNames() {
15867         String[] procStateNames = new String[BatteryConsumer.PROCESS_STATE_COUNT];
15868         for (int procState = 0; procState < BatteryConsumer.PROCESS_STATE_COUNT; procState++) {
15869             procStateNames[procState] = BatteryConsumer.processStateToString(procState);
15870         }
15871         return procStateNames;
15872     }
15873 
15874     /** Get the last known Battery voltage (in millivolts), returns -1 if unknown */
15875     @GuardedBy("this")
15876     public int getBatteryVoltageMvLocked() {
15877         return mBatteryVoltageMv;
15878     }
15879 
15880     @VisibleForTesting
15881     public final class Constants extends ContentObserver {
15882         public static final String KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME
15883                 = "track_cpu_active_cluster_time";
15884         public static final String KEY_KERNEL_UID_READERS_THROTTLE_TIME
15885                 = "kernel_uid_readers_throttle_time";
15886         public static final String KEY_UID_REMOVE_DELAY_MS
15887                 = "uid_remove_delay_ms";
15888         public static final String KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
15889                 = "external_stats_collection_rate_limit_ms";
15890         public static final String KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS
15891                 = "battery_level_collection_delay_ms";
15892         public static final String KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS =
15893                 "procstate_change_collection_delay_ms";
15894         public static final String KEY_MAX_HISTORY_FILES = "max_history_files";
15895         public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
15896         public static final String KEY_BATTERY_CHARGED_DELAY_MS =
15897                 "battery_charged_delay_ms";
15898         public static final String KEY_BATTERY_CHARGING_ENFORCE_LEVEL =
15899                 "battery_charging_enforce_level";
15900         public static final String KEY_PER_UID_MODEM_POWER_MODEL =
15901                 "per_uid_modem_power_model";
15902         public static final String KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION =
15903                 "phone_on_external_stats_collection";
15904         public static final String KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS =
15905                 "reset_while_plugged_in_minimum_duration_hours";
15906 
15907         public static final String PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME =
15908                 "mobile_radio_active_time";
15909         public static final String PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME =
15910                 "modem_activity_info_rx_tx";
15911 
15912         /** Convert {@link PerUidModemPowerModel} to string */
15913         public String getPerUidModemModelName(@PerUidModemPowerModel int model) {
15914             switch(model) {
15915                 case PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME:
15916                     return PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME;
15917                 case PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX:
15918                     return PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME;
15919                 default:
15920                     Slog.w(TAG, "Unexpected per uid modem model (" + model + ")");
15921                     return "unknown_" + model;
15922             }
15923         }
15924 
15925         /** Convert string to {@link PerUidModemPowerModel} */
15926         @PerUidModemPowerModel
15927         public int getPerUidModemModel(String name) {
15928             switch(name) {
15929                 case PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME:
15930                     return PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME;
15931                 case PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME:
15932                     return PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX;
15933                 default:
15934                     Slog.w(TAG, "Unexpected per uid modem model name (" + name + ")");
15935                     return DEFAULT_PER_UID_MODEM_MODEL;
15936             }
15937         }
15938 
15939         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
15940         private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000;
15941         private static final long DEFAULT_UID_REMOVE_DELAY_MS = 5L * 60L * 1000L;
15942         private static final long DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = 600_000;
15943         private static final long DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS = 300_000;
15944         private static final long DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS = 60_000;
15945         private static final int DEFAULT_MAX_HISTORY_FILES = 32;
15946         private static final int DEFAULT_MAX_HISTORY_BUFFER_KB = 128; /*Kilo Bytes*/
15947         private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64;
15948         private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
15949         private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
15950         private static final int DEFAULT_BATTERY_CHARGING_ENFORCE_LEVEL = 90;
15951         @PerUidModemPowerModel
15952         private static final int DEFAULT_PER_UID_MODEM_MODEL =
15953                 PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX;
15954         private static final boolean DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION = true;
15955         // Little less than 2 days
15956         private static final int DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS = 47;
15957 
15958         public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
15959         /* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
15960          * update when startObserving. */
15961         public long KERNEL_UID_READERS_THROTTLE_TIME;
15962         public long UID_REMOVE_DELAY_MS = DEFAULT_UID_REMOVE_DELAY_MS;
15963         public long EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
15964                 = DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
15965         public long BATTERY_LEVEL_COLLECTION_DELAY_MS
15966                 = DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS;
15967         public long PROC_STATE_CHANGE_COLLECTION_DELAY_MS =
15968                 DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS;
15969         public int MAX_HISTORY_FILES;
15970         public int MAX_HISTORY_BUFFER; /*Bytes*/
15971         public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
15972         public int BATTERY_CHARGING_ENFORCE_LEVEL = DEFAULT_BATTERY_CHARGING_ENFORCE_LEVEL;
15973         public int PER_UID_MODEM_MODEL = DEFAULT_PER_UID_MODEM_MODEL;
15974         public boolean PHONE_ON_EXTERNAL_STATS_COLLECTION =
15975                 DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION;
15976         public int RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS =
15977                 DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS;
15978 
15979         private ContentResolver mResolver;
15980         private final KeyValueListParser mParser = new KeyValueListParser(',');
15981 
15982         public Constants(Handler handler) {
15983             super(handler);
15984             if (isLowRamDevice()) {
15985                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE;
15986                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB * 1024;
15987             } else {
15988                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES;
15989                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_KB * 1024;
15990             }
15991         }
15992 
15993         public void startObserving(ContentResolver resolver) {
15994             mResolver = resolver;
15995             mResolver.registerContentObserver(
15996                     Settings.Global.getUriFor(Settings.Global.BATTERY_STATS_CONSTANTS),
15997                     false /* notifyForDescendants */, this);
15998             mResolver.registerContentObserver(
15999                     Settings.Global.getUriFor(Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY),
16000                     false /* notifyForDescendants */, this);
16001             mResolver.registerContentObserver(Settings.Global.getUriFor(
16002                             Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL),
16003                     false /* notifyForDescendants */, this);
16004             updateConstants();
16005         }
16006 
16007         @Override
16008         public void onChange(boolean selfChange, Uri uri) {
16009             if (uri.equals(
16010                     Settings.Global.getUriFor(
16011                             Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY))) {
16012                 synchronized (BatteryStatsImpl.this) {
16013                     updateBatteryChargedDelayMsLocked();
16014                 }
16015                 return;
16016             } else if (uri.equals(Settings.Global.getUriFor(
16017                     Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL))) {
16018                 synchronized (BatteryStatsImpl.this) {
16019                     updateBatteryChargingEnforceLevelLocked();
16020                 }
16021                 return;
16022             }
16023             updateConstants();
16024         }
16025 
16026         private void updateConstants() {
16027             synchronized (BatteryStatsImpl.this) {
16028                 try {
16029                     mParser.setString(Settings.Global.getString(mResolver,
16030                             Settings.Global.BATTERY_STATS_CONSTANTS));
16031                 } catch (IllegalArgumentException e) {
16032                     // Failed to parse the settings string, log this and move on
16033                     // with defaults.
16034                     Slog.e(TAG, "Bad batterystats settings", e);
16035                 }
16036 
16037                 TRACK_CPU_ACTIVE_CLUSTER_TIME = mParser.getBoolean(
16038                         KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME, DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME);
16039                 updateKernelUidReadersThrottleTime(KERNEL_UID_READERS_THROTTLE_TIME,
16040                         mParser.getLong(KEY_KERNEL_UID_READERS_THROTTLE_TIME,
16041                                 DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME));
16042                 updateUidRemoveDelay(
16043                         mParser.getLong(KEY_UID_REMOVE_DELAY_MS, DEFAULT_UID_REMOVE_DELAY_MS));
16044                 EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = mParser.getLong(
16045                         KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS,
16046                         DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
16047                 BATTERY_LEVEL_COLLECTION_DELAY_MS = mParser.getLong(
16048                         KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS,
16049                         DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS);
16050                 PROC_STATE_CHANGE_COLLECTION_DELAY_MS = mParser.getLong(
16051                         KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS,
16052                         DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
16053                 MAX_HISTORY_FILES = mParser.getInt(KEY_MAX_HISTORY_FILES,
16054                         isLowRamDevice() ? DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE
16055                                 : DEFAULT_MAX_HISTORY_FILES);
16056                 MAX_HISTORY_BUFFER = mParser.getInt(KEY_MAX_HISTORY_BUFFER_KB,
16057                         isLowRamDevice() ? DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB
16058                                 : DEFAULT_MAX_HISTORY_BUFFER_KB)
16059                         * 1024;
16060                 final String perUidModemModel = mParser.getString(KEY_PER_UID_MODEM_POWER_MODEL,
16061                         "");
16062                 PER_UID_MODEM_MODEL = getPerUidModemModel(perUidModemModel);
16063 
16064                 PHONE_ON_EXTERNAL_STATS_COLLECTION = mParser.getBoolean(
16065                         KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION,
16066                         DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION);
16067 
16068                 RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS = mParser.getInt(
16069                         KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS,
16070                         DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS);
16071 
16072                 updateBatteryChargedDelayMsLocked();
16073                 updateBatteryChargingEnforceLevelLocked();
16074 
16075                 onChange();
16076             }
16077         }
16078 
16079         /**
16080          * Propagates changes in constant values.
16081          */
16082         @VisibleForTesting
16083         public void onChange() {
16084             mHistory.setMaxHistoryFiles(MAX_HISTORY_FILES);
16085             mHistory.setMaxHistoryBufferSize(MAX_HISTORY_BUFFER);
16086         }
16087 
16088         private void updateBatteryChargedDelayMsLocked() {
16089             // a negative value indicates that we should ignore this override
16090             final int delay = Settings.Global.getInt(mResolver,
16091                     Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
16092                     -1);
16093 
16094             BATTERY_CHARGED_DELAY_MS = delay >= 0 ? delay : mParser.getInt(
16095                     KEY_BATTERY_CHARGED_DELAY_MS,
16096                     DEFAULT_BATTERY_CHARGED_DELAY_MS);
16097 
16098             if (mHandler.hasCallbacks(mDeferSetCharging)) {
16099                 mHandler.removeCallbacks(mDeferSetCharging);
16100                 mHandler.postDelayed(mDeferSetCharging, BATTERY_CHARGED_DELAY_MS);
16101             }
16102         }
16103 
16104         private void updateBatteryChargingEnforceLevelLocked() {
16105             int lastChargingEnforceLevel = BATTERY_CHARGING_ENFORCE_LEVEL;
16106             final int level = Settings.Global.getInt(mResolver,
16107                     Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL,
16108                     -1);
16109 
16110             BATTERY_CHARGING_ENFORCE_LEVEL = level >= 0 ? level : mParser.getInt(
16111                     KEY_BATTERY_CHARGING_ENFORCE_LEVEL, DEFAULT_BATTERY_CHARGING_ENFORCE_LEVEL);
16112 
16113             if (BATTERY_CHARGING_ENFORCE_LEVEL <= mLastChargeStepLevel
16114                     && mLastChargeStepLevel < lastChargingEnforceLevel) {
16115                 setChargingLocked(true);
16116             }
16117         }
16118 
16119         private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
16120             KERNEL_UID_READERS_THROTTLE_TIME = newTimeMs;
16121             if (oldTimeMs != newTimeMs) {
16122                 mCpuUidUserSysTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
16123                 mCpuUidFreqTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
16124                 mCpuUidActiveTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
16125                 mCpuUidClusterTimeReader
16126                         .setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
16127             }
16128         }
16129 
16130         @GuardedBy("BatteryStatsImpl.this")
16131         private void updateUidRemoveDelay(long newTimeMs) {
16132             UID_REMOVE_DELAY_MS = newTimeMs;
16133             clearPendingRemovedUidsLocked();
16134         }
16135 
16136         public void dumpLocked(PrintWriter pw) {
16137             pw.print(KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME); pw.print("=");
16138             pw.println(TRACK_CPU_ACTIVE_CLUSTER_TIME);
16139             pw.print(KEY_KERNEL_UID_READERS_THROTTLE_TIME); pw.print("=");
16140             pw.println(KERNEL_UID_READERS_THROTTLE_TIME);
16141             pw.print(KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS); pw.print("=");
16142             pw.println(EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
16143             pw.print(KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS); pw.print("=");
16144             pw.println(BATTERY_LEVEL_COLLECTION_DELAY_MS);
16145             pw.print(KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS); pw.print("=");
16146             pw.println(PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
16147             pw.print(KEY_MAX_HISTORY_FILES); pw.print("=");
16148             pw.println(MAX_HISTORY_FILES);
16149             pw.print(KEY_MAX_HISTORY_BUFFER_KB); pw.print("=");
16150             pw.println(MAX_HISTORY_BUFFER/1024);
16151             pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("=");
16152             pw.println(BATTERY_CHARGED_DELAY_MS);
16153             pw.print(KEY_BATTERY_CHARGING_ENFORCE_LEVEL); pw.print("=");
16154             pw.println(BATTERY_CHARGING_ENFORCE_LEVEL);
16155             pw.print(KEY_PER_UID_MODEM_POWER_MODEL); pw.print("=");
16156             pw.println(getPerUidModemModelName(PER_UID_MODEM_MODEL));
16157             pw.print(KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION); pw.print("=");
16158             pw.println(PHONE_ON_EXTERNAL_STATS_COLLECTION);
16159             pw.print(KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS); pw.print("=");
16160             pw.println(RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS);
16161         }
16162     }
16163 
16164     public long getExternalStatsCollectionRateLimitMs() {
16165         synchronized (this) {
16166             return mConstants.EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
16167         }
16168     }
16169 
16170     @GuardedBy("this")
16171     public void dumpConstantsLocked(PrintWriter pw) {
16172         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
16173         iPw.println("BatteryStats constants:");
16174         iPw.increaseIndent();
16175         mConstants.dumpLocked(iPw);
16176         iPw.decreaseIndent();
16177     }
16178 
16179     @GuardedBy("this")
16180     public void dumpCpuStatsLocked(PrintWriter pw) {
16181         int size = mUidStats.size();
16182         pw.println("Per UID CPU user & system time in ms:");
16183         for (int i = 0; i < size; i++) {
16184             int u = mUidStats.keyAt(i);
16185             Uid uid = mUidStats.get(u);
16186             pw.print("  "); pw.print(u); pw.print(": ");
16187             pw.print(uid.getUserCpuTimeUs(STATS_SINCE_CHARGED) / 1000); pw.print(" ");
16188             pw.println(uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED) / 1000);
16189         }
16190 
16191         pw.println("Per UID CPU active time in ms:");
16192         for (int i = 0; i < size; i++) {
16193             int u = mUidStats.keyAt(i);
16194             Uid uid = mUidStats.get(u);
16195             if (uid.getCpuActiveTime() > 0) {
16196                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(uid.getCpuActiveTime());
16197             }
16198         }
16199         pw.println("Per UID CPU cluster time in ms:");
16200         for (int i = 0; i < size; i++) {
16201             int u = mUidStats.keyAt(i);
16202             long[] times = mUidStats.get(u).getCpuClusterTimes();
16203             if (times != null) {
16204                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
16205             }
16206         }
16207         pw.println("Per UID CPU frequency time in ms:");
16208         for (int i = 0; i < size; i++) {
16209             int u = mUidStats.keyAt(i);
16210             long[] times = mUidStats.get(u).getCpuFreqTimes(STATS_SINCE_CHARGED);
16211             if (times != null) {
16212                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
16213             }
16214         }
16215 
16216         if (!Flags.disableSystemServicePowerAttr()) {
16217             updateSystemServiceCallStats();
16218             if (mBinderThreadCpuTimesUs != null) {
16219                 pw.println("Per UID System server binder time in ms:");
16220                 long[] systemServiceTimeAtCpuSpeeds = getSystemServiceTimeAtCpuSpeeds();
16221                 for (int i = 0; i < size; i++) {
16222                     int u = mUidStats.keyAt(i);
16223                     Uid uid = mUidStats.get(u);
16224                     double proportionalSystemServiceUsage = uid.getProportionalSystemServiceUsage();
16225                     long timeUs = 0;
16226                     for (int j = systemServiceTimeAtCpuSpeeds.length - 1; j >= 0; j--) {
16227                         timeUs += systemServiceTimeAtCpuSpeeds[j] * proportionalSystemServiceUsage;
16228                     }
16229 
16230                     pw.print("  ");
16231                     pw.print(u);
16232                     pw.print(": ");
16233                     pw.println(timeUs / 1000);
16234                 }
16235             }
16236         }
16237     }
16238 
16239     /**
16240      * Dump EnergyConsumer stats
16241      */
16242     @GuardedBy("this")
16243     public void dumpEnergyConsumerStatsLocked(PrintWriter pw) {
16244         pw.printf("On-battery energy consumer stats (microcoulombs) \n");
16245         if (mGlobalEnergyConsumerStats == null) {
16246             pw.printf("    Not supported on this device.\n");
16247             return;
16248         }
16249 
16250         dumpEnergyConsumerStatsLocked(pw, "global usage", mGlobalEnergyConsumerStats);
16251 
16252         int size = mUidStats.size();
16253         for (int i = 0; i < size; i++) {
16254             final int u = mUidStats.keyAt(i);
16255             final Uid uid = mUidStats.get(u);
16256             final String name = "uid " + uid.mUid;
16257             dumpEnergyConsumerStatsLocked(pw, name, uid.mUidEnergyConsumerStats);
16258         }
16259     }
16260 
16261     /** Dump EnergyConsumer stats for the given uid */
16262     @GuardedBy("this")
16263     private void dumpEnergyConsumerStatsLocked(PrintWriter pw, String name,
16264             EnergyConsumerStats stats) {
16265         if (stats == null) return;
16266         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
16267         iPw.increaseIndent();
16268         iPw.printf("%s:\n", name);
16269         iPw.increaseIndent();
16270         stats.dump(iPw);
16271         iPw.decreaseIndent();
16272     }
16273 
16274     /**
16275      * Dump Power Profile
16276      */
16277     @GuardedBy("this")
16278     public void dumpPowerProfileLocked(PrintWriter pw) {
16279         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
16280         iPw.printf("Power Profile: \n");
16281         iPw.increaseIndent();
16282         mPowerProfile.dump(iPw);
16283         iPw.decreaseIndent();
16284     }
16285 
16286     /**
16287      * Schedules an immediate (but asynchronous) collection of PowerStats samples.
16288      * Callers will need to wait for the collection to complete on the handler thread.
16289      */
16290     public void schedulePowerStatsSampleCollection() {
16291         mCpuPowerStatsCollector.forceSchedule();
16292         mMobileRadioPowerStatsCollector.forceSchedule();
16293         mWifiPowerStatsCollector.forceSchedule();
16294         mBluetoothPowerStatsCollector.forceSchedule();
16295         mCameraPowerStatsCollector.forceSchedule();
16296         mGnssPowerStatsCollector.forceSchedule();
16297     }
16298 
16299     /**
16300      * Schedules an immediate collection of PowerStats samples and awaits the result.
16301      */
16302     public void collectPowerStatsSamples() {
16303         schedulePowerStatsSampleCollection();
16304         ConditionVariable done = new ConditionVariable();
16305         mHandler.post(done::open);
16306         done.block();
16307     }
16308 
16309     /**
16310      * Grabs one sample of PowerStats and prints it.
16311      */
16312     public void dumpStatsSample(PrintWriter pw) {
16313         mCpuPowerStatsCollector.collectAndDump(pw);
16314         mMobileRadioPowerStatsCollector.collectAndDump(pw);
16315         mWifiPowerStatsCollector.collectAndDump(pw);
16316         mBluetoothPowerStatsCollector.collectAndDump(pw);
16317         mCameraPowerStatsCollector.collectAndDump(pw);
16318         mGnssPowerStatsCollector.collectAndDump(pw);
16319     }
16320 
16321     private final Runnable mWriteAsyncRunnable = () -> {
16322         synchronized (BatteryStatsImpl.this) {
16323             writeSyncLocked();
16324         }
16325     };
16326 
16327     @GuardedBy("this")
16328     public void writeAsyncLocked() {
16329         BackgroundThread.getHandler().removeCallbacks(mWriteAsyncRunnable);
16330         BackgroundThread.getHandler().post(mWriteAsyncRunnable);
16331     }
16332 
16333     @GuardedBy("this")
16334     public void writeSyncLocked() {
16335         BackgroundThread.getHandler().removeCallbacks(mWriteAsyncRunnable);
16336         writeStatsLocked();
16337         writeHistoryLocked();
16338     }
16339 
16340     @GuardedBy("this")
16341     private void writeStatsLocked() {
16342         if (mStatsFile == null) {
16343             Slog.w(TAG,
16344                     "writeStatsLocked: no file associated with this instance");
16345             return;
16346         }
16347 
16348         if (mShuttingDown) {
16349             return;
16350         }
16351 
16352         final Parcel p = Parcel.obtain();
16353         try {
16354             final long start = SystemClock.uptimeMillis();
16355             writeSummaryToParcel(p, false/*history is in separate file*/);
16356             if (DEBUG) {
16357                 Slog.d(TAG, "writeSummaryToParcel duration ms:"
16358                         + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
16359             }
16360             mLastWriteTimeMs = mClock.elapsedRealtime();
16361             writeParcelToFileLocked(p, mStatsFile);
16362         } finally {
16363             p.recycle();
16364         }
16365     }
16366 
16367     private void writeHistoryLocked() {
16368         if (mShuttingDown) {
16369             return;
16370         }
16371 
16372         mHistory.writeHistory();
16373     }
16374 
16375     private final ReentrantLock mWriteLock = new ReentrantLock();
16376     private void writeParcelToFileLocked(Parcel p, AtomicFile file) {
16377         mWriteLock.lock();
16378         FileOutputStream fos = null;
16379         try {
16380             final long startTimeMs = SystemClock.uptimeMillis();
16381             fos = file.startWrite();
16382             fos.write(p.marshall());
16383             fos.flush();
16384             file.finishWrite(fos);
16385             if (DEBUG) {
16386                 Slog.d(TAG, "commitPendingDataToDisk file:" + file.getBaseFile().getPath()
16387                         + " duration ms:" + (SystemClock.uptimeMillis() - startTimeMs)
16388                         + " bytes:" + p.dataSize());
16389             }
16390             mFrameworkStatsLogger.writeCommitSysConfigFile(
16391                     "batterystats", SystemClock.uptimeMillis() - startTimeMs);
16392         } catch (IOException e) {
16393             Slog.w(TAG, "Error writing battery statistics", e);
16394             file.failWrite(fos);
16395         } finally {
16396             mWriteLock.unlock();
16397         }
16398     }
16399 
16400     @GuardedBy("this")
16401     public void readLocked() {
16402         if (mDailyFile != null) {
16403             readDailyStatsLocked();
16404         }
16405 
16406         if (mStatsFile == null) {
16407             Slog.w(TAG, "readLocked: no file associated with this instance");
16408             return;
16409         }
16410 
16411         mUidStats.clear();
16412 
16413         Parcel stats = Parcel.obtain();
16414         try {
16415             final long start = SystemClock.uptimeMillis();
16416             if (mStatsFile.exists()) {
16417                 byte[] raw = mStatsFile.readFully();
16418                 stats.unmarshall(raw, 0, raw.length);
16419                 stats.setDataPosition(0);
16420                 readSummaryFromParcel(stats);
16421                 if (DEBUG) {
16422                     Slog.d(TAG, "readLocked stats file:" + mStatsFile.getBaseFile().getPath()
16423                             + " bytes:" + raw.length + " took ms:" + (SystemClock.uptimeMillis()
16424                             - start));
16425                 }
16426             }
16427         } catch (Exception e) {
16428             Slog.e(TAG, "Error reading battery statistics", e);
16429             resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
16430                     RESET_REASON_CORRUPT_FILE);
16431         } finally {
16432             stats.recycle();
16433         }
16434 
16435         if (!mHistory.readSummary()) {
16436             resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
16437                     RESET_REASON_CORRUPT_FILE);
16438         }
16439 
16440         mEndPlatformVersion = Build.ID;
16441 
16442         mMonotonicEndTime = MonotonicClock.UNDEFINED;
16443         mHistory.continueRecordingHistory();
16444 
16445         recordDailyStatsIfNeededLocked(false, mClock.currentTimeMillis());
16446     }
16447 
16448     @GuardedBy("this")
16449     public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
16450         final int version = in.readInt();
16451 
16452         if (version != VERSION) {
16453             Slog.w("BatteryStats", "readFromParcel: version got " + version
16454                 + ", expected " + VERSION + "; erasing old stats");
16455             return;
16456         }
16457 
16458         mHistory.readSummaryFromParcel(in);
16459 
16460         mStartCount = in.readInt();
16461         mUptimeUs = in.readLong();
16462         mRealtimeUs = in.readLong();
16463         mStartClockTimeMs = in.readLong();
16464         mMonotonicStartTime = in.readLong();
16465         mMonotonicEndTime = in.readLong();
16466         mStartPlatformVersion = in.readString();
16467         mEndPlatformVersion = in.readString();
16468         mOnBatteryTimeBase.readSummaryFromParcel(in);
16469         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
16470         mDischargeUnplugLevel = in.readInt();
16471         mDischargePlugLevel = in.readInt();
16472         mDischargeCurrentLevel = in.readInt();
16473         mBatteryLevel = in.readInt();
16474         mEstimatedBatteryCapacityMah = in.readInt();
16475         mLastLearnedBatteryCapacityUah = in.readInt();
16476         mMinLearnedBatteryCapacityUah = in.readInt();
16477         mMaxLearnedBatteryCapacityUah = in.readInt();
16478         mLowDischargeAmountSinceCharge = in.readInt();
16479         mHighDischargeAmountSinceCharge = in.readInt();
16480         mDischargeAmountScreenOnSinceCharge = in.readInt();
16481         mDischargeAmountScreenOffSinceCharge = in.readInt();
16482         mDischargeAmountScreenDozeSinceCharge = in.readInt();
16483         mDischargeStepTracker.readFromParcel(in);
16484         mChargeStepTracker.readFromParcel(in);
16485         mDailyDischargeStepTracker.readFromParcel(in);
16486         mDailyChargeStepTracker.readFromParcel(in);
16487         mDischargeCounter.readSummaryFromParcelLocked(in);
16488         mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
16489         mDischargeScreenDozeCounter.readSummaryFromParcelLocked(in);
16490         mDischargeLightDozeCounter.readSummaryFromParcelLocked(in);
16491         mDischargeDeepDozeCounter.readSummaryFromParcelLocked(in);
16492         int NPKG = in.readInt();
16493         if (NPKG > 0) {
16494             mDailyPackageChanges = new ArrayList<>(NPKG);
16495             while (NPKG > 0) {
16496                 NPKG--;
16497                 PackageChange pc = new PackageChange();
16498                 pc.mPackageName = in.readString();
16499                 pc.mUpdate = in.readInt() != 0;
16500                 pc.mVersionCode = in.readLong();
16501                 mDailyPackageChanges.add(pc);
16502             }
16503         } else {
16504             mDailyPackageChanges = null;
16505         }
16506         mDailyStartTimeMs = in.readLong();
16507         mNextMinDailyDeadlineMs = in.readLong();
16508         mNextMaxDailyDeadlineMs = in.readLong();
16509         mBatteryTimeToFullSeconds = in.readLong();
16510 
16511         final EnergyConsumerStats.Config config = EnergyConsumerStats.Config.createFromParcel(in);
16512         final EnergyConsumerStats energyConsumerStats =
16513                 EnergyConsumerStats.createAndReadSummaryFromParcel(mEnergyConsumerStatsConfig, in);
16514         if (config != null && Arrays.equals(config.getStateNames(),
16515                 getBatteryConsumerProcessStateNames())) {
16516             /**
16517              * WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled
16518              *          later when {@link #initEnergyConsumerStatsLocked} is called.
16519              */
16520             mEnergyConsumerStatsConfig = config;
16521             mGlobalEnergyConsumerStats = energyConsumerStats;
16522         }
16523 
16524         mStartCount++;
16525 
16526         mScreenState = Display.STATE_UNKNOWN;
16527         mScreenOnTimer.readSummaryFromParcelLocked(in);
16528         mScreenDozeTimer.readSummaryFromParcelLocked(in);
16529         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
16530             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
16531         }
16532         final int numDisplays = in.readInt();
16533         for (int i = 0; i < numDisplays; i++) {
16534             mPerDisplayBatteryStats[i].readSummaryFromParcel(in);
16535         }
16536         mInteractive = false;
16537         mInteractiveTimer.readSummaryFromParcelLocked(in);
16538         mPhoneOn = false;
16539         mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
16540         mLongestLightIdleTimeMs = in.readLong();
16541         mLongestFullIdleTimeMs = in.readLong();
16542         mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
16543         mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
16544         mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
16545         mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
16546         mPhoneOnTimer.readSummaryFromParcelLocked(in);
16547         for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
16548             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
16549         }
16550         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
16551         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
16552             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
16553         }
16554         mNrNsaTimer.readSummaryFromParcelLocked(in);
16555         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
16556             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
16557             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
16558         }
16559 
16560         final int numRat = in.readInt();
16561         for (int i = 0; i < numRat; i++) {
16562             if (in.readInt() == 0) continue;
16563             getRatBatteryStatsLocked(i).readSummaryFromParcel(in);
16564         }
16565 
16566         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
16567         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
16568         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
16569         mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
16570         mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
16571         mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
16572         mWifiMulticastWakelockTimer.readSummaryFromParcelLocked(in);
16573         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
16574         mWifiOn = false;
16575         mWifiOnTimer.readSummaryFromParcelLocked(in);
16576         mGlobalWifiRunning = false;
16577         mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
16578         for (int i=0; i<NUM_WIFI_STATES; i++) {
16579             mWifiStateTimer[i].readSummaryFromParcelLocked(in);
16580         }
16581         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
16582             mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
16583         }
16584         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
16585             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
16586         }
16587         mWifiActiveTimer.readSummaryFromParcelLocked(in);
16588         mWifiActivity.readSummaryFromParcel(in);
16589         for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
16590             mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
16591         }
16592         mBluetoothActivity.readSummaryFromParcel(in);
16593         mModemActivity.readSummaryFromParcel(in);
16594         mHasWifiReporting = in.readInt() != 0;
16595         mHasBluetoothReporting = in.readInt() != 0;
16596         mHasModemReporting = in.readInt() != 0;
16597 
16598         mNumConnectivityChange = in.readInt();
16599         mFlashlightOnNesting = 0;
16600         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
16601         mCameraOnNesting = 0;
16602         mCameraOnTimer.readSummaryFromParcelLocked(in);
16603         mBluetoothScanNesting = 0;
16604         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
16605 
16606         int NRPMS = in.readInt();
16607         if (NRPMS > 10000) {
16608             throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS);
16609         }
16610         for (int irpm = 0; irpm < NRPMS; irpm++) {
16611             if (in.readInt() != 0) {
16612                 String rpmName = in.readString();
16613                 getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
16614             }
16615         }
16616         int NSORPMS = in.readInt();
16617         if (NSORPMS > 10000) {
16618             throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS);
16619         }
16620         for (int irpm = 0; irpm < NSORPMS; irpm++) {
16621             if (in.readInt() != 0) {
16622                 String rpmName = in.readString();
16623                 getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
16624             }
16625         }
16626         int NKW = in.readInt();
16627         if (NKW > 10000) {
16628             throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
16629         }
16630         for (int ikw = 0; ikw < NKW; ikw++) {
16631             if (in.readInt() != 0) {
16632                 String kwltName = in.readString();
16633                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
16634             }
16635         }
16636 
16637         int NWR = in.readInt();
16638         if (NWR > 10000) {
16639             throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
16640         }
16641         for (int iwr = 0; iwr < NWR; iwr++) {
16642             if (in.readInt() != 0) {
16643                 String reasonName = in.readString();
16644                 getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
16645             }
16646         }
16647 
16648         int NMS = in.readInt();
16649         for (int ims = 0; ims < NMS; ims++) {
16650             if (in.readInt() != 0) {
16651                 long kmstName = in.readLong();
16652                 getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
16653             }
16654         }
16655 
16656         final int NU = in.readInt();
16657         if (NU > 10000) {
16658             throw new ParcelFormatException("File corrupt: too many uids " + NU);
16659         }
16660         final long elapsedRealtimeMs = mClock.elapsedRealtime();
16661         final long uptimeMs = mClock.uptimeMillis();
16662         for (int iu = 0; iu < NU; iu++) {
16663             int uid = in.readInt();
16664             Uid u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
16665             mUidStats.put(uid, u);
16666 
16667             u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
16668             u.mOnBatteryScreenOffBackgroundTimeBase.readSummaryFromParcel(in);
16669 
16670             u.mWifiRunning = false;
16671             if (in.readInt() != 0) {
16672                 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
16673             }
16674             u.mFullWifiLockOut = false;
16675             if (in.readInt() != 0) {
16676                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
16677             }
16678             u.mWifiScanStarted = false;
16679             if (in.readInt() != 0) {
16680                 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
16681             }
16682             u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
16683             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
16684                 if (in.readInt() != 0) {
16685                     u.makeWifiBatchedScanBin(i, null);
16686                     u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
16687                 }
16688             }
16689             u.mWifiMulticastWakelockCount = 0;
16690             if (in.readInt() != 0) {
16691                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
16692             }
16693             if (in.readInt() != 0) {
16694                 u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
16695             }
16696             if (in.readInt() != 0) {
16697                 u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
16698             }
16699             if (in.readInt() != 0) {
16700                 u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
16701             }
16702             if (in.readInt() != 0) {
16703                 u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
16704             }
16705             if (in.readInt() != 0) {
16706                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
16707             }
16708             if (in.readInt() != 0) {
16709                 u.createForegroundServiceTimerLocked().readSummaryFromParcelLocked(in);
16710             }
16711             if (in.readInt() != 0) {
16712                 u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
16713             }
16714             if (in.readInt() != 0) {
16715                 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
16716             }
16717             if (in.readInt() != 0) {
16718                 u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in);
16719             }
16720             if (in.readInt() != 0) {
16721                 u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
16722             }
16723             if (in.readInt() != 0) {
16724                 u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in);
16725             }
16726             u.mProcessState = Uid.PROCESS_STATE_NONEXISTENT;
16727             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
16728                 if (in.readInt() != 0) {
16729                     u.makeProcessState(i, null);
16730                     u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
16731                 }
16732             }
16733             if (in.readInt() != 0) {
16734                 u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
16735             }
16736 
16737             if (in.readInt() != 0) {
16738                 if (u.mUserActivityCounters == null) {
16739                     u.initUserActivityLocked();
16740                 }
16741                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
16742                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
16743                 }
16744             }
16745 
16746             if (in.readInt() != 0) {
16747                 u.ensureNetworkActivityLocked();
16748                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
16749                     u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
16750                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
16751                 }
16752                 if (in.readBoolean()) {
16753                     u.mMobileRadioActiveTime = TimeMultiStateCounter.readFromParcel(in,
16754                             mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
16755                             elapsedRealtimeMs);
16756                 }
16757                 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
16758             }
16759 
16760             u.mUserCpuTime.readSummaryFromParcelLocked(in);
16761             u.mSystemCpuTime.readSummaryFromParcelLocked(in);
16762 
16763             if (in.readInt() != 0) {
16764                 final int numClusters = in.readInt();
16765                 int[] policies =
16766                         mCpuScalingPolicies != null ? mCpuScalingPolicies.getPolicies() : null;
16767                 if (policies != null && policies.length != numClusters) {
16768                     throw new ParcelFormatException("Incompatible cpu cluster arrangement");
16769                 }
16770                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
16771                 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
16772                 for (int cluster = 0; cluster < numClusters; cluster++) {
16773                     if (in.readInt() != 0) {
16774                         final int NSB = in.readInt();
16775                         if (policies != null
16776                                 && mCpuScalingPolicies.getFrequencies(policies[cluster]).length
16777                                 != NSB) {
16778                             throw new ParcelFormatException("File corrupt: too many speed bins " +
16779                                     NSB);
16780                         }
16781 
16782                         u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[NSB];
16783                         for (int speed = 0; speed < NSB; speed++) {
16784                             if (in.readInt() != 0) {
16785                                 u.mCpuClusterSpeedTimesUs[cluster][speed] = new LongSamplingCounter(
16786                                         mOnBatteryTimeBase);
16787                                 u.mCpuClusterSpeedTimesUs[cluster][speed].readSummaryFromParcelLocked(in);
16788                             }
16789                         }
16790                     } else {
16791                         u.mCpuClusterSpeedTimesUs[cluster] = null;
16792                     }
16793                 }
16794             } else {
16795                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
16796                 u.mCpuClusterSpeedTimesUs = null;
16797             }
16798 
16799             detachIfNotNull(u.mCpuFreqTimeMs);
16800             u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
16801                     in, mOnBatteryTimeBase);
16802             detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
16803             u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
16804                     in, mOnBatteryScreenOffTimeBase);
16805 
16806             int stateCount = in.readInt();
16807             if (stateCount != 0) {
16808                 u.mCpuActiveTimeMs = TimeMultiStateCounter.readFromParcel(in,
16809                         mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
16810                         mClock.elapsedRealtime());
16811             }
16812             u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
16813 
16814             detachIfNotNull(u.mProcStateTimeMs);
16815             u.mProcStateTimeMs = null;
16816 
16817             stateCount = in.readInt();
16818             if (stateCount != 0) {
16819                 detachIfNotNull(u.mProcStateTimeMs);
16820                 u.mProcStateTimeMs = TimeInFreqMultiStateCounter.readFromParcel(in,
16821                         mOnBatteryTimeBase, PROC_STATE_TIME_COUNTER_STATE_COUNT,
16822                         mCpuScalingPolicies.getScalingStepCount(), mClock.elapsedRealtime());
16823             }
16824 
16825             detachIfNotNull(u.mProcStateScreenOffTimeMs);
16826             u.mProcStateScreenOffTimeMs = null;
16827 
16828             stateCount = in.readInt();
16829             if (stateCount != 0) {
16830                 detachIfNotNull(u.mProcStateScreenOffTimeMs);
16831                 u.mProcStateScreenOffTimeMs = TimeInFreqMultiStateCounter.readFromParcel(in,
16832                         mOnBatteryScreenOffTimeBase, PROC_STATE_TIME_COUNTER_STATE_COUNT,
16833                         mCpuScalingPolicies.getScalingStepCount(), mClock.elapsedRealtime());
16834             }
16835 
16836             if (in.readInt() != 0) {
16837                 detachIfNotNull(u.mMobileRadioApWakeupCount);
16838                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
16839                 u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
16840             } else {
16841                 detachIfNotNull(u.mMobileRadioApWakeupCount);
16842                 u.mMobileRadioApWakeupCount = null;
16843             }
16844 
16845             if (in.readInt() != 0) {
16846                 detachIfNotNull(u.mWifiRadioApWakeupCount);
16847                 u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
16848                 u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
16849             } else {
16850                 detachIfNotNull(u.mWifiRadioApWakeupCount);
16851                 u.mWifiRadioApWakeupCount = null;
16852             }
16853 
16854             u.mUidEnergyConsumerStats = EnergyConsumerStats.createAndReadSummaryFromParcel(
16855                     mEnergyConsumerStatsConfig, in);
16856 
16857             int NW = in.readInt();
16858             if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
16859                 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
16860             }
16861             for (int iw = 0; iw < NW; iw++) {
16862                 String wlName = in.readString();
16863                 u.readWakeSummaryFromParcelLocked(wlName, in);
16864             }
16865 
16866             int NS = in.readInt();
16867             if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
16868                 throw new ParcelFormatException("File corrupt: too many syncs " + NS);
16869             }
16870             for (int is = 0; is < NS; is++) {
16871                 String name = in.readString();
16872                 u.readSyncSummaryFromParcelLocked(name, in);
16873             }
16874 
16875             int NJ = in.readInt();
16876             if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
16877                 throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
16878             }
16879             for (int ij = 0; ij < NJ; ij++) {
16880                 String name = in.readString();
16881                 u.readJobSummaryFromParcelLocked(name, in);
16882             }
16883 
16884             u.readJobCompletionsFromParcelLocked(in);
16885 
16886             u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in);
16887             u.mJobsDeferredCount.readSummaryFromParcelLocked(in);
16888             u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in);
16889             detachIfNotNull(u.mJobsFreshnessBuckets);
16890             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
16891                 if (in.readInt() != 0) {
16892                     u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase);
16893                     u.mJobsFreshnessBuckets[i].readSummaryFromParcelLocked(in);
16894                 }
16895             }
16896 
16897             int NP = in.readInt();
16898             if (NP > 1000) {
16899                 throw new ParcelFormatException("File corrupt: too many sensors " + NP);
16900             }
16901             for (int is = 0; is < NP; is++) {
16902                 int seNumber = in.readInt();
16903                 if (in.readInt() != 0) {
16904                     u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
16905                 }
16906             }
16907 
16908             NP = in.readInt();
16909             if (NP > 10000) {
16910                 throw new ParcelFormatException("File corrupt: too many processes " + NP);
16911             }
16912             for (int ip = 0; ip < NP; ip++) {
16913                 String procName = in.readString();
16914                 Uid.Proc p = u.getProcessStatsLocked(procName);
16915                 p.mUserTimeMs = in.readLong();
16916                 p.mSystemTimeMs = in.readLong();
16917                 p.mForegroundTimeMs = in.readLong();
16918                 p.mStarts = in.readInt();
16919                 p.mNumCrashes = in.readInt();
16920                 p.mNumAnrs = in.readInt();
16921                 p.readExcessivePowerFromParcelLocked(in);
16922             }
16923 
16924             NP = in.readInt();
16925             if (NP > 10000) {
16926                 throw new ParcelFormatException("File corrupt: too many packages " + NP);
16927             }
16928             for (int ip = 0; ip < NP; ip++) {
16929                 String pkgName = in.readString();
16930                 detachIfNotNull(u.mPackageStats.get(pkgName));
16931                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
16932                 final int NWA = in.readInt();
16933                 if (NWA > 10000) {
16934                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
16935                 }
16936                 p.mWakeupAlarms.clear();
16937                 for (int iwa = 0; iwa < NWA; iwa++) {
16938                     String tag = in.readString();
16939                     Counter c = new Counter(mOnBatteryScreenOffTimeBase);
16940                     c.readSummaryFromParcelLocked(in);
16941                     p.mWakeupAlarms.put(tag, c);
16942                 }
16943                 NS = in.readInt();
16944                 if (NS > 10000) {
16945                     throw new ParcelFormatException("File corrupt: too many services " + NS);
16946                 }
16947                 for (int is = 0; is < NS; is++) {
16948                     String servName = in.readString();
16949                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
16950                     s.mStartTimeMs = in.readLong();
16951                     s.mStarts = in.readInt();
16952                     s.mLaunches = in.readInt();
16953                 }
16954             }
16955         }
16956 
16957         if (!Flags.disableSystemServicePowerAttr()) {
16958             mBinderThreadCpuTimesUs =
16959                     LongSamplingCounterArray.readSummaryFromParcelLocked(in, mOnBatteryTimeBase);
16960         }
16961     }
16962 
16963     /**
16964      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
16965      * disk.  This format does not allow a lossless round-trip.
16966      *
16967      * @param out the Parcel to be written to.
16968      */
16969     @GuardedBy("this")
16970     public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
16971         pullPendingStateUpdatesLocked();
16972 
16973         // Pull the clock time.  This may update the time and make a new history entry
16974         // if we had originally pulled a time before the RTC was set.
16975         getStartClockTime();
16976 
16977         final long nowUptime = mClock.uptimeMillis() * 1000;
16978         final long nowRealtime = mClock.elapsedRealtime() * 1000;
16979 
16980         out.writeInt(VERSION);
16981 
16982         mHistory.writeSummaryToParcel(out, inclHistory);
16983 
16984         out.writeInt(mStartCount);
16985         out.writeLong(computeUptime(nowUptime, STATS_SINCE_CHARGED));
16986         out.writeLong(computeRealtime(nowRealtime, STATS_SINCE_CHARGED));
16987         out.writeLong(mStartClockTimeMs);
16988         out.writeLong(mMonotonicStartTime);
16989         out.writeLong(mMonotonicClock.monotonicTime());
16990         out.writeString(mStartPlatformVersion);
16991         out.writeString(mEndPlatformVersion);
16992         mOnBatteryTimeBase.writeSummaryToParcel(out, nowUptime, nowRealtime);
16993         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, nowUptime, nowRealtime);
16994         out.writeInt(mDischargeUnplugLevel);
16995         out.writeInt(mDischargePlugLevel);
16996         out.writeInt(mDischargeCurrentLevel);
16997         out.writeInt(mBatteryLevel);
16998         out.writeInt(mEstimatedBatteryCapacityMah);
16999         out.writeInt(mLastLearnedBatteryCapacityUah);
17000         out.writeInt(mMinLearnedBatteryCapacityUah);
17001         out.writeInt(mMaxLearnedBatteryCapacityUah);
17002         out.writeInt(getLowDischargeAmountSinceCharge());
17003         out.writeInt(getHighDischargeAmountSinceCharge());
17004         out.writeInt(getDischargeAmountScreenOnSinceCharge());
17005         out.writeInt(getDischargeAmountScreenOffSinceCharge());
17006         out.writeInt(getDischargeAmountScreenDozeSinceCharge());
17007         mDischargeStepTracker.writeToParcel(out);
17008         mChargeStepTracker.writeToParcel(out);
17009         mDailyDischargeStepTracker.writeToParcel(out);
17010         mDailyChargeStepTracker.writeToParcel(out);
17011         mDischargeCounter.writeSummaryFromParcelLocked(out);
17012         mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
17013         mDischargeScreenDozeCounter.writeSummaryFromParcelLocked(out);
17014         mDischargeLightDozeCounter.writeSummaryFromParcelLocked(out);
17015         mDischargeDeepDozeCounter.writeSummaryFromParcelLocked(out);
17016         if (mDailyPackageChanges != null) {
17017             final int NPKG = mDailyPackageChanges.size();
17018             out.writeInt(NPKG);
17019             for (int i=0; i<NPKG; i++) {
17020                 PackageChange pc = mDailyPackageChanges.get(i);
17021                 out.writeString(pc.mPackageName);
17022                 out.writeInt(pc.mUpdate ? 1 : 0);
17023                 out.writeLong(pc.mVersionCode);
17024             }
17025         } else {
17026             out.writeInt(0);
17027         }
17028         out.writeLong(mDailyStartTimeMs);
17029         out.writeLong(mNextMinDailyDeadlineMs);
17030         out.writeLong(mNextMaxDailyDeadlineMs);
17031         out.writeLong(mBatteryTimeToFullSeconds);
17032 
17033         EnergyConsumerStats.Config.writeToParcel(mEnergyConsumerStatsConfig, out);
17034         EnergyConsumerStats.writeSummaryToParcel(mGlobalEnergyConsumerStats, out);
17035 
17036         mScreenOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17037         mScreenDozeTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17038         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
17039             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17040         }
17041         final int numDisplays = mPerDisplayBatteryStats.length;
17042         out.writeInt(numDisplays);
17043         for (int i = 0; i < numDisplays; i++) {
17044             mPerDisplayBatteryStats[i].writeSummaryToParcel(out, nowRealtime);
17045         }
17046         mInteractiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17047         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17048         out.writeLong(mLongestLightIdleTimeMs);
17049         out.writeLong(mLongestFullIdleTimeMs);
17050         mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17051         mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17052         mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17053         mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17054         mPhoneOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17055         for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
17056             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17057         }
17058         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17059         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
17060             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17061         }
17062         mNrNsaTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17063         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
17064             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
17065             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
17066         }
17067         final int numRat = mPerRatBatteryStats.length;
17068         out.writeInt(numRat);
17069         for (int i = 0; i < numRat; i++) {
17070             final RadioAccessTechnologyBatteryStats ratStat = mPerRatBatteryStats[i];
17071             if (ratStat == null) {
17072                 out.writeInt(0);
17073                 continue;
17074             }
17075             out.writeInt(1);
17076             ratStat.writeSummaryToParcel(out, nowRealtime);
17077         }
17078         mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17079         mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17080         mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
17081         mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
17082         mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
17083         mWifiMulticastWakelockTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17084         mWifiOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17085         mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17086         for (int i=0; i<NUM_WIFI_STATES; i++) {
17087             mWifiStateTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17088         }
17089         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
17090             mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17091         }
17092         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
17093             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17094         }
17095         mWifiActiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17096         mWifiActivity.writeSummaryToParcel(out);
17097         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
17098             mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17099         }
17100         mBluetoothActivity.writeSummaryToParcel(out);
17101         mModemActivity.writeSummaryToParcel(out);
17102         out.writeInt(mHasWifiReporting ? 1 : 0);
17103         out.writeInt(mHasBluetoothReporting ? 1 : 0);
17104         out.writeInt(mHasModemReporting ? 1 : 0);
17105 
17106         out.writeInt(mNumConnectivityChange);
17107         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17108         mCameraOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17109         mBluetoothScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17110 
17111         out.writeInt(mRpmStats.size());
17112         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
17113             Timer rpmt = ent.getValue();
17114             if (rpmt != null) {
17115                 out.writeInt(1);
17116                 out.writeString(ent.getKey());
17117                 rpmt.writeSummaryFromParcelLocked(out, nowRealtime);
17118             } else {
17119                 out.writeInt(0);
17120             }
17121         }
17122         out.writeInt(mScreenOffRpmStats.size());
17123         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
17124             Timer rpmt = ent.getValue();
17125             if (rpmt != null) {
17126                 out.writeInt(1);
17127                 out.writeString(ent.getKey());
17128                 rpmt.writeSummaryFromParcelLocked(out, nowRealtime);
17129             } else {
17130                 out.writeInt(0);
17131             }
17132         }
17133 
17134         out.writeInt(mKernelWakelockStats.size());
17135         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
17136             Timer kwlt = ent.getValue();
17137             if (kwlt != null) {
17138                 out.writeInt(1);
17139                 out.writeString(ent.getKey());
17140                 kwlt.writeSummaryFromParcelLocked(out, nowRealtime);
17141             } else {
17142                 out.writeInt(0);
17143             }
17144         }
17145 
17146         out.writeInt(mWakeupReasonStats.size());
17147         for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
17148             SamplingTimer timer = ent.getValue();
17149             if (timer != null) {
17150                 out.writeInt(1);
17151                 out.writeString(ent.getKey());
17152                 timer.writeSummaryFromParcelLocked(out, nowRealtime);
17153             } else {
17154                 out.writeInt(0);
17155             }
17156         }
17157 
17158         out.writeInt(mKernelMemoryStats.size());
17159         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
17160             Timer kmt = mKernelMemoryStats.valueAt(i);
17161             if (kmt != null) {
17162                 out.writeInt(1);
17163                 out.writeLong(mKernelMemoryStats.keyAt(i));
17164                 kmt.writeSummaryFromParcelLocked(out, nowRealtime);
17165             } else {
17166                 out.writeInt(0);
17167             }
17168         }
17169 
17170         final int NU = mUidStats.size();
17171         out.writeInt(NU);
17172         for (int iu = 0; iu < NU; iu++) {
17173             out.writeInt(mUidStats.keyAt(iu));
17174             Uid u = mUidStats.valueAt(iu);
17175 
17176             u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, nowUptime, nowRealtime);
17177             u.mOnBatteryScreenOffBackgroundTimeBase.writeSummaryToParcel(out, nowUptime,
17178                     nowRealtime);
17179 
17180             if (u.mWifiRunningTimer != null) {
17181                 out.writeInt(1);
17182                 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17183             } else {
17184                 out.writeInt(0);
17185             }
17186             if (u.mFullWifiLockTimer != null) {
17187                 out.writeInt(1);
17188                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17189             } else {
17190                 out.writeInt(0);
17191             }
17192             if (u.mWifiScanTimer != null) {
17193                 out.writeInt(1);
17194                 u.mWifiScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17195             } else {
17196                 out.writeInt(0);
17197             }
17198             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
17199                 if (u.mWifiBatchedScanTimer[i] != null) {
17200                     out.writeInt(1);
17201                     u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17202                 } else {
17203                     out.writeInt(0);
17204                 }
17205             }
17206             if (u.mWifiMulticastTimer != null) {
17207                 out.writeInt(1);
17208                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17209             } else {
17210                 out.writeInt(0);
17211             }
17212             if (u.mAudioTurnedOnTimer != null) {
17213                 out.writeInt(1);
17214                 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17215             } else {
17216                 out.writeInt(0);
17217             }
17218             if (u.mVideoTurnedOnTimer != null) {
17219                 out.writeInt(1);
17220                 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17221             } else {
17222                 out.writeInt(0);
17223             }
17224             if (u.mFlashlightTurnedOnTimer != null) {
17225                 out.writeInt(1);
17226                 u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17227             } else {
17228                 out.writeInt(0);
17229             }
17230             if (u.mCameraTurnedOnTimer != null) {
17231                 out.writeInt(1);
17232                 u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17233             } else {
17234                 out.writeInt(0);
17235             }
17236             if (u.mForegroundActivityTimer != null) {
17237                 out.writeInt(1);
17238                 u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17239             } else {
17240                 out.writeInt(0);
17241             }
17242             if (u.mForegroundServiceTimer != null) {
17243                 out.writeInt(1);
17244                 u.mForegroundServiceTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17245             } else {
17246                 out.writeInt(0);
17247             }
17248             if (u.mAggregatedPartialWakelockTimer != null) {
17249                 out.writeInt(1);
17250                 u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17251             } else {
17252                 out.writeInt(0);
17253             }
17254             if (u.mBluetoothScanTimer != null) {
17255                 out.writeInt(1);
17256                 u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17257             } else {
17258                 out.writeInt(0);
17259             }
17260             if (u.mBluetoothUnoptimizedScanTimer != null) {
17261                 out.writeInt(1);
17262                 u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17263             } else {
17264                 out.writeInt(0);
17265             }
17266             if (u.mBluetoothScanResultCounter != null) {
17267                 out.writeInt(1);
17268                 u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
17269             } else {
17270                 out.writeInt(0);
17271             }
17272             if (u.mBluetoothScanResultBgCounter != null) {
17273                 out.writeInt(1);
17274                 u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out);
17275             } else {
17276                 out.writeInt(0);
17277             }
17278             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
17279                 if (u.mProcessStateTimer[i] != null) {
17280                     out.writeInt(1);
17281                     u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
17282                 } else {
17283                     out.writeInt(0);
17284                 }
17285             }
17286             if (u.mVibratorOnTimer != null) {
17287                 out.writeInt(1);
17288                 u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17289             } else {
17290                 out.writeInt(0);
17291             }
17292 
17293             if (u.mUserActivityCounters == null) {
17294                 out.writeInt(0);
17295             } else {
17296                 out.writeInt(1);
17297                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
17298                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
17299                 }
17300             }
17301 
17302             if (u.mNetworkByteActivityCounters == null) {
17303                 out.writeInt(0);
17304             } else {
17305                 out.writeInt(1);
17306                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
17307                     u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
17308                     u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
17309                 }
17310                 if (u.mMobileRadioActiveTime != null) {
17311                     out.writeBoolean(true);
17312                     u.mMobileRadioActiveTime.writeToParcel(out);
17313                 } else {
17314                     out.writeBoolean(false);
17315                 }
17316                 u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
17317             }
17318 
17319             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
17320             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
17321 
17322             if (u.mCpuClusterSpeedTimesUs != null) {
17323                 out.writeInt(1);
17324                 out.writeInt(u.mCpuClusterSpeedTimesUs.length);
17325                 for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeedTimesUs) {
17326                     if (cpuSpeeds != null) {
17327                         out.writeInt(1);
17328                         out.writeInt(cpuSpeeds.length);
17329                         for (LongSamplingCounter c : cpuSpeeds) {
17330                             if (c != null) {
17331                                 out.writeInt(1);
17332                                 c.writeSummaryFromParcelLocked(out);
17333                             } else {
17334                                 out.writeInt(0);
17335                             }
17336                         }
17337                     } else {
17338                         out.writeInt(0);
17339                     }
17340                 }
17341             } else {
17342                 out.writeInt(0);
17343             }
17344 
17345             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
17346             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
17347 
17348             if (u.mCpuActiveTimeMs != null) {
17349                 out.writeInt(u.mCpuActiveTimeMs.getStateCount());
17350                 u.mCpuActiveTimeMs.writeToParcel(out);
17351             } else {
17352                 out.writeInt(0);
17353             }
17354 
17355             u.mCpuClusterTimesMs.writeSummaryToParcelLocked(out);
17356 
17357             if (u.mProcStateTimeMs != null) {
17358                 out.writeInt(u.mProcStateTimeMs.getStateCount());
17359                 u.mProcStateTimeMs.writeToParcel(out);
17360             } else {
17361                 out.writeInt(0);
17362             }
17363 
17364             if (u.mProcStateScreenOffTimeMs != null) {
17365                 out.writeInt(u.mProcStateScreenOffTimeMs.getStateCount());
17366                 u.mProcStateScreenOffTimeMs.writeToParcel(out);
17367             } else {
17368                 out.writeInt(0);
17369             }
17370 
17371             if (u.mMobileRadioApWakeupCount != null) {
17372                 out.writeInt(1);
17373                 u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
17374             } else {
17375                 out.writeInt(0);
17376             }
17377 
17378             if (u.mWifiRadioApWakeupCount != null) {
17379                 out.writeInt(1);
17380                 u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
17381             } else {
17382                 out.writeInt(0);
17383             }
17384 
17385             EnergyConsumerStats.writeSummaryToParcel(u.mUidEnergyConsumerStats, out);
17386 
17387             final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
17388             int NW = wakeStats.size();
17389             out.writeInt(NW);
17390             for (int iw=0; iw<NW; iw++) {
17391                 out.writeString(wakeStats.keyAt(iw));
17392                 Uid.Wakelock wl = wakeStats.valueAt(iw);
17393                 if (wl.mTimerFull != null) {
17394                     out.writeInt(1);
17395                     wl.mTimerFull.writeSummaryFromParcelLocked(out, nowRealtime);
17396                 } else {
17397                     out.writeInt(0);
17398                 }
17399                 if (wl.mTimerPartial != null) {
17400                     out.writeInt(1);
17401                     wl.mTimerPartial.writeSummaryFromParcelLocked(out, nowRealtime);
17402                 } else {
17403                     out.writeInt(0);
17404                 }
17405                 if (wl.mTimerWindow != null) {
17406                     out.writeInt(1);
17407                     wl.mTimerWindow.writeSummaryFromParcelLocked(out, nowRealtime);
17408                 } else {
17409                     out.writeInt(0);
17410                 }
17411                 if (wl.mTimerDraw != null) {
17412                     out.writeInt(1);
17413                     wl.mTimerDraw.writeSummaryFromParcelLocked(out, nowRealtime);
17414                 } else {
17415                     out.writeInt(0);
17416                 }
17417             }
17418 
17419             final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
17420             int NS = syncStats.size();
17421             out.writeInt(NS);
17422             for (int is=0; is<NS; is++) {
17423                 out.writeString(syncStats.keyAt(is));
17424                 syncStats.valueAt(is).writeSummaryFromParcelLocked(out, nowRealtime);
17425             }
17426 
17427             final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
17428             int NJ = jobStats.size();
17429             out.writeInt(NJ);
17430             for (int ij=0; ij<NJ; ij++) {
17431                 out.writeString(jobStats.keyAt(ij));
17432                 jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, nowRealtime);
17433             }
17434 
17435             u.writeJobCompletionsToParcelLocked(out);
17436 
17437             u.mJobsDeferredEventCount.writeSummaryFromParcelLocked(out);
17438             u.mJobsDeferredCount.writeSummaryFromParcelLocked(out);
17439             u.mJobsFreshnessTimeMs.writeSummaryFromParcelLocked(out);
17440             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
17441                 if (u.mJobsFreshnessBuckets[i] != null) {
17442                     out.writeInt(1);
17443                     u.mJobsFreshnessBuckets[i].writeSummaryFromParcelLocked(out);
17444                 } else {
17445                     out.writeInt(0);
17446                 }
17447             }
17448 
17449             int NSE = u.mSensorStats.size();
17450             out.writeInt(NSE);
17451             for (int ise=0; ise<NSE; ise++) {
17452                 out.writeInt(u.mSensorStats.keyAt(ise));
17453                 Uid.Sensor se = u.mSensorStats.valueAt(ise);
17454                 if (se.mTimer != null) {
17455                     out.writeInt(1);
17456                     se.mTimer.writeSummaryFromParcelLocked(out, nowRealtime);
17457                 } else {
17458                     out.writeInt(0);
17459                 }
17460             }
17461 
17462             int NP = u.mProcessStats.size();
17463             out.writeInt(NP);
17464             for (int ip=0; ip<NP; ip++) {
17465                 out.writeString(u.mProcessStats.keyAt(ip));
17466                 Uid.Proc ps = u.mProcessStats.valueAt(ip);
17467                 out.writeLong(ps.mUserTimeMs);
17468                 out.writeLong(ps.mSystemTimeMs);
17469                 out.writeLong(ps.mForegroundTimeMs);
17470                 out.writeInt(ps.mStarts);
17471                 out.writeInt(ps.mNumCrashes);
17472                 out.writeInt(ps.mNumAnrs);
17473                 ps.writeExcessivePowerToParcelLocked(out);
17474             }
17475 
17476             NP = u.mPackageStats.size();
17477             out.writeInt(NP);
17478             if (NP > 0) {
17479                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
17480                     : u.mPackageStats.entrySet()) {
17481                     out.writeString(ent.getKey());
17482                     Uid.Pkg ps = ent.getValue();
17483                     final int NWA = ps.mWakeupAlarms.size();
17484                     out.writeInt(NWA);
17485                     for (int iwa=0; iwa<NWA; iwa++) {
17486                         out.writeString(ps.mWakeupAlarms.keyAt(iwa));
17487                         ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
17488                     }
17489                     NS = ps.mServiceStats.size();
17490                     out.writeInt(NS);
17491                     for (int is=0; is<NS; is++) {
17492                         out.writeString(ps.mServiceStats.keyAt(is));
17493                         BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
17494                         long time = ss.getStartTimeToNowLocked(
17495                                 mOnBatteryTimeBase.getUptime(nowUptime) / 1000);
17496                         out.writeLong(time);
17497                         out.writeInt(ss.mStarts);
17498                         out.writeInt(ss.mLaunches);
17499                     }
17500                 }
17501             }
17502         }
17503 
17504         if (!Flags.disableSystemServicePowerAttr()) {
17505             LongSamplingCounterArray.writeSummaryToParcelLocked(out, mBinderThreadCpuTimesUs);
17506         }
17507     }
17508 
17509     @GuardedBy("this")
17510     public void prepareForDumpLocked() {
17511         // Need to retrieve current kernel wake lock stats before printing.
17512         pullPendingStateUpdatesLocked();
17513 
17514         // Pull the clock time.  This may update the time and make a new history entry
17515         // if we had originally pulled a time before the RTC was set.
17516         getStartClockTime();
17517 
17518         if (!Flags.disableSystemServicePowerAttr()) {
17519             updateSystemServiceCallStats();
17520         }
17521     }
17522 
17523     @GuardedBy("this")
17524     public void dump(Context context, PrintWriter pw, int flags, int reqUid, long histStart,
17525             BatteryStatsDumpHelper dumpHelper) {
17526         if (DEBUG) {
17527             pw.println("mOnBatteryTimeBase:");
17528             mOnBatteryTimeBase.dump(pw, "  ");
17529             pw.println("mOnBatteryScreenOffTimeBase:");
17530             mOnBatteryScreenOffTimeBase.dump(pw, "  ");
17531             Printer pr = new PrintWriterPrinter(pw);
17532             pr.println("*** Screen on timer:");
17533             mScreenOnTimer.logState(pr, "  ");
17534             pr.println("*** Screen doze timer:");
17535             mScreenDozeTimer.logState(pr, "  ");
17536             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
17537                 pr.println("*** Screen brightness #" + i + ":");
17538                 mScreenBrightnessTimer[i].logState(pr, "  ");
17539             }
17540             pr.println("*** Interactive timer:");
17541             mInteractiveTimer.logState(pr, "  ");
17542             pr.println("*** Power save mode timer:");
17543             mPowerSaveModeEnabledTimer.logState(pr, "  ");
17544             pr.println("*** Device idle mode light timer:");
17545             mDeviceIdleModeLightTimer.logState(pr, "  ");
17546             pr.println("*** Device idle mode full timer:");
17547             mDeviceIdleModeFullTimer.logState(pr, "  ");
17548             pr.println("*** Device light idling timer:");
17549             mDeviceLightIdlingTimer.logState(pr, "  ");
17550             pr.println("*** Device idling timer:");
17551             mDeviceIdlingTimer.logState(pr, "  ");
17552             pr.println("*** Phone timer:");
17553             mPhoneOnTimer.logState(pr, "  ");
17554             for (int i = 0; i < CELL_SIGNAL_STRENGTH_LEVEL_COUNT; i++) {
17555                 pr.println("*** Phone signal strength #" + i + ":");
17556                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
17557             }
17558             pr.println("*** Signal scanning :");
17559             mPhoneSignalScanningTimer.logState(pr, "  ");
17560             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
17561                 pr.println("*** Data connection type #" + i + ":");
17562                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
17563             }
17564             pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
17565             pr.println("*** Mobile network active timer:");
17566             mMobileRadioActiveTimer.logState(pr, "  ");
17567             pr.println("*** Mobile network active adjusted timer:");
17568             mMobileRadioActiveAdjustedTime.logState(pr, "  ");
17569             pr.println("*** Wifi Multicast WakeLock Timer:");
17570             mWifiMulticastWakelockTimer.logState(pr, "  ");
17571             pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
17572             pr.println("*** Wifi timer:");
17573             mWifiOnTimer.logState(pr, "  ");
17574             pr.println("*** WifiRunning timer:");
17575             mGlobalWifiRunningTimer.logState(pr, "  ");
17576             for (int i=0; i<NUM_WIFI_STATES; i++) {
17577                 pr.println("*** Wifi state #" + i + ":");
17578                 mWifiStateTimer[i].logState(pr, "  ");
17579             }
17580             for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
17581                 pr.println("*** Wifi suppl state #" + i + ":");
17582                 mWifiSupplStateTimer[i].logState(pr, "  ");
17583             }
17584             for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
17585                 pr.println("*** Wifi signal strength #" + i + ":");
17586                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
17587             }
17588             for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
17589                 pr.println("*** GPS signal quality #" + i + ":");
17590                 mGpsSignalQualityTimer[i].logState(pr, "  ");
17591             }
17592             pr.println("*** Flashlight timer:");
17593             mFlashlightOnTimer.logState(pr, "  ");
17594             pr.println("*** Camera timer:");
17595             mCameraOnTimer.logState(pr, "  ");
17596         }
17597         super.dump(context, pw, flags, reqUid, histStart, dumpHelper);
17598 
17599         synchronized (this) {
17600             pw.print("Per process state tracking available: ");
17601             pw.println(trackPerProcStateCpuTimes());
17602             pw.print("Total cpu time reads: ");
17603             pw.println(mNumSingleUidCpuTimeReads);
17604             pw.print("Batching Duration (min): ");
17605             pw.println((mClock.uptimeMillis() - mCpuTimeReadsTrackingStartTimeMs) / (60 * 1000));
17606             pw.print("All UID cpu time reads since the later of device start or stats reset: ");
17607             pw.println(mNumAllUidCpuTimeReads);
17608             pw.print("UIDs removed since the later of device start or stats reset: ");
17609             pw.println(mNumUidsRemoved);
17610 
17611             mPowerStatsUidResolver.dump(pw);
17612 
17613             pw.println();
17614             dumpConstantsLocked(pw);
17615 
17616             pw.println();
17617             mCpuPowerStatsCollector.dumpCpuPowerBracketsLocked(pw);
17618 
17619             pw.println();
17620             dumpEnergyConsumerStatsLocked(pw);
17621         }
17622     }
17623 }
17624