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.BatteryStatsManager.NUM_WIFI_STATES;
23 import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;
24 
25 import android.annotation.IntDef;
26 import android.annotation.NonNull;
27 import android.annotation.Nullable;
28 import android.app.ActivityManager;
29 import android.app.AlarmManager;
30 import android.app.usage.NetworkStatsManager;
31 import android.bluetooth.BluetoothActivityEnergyInfo;
32 import android.bluetooth.UidTraffic;
33 import android.content.BroadcastReceiver;
34 import android.content.ContentResolver;
35 import android.content.Context;
36 import android.content.Intent;
37 import android.content.IntentFilter;
38 import android.database.ContentObserver;
39 import android.hardware.usb.UsbManager;
40 import android.location.GnssSignalQuality;
41 import android.net.NetworkStats;
42 import android.net.Uri;
43 import android.net.wifi.WifiManager;
44 import android.os.BatteryConsumer;
45 import android.os.BatteryManager;
46 import android.os.BatteryStats;
47 import android.os.BatteryUsageStats;
48 import android.os.BatteryUsageStatsQuery;
49 import android.os.Binder;
50 import android.os.BluetoothBatteryStats;
51 import android.os.Build;
52 import android.os.Handler;
53 import android.os.IBatteryPropertiesRegistrar;
54 import android.os.Looper;
55 import android.os.Message;
56 import android.os.OsProtoEnums;
57 import android.os.Parcel;
58 import android.os.ParcelFormatException;
59 import android.os.Parcelable;
60 import android.os.PowerManager;
61 import android.os.Process;
62 import android.os.RemoteException;
63 import android.os.ServiceManager;
64 import android.os.SystemClock;
65 import android.os.UserHandle;
66 import android.os.WakeLockStats;
67 import android.os.WorkSource;
68 import android.os.WorkSource.WorkChain;
69 import android.os.connectivity.CellularBatteryStats;
70 import android.os.connectivity.GpsBatteryStats;
71 import android.os.connectivity.WifiActivityEnergyInfo;
72 import android.os.connectivity.WifiBatteryStats;
73 import android.provider.Settings;
74 import android.telephony.AccessNetworkConstants;
75 import android.telephony.Annotation.NetworkType;
76 import android.telephony.CellSignalStrength;
77 import android.telephony.CellSignalStrengthLte;
78 import android.telephony.CellSignalStrengthNr;
79 import android.telephony.DataConnectionRealTimeInfo;
80 import android.telephony.ModemActivityInfo;
81 import android.telephony.ServiceState;
82 import android.telephony.ServiceState.RegState;
83 import android.telephony.SignalStrength;
84 import android.telephony.TelephonyManager;
85 import android.text.TextUtils;
86 import android.text.format.DateUtils;
87 import android.util.ArrayMap;
88 import android.util.ArraySet;
89 import android.util.AtomicFile;
90 import android.util.IndentingPrintWriter;
91 import android.util.KeyValueListParser;
92 import android.util.Log;
93 import android.util.LongSparseArray;
94 import android.util.LongSparseLongArray;
95 import android.util.MutableInt;
96 import android.util.PrintWriterPrinter;
97 import android.util.Printer;
98 import android.util.Slog;
99 import android.util.SparseArray;
100 import android.util.SparseDoubleArray;
101 import android.util.SparseIntArray;
102 import android.util.SparseLongArray;
103 import android.util.TimeUtils;
104 import android.util.Xml;
105 import android.view.Display;
106 
107 import com.android.internal.annotations.GuardedBy;
108 import com.android.internal.annotations.VisibleForTesting;
109 import com.android.internal.os.BackgroundThread;
110 import com.android.internal.os.BatteryStatsHistory;
111 import com.android.internal.os.BatteryStatsHistory.HistoryStepDetailsCalculator;
112 import com.android.internal.os.BatteryStatsHistoryIterator;
113 import com.android.internal.os.BinderCallsStats;
114 import com.android.internal.os.BinderTransactionNameResolver;
115 import com.android.internal.os.Clock;
116 import com.android.internal.os.KernelCpuSpeedReader;
117 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
118 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
119 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
120 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
121 import com.android.internal.os.KernelMemoryBandwidthStats;
122 import com.android.internal.os.KernelSingleUidTimeReader;
123 import com.android.internal.os.LongArrayMultiStateCounter;
124 import com.android.internal.os.LongMultiStateCounter;
125 import com.android.internal.os.PowerProfile;
126 import com.android.internal.os.RailStats;
127 import com.android.internal.os.RpmStats;
128 import com.android.internal.power.EnergyConsumerStats;
129 import com.android.internal.power.EnergyConsumerStats.StandardPowerBucket;
130 import com.android.internal.util.ArrayUtils;
131 import com.android.internal.util.FrameworkStatsLog;
132 import com.android.internal.util.XmlUtils;
133 import com.android.modules.utils.TypedXmlPullParser;
134 import com.android.modules.utils.TypedXmlSerializer;
135 import com.android.net.module.util.NetworkCapabilitiesUtils;
136 import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
137 
138 import libcore.util.EmptyArray;
139 
140 import org.xmlpull.v1.XmlPullParser;
141 import org.xmlpull.v1.XmlPullParserException;
142 
143 import java.io.ByteArrayOutputStream;
144 import java.io.File;
145 import java.io.FileInputStream;
146 import java.io.FileNotFoundException;
147 import java.io.FileOutputStream;
148 import java.io.IOException;
149 import java.io.PrintWriter;
150 import java.lang.annotation.Retention;
151 import java.lang.annotation.RetentionPolicy;
152 import java.util.ArrayList;
153 import java.util.Arrays;
154 import java.util.Calendar;
155 import java.util.Collection;
156 import java.util.HashMap;
157 import java.util.HashSet;
158 import java.util.Iterator;
159 import java.util.LinkedList;
160 import java.util.List;
161 import java.util.Map;
162 import java.util.Queue;
163 import java.util.concurrent.Future;
164 import java.util.concurrent.atomic.AtomicInteger;
165 import java.util.concurrent.locks.ReentrantLock;
166 
167 /**
168  * All information we are collecting about things that can happen that impact
169  * battery life.  All times are represented in microseconds except where indicated
170  * otherwise.
171  */
172 public class BatteryStatsImpl extends BatteryStats {
173     private static final String TAG = "BatteryStatsImpl";
174     private static final boolean DEBUG = false;
175     public static final boolean DEBUG_ENERGY = false;
176     private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
177     private static final boolean DEBUG_BINDER_STATS = false;
178     private static final boolean DEBUG_MEMORY = false;
179 
180     // TODO: remove "tcp" from network methods, since we measure total stats.
181 
182     // Current on-disk Parcel version. Must be updated when the format of the parcelable changes
183     public static final int VERSION = 212;
184 
185     // The maximum number of names wakelocks we will keep track of
186     // per uid; once the limit is reached, we batch the remaining wakelocks
187     // in to one common name.
188     private static final int MAX_WAKELOCKS_PER_UID;
189 
190     static {
191         if (ActivityManager.isLowRamDeviceStatic()) {
192             MAX_WAKELOCKS_PER_UID = 40;
193         } else {
194             MAX_WAKELOCKS_PER_UID = 200;
195         }
196     }
197 
198     // Number of transmit power states the Wifi controller can be in.
199     private static final int NUM_WIFI_TX_LEVELS = 1;
200 
201     // Number of transmit power states the Bluetooth controller can be in.
202     private static final int NUM_BT_TX_LEVELS = 1;
203 
204     /**
205      * Holding a wakelock costs more than just using the cpu.
206      * Currently, we assign only half the cpu time to an app that is running but
207      * not holding a wakelock. The apps holding wakelocks get the rest of the blame.
208      * If no app is holding a wakelock, then the distribution is normal.
209      */
210     @VisibleForTesting
211     public static final int WAKE_LOCK_WEIGHT = 50;
212 
213     public static final int RESET_REASON_CORRUPT_FILE = 1;
214     public static final int RESET_REASON_ADB_COMMAND = 2;
215     public static final int RESET_REASON_FULL_CHARGE = 3;
216     public static final int RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE = 4;
217     public static final int RESET_REASON_PLUGGED_IN_FOR_LONG_DURATION = 5;
218 
219     protected Clock mClock;
220 
221     private final AtomicFile mStatsFile;
222     public final AtomicFile mCheckinFile;
223     public final AtomicFile mDailyFile;
224 
225     static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1;
226     static final int MSG_REPORT_POWER_CHANGE = 2;
227     static final int MSG_REPORT_CHARGING = 3;
228     static final int MSG_REPORT_RESET_STATS = 4;
229     static final long DELAY_UPDATE_WAKELOCKS = 60 * 1000;
230 
231     private static final double MILLISECONDS_IN_HOUR = 3600 * 1000;
232     private static final long MILLISECONDS_IN_YEAR = 365 * 24 * 3600 * 1000L;
233 
234     private static final LongCounter ZERO_LONG_COUNTER = new LongCounter() {
235         @Override
236         public long getCountLocked(int which) {
237             return 0;
238         }
239 
240         @Override
241         public long getCountForProcessState(int procState) {
242             return 0;
243         }
244 
245         @Override
246         public void logState(Printer pw, String prefix) {
247             pw.println(prefix + "mCount=0");
248         }
249     };
250 
251     private static final LongCounter[] ZERO_LONG_COUNTER_ARRAY =
252             new LongCounter[]{ZERO_LONG_COUNTER};
253 
254     private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
255     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
256 
257     @VisibleForTesting
258     protected KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader;
259     @VisibleForTesting
260     protected KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
261     @VisibleForTesting
262     protected KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader;
263     @VisibleForTesting
264     protected KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader;
265     @VisibleForTesting
266     protected KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader;
267     @VisibleForTesting
268     protected KernelSingleUidTimeReader mKernelSingleUidTimeReader;
269     @VisibleForTesting
270     protected SystemServerCpuThreadReader mSystemServerCpuThreadReader =
271             SystemServerCpuThreadReader.create();
272 
273     private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats
274             = new KernelMemoryBandwidthStats();
275     private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>();
276     private int[] mCpuPowerBracketMap;
277     private final CpuUsageDetails mCpuUsageDetails = new CpuUsageDetails();
278 
getKernelMemoryStats()279     public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
280         return mKernelMemoryStats;
281     }
282 
283     private static final int[] SUPPORTED_PER_PROCESS_STATE_STANDARD_ENERGY_BUCKETS = {
284             EnergyConsumerStats.POWER_BUCKET_CPU,
285             EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO,
286             EnergyConsumerStats.POWER_BUCKET_WIFI,
287             EnergyConsumerStats.POWER_BUCKET_BLUETOOTH,
288     };
289 
290     // TimeInState counters need NUM_PROCESS_STATE states in order to accommodate
291     // Uid.PROCESS_STATE_NONEXISTENT, which is outside the range of legitimate proc states.
292     private static final int PROC_STATE_TIME_COUNTER_STATE_COUNT = NUM_PROCESS_STATE + 1;
293 
294     @GuardedBy("this")
295     public boolean mPerProcStateCpuTimesAvailable = true;
296 
297     @GuardedBy("this")
298     private long mNumSingleUidCpuTimeReads;
299     @GuardedBy("this")
300     private long mCpuTimeReadsTrackingStartTimeMs = SystemClock.uptimeMillis();
301     @GuardedBy("this")
302     private int mNumUidsRemoved;
303     @GuardedBy("this")
304     private int mNumAllUidCpuTimeReads;
305 
306     /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
307     private RpmStats mTmpRpmStats = null;
308     /** The soonest the RPM stats can be updated after it was last updated. */
309     private static final long RPM_STATS_UPDATE_FREQ_MS = 1000;
310     /** Last time that RPM stats were updated by updateRpmStatsLocked. */
311     private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
312 
313     /** Container for Rail Energy Data stats. */
314     private final RailStats mTmpRailStats = new RailStats();
315 
316     /**
317      * Estimate UID modem power usage based on their estimated mobile radio active time.
318      */
319     public static final int PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME = 1;
320     /**
321      * Estimate UID modem power consumption by proportionally attributing estimated Rx and Tx
322      * power consumption individually.
323      * ModemActivityInfo must be available.
324      */
325     public static final int PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX = 2;
326     @IntDef(flag = true, prefix = "PER_UID_MODEM_MODEL_", value = {
327             PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME,
328             PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX,
329     })
330     @Retention(RetentionPolicy.SOURCE)
331     public @interface PerUidModemPowerModel {
332     }
333 
334     /**
335      * Use a queue to delay removing UIDs from {@link KernelCpuUidUserSysTimeReader},
336      * {@link KernelCpuUidActiveTimeReader}, {@link KernelCpuUidClusterTimeReader},
337      * {@link KernelCpuUidFreqTimeReader} and from the Kernel.
338      *
339      * Isolated and invalid UID info must be removed to conserve memory. However, STATSD and
340      * Batterystats both need to access UID cpu time. To resolve this race condition, only
341      * Batterystats shall remove UIDs, and a delay {@link Constants#UID_REMOVE_DELAY_MS} is
342      * implemented so that STATSD can capture those UID times before they are deleted.
343      */
344     @GuardedBy("this")
345     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
346     protected Queue<UidToRemove> mPendingRemovedUids = new LinkedList<>();
347 
348     @NonNull
copyHistory()349     BatteryStatsHistory copyHistory() {
350         return mHistory.copy();
351     }
352 
353     @VisibleForTesting
354     public final class UidToRemove {
355         private final int mStartUid;
356         private final int mEndUid;
357         private final long mUidRemovalTimestamp;
358 
359         /** Remove just one UID */
UidToRemove(int uid, long timestamp)360         public UidToRemove(int uid, long timestamp) {
361             this(uid, uid, timestamp);
362         }
363 
364         /** Remove a range of UIDs, startUid must be smaller than endUid. */
UidToRemove(int startUid, int endUid, long timestamp)365         public UidToRemove(int startUid, int endUid, long timestamp) {
366             mStartUid = startUid;
367             mEndUid = endUid;
368             mUidRemovalTimestamp = timestamp;
369         }
370 
getUidRemovalTimestamp()371         public long getUidRemovalTimestamp() {
372             return mUidRemovalTimestamp;
373         }
374 
375         @GuardedBy("BatteryStatsImpl.this")
removeLocked()376         void removeLocked() {
377             removeCpuStatsForUidRangeLocked(mStartUid, mEndUid);
378         }
379     }
380 
381     /**
382      * Listener for the battery stats reset.
383      */
384     public interface BatteryResetListener {
385 
386         /**
387          * Callback invoked immediately prior to resetting battery stats.
388          * @param resetReason One of the RESET_REASON_* constants.
389          */
prepareForBatteryStatsReset(int resetReason)390         void prepareForBatteryStatsReset(int resetReason);
391     }
392 
393     private BatteryResetListener mBatteryResetListener;
394 
395     public interface BatteryCallback {
batteryNeedsCpuUpdate()396         public void batteryNeedsCpuUpdate();
batteryPowerChanged(boolean onBattery)397         public void batteryPowerChanged(boolean onBattery);
batterySendBroadcast(Intent intent)398         public void batterySendBroadcast(Intent intent);
batteryStatsReset()399         public void batteryStatsReset();
400     }
401 
402     public interface PlatformIdleStateCallback {
fillLowPowerStats(RpmStats rpmStats)403         public void fillLowPowerStats(RpmStats rpmStats);
getSubsystemLowPowerStats()404         public String getSubsystemLowPowerStats();
405     }
406 
407     /** interface to update rail information for power monitor */
408     public interface EnergyStatsRetriever {
409         /** Function to fill the map for the rail data stats
410          * Used for power monitoring feature
411          * @param railStats
412          */
fillRailDataStats(RailStats railStats)413         void fillRailDataStats(RailStats railStats);
414     }
415 
416     public static abstract class UserInfoProvider {
417         private int[] userIds;
getUserIds()418         protected abstract @Nullable int[] getUserIds();
419         @VisibleForTesting
refreshUserIds()420         public final void refreshUserIds() {
421             userIds = getUserIds();
422         }
423         @VisibleForTesting
exists(int userId)424         public boolean exists(int userId) {
425             return userIds != null ? ArrayUtils.contains(userIds, userId) : true;
426         }
427     }
428 
429     /** Provide BatteryStatsImpl configuration choices */
430     public static class BatteryStatsConfig {
431         static final int RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG = 1 << 0;
432         static final int RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG = 1 << 1;
433 
434         private final int mFlags;
435 
BatteryStatsConfig(Builder builder)436         private BatteryStatsConfig(Builder builder) {
437             int flags = 0;
438             if (builder.mResetOnUnplugHighBatteryLevel) {
439                 flags |= RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG;
440             }
441             if (builder.mResetOnUnplugAfterSignificantCharge) {
442                 flags |= RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG;
443             }
444             mFlags = flags;
445         }
446 
447         /**
448          * Returns whether a BatteryStats reset should occur on unplug when the battery level is
449          * high.
450          */
shouldResetOnUnplugHighBatteryLevel()451         boolean shouldResetOnUnplugHighBatteryLevel() {
452             return (mFlags & RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG)
453                     == RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG;
454         }
455 
456         /**
457          * Returns whether a BatteryStats reset should occur on unplug if the battery charge a
458          * significant amount since it has been plugged in.
459          */
shouldResetOnUnplugAfterSignificantCharge()460         boolean shouldResetOnUnplugAfterSignificantCharge() {
461             return (mFlags & RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG)
462                     == RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG;
463         }
464 
465         /**
466          * Builder for BatteryStatsConfig
467          */
468         public static class Builder {
469             private boolean mResetOnUnplugHighBatteryLevel;
470             private boolean mResetOnUnplugAfterSignificantCharge;
Builder()471             public Builder() {
472                 mResetOnUnplugHighBatteryLevel = true;
473                 mResetOnUnplugAfterSignificantCharge = true;
474             }
475 
476             /**
477              * Build the BatteryStatsConfig.
478              */
build()479             public BatteryStatsConfig build() {
480                 return new BatteryStatsConfig(this);
481             }
482 
483             /**
484              * Set whether a BatteryStats reset should occur on unplug when the battery level is
485              * high.
486              */
setResetOnUnplugHighBatteryLevel(boolean reset)487             public Builder setResetOnUnplugHighBatteryLevel(boolean reset) {
488                 mResetOnUnplugHighBatteryLevel = reset;
489                 return this;
490             }
491 
492             /**
493              * Set whether a BatteryStats reset should occur on unplug if the battery charge a
494              * significant amount since it has been plugged in.
495              */
setResetOnUnplugAfterSignificantCharge(boolean reset)496             public Builder setResetOnUnplugAfterSignificantCharge(boolean reset) {
497                 mResetOnUnplugAfterSignificantCharge = reset;
498                 return this;
499             }
500         }
501 
502     }
503 
504     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
505 
506     private final Runnable mDeferSetCharging = new Runnable() {
507         @Override
508         public void run() {
509             synchronized (BatteryStatsImpl.this) {
510                 if (mOnBattery) {
511                     // if the device gets unplugged in the time between this runnable being
512                     // executed and the lock being taken, we don't want to set charging state
513                     return;
514                 }
515                 boolean changed = setChargingLocked(true);
516                 if (changed) {
517                     final long uptimeMs = mClock.uptimeMillis();
518                     final long elapsedRealtimeMs = mClock.elapsedRealtime();
519                     mHistory.writeHistoryItem(elapsedRealtimeMs, uptimeMs);
520                 }
521             }
522         }
523     };
524 
525     public final EnergyStatsRetriever mEnergyConsumerRetriever;
526 
527     /**
528      * This handler is running on {@link BackgroundThread}.
529      */
530     final class MyHandler extends Handler {
MyHandler(Looper looper)531         public MyHandler(Looper looper) {
532             super(looper, null, true);
533         }
534 
535         @Override
handleMessage(Message msg)536         public void handleMessage(Message msg) {
537             BatteryCallback cb = mCallback;
538             switch (msg.what) {
539                 case MSG_REPORT_CPU_UPDATE_NEEDED:
540                     if (cb != null) {
541                         cb.batteryNeedsCpuUpdate();
542                     }
543                     break;
544                 case MSG_REPORT_POWER_CHANGE:
545                     if (cb != null) {
546                         cb.batteryPowerChanged(msg.arg1 != 0);
547                     }
548                     break;
549                 case MSG_REPORT_CHARGING:
550                     if (cb != null) {
551                         final String action;
552                         synchronized (BatteryStatsImpl.this) {
553                             action = mCharging ? BatteryManager.ACTION_CHARGING
554                                     : BatteryManager.ACTION_DISCHARGING;
555                         }
556                         Intent intent = new Intent(action);
557                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
558                         cb.batterySendBroadcast(intent);
559                     }
560                     break;
561                 case MSG_REPORT_RESET_STATS:
562                     if (cb != null) {
563                         cb.batteryStatsReset();
564                     }
565                 }
566         }
567     }
568 
postBatteryNeedsCpuUpdateMsg()569     public void postBatteryNeedsCpuUpdateMsg() {
570         mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED);
571     }
572 
573     /**
574      * Update per-freq cpu times for the supplied UID.
575      */
576     @GuardedBy("this")
577     @SuppressWarnings("GuardedBy")    // errorprone false positive on getProcStateTimeCounter
578     @VisibleForTesting
updateProcStateCpuTimesLocked(int uid, long elapsedRealtimeMs, long uptimeMs)579     public void updateProcStateCpuTimesLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
580         if (!initKernelSingleUidTimeReaderLocked()) {
581             return;
582         }
583 
584         final Uid u = getUidStatsLocked(uid);
585 
586         mNumSingleUidCpuTimeReads++;
587 
588         LongArrayMultiStateCounter onBatteryCounter =
589                 u.getProcStateTimeCounter(elapsedRealtimeMs).getCounter();
590         LongArrayMultiStateCounter onBatteryScreenOffCounter =
591                 u.getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter();
592 
593         if (isUsageHistoryEnabled()) {
594             LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
595                     getCpuTimeInFreqContainer();
596             mKernelSingleUidTimeReader.addDelta(uid, onBatteryCounter, elapsedRealtimeMs,
597                     deltaContainer);
598             recordCpuUsage(uid, deltaContainer, elapsedRealtimeMs, uptimeMs);
599         } else {
600             mKernelSingleUidTimeReader.addDelta(uid, onBatteryCounter, elapsedRealtimeMs);
601         }
602         mKernelSingleUidTimeReader.addDelta(uid, onBatteryScreenOffCounter, elapsedRealtimeMs);
603 
604         if (u.mChildUids != null) {
605             LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
606                     getCpuTimeInFreqContainer();
607             int childUidCount = u.mChildUids.size();
608             for (int j = childUidCount - 1; j >= 0; --j) {
609                 LongArrayMultiStateCounter cpuTimeInFreqCounter =
610                         u.mChildUids.valueAt(j).cpuTimeInFreqCounter;
611                 if (cpuTimeInFreqCounter != null) {
612                     mKernelSingleUidTimeReader.addDelta(u.mChildUids.keyAt(j),
613                             cpuTimeInFreqCounter, elapsedRealtimeMs, deltaContainer);
614                     onBatteryCounter.addCounts(deltaContainer);
615                     if (isUsageHistoryEnabled()) {
616                         recordCpuUsage(uid, deltaContainer, elapsedRealtimeMs, uptimeMs);
617                     }
618                     onBatteryScreenOffCounter.addCounts(deltaContainer);
619                 }
620             }
621         }
622     }
623 
recordCpuUsage(int uid, LongArrayMultiStateCounter.LongArrayContainer cpuUsage, long elapsedRealtimeMs, long uptimeMs)624     private void recordCpuUsage(int uid, LongArrayMultiStateCounter.LongArrayContainer cpuUsage,
625             long elapsedRealtimeMs, long uptimeMs) {
626         if (!cpuUsage.combineValues(mCpuUsageDetails.cpuUsageMs, mCpuPowerBracketMap)) {
627             return;
628         }
629 
630         mCpuUsageDetails.uid = uid;
631         mHistory.recordCpuUsage(elapsedRealtimeMs, uptimeMs, mCpuUsageDetails);
632     }
633 
634     /**
635      * Removes kernel CPU stats for removed UIDs, in the order they were added to the
636      * mPendingRemovedUids queue.
637      */
638     @GuardedBy("this")
639     @SuppressWarnings("GuardedBy")    // errorprone false positive on removeLocked
clearPendingRemovedUidsLocked()640     public void clearPendingRemovedUidsLocked() {
641         long cutOffTimeMs = mClock.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS;
642         while (!mPendingRemovedUids.isEmpty()
643                 && mPendingRemovedUids.peek().getUidRemovalTimestamp() < cutOffTimeMs) {
644             mPendingRemovedUids.poll().removeLocked();
645         }
646     }
647 
648     /**
649      * When the battery/screen state changes, we don't attribute the cpu times to any process
650      * but we still need to take snapshots of all uids to get correct deltas later on.
651      */
652     @SuppressWarnings("GuardedBy")    // errorprone false positive on getProcStateTimeCounter
updateCpuTimesForAllUids()653     public void updateCpuTimesForAllUids() {
654         synchronized (BatteryStatsImpl.this) {
655             if (!trackPerProcStateCpuTimes()) {
656                 return;
657             }
658 
659             if(!initKernelSingleUidTimeReaderLocked()) {
660                 return;
661             }
662 
663             // TODO(b/197162116): just get a list of UIDs
664             final SparseArray<long[]> allUidCpuFreqTimesMs =
665                     mCpuUidFreqTimeReader.getAllUidCpuFreqTimeMs();
666             for (int i = allUidCpuFreqTimesMs.size() - 1; i >= 0; --i) {
667                 final int uid = allUidCpuFreqTimesMs.keyAt(i);
668                 final int parentUid = mapUid(uid);
669                 final Uid u = getAvailableUidStatsLocked(parentUid);
670                 if (u == null) {
671                     continue;
672                 }
673 
674                 final int procState = u.mProcessState;
675                 if (procState == Uid.PROCESS_STATE_NONEXISTENT) {
676                     continue;
677                 }
678 
679                 final long elapsedRealtimeMs = mClock.elapsedRealtime();
680                 final long uptimeMs = mClock.uptimeMillis();
681                 final LongArrayMultiStateCounter onBatteryCounter =
682                         u.getProcStateTimeCounter(elapsedRealtimeMs).getCounter();
683                 final LongArrayMultiStateCounter onBatteryScreenOffCounter =
684                         u.getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter();
685 
686                 if (uid == parentUid || Process.isSdkSandboxUid(uid)) {
687                     if (isUsageHistoryEnabled()) {
688                         LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
689                                 getCpuTimeInFreqContainer();
690                         mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryCounter,
691                                 elapsedRealtimeMs, deltaContainer);
692                         recordCpuUsage(parentUid, deltaContainer, elapsedRealtimeMs, uptimeMs);
693                     } else {
694                         mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryCounter,
695                                 elapsedRealtimeMs);
696                     }
697                     mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryScreenOffCounter,
698                             elapsedRealtimeMs);
699                 } else {
700                     Uid.ChildUid childUid = u.getChildUid(uid);
701                     if (childUid != null) {
702                         final LongArrayMultiStateCounter counter = childUid.cpuTimeInFreqCounter;
703                         if (counter != null) {
704                             final LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
705                                     getCpuTimeInFreqContainer();
706                             mKernelSingleUidTimeReader.addDelta(uid, counter, elapsedRealtimeMs,
707                                     deltaContainer);
708                             onBatteryCounter.addCounts(deltaContainer);
709                             if (isUsageHistoryEnabled()) {
710                                 recordCpuUsage(uid, deltaContainer, elapsedRealtimeMs, uptimeMs);
711                             }
712                             onBatteryScreenOffCounter.addCounts(deltaContainer);
713                         }
714                     }
715                 }
716             }
717         }
718     }
719 
720     @GuardedBy("this")
initKernelSingleUidTimeReaderLocked()721     private boolean initKernelSingleUidTimeReaderLocked() {
722         if (mKernelSingleUidTimeReader == null) {
723             if (mPowerProfile == null) {
724                 return false;
725             }
726             if (mCpuFreqs == null) {
727                 mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
728             }
729             if (mCpuFreqs != null) {
730                 mKernelSingleUidTimeReader = new KernelSingleUidTimeReader(mCpuFreqs.length);
731             } else {
732                 mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.allUidTimesAvailable();
733                 return false;
734             }
735         }
736         mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.allUidTimesAvailable()
737                 && mKernelSingleUidTimeReader.singleUidCpuTimesAvailable();
738         return true;
739     }
740 
741     public interface ExternalStatsSync {
742         int UPDATE_CPU = 0x01;
743         int UPDATE_WIFI = 0x02;
744         int UPDATE_RADIO = 0x04;
745         int UPDATE_BT = 0x08;
746         int UPDATE_RPM = 0x10;
747         int UPDATE_DISPLAY = 0x20;
748         int UPDATE_CAMERA = 0x40;
749         int RESET = 0x80;
750 
751         int UPDATE_ALL =
752                 UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM | UPDATE_DISPLAY
753                         | UPDATE_CAMERA;
754 
755         int UPDATE_ON_PROC_STATE_CHANGE = UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
756 
757         int UPDATE_ON_RESET = UPDATE_ALL | RESET;
758 
759         @IntDef(flag = true, prefix = "UPDATE_", value = {
760                 UPDATE_CPU,
761                 UPDATE_WIFI,
762                 UPDATE_RADIO,
763                 UPDATE_BT,
764                 UPDATE_RPM,
765                 UPDATE_DISPLAY,
766                 UPDATE_CAMERA,
767                 UPDATE_ALL,
768         })
769         @Retention(RetentionPolicy.SOURCE)
770         public @interface ExternalUpdateFlag {
771         }
772 
scheduleSync(String reason, int flags)773         Future<?> scheduleSync(String reason, int flags);
scheduleCpuSyncDueToRemovedUid(int uid)774         Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
775 
776         /**
777          * Schedule a sync because of a screen state change.
778          */
scheduleSyncDueToScreenStateChange(int flags, boolean onBattery, boolean onBatteryScreenOff, int screenState, int[] perDisplayScreenStates)779         Future<?> scheduleSyncDueToScreenStateChange(int flags, boolean onBattery,
780                 boolean onBatteryScreenOff, int screenState, int[] perDisplayScreenStates);
scheduleCpuSyncDueToWakelockChange(long delayMillis)781         Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis);
cancelCpuSyncDueToWakelockChange()782         void cancelCpuSyncDueToWakelockChange();
scheduleSyncDueToBatteryLevelChange(long delayMillis)783         Future<?> scheduleSyncDueToBatteryLevelChange(long delayMillis);
784         /** Schedule removal of UIDs corresponding to a removed user */
scheduleCleanupDueToRemovedUser(int userId)785         Future<?> scheduleCleanupDueToRemovedUser(int userId);
786         /** Schedule a sync because of a process state change */
scheduleSyncDueToProcessStateChange(int flags, long delayMillis)787         void scheduleSyncDueToProcessStateChange(int flags, long delayMillis);
788     }
789 
790     public Handler mHandler;
791     private ExternalStatsSync mExternalSync = null;
792     @VisibleForTesting
793     protected UserInfoProvider mUserInfoProvider = null;
794 
795     private BatteryCallback mCallback;
796 
797     /**
798      * Mapping isolated uids to the actual owning app uid.
799      */
800     private final SparseIntArray mIsolatedUids = new SparseIntArray();
801     /**
802      * Internal reference count of isolated uids.
803      */
804     private final SparseIntArray mIsolatedUidRefCounts = new SparseIntArray();
805 
806     /**
807      * The statistics we have collected organized by uids.
808      */
809     private final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
810 
811     // A set of pools of currently active timers.  When a timer is queried, we will divide the
812     // elapsed time by the number of active timers to arrive at that timer's share of the time.
813     // In order to do this, we must refresh each timer whenever the number of active timers
814     // changes.
815     @VisibleForTesting
816     protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
817     private final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
818     private final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
819     private final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
820     private final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
821     private final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
822     private final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
823     private final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
824     private final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
825     private final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers =
826             new SparseArray<>();
827     private final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
828     private final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
829     private final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
830     private final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
831     private final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
832 
833     // Last partial timers we use for distributing CPU usage.
834     @VisibleForTesting
835     protected ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
836 
837     // These are the objects that will want to do something when the device
838     // is unplugged from power.
839     protected final TimeBase mOnBatteryTimeBase = new TimeBase(true);
840 
841     // These are the objects that will want to do something when the device
842     // is unplugged from power *and* the screen is off or doze.
843     protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(true);
844 
845     private boolean mSystemReady;
846     private boolean mShuttingDown;
847 
848     private final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
849     private final HistoryStepDetailsCalculatorImpl mStepDetailsCalculator =
850             new HistoryStepDetailsCalculatorImpl();
851 
852     private boolean mHaveBatteryLevel = false;
853     private boolean mBatteryPluggedIn;
854     private long mBatteryPluggedInRealTimeMs = 0;
855     private int mBatteryStatus;
856     private int mBatteryLevel;
857     private int mBatteryPlugType;
858     private int mBatteryChargeUah;
859     private int mBatteryHealth;
860     private int mBatteryTemperature;
861     private int mBatteryVoltageMv = -1;
862 
863     @NonNull
864     private final BatteryStatsHistory mHistory;
865 
866     int mStartCount;
867 
868     /**
869      * Set to true when a reset occurs, informing us that the next time BatteryExternalStatsWorker
870      * gives us data, we mustn't process it since this data includes pre-reset-period data.
871      */
872     @GuardedBy("this")
873     boolean mIgnoreNextExternalStats = false;
874 
875     long mStartClockTimeMs;
876     String mStartPlatformVersion;
877     String mEndPlatformVersion;
878 
879     long mUptimeUs;
880     long mUptimeStartUs;
881     long mRealtimeUs;
882     long mRealtimeStartUs;
883 
884     int mWakeLockNesting;
885     boolean mWakeLockImportant;
886     public boolean mRecordAllHistory;
887     boolean mNoAutoReset;
888 
889     /**
890      * Overall screen state. For multidisplay devices, this represents the current highest screen
891      * state of the displays.
892      */
893     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
894     protected int mScreenState = Display.STATE_UNKNOWN;
895     /**
896      * Overall screen on timer. For multidisplay devices, this represents the time spent with at
897      * least one display in the screen on state.
898      */
899     StopwatchTimer mScreenOnTimer;
900     /**
901      * Overall screen doze timer. For multidisplay devices, this represents the time spent with
902      * screen doze being the highest screen state.
903      */
904     StopwatchTimer mScreenDozeTimer;
905     /**
906      * Overall screen brightness bin. For multidisplay devices, this represents the current
907      * brightest screen.
908      */
909     int mScreenBrightnessBin = -1;
910     /**
911      * Overall screen brightness timers. For multidisplay devices, the {@link mScreenBrightnessBin}
912      * timer will be active at any given time
913      */
914     final StopwatchTimer[] mScreenBrightnessTimer =
915             new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
916 
917     boolean mPretendScreenOff;
918 
919     private static class DisplayBatteryStats {
920         /**
921          * Per display screen state.
922          */
923         public int screenState = Display.STATE_UNKNOWN;
924         /**
925          * Per display screen on timers.
926          */
927         public StopwatchTimer screenOnTimer;
928         /**
929          * Per display screen doze timers.
930          */
931         public StopwatchTimer screenDozeTimer;
932         /**
933          * Per display screen brightness bins.
934          */
935         public int screenBrightnessBin = -1;
936         /**
937          * Per display screen brightness timers.
938          */
939         public StopwatchTimer[] screenBrightnessTimers =
940                 new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
941         /**
942          * Per display screen state the last time {@link #updateDisplayEnergyConsumerStatsLocked}
943          * was called.
944          */
945         public int screenStateAtLastEnergyMeasurement = Display.STATE_UNKNOWN;
946 
DisplayBatteryStats(Clock clock, TimeBase timeBase)947         DisplayBatteryStats(Clock clock, TimeBase timeBase) {
948             screenOnTimer = new StopwatchTimer(clock, null, -1, null,
949                     timeBase);
950             screenDozeTimer = new StopwatchTimer(clock, null, -1, null,
951                     timeBase);
952             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
953                 screenBrightnessTimers[i] = new StopwatchTimer(clock, null, -100 - i, null,
954                         timeBase);
955             }
956         }
957 
958         /**
959          * Reset display timers.
960          */
reset(long elapsedRealtimeUs)961         public void reset(long elapsedRealtimeUs) {
962             screenOnTimer.reset(false, elapsedRealtimeUs);
963             screenDozeTimer.reset(false, elapsedRealtimeUs);
964             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
965                 screenBrightnessTimers[i].reset(false, elapsedRealtimeUs);
966             }
967         }
968 
969         /**
970          * Write data to summary parcel
971          */
writeSummaryToParcel(Parcel out, long elapsedRealtimeUs)972         public void writeSummaryToParcel(Parcel out, long elapsedRealtimeUs) {
973             screenOnTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
974             screenDozeTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
975             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
976                 screenBrightnessTimers[i].writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
977             }
978         }
979 
980         /**
981          * Read data from summary parcel
982          */
readSummaryFromParcel(Parcel in)983         public void readSummaryFromParcel(Parcel in) {
984             screenOnTimer.readSummaryFromParcelLocked(in);
985             screenDozeTimer.readSummaryFromParcelLocked(in);
986             for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
987                 screenBrightnessTimers[i].readSummaryFromParcelLocked(in);
988             }
989         }
990     }
991 
992     DisplayBatteryStats[] mPerDisplayBatteryStats;
993 
994     private int mDisplayMismatchWtfCount = 0;
995 
996     boolean mInteractive;
997     StopwatchTimer mInteractiveTimer;
998 
999     boolean mPowerSaveModeEnabled;
1000     StopwatchTimer mPowerSaveModeEnabledTimer;
1001 
1002     boolean mDeviceIdling;
1003     StopwatchTimer mDeviceIdlingTimer;
1004 
1005     boolean mDeviceLightIdling;
1006     StopwatchTimer mDeviceLightIdlingTimer;
1007 
1008     int mDeviceIdleMode;
1009     long mLastIdleTimeStartMs;
1010     long mLongestLightIdleTimeMs;
1011     long mLongestFullIdleTimeMs;
1012     StopwatchTimer mDeviceIdleModeLightTimer;
1013     StopwatchTimer mDeviceIdleModeFullTimer;
1014 
1015     boolean mPhoneOn;
1016     StopwatchTimer mPhoneOnTimer;
1017 
1018     int mAudioOnNesting;
1019     StopwatchTimer mAudioOnTimer;
1020 
1021     int mVideoOnNesting;
1022     StopwatchTimer mVideoOnTimer;
1023 
1024     int mFlashlightOnNesting;
1025     StopwatchTimer mFlashlightOnTimer;
1026 
1027     int mCameraOnNesting;
1028     StopwatchTimer mCameraOnTimer;
1029 
1030     private static final int USB_DATA_UNKNOWN = 0;
1031     private static final int USB_DATA_DISCONNECTED = 1;
1032     private static final int USB_DATA_CONNECTED = 2;
1033     int mUsbDataState = USB_DATA_UNKNOWN;
1034 
1035     int mGpsSignalQualityBin = -1;
1036     final StopwatchTimer[] mGpsSignalQualityTimer =
1037         new StopwatchTimer[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
1038 
1039     int mPhoneSignalStrengthBin = -1;
1040     int mPhoneSignalStrengthBinRaw = -1;
1041     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
1042             new StopwatchTimer[CellSignalStrength.getNumSignalStrengthLevels()];
1043 
1044     StopwatchTimer mPhoneSignalScanningTimer;
1045 
1046     int mPhoneDataConnectionType = -1;
1047     final StopwatchTimer[] mPhoneDataConnectionsTimer =
1048             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
1049 
1050     @RadioAccessTechnology
1051     int mActiveRat = RADIO_ACCESS_TECHNOLOGY_OTHER;
1052 
1053     private static class RadioAccessTechnologyBatteryStats {
1054         /**
1055          * This RAT is currently being used.
1056          */
1057         private boolean mActive = false;
1058         /**
1059          * Current active frequency range for this RAT.
1060          */
1061         @ServiceState.FrequencyRange
1062         private int mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
1063         /**
1064          * Current signal strength for this RAT.
1065          */
1066         private int mSignalStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
1067         /**
1068          * Timers for each combination of frequency range and signal strength.
1069          */
1070         public final StopwatchTimer[][] perStateTimers;
1071         /**
1072          * Counters tracking the time (in milliseconds) spent transmitting data in a given state.
1073          */
1074         @Nullable
1075         private LongSamplingCounter[][] mPerStateTxDurationMs = null;
1076         /**
1077          * Counters tracking the time (in milliseconds) spent receiving data in at given frequency.
1078          */
1079         @Nullable
1080         private LongSamplingCounter[] mPerFrequencyRxDurationMs = null;
1081 
RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase)1082         RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase) {
1083             perStateTimers =
1084                     new StopwatchTimer[freqCount][CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS];
1085             for (int i = 0; i < freqCount; i++) {
1086                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1087                     perStateTimers[i][j] = new StopwatchTimer(clock, null, -1, null, timeBase);
1088                 }
1089             }
1090         }
1091 
1092         /**
1093          * Note this RAT is currently being used.
1094          */
noteActive(boolean active, long elapsedRealtimeMs)1095         public void noteActive(boolean active, long elapsedRealtimeMs) {
1096             if (mActive == active) return;
1097             mActive = active;
1098             if (mActive) {
1099                 perStateTimers[mFrequencyRange][mSignalStrength].startRunningLocked(
1100                         elapsedRealtimeMs);
1101             } else {
1102                 perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(
1103                         elapsedRealtimeMs);
1104             }
1105         }
1106 
1107         /**
1108          * Note current frequency range has changed.
1109          */
noteFrequencyRange(@erviceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs)1110         public void noteFrequencyRange(@ServiceState.FrequencyRange int frequencyRange,
1111                 long elapsedRealtimeMs) {
1112             if (mFrequencyRange == frequencyRange) return;
1113 
1114             if (!mActive) {
1115                 // RAT not in use, note the frequency change and move on.
1116                 mFrequencyRange = frequencyRange;
1117                 return;
1118             }
1119             perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(elapsedRealtimeMs);
1120             perStateTimers[frequencyRange][mSignalStrength].startRunningLocked(elapsedRealtimeMs);
1121             mFrequencyRange = frequencyRange;
1122         }
1123 
1124         /**
1125          * Note current signal strength has changed.
1126          */
noteSignalStrength(int signalStrength, long elapsedRealtimeMs)1127         public void noteSignalStrength(int signalStrength, long elapsedRealtimeMs) {
1128             if (mSignalStrength == signalStrength) return;
1129 
1130             if (!mActive) {
1131                 // RAT not in use, note the signal strength change and move on.
1132                 mSignalStrength = signalStrength;
1133                 return;
1134             }
1135             perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(elapsedRealtimeMs);
1136             perStateTimers[mFrequencyRange][signalStrength].startRunningLocked(elapsedRealtimeMs);
1137             mSignalStrength = signalStrength;
1138         }
1139 
1140         /**
1141          * Returns the duration in milliseconds spent in a given state since the last mark.
1142          */
getTimeSinceMark(@erviceState.FrequencyRange int frequencyRange, int signalStrength, long elapsedRealtimeMs)1143         public long getTimeSinceMark(@ServiceState.FrequencyRange int frequencyRange,
1144                 int signalStrength, long elapsedRealtimeMs) {
1145             return perStateTimers[frequencyRange][signalStrength].getTimeSinceMarkLocked(
1146                     elapsedRealtimeMs * 1000) / 1000;
1147         }
1148 
1149         /**
1150          * Set mark for all timers.
1151          */
setMark(long elapsedRealtimeMs)1152         public void setMark(long elapsedRealtimeMs) {
1153             final int size = perStateTimers.length;
1154             for (int i = 0; i < size; i++) {
1155                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1156                     perStateTimers[i][j].setMark(elapsedRealtimeMs);
1157                 }
1158             }
1159         }
1160 
1161         /**
1162          * Returns numbers of frequencies tracked for this RAT.
1163          */
getFrequencyRangeCount()1164         public int getFrequencyRangeCount() {
1165             return perStateTimers.length;
1166         }
1167 
1168         /**
1169          * Add TX time for a given state.
1170          */
incrementTxDuration(@erviceState.FrequencyRange int frequencyRange, int signalStrength, long durationMs)1171         public void incrementTxDuration(@ServiceState.FrequencyRange int frequencyRange,
1172                 int signalStrength, long durationMs) {
1173             getTxDurationCounter(frequencyRange, signalStrength, true).addCountLocked(durationMs);
1174         }
1175 
1176         /**
1177          * Add TX time for a given frequency.
1178          */
incrementRxDuration(@erviceState.FrequencyRange int frequencyRange, long durationMs)1179         public void incrementRxDuration(@ServiceState.FrequencyRange int frequencyRange,
1180                 long durationMs) {
1181             getRxDurationCounter(frequencyRange, true).addCountLocked(durationMs);
1182         }
1183 
1184         /**
1185          * Reset radio access technology timers and counts.
1186          */
reset(long elapsedRealtimeUs)1187         public void reset(long elapsedRealtimeUs) {
1188             final int size = perStateTimers.length;
1189             for (int i = 0; i < size; i++) {
1190                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1191                     perStateTimers[i][j].reset(false, elapsedRealtimeUs);
1192                     if (mPerStateTxDurationMs == null) continue;
1193                     mPerStateTxDurationMs[i][j].reset(false, elapsedRealtimeUs);
1194                 }
1195                 if (mPerFrequencyRxDurationMs == null) continue;
1196                 mPerFrequencyRxDurationMs[i].reset(false, elapsedRealtimeUs);
1197             }
1198         }
1199 
1200         /**
1201          * Write data to summary parcel
1202          */
writeSummaryToParcel(Parcel out, long elapsedRealtimeUs)1203         public void writeSummaryToParcel(Parcel out, long elapsedRealtimeUs) {
1204             final int freqCount = perStateTimers.length;
1205             out.writeInt(freqCount);
1206             out.writeInt(CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS);
1207             for (int i = 0; i < freqCount; i++) {
1208                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1209                     perStateTimers[i][j].writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
1210                 }
1211             }
1212 
1213             if (mPerStateTxDurationMs == null) {
1214                 out.writeInt(0);
1215             } else {
1216                 out.writeInt(1);
1217                 for (int i = 0; i < freqCount; i++) {
1218                     for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
1219                         mPerStateTxDurationMs[i][j].writeSummaryFromParcelLocked(out);
1220                     }
1221                 }
1222             }
1223 
1224             if (mPerFrequencyRxDurationMs == null) {
1225                 out.writeInt(0);
1226             } else {
1227                 out.writeInt(1);
1228                 for (int i = 0; i < freqCount; i++) {
1229                     mPerFrequencyRxDurationMs[i].writeSummaryFromParcelLocked(out);
1230                 }
1231             }
1232         }
1233 
1234         /**
1235          * Read data from summary parcel
1236          */
readSummaryFromParcel(Parcel in)1237         public void readSummaryFromParcel(Parcel in) {
1238             final int oldFreqCount = in.readInt();
1239             final int oldSignalStrengthCount = in.readInt();
1240             final int currFreqCount = perStateTimers.length;
1241             final int currSignalStrengthCount = CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS;
1242 
1243             for (int freq = 0; freq < oldFreqCount; freq++) {
1244                 for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
1245                     if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
1246                         // Mismatch with the summary parcel. Consume the data but don't use it.
1247                         final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
1248                                 new TimeBase());
1249                         // Consume perStateTimers data.
1250                         temp.readSummaryFromParcelLocked(in);
1251                     } else {
1252                         perStateTimers[freq][strength].readSummaryFromParcelLocked(in);
1253                     }
1254                 }
1255             }
1256 
1257             if (in.readInt() == 1) {
1258                 for (int freq = 0; freq < oldFreqCount; freq++) {
1259                     for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
1260                         if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
1261                             // Mismatch with the summary parcel. Consume the data but don't use it.
1262                             final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
1263                                     new TimeBase());
1264                             // Consume mPerStateTxDurationMs data.
1265                             temp.readSummaryFromParcelLocked(in);
1266                         }
1267                         getTxDurationCounter(freq, strength, true).readSummaryFromParcelLocked(in);
1268                     }
1269                 }
1270             }
1271 
1272             if (in.readInt() == 1) {
1273                 for (int freq = 0; freq < oldFreqCount; freq++) {
1274                     if (freq >= currFreqCount) {
1275                         // Mismatch with the summary parcel. Consume the data but don't use it.
1276                         final StopwatchTimer
1277                                 temp = new StopwatchTimer(null, null, -1, null, new TimeBase());
1278                         // Consume mPerFrequencyRxDurationMs data.
1279                         temp.readSummaryFromParcelLocked(in);
1280                         continue;
1281                     }
1282                     getRxDurationCounter(freq, true).readSummaryFromParcelLocked(in);
1283                 }
1284             }
1285         }
1286 
getTxDurationCounter( @erviceState.FrequencyRange int frequencyRange, int signalStrength, boolean make)1287         private LongSamplingCounter getTxDurationCounter(
1288                 @ServiceState.FrequencyRange int frequencyRange, int signalStrength, boolean make) {
1289             if (mPerStateTxDurationMs == null) {
1290                 if (!make) return null;
1291 
1292                 final int freqCount = getFrequencyRangeCount();
1293                 final int signalStrengthCount = perStateTimers[0].length;
1294                 final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
1295                 mPerStateTxDurationMs = new LongSamplingCounter[freqCount][signalStrengthCount];
1296                 for (int freq = 0; freq < freqCount; freq++) {
1297                     for (int strength = 0; strength < signalStrengthCount; strength++) {
1298                         mPerStateTxDurationMs[freq][strength] = new LongSamplingCounter(timeBase);
1299                     }
1300                 }
1301             }
1302             if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
1303                 Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
1304                         + ") requested in getTxDurationCounter");
1305                 return null;
1306             }
1307             if (signalStrength < 0 || signalStrength >= perStateTimers[0].length) {
1308                 Slog.w(TAG, "Unexpected signal strength (" + signalStrength
1309                         + ") requested in getTxDurationCounter");
1310                 return null;
1311             }
1312             return mPerStateTxDurationMs[frequencyRange][signalStrength];
1313         }
1314 
getRxDurationCounter( @erviceState.FrequencyRange int frequencyRange, boolean make)1315         private LongSamplingCounter getRxDurationCounter(
1316                 @ServiceState.FrequencyRange int frequencyRange, boolean make) {
1317             if (mPerFrequencyRxDurationMs == null) {
1318                 if (!make) return null;
1319 
1320                 final int freqCount = getFrequencyRangeCount();
1321                 final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
1322                 mPerFrequencyRxDurationMs = new LongSamplingCounter[freqCount];
1323                 for (int freq = 0; freq < freqCount; freq++) {
1324                     mPerFrequencyRxDurationMs[freq] = new LongSamplingCounter(timeBase);
1325                 }
1326             }
1327             if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
1328                 Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
1329                         + ") requested in getRxDurationCounter");
1330                 return null;
1331             }
1332             return mPerFrequencyRxDurationMs[frequencyRange];
1333         }
1334     }
1335 
1336     /**
1337      * Number of frequency ranges, keep in sync with {@link ServiceState.FrequencyRange}
1338      */
1339     private static final int NR_FREQUENCY_COUNT = 5;
1340 
1341     RadioAccessTechnologyBatteryStats[] mPerRatBatteryStats =
1342             new RadioAccessTechnologyBatteryStats[RADIO_ACCESS_TECHNOLOGY_COUNT];
1343 
1344     @GuardedBy("this")
getRatBatteryStatsLocked( @adioAccessTechnology int rat)1345     private RadioAccessTechnologyBatteryStats getRatBatteryStatsLocked(
1346             @RadioAccessTechnology int rat) {
1347         RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
1348         if (stats == null) {
1349             final int freqCount = rat == RADIO_ACCESS_TECHNOLOGY_NR ? NR_FREQUENCY_COUNT : 1;
1350             stats = new RadioAccessTechnologyBatteryStats(freqCount, mClock, mOnBatteryTimeBase);
1351             mPerRatBatteryStats[rat] = stats;
1352         }
1353         return stats;
1354     }
1355 
1356     final LongSamplingCounter[] mNetworkByteActivityCounters =
1357             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
1358 
1359     final LongSamplingCounter[] mNetworkPacketActivityCounters =
1360             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
1361 
1362     /**
1363      * The WiFi Overall wakelock timer
1364      * This timer tracks the actual aggregate time for which MC wakelocks are enabled
1365      * since addition of per UID timers would not result in an accurate value due to overlapp of
1366      * per uid wakelock timers
1367      */
1368     StopwatchTimer mWifiMulticastWakelockTimer;
1369 
1370     /**
1371      * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
1372      */
1373     ControllerActivityCounterImpl mWifiActivity;
1374 
1375     /**
1376      * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
1377      */
1378     ControllerActivityCounterImpl mBluetoothActivity;
1379 
1380     /**
1381      * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
1382      */
1383     ControllerActivityCounterImpl mModemActivity;
1384 
1385     /**
1386      * Whether the device supports WiFi controller energy reporting. This is set to true on
1387      * the first WiFi energy report. See {@link #mWifiActivity}.
1388      */
1389     boolean mHasWifiReporting = false;
1390 
1391     /**
1392      * Whether the device supports Bluetooth controller energy reporting. This is set to true on
1393      * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
1394      */
1395     boolean mHasBluetoothReporting = false;
1396 
1397     /**
1398      * Whether the device supports Modem controller energy reporting. This is set to true on
1399      * the first Modem energy report. See {@link #mModemActivity}.
1400      */
1401     boolean mHasModemReporting = false;
1402 
1403     boolean mWifiOn;
1404     StopwatchTimer mWifiOnTimer;
1405 
1406     boolean mGlobalWifiRunning;
1407     StopwatchTimer mGlobalWifiRunningTimer;
1408 
1409     int mWifiState = -1;
1410     final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
1411 
1412     int mWifiSupplState = -1;
1413     final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
1414 
1415     int mWifiSignalStrengthBin = -1;
1416     final StopwatchTimer[] mWifiSignalStrengthsTimer =
1417             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
1418 
1419     StopwatchTimer mWifiActiveTimer;
1420 
1421     int mBluetoothScanNesting;
1422     StopwatchTimer mBluetoothScanTimer;
1423 
1424     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
1425     long mMobileRadioActiveStartTimeMs;
1426     StopwatchTimer mMobileRadioActiveTimer;
1427     StopwatchTimer mMobileRadioActivePerAppTimer;
1428     LongSamplingCounter mMobileRadioActiveAdjustedTime;
1429     LongSamplingCounter mMobileRadioActiveUnknownTime;
1430     LongSamplingCounter mMobileRadioActiveUnknownCount;
1431 
1432     /**
1433      * The soonest the Mobile Radio stats can be updated due to a mobile radio power state change
1434      * after it was last updated.
1435      */
1436     @VisibleForTesting
1437     protected static final long MOBILE_RADIO_POWER_STATE_UPDATE_FREQ_MS = 1000 * 60 * 10;
1438 
1439     int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
1440 
1441     @GuardedBy("this")
1442     @VisibleForTesting
1443     protected @Nullable EnergyConsumerStats.Config mEnergyConsumerStatsConfig;
1444 
1445     /**
1446      * Accumulated global (generally, device-wide total) charge consumption of various consumers
1447      * while on battery.
1448      * Its '<b>custom</b> power buckets' correspond to the
1449      * {@link android.hardware.power.stats.EnergyConsumer.ordinal}s of (custom) energy consumer
1450      * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
1451      *
1452      * If energy consumer data is completely unavailable this will be null.
1453      */
1454     @GuardedBy("this")
1455     @VisibleForTesting
1456     @Nullable
1457     protected EnergyConsumerStats mGlobalEnergyConsumerStats;
1458     /** Bluetooth Power calculator for attributing bluetooth EnergyConsumer to uids */
1459     @Nullable BluetoothPowerCalculator mBluetoothPowerCalculator = null;
1460     /** Cpu Power calculator for attributing cpu EnergyConsumer to uids */
1461     @Nullable CpuPowerCalculator mCpuPowerCalculator = null;
1462     /** Mobile Radio Power calculator for attributing radio EnergyConsumer to uids */
1463     @Nullable MobileRadioPowerCalculator mMobileRadioPowerCalculator = null;
1464     /** Wifi Power calculator for attributing wifi EnergyConsumer to uids */
1465     @Nullable WifiPowerCalculator mWifiPowerCalculator = null;
1466 
1467     /**
1468      * These provide time bases that discount the time the device is plugged
1469      * in to power.
1470      */
1471     boolean mOnBattery;
1472     @VisibleForTesting
1473     protected boolean mOnBatteryInternal;
1474 
1475     /**
1476      * External reporting of whether the device is actually charging.
1477      */
1478     boolean mCharging = true;
1479 
1480     /*
1481      * These keep track of battery levels (1-100) at the last unplug event.
1482      */
1483     int mDischargeUnplugLevel;
1484     int mDischargePlugLevel;
1485     int mDischargeCurrentLevel;
1486     int mLowDischargeAmountSinceCharge;
1487     int mHighDischargeAmountSinceCharge;
1488     int mDischargeScreenOnUnplugLevel;
1489     int mDischargeScreenOffUnplugLevel;
1490     int mDischargeScreenDozeUnplugLevel;
1491     int mDischargeAmountScreenOn;
1492     int mDischargeAmountScreenOnSinceCharge;
1493     int mDischargeAmountScreenOff;
1494     int mDischargeAmountScreenOffSinceCharge;
1495     int mDischargeAmountScreenDoze;
1496     int mDischargeAmountScreenDozeSinceCharge;
1497 
1498     private LongSamplingCounter mDischargeScreenOffCounter;
1499     private LongSamplingCounter mDischargeScreenDozeCounter;
1500     private LongSamplingCounter mDischargeCounter;
1501     private LongSamplingCounter mDischargeLightDozeCounter;
1502     private LongSamplingCounter mDischargeDeepDozeCounter;
1503 
1504     static final int MAX_LEVEL_STEPS = 200;
1505 
1506     int mInitStepMode = 0;
1507     int mCurStepMode = 0;
1508     int mModStepMode = 0;
1509 
1510     int mLastDischargeStepLevel;
1511     int mMinDischargeStepLevel;
1512     final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
1513     final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
1514     ArrayList<PackageChange> mDailyPackageChanges;
1515 
1516     int mLastChargeStepLevel;
1517     int mMaxChargeStepLevel;
1518     final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
1519     final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
1520 
1521     static final int MAX_DAILY_ITEMS = 10;
1522 
1523     long mDailyStartTimeMs = 0;
1524     long mNextMinDailyDeadlineMs = 0;
1525     long mNextMaxDailyDeadlineMs = 0;
1526 
1527     final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
1528 
1529     long mLastWriteTimeMs = 0; // Milliseconds
1530 
1531     private int mPhoneServiceState = -1;
1532     private int mPhoneServiceStateRaw = -1;
1533     private int mPhoneSimStateRaw = -1;
1534 
1535     private int mNumConnectivityChange;
1536 
1537     private int mEstimatedBatteryCapacityMah = -1;
1538 
1539     private int mLastLearnedBatteryCapacityUah = -1;
1540     private int mMinLearnedBatteryCapacityUah = -1;
1541     private int mMaxLearnedBatteryCapacityUah = -1;
1542 
1543     private long mBatteryTimeToFullSeconds = -1;
1544 
1545     private boolean mCpuFreqsInitialized;
1546     private long[] mCpuFreqs;
1547     private LongArrayMultiStateCounter.LongArrayContainer mTmpCpuTimeInFreq;
1548 
1549     /**
1550      * Times spent by the system server threads handling incoming binder requests.
1551      */
1552     private LongSamplingCounterArray mBinderThreadCpuTimesUs;
1553 
1554     @VisibleForTesting
1555     protected PowerProfile mPowerProfile;
1556 
1557     @VisibleForTesting
1558     @GuardedBy("this")
1559     protected final Constants mConstants;
1560 
1561     @VisibleForTesting
1562     @GuardedBy("this")
1563     protected BatteryStatsConfig mBatteryStatsConfig = new BatteryStatsConfig.Builder().build();
1564 
1565     @GuardedBy("this")
1566     private AlarmManager mAlarmManager = null;
1567 
1568     private final AlarmManager.OnAlarmListener mLongPlugInAlarmHandler = () ->
1569             mHandler.post(() -> {
1570                 synchronized (BatteryStatsImpl.this) {
1571                     maybeResetWhilePluggedInLocked();
1572                 }
1573             });
1574 
1575     /*
1576      * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
1577      * recording their times when on-battery (regardless of screen state).
1578      */
1579     private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>();
1580     /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */
1581     private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>();
1582 
1583     @Override
getRpmStats()1584     public Map<String, ? extends Timer> getRpmStats() {
1585         return mRpmStats;
1586     }
1587 
1588     // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED.
1589     @Override
getScreenOffRpmStats()1590     public Map<String, ? extends Timer> getScreenOffRpmStats() {
1591         return mScreenOffRpmStats;
1592     }
1593 
1594     /*
1595      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
1596      */
1597     private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
1598 
getKernelWakelockStats()1599     public Map<String, ? extends Timer> getKernelWakelockStats() {
1600         return mKernelWakelockStats;
1601     }
1602 
1603     @Override
getWakeLockStats()1604     public WakeLockStats getWakeLockStats() {
1605         final long realtimeMs = mClock.elapsedRealtime();
1606         final long realtimeUs = realtimeMs * 1000;
1607         List<WakeLockStats.WakeLock> uidWakeLockStats = new ArrayList<>();
1608         for (int i = mUidStats.size() - 1; i >= 0; i--) {
1609             final Uid uid = mUidStats.valueAt(i);
1610             final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats =
1611                     uid.mWakelockStats.getMap();
1612             for (int j = wakelockStats.size() - 1; j >= 0; j--) {
1613                 final String name = wakelockStats.keyAt(j);
1614                 final Uid.Wakelock wakelock = (Uid.Wakelock) wakelockStats.valueAt(j);
1615                 final DualTimer timer = wakelock.mTimerPartial;
1616                 if (timer != null) {
1617                     final long totalTimeLockHeldMs =
1618                             timer.getTotalTimeLocked(realtimeUs, STATS_SINCE_CHARGED) / 1000;
1619                     if (totalTimeLockHeldMs != 0) {
1620                         uidWakeLockStats.add(
1621                                 new WakeLockStats.WakeLock(uid.getUid(), name,
1622                                         timer.getCountLocked(STATS_SINCE_CHARGED),
1623                                         totalTimeLockHeldMs,
1624                                         timer.isRunningLocked()
1625                                                 ? timer.getCurrentDurationMsLocked(realtimeMs)
1626                                                 : 0));
1627                     }
1628                 }
1629             }
1630         }
1631         return new WakeLockStats(uidWakeLockStats);
1632     }
1633 
1634     @Override
1635     @GuardedBy("this")
getBluetoothBatteryStats()1636     public BluetoothBatteryStats getBluetoothBatteryStats() {
1637         final long elapsedRealtimeUs = mClock.elapsedRealtime() * 1000;
1638         ArrayList<BluetoothBatteryStats.UidStats> uidStats = new ArrayList<>();
1639         for (int i = mUidStats.size() - 1; i >= 0; i--) {
1640             final Uid uid = mUidStats.valueAt(i);
1641             final Timer scanTimer = uid.getBluetoothScanTimer();
1642             final long scanTimeMs =
1643                     scanTimer != null ? scanTimer.getTotalTimeLocked(
1644                             elapsedRealtimeUs, STATS_SINCE_CHARGED) / 1000 : 0;
1645 
1646             final Timer unoptimizedScanTimer = uid.getBluetoothUnoptimizedScanTimer();
1647             final long unoptimizedScanTimeMs =
1648                     unoptimizedScanTimer != null ? unoptimizedScanTimer.getTotalTimeLocked(
1649                             elapsedRealtimeUs, STATS_SINCE_CHARGED) / 1000 : 0;
1650 
1651             final Counter scanResultCounter = uid.getBluetoothScanResultCounter();
1652             final int scanResultCount =
1653                     scanResultCounter != null ? scanResultCounter.getCountLocked(
1654                             STATS_SINCE_CHARGED) : 0;
1655 
1656             final ControllerActivityCounter counter = uid.getBluetoothControllerActivity();
1657             final long rxTimeMs =  counter != null ? counter.getRxTimeCounter().getCountLocked(
1658                     STATS_SINCE_CHARGED) : 0;
1659             final long txTimeMs =  counter != null ? counter.getTxTimeCounters()[0].getCountLocked(
1660                     STATS_SINCE_CHARGED) : 0;
1661 
1662             if (scanTimeMs != 0 || unoptimizedScanTimeMs != 0 || scanResultCount != 0
1663                     || rxTimeMs != 0 || txTimeMs != 0) {
1664                 uidStats.add(new BluetoothBatteryStats.UidStats(uid.getUid(),
1665                         scanTimeMs,
1666                         unoptimizedScanTimeMs,
1667                         scanResultCount,
1668                         rxTimeMs,
1669                         txTimeMs));
1670             }
1671         }
1672 
1673         return new BluetoothBatteryStats(uidStats);
1674     }
1675 
1676     String mLastWakeupReason = null;
1677     long mLastWakeupUptimeMs = 0;
1678     long mLastWakeupElapsedTimeMs = 0;
1679     private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
1680 
getWakeupReasonStats()1681     public Map<String, ? extends Timer> getWakeupReasonStats() {
1682         return mWakeupReasonStats;
1683     }
1684 
1685     @Override
getUahDischarge(int which)1686     public long getUahDischarge(int which) {
1687         return mDischargeCounter.getCountLocked(which);
1688     }
1689 
1690     @Override
getUahDischargeScreenOff(int which)1691     public long getUahDischargeScreenOff(int which) {
1692         return mDischargeScreenOffCounter.getCountLocked(which);
1693     }
1694 
1695     @Override
getUahDischargeScreenDoze(int which)1696     public long getUahDischargeScreenDoze(int which) {
1697         return mDischargeScreenDozeCounter.getCountLocked(which);
1698     }
1699 
1700     @Override
getUahDischargeLightDoze(int which)1701     public long getUahDischargeLightDoze(int which) {
1702         return mDischargeLightDozeCounter.getCountLocked(which);
1703     }
1704 
1705     @Override
getUahDischargeDeepDoze(int which)1706     public long getUahDischargeDeepDoze(int which) {
1707         return mDischargeDeepDozeCounter.getCountLocked(which);
1708     }
1709 
1710     @Override
getEstimatedBatteryCapacity()1711     public int getEstimatedBatteryCapacity() {
1712         return mEstimatedBatteryCapacityMah;
1713     }
1714 
1715     @Override
getLearnedBatteryCapacity()1716     public int getLearnedBatteryCapacity() {
1717         return mLastLearnedBatteryCapacityUah;
1718     }
1719 
1720     @Override
getMinLearnedBatteryCapacity()1721     public int getMinLearnedBatteryCapacity() {
1722         return mMinLearnedBatteryCapacityUah;
1723     }
1724 
1725     @Override
getMaxLearnedBatteryCapacity()1726     public int getMaxLearnedBatteryCapacity() {
1727         return mMaxLearnedBatteryCapacityUah;
1728     }
1729 
BatteryStatsImpl()1730     public BatteryStatsImpl() {
1731         this(Clock.SYSTEM_CLOCK);
1732     }
1733 
BatteryStatsImpl(Clock clock)1734     public BatteryStatsImpl(Clock clock) {
1735         this(clock, null);
1736     }
1737 
BatteryStatsImpl(Clock clock, File historyDirectory)1738     public BatteryStatsImpl(Clock clock, File historyDirectory) {
1739         init(clock);
1740         mHandler = null;
1741         mConstants = new Constants(mHandler);
1742         mStartClockTimeMs = clock.currentTimeMillis();
1743         mDailyFile = null;
1744         if (historyDirectory == null) {
1745             mCheckinFile = null;
1746             mStatsFile = null;
1747             mHistory = new BatteryStatsHistory(mConstants.MAX_HISTORY_FILES,
1748                     mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock);
1749         } else {
1750             mCheckinFile = new AtomicFile(new File(historyDirectory, "batterystats-checkin.bin"));
1751             mStatsFile = new AtomicFile(new File(historyDirectory, "batterystats.bin"));
1752             mHistory = new BatteryStatsHistory(historyDirectory, mConstants.MAX_HISTORY_FILES,
1753                     mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock);
1754         }
1755         mPlatformIdleStateCallback = null;
1756         mEnergyConsumerRetriever = null;
1757         mUserInfoProvider = null;
1758     }
1759 
init(Clock clock)1760     private void init(Clock clock) {
1761         mClock = clock;
1762         mCpuUidUserSysTimeReader = new KernelCpuUidUserSysTimeReader(true, clock);
1763         mCpuUidFreqTimeReader = new KernelCpuUidFreqTimeReader(true, clock);
1764         mCpuUidActiveTimeReader = new KernelCpuUidActiveTimeReader(true, clock);
1765         mCpuUidClusterTimeReader = new KernelCpuUidClusterTimeReader(true, clock);
1766     }
1767 
1768     /**
1769      * TimeBase observer.
1770      */
1771     public interface TimeBaseObs {
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1772         void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs);
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1773         void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs);
1774 
1775         /**
1776          * Reset the observer's state, returns true if the timer/counter is inactive
1777          * so it can be destroyed.
1778          * @param detachIfReset detach if true, no-op if false.
1779          * @return Returns true if the timer/counter is inactive and can be destroyed.
1780          */
reset(boolean detachIfReset)1781         default boolean reset(boolean detachIfReset) {
1782             return reset(detachIfReset, SystemClock.elapsedRealtime() * 1000);
1783         }
1784 
1785         /**
1786          * @see #reset(boolean)
1787          * @param detachIfReset detach if true, no-op if false.
1788          * @param elapsedRealtimeUs the timestamp when this reset is actually reequested
1789          * @return Returns true if the timer/counter is inactive and can be destroyed.
1790          */
reset(boolean detachIfReset, long elapsedRealtimeUs)1791         boolean reset(boolean detachIfReset, long elapsedRealtimeUs);
1792 
1793         /**
1794          * Detach the observer from TimeBase.
1795          */
detach()1796         void detach();
1797     }
1798 
1799     // methods are protected not private to be VisibleForTesting
1800     public static class TimeBase {
1801         protected final Collection<TimeBaseObs> mObservers;
1802 
1803         // All below time metrics are in microseconds.
1804         protected long mUptimeUs;
1805         protected long mRealtimeUs;
1806 
1807         protected boolean mRunning;
1808 
1809         protected long mPastUptimeUs;
1810         protected long mUptimeStartUs;
1811         protected long mPastRealtimeUs;
1812         protected long mRealtimeStartUs;
1813         protected long mUnpluggedUptimeUs;
1814         protected long mUnpluggedRealtimeUs;
1815 
dump(PrintWriter pw, String prefix)1816         public void dump(PrintWriter pw, String prefix) {
1817             StringBuilder sb = new StringBuilder(128);
1818             pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
1819             sb.setLength(0);
1820             sb.append(prefix);
1821                     sb.append("mUptime=");
1822                     formatTimeMs(sb, mUptimeUs / 1000);
1823             pw.println(sb.toString());
1824             sb.setLength(0);
1825             sb.append(prefix);
1826                     sb.append("mRealtime=");
1827                     formatTimeMs(sb, mRealtimeUs / 1000);
1828             pw.println(sb.toString());
1829             sb.setLength(0);
1830             sb.append(prefix);
1831                     sb.append("mPastUptime=");
1832                     formatTimeMs(sb, mPastUptimeUs / 1000); sb.append("mUptimeStart=");
1833                     formatTimeMs(sb, mUptimeStartUs / 1000);
1834                     sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptimeUs / 1000);
1835             pw.println(sb.toString());
1836             sb.setLength(0);
1837             sb.append(prefix);
1838                     sb.append("mPastRealtime=");
1839                     formatTimeMs(sb, mPastRealtimeUs / 1000); sb.append("mRealtimeStart=");
1840                     formatTimeMs(sb, mRealtimeStartUs / 1000);
1841                     sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtimeUs / 1000);
1842             pw.println(sb.toString());
1843         }
1844         /**
1845          * The mObservers of TimeBase in BatteryStatsImpl object can contain up to 20k entries.
1846          * The mObservers of TimeBase in BatteryStatsImpl.Uid object only contains a few or tens of
1847          * entries.
1848          * mObservers must have good performance on add(), remove(), also be memory efficient.
1849          * This is why we provide isLongList parameter for long and short list user cases.
1850          * @param isLongList If true, use HashSet for mObservers list.
1851          *                   If false, use ArrayList for mObservers list.
1852         */
TimeBase(boolean isLongList)1853         public TimeBase(boolean isLongList) {
1854             mObservers = isLongList ? new HashSet<>() : new ArrayList<>();
1855         }
1856 
TimeBase()1857         public TimeBase() {
1858             this(false);
1859         }
1860 
add(TimeBaseObs observer)1861         public void add(TimeBaseObs observer) {
1862             mObservers.add(observer);
1863         }
1864 
remove(TimeBaseObs observer)1865         public void remove(TimeBaseObs observer) {
1866             mObservers.remove(observer);
1867         }
1868 
hasObserver(TimeBaseObs observer)1869         public boolean hasObserver(TimeBaseObs observer) {
1870             return mObservers.contains(observer);
1871         }
1872 
init(long uptimeUs, long elapsedRealtimeUs)1873         public void init(long uptimeUs, long elapsedRealtimeUs) {
1874             mRealtimeUs = 0;
1875             mUptimeUs = 0;
1876             mPastUptimeUs = 0;
1877             mPastRealtimeUs = 0;
1878             mUptimeStartUs = uptimeUs;
1879             mRealtimeStartUs = elapsedRealtimeUs;
1880             mUnpluggedUptimeUs = getUptime(mUptimeStartUs);
1881             mUnpluggedRealtimeUs = getRealtime(mRealtimeStartUs);
1882         }
1883 
reset(long uptimeUs, long elapsedRealtimeUs)1884         public void reset(long uptimeUs, long elapsedRealtimeUs) {
1885             if (!mRunning) {
1886                 mPastUptimeUs = 0;
1887                 mPastRealtimeUs = 0;
1888             } else {
1889                 mUptimeStartUs = uptimeUs;
1890                 mRealtimeStartUs = elapsedRealtimeUs;
1891                 // TODO: Since mUptimeStartUs was just reset and we are running, getUptime will
1892                 // just return mPastUptimeUs. Also, are we sure we don't want to reset that?
1893                 mUnpluggedUptimeUs = getUptime(uptimeUs);
1894                 // TODO: likewise.
1895                 mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs);
1896             }
1897         }
1898 
computeUptime(long curTimeUs, int which)1899         public long computeUptime(long curTimeUs, int which) {
1900             return mUptimeUs + getUptime(curTimeUs);
1901         }
1902 
computeRealtime(long curTimeUs, int which)1903         public long computeRealtime(long curTimeUs, int which) {
1904             return mRealtimeUs + getRealtime(curTimeUs);
1905         }
1906 
getUptime(long curTimeUs)1907         public long getUptime(long curTimeUs) {
1908             long time = mPastUptimeUs;
1909             if (mRunning) {
1910                 time += curTimeUs - mUptimeStartUs;
1911             }
1912             return time;
1913         }
1914 
getRealtime(long curTimeUs)1915         public long getRealtime(long curTimeUs) {
1916             long time = mPastRealtimeUs;
1917             if (mRunning) {
1918                 time += curTimeUs - mRealtimeStartUs;
1919             }
1920             return time;
1921         }
1922 
getUptimeStart()1923         public long getUptimeStart() {
1924             return mUptimeStartUs;
1925         }
1926 
getRealtimeStart()1927         public long getRealtimeStart() {
1928             return mRealtimeStartUs;
1929         }
1930 
isRunning()1931         public boolean isRunning() {
1932             return mRunning;
1933         }
1934 
setRunning(boolean running, long uptimeUs, long elapsedRealtimeUs)1935         public boolean setRunning(boolean running, long uptimeUs, long elapsedRealtimeUs) {
1936             if (mRunning != running) {
1937                 mRunning = running;
1938                 if (running) {
1939                     mUptimeStartUs = uptimeUs;
1940                     mRealtimeStartUs = elapsedRealtimeUs;
1941                     long batteryUptimeUs = mUnpluggedUptimeUs = getUptime(uptimeUs);
1942                     long batteryRealtimeUs = mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs);
1943                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
1944                     // Iterator object, here is an exception because mObservers' type is Collection
1945                     // instead of list.
1946                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
1947                     while (iter.hasNext()) {
1948                         iter.next().onTimeStarted(
1949                                 elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs);
1950                     }
1951                 } else {
1952                     mPastUptimeUs += uptimeUs - mUptimeStartUs;
1953                     mPastRealtimeUs += elapsedRealtimeUs - mRealtimeStartUs;
1954                     long batteryUptimeUs = getUptime(uptimeUs);
1955                     long batteryRealtimeUs = getRealtime(elapsedRealtimeUs);
1956                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
1957                     // Iterator object, here is an exception because mObservers' type is Collection
1958                     // instead of list.
1959                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
1960                     while (iter.hasNext()) {
1961                         iter.next().onTimeStopped(
1962                                 elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs);
1963                     }
1964                 }
1965                 return true;
1966             }
1967             return false;
1968         }
1969 
readSummaryFromParcel(Parcel in)1970         public void readSummaryFromParcel(Parcel in) {
1971             mUptimeUs = in.readLong();
1972             mRealtimeUs = in.readLong();
1973         }
1974 
writeSummaryToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs)1975         public void writeSummaryToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
1976             out.writeLong(computeUptime(uptimeUs, STATS_SINCE_CHARGED));
1977             out.writeLong(computeRealtime(elapsedRealtimeUs, STATS_SINCE_CHARGED));
1978         }
1979 
readFromParcel(Parcel in)1980         public void readFromParcel(Parcel in) {
1981             mRunning = false;
1982             mUptimeUs = in.readLong();
1983             mPastUptimeUs = in.readLong();
1984             mUptimeStartUs = in.readLong();
1985             mRealtimeUs = in.readLong();
1986             mPastRealtimeUs = in.readLong();
1987             mRealtimeStartUs = in.readLong();
1988             mUnpluggedUptimeUs = in.readLong();
1989             mUnpluggedRealtimeUs = in.readLong();
1990         }
1991 
writeToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs)1992         public void writeToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
1993             final long runningUptime = getUptime(uptimeUs);
1994             final long runningRealtime = getRealtime(elapsedRealtimeUs);
1995             out.writeLong(mUptimeUs);
1996             out.writeLong(runningUptime);
1997             out.writeLong(mUptimeStartUs);
1998             out.writeLong(mRealtimeUs);
1999             out.writeLong(runningRealtime);
2000             out.writeLong(mRealtimeStartUs);
2001             out.writeLong(mUnpluggedUptimeUs);
2002             out.writeLong(mUnpluggedRealtimeUs);
2003         }
2004     }
2005 
2006     /**
2007      * State for keeping track of counting information.
2008      */
2009     public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
2010         final AtomicInteger mCount = new AtomicInteger();
2011         final TimeBase mTimeBase;
2012 
Counter(TimeBase timeBase, Parcel in)2013         public Counter(TimeBase timeBase, Parcel in) {
2014             mTimeBase = timeBase;
2015             mCount.set(in.readInt());
2016             timeBase.add(this);
2017         }
2018 
Counter(TimeBase timeBase)2019         public Counter(TimeBase timeBase) {
2020             mTimeBase = timeBase;
2021             timeBase.add(this);
2022         }
2023 
writeToParcel(Parcel out)2024         public void writeToParcel(Parcel out) {
2025             out.writeInt(mCount.get());
2026         }
2027 
2028         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2029         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2030         }
2031 
2032         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2033         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2034         }
2035 
2036         @Override
getCountLocked(int which)2037         public int getCountLocked(int which) {
2038             return mCount.get();
2039         }
2040 
logState(Printer pw, String prefix)2041         public void logState(Printer pw, String prefix) {
2042             pw.println(prefix + "mCount=" + mCount.get());
2043         }
2044 
2045         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
stepAtomic()2046         public void stepAtomic() {
2047             if (mTimeBase.isRunning()) {
2048                 mCount.incrementAndGet();
2049             }
2050         }
2051 
addAtomic(int delta)2052         void addAtomic(int delta) {
2053             if (mTimeBase.isRunning()) {
2054                 mCount.addAndGet(delta);
2055             }
2056         }
2057 
2058         /**
2059          * Clear state of this counter.
2060          */
2061         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2062         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2063             mCount.set(0);
2064             if (detachIfReset) {
2065                 detach();
2066             }
2067             return true;
2068         }
2069 
2070         @Override
detach()2071         public void detach() {
2072             mTimeBase.remove(this);
2073         }
2074 
2075         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
writeSummaryFromParcelLocked(Parcel out)2076         public void writeSummaryFromParcelLocked(Parcel out) {
2077             out.writeInt(mCount.get());
2078         }
2079 
2080         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
readSummaryFromParcelLocked(Parcel in)2081         public void readSummaryFromParcelLocked(Parcel in) {
2082             mCount.set(in.readInt());
2083         }
2084     }
2085 
2086     @VisibleForTesting
2087     public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
2088         final TimeBase mTimeBase;
2089         public long[] mCounts;
2090 
LongSamplingCounterArray(TimeBase timeBase, Parcel in)2091         private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
2092             mTimeBase = timeBase;
2093             mCounts = in.createLongArray();
2094             timeBase.add(this);
2095         }
2096 
LongSamplingCounterArray(TimeBase timeBase)2097         public LongSamplingCounterArray(TimeBase timeBase) {
2098             mTimeBase = timeBase;
2099             timeBase.add(this);
2100         }
2101 
writeToParcel(Parcel out)2102         private void writeToParcel(Parcel out) {
2103             out.writeLongArray(mCounts);
2104         }
2105 
2106         @Override
onTimeStarted(long elapsedRealTimeUs, long baseUptimeUs, long baseRealtimeUs)2107         public void onTimeStarted(long elapsedRealTimeUs, long baseUptimeUs, long baseRealtimeUs) {
2108         }
2109 
2110         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2111         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2112         }
2113 
2114         @Override
getCountsLocked(int which)2115         public long[] getCountsLocked(int which) {
2116             return mCounts == null ? null : Arrays.copyOf(mCounts, mCounts.length);
2117         }
2118 
2119         @Override
logState(Printer pw, String prefix)2120         public void logState(Printer pw, String prefix) {
2121             pw.println(prefix + "mCounts=" + Arrays.toString(mCounts));
2122         }
2123 
addCountLocked(long[] counts)2124         public void addCountLocked(long[] counts) {
2125             addCountLocked(counts, mTimeBase.isRunning());
2126         }
2127 
addCountLocked(long[] counts, boolean isRunning)2128         public void addCountLocked(long[] counts, boolean isRunning) {
2129             if (counts == null) {
2130                 return;
2131             }
2132             if (isRunning) {
2133                 if (mCounts == null) {
2134                     mCounts = new long[counts.length];
2135                 }
2136                 for (int i = 0; i < counts.length; ++i) {
2137                     mCounts[i] += counts[i];
2138                 }
2139             }
2140         }
2141 
getSize()2142         public int getSize() {
2143             return mCounts == null ? 0 : mCounts.length;
2144         }
2145 
2146         /**
2147          * Clear state of this counter.
2148          */
2149         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2150         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2151             if (mCounts != null) {
2152                 Arrays.fill(mCounts, 0);
2153             }
2154             if (detachIfReset) {
2155                 detach();
2156             }
2157             return true;
2158         }
2159 
2160         @Override
detach()2161         public void detach() {
2162             mTimeBase.remove(this);
2163         }
2164 
writeSummaryToParcelLocked(Parcel out)2165         private void writeSummaryToParcelLocked(Parcel out) {
2166             out.writeLongArray(mCounts);
2167         }
2168 
readSummaryFromParcelLocked(Parcel in)2169         private void readSummaryFromParcelLocked(Parcel in) {
2170             mCounts = in.createLongArray();
2171         }
2172 
writeToParcel(Parcel out, LongSamplingCounterArray counterArray)2173         public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
2174             if (counterArray != null) {
2175                 out.writeInt(1);
2176                 counterArray.writeToParcel(out);
2177             } else {
2178                 out.writeInt(0);
2179             }
2180         }
2181 
readFromParcel(Parcel in, TimeBase timeBase)2182         public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
2183             if (in.readInt() != 0) {
2184                 return new LongSamplingCounterArray(timeBase, in);
2185             } else {
2186                 return null;
2187             }
2188         }
2189 
writeSummaryToParcelLocked(Parcel out, LongSamplingCounterArray counterArray)2190         public static void writeSummaryToParcelLocked(Parcel out,
2191                 LongSamplingCounterArray counterArray) {
2192             if (counterArray != null) {
2193                 out.writeInt(1);
2194                 counterArray.writeSummaryToParcelLocked(out);
2195             } else {
2196                 out.writeInt(0);
2197             }
2198         }
2199 
readSummaryFromParcelLocked(Parcel in, TimeBase timeBase)2200         public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
2201                 TimeBase timeBase) {
2202             if (in.readInt() != 0) {
2203                 final LongSamplingCounterArray counterArray
2204                         = new LongSamplingCounterArray(timeBase);
2205                 counterArray.readSummaryFromParcelLocked(in);
2206                 return counterArray;
2207             } else {
2208                 return null;
2209             }
2210         }
2211     }
2212 
2213     private static class TimeMultiStateCounter extends LongCounter implements TimeBaseObs {
2214         private final TimeBase mTimeBase;
2215         private final LongMultiStateCounter mCounter;
2216 
TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs)2217         private TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs) {
2218             this(timeBase, new LongMultiStateCounter(stateCount), timestampMs);
2219         }
2220 
TimeMultiStateCounter(TimeBase timeBase, LongMultiStateCounter counter, long timestampMs)2221         private TimeMultiStateCounter(TimeBase timeBase, LongMultiStateCounter counter,
2222                 long timestampMs) {
2223             mTimeBase = timeBase;
2224             mCounter = counter;
2225             mCounter.setEnabled(mTimeBase.isRunning(), timestampMs);
2226             timeBase.add(this);
2227         }
2228 
2229         @Nullable
readFromParcel(Parcel in, TimeBase timeBase, int stateCount, long timestampMs)2230         private static TimeMultiStateCounter readFromParcel(Parcel in, TimeBase timeBase,
2231                 int stateCount, long timestampMs) {
2232             LongMultiStateCounter counter = LongMultiStateCounter.CREATOR.createFromParcel(in);
2233             if (counter.getStateCount() != stateCount) {
2234                 return null;
2235             }
2236             return new TimeMultiStateCounter(timeBase, counter, timestampMs);
2237         }
2238 
writeToParcel(Parcel out)2239         private void writeToParcel(Parcel out) {
2240             mCounter.writeToParcel(out, 0);
2241         }
2242 
2243         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2244         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2245             mCounter.setEnabled(true, elapsedRealtimeUs / 1000);
2246         }
2247 
2248         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2249         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2250             mCounter.setEnabled(false, elapsedRealtimeUs / 1000);
2251         }
2252 
getStateCount()2253         public int getStateCount() {
2254             return mCounter.getStateCount();
2255         }
2256 
setState(@atteryConsumer.ProcessState int processState, long elapsedRealtimeMs)2257         private void setState(@BatteryConsumer.ProcessState int processState,
2258                 long elapsedRealtimeMs) {
2259             mCounter.setState(processState, elapsedRealtimeMs);
2260         }
2261 
update(long value, long timestampMs)2262         private long update(long value, long timestampMs) {
2263             return mCounter.updateValue(value, timestampMs);
2264         }
2265 
increment(long increment, long timestampMs)2266         private void increment(long increment, long timestampMs) {
2267             mCounter.incrementValue(increment, timestampMs);
2268         }
2269 
2270         /**
2271          * Returns accumulated count for the specified state.
2272          */
getCountForProcessState(@atteryConsumer.ProcessState int procState)2273         public long getCountForProcessState(@BatteryConsumer.ProcessState int procState) {
2274             return mCounter.getCount(procState);
2275         }
2276 
getTotalCountLocked()2277         public long getTotalCountLocked() {
2278             return mCounter.getTotalCount();
2279         }
2280 
2281         @Override
getCountLocked(int statsType)2282         public long getCountLocked(int statsType) {
2283             return getTotalCountLocked();
2284         }
2285 
2286         @Override
logState(Printer pw, String prefix)2287         public void logState(Printer pw, String prefix) {
2288             pw.println(prefix + "mCounter=" + mCounter);
2289         }
2290 
2291         /**
2292          * Clears state of this counter.
2293          */
2294         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2295         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2296             mCounter.reset();
2297             if (detachIfReset) {
2298                 detach();
2299             }
2300             return true;
2301         }
2302 
2303         @Override
detach()2304         public void detach() {
2305             mTimeBase.remove(this);
2306         }
2307     }
2308 
2309     private static class TimeInFreqMultiStateCounter implements TimeBaseObs {
2310         private final TimeBase mTimeBase;
2311         private final LongArrayMultiStateCounter mCounter;
2312 
TimeInFreqMultiStateCounter(TimeBase timeBase, int stateCount, int cpuFreqCount, long timestampMs)2313         private TimeInFreqMultiStateCounter(TimeBase timeBase, int stateCount, int cpuFreqCount,
2314                 long timestampMs) {
2315             this(timeBase, new LongArrayMultiStateCounter(stateCount, cpuFreqCount), timestampMs);
2316         }
2317 
TimeInFreqMultiStateCounter(TimeBase timeBase, LongArrayMultiStateCounter counter, long timestampMs)2318         private TimeInFreqMultiStateCounter(TimeBase timeBase, LongArrayMultiStateCounter counter,
2319                 long timestampMs) {
2320             mTimeBase = timeBase;
2321             mCounter = counter;
2322             mCounter.setEnabled(mTimeBase.isRunning(), timestampMs);
2323             timeBase.add(this);
2324         }
2325 
writeToParcel(Parcel out)2326         private void writeToParcel(Parcel out) {
2327             mCounter.writeToParcel(out, 0);
2328         }
2329 
2330         @Nullable
readFromParcel(Parcel in, TimeBase timeBase, int stateCount, int cpuFreqCount, long timestampMs)2331         private static TimeInFreqMultiStateCounter readFromParcel(Parcel in, TimeBase timeBase,
2332                 int stateCount, int cpuFreqCount, long timestampMs) {
2333             // Read the object from the Parcel, whether it's usable or not
2334             LongArrayMultiStateCounter counter =
2335                     LongArrayMultiStateCounter.CREATOR.createFromParcel(in);
2336             if (counter.getStateCount() != stateCount
2337                     || counter.getArrayLength() != cpuFreqCount) {
2338                 return null;
2339             }
2340             return new TimeInFreqMultiStateCounter(timeBase, counter, timestampMs);
2341         }
2342 
2343         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2344         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2345             mCounter.setEnabled(true, elapsedRealtimeUs / 1000);
2346         }
2347 
2348         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2349         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2350             mCounter.setEnabled(false, elapsedRealtimeUs / 1000);
2351         }
2352 
getCounter()2353         public LongArrayMultiStateCounter getCounter() {
2354             return mCounter;
2355         }
2356 
getStateCount()2357         public int getStateCount() {
2358             return mCounter.getStateCount();
2359         }
2360 
setTrackingEnabled(boolean enabled, long timestampMs)2361         public void setTrackingEnabled(boolean enabled, long timestampMs) {
2362             mCounter.setEnabled(enabled && mTimeBase.isRunning(), timestampMs);
2363         }
2364 
setState(int uidRunningState, long elapsedRealtimeMs)2365         private void setState(int uidRunningState, long elapsedRealtimeMs) {
2366             mCounter.setState(uidRunningState, elapsedRealtimeMs);
2367         }
2368 
2369         /**
2370          * Returns accumulated counts for the specified state, or false if all counts are zero.
2371          */
getCountsLocked(long[] counts, int procState)2372         public boolean getCountsLocked(long[] counts, int procState) {
2373             if (counts.length != mCounter.getArrayLength()) {
2374                 return false;
2375             }
2376 
2377             mCounter.getCounts(counts, procState);
2378 
2379             // Return counts only if at least one of the elements is non-zero.
2380             for (int i = counts.length - 1; i >= 0; --i) {
2381                 if (counts[i] != 0) {
2382                     return true;
2383                 }
2384             }
2385             return false;
2386         }
2387 
logState(Printer pw, String prefix)2388         public void logState(Printer pw, String prefix) {
2389             pw.println(prefix + "mCounter=" + mCounter);
2390         }
2391 
2392         /**
2393          * Clears state of this counter.
2394          */
2395         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2396         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2397             mCounter.reset();
2398             if (detachIfReset) {
2399                 detach();
2400             }
2401             return true;
2402         }
2403 
2404         @Override
detach()2405         public void detach() {
2406             mTimeBase.remove(this);
2407         }
2408     }
2409 
2410     @VisibleForTesting
2411     public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
2412         final TimeBase mTimeBase;
2413         private long mCount;
2414 
LongSamplingCounter(TimeBase timeBase, Parcel in)2415         public LongSamplingCounter(TimeBase timeBase, Parcel in) {
2416             mTimeBase = timeBase;
2417             mCount = in.readLong();
2418             timeBase.add(this);
2419         }
2420 
LongSamplingCounter(TimeBase timeBase)2421         public LongSamplingCounter(TimeBase timeBase) {
2422             mTimeBase = timeBase;
2423             timeBase.add(this);
2424         }
2425 
writeToParcel(Parcel out)2426         public void writeToParcel(Parcel out) {
2427             out.writeLong(mCount);
2428         }
2429 
2430         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2431         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2432         }
2433 
2434         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2435         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2436         }
2437 
getCountLocked(int which)2438         public long getCountLocked(int which) {
2439             return mCount;
2440         }
2441 
2442         @Override
getCountForProcessState(int procState)2443         public long getCountForProcessState(int procState) {
2444             if (procState == BatteryConsumer.PROCESS_STATE_ANY) {
2445                 return getCountLocked(STATS_SINCE_CHARGED);
2446             }
2447             return 0;
2448         }
2449 
2450         @Override
logState(Printer pw, String prefix)2451         public void logState(Printer pw, String prefix) {
2452             pw.println(prefix + "mCount=" + mCount);
2453         }
2454 
addCountLocked(long count)2455         public void addCountLocked(long count) {
2456             addCountLocked(count, mTimeBase.isRunning());
2457         }
2458 
addCountLocked(long count, boolean isRunning)2459         public void addCountLocked(long count, boolean isRunning) {
2460             if (isRunning) {
2461                 mCount += count;
2462             }
2463         }
2464 
2465         /**
2466          * Clear state of this counter.
2467          */
2468         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2469         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2470             mCount = 0;
2471             if (detachIfReset) {
2472                 detach();
2473             }
2474             return true;
2475         }
2476 
2477         @Override
detach()2478         public void detach() {
2479             mTimeBase.remove(this);
2480         }
2481 
writeSummaryFromParcelLocked(Parcel out)2482         public void writeSummaryFromParcelLocked(Parcel out) {
2483             out.writeLong(mCount);
2484         }
2485 
readSummaryFromParcelLocked(Parcel in)2486         public void readSummaryFromParcelLocked(Parcel in) {
2487             mCount = in.readLong();
2488         }
2489     }
2490 
2491     /**
2492      * State for keeping track of timing information.
2493      */
2494     public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
2495         protected final Clock mClock;
2496         protected final int mType;
2497         protected final TimeBase mTimeBase;
2498 
2499         protected int mCount;
2500 
2501         // Times are in microseconds for better accuracy when dividing by the
2502         // lock count, and are in "battery realtime" units.
2503 
2504         /**
2505          * The total time we have accumulated since the start of the original
2506          * boot, to the last time something interesting happened in the
2507          * current run.
2508          */
2509         protected long mTotalTimeUs;
2510 
2511         /**
2512          * The total time this timer has been running until the latest mark has been set.
2513          * Subtract this from mTotalTimeUs to get the time spent running since the mark was set.
2514          */
2515         protected long mTimeBeforeMarkUs;
2516 
2517         /**
2518          * Constructs from a parcel.
2519          * @param type
2520          * @param timeBase
2521          * @param in
2522          */
Timer(Clock clock, int type, TimeBase timeBase, Parcel in)2523         public Timer(Clock clock, int type, TimeBase timeBase, Parcel in) {
2524             mClock = clock;
2525             mType = type;
2526             mTimeBase = timeBase;
2527 
2528             mCount = in.readInt();
2529             mTotalTimeUs = in.readLong();
2530             mTimeBeforeMarkUs = in.readLong();
2531             timeBase.add(this);
2532             if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTimeUs);
2533         }
2534 
Timer(Clock clock, int type, TimeBase timeBase)2535         public Timer(Clock clock, int type, TimeBase timeBase) {
2536             mClock = clock;
2537             mType = type;
2538             mTimeBase = timeBase;
2539             timeBase.add(this);
2540         }
2541 
writeToParcel(Parcel out, long elapsedRealtimeUs)2542         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2543             if (DEBUG) {
2544                 Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
2545                         + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2546                                 elapsedRealtimeUs));
2547             }
2548             out.writeInt(computeCurrentCountLocked());
2549             out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2550                         elapsedRealtimeUs));
2551             out.writeLong(mTimeBeforeMarkUs);
2552         }
2553 
computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs)2554         protected abstract long computeRunTimeLocked(long curBatteryRealtime,
2555                 long elapsedRealtimeUs);
2556 
computeCurrentCountLocked()2557         protected abstract int computeCurrentCountLocked();
2558 
2559         /**
2560          * Clear state of this timer.  Returns true if the timer is inactive
2561          * so can be completely dropped.
2562          */
2563         @Override
reset(boolean detachIfReset)2564         public boolean reset(boolean detachIfReset) {
2565             return reset(detachIfReset, mClock.elapsedRealtime() * 1000);
2566         }
2567 
2568         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )2569         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
2570             mTotalTimeUs = mTimeBeforeMarkUs = 0;
2571             mCount = 0;
2572             if (detachIfReset) {
2573                 detach();
2574             }
2575             return true;
2576         }
2577 
2578         @Override
detach()2579         public void detach() {
2580             mTimeBase.remove(this);
2581         }
2582 
2583         @Override
onTimeStarted(long elapsedRealtimeUs, long timeBaseUptimeUs, long baseRealtimeUs)2584         public void onTimeStarted(long elapsedRealtimeUs, long timeBaseUptimeUs,
2585                 long baseRealtimeUs) {
2586         }
2587 
2588         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2589         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2590             if (DEBUG && mType < 0) {
2591                 Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtimeUs
2592                         + " old mTotalTime=" + mTotalTimeUs);
2593             }
2594             mTotalTimeUs = computeRunTimeLocked(baseRealtimeUs, elapsedRealtimeUs);
2595             mCount = computeCurrentCountLocked();
2596             if (DEBUG && mType < 0) {
2597                 Log.v(TAG, "plug #" + mType + ": new mTotalTime=" + mTotalTimeUs);
2598             }
2599         }
2600 
2601         /**
2602          * Writes a possibly null Timer to a Parcel.
2603          *
2604          * @param out the Parcel to be written to.
2605          * @param timer a Timer, or null.
2606          */
writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs)2607         public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
2608             if (timer == null) {
2609                 out.writeInt(0); // indicates null
2610                 return;
2611             }
2612             out.writeInt(1); // indicates non-null
2613             timer.writeToParcel(out, elapsedRealtimeUs);
2614         }
2615 
2616         @Override
getTotalTimeLocked(long elapsedRealtimeUs, int which)2617         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
2618             return computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2619                     elapsedRealtimeUs);
2620         }
2621 
2622         @Override
getCountLocked(int which)2623         public int getCountLocked(int which) {
2624             return computeCurrentCountLocked();
2625         }
2626 
2627         @Override
getTimeSinceMarkLocked(long elapsedRealtimeUs)2628         public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
2629             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2630                     elapsedRealtimeUs);
2631             return val - mTimeBeforeMarkUs;
2632         }
2633 
2634         @Override
logState(Printer pw, String prefix)2635         public void logState(Printer pw, String prefix) {
2636             pw.println(prefix + "mCount=" + mCount);
2637             pw.println(prefix + "mTotalTime=" + mTotalTimeUs);
2638         }
2639 
2640 
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2641         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2642             long runTimeUs = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
2643                     elapsedRealtimeUs);
2644             out.writeLong(runTimeUs);
2645             out.writeInt(computeCurrentCountLocked());
2646         }
2647 
readSummaryFromParcelLocked(Parcel in)2648         public void readSummaryFromParcelLocked(Parcel in) {
2649             // Multiply by 1000 for backwards compatibility
2650             mTotalTimeUs = in.readLong();
2651             mCount = in.readInt();
2652             // When reading the summary, we set the mark to be the latest information.
2653             mTimeBeforeMarkUs = mTotalTimeUs;
2654         }
2655     }
2656 
2657     /**
2658      * A counter meant to accept monotonically increasing values to its {@link #update(long, int)}
2659      * method. The state of the timer according to its {@link TimeBase} will determine how much
2660      * of the value is recorded.
2661      *
2662      * If the value being recorded resets, {@link #endSample()} can be called in order to
2663      * account for the change. If the value passed in to {@link #update(long, int)} decreased
2664      * between calls, the {@link #endSample()} is automatically called and the new value is
2665      * expected to increase monotonically from that point on.
2666      */
2667     public static class SamplingTimer extends Timer {
2668 
2669         /**
2670          * The most recent reported count from /proc/wakelocks.
2671          */
2672         int mCurrentReportedCount;
2673 
2674         /**
2675          * The reported count from /proc/wakelocks when unplug() was last
2676          * called.
2677          */
2678         int mUnpluggedReportedCount;
2679 
2680         /**
2681          * The most recent reported total_time from /proc/wakelocks.
2682          */
2683         long mCurrentReportedTotalTimeUs;
2684 
2685 
2686         /**
2687          * The reported total_time from /proc/wakelocks when unplug() was last
2688          * called.
2689          */
2690         long mUnpluggedReportedTotalTimeUs;
2691 
2692         /**
2693          * Whether we are currently in a discharge cycle.
2694          */
2695         boolean mTimeBaseRunning;
2696 
2697         /**
2698          * Whether we are currently recording reported values.
2699          */
2700         boolean mTrackingReportedValues;
2701 
2702         /*
2703          * A sequence counter, incremented once for each update of the stats.
2704          */
2705         int mUpdateVersion;
2706 
2707         @VisibleForTesting
SamplingTimer(Clock clock, TimeBase timeBase, Parcel in)2708         public SamplingTimer(Clock clock, TimeBase timeBase, Parcel in) {
2709             super(clock, 0, timeBase, in);
2710             mCurrentReportedCount = in.readInt();
2711             mUnpluggedReportedCount = in.readInt();
2712             mCurrentReportedTotalTimeUs = in.readLong();
2713             mUnpluggedReportedTotalTimeUs = in.readLong();
2714             mTrackingReportedValues = in.readInt() == 1;
2715             mTimeBaseRunning = timeBase.isRunning();
2716         }
2717 
2718         @VisibleForTesting
SamplingTimer(Clock clock, TimeBase timeBase)2719         public SamplingTimer(Clock clock, TimeBase timeBase) {
2720             super(clock, 0, timeBase);
2721             mTrackingReportedValues = false;
2722             mTimeBaseRunning = timeBase.isRunning();
2723         }
2724 
2725         /**
2726          * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to
2727          * be less than the values used for a previous invocation.
2728          */
endSample()2729         public void endSample() {
2730             endSample(mClock.elapsedRealtime() * 1000);
2731         }
2732 
2733         /**
2734          * @see #endSample()
2735          */
endSample(long elapsedRealtimeUs)2736         public void endSample(long elapsedRealtimeUs) {
2737             mTotalTimeUs = computeRunTimeLocked(0 /* unused by us */, elapsedRealtimeUs);
2738             mCount = computeCurrentCountLocked();
2739             mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs = 0;
2740             mUnpluggedReportedCount = mCurrentReportedCount = 0;
2741             mTrackingReportedValues = false;
2742         }
2743 
setUpdateVersion(int version)2744         public void setUpdateVersion(int version) {
2745             mUpdateVersion = version;
2746         }
2747 
getUpdateVersion()2748         public int getUpdateVersion() {
2749             return mUpdateVersion;
2750         }
2751 
2752         /**
2753          * Updates the current recorded values. These are meant to be monotonically increasing
2754          * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}.
2755          *
2756          * If the values being recorded have been reset, the monotonically increasing requirement
2757          * will be broken. In this case, {@link #endSample()} is automatically called and
2758          * the total value of totalTimeUs and count are recorded, starting a new monotonically
2759          * increasing sample.
2760          *
2761          * @param totalTimeUs total time of sample in microseconds.
2762          * @param count total number of times the event being sampled occurred.
2763          */
update(long totalTimeUs, int count, long elapsedRealtimeUs)2764         public void update(long totalTimeUs, int count, long elapsedRealtimeUs) {
2765             if (mTimeBaseRunning && !mTrackingReportedValues) {
2766                 // Updating the reported value for the first time.
2767                 mUnpluggedReportedTotalTimeUs = totalTimeUs;
2768                 mUnpluggedReportedCount = count;
2769             }
2770 
2771             mTrackingReportedValues = true;
2772 
2773             if (totalTimeUs < mCurrentReportedTotalTimeUs || count < mCurrentReportedCount) {
2774                 endSample(elapsedRealtimeUs);
2775             }
2776 
2777             mCurrentReportedTotalTimeUs = totalTimeUs;
2778             mCurrentReportedCount = count;
2779         }
2780 
2781         /**
2782          * Adds deltaTime and deltaCount to the current sample.
2783          *
2784          * @param deltaTime additional time recorded since the last sampled event, in microseconds.
2785          * @param deltaCount additional number of times the event being sampled occurred.
2786          */
add(long deltaTimeUs, int deltaCount)2787         public void add(long deltaTimeUs, int deltaCount) {
2788             add(deltaTimeUs, deltaCount, mClock.elapsedRealtime() * 1000);
2789         }
2790 
2791         /**
2792          * @see #add(long, int)
2793          */
add(long deltaTimeUs, int deltaCount, long elapsedRealtimeUs)2794         public void add(long deltaTimeUs, int deltaCount, long elapsedRealtimeUs) {
2795             update(mCurrentReportedTotalTimeUs + deltaTimeUs, mCurrentReportedCount + deltaCount,
2796                     elapsedRealtimeUs);
2797         }
2798 
2799         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2800         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2801             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2802             if (mTrackingReportedValues) {
2803                 mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs;
2804                 mUnpluggedReportedCount = mCurrentReportedCount;
2805             }
2806             mTimeBaseRunning = true;
2807         }
2808 
2809         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2810         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2811             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2812             mTimeBaseRunning = false;
2813         }
2814 
2815         @Override
logState(Printer pw, String prefix)2816         public void logState(Printer pw, String prefix) {
2817             super.logState(pw, prefix);
2818             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
2819                     + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
2820                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTimeUs
2821                     + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTimeUs);
2822         }
2823 
2824         @Override
computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs)2825         protected long computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs) {
2826             return mTotalTimeUs + (mTimeBaseRunning && mTrackingReportedValues
2827                     ? mCurrentReportedTotalTimeUs - mUnpluggedReportedTotalTimeUs : 0);
2828         }
2829 
2830         @Override
computeCurrentCountLocked()2831         protected int computeCurrentCountLocked() {
2832             return mCount + (mTimeBaseRunning && mTrackingReportedValues
2833                     ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
2834         }
2835 
2836         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2837         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2838             super.writeToParcel(out, elapsedRealtimeUs);
2839             out.writeInt(mCurrentReportedCount);
2840             out.writeInt(mUnpluggedReportedCount);
2841             out.writeLong(mCurrentReportedTotalTimeUs);
2842             out.writeLong(mUnpluggedReportedTotalTimeUs);
2843             out.writeInt(mTrackingReportedValues ? 1 : 0);
2844         }
2845 
2846         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)2847         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
2848             super.reset(detachIfReset, elapsedRealtimeUs);
2849             mTrackingReportedValues = false;
2850             mUnpluggedReportedTotalTimeUs = 0;
2851             mUnpluggedReportedCount = 0;
2852             return true;
2853         }
2854     }
2855 
2856     /**
2857      * A timer that increments in batches.  It does not run for durations, but just jumps
2858      * for a pre-determined amount.
2859      */
2860     public static class BatchTimer extends Timer {
2861         final Uid mUid;
2862 
2863         /**
2864          * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
2865          */
2866         long mLastAddedTimeUs;
2867 
2868         /**
2869          * The last duration that we added to the timer.  This is in microseconds.
2870          */
2871         long mLastAddedDurationUs;
2872 
2873         /**
2874          * Whether we are currently in a discharge cycle.
2875          */
2876         boolean mInDischarge;
2877 
BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase, Parcel in)2878         BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase, Parcel in) {
2879             super(clock, type, timeBase, in);
2880             mUid = uid;
2881             mLastAddedTimeUs = in.readLong();
2882             mLastAddedDurationUs = in.readLong();
2883             mInDischarge = timeBase.isRunning();
2884         }
2885 
BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase)2886         BatchTimer(Clock clock, Uid uid, int type, TimeBase timeBase) {
2887             super(clock, type, timeBase);
2888             mUid = uid;
2889             mInDischarge = timeBase.isRunning();
2890         }
2891 
2892         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2893         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2894             super.writeToParcel(out, elapsedRealtimeUs);
2895             out.writeLong(mLastAddedTimeUs);
2896             out.writeLong(mLastAddedDurationUs);
2897         }
2898 
2899         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2900         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2901             recomputeLastDuration(elapsedRealtimeUs, false);
2902             mInDischarge = false;
2903             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2904         }
2905 
2906         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2907         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2908             recomputeLastDuration(elapsedRealtimeUs, false);
2909             mInDischarge = true;
2910             // If we are still within the last added duration, then re-added whatever remains.
2911             if (mLastAddedTimeUs == elapsedRealtimeUs) {
2912                 mTotalTimeUs += mLastAddedDurationUs;
2913             }
2914             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2915         }
2916 
2917         @Override
logState(Printer pw, String prefix)2918         public void logState(Printer pw, String prefix) {
2919             super.logState(pw, prefix);
2920             pw.println(prefix + "mLastAddedTime=" + mLastAddedTimeUs
2921                     + " mLastAddedDuration=" + mLastAddedDurationUs);
2922         }
2923 
computeOverage(long curTimeUs)2924         private long computeOverage(long curTimeUs) {
2925             if (mLastAddedTimeUs > 0) {
2926                 return mLastAddedDurationUs - curTimeUs;
2927             }
2928             return 0;
2929         }
2930 
recomputeLastDuration(long curTimeUs, boolean abort)2931         private void recomputeLastDuration(long curTimeUs, boolean abort) {
2932             final long overage = computeOverage(curTimeUs);
2933             if (overage > 0) {
2934                 // Aborting before the duration ran out -- roll back the remaining
2935                 // duration.  Only do this if currently discharging; otherwise we didn't
2936                 // actually add the time.
2937                 if (mInDischarge) {
2938                     mTotalTimeUs -= overage;
2939                 }
2940                 if (abort) {
2941                     mLastAddedTimeUs = 0;
2942                 } else {
2943                     mLastAddedTimeUs = curTimeUs;
2944                     mLastAddedDurationUs -= overage;
2945                 }
2946             }
2947         }
2948 
addDuration(long durationMs, long elapsedRealtimeMs)2949         public void addDuration(long durationMs, long elapsedRealtimeMs) {
2950             final long nowUs = elapsedRealtimeMs * 1000;
2951             recomputeLastDuration(nowUs, true);
2952             mLastAddedTimeUs = nowUs;
2953             mLastAddedDurationUs = durationMs * 1000;
2954             if (mInDischarge) {
2955                 mTotalTimeUs += mLastAddedDurationUs;
2956                 mCount++;
2957             }
2958         }
2959 
abortLastDuration(long elapsedRealtimeMs)2960         public void abortLastDuration(long elapsedRealtimeMs) {
2961             final long nowUs = elapsedRealtimeMs * 1000;
2962             recomputeLastDuration(nowUs, true);
2963         }
2964 
2965         @Override
computeCurrentCountLocked()2966         protected int computeCurrentCountLocked() {
2967             return mCount;
2968         }
2969 
2970         @Override
computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs)2971         protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) {
2972             final long overage = computeOverage(elapsedRealtimeUs);
2973             if (overage > 0) {
2974                 return mTotalTimeUs = overage;
2975             }
2976             return mTotalTimeUs;
2977         }
2978 
2979         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)2980         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
2981             recomputeLastDuration(elapsedRealtimeUs, true);
2982             boolean stillActive = mLastAddedTimeUs == elapsedRealtimeUs;
2983             super.reset(!stillActive && detachIfReset, elapsedRealtimeUs);
2984             return !stillActive;
2985         }
2986     }
2987 
2988 
2989     /**
2990      * A StopwatchTimer that also tracks the total and max individual
2991      * time spent active according to the given timebase.  Whereas
2992      * StopwatchTimer apportions the time amongst all in the pool,
2993      * the total and max durations are not apportioned.
2994      */
2995     public static class DurationTimer extends StopwatchTimer {
2996         /**
2997          * The time (in ms) that the timer was last acquired or the time base
2998          * last (re-)started. Increasing the nesting depth does not reset this time.
2999          *
3000          * -1 if the timer is currently not running or the time base is not running.
3001          *
3002          * If written to a parcel, the start time is reset, as is mNesting in the base class
3003          * StopwatchTimer.
3004          */
3005         long mStartTimeMs = -1;
3006 
3007         /**
3008          * The longest time period (in ms) that the timer has been active. Not pooled.
3009          */
3010         long mMaxDurationMs;
3011 
3012         /**
3013          * The time (in ms) that that the timer has been active since most recent
3014          * stopRunningLocked() or reset(). Not pooled.
3015          */
3016         long mCurrentDurationMs;
3017 
3018         /**
3019          * The total time (in ms) that that the timer has been active since most recent reset()
3020          * prior to the current startRunningLocked. This is the sum of all past currentDurations
3021          * (but not including the present currentDuration) since reset. Not pooled.
3022          */
3023         long mTotalDurationMs;
3024 
DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)3025         public DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3026                 TimeBase timeBase, Parcel in) {
3027             super(clock, uid, type, timerPool, timeBase, in);
3028             mMaxDurationMs = in.readLong();
3029             mTotalDurationMs = in.readLong();
3030             mCurrentDurationMs = in.readLong();
3031         }
3032 
DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)3033         public DurationTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3034                 TimeBase timeBase) {
3035             super(clock, uid, type, timerPool, timeBase);
3036         }
3037 
3038         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)3039         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3040             super.writeToParcel(out, elapsedRealtimeUs);
3041             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
3042             out.writeLong(mTotalDurationMs);
3043             out.writeLong(getCurrentDurationMsLocked(elapsedRealtimeUs / 1000));
3044         }
3045 
3046         /**
3047          * Write the summary to the parcel.
3048          *
3049          * Since the time base is probably meaningless after we come back, reading
3050          * from this will have the effect of stopping the timer. So here all we write
3051          * is the max and total durations.
3052          */
3053         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)3054         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
3055             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
3056             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
3057             out.writeLong(getTotalDurationMsLocked(elapsedRealtimeUs / 1000));
3058         }
3059 
3060         /**
3061          * Read the summary parcel.
3062          *
3063          * Has the side effect of stopping the timer.
3064          */
3065         @Override
readSummaryFromParcelLocked(Parcel in)3066         public void readSummaryFromParcelLocked(Parcel in) {
3067             super.readSummaryFromParcelLocked(in);
3068             mMaxDurationMs = in.readLong();
3069             mTotalDurationMs = in.readLong();
3070             mStartTimeMs = -1;
3071             mCurrentDurationMs = 0;
3072         }
3073 
3074         /**
3075          * The TimeBase time started (again).
3076          *
3077          * If the timer is also running, store the start time.
3078          */
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3079         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3080             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3081             if (mNesting > 0) {
3082                 mStartTimeMs = baseRealtimeUs / 1000;
3083             }
3084         }
3085 
3086         /**
3087          * The TimeBase stopped running.
3088          *
3089          * If the timer is running, add the duration into mCurrentDurationMs.
3090          */
3091         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3092         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3093             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3094             if (mNesting > 0) {
3095                 // baseRealtimeUs has already been converted to the timebase's realtime.
3096                 mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
3097             }
3098             mStartTimeMs = -1;
3099         }
3100 
3101         @Override
logState(Printer pw, String prefix)3102         public void logState(Printer pw, String prefix) {
3103             super.logState(pw, prefix);
3104         }
3105 
3106         @Override
startRunningLocked(long elapsedRealtimeMs)3107         public void startRunningLocked(long elapsedRealtimeMs) {
3108             super.startRunningLocked(elapsedRealtimeMs);
3109             if (mNesting == 1 && mTimeBase.isRunning()) {
3110                 // Just started
3111                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000;
3112             }
3113         }
3114 
3115         /**
3116          * Decrements the mNesting ref-count on this timer.
3117          *
3118          * If it actually stopped (mNesting went to 0), then possibly update
3119          * mMaxDuration if the current duration was the longest ever.
3120          */
3121         @Override
stopRunningLocked(long elapsedRealtimeMs)3122         public void stopRunningLocked(long elapsedRealtimeMs) {
3123             if (mNesting == 1) {
3124                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
3125                 mTotalDurationMs += durationMs;
3126                 if (durationMs > mMaxDurationMs) {
3127                     mMaxDurationMs = durationMs;
3128                 }
3129                 mStartTimeMs = -1;
3130                 mCurrentDurationMs = 0;
3131             }
3132             // super method decrements mNesting, which getCurrentDurationMsLocked relies on,
3133             // so call super.stopRunningLocked after calling getCurrentDurationMsLocked.
3134             super.stopRunningLocked(elapsedRealtimeMs);
3135         }
3136 
3137         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3138         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3139             boolean result = super.reset(detachIfReset, elapsedRealtimeUs);
3140             mMaxDurationMs = 0;
3141             mTotalDurationMs = 0;
3142             mCurrentDurationMs = 0;
3143             if (mNesting > 0) {
3144                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeUs) / 1000;
3145             } else {
3146                 mStartTimeMs = -1;
3147             }
3148             return result;
3149         }
3150 
3151         /**
3152          * Returns the max duration that this timer has ever seen.
3153          *
3154          * Note that this time is NOT split between the timers in the timer group that
3155          * this timer is attached to.  It is the TOTAL time.
3156          */
3157         @Override
getMaxDurationMsLocked(long elapsedRealtimeMs)3158         public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
3159             if (mNesting > 0) {
3160                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
3161                 if (durationMs > mMaxDurationMs) {
3162                     return durationMs;
3163                 }
3164             }
3165             return mMaxDurationMs;
3166         }
3167 
3168         /**
3169          * Returns the time since the timer was started.
3170          * Returns 0 if the timer is not currently running.
3171          *
3172          * Note that this time is NOT split between the timers in the timer group that
3173          * this timer is attached to.  It is the TOTAL time.
3174          *
3175          * Note that if running timer is parceled and unparceled, this method will return
3176          * current duration value at the time of parceling even though timer may not be
3177          * currently running.
3178          */
3179         @Override
getCurrentDurationMsLocked(long elapsedRealtimeMs)3180         public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
3181             long durationMs = mCurrentDurationMs;
3182             if (mNesting > 0 && mTimeBase.isRunning()) {
3183                 durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000)
3184                         - mStartTimeMs;
3185             }
3186             return durationMs;
3187         }
3188 
3189         /**
3190          * Returns the total cumulative duration that this timer has been on since reset().
3191          * If mTimerPool == null, this should be the same
3192          * as getTotalTimeLocked(elapsedRealtimeMs*1000, STATS_SINCE_CHARGED)/1000.
3193          *
3194          * Note that this time is NOT split between the timers in the timer group that
3195          * this timer is attached to.  It is the TOTAL time. For this reason, if mTimerPool != null,
3196          * the result will not be equivalent to getTotalTimeLocked.
3197          */
3198         @Override
getTotalDurationMsLocked(long elapsedRealtimeMs)3199         public long getTotalDurationMsLocked(long elapsedRealtimeMs) {
3200             return mTotalDurationMs + getCurrentDurationMsLocked(elapsedRealtimeMs);
3201         }
3202     }
3203 
3204     /**
3205      * State for keeping track of timing information.
3206      */
3207     public static class StopwatchTimer extends Timer {
3208         final Uid mUid;
3209         final ArrayList<StopwatchTimer> mTimerPool;
3210 
3211         int mNesting;
3212 
3213         /**
3214          * The last time at which we updated the timer.  If mNesting is > 0,
3215          * subtract this from the current battery time to find the amount of
3216          * time we have been running since we last computed an update.
3217          */
3218         long mUpdateTimeUs;
3219 
3220         /**
3221          * The total time at which the timer was acquired, to determine if it
3222          * was actually held for an interesting duration. If time base was not running when timer
3223          * was acquired, will be -1.
3224          */
3225         long mAcquireTimeUs = -1;
3226 
3227         long mTimeoutUs;
3228 
3229         /**
3230          * For partial wake locks, keep track of whether we are in the list
3231          * to consume CPU cycles.
3232          */
3233         @VisibleForTesting
3234         public boolean mInList;
3235 
StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)3236         public StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3237                 TimeBase timeBase, Parcel in) {
3238             super(clock, type, timeBase, in);
3239             mUid = uid;
3240             mTimerPool = timerPool;
3241             mUpdateTimeUs = in.readLong();
3242         }
3243 
StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)3244         public StopwatchTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3245                 TimeBase timeBase) {
3246             super(clock, type, timeBase);
3247             mUid = uid;
3248             mTimerPool = timerPool;
3249         }
3250 
setTimeout(long timeoutUs)3251         public void setTimeout(long timeoutUs) {
3252             mTimeoutUs = timeoutUs;
3253         }
3254 
writeToParcel(Parcel out, long elapsedRealtimeUs)3255         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3256             super.writeToParcel(out, elapsedRealtimeUs);
3257             out.writeLong(mUpdateTimeUs);
3258         }
3259 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)3260         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
3261             if (mNesting > 0) {
3262                 if (DEBUG && mType < 0) {
3263                     Log.v(TAG, "old mUpdateTime=" + mUpdateTimeUs);
3264                 }
3265                 super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
3266                 mUpdateTimeUs = baseRealtimeUs;
3267                 if (DEBUG && mType < 0) {
3268                     Log.v(TAG, "new mUpdateTime=" + mUpdateTimeUs);
3269                 }
3270             }
3271         }
3272 
logState(Printer pw, String prefix)3273         public void logState(Printer pw, String prefix) {
3274             super.logState(pw, prefix);
3275             pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTimeUs
3276                     + " mAcquireTime=" + mAcquireTimeUs);
3277         }
3278 
startRunningLocked(long elapsedRealtimeMs)3279         public void startRunningLocked(long elapsedRealtimeMs) {
3280             if (mNesting++ == 0) {
3281                 final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
3282                 mUpdateTimeUs = batteryRealtimeUs;
3283                 if (mTimerPool != null) {
3284                     // Accumulate time to all currently active timers before adding
3285                     // this new one to the pool.
3286                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, null);
3287                     // Add this timer to the active pool
3288                     mTimerPool.add(this);
3289                 }
3290                 if (mTimeBase.isRunning()) {
3291                     // Increment the count
3292                     mCount++;
3293                     mAcquireTimeUs = mTotalTimeUs;
3294                 } else {
3295                     mAcquireTimeUs = -1;
3296                 }
3297                 if (DEBUG && mType < 0) {
3298                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTimeUs
3299                             + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount
3300                             + " mAcquireTime=" + mAcquireTimeUs);
3301                 }
3302             }
3303         }
3304 
isRunningLocked()3305         public boolean isRunningLocked() {
3306             return mNesting > 0;
3307         }
3308 
stopRunningLocked(long elapsedRealtimeMs)3309         public void stopRunningLocked(long elapsedRealtimeMs) {
3310             // Ignore attempt to stop a timer that isn't running
3311             if (mNesting == 0) {
3312                 return;
3313             }
3314             if (--mNesting == 0) {
3315                 final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
3316                 if (mTimerPool != null) {
3317                     // Accumulate time to all active counters, scaled by the total
3318                     // active in the pool, before taking this one out of the pool.
3319                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, null);
3320                     // Remove this timer from the active pool
3321                     mTimerPool.remove(this);
3322                 } else {
3323                     mNesting = 1;
3324                     mTotalTimeUs = computeRunTimeLocked(batteryRealtimeUs,
3325                             elapsedRealtimeMs * 1000);
3326                     mNesting = 0;
3327                 }
3328 
3329                 if (DEBUG && mType < 0) {
3330                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTimeUs
3331                             + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount
3332                             + " mAcquireTime=" + mAcquireTimeUs);
3333                 }
3334 
3335                 if (mAcquireTimeUs >= 0 && mTotalTimeUs == mAcquireTimeUs) {
3336                     // If there was no change in the time, then discard this
3337                     // count.  A somewhat cheezy strategy, but hey.
3338                     mCount--;
3339                 }
3340             }
3341         }
3342 
stopAllRunningLocked(long elapsedRealtimeMs)3343         public void stopAllRunningLocked(long elapsedRealtimeMs) {
3344             if (mNesting > 0) {
3345                 mNesting = 1;
3346                 stopRunningLocked(elapsedRealtimeMs);
3347             }
3348         }
3349 
3350         // Update the total time for all other running Timers with the same type as this Timer
3351         // due to a change in timer count
refreshTimersLocked(long batteryRealtimeUs, final ArrayList<StopwatchTimer> pool, StopwatchTimer self)3352         private static long refreshTimersLocked(long batteryRealtimeUs,
3353                 final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
3354             long selfTimeUs = 0;
3355             final int N = pool.size();
3356             for (int i=N-1; i>= 0; i--) {
3357                 final StopwatchTimer t = pool.get(i);
3358                 long heldTimeUs = batteryRealtimeUs - t.mUpdateTimeUs;
3359                 if (heldTimeUs > 0) {
3360                     final long myTimeUs = heldTimeUs / N;
3361                     if (t == self) {
3362                         selfTimeUs = myTimeUs;
3363                     }
3364                     t.mTotalTimeUs += myTimeUs;
3365                 }
3366                 t.mUpdateTimeUs = batteryRealtimeUs;
3367             }
3368             return selfTimeUs;
3369         }
3370 
3371         @Override
computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs)3372         protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) {
3373             if (mTimeoutUs > 0 && curBatteryRealtimeUs > mUpdateTimeUs + mTimeoutUs) {
3374                 curBatteryRealtimeUs = mUpdateTimeUs + mTimeoutUs;
3375             }
3376             return mTotalTimeUs + (mNesting > 0
3377                     ? (curBatteryRealtimeUs - mUpdateTimeUs)
3378                             / (mTimerPool != null ? mTimerPool.size() : 1)
3379                     : 0);
3380         }
3381 
3382         @Override
computeCurrentCountLocked()3383         protected int computeCurrentCountLocked() {
3384             return mCount;
3385         }
3386 
3387         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3388         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3389             boolean canDetach = mNesting <= 0;
3390             super.reset(canDetach && detachIfReset, elapsedRealtimeUs);
3391             if (mNesting > 0) {
3392                 mUpdateTimeUs = mTimeBase.getRealtime(elapsedRealtimeUs);
3393             }
3394             // To ensure mCount isn't decreased to -1 if timer is stopped later.
3395             mAcquireTimeUs = -1;
3396             return canDetach;
3397         }
3398 
3399         @Override
detach()3400         public void detach() {
3401             super.detach();
3402             if (mTimerPool != null) {
3403                 mTimerPool.remove(this);
3404             }
3405         }
3406 
3407         @Override
readSummaryFromParcelLocked(Parcel in)3408         public void readSummaryFromParcelLocked(Parcel in) {
3409             super.readSummaryFromParcelLocked(in);
3410             mNesting = 0;
3411         }
3412 
3413         /**
3414          * Set the mark so that we can query later for the total time the timer has
3415          * accumulated since this point. The timer can be running or not.
3416          *
3417          * @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
3418          */
setMark(long elapsedRealtimeMs)3419         public void setMark(long elapsedRealtimeMs) {
3420             final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
3421             if (mNesting > 0) {
3422                 // We are running.
3423                 if (mTimerPool != null) {
3424                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, this);
3425                 } else {
3426                     mTotalTimeUs += batteryRealtimeUs - mUpdateTimeUs;
3427                     mUpdateTimeUs = batteryRealtimeUs;
3428                 }
3429             }
3430             mTimeBeforeMarkUs = mTotalTimeUs;
3431         }
3432     }
3433 
3434     /**
3435      * State for keeping track of two DurationTimers with different TimeBases, presumably where one
3436      * TimeBase is effectively a subset of the other.
3437      */
3438     public static class DualTimer extends DurationTimer {
3439         // This class both is a DurationTimer and also holds a second DurationTimer.
3440         // The main timer (this) typically tracks the total time. It may be pooled (but since it's a
3441         // durationTimer, it also has the unpooled getTotalDurationMsLocked() for
3442         // STATS_SINCE_CHARGED).
3443         // mSubTimer typically tracks only part of the total time, such as background time, as
3444         // determined by a subTimeBase. It is NOT pooled.
3445         private final DurationTimer mSubTimer;
3446 
3447         /**
3448          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
3449          * The main timer (this) is based on the given timeBase and timerPool.
3450          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
3451          * the main timer is.
3452          */
DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase, Parcel in)3453         public DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3454                 TimeBase timeBase, TimeBase subTimeBase, Parcel in) {
3455             super(clock, uid, type, timerPool, timeBase, in);
3456             mSubTimer = new DurationTimer(clock, uid, type, null, subTimeBase, in);
3457         }
3458 
3459         /**
3460          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
3461          * The main timer (this) is based on the given timeBase and timerPool.
3462          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
3463          * the main timer is.
3464          */
DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase)3465         public DualTimer(Clock clock, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
3466                 TimeBase timeBase, TimeBase subTimeBase) {
3467             super(clock, uid, type, timerPool, timeBase);
3468             mSubTimer = new DurationTimer(clock, uid, type, null, subTimeBase);
3469         }
3470 
3471         /** Get the secondary timer. */
3472         @Override
getSubTimer()3473         public DurationTimer getSubTimer() {
3474             return mSubTimer;
3475         }
3476 
3477         @Override
startRunningLocked(long elapsedRealtimeMs)3478         public void startRunningLocked(long elapsedRealtimeMs) {
3479             super.startRunningLocked(elapsedRealtimeMs);
3480             mSubTimer.startRunningLocked(elapsedRealtimeMs);
3481         }
3482 
3483         @Override
stopRunningLocked(long elapsedRealtimeMs)3484         public void stopRunningLocked(long elapsedRealtimeMs) {
3485             super.stopRunningLocked(elapsedRealtimeMs);
3486             mSubTimer.stopRunningLocked(elapsedRealtimeMs);
3487         }
3488 
3489         @Override
stopAllRunningLocked(long elapsedRealtimeMs)3490         public void stopAllRunningLocked(long elapsedRealtimeMs) {
3491             super.stopAllRunningLocked(elapsedRealtimeMs);
3492             mSubTimer.stopAllRunningLocked(elapsedRealtimeMs);
3493         }
3494 
3495         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)3496         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
3497             boolean active = false;
3498             // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
3499             active |= !mSubTimer.reset(false, elapsedRealtimeUs);
3500             active |= !super.reset(detachIfReset, elapsedRealtimeUs);
3501             return !active;
3502         }
3503 
3504         @Override
detach()3505         public void detach() {
3506             mSubTimer.detach();
3507             super.detach();
3508         }
3509 
3510         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)3511         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
3512             super.writeToParcel(out, elapsedRealtimeUs);
3513             mSubTimer.writeToParcel(out, elapsedRealtimeUs);
3514         }
3515 
3516         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)3517         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
3518             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
3519             mSubTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
3520         }
3521 
3522         @Override
readSummaryFromParcelLocked(Parcel in)3523         public void readSummaryFromParcelLocked(Parcel in) {
3524             super.readSummaryFromParcelLocked(in);
3525             mSubTimer.readSummaryFromParcelLocked(in);
3526         }
3527     }
3528 
3529 
3530     public abstract class OverflowArrayMap<T> {
3531         private static final String OVERFLOW_NAME = "*overflow*";
3532 
3533         final int mUid;
3534         final ArrayMap<String, T> mMap = new ArrayMap<>();
3535         T mCurOverflow;
3536         ArrayMap<String, MutableInt> mActiveOverflow;
3537         long mLastOverflowTimeMs;
3538         long mLastOverflowFinishTimeMs;
3539         long mLastClearTimeMs;
3540         long mLastCleanupTimeMs;
3541 
OverflowArrayMap(int uid)3542         public OverflowArrayMap(int uid) {
3543             mUid = uid;
3544         }
3545 
getMap()3546         public ArrayMap<String, T> getMap() {
3547             return mMap;
3548         }
3549 
clear()3550         public void clear() {
3551             mLastClearTimeMs = SystemClock.elapsedRealtime();
3552             mMap.clear();
3553             mCurOverflow = null;
3554             mActiveOverflow = null;
3555         }
3556 
add(String name, T obj)3557         public void add(String name, T obj) {
3558             if (name == null) {
3559                 name = "";
3560             }
3561             mMap.put(name, obj);
3562             if (OVERFLOW_NAME.equals(name)) {
3563                 mCurOverflow = obj;
3564             }
3565         }
3566 
cleanup(long elapsedRealtimeMs)3567         public void cleanup(long elapsedRealtimeMs) {
3568             mLastCleanupTimeMs = elapsedRealtimeMs;
3569             if (mActiveOverflow != null) {
3570                 if (mActiveOverflow.size() == 0) {
3571                     mActiveOverflow = null;
3572                 }
3573             }
3574             if (mActiveOverflow == null) {
3575                 // There is no currently active overflow, so we should no longer have
3576                 // an overflow entry.
3577                 if (mMap.containsKey(OVERFLOW_NAME)) {
3578                     Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
3579                             + mMap.get(OVERFLOW_NAME));
3580                     mMap.remove(OVERFLOW_NAME);
3581                 }
3582                 mCurOverflow = null;
3583             } else {
3584                 // There is currently active overflow, so we should still have an overflow entry.
3585                 if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
3586                     Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
3587                             + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
3588                 }
3589             }
3590         }
3591 
startObject(String name, long elapsedRealtimeMs)3592         public T startObject(String name, long elapsedRealtimeMs) {
3593             if (name == null) {
3594                 name = "";
3595             }
3596             T obj = mMap.get(name);
3597             if (obj != null) {
3598                 return obj;
3599             }
3600 
3601             // No object exists for the given name, but do we currently have it
3602             // running as part of the overflow?
3603             if (mActiveOverflow != null) {
3604                 MutableInt over = mActiveOverflow.get(name);
3605                 if (over != null) {
3606                     // We are already actively counting this name in the overflow object.
3607                     obj = mCurOverflow;
3608                     if (obj == null) {
3609                         // Shouldn't be here, but we'll try to recover.
3610                         Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
3611                         obj = mCurOverflow = instantiateObject();
3612                         mMap.put(OVERFLOW_NAME, obj);
3613                     }
3614                     over.value++;
3615                     return obj;
3616                 }
3617             }
3618 
3619             // No object exists for given name nor in the overflow; we need to make
3620             // a new one.
3621             final int N = mMap.size();
3622             if (N >= MAX_WAKELOCKS_PER_UID) {
3623                 // Went over the limit on number of objects to track; this one goes
3624                 // in to the overflow.
3625                 obj = mCurOverflow;
3626                 if (obj == null) {
3627                     // Need to start overflow now...
3628                     obj = mCurOverflow = instantiateObject();
3629                     mMap.put(OVERFLOW_NAME, obj);
3630                 }
3631                 if (mActiveOverflow == null) {
3632                     mActiveOverflow = new ArrayMap<>();
3633                 }
3634                 mActiveOverflow.put(name, new MutableInt(1));
3635                 mLastOverflowTimeMs = elapsedRealtimeMs;
3636                 return obj;
3637             }
3638 
3639             // Normal case where we just need to make a new object.
3640             obj = instantiateObject();
3641             mMap.put(name, obj);
3642             return obj;
3643         }
3644 
stopObject(String name, long elapsedRealtimeMs)3645         public T stopObject(String name, long elapsedRealtimeMs) {
3646             if (name == null) {
3647                 name = "";
3648             }
3649             T obj = mMap.get(name);
3650             if (obj != null) {
3651                 return obj;
3652             }
3653 
3654             // No object exists for the given name, but do we currently have it
3655             // running as part of the overflow?
3656             if (mActiveOverflow != null) {
3657                 MutableInt over = mActiveOverflow.get(name);
3658                 if (over != null) {
3659                     // We are already actively counting this name in the overflow object.
3660                     obj = mCurOverflow;
3661                     if (obj != null) {
3662                         over.value--;
3663                         if (over.value <= 0) {
3664                             mActiveOverflow.remove(name);
3665                             mLastOverflowFinishTimeMs = elapsedRealtimeMs;
3666                         }
3667                         return obj;
3668                     }
3669                 }
3670             }
3671 
3672             // Huh, they are stopping an active operation but we can't find one!
3673             // That's not good.
3674             StringBuilder sb = new StringBuilder();
3675             sb.append("Unable to find object for ");
3676             sb.append(name);
3677             sb.append(" in uid ");
3678             sb.append(mUid);
3679             sb.append(" mapsize=");
3680             sb.append(mMap.size());
3681             sb.append(" activeoverflow=");
3682             sb.append(mActiveOverflow);
3683             sb.append(" curoverflow=");
3684             sb.append(mCurOverflow);
3685             long now = elapsedRealtimeMs;
3686             if (mLastOverflowTimeMs != 0) {
3687                 sb.append(" lastOverflowTime=");
3688                 TimeUtils.formatDuration(mLastOverflowTimeMs - now, sb);
3689             }
3690             if (mLastOverflowFinishTimeMs != 0) {
3691                 sb.append(" lastOverflowFinishTime=");
3692                 TimeUtils.formatDuration(mLastOverflowFinishTimeMs - now, sb);
3693             }
3694             if (mLastClearTimeMs != 0) {
3695                 sb.append(" lastClearTime=");
3696                 TimeUtils.formatDuration(mLastClearTimeMs - now, sb);
3697             }
3698             if (mLastCleanupTimeMs != 0) {
3699                 sb.append(" lastCleanupTime=");
3700                 TimeUtils.formatDuration(mLastCleanupTimeMs - now, sb);
3701             }
3702             Slog.wtf(TAG, sb.toString());
3703             return null;
3704         }
3705 
instantiateObject()3706         public abstract T instantiateObject();
3707     }
3708 
3709     public static class ControllerActivityCounterImpl extends ControllerActivityCounter
3710             implements Parcelable {
3711         private final Clock mClock;
3712         private final TimeBase mTimeBase;
3713         private int mNumTxStates;
3714         private int mProcessState;
3715         private TimeMultiStateCounter mIdleTimeMillis;
3716         private final LongSamplingCounter mScanTimeMillis;
3717         private final LongSamplingCounter mSleepTimeMillis;
3718         private TimeMultiStateCounter mRxTimeMillis;
3719         private TimeMultiStateCounter[] mTxTimeMillis;
3720         private final LongSamplingCounter mPowerDrainMaMs;
3721         private final LongSamplingCounter mMonitoredRailChargeConsumedMaMs;
3722 
ControllerActivityCounterImpl(Clock clock, TimeBase timeBase, int numTxStates)3723         public ControllerActivityCounterImpl(Clock clock, TimeBase timeBase, int numTxStates) {
3724             mClock = clock;
3725             mTimeBase = timeBase;
3726             mNumTxStates = numTxStates;
3727             mScanTimeMillis = new LongSamplingCounter(timeBase);
3728             mSleepTimeMillis = new LongSamplingCounter(timeBase);
3729             mPowerDrainMaMs = new LongSamplingCounter(timeBase);
3730             mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase);
3731         }
3732 
readSummaryFromParcel(Parcel in)3733         public void readSummaryFromParcel(Parcel in) {
3734             mIdleTimeMillis = readTimeMultiStateCounter(in, mTimeBase);
3735             mScanTimeMillis.readSummaryFromParcelLocked(in);
3736             mSleepTimeMillis.readSummaryFromParcelLocked(in);
3737             mRxTimeMillis = readTimeMultiStateCounter(in, mTimeBase);
3738             mTxTimeMillis = readTimeMultiStateCounters(in, mTimeBase, mNumTxStates);
3739 
3740             mPowerDrainMaMs.readSummaryFromParcelLocked(in);
3741             mMonitoredRailChargeConsumedMaMs.readSummaryFromParcelLocked(in);
3742         }
3743 
3744         @Override
describeContents()3745         public int describeContents() {
3746             return 0;
3747         }
3748 
writeSummaryToParcel(Parcel dest)3749         public void writeSummaryToParcel(Parcel dest) {
3750             writeTimeMultiStateCounter(dest, mIdleTimeMillis);
3751             mScanTimeMillis.writeSummaryFromParcelLocked(dest);
3752             mSleepTimeMillis.writeSummaryFromParcelLocked(dest);
3753             writeTimeMultiStateCounter(dest, mRxTimeMillis);
3754             writeTimeMultiStateCounters(dest, mTxTimeMillis);
3755             mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
3756             mMonitoredRailChargeConsumedMaMs.writeSummaryFromParcelLocked(dest);
3757         }
3758 
3759         @Override
writeToParcel(Parcel dest, int flags)3760         public void writeToParcel(Parcel dest, int flags) {
3761             writeTimeMultiStateCounter(dest, mIdleTimeMillis);
3762             mScanTimeMillis.writeToParcel(dest);
3763             mSleepTimeMillis.writeToParcel(dest);
3764             writeTimeMultiStateCounter(dest, mRxTimeMillis);
3765             writeTimeMultiStateCounters(dest, mTxTimeMillis);
3766             mPowerDrainMaMs.writeToParcel(dest);
3767             mMonitoredRailChargeConsumedMaMs.writeToParcel(dest);
3768         }
3769 
readTimeMultiStateCounter(Parcel in, TimeBase timeBase)3770         private TimeMultiStateCounter readTimeMultiStateCounter(Parcel in, TimeBase timeBase) {
3771             if (in.readBoolean()) {
3772                 return TimeMultiStateCounter.readFromParcel(in, timeBase,
3773                         BatteryConsumer.PROCESS_STATE_COUNT, mClock.elapsedRealtime());
3774             }
3775             return null;
3776         }
3777 
writeTimeMultiStateCounter(Parcel dest, TimeMultiStateCounter counter)3778         private void writeTimeMultiStateCounter(Parcel dest, TimeMultiStateCounter counter) {
3779             if (counter != null) {
3780                 dest.writeBoolean(true);
3781                 counter.writeToParcel(dest);
3782             } else {
3783                 dest.writeBoolean(false);
3784             }
3785         }
3786 
readTimeMultiStateCounters(Parcel in, TimeBase timeBase, int expectedNumCounters)3787         private TimeMultiStateCounter[] readTimeMultiStateCounters(Parcel in, TimeBase timeBase,
3788                 int expectedNumCounters) {
3789             if (in.readBoolean()) {
3790                 final int numCounters = in.readInt();
3791                 boolean valid = (numCounters == expectedNumCounters);
3792                 // Need to read counters out of the Parcel, even if all or some of them are
3793                 // invalid.
3794                 TimeMultiStateCounter[] counters = new TimeMultiStateCounter[numCounters];
3795                 for (int i = 0; i < numCounters; i++) {
3796                     final TimeMultiStateCounter counter = TimeMultiStateCounter.readFromParcel(in,
3797                             timeBase, BatteryConsumer.PROCESS_STATE_COUNT,
3798                             mClock.elapsedRealtime());
3799                     if (counter != null) {
3800                         counters[i] = counter;
3801                     } else {
3802                         valid = false;
3803                     }
3804                 }
3805                 if (valid) {
3806                     return counters;
3807                 }
3808             }
3809             return null;
3810         }
3811 
writeTimeMultiStateCounters(Parcel dest, TimeMultiStateCounter[] counters)3812         private void writeTimeMultiStateCounters(Parcel dest, TimeMultiStateCounter[] counters) {
3813             if (counters != null) {
3814                 dest.writeBoolean(true);
3815                 dest.writeInt(counters.length);
3816                 for (TimeMultiStateCounter counter : counters) {
3817                     counter.writeToParcel(dest);
3818                 }
3819             } else {
3820                 dest.writeBoolean(false);
3821             }
3822         }
3823 
reset(boolean detachIfReset, long elapsedRealtimeUs)3824         public void reset(boolean detachIfReset, long elapsedRealtimeUs) {
3825             resetIfNotNull(mIdleTimeMillis, detachIfReset, elapsedRealtimeUs);
3826             mScanTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
3827             mSleepTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
3828             resetIfNotNull(mRxTimeMillis, detachIfReset, elapsedRealtimeUs);
3829             resetIfNotNull(mTxTimeMillis, detachIfReset, elapsedRealtimeUs);
3830             mPowerDrainMaMs.reset(detachIfReset, elapsedRealtimeUs);
3831             mMonitoredRailChargeConsumedMaMs.reset(detachIfReset, elapsedRealtimeUs);
3832         }
3833 
detach()3834         public void detach() {
3835             detachIfNotNull(mIdleTimeMillis);
3836             mScanTimeMillis.detach();
3837             mSleepTimeMillis.detach();
3838             detachIfNotNull(mRxTimeMillis);
3839             detachIfNotNull(mTxTimeMillis);
3840             mPowerDrainMaMs.detach();
3841             mMonitoredRailChargeConsumedMaMs.detach();
3842         }
3843 
3844         /**
3845          * @return a LongSamplingCounter, measuring time spent in the idle state in
3846          * milliseconds.
3847          */
3848         @Override
getIdleTimeCounter()3849         public LongCounter getIdleTimeCounter() {
3850             if (mIdleTimeMillis == null) {
3851                 return ZERO_LONG_COUNTER;
3852             }
3853             return mIdleTimeMillis;
3854         }
3855 
getOrCreateIdleTimeCounter()3856         private TimeMultiStateCounter getOrCreateIdleTimeCounter() {
3857             if (mIdleTimeMillis == null) {
3858                 mIdleTimeMillis = createTimeMultiStateCounter();
3859             }
3860             return mIdleTimeMillis;
3861         }
3862 
3863         /**
3864          * @return a LongSamplingCounter, measuring time spent in the scan state in
3865          * milliseconds.
3866          */
3867         @Override
getScanTimeCounter()3868         public LongSamplingCounter getScanTimeCounter() {
3869             return mScanTimeMillis;
3870         }
3871 
3872         /**
3873          * @return a LongSamplingCounter, measuring time spent in the sleep state in
3874          * milliseconds.
3875          */
3876         @Override
getSleepTimeCounter()3877         public LongSamplingCounter getSleepTimeCounter() {
3878             return mSleepTimeMillis;
3879         }
3880 
3881         /**
3882          * @return a LongSamplingCounter, measuring time spent in the receive state in
3883          * milliseconds.
3884          */
3885         @Override
getRxTimeCounter()3886         public LongCounter getRxTimeCounter() {
3887             if (mRxTimeMillis == null) {
3888                 return ZERO_LONG_COUNTER;
3889             }
3890             return mRxTimeMillis;
3891         }
3892 
getOrCreateRxTimeCounter()3893         private TimeMultiStateCounter getOrCreateRxTimeCounter() {
3894             if (mRxTimeMillis == null) {
3895                 mRxTimeMillis = createTimeMultiStateCounter();
3896             }
3897             return mRxTimeMillis;
3898         }
3899 
3900         /**
3901          * @return a LongSamplingCounter[], measuring time spent in various transmit states in
3902          * milliseconds.
3903          */
3904         @Override
getTxTimeCounters()3905         public LongCounter[] getTxTimeCounters() {
3906             if (mTxTimeMillis == null) {
3907                 return ZERO_LONG_COUNTER_ARRAY;
3908             }
3909             return mTxTimeMillis;
3910         }
3911 
getOrCreateTxTimeCounters()3912         private TimeMultiStateCounter[] getOrCreateTxTimeCounters() {
3913             if (mTxTimeMillis == null) {
3914                 mTxTimeMillis = new TimeMultiStateCounter[mNumTxStates];
3915                 for (int i = 0; i < mNumTxStates; i++) {
3916                     mTxTimeMillis[i] = createTimeMultiStateCounter();
3917                 }
3918             }
3919             return mTxTimeMillis;
3920         }
3921 
createTimeMultiStateCounter()3922         private TimeMultiStateCounter createTimeMultiStateCounter() {
3923             final long timestampMs = mClock.elapsedRealtime();
3924             TimeMultiStateCounter counter = new TimeMultiStateCounter(mTimeBase,
3925                     BatteryConsumer.PROCESS_STATE_COUNT, timestampMs);
3926             counter.setState(mapUidProcessStateToBatteryConsumerProcessState(mProcessState),
3927                     timestampMs);
3928             counter.update(0, timestampMs);
3929             return counter;
3930         }
3931 
3932         /**
3933          * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
3934          */
3935         @Override
getPowerCounter()3936         public LongSamplingCounter getPowerCounter() {
3937             return mPowerDrainMaMs;
3938         }
3939 
3940         /**
3941          * @return a LongSamplingCounter, measuring actual monitored rail energy consumed
3942          * milli-ampere milli-seconds (mAmS).
3943          */
3944         @Override
getMonitoredRailChargeConsumedMaMs()3945         public LongSamplingCounter getMonitoredRailChargeConsumedMaMs() {
3946             return mMonitoredRailChargeConsumedMaMs;
3947         }
3948 
setState(int processState, long elapsedTimeMs)3949         private void setState(int processState, long elapsedTimeMs) {
3950             mProcessState = processState;
3951             if (mIdleTimeMillis != null) {
3952                 mIdleTimeMillis.setState(processState, elapsedTimeMs);
3953             }
3954             if (mRxTimeMillis != null) {
3955                 mRxTimeMillis.setState(processState, elapsedTimeMs);
3956             }
3957             if (mTxTimeMillis != null) {
3958                 for (int i = 0; i < mTxTimeMillis.length; i++) {
3959                     mTxTimeMillis[i].setState(processState, elapsedTimeMs);
3960                 }
3961             }
3962         }
3963     }
3964 
3965     /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */
getRpmTimerLocked(String name)3966     public SamplingTimer getRpmTimerLocked(String name) {
3967         SamplingTimer rpmt = mRpmStats.get(name);
3968         if (rpmt == null) {
3969             rpmt = new SamplingTimer(mClock, mOnBatteryTimeBase);
3970             mRpmStats.put(name, rpmt);
3971         }
3972         return rpmt;
3973     }
3974 
3975     /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */
getScreenOffRpmTimerLocked(String name)3976     public SamplingTimer getScreenOffRpmTimerLocked(String name) {
3977         SamplingTimer rpmt = mScreenOffRpmStats.get(name);
3978         if (rpmt == null) {
3979             rpmt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase);
3980             mScreenOffRpmStats.put(name, rpmt);
3981         }
3982         return rpmt;
3983     }
3984 
3985     /*
3986      * Get the wakeup reason counter, and create a new one if one
3987      * doesn't already exist.
3988      */
getWakeupReasonTimerLocked(String name)3989     public SamplingTimer getWakeupReasonTimerLocked(String name) {
3990         SamplingTimer timer = mWakeupReasonStats.get(name);
3991         if (timer == null) {
3992             timer = new SamplingTimer(mClock, mOnBatteryTimeBase);
3993             mWakeupReasonStats.put(name, timer);
3994         }
3995         return timer;
3996     }
3997 
3998     /*
3999      * Get the KernelWakelockTimer associated with name, and create a new one if one
4000      * doesn't already exist.
4001      */
getKernelWakelockTimerLocked(String name)4002     public SamplingTimer getKernelWakelockTimerLocked(String name) {
4003         SamplingTimer kwlt = mKernelWakelockStats.get(name);
4004         if (kwlt == null) {
4005             kwlt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase);
4006             mKernelWakelockStats.put(name, kwlt);
4007         }
4008         return kwlt;
4009     }
4010 
getKernelMemoryTimerLocked(long bucket)4011     public SamplingTimer getKernelMemoryTimerLocked(long bucket) {
4012         SamplingTimer kmt = mKernelMemoryStats.get(bucket);
4013         if (kmt == null) {
4014             kmt = new SamplingTimer(mClock, mOnBatteryTimeBase);
4015             mKernelMemoryStats.put(bucket, kmt);
4016         }
4017         return kmt;
4018     }
4019 
4020     private class HistoryStepDetailsCalculatorImpl implements HistoryStepDetailsCalculator {
4021         private final HistoryStepDetails mDetails = new HistoryStepDetails();
4022 
4023         private boolean mHasHistoryStepDetails;
4024         private boolean mUpdateRequested;
4025 
4026         /**
4027          * Total time (in milliseconds) spent executing in user code.
4028          */
4029         private long mLastStepCpuUserTimeMs;
4030         private long mCurStepCpuUserTimeMs;
4031         /**
4032          * Total time (in milliseconds) spent executing in kernel code.
4033          */
4034         private long mLastStepCpuSystemTimeMs;
4035         private long mCurStepCpuSystemTimeMs;
4036         /**
4037          * Times from /proc/stat (but measured in milliseconds).
4038          */
4039         private long mLastStepStatUserTimeMs;
4040         private long mLastStepStatSystemTimeMs;
4041         private long mLastStepStatIOWaitTimeMs;
4042         private long mLastStepStatIrqTimeMs;
4043         private long mLastStepStatSoftIrqTimeMs;
4044         private long mLastStepStatIdleTimeMs;
4045         private long mCurStepStatUserTimeMs;
4046         private long mCurStepStatSystemTimeMs;
4047         private long mCurStepStatIOWaitTimeMs;
4048         private long mCurStepStatIrqTimeMs;
4049         private long mCurStepStatSoftIrqTimeMs;
4050         private long mCurStepStatIdleTimeMs;
4051 
4052         @Override
getHistoryStepDetails()4053         public HistoryStepDetails getHistoryStepDetails() {
4054             if (!mUpdateRequested) {
4055                 mUpdateRequested = true;
4056                 // Perform a CPU update right after we do this collection, so we have started
4057                 // collecting good data for the next step.
4058                 requestImmediateCpuUpdate();
4059 
4060                 if (mPlatformIdleStateCallback != null) {
4061                     mDetails.statSubsystemPowerState =
4062                             mPlatformIdleStateCallback.getSubsystemLowPowerStats();
4063                     if (DEBUG) {
4064                         Slog.i(TAG,
4065                                 "WRITE SubsystemPowerState:" + mDetails.statSubsystemPowerState);
4066                     }
4067                 }
4068             }
4069 
4070             if (!mHasHistoryStepDetails) {
4071                 // We are not generating a delta, so all we need to do is reset the stats
4072                 // we will later be doing a delta from.
4073                 final int uidCount = mUidStats.size();
4074                 for (int i = 0; i < uidCount; i++) {
4075                     final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4076                     uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
4077                     uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
4078                 }
4079                 mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
4080                 mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
4081                 mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
4082                 mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
4083                 mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
4084                 mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
4085                 mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
4086                 mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
4087                 return null;
4088             } else {
4089                 if (DEBUG) {
4090                     Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTimeMs + " sys="
4091                             + mLastStepStatSystemTimeMs + " io=" + mLastStepStatIOWaitTimeMs
4092                             + " irq=" + mLastStepStatIrqTimeMs + " sirq="
4093                             + mLastStepStatSoftIrqTimeMs + " idle=" + mLastStepStatIdleTimeMs);
4094                     Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTimeMs + " sys="
4095                             + mCurStepStatSystemTimeMs + " io=" + mCurStepStatIOWaitTimeMs
4096                             + " irq=" + mCurStepStatIrqTimeMs + " sirq="
4097                             + mCurStepStatSoftIrqTimeMs + " idle=" + mCurStepStatIdleTimeMs);
4098                 }
4099                 mDetails.userTime = (int) (mCurStepCpuUserTimeMs - mLastStepCpuUserTimeMs);
4100                 mDetails.systemTime = (int) (mCurStepCpuSystemTimeMs - mLastStepCpuSystemTimeMs);
4101                 mDetails.statUserTime = (int) (mCurStepStatUserTimeMs - mLastStepStatUserTimeMs);
4102                 mDetails.statSystemTime =
4103                         (int) (mCurStepStatSystemTimeMs - mLastStepStatSystemTimeMs);
4104                 mDetails.statIOWaitTime =
4105                         (int) (mCurStepStatIOWaitTimeMs - mLastStepStatIOWaitTimeMs);
4106                 mDetails.statIrqTime = (int) (mCurStepStatIrqTimeMs - mLastStepStatIrqTimeMs);
4107                 mDetails.statSoftIrqTime =
4108                         (int) (mCurStepStatSoftIrqTimeMs - mLastStepStatSoftIrqTimeMs);
4109                 mDetails.statIdlTime = (int) (mCurStepStatIdleTimeMs - mLastStepStatIdleTimeMs);
4110                 mDetails.appCpuUid1 = mDetails.appCpuUid2 = mDetails.appCpuUid3 = -1;
4111                 mDetails.appCpuUTime1 = mDetails.appCpuUTime2 = mDetails.appCpuUTime3 = 0;
4112                 mDetails.appCpuSTime1 = mDetails.appCpuSTime2 = mDetails.appCpuSTime3 = 0;
4113                 final int uidCount = mUidStats.size();
4114                 for (int i = 0; i < uidCount; i++) {
4115                     final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4116                     final int totalUTimeMs =
4117                             (int) (uid.mCurStepUserTimeMs - uid.mLastStepUserTimeMs);
4118                     final int totalSTimeMs =
4119                             (int) (uid.mCurStepSystemTimeMs - uid.mLastStepSystemTimeMs);
4120                     final int totalTimeMs = totalUTimeMs + totalSTimeMs;
4121                     uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
4122                     uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
4123                     if (totalTimeMs <= (mDetails.appCpuUTime3 + mDetails.appCpuSTime3)) {
4124                         continue;
4125                     }
4126                     if (totalTimeMs <= (mDetails.appCpuUTime2 + mDetails.appCpuSTime2)) {
4127                         mDetails.appCpuUid3 = uid.mUid;
4128                         mDetails.appCpuUTime3 = totalUTimeMs;
4129                         mDetails.appCpuSTime3 = totalSTimeMs;
4130                     } else {
4131                         mDetails.appCpuUid3 = mDetails.appCpuUid2;
4132                         mDetails.appCpuUTime3 = mDetails.appCpuUTime2;
4133                         mDetails.appCpuSTime3 = mDetails.appCpuSTime2;
4134                         if (totalTimeMs <= (mDetails.appCpuUTime1 + mDetails.appCpuSTime1)) {
4135                             mDetails.appCpuUid2 = uid.mUid;
4136                             mDetails.appCpuUTime2 = totalUTimeMs;
4137                             mDetails.appCpuSTime2 = totalSTimeMs;
4138                         } else {
4139                             mDetails.appCpuUid2 = mDetails.appCpuUid1;
4140                             mDetails.appCpuUTime2 = mDetails.appCpuUTime1;
4141                             mDetails.appCpuSTime2 = mDetails.appCpuSTime1;
4142                             mDetails.appCpuUid1 = uid.mUid;
4143                             mDetails.appCpuUTime1 = totalUTimeMs;
4144                             mDetails.appCpuSTime1 = totalSTimeMs;
4145                         }
4146                     }
4147                 }
4148                 mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
4149                 mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
4150                 mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
4151                 mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
4152                 mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
4153                 mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
4154                 mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
4155                 mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
4156                 return mDetails;
4157             }
4158         }
4159 
addCpuStats(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs, int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs, int statSoftIrqTimeMs, int statIdleTimeMs)4160         public void addCpuStats(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs,
4161                 int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
4162                 int statSoftIrqTimeMs, int statIdleTimeMs) {
4163             if (DEBUG) {
4164                 Slog.d(TAG, "Adding cpu: tuser=" + totalUTimeMs + " tsys=" + totalSTimeMs
4165                         + " user=" + statUserTimeMs + " sys=" + statSystemTimeMs
4166                         + " io=" + statIOWaitTimeMs + " irq=" + statIrqTimeMs
4167                         + " sirq=" + statSoftIrqTimeMs + " idle=" + statIdleTimeMs);
4168             }
4169             mCurStepCpuUserTimeMs += totalUTimeMs;
4170             mCurStepCpuSystemTimeMs += totalSTimeMs;
4171             mCurStepStatUserTimeMs += statUserTimeMs;
4172             mCurStepStatSystemTimeMs += statSystemTimeMs;
4173             mCurStepStatIOWaitTimeMs += statIOWaitTimeMs;
4174             mCurStepStatIrqTimeMs += statIrqTimeMs;
4175             mCurStepStatSoftIrqTimeMs += statSoftIrqTimeMs;
4176             mCurStepStatIdleTimeMs += statIdleTimeMs;
4177         }
4178 
finishAddingCpuLocked()4179         public void finishAddingCpuLocked() {
4180             mHasHistoryStepDetails = true;
4181             mUpdateRequested = false;
4182         }
4183 
4184         @Override
clear()4185         public void clear() {
4186             mHasHistoryStepDetails = false;
4187             mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs = 0;
4188             mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs = 0;
4189             mLastStepStatUserTimeMs = mCurStepStatUserTimeMs = 0;
4190             mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs = 0;
4191             mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs = 0;
4192             mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs = 0;
4193             mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs = 0;
4194             mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs = 0;
4195         }
4196     }
4197 
4198     @GuardedBy("this")
4199     @Override
commitCurrentHistoryBatchLocked()4200     public void commitCurrentHistoryBatchLocked() {
4201         mHistory.commitCurrentHistoryBatchLocked();
4202     }
4203 
4204     @GuardedBy("this")
createFakeHistoryEvents(long numEvents)4205     public void createFakeHistoryEvents(long numEvents) {
4206         final long elapsedRealtimeMs = mClock.elapsedRealtime();
4207         final long uptimeMs = mClock.uptimeMillis();
4208         for(long i = 0; i < numEvents; i++) {
4209             noteLongPartialWakelockStart("name1", "historyName1", 1000,
4210                     elapsedRealtimeMs, uptimeMs);
4211             noteLongPartialWakelockFinish("name1", "historyName1", 1000,
4212                     elapsedRealtimeMs, uptimeMs);
4213         }
4214     }
4215 
4216     @GuardedBy("this")
recordHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code, String name, int uid)4217     public void recordHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
4218             String name, int uid) {
4219         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, code, name, uid);
4220     }
4221 
4222     @GuardedBy("this")
updateTimeBasesLocked(boolean unplugged, int screenState, long uptimeUs, long realtimeUs)4223     public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptimeUs,
4224             long realtimeUs) {
4225         final boolean screenOff = !Display.isOnState(screenState);
4226         final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
4227         final boolean updateOnBatteryScreenOffTimeBase =
4228                 (unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
4229 
4230         if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) {
4231             if (updateOnBatteryScreenOffTimeBase) {
4232                 updateKernelWakelocksLocked(realtimeUs);
4233                 updateBatteryPropertiesLocked();
4234             }
4235             // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
4236             // updateRpmStatsLocked is too slow to run each screen change. When the speed is
4237             // improved, remove the surrounding if{}.
4238             if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
4239                 // if either OnBattery or OnBatteryScreenOfftimebase changes.
4240                 updateRpmStatsLocked(realtimeUs);
4241             }
4242             if (DEBUG_ENERGY_CPU) {
4243                 Slog.d(TAG, "Updating cpu time because screen is now "
4244                         + Display.stateToString(screenState)
4245                         + " and battery is " + (unplugged ? "on" : "off"));
4246             }
4247 
4248             mOnBatteryTimeBase.setRunning(unplugged, uptimeUs, realtimeUs);
4249             if (updateOnBatteryTimeBase) {
4250                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
4251                     mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptimeUs, realtimeUs);
4252                 }
4253             }
4254             if (updateOnBatteryScreenOffTimeBase) {
4255                 mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff,
4256                         uptimeUs, realtimeUs);
4257                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
4258                     mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptimeUs, realtimeUs);
4259                 }
4260             }
4261         }
4262     }
4263 
4264     @GuardedBy("this")
updateBatteryPropertiesLocked()4265     private void updateBatteryPropertiesLocked() {
4266         try {
4267             IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
4268                     ServiceManager.getService("batteryproperties"));
4269             if (registrar != null) {
4270                 registrar.scheduleUpdate();
4271             }
4272         } catch (RemoteException e) {
4273             // Ignore.
4274         }
4275     }
4276 
4277     @GuardedBy("this")
addIsolatedUidLocked(int isolatedUid, int appUid)4278     public void addIsolatedUidLocked(int isolatedUid, int appUid) {
4279         addIsolatedUidLocked(isolatedUid, appUid,
4280                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4281     }
4282 
4283     @GuardedBy("this")
4284     @SuppressWarnings("GuardedBy")   // errorprone false positive on u.addIsolatedUid
addIsolatedUidLocked(int isolatedUid, int appUid, long elapsedRealtimeMs, long uptimeMs)4285     public void addIsolatedUidLocked(int isolatedUid, int appUid,
4286             long elapsedRealtimeMs, long uptimeMs) {
4287         mIsolatedUids.put(isolatedUid, appUid);
4288         mIsolatedUidRefCounts.put(isolatedUid, 1);
4289         final Uid u = getUidStatsLocked(appUid, elapsedRealtimeMs, uptimeMs);
4290         u.addIsolatedUid(isolatedUid);
4291     }
4292 
4293     /**
4294      * Schedules a read of the latest cpu times before removing the isolated UID.
4295      * @see #removeIsolatedUidLocked(int, int, int)
4296      */
scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid)4297     public void scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid) {
4298         int curUid = mIsolatedUids.get(isolatedUid, -1);
4299         if (curUid == appUid) {
4300             if (mExternalSync != null) {
4301                 mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
4302             }
4303         }
4304     }
4305 
4306     /**
4307      * Isolated uid should only be removed after all wakelocks associated with the uid are stopped
4308      * and the cpu time-in-state has been read one last time for the uid.
4309      *
4310      * @see #scheduleRemoveIsolatedUidLocked(int, int)
4311      *
4312      * @return true if the isolated uid is actually removed.
4313      */
4314     @GuardedBy("this")
maybeRemoveIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs, long uptimeMs)4315     public boolean maybeRemoveIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs,
4316             long uptimeMs) {
4317         final int refCount = mIsolatedUidRefCounts.get(isolatedUid, 0) - 1;
4318         if (refCount > 0) {
4319             // Isolated uid is still being tracked
4320             mIsolatedUidRefCounts.put(isolatedUid, refCount);
4321             return false;
4322         }
4323 
4324         final int idx = mIsolatedUids.indexOfKey(isolatedUid);
4325         if (idx >= 0) {
4326             final int ownerUid = mIsolatedUids.valueAt(idx);
4327             final Uid u = getUidStatsLocked(ownerUid, elapsedRealtimeMs, uptimeMs);
4328             u.removeIsolatedUid(isolatedUid);
4329             mIsolatedUids.removeAt(idx);
4330             mIsolatedUidRefCounts.delete(isolatedUid);
4331         } else {
4332             Slog.w(TAG, "Attempted to remove untracked isolated uid (" + isolatedUid + ")");
4333         }
4334         mPendingRemovedUids.add(new UidToRemove(isolatedUid, elapsedRealtimeMs));
4335 
4336         return true;
4337     }
4338 
4339     /**
4340      * Increment the ref count for an isolated uid.
4341      * call #maybeRemoveIsolatedUidLocked to decrement.
4342      */
incrementIsolatedUidRefCount(int uid)4343     public void incrementIsolatedUidRefCount(int uid) {
4344         final int refCount = mIsolatedUidRefCounts.get(uid, 0);
4345         if (refCount <= 0) {
4346             // Uid is not mapped or referenced
4347             Slog.w(TAG,
4348                     "Attempted to increment ref counted of untracked isolated uid (" + uid + ")");
4349             return;
4350         }
4351         mIsolatedUidRefCounts.put(uid, refCount + 1);
4352     }
4353 
mapUid(int uid)4354     private int mapUid(int uid) {
4355         if (Process.isSdkSandboxUid(uid)) {
4356             return Process.getAppUidForSdkSandboxUid(uid);
4357         }
4358         return mapIsolatedUid(uid);
4359     }
4360 
mapIsolatedUid(int uid)4361     private int mapIsolatedUid(int uid) {
4362         return mIsolatedUids.get(/*key=*/uid, /*valueIfKeyNotFound=*/uid);
4363     }
4364 
4365     @GuardedBy("this")
noteEventLocked(int code, String name, int uid, long elapsedRealtimeMs, long uptimeMs)4366     public void noteEventLocked(int code, String name, int uid,
4367             long elapsedRealtimeMs, long uptimeMs) {
4368         uid = mapUid(uid);
4369         if (!mActiveEvents.updateState(code, name, uid, 0)) {
4370             return;
4371         }
4372         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, code, name, uid);
4373     }
4374 
4375     @GuardedBy("this")
noteCurrentTimeChangedLocked(long currentTimeMs, long elapsedRealtimeMs, long uptimeMs)4376     public void noteCurrentTimeChangedLocked(long currentTimeMs,
4377             long elapsedRealtimeMs, long uptimeMs) {
4378         mHistory.recordCurrentTimeChange(elapsedRealtimeMs, uptimeMs, currentTimeMs);
4379     }
4380 
4381     @GuardedBy("this")
noteProcessStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4382     public void noteProcessStartLocked(String name, int uid,
4383             long elapsedRealtimeMs, long uptimeMs) {
4384         uid = mapUid(uid);
4385         if (isOnBattery()) {
4386             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4387             u.getProcessStatsLocked(name).incStartsLocked();
4388         }
4389         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
4390             return;
4391         }
4392         if (!mRecordAllHistory) {
4393             return;
4394         }
4395         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid);
4396     }
4397 
4398     @GuardedBy("this")
noteProcessCrashLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4399     public void noteProcessCrashLocked(String name, int uid,
4400             long elapsedRealtimeMs, long uptimeMs) {
4401         uid = mapUid(uid);
4402         if (isOnBattery()) {
4403             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4404             u.getProcessStatsLocked(name).incNumCrashesLocked();
4405         }
4406     }
4407 
4408     @GuardedBy("this")
noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4409     public void noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4410         uid = mapUid(uid);
4411         if (isOnBattery()) {
4412             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4413             u.getProcessStatsLocked(name).incNumAnrsLocked();
4414         }
4415     }
4416 
4417     @GuardedBy("this")
noteUidProcessStateLocked(int uid, int state)4418     public void noteUidProcessStateLocked(int uid, int state) {
4419         noteUidProcessStateLocked(uid, state, mClock.elapsedRealtime(), mClock.uptimeMillis());
4420     }
4421 
4422     @GuardedBy("this")
4423     @SuppressWarnings("GuardedBy")   // errorprone false positive on u.updateUidProcessStateLocked
noteUidProcessStateLocked(int uid, int state, long elapsedRealtimeMs, long uptimeMs)4424     public void noteUidProcessStateLocked(int uid, int state,
4425             long elapsedRealtimeMs, long uptimeMs) {
4426         int parentUid = mapUid(uid);
4427         if (uid != parentUid) {
4428             if (Process.isIsolated(uid)) {
4429                 // Isolated UIDs process state is already rolled up into parent, so no need to track
4430                 // Otherwise the parent's process state will get downgraded incorrectly
4431                 return;
4432             }
4433         }
4434         // TODO(b/155216561): It is possible for isolated uids to be in a higher
4435         // state than its parent uid. We should track the highest state within the union of host
4436         // and isolated uids rather than only the parent uid.
4437         FrameworkStatsLog.write(FrameworkStatsLog.UID_PROCESS_STATE_CHANGED, uid,
4438                 ActivityManager.processStateAmToProto(state));
4439         getUidStatsLocked(parentUid, elapsedRealtimeMs, uptimeMs)
4440                 .updateUidProcessStateLocked(state, elapsedRealtimeMs, uptimeMs);
4441     }
4442 
4443     @GuardedBy("this")
noteProcessFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4444     public void noteProcessFinishLocked(String name, int uid,
4445             long elapsedRealtimeMs, long uptimeMs) {
4446         uid = mapUid(uid);
4447         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
4448             return;
4449         }
4450         if (!mRecordAllHistory) {
4451             return;
4452         }
4453         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH, name, uid);
4454     }
4455 
4456     @GuardedBy("this")
noteSyncStartLocked(String name, int uid)4457     public void noteSyncStartLocked(String name, int uid) {
4458         noteSyncStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4459     }
4460 
4461     @GuardedBy("this")
noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4462     public void noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4463         uid = mapUid(uid);
4464         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4465                 .noteStartSyncLocked(name, elapsedRealtimeMs);
4466         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
4467             return;
4468         }
4469         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid);
4470     }
4471 
4472     @GuardedBy("this")
noteSyncFinishLocked(String name, int uid)4473     public void noteSyncFinishLocked(String name, int uid) {
4474         noteSyncFinishLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4475     }
4476 
4477     @GuardedBy("this")
noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4478     public void noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4479         uid = mapUid(uid);
4480         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4481                 .noteStopSyncLocked(name, elapsedRealtimeMs);
4482         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
4483             return;
4484         }
4485         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH, name, uid);
4486     }
4487 
4488     @GuardedBy("this")
noteJobStartLocked(String name, int uid)4489     public void noteJobStartLocked(String name, int uid) {
4490         noteJobStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
4491     }
4492 
4493     @GuardedBy("this")
noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4494     public void noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4495         uid = mapUid(uid);
4496         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4497                 .noteStartJobLocked(name, elapsedRealtimeMs);
4498         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
4499             return;
4500         }
4501         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid);
4502     }
4503 
4504     @GuardedBy("this")
noteJobFinishLocked(String name, int uid, int stopReason)4505     public void noteJobFinishLocked(String name, int uid, int stopReason) {
4506         noteJobFinishLocked(name, uid, stopReason,
4507                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4508     }
4509 
4510     @GuardedBy("this")
noteJobFinishLocked(String name, int uid, int stopReason, long elapsedRealtimeMs, long uptimeMs)4511     public void noteJobFinishLocked(String name, int uid, int stopReason,
4512             long elapsedRealtimeMs, long uptimeMs) {
4513         uid = mapUid(uid);
4514         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4515                 .noteStopJobLocked(name, elapsedRealtimeMs, stopReason);
4516         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
4517             return;
4518         }
4519         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid);
4520     }
4521 
4522     @GuardedBy("this")
noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast, long elapsedRealtimeMs, long uptimeMs)4523     public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast,
4524             long elapsedRealtimeMs, long uptimeMs) {
4525         uid = mapUid(uid);
4526         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4527                 .noteJobsDeferredLocked(numDeferred, sinceLast);
4528     }
4529 
4530     @GuardedBy("this")
noteAlarmStartLocked(String name, WorkSource workSource, int uid)4531     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
4532         noteAlarmStartLocked(name, workSource, uid,
4533                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4534     }
4535 
4536     @GuardedBy("this")
noteAlarmStartLocked(String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4537     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid,
4538             long elapsedRealtimeMs, long uptimeMs) {
4539         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid,
4540                 elapsedRealtimeMs, uptimeMs);
4541     }
4542 
4543     @GuardedBy("this")
noteAlarmFinishLocked(String name, WorkSource workSource, int uid)4544     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
4545         noteAlarmFinishLocked(name, workSource, uid,
4546                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4547     }
4548 
4549     @GuardedBy("this")
noteAlarmFinishLocked(String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4550     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid,
4551             long elapsedRealtimeMs, long uptimeMs) {
4552         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid,
4553                 elapsedRealtimeMs, uptimeMs);
4554     }
4555 
4556     @GuardedBy("this")
noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4557     private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
4558             int uid, long elapsedRealtimeMs, long uptimeMs) {
4559         if (!mRecordAllHistory) {
4560             return;
4561         }
4562 
4563         if (workSource != null) {
4564             for (int i = 0; i < workSource.size(); ++i) {
4565                 uid = mapUid(workSource.getUid(i));
4566                 if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4567                     mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4568                 }
4569             }
4570 
4571             List<WorkChain> workChains = workSource.getWorkChains();
4572             if (workChains != null) {
4573                 for (int i = 0; i < workChains.size(); ++i) {
4574                     uid = mapUid(workChains.get(i).getAttributionUid());
4575                     if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4576                         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4577                     }
4578                 }
4579             }
4580         } else {
4581             uid = mapUid(uid);
4582 
4583             if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4584                 mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4585             }
4586         }
4587     }
4588 
4589     @GuardedBy("this")
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag)4590     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4591             String tag) {
4592         noteWakupAlarmLocked(packageName, uid, workSource, tag,
4593                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4594     }
4595 
4596     @GuardedBy("this")
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag, long elapsedRealtimeMs, long uptimeMs)4597     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4598             String tag, long elapsedRealtimeMs, long uptimeMs) {
4599         if (workSource != null) {
4600             for (int i = 0; i < workSource.size(); ++i) {
4601                 uid = workSource.getUid(i);
4602                 final String workSourceName = workSource.getPackageName(i);
4603 
4604                 if (isOnBattery()) {
4605                     BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
4606                             workSourceName != null ? workSourceName : packageName,
4607                             elapsedRealtimeMs, uptimeMs);
4608                     pkg.noteWakeupAlarmLocked(tag);
4609                 }
4610             }
4611 
4612             List<WorkChain> workChains = workSource.getWorkChains();
4613             if (workChains != null) {
4614                 for (int i = 0; i < workChains.size(); ++i) {
4615                     final WorkChain wc = workChains.get(i);
4616                     uid = wc.getAttributionUid();
4617 
4618                     if (isOnBattery()) {
4619                         BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName,
4620                                 elapsedRealtimeMs, uptimeMs);
4621                         pkg.noteWakeupAlarmLocked(tag);
4622                     }
4623                 }
4624             }
4625         } else {
4626             if (isOnBattery()) {
4627                 BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName,
4628                         elapsedRealtimeMs, uptimeMs);
4629                 pkg.noteWakeupAlarmLocked(tag);
4630             }
4631         }
4632     }
4633 
requestWakelockCpuUpdate()4634     private void requestWakelockCpuUpdate() {
4635         mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS);
4636     }
4637 
requestImmediateCpuUpdate()4638     private void requestImmediateCpuUpdate() {
4639         mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
4640     }
4641 
4642     @GuardedBy("this")
setRecordAllHistoryLocked(boolean enabled)4643     public void setRecordAllHistoryLocked(boolean enabled) {
4644         mRecordAllHistory = enabled;
4645         if (!enabled) {
4646             // Clear out any existing state.
4647             mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
4648             mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
4649             // Record the currently running processes as stopping, now that we are no
4650             // longer tracking them.
4651             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4652                     HistoryItem.EVENT_PROC);
4653             if (active != null) {
4654                 long mSecRealtime = mClock.elapsedRealtime();
4655                 final long mSecUptime = mClock.uptimeMillis();
4656                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4657                     SparseIntArray uids = ent.getValue();
4658                     for (int j=0; j<uids.size(); j++) {
4659                         mHistory.recordEvent(mSecRealtime, mSecUptime,
4660                                 HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
4661                     }
4662                 }
4663             }
4664         } else {
4665             // Record the currently running processes as starting, now that we are tracking them.
4666             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4667                     HistoryItem.EVENT_PROC);
4668             if (active != null) {
4669                 long mSecRealtime = mClock.elapsedRealtime();
4670                 final long mSecUptime = mClock.uptimeMillis();
4671                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4672                     SparseIntArray uids = ent.getValue();
4673                     for (int j=0; j<uids.size(); j++) {
4674                         mHistory.recordEvent(mSecRealtime, mSecUptime, HistoryItem.EVENT_PROC_START,
4675                                 ent.getKey(), uids.keyAt(j));
4676                     }
4677                 }
4678             }
4679         }
4680     }
4681 
setNoAutoReset(boolean enabled)4682     public void setNoAutoReset(boolean enabled) {
4683         mNoAutoReset = enabled;
4684     }
4685 
4686     @GuardedBy("this")
setPretendScreenOff(boolean pretendScreenOff)4687     public void setPretendScreenOff(boolean pretendScreenOff) {
4688         if (mPretendScreenOff != pretendScreenOff) {
4689             mPretendScreenOff = pretendScreenOff;
4690             final int primaryScreenState = mPerDisplayBatteryStats[0].screenState;
4691             noteScreenStateLocked(0, primaryScreenState,
4692                     mClock.elapsedRealtime(), mClock.uptimeMillis(),
4693                     mClock.currentTimeMillis());
4694         }
4695     }
4696 
4697     @GuardedBy("this")
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging)4698     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4699             int type, boolean unimportantForLogging) {
4700         noteStartWakeLocked(uid, pid, wc, name, historyName, type, unimportantForLogging,
4701                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4702     }
4703 
4704     @GuardedBy("this")
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs)4705     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4706             int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs) {
4707         final int mappedUid = mapUid(uid);
4708         if (type == WAKE_TYPE_PARTIAL) {
4709             // Only care about partial wake locks, since full wake locks
4710             // will be canceled when the user puts the screen to sleep.
4711             aggregateLastWakeupUptimeLocked(elapsedRealtimeMs, uptimeMs);
4712             if (historyName == null) {
4713                 historyName = name;
4714             }
4715             if (mRecordAllHistory) {
4716                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
4717                         mappedUid, 0)) {
4718                     mHistory.recordEvent(elapsedRealtimeMs, uptimeMs,
4719                             HistoryItem.EVENT_WAKE_LOCK_START, historyName, mappedUid);
4720                 }
4721             }
4722             if (mWakeLockNesting == 0) {
4723                 mWakeLockImportant = !unimportantForLogging;
4724                 mHistory.recordWakelockStartEvent(elapsedRealtimeMs, uptimeMs, historyName,
4725                         mappedUid);
4726             } else if (!mWakeLockImportant && !unimportantForLogging) {
4727                 if (mHistory.maybeUpdateWakelockTag(elapsedRealtimeMs, uptimeMs, historyName,
4728                         mappedUid)) {
4729                     mWakeLockImportant = true;
4730                 }
4731             }
4732             mWakeLockNesting++;
4733         }
4734         if (mappedUid >= 0) {
4735             if (mappedUid != uid) {
4736                 // Prevent the isolated uid mapping from being removed while the wakelock is
4737                 // being held.
4738                 incrementIsolatedUidRefCount(uid);
4739             }
4740             if (mOnBatteryScreenOffTimeBase.isRunning()) {
4741                 // We only update the cpu time when a wake lock is acquired if the screen is off.
4742                 // If the screen is on, we don't distribute the power amongst partial wakelocks.
4743                 if (DEBUG_ENERGY_CPU) {
4744                     Slog.d(TAG, "Updating cpu time because of +wake_lock");
4745                 }
4746                 requestWakelockCpuUpdate();
4747             }
4748 
4749             Uid uidStats = getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs);
4750             uidStats.noteStartWakeLocked(pid, name, type, elapsedRealtimeMs);
4751 
4752             int procState = uidStats.mProcessState;
4753 
4754             if (wc != null) {
4755                 FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(),
4756                         wc.getTags(), getPowerManagerWakeLockLevel(type), name,
4757                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE, procState);
4758             } else {
4759                 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED,
4760                         mapIsolatedUid(uid), null, getPowerManagerWakeLockLevel(type), name,
4761                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE, procState);
4762             }
4763         }
4764     }
4765 
4766     @GuardedBy("this")
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type)4767     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4768             int type) {
4769         noteStopWakeLocked(uid, pid, wc, name, historyName, type,
4770                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4771     }
4772 
4773     @GuardedBy("this")
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs)4774     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4775             int type, long elapsedRealtimeMs, long uptimeMs) {
4776         final int mappedUid = mapUid(uid);
4777         if (type == WAKE_TYPE_PARTIAL) {
4778             mWakeLockNesting--;
4779             if (historyName == null) {
4780                 historyName = name;
4781             }
4782             if (mRecordAllHistory) {
4783                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
4784                         mappedUid, 0)) {
4785                     mHistory.recordEvent(elapsedRealtimeMs, uptimeMs,
4786                             HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, mappedUid);
4787                 }
4788             }
4789             if (mWakeLockNesting == 0) {
4790                 mHistory.recordWakelockStopEvent(elapsedRealtimeMs, uptimeMs, historyName,
4791                         mappedUid);
4792             }
4793         }
4794         if (mappedUid >= 0) {
4795             if (mOnBatteryScreenOffTimeBase.isRunning()) {
4796                 if (DEBUG_ENERGY_CPU) {
4797                     Slog.d(TAG, "Updating cpu time because of -wake_lock");
4798                 }
4799                 requestWakelockCpuUpdate();
4800             }
4801 
4802             Uid uidStats = getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs);
4803             uidStats.noteStopWakeLocked(pid, name, type, elapsedRealtimeMs);
4804 
4805             int procState = uidStats.mProcessState;
4806             if (wc != null) {
4807                 FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(),
4808                         wc.getTags(), getPowerManagerWakeLockLevel(type), name,
4809                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE, procState);
4810             } else {
4811                 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED,
4812                         mapIsolatedUid(uid), null, getPowerManagerWakeLockLevel(type), name,
4813                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE, procState);
4814             }
4815 
4816             if (mappedUid != uid) {
4817                 // Decrement the ref count for the isolated uid and delete the mapping if uneeded.
4818                 maybeRemoveIsolatedUidLocked(uid, elapsedRealtimeMs, uptimeMs);
4819             }
4820         }
4821     }
4822 
4823     /**
4824      * Converts BatteryStats wakelock types back into PowerManager wakelock levels.
4825      * This is the inverse map of Notifier.getBatteryStatsWakeLockMonitorType().
4826      * These are estimations, since batterystats loses some of the original data.
4827      * TODO: Delete this. Instead, FrameworkStatsLog.write should be called from
4828      * PowerManager's Notifier.
4829      */
getPowerManagerWakeLockLevel(int battertStatsWakelockType)4830     private int getPowerManagerWakeLockLevel(int battertStatsWakelockType) {
4831         switch (battertStatsWakelockType) {
4832             // PowerManager.PARTIAL_WAKE_LOCK or PROXIMITY_SCREEN_OFF_WAKE_LOCK
4833             case BatteryStats.WAKE_TYPE_PARTIAL:
4834                 return PowerManager.PARTIAL_WAKE_LOCK;
4835 
4836             // PowerManager.SCREEN_DIM_WAKE_LOCK or SCREEN_BRIGHT_WAKE_LOCK
4837             case BatteryStats.WAKE_TYPE_FULL:
4838                 return PowerManager.FULL_WAKE_LOCK;
4839 
4840             case BatteryStats.WAKE_TYPE_DRAW:
4841                 return PowerManager.DRAW_WAKE_LOCK;
4842 
4843             // It appears that nothing can ever make a Window and PowerManager lacks an equivalent.
4844             case BatteryStats.WAKE_TYPE_WINDOW:
4845                 Slog.e(TAG, "Illegal window wakelock type observed in batterystats.");
4846                 return -1;
4847 
4848             default:
4849                 Slog.e(TAG, "Illegal wakelock type in batterystats: " + battertStatsWakelockType);
4850                 return -1;
4851         }
4852     }
4853 
4854     @GuardedBy("this")
noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs)4855     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
4856             String historyName, int type, boolean unimportantForLogging,
4857             long elapsedRealtimeMs, long uptimeMs) {
4858         final int N = ws.size();
4859         for (int i=0; i<N; i++) {
4860             noteStartWakeLocked(ws.getUid(i), pid, null, name, historyName, type,
4861                     unimportantForLogging, elapsedRealtimeMs, uptimeMs);
4862         }
4863 
4864         List<WorkChain> wcs = ws.getWorkChains();
4865         if (wcs != null) {
4866             for (int i = 0; i < wcs.size(); ++i) {
4867                 final WorkChain wc = wcs.get(i);
4868                 noteStartWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4869                         unimportantForLogging, elapsedRealtimeMs, uptimeMs);
4870             }
4871         }
4872     }
4873 
4874     @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)4875     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
4876             String historyName, int type, WorkSource newWs, int newPid, String newName,
4877             String newHistoryName, int newType, boolean newUnimportantForLogging,
4878             long elapsedRealtimeMs, long uptimeMs) {
4879         List<WorkChain>[] wcs = WorkSource.diffChains(ws, newWs);
4880 
4881         // For correct semantics, we start the need worksources first, so that we won't
4882         // make inappropriate history items as if all wake locks went away and new ones
4883         // appeared.  This is okay because tracking of wake locks allows nesting.
4884         //
4885         // First the starts :
4886         final int NN = newWs.size();
4887         for (int i=0; i<NN; i++) {
4888             noteStartWakeLocked(newWs.getUid(i), newPid, null, newName, newHistoryName, newType,
4889                     newUnimportantForLogging, elapsedRealtimeMs, uptimeMs);
4890         }
4891         if (wcs != null) {
4892             List<WorkChain> newChains = wcs[0];
4893             if (newChains != null) {
4894                 for (int i = 0; i < newChains.size(); ++i) {
4895                     final WorkChain newChain = newChains.get(i);
4896                     noteStartWakeLocked(newChain.getAttributionUid(), newPid, newChain, newName,
4897                             newHistoryName, newType, newUnimportantForLogging, elapsedRealtimeMs,
4898                             uptimeMs);
4899                 }
4900             }
4901         }
4902 
4903         // Then the stops :
4904         final int NO = ws.size();
4905         for (int i=0; i<NO; i++) {
4906             noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs,
4907                     uptimeMs);
4908         }
4909         if (wcs != null) {
4910             List<WorkChain> goneChains = wcs[1];
4911             if (goneChains != null) {
4912                 for (int i = 0; i < goneChains.size(); ++i) {
4913                     final WorkChain goneChain = goneChains.get(i);
4914                     noteStopWakeLocked(goneChain.getAttributionUid(), pid, goneChain, name,
4915                             historyName, type, elapsedRealtimeMs, uptimeMs);
4916                 }
4917             }
4918         }
4919     }
4920 
4921     @GuardedBy("this")
noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs)4922     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
4923             String historyName, int type, long elapsedRealtimeMs, long uptimeMs) {
4924         final int N = ws.size();
4925         for (int i=0; i<N; i++) {
4926             noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs,
4927                     uptimeMs);
4928         }
4929 
4930         List<WorkChain> wcs = ws.getWorkChains();
4931         if (wcs != null) {
4932             for (int i = 0; i < wcs.size(); ++i) {
4933                 final WorkChain wc = wcs.get(i);
4934                 noteStopWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4935                         elapsedRealtimeMs, uptimeMs);
4936             }
4937         }
4938     }
4939 
4940     @GuardedBy("this")
noteLongPartialWakelockStart(String name, String historyName, int uid)4941     public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
4942         noteLongPartialWakelockStart(name, historyName, uid,
4943                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4944     }
4945 
4946     @GuardedBy("this")
noteLongPartialWakelockStart(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)4947     public void noteLongPartialWakelockStart(String name, String historyName, int uid,
4948             long elapsedRealtimeMs, long uptimeMs) {
4949         noteLongPartialWakeLockStartInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
4950     }
4951 
4952     @GuardedBy("this")
noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource, long elapsedRealtimeMs, long uptimeMs)4953     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
4954             WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
4955         final int N = workSource.size();
4956         for (int i = 0; i < N; ++i) {
4957             final int uid = mapUid(workSource.getUid(i));
4958             noteLongPartialWakeLockStartInternal(name, historyName, uid,
4959                     elapsedRealtimeMs, uptimeMs);
4960         }
4961 
4962         final List<WorkChain> workChains = workSource.getWorkChains();
4963         if (workChains != null) {
4964             for (int i = 0; i < workChains.size(); ++i) {
4965                 final WorkChain workChain = workChains.get(i);
4966                 final int uid = workChain.getAttributionUid();
4967                 noteLongPartialWakeLockStartInternal(name, historyName, uid,
4968                         elapsedRealtimeMs, uptimeMs);
4969             }
4970         }
4971     }
4972 
4973     @GuardedBy("this")
noteLongPartialWakeLockStartInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)4974     private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid,
4975             long elapsedRealtimeMs, long uptimeMs) {
4976         final int mappedUid = mapUid(uid);
4977         if (historyName == null) {
4978             historyName = name;
4979         }
4980         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName,
4981                 mappedUid, 0)) {
4982             return;
4983         }
4984         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
4985                 historyName, mappedUid);
4986         if (mappedUid != uid) {
4987             // Prevent the isolated uid mapping from being removed while the wakelock is
4988             // being held.
4989             incrementIsolatedUidRefCount(uid);
4990         }
4991     }
4992 
4993     @GuardedBy("this")
noteLongPartialWakelockFinish(String name, String historyName, int uid)4994     public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
4995         noteLongPartialWakelockFinish(name, historyName, uid,
4996                 mClock.elapsedRealtime(), mClock.uptimeMillis());
4997     }
4998 
4999     @GuardedBy("this")
noteLongPartialWakelockFinish(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5000     public void noteLongPartialWakelockFinish(String name, String historyName, int uid,
5001             long elapsedRealtimeMs, long uptimeMs) {
5002         noteLongPartialWakeLockFinishInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
5003     }
5004 
5005     @GuardedBy("this")
noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource, long elapsedRealtimeMs, long uptimeMs)5006     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
5007             WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
5008         final int N = workSource.size();
5009         for (int i = 0; i < N; ++i) {
5010             final int uid = mapUid(workSource.getUid(i));
5011             noteLongPartialWakeLockFinishInternal(name, historyName, uid,
5012                     elapsedRealtimeMs, uptimeMs);
5013         }
5014 
5015         final List<WorkChain> workChains = workSource.getWorkChains();
5016         if (workChains != null) {
5017             for (int i = 0; i < workChains.size(); ++i) {
5018                 final WorkChain workChain = workChains.get(i);
5019                 final int uid = workChain.getAttributionUid();
5020                 noteLongPartialWakeLockFinishInternal(name, historyName, uid,
5021                         elapsedRealtimeMs, uptimeMs);
5022             }
5023         }
5024     }
5025 
5026     @GuardedBy("this")
noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)5027     private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid,
5028             long elapsedRealtimeMs, long uptimeMs) {
5029         final int mappedUid = mapUid(uid);
5030         if (historyName == null) {
5031             historyName = name;
5032         }
5033         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName,
5034                 mappedUid, 0)) {
5035             return;
5036         }
5037         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
5038                 historyName, mappedUid);
5039         if (mappedUid != uid) {
5040             // Decrement the ref count for the isolated uid and delete the mapping if uneeded.
5041             maybeRemoveIsolatedUidLocked(uid, elapsedRealtimeMs, uptimeMs);
5042         }
5043     }
5044 
5045     @GuardedBy("this")
aggregateLastWakeupUptimeLocked(long elapsedRealtimeMs, long uptimeMs)5046     void aggregateLastWakeupUptimeLocked(long elapsedRealtimeMs, long uptimeMs) {
5047         if (mLastWakeupReason != null) {
5048             long deltaUptimeMs = uptimeMs - mLastWakeupUptimeMs;
5049             SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
5050             timer.add(deltaUptimeMs * 1000, 1, elapsedRealtimeMs); // time in in microseconds
5051             FrameworkStatsLog.write(FrameworkStatsLog.KERNEL_WAKEUP_REPORTED, mLastWakeupReason,
5052                     /* duration_usec */ deltaUptimeMs * 1000, mLastWakeupElapsedTimeMs);
5053             mLastWakeupReason = null;
5054         }
5055     }
5056 
5057     @GuardedBy("this")
noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs)5058     public void noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs) {
5059         aggregateLastWakeupUptimeLocked(elapsedRealtimeMs, uptimeMs);
5060         mHistory.recordWakeupEvent(elapsedRealtimeMs, uptimeMs, reason);
5061         mLastWakeupReason = reason;
5062         mLastWakeupUptimeMs = uptimeMs;
5063         mLastWakeupElapsedTimeMs = elapsedRealtimeMs;
5064     }
5065 
5066     @GuardedBy("this")
startAddingCpuStatsLocked()5067     public boolean startAddingCpuStatsLocked() {
5068         mExternalSync.cancelCpuSyncDueToWakelockChange();
5069         return mOnBatteryInternal;
5070     }
5071 
5072     @GuardedBy("this")
addCpuStatsLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs, int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs, int statSoftIrqTimeMs, int statIdleTimeMs)5073     public void addCpuStatsLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs,
5074             int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
5075             int statSoftIrqTimeMs, int statIdleTimeMs) {
5076         mStepDetailsCalculator.addCpuStats(totalUTimeMs, totalSTimeMs, statUserTimeMs,
5077                 statSystemTimeMs, statIOWaitTimeMs, statIrqTimeMs,
5078                 statSoftIrqTimeMs, statIdleTimeMs);
5079     }
5080 
5081     /**
5082      * Called after {@link #addCpuStatsLocked} has been invoked for all active apps.
5083      */
5084     @GuardedBy("this")
finishAddingCpuStatsLocked()5085     public void finishAddingCpuStatsLocked() {
5086         mStepDetailsCalculator.finishAddingCpuLocked();
5087     }
5088 
noteProcessDiedLocked(int uid, int pid)5089     public void noteProcessDiedLocked(int uid, int pid) {
5090         uid = mapUid(uid);
5091         Uid u = mUidStats.get(uid);
5092         if (u != null) {
5093             u.mPids.remove(pid);
5094         }
5095     }
5096 
reportExcessiveCpuLocked(int uid, String proc, long overTimeMs, long usedTimeMs)5097     public void reportExcessiveCpuLocked(int uid, String proc, long overTimeMs, long usedTimeMs) {
5098         uid = mapUid(uid);
5099         Uid u = mUidStats.get(uid);
5100         if (u != null) {
5101             u.reportExcessiveCpuLocked(proc, overTimeMs, usedTimeMs);
5102         }
5103     }
5104 
5105     int mSensorNesting;
5106 
5107     @GuardedBy("this")
noteStartSensorLocked(int uid, int sensor)5108     public void noteStartSensorLocked(int uid, int sensor) {
5109         noteStartSensorLocked(uid, sensor, mClock.elapsedRealtime(), mClock.uptimeMillis());
5110     }
5111 
5112     @GuardedBy("this")
noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs)5113     public void noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
5114         uid = mapUid(uid);
5115         if (mSensorNesting == 0) {
5116             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
5117                     HistoryItem.STATE_SENSOR_ON_FLAG);
5118         }
5119         mSensorNesting++;
5120         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5121                 .noteStartSensor(sensor, elapsedRealtimeMs);
5122     }
5123 
5124     @GuardedBy("this")
noteStopSensorLocked(int uid, int sensor)5125     public void noteStopSensorLocked(int uid, int sensor) {
5126         noteStopSensorLocked(uid, sensor, mClock.elapsedRealtime(), mClock.uptimeMillis());
5127     }
5128 
5129     @GuardedBy("this")
noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs)5130     public void noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
5131         uid = mapUid(uid);
5132         mSensorNesting--;
5133         if (mSensorNesting == 0) {
5134             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
5135                     HistoryItem.STATE_SENSOR_ON_FLAG);
5136         }
5137         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5138                 .noteStopSensor(sensor, elapsedRealtimeMs);
5139     }
5140 
5141     int mGpsNesting;
5142 
5143     @GuardedBy("this")
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs)5144     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
5145         noteGpsChangedLocked(oldWs, newWs, mClock.elapsedRealtime(), mClock.uptimeMillis());
5146     }
5147 
5148     @GuardedBy("this")
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs, long elapsedRealtimeMs, long uptimeMs)5149     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs,
5150             long elapsedRealtimeMs, long uptimeMs) {
5151         for (int i = 0; i < newWs.size(); ++i) {
5152             noteStartGpsLocked(newWs.getUid(i), null, elapsedRealtimeMs, uptimeMs);
5153         }
5154 
5155         for (int i = 0; i < oldWs.size(); ++i) {
5156             noteStopGpsLocked((oldWs.getUid(i)), null, elapsedRealtimeMs, uptimeMs);
5157         }
5158 
5159         List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
5160         if (wcs != null) {
5161             if (wcs[0] != null) {
5162                 final List<WorkChain> newChains = wcs[0];
5163                 for (int i = 0; i < newChains.size(); ++i) {
5164                     noteStartGpsLocked(-1, newChains.get(i), elapsedRealtimeMs, uptimeMs);
5165                 }
5166             }
5167 
5168             if (wcs[1] != null) {
5169                 final List<WorkChain> goneChains = wcs[1];
5170                 for (int i = 0; i < goneChains.size(); ++i) {
5171                     noteStopGpsLocked(-1, goneChains.get(i), elapsedRealtimeMs, uptimeMs);
5172                 }
5173             }
5174         }
5175     }
5176 
5177     @GuardedBy("this")
noteStartGpsLocked(int uid, WorkChain workChain, long elapsedRealtimeMs, long uptimeMs)5178     private void noteStartGpsLocked(int uid, WorkChain workChain,
5179             long elapsedRealtimeMs, long uptimeMs) {
5180         if (workChain != null) {
5181             uid = workChain.getAttributionUid();
5182         }
5183         final int mappedUid = mapUid(uid);
5184         if (mGpsNesting == 0) {
5185             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
5186                     HistoryItem.STATE_GPS_ON_FLAG);
5187         }
5188         mGpsNesting++;
5189 
5190         if (workChain == null) {
5191             FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
5192                     mapIsolatedUid(uid), null, FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
5193         } else {
5194             FrameworkStatsLog.write(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
5195                     workChain.getUids(), workChain.getTags(),
5196                     FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
5197         }
5198 
5199         getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs).noteStartGps(elapsedRealtimeMs);
5200     }
5201 
5202     @GuardedBy("this")
noteStopGpsLocked(int uid, WorkChain workChain, long elapsedRealtimeMs, long uptimeMs)5203     private void noteStopGpsLocked(int uid, WorkChain workChain,
5204             long elapsedRealtimeMs, long uptimeMs) {
5205         if (workChain != null) {
5206             uid = workChain.getAttributionUid();
5207         }
5208         final int mappedUid = mapUid(uid);
5209         mGpsNesting--;
5210         if (mGpsNesting == 0) {
5211             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
5212                     HistoryItem.STATE_GPS_ON_FLAG);
5213             stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
5214             mGpsSignalQualityBin = -1;
5215         }
5216 
5217         if (workChain == null) {
5218             FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
5219                     mapIsolatedUid(uid), null,
5220                     FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
5221         } else {
5222             FrameworkStatsLog.write(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(),
5223                     workChain.getTags(), FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
5224         }
5225 
5226         getUidStatsLocked(mappedUid, elapsedRealtimeMs, uptimeMs).noteStopGps(elapsedRealtimeMs);
5227     }
5228 
5229     @GuardedBy("this")
noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs)5230     public void noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs) {
5231         if (mGpsNesting == 0) {
5232             return;
5233         }
5234         if (signalLevel < 0 || signalLevel >= mGpsSignalQualityTimer.length) {
5235             stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
5236             return;
5237         }
5238         if (mGpsSignalQualityBin != signalLevel) {
5239             if (mGpsSignalQualityBin >= 0) {
5240                 mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtimeMs);
5241             }
5242             if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
5243                 mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtimeMs);
5244             }
5245             mHistory.recordGpsSignalQualityEvent(elapsedRealtimeMs, uptimeMs, signalLevel);
5246             mGpsSignalQualityBin = signalLevel;
5247         }
5248     }
5249 
5250     @GuardedBy("this")
noteScreenStateLocked(int display, int state)5251     public void noteScreenStateLocked(int display, int state) {
5252         noteScreenStateLocked(display, state, mClock.elapsedRealtime(), mClock.uptimeMillis(),
5253                 mClock.currentTimeMillis());
5254     }
5255 
5256     @GuardedBy("this")
noteScreenStateLocked(int display, int displayState, long elapsedRealtimeMs, long uptimeMs, long currentTimeMs)5257     public void noteScreenStateLocked(int display, int displayState,
5258             long elapsedRealtimeMs, long uptimeMs, long currentTimeMs) {
5259         // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
5260         // original 4 are mapped to one of the originals.
5261         if (displayState > MAX_TRACKED_SCREEN_STATE) {
5262             if (Display.isOnState(displayState)) {
5263                 displayState = Display.STATE_ON;
5264             } else if (Display.isDozeState(displayState)) {
5265                 if (Display.isSuspendedState(displayState)) {
5266                     displayState = Display.STATE_DOZE_SUSPEND;
5267                 } else {
5268                     displayState = Display.STATE_DOZE;
5269                 }
5270             } else if (Display.isOffState(displayState)) {
5271                 displayState = Display.STATE_OFF;
5272             } else {
5273                 Slog.wtf(TAG, "Unknown screen state (not mapped): " + displayState);
5274                 displayState = Display.STATE_UNKNOWN;
5275             }
5276         }
5277         // As of this point, displayState should be mapped to one of:
5278         //  - Display.STATE_ON,
5279         //  - Display.STATE_DOZE
5280         //  - Display.STATE_DOZE_SUSPEND
5281         //  - Display.STATE_OFF
5282         //  - Display.STATE_UNKNOWN
5283 
5284         int state;
5285         int overallBin = mScreenBrightnessBin;
5286         int externalUpdateFlag = 0;
5287         boolean shouldScheduleSync = false;
5288         final int numDisplay = mPerDisplayBatteryStats.length;
5289         if (display < 0 || display >= numDisplay) {
5290             Slog.wtf(TAG, "Unexpected note screen state for display " + display + " (only "
5291                     + mPerDisplayBatteryStats.length + " displays exist...)");
5292             return;
5293         }
5294         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
5295         final int oldDisplayState = displayStats.screenState;
5296 
5297         if (oldDisplayState == displayState) {
5298             // Nothing changed
5299             state = mScreenState;
5300         } else {
5301             displayStats.screenState = displayState;
5302 
5303             // Stop timer for previous display state.
5304             switch (oldDisplayState) {
5305                 case Display.STATE_ON:
5306                     displayStats.screenOnTimer.stopRunningLocked(elapsedRealtimeMs);
5307                     final int bin = displayStats.screenBrightnessBin;
5308                     if (bin >= 0) {
5309                         displayStats.screenBrightnessTimers[bin].stopRunningLocked(
5310                                 elapsedRealtimeMs);
5311                     }
5312                     overallBin = evaluateOverallScreenBrightnessBinLocked();
5313                     shouldScheduleSync = true;
5314                     break;
5315                 case Display.STATE_DOZE:
5316                     // Transition from doze to doze suspend can be ignored.
5317                     if (displayState == Display.STATE_DOZE_SUSPEND) break;
5318                     displayStats.screenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5319                     shouldScheduleSync = true;
5320                     break;
5321                 case Display.STATE_DOZE_SUSPEND:
5322                     // Transition from doze suspend to doze can be ignored.
5323                     if (displayState == Display.STATE_DOZE) break;
5324                     displayStats.screenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5325                     shouldScheduleSync = true;
5326                     break;
5327                 case Display.STATE_OFF: // fallthrough
5328                 case Display.STATE_UNKNOWN:
5329                     // Not tracked by timers.
5330                     break;
5331                 default:
5332                     Slog.wtf(TAG,
5333                             "Attempted to stop timer for unexpected display state " + display);
5334             }
5335 
5336             // Start timer for new display state.
5337             switch (displayState) {
5338                 case Display.STATE_ON:
5339                     displayStats.screenOnTimer.startRunningLocked(elapsedRealtimeMs);
5340                     final int bin = displayStats.screenBrightnessBin;
5341                     if (bin >= 0) {
5342                         displayStats.screenBrightnessTimers[bin].startRunningLocked(
5343                                 elapsedRealtimeMs);
5344                     }
5345                     overallBin = evaluateOverallScreenBrightnessBinLocked();
5346                     shouldScheduleSync = true;
5347                     break;
5348                 case Display.STATE_DOZE:
5349                     // Transition from doze suspend to doze can be ignored.
5350                     if (oldDisplayState == Display.STATE_DOZE_SUSPEND) break;
5351                     displayStats.screenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5352                     shouldScheduleSync = true;
5353                     break;
5354                 case Display.STATE_DOZE_SUSPEND:
5355                     // Transition from doze to doze suspend can be ignored.
5356                     if (oldDisplayState == Display.STATE_DOZE) break;
5357                     displayStats.screenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5358                     shouldScheduleSync = true;
5359                     break;
5360                 case Display.STATE_OFF: // fallthrough
5361                 case Display.STATE_UNKNOWN:
5362                     // Not tracked by timers.
5363                     break;
5364                 default:
5365                     Slog.wtf(TAG,
5366                             "Attempted to start timer for unexpected display state " + displayState
5367                                     + " for display " + display);
5368             }
5369 
5370             if (shouldScheduleSync
5371                     && mGlobalEnergyConsumerStats != null
5372                     && mGlobalEnergyConsumerStats.isStandardBucketSupported(
5373                     EnergyConsumerStats.POWER_BUCKET_SCREEN_ON)) {
5374                 // Display energy consumption stats is available. Prepare to schedule an
5375                 // external sync.
5376                 externalUpdateFlag |= ExternalStatsSync.UPDATE_DISPLAY;
5377             }
5378 
5379             // Reevaluate most important display screen state.
5380             state = Display.STATE_UNKNOWN;
5381             for (int i = 0; i < numDisplay; i++) {
5382                 final int tempState = mPerDisplayBatteryStats[i].screenState;
5383                 if (tempState == Display.STATE_ON
5384                         || state == Display.STATE_ON) {
5385                     state = Display.STATE_ON;
5386                 } else if (tempState == Display.STATE_DOZE
5387                         || state == Display.STATE_DOZE) {
5388                     state = Display.STATE_DOZE;
5389                 } else if (tempState == Display.STATE_DOZE_SUSPEND
5390                         || state == Display.STATE_DOZE_SUSPEND) {
5391                     state = Display.STATE_DOZE_SUSPEND;
5392                 } else if (tempState == Display.STATE_OFF
5393                         || state == Display.STATE_OFF) {
5394                     state = Display.STATE_OFF;
5395                 }
5396             }
5397         }
5398 
5399         final boolean batteryRunning = mOnBatteryTimeBase.isRunning();
5400         final boolean batteryScreenOffRunning = mOnBatteryScreenOffTimeBase.isRunning();
5401 
5402         state = mPretendScreenOff ? Display.STATE_OFF : state;
5403         if (mScreenState != state) {
5404             recordDailyStatsIfNeededLocked(true, currentTimeMs);
5405             final int oldState = mScreenState;
5406             mScreenState = state;
5407             if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
5408                     + ", newState=" + Display.stateToString(state));
5409 
5410             if (state != Display.STATE_UNKNOWN) {
5411                 int stepState = state-1;
5412                 if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
5413                     mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
5414                     mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
5415                 } else {
5416                     Slog.wtf(TAG, "Unexpected screen state: " + state);
5417                 }
5418             }
5419 
5420             int startStates = 0;
5421             int stopStates = 0;
5422             if (Display.isDozeState(state) && !Display.isDozeState(oldState)) {
5423                 startStates |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
5424                 mScreenDozeTimer.startRunningLocked(elapsedRealtimeMs);
5425             } else if (Display.isDozeState(oldState) && !Display.isDozeState(state)) {
5426                 stopStates |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
5427                 mScreenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
5428             }
5429             if (Display.isOnState(state)) {
5430                 startStates |= HistoryItem.STATE_SCREEN_ON_FLAG;
5431                 mScreenOnTimer.startRunningLocked(elapsedRealtimeMs);
5432                 if (mScreenBrightnessBin >= 0) {
5433                     mScreenBrightnessTimer[mScreenBrightnessBin]
5434                             .startRunningLocked(elapsedRealtimeMs);
5435                 }
5436             } else if (Display.isOnState(oldState)) {
5437                 stopStates |= HistoryItem.STATE_SCREEN_ON_FLAG;
5438                 mScreenOnTimer.stopRunningLocked(elapsedRealtimeMs);
5439                 if (mScreenBrightnessBin >= 0) {
5440                     mScreenBrightnessTimer[mScreenBrightnessBin]
5441                             .stopRunningLocked(elapsedRealtimeMs);
5442                 }
5443             }
5444             if (startStates != 0 || stopStates != 0) {
5445                 mHistory.recordStateChangeEvent(elapsedRealtimeMs, uptimeMs, startStates,
5446                         stopStates);
5447             }
5448 
5449             // Per screen state Cpu stats needed. Prepare to schedule an external sync.
5450             externalUpdateFlag |= ExternalStatsSync.UPDATE_CPU;
5451             shouldScheduleSync = true;
5452 
5453             if (Display.isOnState(state)) {
5454                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
5455                         uptimeMs * 1000, elapsedRealtimeMs * 1000);
5456                 // Fake a wake lock, so we consider the device waked as long as the screen is on.
5457                 noteStartWakeLocked(-1, -1, null, "screen", null, WAKE_TYPE_PARTIAL, false,
5458                         elapsedRealtimeMs, uptimeMs);
5459             } else if (Display.isOnState(oldState)) {
5460                 noteStopWakeLocked(-1, -1, null, "screen", "screen", WAKE_TYPE_PARTIAL,
5461                         elapsedRealtimeMs, uptimeMs);
5462                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
5463                         uptimeMs * 1000, elapsedRealtimeMs * 1000);
5464             }
5465             // Update discharge amounts.
5466             if (mOnBatteryInternal) {
5467                 updateDischargeScreenLevelsLocked(oldState, state);
5468             }
5469         }
5470 
5471         // Changing display states might have changed the screen used to determine the overall
5472         // brightness.
5473         maybeUpdateOverallScreenBrightness(overallBin, elapsedRealtimeMs, uptimeMs);
5474 
5475         if (shouldScheduleSync) {
5476             final int numDisplays = mPerDisplayBatteryStats.length;
5477             final int[] displayStates = new int[numDisplays];
5478             for (int i = 0; i < numDisplays; i++) {
5479                 displayStates[i] = mPerDisplayBatteryStats[i].screenState;
5480             }
5481             mExternalSync.scheduleSyncDueToScreenStateChange(externalUpdateFlag,
5482                     batteryRunning, batteryScreenOffRunning, state, displayStates);
5483         }
5484     }
5485 
5486     /**
5487      * Note screen brightness change for a display.
5488      */
5489     @GuardedBy("this")
noteScreenBrightnessLocked(int display, int brightness)5490     public void noteScreenBrightnessLocked(int display, int brightness) {
5491         noteScreenBrightnessLocked(display, brightness, mClock.elapsedRealtime(),
5492                 mClock.uptimeMillis());
5493     }
5494 
5495 
5496     /**
5497      * Note screen brightness change for a display.
5498      */
5499     @GuardedBy("this")
noteScreenBrightnessLocked(int display, int brightness, long elapsedRealtimeMs, long uptimeMs)5500     public void noteScreenBrightnessLocked(int display, int brightness, long elapsedRealtimeMs,
5501             long uptimeMs) {
5502         // Bin the brightness.
5503         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
5504         if (bin < 0) bin = 0;
5505         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
5506 
5507         final int overallBin;
5508 
5509         final int numDisplays = mPerDisplayBatteryStats.length;
5510         if (display < 0 || display >= numDisplays) {
5511             Slog.wtf(TAG, "Unexpected note screen brightness for display " + display + " (only "
5512                     + mPerDisplayBatteryStats.length + " displays exist...)");
5513             return;
5514         }
5515 
5516         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
5517         final int oldBin = displayStats.screenBrightnessBin;
5518         if (oldBin == bin) {
5519             // Nothing changed
5520             overallBin = mScreenBrightnessBin;
5521         } else {
5522             displayStats.screenBrightnessBin = bin;
5523             if (displayStats.screenState == Display.STATE_ON) {
5524                 if (oldBin >= 0) {
5525                     displayStats.screenBrightnessTimers[oldBin].stopRunningLocked(
5526                             elapsedRealtimeMs);
5527                 }
5528                 displayStats.screenBrightnessTimers[bin].startRunningLocked(
5529                         elapsedRealtimeMs);
5530             }
5531             overallBin = evaluateOverallScreenBrightnessBinLocked();
5532         }
5533 
5534         maybeUpdateOverallScreenBrightness(overallBin, elapsedRealtimeMs, uptimeMs);
5535     }
5536 
5537     @GuardedBy("this")
evaluateOverallScreenBrightnessBinLocked()5538     private int evaluateOverallScreenBrightnessBinLocked() {
5539         int overallBin = -1;
5540         final int numDisplays = getDisplayCount();
5541         for (int display = 0; display < numDisplays; display++) {
5542             final int displayBrightnessBin;
5543             if (mPerDisplayBatteryStats[display].screenState == Display.STATE_ON) {
5544                 displayBrightnessBin = mPerDisplayBatteryStats[display].screenBrightnessBin;
5545             } else {
5546                 displayBrightnessBin = -1;
5547             }
5548             if (displayBrightnessBin > overallBin) {
5549                 overallBin = displayBrightnessBin;
5550             }
5551         }
5552         return overallBin;
5553     }
5554 
5555     @GuardedBy("this")
maybeUpdateOverallScreenBrightness(int overallBin, long elapsedRealtimeMs, long uptimeMs)5556     private void maybeUpdateOverallScreenBrightness(int overallBin, long elapsedRealtimeMs,
5557             long uptimeMs) {
5558         if (mScreenBrightnessBin != overallBin) {
5559             if (overallBin >= 0) {
5560                 mHistory.recordScreenBrightnessEvent(elapsedRealtimeMs, uptimeMs, overallBin);
5561             }
5562             if (mScreenState == Display.STATE_ON) {
5563                 if (mScreenBrightnessBin >= 0) {
5564                     mScreenBrightnessTimer[mScreenBrightnessBin]
5565                             .stopRunningLocked(elapsedRealtimeMs);
5566                 }
5567                 if (overallBin >= 0) {
5568                     mScreenBrightnessTimer[overallBin]
5569                             .startRunningLocked(elapsedRealtimeMs);
5570                 }
5571             }
5572             mScreenBrightnessBin = overallBin;
5573         }
5574     }
5575 
5576     @GuardedBy("this")
noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event, long elapsedRealtimeMs, long uptimeMs)5577     public void noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event,
5578             long elapsedRealtimeMs, long uptimeMs) {
5579         if (mOnBatteryInternal) {
5580             uid = mapUid(uid);
5581             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteUserActivityLocked(event);
5582         }
5583     }
5584 
5585     @GuardedBy("this")
noteWakeUpLocked(String reason, int reasonUid, long elapsedRealtimeMs, long uptimeMs)5586     public void noteWakeUpLocked(String reason, int reasonUid,
5587             long elapsedRealtimeMs, long uptimeMs) {
5588         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP, reason,
5589                 reasonUid);
5590     }
5591 
5592     @GuardedBy("this")
noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs)5593     public void noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs) {
5594         if (mInteractive != interactive) {
5595             mInteractive = interactive;
5596             if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
5597             if (interactive) {
5598                 mInteractiveTimer.startRunningLocked(elapsedRealtimeMs);
5599             } else {
5600                 mInteractiveTimer.stopRunningLocked(elapsedRealtimeMs);
5601             }
5602         }
5603     }
5604 
5605     @GuardedBy("this")
noteConnectivityChangedLocked(int type, String extra, long elapsedRealtimeMs, long uptimeMs)5606     public void noteConnectivityChangedLocked(int type, String extra,
5607             long elapsedRealtimeMs, long uptimeMs) {
5608         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
5609                 extra, type);
5610         mNumConnectivityChange++;
5611     }
5612 
5613     @GuardedBy("this")
noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)5614     private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
5615             final long uptimeMillis, int uid) {
5616         uid = mapUid(uid);
5617         mHistory.recordEvent(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
5618                 uid);
5619         getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteMobileRadioApWakeupLocked();
5620     }
5621 
5622     /**
5623      * Updates the radio power state and returns true if an external stats collection should occur.
5624      */
5625     @GuardedBy("this")
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid)5626     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
5627         return noteMobileRadioPowerStateLocked(powerState, timestampNs, uid,
5628                 mClock.elapsedRealtime(), mClock.uptimeMillis());
5629     }
5630 
5631     @GuardedBy("this")
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid, long elapsedRealtimeMs, long uptimeMs)5632     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid,
5633             long elapsedRealtimeMs, long uptimeMs) {
5634         if (mMobileRadioPowerState != powerState) {
5635             long realElapsedRealtimeMs;
5636             final boolean active = isActiveRadioPowerState(powerState);
5637             if (active) {
5638                 if (uid > 0) {
5639                     noteMobileRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
5640                 }
5641 
5642                 mMobileRadioActiveStartTimeMs = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
5643                 mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
5644                         HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG);
5645             } else {
5646                 realElapsedRealtimeMs = timestampNs / (1000*1000);
5647                 long lastUpdateTimeMs = mMobileRadioActiveStartTimeMs;
5648                 if (realElapsedRealtimeMs < lastUpdateTimeMs) {
5649                     Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
5650                             + " is before start time " + lastUpdateTimeMs);
5651                     realElapsedRealtimeMs = elapsedRealtimeMs;
5652                 } else if (realElapsedRealtimeMs < elapsedRealtimeMs) {
5653                     mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtimeMs
5654                             - realElapsedRealtimeMs);
5655                 }
5656                 mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
5657                         HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG);
5658             }
5659             mMobileRadioPowerState = powerState;
5660 
5661             // Inform current RatBatteryStats that the modem active state might have changed.
5662             getRatBatteryStatsLocked(mActiveRat).noteActive(active, elapsedRealtimeMs);
5663 
5664             if (active) {
5665                 mMobileRadioActiveTimer.startRunningLocked(elapsedRealtimeMs);
5666                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtimeMs);
5667             } else {
5668                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
5669                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
5670 
5671                 if (mLastModemActivityInfo != null) {
5672                     if (elapsedRealtimeMs < mLastModemActivityInfo.getTimestampMillis()
5673                             + MOBILE_RADIO_POWER_STATE_UPDATE_FREQ_MS) {
5674                         // Modem Activity info has been collected recently, don't bother
5675                         // triggering another update.
5676                         return false;
5677                     }
5678                 }
5679                 // Tell the caller to collect radio network/power stats.
5680                 return true;
5681             }
5682         }
5683         return false;
5684     }
5685 
isActiveRadioPowerState(int powerState)5686     private static boolean isActiveRadioPowerState(int powerState) {
5687         return powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
5688                 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
5689     }
5690 
5691     /**
5692      * Toggles the power save mode state.
5693      */
5694     @GuardedBy("this")
notePowerSaveModeLockedInit(boolean enabled, long elapsedRealtimeMs, long uptimeMs)5695     public void notePowerSaveModeLockedInit(boolean enabled, long elapsedRealtimeMs,
5696             long uptimeMs) {
5697         if (mPowerSaveModeEnabled != enabled) {
5698             notePowerSaveModeLocked(enabled, elapsedRealtimeMs, uptimeMs);
5699         } else {
5700             // Log an initial value for BATTERY_SAVER_MODE_STATE_CHANGED in order to
5701             // allow the atom to read all future state changes.
5702             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
5703                     enabled
5704                         ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
5705                         : FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
5706         }
5707     }
5708 
5709     @GuardedBy("this")
notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs)5710     public void notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs) {
5711         if (mPowerSaveModeEnabled != enabled) {
5712             int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
5713             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
5714             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
5715             mPowerSaveModeEnabled = enabled;
5716             if (enabled) {
5717                 mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
5718                         HistoryItem.STATE2_POWER_SAVE_FLAG);
5719                 mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtimeMs);
5720             } else {
5721                 mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
5722                         HistoryItem.STATE2_POWER_SAVE_FLAG);
5723                 mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtimeMs);
5724             }
5725             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
5726                     enabled
5727                         ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
5728                         : FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
5729         }
5730     }
5731 
5732     @GuardedBy("this")
noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid, long elapsedRealtimeMs, long uptimeMs)5733     public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid,
5734             long elapsedRealtimeMs, long uptimeMs) {
5735         boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
5736         if (mDeviceIdling && !nowIdling && activeReason == null) {
5737             // We don't go out of general idling mode until explicitly taken out of
5738             // device idle through going active or significant motion.
5739             nowIdling = true;
5740         }
5741         boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
5742         if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
5743             // We don't go out of general light idling mode until explicitly taken out of
5744             // device idle through going active or significant motion.
5745             nowLightIdling = true;
5746         }
5747         if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
5748             mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE,
5749                     activeReason, activeUid);
5750         }
5751         if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
5752             int statsmode;
5753             if (nowIdling)           statsmode = DEVICE_IDLE_MODE_DEEP;
5754             else if (nowLightIdling) statsmode = DEVICE_IDLE_MODE_LIGHT;
5755             else                     statsmode = DEVICE_IDLE_MODE_OFF;
5756             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLING_MODE_STATE_CHANGED, statsmode);
5757         }
5758         if (mDeviceIdling != nowIdling) {
5759             mDeviceIdling = nowIdling;
5760             int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
5761             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
5762             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
5763             if (nowIdling) {
5764                 mDeviceIdlingTimer.startRunningLocked(elapsedRealtimeMs);
5765             } else {
5766                 mDeviceIdlingTimer.stopRunningLocked(elapsedRealtimeMs);
5767             }
5768         }
5769         if (mDeviceLightIdling != nowLightIdling) {
5770             mDeviceLightIdling = nowLightIdling;
5771             if (nowLightIdling) {
5772                 mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtimeMs);
5773             } else {
5774                 mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtimeMs);
5775             }
5776         }
5777         if (mDeviceIdleMode != mode) {
5778             mHistory.recordDeviceIdleEvent(elapsedRealtimeMs, uptimeMs, mode);
5779             long lastDuration = elapsedRealtimeMs - mLastIdleTimeStartMs;
5780             mLastIdleTimeStartMs = elapsedRealtimeMs;
5781             if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
5782                 if (lastDuration > mLongestLightIdleTimeMs) {
5783                     mLongestLightIdleTimeMs = lastDuration;
5784                 }
5785                 mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtimeMs);
5786             } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
5787                 if (lastDuration > mLongestFullIdleTimeMs) {
5788                     mLongestFullIdleTimeMs = lastDuration;
5789                 }
5790                 mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtimeMs);
5791             }
5792             if (mode == DEVICE_IDLE_MODE_LIGHT) {
5793                 mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtimeMs);
5794             } else if (mode == DEVICE_IDLE_MODE_DEEP) {
5795                 mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtimeMs);
5796             }
5797             mDeviceIdleMode = mode;
5798             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mode);
5799         }
5800     }
5801 
5802     @GuardedBy("this")
notePackageInstalledLocked(String pkgName, long versionCode, long elapsedRealtimeMs, long uptimeMs)5803     public void notePackageInstalledLocked(String pkgName, long versionCode,
5804             long elapsedRealtimeMs, long uptimeMs) {
5805         // XXX need to figure out what to do with long version codes.
5806         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED,
5807                 pkgName, (int)versionCode);
5808         PackageChange pc = new PackageChange();
5809         pc.mPackageName = pkgName;
5810         pc.mUpdate = true;
5811         pc.mVersionCode = versionCode;
5812         addPackageChange(pc);
5813     }
5814 
5815     @GuardedBy("this")
notePackageUninstalledLocked(String pkgName, long elapsedRealtimeMs, long uptimeMs)5816     public void notePackageUninstalledLocked(String pkgName,
5817             long elapsedRealtimeMs, long uptimeMs) {
5818         mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
5819                 pkgName, 0);
5820         PackageChange pc = new PackageChange();
5821         pc.mPackageName = pkgName;
5822         pc.mUpdate = true;
5823         addPackageChange(pc);
5824     }
5825 
addPackageChange(PackageChange pc)5826     private void addPackageChange(PackageChange pc) {
5827         if (mDailyPackageChanges == null) {
5828             mDailyPackageChanges = new ArrayList<>();
5829         }
5830         mDailyPackageChanges.add(pc);
5831     }
5832 
5833     @GuardedBy("this")
stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs)5834     void stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs) {
5835         for (int i = 0; i < mGpsSignalQualityTimer.length; i++) {
5836             if (i == except) {
5837                 continue;
5838             }
5839             while (mGpsSignalQualityTimer[i].isRunningLocked()) {
5840                 mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtimeMs);
5841             }
5842         }
5843     }
5844 
5845     @GuardedBy("this")
notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs)5846     public void notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs) {
5847         if (!mPhoneOn) {
5848             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
5849                     HistoryItem.STATE2_PHONE_IN_CALL_FLAG);
5850             mPhoneOn = true;
5851             mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs);
5852             if (mConstants.PHONE_ON_EXTERNAL_STATS_COLLECTION) {
5853                 scheduleSyncExternalStatsLocked("phone-on", ExternalStatsSync.UPDATE_RADIO);
5854             }
5855         }
5856     }
5857 
5858     @GuardedBy("this")
notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs)5859     public void notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs) {
5860         if (mPhoneOn) {
5861             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
5862                     HistoryItem.STATE2_PHONE_IN_CALL_FLAG);
5863             mPhoneOn = false;
5864             mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs);
5865             scheduleSyncExternalStatsLocked("phone-off", ExternalStatsSync.UPDATE_RADIO);
5866         }
5867     }
5868 
5869     @GuardedBy("this")
registerUsbStateReceiver(Context context)5870     private void registerUsbStateReceiver(Context context) {
5871         final IntentFilter usbStateFilter = new IntentFilter();
5872         usbStateFilter.addAction(UsbManager.ACTION_USB_STATE);
5873         context.registerReceiver(new BroadcastReceiver() {
5874             @Override
5875             public void onReceive(Context context, Intent intent) {
5876                 final boolean state = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
5877                 synchronized (BatteryStatsImpl.this) {
5878                     noteUsbConnectionStateLocked(state, mClock.elapsedRealtime(),
5879                             mClock.uptimeMillis());
5880                 }
5881             }
5882         }, usbStateFilter);
5883         synchronized (this) {
5884             if (mUsbDataState == USB_DATA_UNKNOWN) {
5885                 final Intent usbState = context.registerReceiver(null, usbStateFilter);
5886                 final boolean initState = usbState != null && usbState.getBooleanExtra(
5887                         UsbManager.USB_CONNECTED, false);
5888                 noteUsbConnectionStateLocked(initState, mClock.elapsedRealtime(),
5889                         mClock.uptimeMillis());
5890             }
5891         }
5892     }
5893 
5894     @GuardedBy("this")
noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs, long uptimeMs)5895     private void noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs,
5896             long uptimeMs) {
5897         int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED;
5898         if (mUsbDataState != newState) {
5899             mUsbDataState = newState;
5900             if (connected) {
5901                 mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
5902                         HistoryItem.STATE2_USB_DATA_LINK_FLAG);
5903             } else {
5904                 mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
5905                         HistoryItem.STATE2_USB_DATA_LINK_FLAG);
5906             }
5907         }
5908     }
5909 
5910     @GuardedBy("this")
stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs)5911     void stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
5912         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
5913             if (i == except) {
5914                 continue;
5915             }
5916             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
5917                 mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs);
5918             }
5919         }
5920     }
5921 
5922     @GuardedBy("this")
updateAllPhoneStateLocked(int state, int simState, int strengthBin, long elapsedRealtimeMs, long uptimeMs)5923     private void updateAllPhoneStateLocked(int state, int simState, int strengthBin,
5924             long elapsedRealtimeMs, long uptimeMs) {
5925         boolean scanning = false;
5926         boolean newHistory = false;
5927         int addStateFlag = 0;
5928         int removeStateFlag = 0;
5929         int newState = -1;
5930         int newSignalStrength = -1;
5931 
5932         mPhoneServiceStateRaw = state;
5933         mPhoneSimStateRaw = simState;
5934         mPhoneSignalStrengthBinRaw = strengthBin;
5935 
5936         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
5937             // In this case we will always be STATE_OUT_OF_SERVICE, so need
5938             // to infer that we are scanning from other data.
5939             if (state == ServiceState.STATE_OUT_OF_SERVICE
5940                     && strengthBin > CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5941                 state = ServiceState.STATE_IN_SERVICE;
5942             }
5943         }
5944 
5945         // If the phone is powered off, stop all timers.
5946         if (state == ServiceState.STATE_POWER_OFF) {
5947             strengthBin = -1;
5948 
5949         // If we are in service, make sure the correct signal string timer is running.
5950         } else if (state == ServiceState.STATE_IN_SERVICE) {
5951             // Bin will be changed below.
5952 
5953         // If we're out of service, we are in the lowest signal strength
5954         // bin and have the scanning bit set.
5955         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
5956             scanning = true;
5957             strengthBin = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
5958             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
5959                 addStateFlag = HistoryItem.STATE_PHONE_SCANNING_FLAG;
5960                 newHistory = true;
5961                 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtimeMs);
5962                 FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
5963                         simState, strengthBin);
5964             }
5965         }
5966 
5967         if (!scanning) {
5968             // If we are no longer scanning, then stop the scanning timer.
5969             if (mPhoneSignalScanningTimer.isRunningLocked()) {
5970                 removeStateFlag = HistoryItem.STATE_PHONE_SCANNING_FLAG;
5971                 newHistory = true;
5972                 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtimeMs);
5973                 FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
5974                         simState, strengthBin);
5975             }
5976         }
5977 
5978         if (mPhoneServiceState != state) {
5979             newState = state;
5980             newHistory = true;
5981             mPhoneServiceState = state;
5982         }
5983 
5984         if (mPhoneSignalStrengthBin != strengthBin) {
5985             if (mPhoneSignalStrengthBin >= 0) {
5986                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
5987                         elapsedRealtimeMs);
5988             }
5989             if (strengthBin >= 0) {
5990                 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
5991                     mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
5992                 }
5993                 newSignalStrength = strengthBin;
5994                 newHistory = true;
5995                 FrameworkStatsLog.write(
5996                         FrameworkStatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
5997             } else {
5998                 stopAllPhoneSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
5999             }
6000             mPhoneSignalStrengthBin = strengthBin;
6001         }
6002 
6003         if (newHistory) {
6004             mHistory.recordPhoneStateChangeEvent(elapsedRealtimeMs, uptimeMs,
6005                     addStateFlag, removeStateFlag, newState, newSignalStrength);
6006         }
6007     }
6008 
6009     @GuardedBy("this")
notePhoneStateLocked(int state, int simState, long elapsedRealtimeMs, long uptimeMs)6010     public void notePhoneStateLocked(int state, int simState,
6011             long elapsedRealtimeMs, long uptimeMs) {
6012         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw,
6013                 elapsedRealtimeMs, uptimeMs);
6014     }
6015 
6016     @GuardedBy("this")
notePhoneSignalStrengthLocked(SignalStrength signalStrength, long elapsedRealtimeMs, long uptimeMs)6017     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength,
6018             long elapsedRealtimeMs, long uptimeMs) {
6019         final int overallSignalStrength = signalStrength.getLevel();
6020         final SparseIntArray perRatSignalStrength = new SparseIntArray(
6021                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT);
6022 
6023         // Extract signal strength level for each RAT.
6024         final List<CellSignalStrength> cellSignalStrengths =
6025                 signalStrength.getCellSignalStrengths();
6026         final int size = cellSignalStrengths.size();
6027         for (int i = 0; i < size; i++) {
6028             CellSignalStrength cellSignalStrength = cellSignalStrengths.get(i);
6029             // Map each CellSignalStrength to a BatteryStats.RadioAccessTechnology
6030             final int ratType;
6031             final int level;
6032             if (cellSignalStrength instanceof CellSignalStrengthNr) {
6033                 ratType = RADIO_ACCESS_TECHNOLOGY_NR;
6034                 level = cellSignalStrength.getLevel();
6035             } else if (cellSignalStrength instanceof CellSignalStrengthLte) {
6036                 ratType = RADIO_ACCESS_TECHNOLOGY_LTE;
6037                 level = cellSignalStrength.getLevel();
6038             } else {
6039                 ratType = RADIO_ACCESS_TECHNOLOGY_OTHER;
6040                 level = cellSignalStrength.getLevel();
6041             }
6042 
6043             // According to SignalStrength#getCellSignalStrengths(), multiple of the same
6044             // cellSignalStrength can be present. Just take the highest level one for each RAT.
6045             if (perRatSignalStrength.get(ratType, -1) < level) {
6046                 perRatSignalStrength.put(ratType, level);
6047             }
6048         }
6049 
6050         notePhoneSignalStrengthLocked(overallSignalStrength, perRatSignalStrength,
6051                 elapsedRealtimeMs, uptimeMs);
6052     }
6053 
6054     /**
6055      * Note phone signal strength change, including per RAT signal strength.
6056      *
6057      * @param signalStrength overall signal strength {@see SignalStrength#getLevel()}
6058      * @param perRatSignalStrength signal strength of available RATs
6059      */
6060     @GuardedBy("this")
notePhoneSignalStrengthLocked(int signalStrength, SparseIntArray perRatSignalStrength)6061     public void notePhoneSignalStrengthLocked(int signalStrength,
6062             SparseIntArray perRatSignalStrength) {
6063         notePhoneSignalStrengthLocked(signalStrength, perRatSignalStrength,
6064                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6065     }
6066 
6067     /**
6068      * Note phone signal strength change, including per RAT signal strength.
6069      *
6070      * @param signalStrength overall signal strength {@see SignalStrength#getLevel()}
6071      * @param perRatSignalStrength signal strength of available RATs
6072      */
6073     @GuardedBy("this")
notePhoneSignalStrengthLocked(int signalStrength, SparseIntArray perRatSignalStrength, long elapsedRealtimeMs, long uptimeMs)6074     public void notePhoneSignalStrengthLocked(int signalStrength,
6075             SparseIntArray perRatSignalStrength,
6076             long elapsedRealtimeMs, long uptimeMs) {
6077         // Note each RAT's signal strength.
6078         final int size = perRatSignalStrength.size();
6079         for (int i = 0; i < size; i++) {
6080             final int rat = perRatSignalStrength.keyAt(i);
6081             final int ratSignalStrength = perRatSignalStrength.valueAt(i);
6082             getRatBatteryStatsLocked(rat).noteSignalStrength(ratSignalStrength, elapsedRealtimeMs);
6083         }
6084         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, signalStrength,
6085                 elapsedRealtimeMs, uptimeMs);
6086     }
6087 
6088     @GuardedBy("this")
notePhoneDataConnectionStateLocked(@etworkType int dataType, boolean hasData, @RegState int serviceType, @ServiceState.FrequencyRange int nrFrequency)6089     public void notePhoneDataConnectionStateLocked(@NetworkType int dataType, boolean hasData,
6090             @RegState int serviceType, @ServiceState.FrequencyRange int nrFrequency) {
6091         notePhoneDataConnectionStateLocked(dataType, hasData, serviceType, nrFrequency,
6092                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6093     }
6094 
6095     @GuardedBy("this")
notePhoneDataConnectionStateLocked(@etworkType int dataType, boolean hasData, @RegState int serviceType, @ServiceState.FrequencyRange int nrFrequency, long elapsedRealtimeMs, long uptimeMs)6096     public void notePhoneDataConnectionStateLocked(@NetworkType int dataType, boolean hasData,
6097             @RegState int serviceType, @ServiceState.FrequencyRange int nrFrequency,
6098             long elapsedRealtimeMs, long uptimeMs) {
6099         // BatteryStats uses 0 to represent no network type.
6100         // Telephony does not have a concept of no network type, and uses 0 to represent unknown.
6101         // Unknown is included in DATA_CONNECTION_OTHER.
6102         int bin = DATA_CONNECTION_OUT_OF_SERVICE;
6103         if (hasData) {
6104             if (dataType > 0 && dataType <= TelephonyManager.getAllNetworkTypes().length) {
6105                 bin = dataType;
6106             } else {
6107                 switch (serviceType) {
6108                     case ServiceState.STATE_OUT_OF_SERVICE:
6109                         bin = DATA_CONNECTION_OUT_OF_SERVICE;
6110                         break;
6111                     case ServiceState.STATE_EMERGENCY_ONLY:
6112                         bin = DATA_CONNECTION_EMERGENCY_SERVICE;
6113                         break;
6114                     default:
6115                         bin = DATA_CONNECTION_OTHER;
6116                         break;
6117                 }
6118             }
6119         }
6120 
6121         final int newRat = mapNetworkTypeToRadioAccessTechnology(bin);
6122         if (newRat == RADIO_ACCESS_TECHNOLOGY_NR) {
6123             // Note possible frequency change for the NR RAT.
6124             getRatBatteryStatsLocked(newRat).noteFrequencyRange(nrFrequency, elapsedRealtimeMs);
6125         }
6126 
6127         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
6128         if (mPhoneDataConnectionType != bin) {
6129             mHistory.recordDataConnectionTypeChangeEvent(elapsedRealtimeMs, uptimeMs, bin);
6130             if (mPhoneDataConnectionType >= 0) {
6131                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
6132                         elapsedRealtimeMs);
6133             }
6134             mPhoneDataConnectionType = bin;
6135             mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtimeMs);
6136 
6137             if (mActiveRat != newRat) {
6138                 getRatBatteryStatsLocked(mActiveRat).noteActive(false, elapsedRealtimeMs);
6139                 mActiveRat = newRat;
6140             }
6141             final boolean modemActive = mMobileRadioActiveTimer.isRunningLocked();
6142             getRatBatteryStatsLocked(newRat).noteActive(modemActive, elapsedRealtimeMs);
6143         }
6144     }
6145 
6146     @RadioAccessTechnology
mapNetworkTypeToRadioAccessTechnology(@etworkType int dataType)6147     private static int mapNetworkTypeToRadioAccessTechnology(@NetworkType int dataType) {
6148         switch (dataType) {
6149             case TelephonyManager.NETWORK_TYPE_NR:
6150                 return RADIO_ACCESS_TECHNOLOGY_NR;
6151             case TelephonyManager.NETWORK_TYPE_LTE:
6152                 return RADIO_ACCESS_TECHNOLOGY_LTE;
6153             case TelephonyManager.NETWORK_TYPE_UNKNOWN: //fallthrough
6154             case TelephonyManager.NETWORK_TYPE_GPRS: //fallthrough
6155             case TelephonyManager.NETWORK_TYPE_EDGE: //fallthrough
6156             case TelephonyManager.NETWORK_TYPE_UMTS: //fallthrough
6157             case TelephonyManager.NETWORK_TYPE_CDMA: //fallthrough
6158             case TelephonyManager.NETWORK_TYPE_EVDO_0: //fallthrough
6159             case TelephonyManager.NETWORK_TYPE_EVDO_A: //fallthrough
6160             case TelephonyManager.NETWORK_TYPE_1xRTT: //fallthrough
6161             case TelephonyManager.NETWORK_TYPE_HSDPA: //fallthrough
6162             case TelephonyManager.NETWORK_TYPE_HSUPA: //fallthrough
6163             case TelephonyManager.NETWORK_TYPE_HSPA: //fallthrough
6164             case TelephonyManager.NETWORK_TYPE_IDEN: //fallthrough
6165             case TelephonyManager.NETWORK_TYPE_EVDO_B: //fallthrough
6166             case TelephonyManager.NETWORK_TYPE_EHRPD: //fallthrough
6167             case TelephonyManager.NETWORK_TYPE_HSPAP: //fallthrough
6168             case TelephonyManager.NETWORK_TYPE_GSM: //fallthrough
6169             case TelephonyManager.NETWORK_TYPE_TD_SCDMA: //fallthrough
6170             case TelephonyManager.NETWORK_TYPE_IWLAN: //fallthrough
6171                 return RADIO_ACCESS_TECHNOLOGY_OTHER;
6172             default:
6173                 Slog.w(TAG, "Unhandled NetworkType (" + dataType + "), mapping to OTHER");
6174                 return RADIO_ACCESS_TECHNOLOGY_OTHER;
6175         }
6176     }
6177 
6178     @RadioAccessTechnology
mapRadioAccessNetworkTypeToRadioAccessTechnology( @ccessNetworkConstants.RadioAccessNetworkType int dataType)6179     private static int mapRadioAccessNetworkTypeToRadioAccessTechnology(
6180             @AccessNetworkConstants.RadioAccessNetworkType int dataType) {
6181         switch (dataType) {
6182             case AccessNetworkConstants.AccessNetworkType.NGRAN:
6183                 return RADIO_ACCESS_TECHNOLOGY_NR;
6184             case AccessNetworkConstants.AccessNetworkType.EUTRAN:
6185                 return RADIO_ACCESS_TECHNOLOGY_LTE;
6186             case AccessNetworkConstants.AccessNetworkType.UNKNOWN: //fallthrough
6187             case AccessNetworkConstants.AccessNetworkType.GERAN: //fallthrough
6188             case AccessNetworkConstants.AccessNetworkType.UTRAN: //fallthrough
6189             case AccessNetworkConstants.AccessNetworkType.CDMA2000: //fallthrough
6190             case AccessNetworkConstants.AccessNetworkType.IWLAN:
6191                 return RADIO_ACCESS_TECHNOLOGY_OTHER;
6192             default:
6193                 Slog.w(TAG,
6194                         "Unhandled RadioAccessNetworkType (" + dataType + "), mapping to OTHER");
6195                 return RADIO_ACCESS_TECHNOLOGY_OTHER;
6196         }
6197     }
6198 
6199     @GuardedBy("this")
noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs)6200     public void noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs) {
6201         if (!mWifiOn) {
6202             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6203                     HistoryItem.STATE2_WIFI_ON_FLAG);
6204             mWifiOn = true;
6205             mWifiOnTimer.startRunningLocked(elapsedRealtimeMs);
6206             scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
6207         }
6208     }
6209 
6210     @GuardedBy("this")
noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs)6211     public void noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs) {
6212         if (mWifiOn) {
6213             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6214                     HistoryItem.STATE2_WIFI_ON_FLAG);
6215             mWifiOn = false;
6216             mWifiOnTimer.stopRunningLocked(elapsedRealtimeMs);
6217             scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
6218         }
6219     }
6220 
6221     @GuardedBy("this")
noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6222     public void noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6223         uid = mapUid(uid);
6224         if (mAudioOnNesting == 0) {
6225             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
6226                     HistoryItem.STATE_AUDIO_ON_FLAG);
6227             mAudioOnTimer.startRunningLocked(elapsedRealtimeMs);
6228         }
6229         mAudioOnNesting++;
6230         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6231                 .noteAudioTurnedOnLocked(elapsedRealtimeMs);
6232     }
6233 
6234     @GuardedBy("this")
noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6235     public void noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6236         if (mAudioOnNesting == 0) {
6237             return;
6238         }
6239         uid = mapUid(uid);
6240         if (--mAudioOnNesting == 0) {
6241             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
6242                     HistoryItem.STATE_AUDIO_ON_FLAG);
6243             mAudioOnTimer.stopRunningLocked(elapsedRealtimeMs);
6244         }
6245         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6246                 .noteAudioTurnedOffLocked(elapsedRealtimeMs);
6247     }
6248 
6249     @GuardedBy("this")
noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6250     public void noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6251         uid = mapUid(uid);
6252         if (mVideoOnNesting == 0) {
6253             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6254                     HistoryItem.STATE2_VIDEO_ON_FLAG);
6255             mVideoOnTimer.startRunningLocked(elapsedRealtimeMs);
6256         }
6257         mVideoOnNesting++;
6258         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6259                 .noteVideoTurnedOnLocked(elapsedRealtimeMs);
6260     }
6261 
6262     @GuardedBy("this")
noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6263     public void noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6264         if (mVideoOnNesting == 0) {
6265             return;
6266         }
6267         uid = mapUid(uid);
6268         if (--mVideoOnNesting == 0) {
6269             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6270                     HistoryItem.STATE2_VIDEO_ON_FLAG);
6271             mVideoOnTimer.stopRunningLocked(elapsedRealtimeMs);
6272         }
6273         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6274                 .noteVideoTurnedOffLocked(elapsedRealtimeMs);
6275     }
6276 
6277     @GuardedBy("this")
noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs)6278     public void noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs) {
6279         if (mAudioOnNesting > 0) {
6280             mAudioOnNesting = 0;
6281             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
6282                     HistoryItem.STATE_AUDIO_ON_FLAG);
6283             mAudioOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6284             for (int i=0; i<mUidStats.size(); i++) {
6285                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6286                 uid.noteResetAudioLocked(elapsedRealtimeMs);
6287             }
6288         }
6289     }
6290 
6291     @GuardedBy("this")
noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs)6292     public void noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs) {
6293         if (mVideoOnNesting > 0) {
6294             mVideoOnNesting = 0;
6295             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6296                     HistoryItem.STATE2_VIDEO_ON_FLAG);
6297             mVideoOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6298             for (int i=0; i<mUidStats.size(); i++) {
6299                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6300                 uid.noteResetVideoLocked(elapsedRealtimeMs);
6301             }
6302         }
6303     }
6304 
6305     @GuardedBy("this")
noteActivityResumedLocked(int uid)6306     public void noteActivityResumedLocked(int uid) {
6307         noteActivityResumedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
6308     }
6309 
6310     @GuardedBy("this")
noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6311     public void noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6312         uid = mapUid(uid);
6313         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6314                 .noteActivityResumedLocked(elapsedRealtimeMs);
6315     }
6316 
6317     @GuardedBy("this")
noteActivityPausedLocked(int uid)6318     public void noteActivityPausedLocked(int uid) {
6319         noteActivityPausedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
6320     }
6321 
6322     @GuardedBy("this")
noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6323     public void noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6324         uid = mapUid(uid);
6325         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6326                 .noteActivityPausedLocked(elapsedRealtimeMs);
6327     }
6328 
6329     @GuardedBy("this")
noteVibratorOnLocked(int uid, long durationMillis, long elapsedRealtimeMs, long uptimeMs)6330     public void noteVibratorOnLocked(int uid, long durationMillis,
6331             long elapsedRealtimeMs, long uptimeMs) {
6332         uid = mapUid(uid);
6333         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6334                 .noteVibratorOnLocked(durationMillis, elapsedRealtimeMs);
6335     }
6336 
6337     @GuardedBy("this")
noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6338     public void noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6339         uid = mapUid(uid);
6340         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6341                 .noteVibratorOffLocked(elapsedRealtimeMs);
6342     }
6343 
6344     @GuardedBy("this")
noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6345     public void noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6346         uid = mapUid(uid);
6347         if (mFlashlightOnNesting++ == 0) {
6348             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6349                     HistoryItem.STATE2_FLASHLIGHT_FLAG);
6350             mFlashlightOnTimer.startRunningLocked(elapsedRealtimeMs);
6351         }
6352         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6353                 .noteFlashlightTurnedOnLocked(elapsedRealtimeMs);
6354     }
6355 
6356     @GuardedBy("this")
noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6357     public void noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6358         if (mFlashlightOnNesting == 0) {
6359             return;
6360         }
6361         uid = mapUid(uid);
6362         if (--mFlashlightOnNesting == 0) {
6363             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6364                     HistoryItem.STATE2_FLASHLIGHT_FLAG);
6365             mFlashlightOnTimer.stopRunningLocked(elapsedRealtimeMs);
6366         }
6367         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6368                 .noteFlashlightTurnedOffLocked(elapsedRealtimeMs);
6369     }
6370 
6371     @GuardedBy("this")
noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6372     public void noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6373         uid = mapUid(uid);
6374         if (mCameraOnNesting++ == 0) {
6375             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6376                     HistoryItem.STATE2_CAMERA_FLAG);
6377             mCameraOnTimer.startRunningLocked(elapsedRealtimeMs);
6378         }
6379         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6380                 .noteCameraTurnedOnLocked(elapsedRealtimeMs);
6381 
6382         scheduleSyncExternalStatsLocked("camera-on", ExternalStatsSync.UPDATE_CAMERA);
6383     }
6384 
6385     @GuardedBy("this")
noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6386     public void noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6387         if (mCameraOnNesting == 0) {
6388             return;
6389         }
6390         uid = mapUid(uid);
6391         if (--mCameraOnNesting == 0) {
6392             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6393                     HistoryItem.STATE2_CAMERA_FLAG);
6394             mCameraOnTimer.stopRunningLocked(elapsedRealtimeMs);
6395         }
6396         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6397                 .noteCameraTurnedOffLocked(elapsedRealtimeMs);
6398 
6399         scheduleSyncExternalStatsLocked("camera-off", ExternalStatsSync.UPDATE_CAMERA);
6400     }
6401 
6402     @GuardedBy("this")
noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs)6403     public void noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs) {
6404         if (mCameraOnNesting > 0) {
6405             mCameraOnNesting = 0;
6406             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6407                     HistoryItem.STATE2_CAMERA_FLAG);
6408             mCameraOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6409             for (int i=0; i<mUidStats.size(); i++) {
6410                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6411                 uid.noteResetCameraLocked(elapsedRealtimeMs);
6412             }
6413         }
6414 
6415         scheduleSyncExternalStatsLocked("camera-reset", ExternalStatsSync.UPDATE_CAMERA);
6416     }
6417 
6418     @GuardedBy("this")
noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs)6419     public void noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs) {
6420         if (mFlashlightOnNesting > 0) {
6421             mFlashlightOnNesting = 0;
6422             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6423                     HistoryItem.STATE2_FLASHLIGHT_FLAG);
6424             mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
6425             for (int i=0; i<mUidStats.size(); i++) {
6426                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6427                 uid.noteResetFlashlightLocked(elapsedRealtimeMs);
6428             }
6429         }
6430     }
6431 
6432     @GuardedBy("this")
noteBluetoothScanStartedLocked(WorkChain workChain, int uid, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6433     private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
6434             boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
6435         if (workChain != null) {
6436             uid = workChain.getAttributionUid();
6437         }
6438         uid = mapUid(uid);
6439         if (mBluetoothScanNesting == 0) {
6440             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6441                     HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
6442             mBluetoothScanTimer.startRunningLocked(elapsedRealtimeMs);
6443         }
6444         mBluetoothScanNesting++;
6445         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6446                 .noteBluetoothScanStartedLocked(elapsedRealtimeMs, isUnoptimized);
6447     }
6448 
6449     @GuardedBy("this")
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized)6450     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
6451         noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized,
6452                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6453     }
6454 
6455     @GuardedBy("this")
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6456     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
6457             long elapsedRealtimeMs, long uptimeMs) {
6458         final int N = ws.size();
6459         for (int i = 0; i < N; i++) {
6460             noteBluetoothScanStartedLocked(null, ws.getUid(i), isUnoptimized,
6461                     elapsedRealtimeMs, uptimeMs);
6462         }
6463 
6464         final List<WorkChain> workChains = ws.getWorkChains();
6465         if (workChains != null) {
6466             for (int i = 0; i < workChains.size(); ++i) {
6467                 noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized,
6468                         elapsedRealtimeMs, uptimeMs);
6469             }
6470         }
6471     }
6472 
6473     @GuardedBy("this")
noteBluetoothScanStoppedLocked(WorkChain workChain, int uid, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6474     private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
6475             boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
6476         if (workChain != null) {
6477             uid = workChain.getAttributionUid();
6478         }
6479         uid = mapUid(uid);
6480         mBluetoothScanNesting--;
6481         if (mBluetoothScanNesting == 0) {
6482             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6483                     HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
6484             mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
6485         }
6486         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6487                 .noteBluetoothScanStoppedLocked(elapsedRealtimeMs, isUnoptimized);
6488     }
6489 
6490     @GuardedBy("this")
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized)6491     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
6492         noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized,
6493                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6494     }
6495 
6496     @GuardedBy("this")
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)6497     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
6498             long elapsedRealtimeMs, long uptimeMs) {
6499         final int N = ws.size();
6500         for (int i = 0; i < N; i++) {
6501             noteBluetoothScanStoppedLocked(null, ws.getUid(i), isUnoptimized,
6502                     elapsedRealtimeMs, uptimeMs);
6503         }
6504 
6505         final List<WorkChain> workChains = ws.getWorkChains();
6506         if (workChains != null) {
6507             for (int i = 0; i < workChains.size(); ++i) {
6508                 noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized,
6509                         elapsedRealtimeMs, uptimeMs);
6510             }
6511         }
6512     }
6513 
6514     @GuardedBy("this")
noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs)6515     public void noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs) {
6516         if (mBluetoothScanNesting > 0) {
6517             mBluetoothScanNesting = 0;
6518             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6519                     HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
6520             mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
6521             for (int i=0; i<mUidStats.size(); i++) {
6522                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
6523                 uid.noteResetBluetoothScanLocked(elapsedRealtimeMs);
6524             }
6525         }
6526     }
6527 
6528     @GuardedBy("this")
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults)6529     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
6530         noteBluetoothScanResultsFromSourceLocked(ws, numNewResults,
6531                 mClock.elapsedRealtime(), mClock.uptimeMillis());
6532     }
6533 
6534     @GuardedBy("this")
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults, long elapsedRealtimeMs, long uptimeMs)6535     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults,
6536             long elapsedRealtimeMs, long uptimeMs) {
6537         final int N = ws.size();
6538         for (int i = 0; i < N; i++) {
6539             int uid = mapUid(ws.getUid(i));
6540             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6541                     .noteBluetoothScanResultsLocked(numNewResults);
6542         }
6543 
6544         final List<WorkChain> workChains = ws.getWorkChains();
6545         if (workChains != null) {
6546             for (int i = 0; i < workChains.size(); ++i) {
6547                 final WorkChain wc = workChains.get(i);
6548                 int uid = mapUid(wc.getAttributionUid());
6549                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6550                         .noteBluetoothScanResultsLocked(numNewResults);
6551             }
6552         }
6553     }
6554 
6555     @GuardedBy("this")
noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)6556     private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
6557             final long uptimeMillis, int uid) {
6558         uid = mapUid(uid);
6559         mHistory.recordEvent(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
6560                 uid);
6561         getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteWifiRadioApWakeupLocked();
6562     }
6563 
6564     @GuardedBy("this")
noteWifiRadioPowerState(int powerState, long timestampNs, int uid, long elapsedRealtimeMs, long uptimeMs)6565     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid,
6566             long elapsedRealtimeMs, long uptimeMs) {
6567         if (mWifiRadioPowerState != powerState) {
6568             final boolean active =
6569                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
6570                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
6571             if (active) {
6572                 if (uid > 0) {
6573                     noteWifiRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
6574                 }
6575                 mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
6576                         HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG);
6577                 mWifiActiveTimer.startRunningLocked(elapsedRealtimeMs);
6578             } else {
6579                 mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
6580                         HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG);
6581                 mWifiActiveTimer.stopRunningLocked(timestampNs / (1000 * 1000));
6582             }
6583             mWifiRadioPowerState = powerState;
6584         }
6585     }
6586 
6587     @GuardedBy("this")
noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6588     public void noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
6589         if (!mGlobalWifiRunning) {
6590             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
6591                     HistoryItem.STATE2_WIFI_RUNNING_FLAG);
6592             mGlobalWifiRunning = true;
6593             mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
6594             int N = ws.size();
6595             for (int i=0; i<N; i++) {
6596                 int uid = mapUid(ws.getUid(i));
6597                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6598                         .noteWifiRunningLocked(elapsedRealtimeMs);
6599             }
6600 
6601             List<WorkChain> workChains = ws.getWorkChains();
6602             if (workChains != null) {
6603                 for (int i = 0; i < workChains.size(); ++i) {
6604                     int uid = mapUid(workChains.get(i).getAttributionUid());
6605                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6606                             .noteWifiRunningLocked(elapsedRealtimeMs);
6607                 }
6608             }
6609 
6610             scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
6611         } else {
6612             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
6613         }
6614     }
6615 
6616     @GuardedBy("this")
noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs, long elapsedRealtimeMs, long uptimeMs)6617     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs,
6618             long elapsedRealtimeMs, long uptimeMs) {
6619         if (mGlobalWifiRunning) {
6620             int N = oldWs.size();
6621             for (int i=0; i<N; i++) {
6622                 int uid = mapUid(oldWs.getUid(i));
6623                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6624                         .noteWifiStoppedLocked(elapsedRealtimeMs);
6625             }
6626 
6627             List<WorkChain> workChains = oldWs.getWorkChains();
6628             if (workChains != null) {
6629                 for (int i = 0; i < workChains.size(); ++i) {
6630                     int uid = mapUid(workChains.get(i).getAttributionUid());
6631                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6632                             .noteWifiStoppedLocked(elapsedRealtimeMs);
6633                 }
6634             }
6635 
6636             N = newWs.size();
6637             for (int i=0; i<N; i++) {
6638                 int uid = mapUid(newWs.getUid(i));
6639                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6640                         .noteWifiRunningLocked(elapsedRealtimeMs);
6641             }
6642 
6643             workChains = newWs.getWorkChains();
6644             if (workChains != null) {
6645                 for (int i = 0; i < workChains.size(); ++i) {
6646                     int uid = mapUid(workChains.get(i).getAttributionUid());
6647                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6648                             .noteWifiRunningLocked(elapsedRealtimeMs);
6649                 }
6650             }
6651         } else {
6652             Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
6653         }
6654     }
6655 
6656     @GuardedBy("this")
noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6657     public void noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
6658         if (mGlobalWifiRunning) {
6659             mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
6660                     HistoryItem.STATE2_WIFI_RUNNING_FLAG);
6661             mGlobalWifiRunning = false;
6662             mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
6663             int N = ws.size();
6664             for (int i=0; i<N; i++) {
6665                 int uid = mapUid(ws.getUid(i));
6666                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6667                         .noteWifiStoppedLocked(elapsedRealtimeMs);
6668             }
6669 
6670             List<WorkChain> workChains = ws.getWorkChains();
6671             if (workChains != null) {
6672                 for (int i = 0; i < workChains.size(); ++i) {
6673                     int uid = mapUid(workChains.get(i).getAttributionUid());
6674                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6675                             .noteWifiStoppedLocked(elapsedRealtimeMs);
6676                 }
6677             }
6678 
6679             scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
6680         } else {
6681             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
6682         }
6683     }
6684 
6685     @GuardedBy("this")
noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs)6686     public void noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs) {
6687         if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
6688         if (mWifiState != wifiState) {
6689             if (mWifiState >= 0) {
6690                 mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtimeMs);
6691             }
6692             mWifiState = wifiState;
6693             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtimeMs);
6694             scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
6695         }
6696     }
6697 
6698     @GuardedBy("this")
noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth, long elapsedRealtimeMs, long uptimeMs)6699     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth,
6700             long elapsedRealtimeMs, long uptimeMs) {
6701         if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
6702         if (mWifiSupplState != supplState) {
6703             if (mWifiSupplState >= 0) {
6704                 mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtimeMs);
6705             }
6706             mWifiSupplState = supplState;
6707             mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtimeMs);
6708             mHistory.recordWifiSupplicantStateChangeEvent(elapsedRealtimeMs, uptimeMs, supplState);
6709         }
6710     }
6711 
6712     @GuardedBy("this")
stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs)6713     void stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
6714         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
6715             if (i == except) {
6716                 continue;
6717             }
6718             while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
6719                 mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs);
6720             }
6721         }
6722     }
6723 
6724     @GuardedBy("this")
noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs)6725     public void noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs) {
6726         int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
6727         if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
6728         if (mWifiSignalStrengthBin != strengthBin) {
6729             if (mWifiSignalStrengthBin >= 0) {
6730                 mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
6731                         elapsedRealtimeMs);
6732             }
6733             if (strengthBin >= 0) {
6734                 if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
6735                     mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
6736                 }
6737                 mHistory.recordWifiSignalStrengthChangeEvent(elapsedRealtimeMs, uptimeMs,
6738                         strengthBin);
6739             } else {
6740                 stopAllWifiSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
6741             }
6742             mWifiSignalStrengthBin = strengthBin;
6743         }
6744     }
6745 
6746     private int mWifiFullLockNesting = 0;
6747 
6748     @GuardedBy("this")
noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6749     public void noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6750         if (mWifiFullLockNesting == 0) {
6751             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
6752                     HistoryItem.STATE_WIFI_FULL_LOCK_FLAG);
6753         }
6754         mWifiFullLockNesting++;
6755         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6756                 .noteFullWifiLockAcquiredLocked(elapsedRealtimeMs);
6757     }
6758 
6759     @GuardedBy("this")
noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6760     public void noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6761         mWifiFullLockNesting--;
6762         if (mWifiFullLockNesting == 0) {
6763             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
6764                     HistoryItem.STATE_WIFI_FULL_LOCK_FLAG);
6765         }
6766         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6767                 .noteFullWifiLockReleasedLocked(elapsedRealtimeMs);
6768     }
6769 
6770     int mWifiScanNesting = 0;
6771 
6772     @GuardedBy("this")
noteWifiScanStartedLocked(int uid)6773     public void noteWifiScanStartedLocked(int uid) {
6774         noteWifiScanStartedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
6775     }
6776 
6777     @GuardedBy("this")
noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6778     public void noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6779         if (mWifiScanNesting == 0) {
6780             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
6781                     HistoryItem.STATE_WIFI_SCAN_FLAG);
6782         }
6783         mWifiScanNesting++;
6784         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6785                 .noteWifiScanStartedLocked(elapsedRealtimeMs);
6786     }
6787 
6788     @GuardedBy("this")
noteWifiScanStoppedLocked(int uid)6789     public void noteWifiScanStoppedLocked(int uid) {
6790         noteWifiScanStoppedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
6791     }
6792 
6793     @GuardedBy("this")
noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6794     public void noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6795         mWifiScanNesting--;
6796         if (mWifiScanNesting == 0) {
6797             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
6798                     HistoryItem.STATE_WIFI_SCAN_FLAG);
6799         }
6800         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6801                 .noteWifiScanStoppedLocked(elapsedRealtimeMs);
6802     }
6803 
noteWifiBatchedScanStartedLocked(int uid, int csph, long elapsedRealtimeMs, long uptimeMs)6804     public void noteWifiBatchedScanStartedLocked(int uid, int csph,
6805             long elapsedRealtimeMs, long uptimeMs) {
6806         uid = mapUid(uid);
6807         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6808                 .noteWifiBatchedScanStartedLocked(csph, elapsedRealtimeMs);
6809     }
6810 
noteWifiBatchedScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6811     public void noteWifiBatchedScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6812         uid = mapUid(uid);
6813         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6814                 .noteWifiBatchedScanStoppedLocked(elapsedRealtimeMs);
6815     }
6816 
6817     private int mWifiMulticastNesting = 0;
6818 
6819     @GuardedBy("this")
noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6820     public void noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6821         uid = mapUid(uid);
6822         if (mWifiMulticastNesting == 0) {
6823             mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
6824                     HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG);
6825             // Start Wifi Multicast overall timer
6826             if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
6827                 mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtimeMs);
6828             }
6829         }
6830         mWifiMulticastNesting++;
6831         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6832                 .noteWifiMulticastEnabledLocked(elapsedRealtimeMs);
6833     }
6834 
6835     @GuardedBy("this")
noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6836     public void noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6837         uid = mapUid(uid);
6838         mWifiMulticastNesting--;
6839         if (mWifiMulticastNesting == 0) {
6840             mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
6841                     HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG);
6842 
6843             // Stop Wifi Multicast overall timer
6844             if (mWifiMulticastWakelockTimer.isRunningLocked()) {
6845                 if (DEBUG) Slog.v(TAG, "Multicast Overall Timer Stopped");
6846                 mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
6847             }
6848         }
6849         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6850                 .noteWifiMulticastDisabledLocked(elapsedRealtimeMs);
6851     }
6852 
6853     @GuardedBy("this")
noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6854     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws,
6855             long elapsedRealtimeMs, long uptimeMs) {
6856         int N = ws.size();
6857         for (int i=0; i<N; i++) {
6858             final int uid = mapUid(ws.getUid(i));
6859             noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs);
6860         }
6861 
6862         final List<WorkChain> workChains = ws.getWorkChains();
6863         if (workChains != null) {
6864             for (int i = 0; i < workChains.size(); ++i) {
6865                 final WorkChain workChain = workChains.get(i);
6866                 final int uid = mapUid(workChain.getAttributionUid());
6867                 noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs);
6868             }
6869         }
6870     }
6871 
6872     @GuardedBy("this")
noteFullWifiLockReleasedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6873     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws,
6874             long elapsedRealtimeMs, long uptimeMs) {
6875         int N = ws.size();
6876         for (int i=0; i<N; i++) {
6877             final int uid = mapUid(ws.getUid(i));
6878             noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs);
6879         }
6880 
6881         final List<WorkChain> workChains = ws.getWorkChains();
6882         if (workChains != null) {
6883             for (int i = 0; i < workChains.size(); ++i) {
6884                 final WorkChain workChain = workChains.get(i);
6885                 final int uid = mapUid(workChain.getAttributionUid());
6886                 noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs);
6887             }
6888         }
6889     }
6890 
6891     @GuardedBy("this")
noteWifiScanStartedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6892     public void noteWifiScanStartedFromSourceLocked(WorkSource ws,
6893             long elapsedRealtimeMs, long uptimeMs) {
6894         int N = ws.size();
6895         for (int i=0; i<N; i++) {
6896             final int uid = mapUid(ws.getUid(i));
6897             noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs);
6898         }
6899 
6900         final List<WorkChain> workChains = ws.getWorkChains();
6901         if (workChains != null) {
6902             for (int i = 0; i < workChains.size(); ++i) {
6903                 final WorkChain workChain = workChains.get(i);
6904                 final int uid = mapUid(workChain.getAttributionUid());
6905                 noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs);
6906             }
6907         }
6908     }
6909 
6910     @GuardedBy("this")
noteWifiScanStoppedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6911     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws,
6912             long elapsedRealtimeMs, long uptimeMs) {
6913         int N = ws.size();
6914         for (int i=0; i<N; i++) {
6915             final int uid = mapUid(ws.getUid(i));
6916             noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs);
6917         }
6918 
6919         final List<WorkChain> workChains = ws.getWorkChains();
6920         if (workChains != null) {
6921             for (int i = 0; i < workChains.size(); ++i) {
6922                 final WorkChain workChain = workChains.get(i);
6923                 final int uid = mapUid(workChain.getAttributionUid());
6924                 noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs);
6925             }
6926         }
6927     }
6928 
6929     @GuardedBy("this")
noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph, long elapsedRealtimeMs, long uptimeMs)6930     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph,
6931             long elapsedRealtimeMs, long uptimeMs) {
6932         int N = ws.size();
6933         for (int i=0; i<N; i++) {
6934             noteWifiBatchedScanStartedLocked(ws.getUid(i), csph, elapsedRealtimeMs, uptimeMs);
6935         }
6936 
6937         final List<WorkChain> workChains = ws.getWorkChains();
6938         if (workChains != null) {
6939             for (int i = 0; i < workChains.size(); ++i) {
6940                 noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph,
6941                         elapsedRealtimeMs, uptimeMs);
6942             }
6943         }
6944     }
6945 
6946     @GuardedBy("this")
noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6947     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws,
6948             long elapsedRealtimeMs, long uptimeMs) {
6949         int N = ws.size();
6950         for (int i=0; i<N; i++) {
6951             noteWifiBatchedScanStoppedLocked(ws.getUid(i), elapsedRealtimeMs, uptimeMs);
6952         }
6953 
6954         final List<WorkChain> workChains = ws.getWorkChains();
6955         if (workChains != null) {
6956             for (int i = 0; i < workChains.size(); ++i) {
6957                 noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid(),
6958                         elapsedRealtimeMs, uptimeMs);
6959             }
6960         }
6961     }
6962 
includeInStringArray(String[] array, String str)6963     private static String[] includeInStringArray(String[] array, String str) {
6964         if (ArrayUtils.indexOf(array, str) >= 0) {
6965             return array;
6966         }
6967         String[] newArray = new String[array.length+1];
6968         System.arraycopy(array, 0, newArray, 0, array.length);
6969         newArray[array.length] = str;
6970         return newArray;
6971     }
6972 
excludeFromStringArray(String[] array, String str)6973     private static String[] excludeFromStringArray(String[] array, String str) {
6974         int index = ArrayUtils.indexOf(array, str);
6975         if (index >= 0) {
6976             String[] newArray = new String[array.length-1];
6977             if (index > 0) {
6978                 System.arraycopy(array, 0, newArray, 0, index);
6979             }
6980             if (index < array.length-1) {
6981                 System.arraycopy(array, index+1, newArray, index, array.length-index-1);
6982             }
6983             return newArray;
6984         }
6985         return array;
6986     }
6987 
6988     /** @hide */
noteNetworkInterfaceForTransports(String iface, int[] transportTypes)6989     public void noteNetworkInterfaceForTransports(String iface, int[] transportTypes) {
6990         if (TextUtils.isEmpty(iface)) return;
6991         final int displayTransport = NetworkCapabilitiesUtils.getDisplayTransport(transportTypes);
6992 
6993         synchronized (mModemNetworkLock) {
6994             if (displayTransport == TRANSPORT_CELLULAR) {
6995                 mModemIfaces = includeInStringArray(mModemIfaces, iface);
6996                 if (DEBUG) {
6997                     Slog.d(TAG, "Note mobile iface " + iface + ": "
6998                             + Arrays.toString(mModemIfaces));
6999                 }
7000             } else {
7001                 mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
7002                 if (DEBUG) {
7003                     Slog.d(TAG, "Note non-mobile iface " + iface + ": "
7004                             + Arrays.toString(mModemIfaces));
7005                 }
7006             }
7007         }
7008 
7009         synchronized (mWifiNetworkLock) {
7010             if (displayTransport == TRANSPORT_WIFI) {
7011                 mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
7012                 if (DEBUG) {
7013                     Slog.d(TAG, "Note wifi iface " + iface + ": " + Arrays.toString(mWifiIfaces));
7014                 }
7015             } else {
7016                 mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
7017                 if (DEBUG) {
7018                     Slog.d(TAG, "Note non-wifi iface " + iface + ": "
7019                             + Arrays.toString(mWifiIfaces));
7020                 }
7021             }
7022         }
7023     }
7024 
7025     /**
7026      * Records timing data related to an incoming Binder call in order to attribute
7027      * the power consumption to the calling app.
7028      */
noteBinderCallStats(int workSourceUid, long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats)7029     public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
7030             Collection<BinderCallsStats.CallStat> callStats) {
7031         noteBinderCallStats(workSourceUid, incrementalCallCount, callStats,
7032                 mClock.elapsedRealtime(), mClock.uptimeMillis());
7033     }
7034 
noteBinderCallStats(int workSourceUid, long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats, long elapsedRealtimeMs, long uptimeMs)7035     public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
7036             Collection<BinderCallsStats.CallStat> callStats,
7037             long elapsedRealtimeMs, long uptimeMs) {
7038         synchronized (this) {
7039             getUidStatsLocked(workSourceUid, elapsedRealtimeMs, uptimeMs)
7040                     .noteBinderCallStatsLocked(incrementalCallCount, callStats);
7041         }
7042     }
7043 
7044     /**
7045      * Takes note of native IDs of threads taking incoming binder calls. The CPU time
7046      * of these threads is attributed to the apps making those binder calls.
7047      */
noteBinderThreadNativeIds(int[] binderThreadNativeTids)7048     public void noteBinderThreadNativeIds(int[] binderThreadNativeTids) {
7049         mSystemServerCpuThreadReader.setBinderThreadNativeTids(binderThreadNativeTids);
7050     }
7051 
7052     /**
7053      * Estimates the proportion of system server CPU activity handling incoming binder calls
7054      * that can be attributed to each app
7055      */
7056     @VisibleForTesting
updateSystemServiceCallStats()7057     public void updateSystemServiceCallStats() {
7058         // Start off by computing the average duration of recorded binder calls,
7059         // regardless of which binder or transaction. We will use this as a fallback
7060         // for calls that were not sampled at all.
7061         int totalRecordedCallCount = 0;
7062         long totalRecordedCallTimeMicros = 0;
7063         for (int i = 0; i < mUidStats.size(); i++) {
7064             Uid uid = mUidStats.valueAt(i);
7065             ArraySet<BinderCallStats> binderCallStats = uid.mBinderCallStats;
7066             for (int j = binderCallStats.size() - 1; j >= 0; j--) {
7067                 BinderCallStats stats = binderCallStats.valueAt(j);
7068                 totalRecordedCallCount += stats.recordedCallCount;
7069                 totalRecordedCallTimeMicros += stats.recordedCpuTimeMicros;
7070             }
7071         }
7072 
7073         long totalSystemServiceTimeMicros = 0;
7074 
7075         // For every UID, use recorded durations of sampled binder calls to estimate
7076         // the total time the system server spent handling requests from this UID.
7077         for (int i = 0; i < mUidStats.size(); i++) {
7078             Uid uid = mUidStats.valueAt(i);
7079 
7080             long totalTimeForUidUs = 0;
7081             int totalCallCountForUid = 0;
7082             ArraySet<BinderCallStats> binderCallStats = uid.mBinderCallStats;
7083             for (int j = binderCallStats.size() - 1; j >= 0; j--) {
7084                 BinderCallStats stats = binderCallStats.valueAt(j);
7085                 totalCallCountForUid += stats.callCount;
7086                 if (stats.recordedCallCount > 0) {
7087                     totalTimeForUidUs +=
7088                             stats.callCount * stats.recordedCpuTimeMicros / stats.recordedCallCount;
7089                 } else if (totalRecordedCallCount > 0) {
7090                     totalTimeForUidUs +=
7091                             stats.callCount * totalRecordedCallTimeMicros / totalRecordedCallCount;
7092                 }
7093             }
7094 
7095             if (totalCallCountForUid < uid.mBinderCallCount && totalRecordedCallCount > 0) {
7096                 // Estimate remaining calls, which were not tracked because of binder call
7097                 // stats sampling
7098                 totalTimeForUidUs +=
7099                         (uid.mBinderCallCount - totalCallCountForUid) * totalRecordedCallTimeMicros
7100                                 / totalRecordedCallCount;
7101             }
7102 
7103             uid.mSystemServiceTimeUs = totalTimeForUidUs;
7104             totalSystemServiceTimeMicros += totalTimeForUidUs;
7105         }
7106 
7107         for (int i = 0; i < mUidStats.size(); i++) {
7108             Uid uid = mUidStats.valueAt(i);
7109             if (totalSystemServiceTimeMicros > 0) {
7110                 uid.mProportionalSystemServiceUsage =
7111                         (double) uid.mSystemServiceTimeUs / totalSystemServiceTimeMicros;
7112             } else {
7113                 uid.mProportionalSystemServiceUsage = 0;
7114             }
7115         }
7116     }
7117 
getWifiIfaces()7118     public String[] getWifiIfaces() {
7119         synchronized (mWifiNetworkLock) {
7120             return mWifiIfaces;
7121         }
7122     }
7123 
getMobileIfaces()7124     public String[] getMobileIfaces() {
7125         synchronized (mModemNetworkLock) {
7126             return mModemIfaces;
7127         }
7128     }
7129 
getScreenOnTime(long elapsedRealtimeUs, int which)7130     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
7131         return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7132     }
7133 
getScreenOnCount(int which)7134     @Override public int getScreenOnCount(int which) {
7135         return mScreenOnTimer.getCountLocked(which);
7136     }
7137 
getScreenDozeTime(long elapsedRealtimeUs, int which)7138     @Override public long getScreenDozeTime(long elapsedRealtimeUs, int which) {
7139         return mScreenDozeTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7140     }
7141 
getScreenDozeCount(int which)7142     @Override public int getScreenDozeCount(int which) {
7143         return mScreenDozeTimer.getCountLocked(which);
7144     }
7145 
getScreenBrightnessTime(int brightnessBin, long elapsedRealtimeUs, int which)7146     @Override public long getScreenBrightnessTime(int brightnessBin,
7147             long elapsedRealtimeUs, int which) {
7148         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
7149                 elapsedRealtimeUs, which);
7150     }
7151 
getScreenBrightnessTimer(int brightnessBin)7152     @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
7153         return mScreenBrightnessTimer[brightnessBin];
7154     }
7155 
7156     @Override
getDisplayCount()7157     public int getDisplayCount() {
7158         return mPerDisplayBatteryStats.length;
7159     }
7160 
7161     @Override
getDisplayScreenOnTime(int display, long elapsedRealtimeUs)7162     public long getDisplayScreenOnTime(int display, long elapsedRealtimeUs) {
7163         return mPerDisplayBatteryStats[display].screenOnTimer.getTotalTimeLocked(elapsedRealtimeUs,
7164                 STATS_SINCE_CHARGED);
7165     }
7166 
7167     @Override
getDisplayScreenDozeTime(int display, long elapsedRealtimeUs)7168     public long getDisplayScreenDozeTime(int display, long elapsedRealtimeUs) {
7169         return mPerDisplayBatteryStats[display].screenDozeTimer.getTotalTimeLocked(
7170                 elapsedRealtimeUs, STATS_SINCE_CHARGED);
7171     }
7172 
7173     @Override
getDisplayScreenBrightnessTime(int display, int brightnessBin, long elapsedRealtimeUs)7174     public long getDisplayScreenBrightnessTime(int display, int brightnessBin,
7175             long elapsedRealtimeUs) {
7176         final DisplayBatteryStats displayStats = mPerDisplayBatteryStats[display];
7177         return displayStats.screenBrightnessTimers[brightnessBin].getTotalTimeLocked(
7178                 elapsedRealtimeUs, STATS_SINCE_CHARGED);
7179     }
7180 
getInteractiveTime(long elapsedRealtimeUs, int which)7181     @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
7182         return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7183     }
7184 
getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which)7185     @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
7186         return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7187     }
7188 
getPowerSaveModeEnabledCount(int which)7189     @Override public int getPowerSaveModeEnabledCount(int which) {
7190         return mPowerSaveModeEnabledTimer.getCountLocked(which);
7191     }
7192 
getDeviceIdleModeTime(int mode, long elapsedRealtimeUs, int which)7193     @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
7194             int which) {
7195         switch (mode) {
7196             case DEVICE_IDLE_MODE_LIGHT:
7197                 return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7198             case DEVICE_IDLE_MODE_DEEP:
7199                 return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7200         }
7201         return 0;
7202     }
7203 
getDeviceIdleModeCount(int mode, int which)7204     @Override public int getDeviceIdleModeCount(int mode, int which) {
7205         switch (mode) {
7206             case DEVICE_IDLE_MODE_LIGHT:
7207                 return mDeviceIdleModeLightTimer.getCountLocked(which);
7208             case DEVICE_IDLE_MODE_DEEP:
7209                 return mDeviceIdleModeFullTimer.getCountLocked(which);
7210         }
7211         return 0;
7212     }
7213 
getLongestDeviceIdleModeTime(int mode)7214     @Override public long getLongestDeviceIdleModeTime(int mode) {
7215         switch (mode) {
7216             case DEVICE_IDLE_MODE_LIGHT:
7217                 return mLongestLightIdleTimeMs;
7218             case DEVICE_IDLE_MODE_DEEP:
7219                 return mLongestFullIdleTimeMs;
7220         }
7221         return 0;
7222     }
7223 
getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which)7224     @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
7225         switch (mode) {
7226             case DEVICE_IDLE_MODE_LIGHT:
7227                 return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7228             case DEVICE_IDLE_MODE_DEEP:
7229                 return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7230         }
7231         return 0;
7232     }
7233 
getDeviceIdlingCount(int mode, int which)7234     @Override public int getDeviceIdlingCount(int mode, int which) {
7235         switch (mode) {
7236             case DEVICE_IDLE_MODE_LIGHT:
7237                 return mDeviceLightIdlingTimer.getCountLocked(which);
7238             case DEVICE_IDLE_MODE_DEEP:
7239                 return mDeviceIdlingTimer.getCountLocked(which);
7240         }
7241         return 0;
7242     }
7243 
getNumConnectivityChange(int which)7244     @Override public int getNumConnectivityChange(int which) {
7245         return mNumConnectivityChange;
7246     }
7247 
getGpsSignalQualityTime(int strengthBin, long elapsedRealtimeUs, int which)7248     @Override public long getGpsSignalQualityTime(int strengthBin,
7249             long elapsedRealtimeUs, int which) {
7250         if (strengthBin < 0 || strengthBin >= mGpsSignalQualityTimer.length) {
7251             return 0;
7252         }
7253         return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
7254                 elapsedRealtimeUs, which);
7255     }
7256 
getGpsBatteryDrainMaMs()7257     @Override public long getGpsBatteryDrainMaMs() {
7258         final double opVolt = mPowerProfile.getAveragePower(
7259             PowerProfile.POWER_GPS_OPERATING_VOLTAGE) / 1000.0;
7260         if (opVolt == 0) {
7261             return 0;
7262         }
7263         double energyUsedMaMs = 0.0;
7264         final int which = STATS_SINCE_CHARGED;
7265         final long rawRealtimeUs = SystemClock.elapsedRealtime() * 1000;
7266         for(int i=0; i < mGpsSignalQualityTimer.length; i++) {
7267             energyUsedMaMs
7268                     += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
7269                     * (getGpsSignalQualityTime(i, rawRealtimeUs, which) / 1000);
7270         }
7271         return (long) energyUsedMaMs;
7272     }
7273 
getPhoneOnTime(long elapsedRealtimeUs, int which)7274     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
7275         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7276     }
7277 
getPhoneOnCount(int which)7278     @Override public int getPhoneOnCount(int which) {
7279         return mPhoneOnTimer.getCountLocked(which);
7280     }
7281 
getPhoneSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)7282     @Override public long getPhoneSignalStrengthTime(int strengthBin,
7283             long elapsedRealtimeUs, int which) {
7284         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
7285                 elapsedRealtimeUs, which);
7286     }
7287 
getPhoneSignalScanningTime( long elapsedRealtimeUs, int which)7288     @Override public long getPhoneSignalScanningTime(
7289             long elapsedRealtimeUs, int which) {
7290         return mPhoneSignalScanningTimer.getTotalTimeLocked(
7291                 elapsedRealtimeUs, which);
7292     }
7293 
getPhoneSignalScanningTimer()7294     @Override public Timer getPhoneSignalScanningTimer() {
7295         return mPhoneSignalScanningTimer;
7296     }
7297 
getPhoneSignalStrengthCount(int strengthBin, int which)7298     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
7299         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
7300     }
7301 
getPhoneSignalStrengthTimer(int strengthBin)7302     @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
7303         return mPhoneSignalStrengthsTimer[strengthBin];
7304     }
7305 
getPhoneDataConnectionTime(int dataType, long elapsedRealtimeUs, int which)7306     @Override public long getPhoneDataConnectionTime(int dataType,
7307             long elapsedRealtimeUs, int which) {
7308         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
7309                 elapsedRealtimeUs, which);
7310     }
7311 
getPhoneDataConnectionCount(int dataType, int which)7312     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
7313         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
7314     }
7315 
getPhoneDataConnectionTimer(int dataType)7316     @Override public Timer getPhoneDataConnectionTimer(int dataType) {
7317         return mPhoneDataConnectionsTimer[dataType];
7318     }
7319 
getActiveRadioDurationMs(@adioAccessTechnology int rat, @ServiceState.FrequencyRange int frequencyRange, int signalStrength, long elapsedRealtimeMs)7320     @Override public long getActiveRadioDurationMs(@RadioAccessTechnology int rat,
7321             @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
7322             long elapsedRealtimeMs) {
7323         final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
7324         if (stats == null) return 0L;
7325 
7326         final int freqCount = stats.perStateTimers.length;
7327         if (frequencyRange < 0 || frequencyRange >= freqCount) return 0L;
7328 
7329         final StopwatchTimer[] strengthTimers = stats.perStateTimers[frequencyRange];
7330         final int strengthCount = strengthTimers.length;
7331         if (signalStrength < 0 || signalStrength >= strengthCount) return 0L;
7332 
7333         return stats.perStateTimers[frequencyRange][signalStrength].getTotalTimeLocked(
7334                 elapsedRealtimeMs * 1000, STATS_SINCE_CHARGED) / 1000;
7335     }
7336 
7337     @Override
getActiveTxRadioDurationMs(@adioAccessTechnology int rat, @ServiceState.FrequencyRange int frequencyRange, int signalStrength, long elapsedRealtimeMs)7338     public long getActiveTxRadioDurationMs(@RadioAccessTechnology int rat,
7339             @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
7340             long elapsedRealtimeMs) {
7341         final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
7342         if (stats == null) return DURATION_UNAVAILABLE;
7343 
7344         final LongSamplingCounter counter = stats.getTxDurationCounter(frequencyRange,
7345                 signalStrength, false);
7346         if (counter == null) return DURATION_UNAVAILABLE;
7347 
7348         return counter.getCountLocked(STATS_SINCE_CHARGED);
7349     }
7350 
7351     @Override
getActiveRxRadioDurationMs(@adioAccessTechnology int rat, @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs)7352     public long getActiveRxRadioDurationMs(@RadioAccessTechnology int rat,
7353             @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs) {
7354         final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
7355         if (stats == null) return DURATION_UNAVAILABLE;
7356 
7357         final LongSamplingCounter counter = stats.getRxDurationCounter(frequencyRange, false);
7358         if (counter == null) return DURATION_UNAVAILABLE;
7359 
7360         return counter.getCountLocked(STATS_SINCE_CHARGED);
7361     }
7362 
getMobileRadioActiveTime(long elapsedRealtimeUs, int which)7363     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
7364         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7365     }
7366 
getMobileRadioActiveCount(int which)7367     @Override public int getMobileRadioActiveCount(int which) {
7368         return mMobileRadioActiveTimer.getCountLocked(which);
7369     }
7370 
getMobileRadioActiveAdjustedTime(int which)7371     @Override public long getMobileRadioActiveAdjustedTime(int which) {
7372         return mMobileRadioActiveAdjustedTime.getCountLocked(which);
7373     }
7374 
getMobileRadioActiveUnknownTime(int which)7375     @Override public long getMobileRadioActiveUnknownTime(int which) {
7376         return mMobileRadioActiveUnknownTime.getCountLocked(which);
7377     }
7378 
getMobileRadioActiveUnknownCount(int which)7379     @Override public int getMobileRadioActiveUnknownCount(int which) {
7380         return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
7381     }
7382 
getWifiMulticastWakelockTime( long elapsedRealtimeUs, int which)7383     @Override public long getWifiMulticastWakelockTime(
7384             long elapsedRealtimeUs, int which) {
7385         return mWifiMulticastWakelockTimer.getTotalTimeLocked(
7386                 elapsedRealtimeUs, which);
7387     }
7388 
getWifiMulticastWakelockCount(int which)7389     @Override public int getWifiMulticastWakelockCount(int which) {
7390         return mWifiMulticastWakelockTimer.getCountLocked(which);
7391     }
7392 
getWifiOnTime(long elapsedRealtimeUs, int which)7393     @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
7394         return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7395     }
7396 
getWifiActiveTime(long elapsedRealtimeUs, int which)7397     @Override public long getWifiActiveTime(long elapsedRealtimeUs, int which) {
7398         return mWifiActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7399     }
7400 
getGlobalWifiRunningTime(long elapsedRealtimeUs, int which)7401     @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
7402         return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7403     }
7404 
getWifiStateTime(int wifiState, long elapsedRealtimeUs, int which)7405     @Override public long getWifiStateTime(int wifiState,
7406             long elapsedRealtimeUs, int which) {
7407         return mWifiStateTimer[wifiState].getTotalTimeLocked(
7408                 elapsedRealtimeUs, which);
7409     }
7410 
getWifiStateCount(int wifiState, int which)7411     @Override public int getWifiStateCount(int wifiState, int which) {
7412         return mWifiStateTimer[wifiState].getCountLocked(which);
7413     }
7414 
getWifiStateTimer(int wifiState)7415     @Override public Timer getWifiStateTimer(int wifiState) {
7416         return mWifiStateTimer[wifiState];
7417     }
7418 
getWifiSupplStateTime(int state, long elapsedRealtimeUs, int which)7419     @Override public long getWifiSupplStateTime(int state,
7420             long elapsedRealtimeUs, int which) {
7421         return mWifiSupplStateTimer[state].getTotalTimeLocked(
7422                 elapsedRealtimeUs, which);
7423     }
7424 
getWifiSupplStateCount(int state, int which)7425     @Override public int getWifiSupplStateCount(int state, int which) {
7426         return mWifiSupplStateTimer[state].getCountLocked(which);
7427     }
7428 
getWifiSupplStateTimer(int state)7429     @Override public Timer getWifiSupplStateTimer(int state) {
7430         return mWifiSupplStateTimer[state];
7431     }
7432 
getWifiSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)7433     @Override public long getWifiSignalStrengthTime(int strengthBin,
7434             long elapsedRealtimeUs, int which) {
7435         return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
7436                 elapsedRealtimeUs, which);
7437     }
7438 
getWifiSignalStrengthCount(int strengthBin, int which)7439     @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
7440         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
7441     }
7442 
getWifiSignalStrengthTimer(int strengthBin)7443     @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
7444         return mWifiSignalStrengthsTimer[strengthBin];
7445     }
7446 
7447     @Override
getBluetoothControllerActivity()7448     public ControllerActivityCounter getBluetoothControllerActivity() {
7449         return mBluetoothActivity;
7450     }
7451 
7452     @Override
getWifiControllerActivity()7453     public ControllerActivityCounter getWifiControllerActivity() {
7454         return mWifiActivity;
7455     }
7456 
7457     @Override
getModemControllerActivity()7458     public ControllerActivityCounter getModemControllerActivity() {
7459         return mModemActivity;
7460     }
7461 
7462     @Override
hasBluetoothActivityReporting()7463     public boolean hasBluetoothActivityReporting() {
7464         return mHasBluetoothReporting;
7465     }
7466 
7467     @Override
hasWifiActivityReporting()7468     public boolean hasWifiActivityReporting() {
7469         return mHasWifiReporting;
7470     }
7471 
7472     @Override
hasModemActivityReporting()7473     public boolean hasModemActivityReporting() {
7474         return mHasModemReporting;
7475     }
7476 
7477     @Override
getFlashlightOnTime(long elapsedRealtimeUs, int which)7478     public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
7479         return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7480     }
7481 
7482     @Override
getFlashlightOnCount(int which)7483     public long getFlashlightOnCount(int which) {
7484         return mFlashlightOnTimer.getCountLocked(which);
7485     }
7486 
7487     @Override
getCameraOnTime(long elapsedRealtimeUs, int which)7488     public long getCameraOnTime(long elapsedRealtimeUs, int which) {
7489         return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7490     }
7491 
7492     @Override
getBluetoothScanTime(long elapsedRealtimeUs, int which)7493     public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
7494         return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7495     }
7496 
7497     @Override
getNetworkActivityBytes(int type, int which)7498     public long getNetworkActivityBytes(int type, int which) {
7499         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
7500             return mNetworkByteActivityCounters[type].getCountLocked(which);
7501         } else {
7502             return 0;
7503         }
7504     }
7505 
7506     @Override
getNetworkActivityPackets(int type, int which)7507     public long getNetworkActivityPackets(int type, int which) {
7508         if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
7509             return mNetworkPacketActivityCounters[type].getCountLocked(which);
7510         } else {
7511             return 0;
7512         }
7513     }
7514 
7515     @GuardedBy("this")
7516     @Override
getBluetoothEnergyConsumptionUC()7517     public long getBluetoothEnergyConsumptionUC() {
7518         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_BLUETOOTH);
7519     }
7520 
7521     @GuardedBy("this")
7522     @Override
getCpuEnergyConsumptionUC()7523     public long getCpuEnergyConsumptionUC() {
7524         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CPU);
7525     }
7526 
7527     @GuardedBy("this")
7528     @Override
getGnssEnergyConsumptionUC()7529     public long getGnssEnergyConsumptionUC() {
7530         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_GNSS);
7531     }
7532 
7533     @GuardedBy("this")
7534     @Override
getMobileRadioEnergyConsumptionUC()7535     public long getMobileRadioEnergyConsumptionUC() {
7536         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO);
7537     }
7538 
7539     @GuardedBy("this")
7540     @Override
getPhoneEnergyConsumptionUC()7541     public long getPhoneEnergyConsumptionUC() {
7542         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_PHONE);
7543     }
7544 
7545     @GuardedBy("this")
7546     @Override
getScreenOnEnergyConsumptionUC()7547     public long getScreenOnEnergyConsumptionUC() {
7548         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_SCREEN_ON);
7549     }
7550 
7551     @GuardedBy("this")
7552     @Override
getScreenDozeEnergyConsumptionUC()7553     public long getScreenDozeEnergyConsumptionUC() {
7554         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_SCREEN_DOZE);
7555     }
7556 
7557     @GuardedBy("this")
7558     @Override
getWifiEnergyConsumptionUC()7559     public long getWifiEnergyConsumptionUC() {
7560         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_WIFI);
7561     }
7562 
7563     @GuardedBy("this")
7564     @Override
getCameraEnergyConsumptionUC()7565     public long getCameraEnergyConsumptionUC() {
7566         return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CAMERA);
7567     }
7568 
7569     /**
7570      * Returns the consumption (in microcoulombs) that the given standard power bucket consumed.
7571      * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable
7572      *
7573      * @param bucket standard power bucket of interest
7574      * @return charge (in microcoulombs) used for this power bucket
7575      */
7576     @GuardedBy("this")
getPowerBucketConsumptionUC(@tandardPowerBucket int bucket)7577     private long getPowerBucketConsumptionUC(@StandardPowerBucket int bucket) {
7578         if (mGlobalEnergyConsumerStats == null) {
7579             return POWER_DATA_UNAVAILABLE;
7580         }
7581         return mGlobalEnergyConsumerStats.getAccumulatedStandardBucketCharge(bucket);
7582     }
7583 
7584     @GuardedBy("this")
7585     @Override
getCustomEnergyConsumerBatteryConsumptionUC()7586     public @Nullable long[] getCustomEnergyConsumerBatteryConsumptionUC() {
7587         if (mGlobalEnergyConsumerStats == null) {
7588             return null;
7589         }
7590         return mGlobalEnergyConsumerStats.getAccumulatedCustomBucketCharges();
7591     }
7592 
7593     /**
7594      * Returns the names of custom power components.
7595      */
7596     @GuardedBy("this")
7597     @Override
getCustomEnergyConsumerNames()7598     public @NonNull String[] getCustomEnergyConsumerNames() {
7599         if (mEnergyConsumerStatsConfig == null) {
7600             return new String[0];
7601         }
7602         final String[] names = mEnergyConsumerStatsConfig.getCustomBucketNames();
7603         for (int i = 0; i < names.length; i++) {
7604             if (TextUtils.isEmpty(names[i])) {
7605                 names[i] = "CUSTOM_" + BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + i;
7606             }
7607         }
7608         return names;
7609     }
7610 
7611     /**
7612      * Adds energy consumer delta to battery history.
7613      */
7614     @GuardedBy("this")
recordEnergyConsumerDetailsLocked(long elapsedRealtimeMs, long uptimeMs, EnergyConsumerDetails energyConsumerDetails)7615     public void recordEnergyConsumerDetailsLocked(long elapsedRealtimeMs,
7616             long uptimeMs, EnergyConsumerDetails energyConsumerDetails) {
7617         if (isUsageHistoryEnabled()) {
7618             mHistory.recordEnergyConsumerDetails(elapsedRealtimeMs, uptimeMs,
7619                     energyConsumerDetails);
7620         }
7621     }
7622 
7623     @GuardedBy("this")
getStartClockTime()7624     @Override public long getStartClockTime() {
7625         final long currentTimeMs = mClock.currentTimeMillis();
7626         if ((currentTimeMs > MILLISECONDS_IN_YEAR
7627                 && mStartClockTimeMs < (currentTimeMs - MILLISECONDS_IN_YEAR))
7628                 || (mStartClockTimeMs > currentTimeMs)) {
7629             // If the start clock time has changed by more than a year, then presumably
7630             // the previous time was completely bogus.  So we are going to figure out a
7631             // new time based on how much time has elapsed since we started counting.
7632             mHistory.recordCurrentTimeChange(mClock.elapsedRealtime(), mClock.uptimeMillis(),
7633                     currentTimeMs
7634             );
7635             return currentTimeMs - (mClock.elapsedRealtime() - (mRealtimeStartUs / 1000));
7636         }
7637         return mStartClockTimeMs;
7638     }
7639 
getStartPlatformVersion()7640     @Override public String getStartPlatformVersion() {
7641         return mStartPlatformVersion;
7642     }
7643 
getEndPlatformVersion()7644     @Override public String getEndPlatformVersion() {
7645         return mEndPlatformVersion;
7646     }
7647 
getParcelVersion()7648     @Override public int getParcelVersion() {
7649         return VERSION;
7650     }
7651 
getIsOnBattery()7652     @Override public boolean getIsOnBattery() {
7653         return mOnBattery;
7654     }
7655 
getStatsStartRealtime()7656     @Override public long getStatsStartRealtime() {
7657         return mRealtimeStartUs;
7658     }
7659 
getUidStats()7660     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
7661         return mUidStats;
7662     }
7663 
resetIfNotNull(T t, boolean detachIfReset, long elapsedRealtimeUs)7664     private static <T extends TimeBaseObs> boolean resetIfNotNull(T t, boolean detachIfReset,
7665             long elapsedRealtimeUs) {
7666         if (t != null) {
7667             return t.reset(detachIfReset, elapsedRealtimeUs);
7668         }
7669         return true;
7670     }
7671 
resetIfNotNull(T[] t, boolean detachIfReset, long elapsedRealtimeUs)7672     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[] t, boolean detachIfReset,
7673             long elapsedRealtimeUs) {
7674         if (t != null) {
7675             boolean ret = true;
7676             for (int i = 0; i < t.length; i++) {
7677                 ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs);
7678             }
7679             return ret;
7680         }
7681         return true;
7682     }
7683 
resetIfNotNull(T[][] t, boolean detachIfReset, long elapsedRealtimeUs)7684     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[][] t, boolean detachIfReset,
7685             long elapsedRealtimeUs) {
7686         if (t != null) {
7687             boolean ret = true;
7688             for (int i = 0; i < t.length; i++) {
7689                 ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs);
7690             }
7691             return ret;
7692         }
7693         return true;
7694     }
7695 
resetIfNotNull(ControllerActivityCounterImpl counter, boolean detachIfReset, long elapsedRealtimeUs)7696     private static boolean resetIfNotNull(ControllerActivityCounterImpl counter,
7697             boolean detachIfReset, long elapsedRealtimeUs) {
7698         if (counter != null) {
7699             counter.reset(detachIfReset, elapsedRealtimeUs);
7700         }
7701         return true;
7702     }
7703 
detachIfNotNull(T t)7704     private static <T extends TimeBaseObs> void detachIfNotNull(T t) {
7705         if (t != null) {
7706             t.detach();
7707         }
7708     }
7709 
detachIfNotNull(T[] t)7710     private static <T extends TimeBaseObs> void detachIfNotNull(T[] t) {
7711         if (t != null) {
7712             for (int i = 0; i < t.length; i++) {
7713                 detachIfNotNull(t[i]);
7714             }
7715         }
7716     }
7717 
detachIfNotNull(T[][] t)7718     private static <T extends TimeBaseObs> void detachIfNotNull(T[][] t) {
7719         if (t != null) {
7720             for (int i = 0; i < t.length; i++) {
7721                 detachIfNotNull(t[i]);
7722             }
7723         }
7724     }
7725 
detachIfNotNull(ControllerActivityCounterImpl counter)7726     private static void detachIfNotNull(ControllerActivityCounterImpl counter) {
7727         if (counter != null) {
7728             counter.detach();
7729         }
7730     }
7731 
7732     /**
7733      * Accumulates stats for a specific binder transaction.
7734      */
7735     @VisibleForTesting
7736     protected static class BinderCallStats {
7737         public Class<? extends Binder> binderClass;
7738         public int transactionCode;
7739         public String methodName;
7740 
7741         public long callCount;
7742         public long recordedCallCount;
7743         public long recordedCpuTimeMicros;
7744 
7745 
7746         @Override
hashCode()7747         public int hashCode() {
7748             return binderClass.hashCode() * 31 + transactionCode;
7749         }
7750 
7751         @Override
equals(Object obj)7752         public boolean equals(Object obj) {
7753             if (!(obj instanceof BinderCallStats)) {
7754                 return false;
7755             }
7756             BinderCallStats bcsk = (BinderCallStats) obj;
7757             return binderClass.equals(bcsk.binderClass) && transactionCode == bcsk.transactionCode;
7758         }
7759 
getClassName()7760         public String getClassName() {
7761             return binderClass.getName();
7762         }
7763 
getMethodName()7764         public String getMethodName() {
7765             return methodName;
7766         }
7767 
7768         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
ensureMethodName(BinderTransactionNameResolver resolver)7769         public void ensureMethodName(BinderTransactionNameResolver resolver) {
7770             if (methodName == null) {
7771                 methodName = resolver.getMethodName(binderClass, transactionCode);
7772             }
7773         }
7774 
7775         @Override
toString()7776         public String toString() {
7777             return "BinderCallStats{"
7778                     + binderClass
7779                     + " transaction=" + transactionCode
7780                     + " callCount=" + callCount
7781                     + " recordedCallCount=" + recordedCallCount
7782                     + " recorderCpuTimeMicros=" + recordedCpuTimeMicros
7783                     + "}";
7784         }
7785     }
7786 
7787     /**
7788      * The statistics associated with a particular uid.
7789      */
7790     public static class Uid extends BatteryStats.Uid {
7791         /**
7792          * BatteryStatsImpl that we are associated with.
7793          */
7794         protected BatteryStatsImpl mBsi;
7795 
7796         final int mUid;
7797 
7798         /** TimeBase for when uid is in background and device is on battery. */
7799         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
7800         public final TimeBase mOnBatteryBackgroundTimeBase;
7801         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
7802         public final TimeBase mOnBatteryScreenOffBackgroundTimeBase;
7803 
7804         boolean mWifiRunning;
7805         StopwatchTimer mWifiRunningTimer;
7806 
7807         boolean mFullWifiLockOut;
7808         StopwatchTimer mFullWifiLockTimer;
7809 
7810         boolean mWifiScanStarted;
7811         DualTimer mWifiScanTimer;
7812 
7813         static final int NO_BATCHED_SCAN_STARTED = -1;
7814         int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
7815         StopwatchTimer[] mWifiBatchedScanTimer;
7816 
7817         int mWifiMulticastWakelockCount;
7818         StopwatchTimer mWifiMulticastTimer;
7819 
7820         StopwatchTimer mAudioTurnedOnTimer;
7821         StopwatchTimer mVideoTurnedOnTimer;
7822         StopwatchTimer mFlashlightTurnedOnTimer;
7823         StopwatchTimer mCameraTurnedOnTimer;
7824         StopwatchTimer mForegroundActivityTimer;
7825         StopwatchTimer mForegroundServiceTimer;
7826         /** Total time spent by the uid holding any partial wakelocks. */
7827         DualTimer mAggregatedPartialWakelockTimer;
7828         DualTimer mBluetoothScanTimer;
7829         DualTimer mBluetoothUnoptimizedScanTimer;
7830         Counter mBluetoothScanResultCounter;
7831         Counter mBluetoothScanResultBgCounter;
7832 
7833         int mProcessState = Uid.PROCESS_STATE_NONEXISTENT;
7834         StopwatchTimer[] mProcessStateTimer;
7835 
7836         boolean mInForegroundService = false;
7837 
7838         BatchTimer mVibratorOnTimer;
7839 
7840         Counter[] mUserActivityCounters;
7841 
7842         LongSamplingCounter[] mNetworkByteActivityCounters;
7843         LongSamplingCounter[] mNetworkPacketActivityCounters;
7844         TimeMultiStateCounter mMobileRadioActiveTime;
7845         LongSamplingCounter mMobileRadioActiveCount;
7846 
7847         /**
7848          * How many times this UID woke up the Application Processor due to a Mobile radio packet.
7849          */
7850         private LongSamplingCounter mMobileRadioApWakeupCount;
7851 
7852         /**
7853          * How many times this UID woke up the Application Processor due to a Wifi packet.
7854          */
7855         private LongSamplingCounter mWifiRadioApWakeupCount;
7856 
7857         /**
7858          * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
7859          * Can be null if the UID has had no such activity.
7860          */
7861         private ControllerActivityCounterImpl mWifiControllerActivity;
7862 
7863         /**
7864          * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
7865          * Can be null if the UID has had no such activity.
7866          */
7867         private ControllerActivityCounterImpl mBluetoothControllerActivity;
7868 
7869         /**
7870          * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
7871          * Can be null if the UID has had no such activity.
7872          */
7873         private ControllerActivityCounterImpl mModemControllerActivity;
7874 
7875         /**
7876          * The CPU times we had at the last history details update.
7877          */
7878         long mLastStepUserTimeMs;
7879         long mLastStepSystemTimeMs;
7880         long mCurStepUserTimeMs;
7881         long mCurStepSystemTimeMs;
7882 
7883         LongSamplingCounter mUserCpuTime;
7884         LongSamplingCounter mSystemCpuTime;
7885         LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
7886         TimeMultiStateCounter mCpuActiveTimeMs;
7887 
7888         LongSamplingCounterArray mCpuFreqTimeMs;
7889         LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
7890         LongSamplingCounterArray mCpuClusterTimesMs;
7891 
7892         TimeInFreqMultiStateCounter mProcStateTimeMs;
7893         TimeInFreqMultiStateCounter mProcStateScreenOffTimeMs;
7894 
7895         SparseArray<ChildUid> mChildUids;
7896 
7897         /**
7898          * The statistics we have collected for this uid's wake locks.
7899          */
7900         final OverflowArrayMap<Wakelock> mWakelockStats;
7901 
7902         /**
7903          * The statistics we have collected for this uid's syncs.
7904          */
7905         final OverflowArrayMap<DualTimer> mSyncStats;
7906 
7907         /**
7908          * The statistics we have collected for this uid's jobs.
7909          */
7910         final OverflowArrayMap<DualTimer> mJobStats;
7911 
7912         /**
7913          * Count of the jobs that have completed and the reasons why they completed.
7914          */
7915         final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
7916 
7917         /**
7918          * Count of app launch events that had associated deferred job counts or info about
7919          * last time a job was run.
7920          */
7921         Counter mJobsDeferredEventCount;
7922 
7923         /**
7924          * Count of deferred jobs that were pending when the app was launched or brought to
7925          * the foreground through a user interaction.
7926          */
7927         Counter mJobsDeferredCount;
7928 
7929         /**
7930          * Sum of time since the last time a job was run for this app before it was launched.
7931          */
7932         LongSamplingCounter mJobsFreshnessTimeMs;
7933 
7934         /**
7935          * Array of counts of instances where the time since the last job was run for the app
7936          * fell within one of the thresholds in {@link #JOB_FRESHNESS_BUCKETS}.
7937          */
7938         final Counter[] mJobsFreshnessBuckets;
7939 
7940         /**
7941          * The statistics we have collected for this uid's sensor activations.
7942          */
7943         final SparseArray<Sensor> mSensorStats = new SparseArray<>();
7944 
7945         /**
7946          * The statistics we have collected for this uid's processes.
7947          */
7948         final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
7949 
7950         /**
7951          * The statistics we have collected for this uid's processes.
7952          */
7953         final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
7954 
7955         /**
7956          * The transient wake stats we have collected for this uid's pids.
7957          */
7958         final SparseArray<Pid> mPids = new SparseArray<>();
7959 
7960         /**
7961          * Grand total of system server binder calls made by this uid.
7962          */
7963         private long mBinderCallCount;
7964 
7965         /**
7966          * Detailed information about system server binder calls made by this uid.
7967          */
7968         private final ArraySet<BinderCallStats> mBinderCallStats = new ArraySet<>();
7969 
7970         /**
7971          * EnergyConsumer consumption by this uid while on battery.
7972          * Its '<b>custom</b> power buckets' correspond to the
7973          * {@link android.hardware.power.stats.EnergyConsumer.ordinal}s of (custom) energy consumer
7974          * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
7975          *
7976          * Will be null if energy consumer data is completely unavailable (in which case
7977          * {@link #mGlobalEnergyConsumerStats} will also be null) or if the power usage by this uid
7978          * is 0 for every bucket.
7979          */
7980         private EnergyConsumerStats mUidEnergyConsumerStats;
7981 
7982         /**
7983          * Estimated total time spent by the system server handling requests from this uid.
7984          */
7985         private long mSystemServiceTimeUs;
7986 
7987         /**
7988          * Estimated proportion of system server binder call CPU cost for this uid.
7989          */
7990         private double mProportionalSystemServiceUsage;
7991 
Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs)7992         public Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs) {
7993             mBsi = bsi;
7994             mUid = uid;
7995 
7996             /* Observer list of TimeBase object in Uid is short */
7997             mOnBatteryBackgroundTimeBase = new TimeBase(false);
7998             mOnBatteryBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
7999             /* Observer list of TimeBase object in Uid is short */
8000             mOnBatteryScreenOffBackgroundTimeBase = new TimeBase(false);
8001             mOnBatteryScreenOffBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
8002 
8003             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8004             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8005             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase);
8006 
8007             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
8008                 @Override public Wakelock instantiateObject() {
8009                     return new Wakelock(mBsi, Uid.this);
8010                 }
8011             };
8012             mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
8013                 @Override public DualTimer instantiateObject() {
8014                     return new DualTimer(mBsi.mClock, Uid.this, SYNC, null,
8015                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8016                 }
8017             };
8018             mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
8019                 @Override public DualTimer instantiateObject() {
8020                     return new DualTimer(mBsi.mClock, Uid.this, JOB, null,
8021                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8022                 }
8023             };
8024 
8025             mWifiRunningTimer = new StopwatchTimer(mBsi.mClock, this, WIFI_RUNNING,
8026                     mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
8027             mFullWifiLockTimer = new StopwatchTimer(mBsi.mClock, this, FULL_WIFI_LOCK,
8028                     mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
8029             mWifiScanTimer = new DualTimer(mBsi.mClock, this, WIFI_SCAN,
8030                     mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8031             mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
8032             mWifiMulticastTimer = new StopwatchTimer(mBsi.mClock, this, WIFI_MULTICAST_ENABLED,
8033                     mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
8034             mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
8035             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase);
8036             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase);
8037             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8038             mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length];
8039         }
8040 
8041         @GuardedBy("mBsi")
8042         @VisibleForTesting
setProcessStateForTest(int procState, long elapsedTimeMs)8043         public void setProcessStateForTest(int procState, long elapsedTimeMs) {
8044             mProcessState = procState;
8045             getProcStateTimeCounter(elapsedTimeMs).setState(procState, elapsedTimeMs);
8046             getProcStateScreenOffTimeCounter(elapsedTimeMs).setState(procState, elapsedTimeMs);
8047             final int batteryConsumerProcessState =
8048                     mapUidProcessStateToBatteryConsumerProcessState(procState);
8049             getCpuActiveTimeCounter().setState(batteryConsumerProcessState, elapsedTimeMs);
8050             getMobileRadioActiveTimeCounter().setState(batteryConsumerProcessState, elapsedTimeMs);
8051             final ControllerActivityCounterImpl wifiControllerActivity =
8052                     getWifiControllerActivity();
8053             if (wifiControllerActivity != null) {
8054                 wifiControllerActivity.setState(batteryConsumerProcessState, elapsedTimeMs);
8055             }
8056             final ControllerActivityCounterImpl bluetoothControllerActivity =
8057                     getBluetoothControllerActivity();
8058             if (bluetoothControllerActivity != null) {
8059                 bluetoothControllerActivity.setState(batteryConsumerProcessState, elapsedTimeMs);
8060             }
8061             final EnergyConsumerStats energyStats =
8062                     getOrCreateEnergyConsumerStatsIfSupportedLocked();
8063             if (energyStats != null) {
8064                 energyStats.setState(batteryConsumerProcessState, elapsedTimeMs);
8065             }
8066         }
8067 
8068         @Override
getCpuFreqTimes(int which)8069         public long[] getCpuFreqTimes(int which) {
8070             return nullIfAllZeros(mCpuFreqTimeMs, which);
8071         }
8072 
8073         @Override
getScreenOffCpuFreqTimes(int which)8074         public long[] getScreenOffCpuFreqTimes(int which) {
8075             return nullIfAllZeros(mScreenOffCpuFreqTimeMs, which);
8076         }
8077 
getCpuActiveTimeCounter()8078         private TimeMultiStateCounter getCpuActiveTimeCounter() {
8079             if (mCpuActiveTimeMs == null) {
8080                 final long timestampMs = mBsi.mClock.elapsedRealtime();
8081                 mCpuActiveTimeMs = new TimeMultiStateCounter(mBsi.mOnBatteryTimeBase,
8082                         BatteryConsumer.PROCESS_STATE_COUNT, timestampMs);
8083                 mCpuActiveTimeMs.setState(
8084                         mapUidProcessStateToBatteryConsumerProcessState(mProcessState),
8085                         timestampMs);
8086             }
8087             return mCpuActiveTimeMs;
8088         }
8089 
8090         @Override
getCpuActiveTime()8091         public long getCpuActiveTime() {
8092             if (mCpuActiveTimeMs == null) {
8093                 return 0;
8094             }
8095 
8096             long activeTime = 0;
8097             for (int procState = 0; procState < BatteryConsumer.PROCESS_STATE_COUNT; procState++) {
8098                 activeTime += mCpuActiveTimeMs.getCountForProcessState(procState);
8099             }
8100             return activeTime;
8101         }
8102 
8103         @Override
getCpuActiveTime(int procState)8104         public long getCpuActiveTime(int procState) {
8105             if (mCpuActiveTimeMs == null
8106                     || procState < 0 || procState >= BatteryConsumer.PROCESS_STATE_COUNT) {
8107                 return 0;
8108             }
8109 
8110             return mCpuActiveTimeMs.getCountForProcessState(procState);
8111         }
8112 
8113         @Override
getCpuClusterTimes()8114         public long[] getCpuClusterTimes() {
8115             return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
8116         }
8117 
8118         @GuardedBy("mBsi")
8119         @Override
getCpuFreqTimes(long[] timesInFreqMs, int procState)8120         public boolean getCpuFreqTimes(long[] timesInFreqMs, int procState) {
8121             if (procState < 0 || procState >= NUM_PROCESS_STATE) {
8122                 return false;
8123             }
8124             if (mProcStateTimeMs == null) {
8125                 return false;
8126             }
8127             if (!mBsi.mPerProcStateCpuTimesAvailable) {
8128                 mProcStateTimeMs = null;
8129                 return false;
8130             }
8131             return mProcStateTimeMs.getCountsLocked(timesInFreqMs, procState);
8132         }
8133 
8134         @GuardedBy("mBsi")
8135         @Override
getScreenOffCpuFreqTimes(long[] timesInFreqMs, int procState)8136         public boolean getScreenOffCpuFreqTimes(long[] timesInFreqMs, int procState) {
8137             if (procState < 0 || procState >= NUM_PROCESS_STATE) {
8138                 return false;
8139             }
8140             if (mProcStateScreenOffTimeMs == null) {
8141                 return false;
8142             }
8143             if (!mBsi.mPerProcStateCpuTimesAvailable) {
8144                 mProcStateScreenOffTimeMs = null;
8145                 return false;
8146             }
8147             return mProcStateScreenOffTimeMs.getCountsLocked(timesInFreqMs, procState);
8148         }
8149 
getBinderCallCount()8150         public long getBinderCallCount() {
8151             return mBinderCallCount;
8152         }
8153 
8154         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
getBinderCallStats()8155         public ArraySet<BinderCallStats> getBinderCallStats() {
8156             return mBinderCallStats;
8157         }
8158 
8159         @Override
getProportionalSystemServiceUsage()8160         public  double getProportionalSystemServiceUsage() {
8161             return mProportionalSystemServiceUsage;
8162         }
8163 
8164         @GuardedBy("mBsi")
addIsolatedUid(int isolatedUid)8165         public void addIsolatedUid(int isolatedUid) {
8166             if (mChildUids == null) {
8167                 mChildUids = new SparseArray<>();
8168             } else if (mChildUids.indexOfKey(isolatedUid) >= 0) {
8169                 return;
8170             }
8171             mChildUids.put(isolatedUid, new ChildUid());
8172         }
8173 
removeIsolatedUid(int isolatedUid)8174         public void removeIsolatedUid(int isolatedUid) {
8175             final int idx = mChildUids == null ? -1 : mChildUids.indexOfKey(isolatedUid);
8176             if (idx < 0) {
8177                 return;
8178             }
8179             mChildUids.remove(idx);
8180         }
8181 
8182         @GuardedBy("mBsi")
getChildUid(int childUid)8183         ChildUid getChildUid(int childUid) {
8184             return mChildUids == null ? null : mChildUids.get(childUid);
8185         }
8186 
nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which)8187         private long[] nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which) {
8188             if (cpuTimesMs == null) {
8189                 return null;
8190             }
8191             final long[] counts = cpuTimesMs.getCountsLocked(which);
8192             if (counts == null) {
8193                 return null;
8194             }
8195             // Return counts only if at least one of the elements is non-zero.
8196             for (int i = counts.length - 1; i >= 0; --i) {
8197                 if (counts[i] != 0) {
8198                     return counts;
8199                 }
8200             }
8201             return null;
8202         }
8203 
8204         @GuardedBy("mBsi")
ensureMultiStateCounters(long timestampMs)8205         private void ensureMultiStateCounters(long timestampMs) {
8206             if (mProcStateTimeMs != null) {
8207                 return;
8208             }
8209 
8210             mProcStateTimeMs =
8211                     new TimeInFreqMultiStateCounter(mBsi.mOnBatteryTimeBase,
8212                             PROC_STATE_TIME_COUNTER_STATE_COUNT, mBsi.getCpuFreqCount(),
8213                             timestampMs);
8214             mProcStateScreenOffTimeMs =
8215                     new TimeInFreqMultiStateCounter(mBsi.mOnBatteryScreenOffTimeBase,
8216                             PROC_STATE_TIME_COUNTER_STATE_COUNT, mBsi.getCpuFreqCount(),
8217                             timestampMs);
8218         }
8219 
8220         @GuardedBy("mBsi")
getProcStateTimeCounter(long timestampMs)8221         private TimeInFreqMultiStateCounter getProcStateTimeCounter(long timestampMs) {
8222             ensureMultiStateCounters(timestampMs);
8223             return mProcStateTimeMs;
8224         }
8225 
8226         @GuardedBy("mBsi")
getProcStateScreenOffTimeCounter(long timestampMs)8227         private TimeInFreqMultiStateCounter getProcStateScreenOffTimeCounter(long timestampMs) {
8228             ensureMultiStateCounters(timestampMs);
8229             return mProcStateScreenOffTimeMs;
8230         }
8231 
8232         @Override
getAggregatedPartialWakelockTimer()8233         public Timer getAggregatedPartialWakelockTimer() {
8234             return mAggregatedPartialWakelockTimer;
8235         }
8236 
8237         @Override
getWakelockStats()8238         public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
8239             return mWakelockStats.getMap();
8240         }
8241 
8242         @Override
getMulticastWakelockStats()8243         public Timer getMulticastWakelockStats() {
8244             return mWifiMulticastTimer;
8245         }
8246 
8247         @Override
getSyncStats()8248         public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
8249             return mSyncStats.getMap();
8250         }
8251 
8252         @Override
getJobStats()8253         public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
8254             return mJobStats.getMap();
8255         }
8256 
8257         @Override
getJobCompletionStats()8258         public ArrayMap<String, SparseIntArray> getJobCompletionStats() {
8259             return mJobCompletions;
8260         }
8261 
8262         @Override
getSensorStats()8263         public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
8264             return mSensorStats;
8265         }
8266 
8267         @Override
getProcessStats()8268         public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
8269             return mProcessStats;
8270         }
8271 
8272         @Override
getPackageStats()8273         public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
8274             return mPackageStats;
8275         }
8276 
8277         @Override
getUid()8278         public int getUid() {
8279             return mUid;
8280         }
8281 
8282         @Override
noteWifiRunningLocked(long elapsedRealtimeMs)8283         public void noteWifiRunningLocked(long elapsedRealtimeMs) {
8284             if (!mWifiRunning) {
8285                 mWifiRunning = true;
8286                 if (mWifiRunningTimer == null) {
8287                     mWifiRunningTimer = new StopwatchTimer(mBsi.mClock, Uid.this, WIFI_RUNNING,
8288                             mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
8289                 }
8290                 mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
8291             }
8292         }
8293 
8294         @Override
noteWifiStoppedLocked(long elapsedRealtimeMs)8295         public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
8296             if (mWifiRunning) {
8297                 mWifiRunning = false;
8298                 mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
8299             }
8300         }
8301 
8302         @Override
noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs)8303         public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
8304             if (!mFullWifiLockOut) {
8305                 mFullWifiLockOut = true;
8306                 if (mFullWifiLockTimer == null) {
8307                     mFullWifiLockTimer = new StopwatchTimer(mBsi.mClock, Uid.this, FULL_WIFI_LOCK,
8308                             mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
8309                 }
8310                 mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
8311             }
8312         }
8313 
8314         @Override
noteFullWifiLockReleasedLocked(long elapsedRealtimeMs)8315         public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
8316             if (mFullWifiLockOut) {
8317                 mFullWifiLockOut = false;
8318                 mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
8319             }
8320         }
8321 
8322         @Override
noteWifiScanStartedLocked(long elapsedRealtimeMs)8323         public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
8324             if (!mWifiScanStarted) {
8325                 mWifiScanStarted = true;
8326                 if (mWifiScanTimer == null) {
8327                     mWifiScanTimer = new DualTimer(mBsi.mClock, Uid.this, WIFI_SCAN,
8328                             mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase,
8329                             mOnBatteryBackgroundTimeBase);
8330                 }
8331                 mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
8332             }
8333         }
8334 
8335         @Override
noteWifiScanStoppedLocked(long elapsedRealtimeMs)8336         public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
8337             if (mWifiScanStarted) {
8338                 mWifiScanStarted = false;
8339                 mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
8340             }
8341         }
8342 
8343         @Override
noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs)8344         public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
8345             int bin = 0;
8346             while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
8347                 csph = csph >> 3;
8348                 bin++;
8349             }
8350 
8351             if (mWifiBatchedScanBinStarted == bin) return;
8352 
8353             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
8354                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
8355                         stopRunningLocked(elapsedRealtimeMs);
8356             }
8357             mWifiBatchedScanBinStarted = bin;
8358             if (mWifiBatchedScanTimer[bin] == null) {
8359                 makeWifiBatchedScanBin(bin, null);
8360             }
8361             mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
8362         }
8363 
8364         @Override
noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs)8365         public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
8366             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
8367                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
8368                         stopRunningLocked(elapsedRealtimeMs);
8369                 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
8370             }
8371         }
8372 
8373         @Override
noteWifiMulticastEnabledLocked(long elapsedRealtimeMs)8374         public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
8375             if (mWifiMulticastWakelockCount == 0) {
8376                 if (mWifiMulticastTimer == null) {
8377                     mWifiMulticastTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
8378                             WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
8379                 }
8380                 mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
8381             }
8382             mWifiMulticastWakelockCount++;
8383         }
8384 
8385         @Override
noteWifiMulticastDisabledLocked(long elapsedRealtimeMs)8386         public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
8387             if (mWifiMulticastWakelockCount == 0) {
8388                 return;
8389             }
8390 
8391             mWifiMulticastWakelockCount--;
8392             if (mWifiMulticastWakelockCount == 0) {
8393                 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
8394             }
8395         }
8396 
8397         @Override
getWifiControllerActivity()8398         public ControllerActivityCounterImpl getWifiControllerActivity() {
8399             return mWifiControllerActivity;
8400         }
8401 
8402         @Override
getBluetoothControllerActivity()8403         public ControllerActivityCounterImpl getBluetoothControllerActivity() {
8404             return mBluetoothControllerActivity;
8405         }
8406 
8407         @Override
getModemControllerActivity()8408         public ControllerActivityCounter getModemControllerActivity() {
8409             return mModemControllerActivity;
8410         }
8411 
getOrCreateWifiControllerActivityLocked()8412         public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
8413             if (mWifiControllerActivity == null) {
8414                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
8415                         mBsi.mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
8416             }
8417             return mWifiControllerActivity;
8418         }
8419 
getOrCreateBluetoothControllerActivityLocked()8420         public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
8421             if (mBluetoothControllerActivity == null) {
8422                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
8423                         mBsi.mOnBatteryTimeBase, NUM_BT_TX_LEVELS);
8424             }
8425             return mBluetoothControllerActivity;
8426         }
8427 
getOrCreateModemControllerActivityLocked()8428         public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
8429             if (mModemControllerActivity == null) {
8430                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mClock,
8431                         mBsi.mOnBatteryTimeBase, ModemActivityInfo.getNumTxPowerLevels());
8432             }
8433             return mModemControllerActivity;
8434         }
8435 
8436         @GuardedBy("mBsi")
getOrCreateEnergyConsumerStatsLocked()8437         private EnergyConsumerStats getOrCreateEnergyConsumerStatsLocked() {
8438             if (mUidEnergyConsumerStats == null) {
8439                 mUidEnergyConsumerStats = new EnergyConsumerStats(mBsi.mEnergyConsumerStatsConfig);
8440             }
8441             return mUidEnergyConsumerStats;
8442         }
8443 
8444         @GuardedBy("mBsi")
getOrCreateEnergyConsumerStatsIfSupportedLocked()8445         private EnergyConsumerStats getOrCreateEnergyConsumerStatsIfSupportedLocked() {
8446             if (mUidEnergyConsumerStats == null && mBsi.mEnergyConsumerStatsConfig != null) {
8447                 mUidEnergyConsumerStats = new EnergyConsumerStats(mBsi.mEnergyConsumerStatsConfig);
8448             }
8449             return mUidEnergyConsumerStats;
8450         }
8451 
8452         /** Adds the given charge to the given standard power bucket for this uid. */
8453         @GuardedBy("mBsi")
addChargeToStandardBucketLocked(long chargeDeltaUC, @StandardPowerBucket int powerBucket, long timestampMs)8454         private void addChargeToStandardBucketLocked(long chargeDeltaUC,
8455                 @StandardPowerBucket int powerBucket, long timestampMs) {
8456             final EnergyConsumerStats energyConsumerStats =
8457                     getOrCreateEnergyConsumerStatsLocked();
8458             energyConsumerStats.updateStandardBucket(powerBucket, chargeDeltaUC, timestampMs);
8459         }
8460 
8461         /** Adds the given charge to the given custom power bucket for this uid. */
8462         @GuardedBy("mBsi")
addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket)8463         private void addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket) {
8464             getOrCreateEnergyConsumerStatsLocked().updateCustomBucket(powerBucket, chargeDeltaUC,
8465                     mBsi.mClock.elapsedRealtime());
8466         }
8467 
8468         /**
8469          * Returns the battery consumption (in microcoulomb) of this uid for a standard power bucket
8470          * of interest.
8471          * @param bucket standard power bucket of interest
8472          * @return consumption (in microcolombs) used by this uid for this power bucket
8473          */
8474         @GuardedBy("mBsi")
getEnergyConsumptionUC(@tandardPowerBucket int bucket)8475         public long getEnergyConsumptionUC(@StandardPowerBucket int bucket) {
8476             if (mBsi.mGlobalEnergyConsumerStats == null
8477                     || !mBsi.mGlobalEnergyConsumerStats.isStandardBucketSupported(bucket)) {
8478                 return POWER_DATA_UNAVAILABLE;
8479             }
8480             if (mUidEnergyConsumerStats == null) {
8481                 return 0L; // It is supported, but was never filled, so it must be 0
8482             }
8483             return mUidEnergyConsumerStats.getAccumulatedStandardBucketCharge(bucket);
8484         }
8485 
8486         /**
8487          * Returns the battery consumption (in microcoulombs) of this uid for a standard power
8488          * bucket and a process state, such as Uid.PROCESS_STATE_TOP.
8489          */
8490         @GuardedBy("mBsi")
getEnergyConsumptionUC(@tandardPowerBucket int bucket, int processState)8491         public long getEnergyConsumptionUC(@StandardPowerBucket int bucket,
8492                 int processState) {
8493             if (mBsi.mGlobalEnergyConsumerStats == null
8494                     || !mBsi.mGlobalEnergyConsumerStats.isStandardBucketSupported(bucket)) {
8495                 return POWER_DATA_UNAVAILABLE;
8496             }
8497             if (mUidEnergyConsumerStats == null) {
8498                 return 0L; // It is supported, but was never filled, so it must be 0
8499             }
8500             return mUidEnergyConsumerStats.getAccumulatedStandardBucketCharge(bucket, processState);
8501         }
8502 
8503         @GuardedBy("mBsi")
8504         @Override
getCustomEnergyConsumerBatteryConsumptionUC()8505         public long[] getCustomEnergyConsumerBatteryConsumptionUC() {
8506             if (mBsi.mGlobalEnergyConsumerStats == null) {
8507                 return null;
8508             }
8509             if (mUidEnergyConsumerStats == null) {
8510                 // Custom buckets may exist. But all values for this uid are 0 so we report all 0s.
8511                 return new long[mBsi.mGlobalEnergyConsumerStats.getNumberCustomPowerBuckets()];
8512             }
8513             return mUidEnergyConsumerStats.getAccumulatedCustomBucketCharges();
8514         }
8515 
8516         @GuardedBy("mBsi")
8517         @Override
getBluetoothEnergyConsumptionUC()8518         public long getBluetoothEnergyConsumptionUC() {
8519             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_BLUETOOTH);
8520         }
8521 
8522         @GuardedBy("mBsi")
8523         @Override
getBluetoothEnergyConsumptionUC( @atteryConsumer.ProcessState int processState)8524         public long getBluetoothEnergyConsumptionUC(
8525                 @BatteryConsumer.ProcessState int processState) {
8526             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_BLUETOOTH,
8527                     processState);
8528         }
8529 
8530         @GuardedBy("mBsi")
8531         @Override
getCpuEnergyConsumptionUC()8532         public long getCpuEnergyConsumptionUC() {
8533             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CPU);
8534         }
8535 
8536         @GuardedBy("mBsi")
8537         @Override
getCpuEnergyConsumptionUC( @atteryConsumer.ProcessState int processState)8538         public long getCpuEnergyConsumptionUC(
8539                 @BatteryConsumer.ProcessState int processState) {
8540             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CPU,
8541                     processState);
8542         }
8543 
8544         @GuardedBy("mBsi")
8545         @Override
getGnssEnergyConsumptionUC()8546         public long getGnssEnergyConsumptionUC() {
8547             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_GNSS);
8548         }
8549 
8550         @GuardedBy("mBsi")
8551         @Override
getMobileRadioEnergyConsumptionUC()8552         public long getMobileRadioEnergyConsumptionUC() {
8553             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO);
8554         }
8555 
8556         @GuardedBy("mBsi")
8557         @Override
getMobileRadioEnergyConsumptionUC(int processState)8558         public long getMobileRadioEnergyConsumptionUC(int processState) {
8559             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO,
8560                     processState);
8561         }
8562 
8563         @GuardedBy("mBsi")
8564         @Override
getScreenOnEnergyConsumptionUC()8565         public long getScreenOnEnergyConsumptionUC() {
8566             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_SCREEN_ON);
8567         }
8568 
8569         @GuardedBy("mBsi")
8570         @Override
getWifiEnergyConsumptionUC()8571         public long getWifiEnergyConsumptionUC() {
8572             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_WIFI);
8573         }
8574 
8575         @GuardedBy("mBsi")
8576         @Override
getWifiEnergyConsumptionUC(int processState)8577         public long getWifiEnergyConsumptionUC(int processState) {
8578             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_WIFI,
8579                     processState);
8580         }
8581 
8582         @GuardedBy("mBsi")
8583         @Override
getCameraEnergyConsumptionUC()8584         public long getCameraEnergyConsumptionUC() {
8585             return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CAMERA);
8586         }
8587 
8588         /**
8589          * Gets the minimum of the uid's foreground activity time and its PROCESS_STATE_TOP time
8590          * since last marked. Also sets the mark time for both these timers.
8591          *
8592          * @see CpuPowerCalculator
8593          *
8594          * @param doCalc if true, then calculate the minimum; else don't bother and return 0. Either
8595          *               way, the mark is set.
8596          */
markProcessForegroundTimeUs(long elapsedRealtimeMs, boolean doCalc)8597         private long markProcessForegroundTimeUs(long elapsedRealtimeMs,
8598                 boolean doCalc) {
8599             long fgTimeUs = 0;
8600             final StopwatchTimer fgTimer = mForegroundActivityTimer;
8601             if (fgTimer != null) {
8602                 if (doCalc) fgTimeUs = fgTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
8603                 fgTimer.setMark(elapsedRealtimeMs);
8604             }
8605 
8606             long topTimeUs = 0;
8607             final StopwatchTimer topTimer = mProcessStateTimer[PROCESS_STATE_TOP];
8608             if (topTimer != null) {
8609                 if (doCalc) topTimeUs = topTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
8610                 topTimer.setMark(elapsedRealtimeMs);
8611             }
8612 
8613             // Return the min of the two
8614             return (topTimeUs < fgTimeUs) ? topTimeUs : fgTimeUs;
8615         }
8616 
8617 
8618         /**
8619          * Gets the uid's time spent using the GNSS since last marked. Also sets the mark time for
8620          * the GNSS timer.
8621          */
markGnssTimeUs(long elapsedRealtimeMs)8622         private long markGnssTimeUs(long elapsedRealtimeMs) {
8623             final Sensor sensor = mSensorStats.get(Sensor.GPS);
8624             if (sensor == null) {
8625                 return 0;
8626             }
8627 
8628             final StopwatchTimer timer = sensor.mTimer;
8629             if (timer == null) {
8630                 return 0;
8631             }
8632 
8633             final long gnssTimeUs = timer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
8634             timer.setMark(elapsedRealtimeMs);
8635             return gnssTimeUs;
8636         }
8637 
8638         /**
8639          * Gets the uid's time spent using the camera since last marked. Also sets the mark time for
8640          * the camera timer.
8641          */
markCameraTimeUs(long elapsedRealtimeMs)8642         private long markCameraTimeUs(long elapsedRealtimeMs) {
8643             final StopwatchTimer timer = mCameraTurnedOnTimer;
8644             if (timer == null) {
8645                 return 0;
8646             }
8647             final long cameraTimeUs = timer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
8648             timer.setMark(elapsedRealtimeMs);
8649             return cameraTimeUs;
8650         }
8651 
createAudioTurnedOnTimerLocked()8652         public StopwatchTimer createAudioTurnedOnTimerLocked() {
8653             if (mAudioTurnedOnTimer == null) {
8654                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, AUDIO_TURNED_ON,
8655                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
8656             }
8657             return mAudioTurnedOnTimer;
8658         }
8659 
noteAudioTurnedOnLocked(long elapsedRealtimeMs)8660         public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
8661             createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
8662         }
8663 
noteAudioTurnedOffLocked(long elapsedRealtimeMs)8664         public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
8665             if (mAudioTurnedOnTimer != null) {
8666                 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
8667             }
8668         }
8669 
noteResetAudioLocked(long elapsedRealtimeMs)8670         public void noteResetAudioLocked(long elapsedRealtimeMs) {
8671             if (mAudioTurnedOnTimer != null) {
8672                 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
8673             }
8674         }
8675 
createVideoTurnedOnTimerLocked()8676         public StopwatchTimer createVideoTurnedOnTimerLocked() {
8677             if (mVideoTurnedOnTimer == null) {
8678                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, VIDEO_TURNED_ON,
8679                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
8680             }
8681             return mVideoTurnedOnTimer;
8682         }
8683 
noteVideoTurnedOnLocked(long elapsedRealtimeMs)8684         public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
8685             createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
8686         }
8687 
noteVideoTurnedOffLocked(long elapsedRealtimeMs)8688         public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
8689             if (mVideoTurnedOnTimer != null) {
8690                 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
8691             }
8692         }
8693 
noteResetVideoLocked(long elapsedRealtimeMs)8694         public void noteResetVideoLocked(long elapsedRealtimeMs) {
8695             if (mVideoTurnedOnTimer != null) {
8696                 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
8697             }
8698         }
8699 
createFlashlightTurnedOnTimerLocked()8700         public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
8701             if (mFlashlightTurnedOnTimer == null) {
8702                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
8703                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
8704             }
8705             return mFlashlightTurnedOnTimer;
8706         }
8707 
noteFlashlightTurnedOnLocked(long elapsedRealtimeMs)8708         public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
8709             createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
8710         }
8711 
noteFlashlightTurnedOffLocked(long elapsedRealtimeMs)8712         public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
8713             if (mFlashlightTurnedOnTimer != null) {
8714                 mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
8715             }
8716         }
8717 
noteResetFlashlightLocked(long elapsedRealtimeMs)8718         public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
8719             if (mFlashlightTurnedOnTimer != null) {
8720                 mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
8721             }
8722         }
8723 
createCameraTurnedOnTimerLocked()8724         public StopwatchTimer createCameraTurnedOnTimerLocked() {
8725             if (mCameraTurnedOnTimer == null) {
8726                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, CAMERA_TURNED_ON,
8727                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
8728             }
8729             return mCameraTurnedOnTimer;
8730         }
8731 
noteCameraTurnedOnLocked(long elapsedRealtimeMs)8732         public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
8733             createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
8734         }
8735 
noteCameraTurnedOffLocked(long elapsedRealtimeMs)8736         public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
8737             if (mCameraTurnedOnTimer != null) {
8738                 mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
8739             }
8740         }
8741 
noteResetCameraLocked(long elapsedRealtimeMs)8742         public void noteResetCameraLocked(long elapsedRealtimeMs) {
8743             if (mCameraTurnedOnTimer != null) {
8744                 mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
8745             }
8746         }
8747 
createForegroundActivityTimerLocked()8748         public StopwatchTimer createForegroundActivityTimerLocked() {
8749             if (mForegroundActivityTimer == null) {
8750                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
8751                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
8752             }
8753             return mForegroundActivityTimer;
8754         }
8755 
createForegroundServiceTimerLocked()8756         public StopwatchTimer createForegroundServiceTimerLocked() {
8757             if (mForegroundServiceTimer == null) {
8758                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClock, Uid.this,
8759                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase);
8760             }
8761             return mForegroundServiceTimer;
8762         }
8763 
createAggregatedPartialWakelockTimerLocked()8764         public DualTimer createAggregatedPartialWakelockTimerLocked() {
8765             if (mAggregatedPartialWakelockTimer == null) {
8766                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClock, this,
8767                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
8768                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase);
8769             }
8770             return mAggregatedPartialWakelockTimer;
8771         }
8772 
createBluetoothScanTimerLocked()8773         public DualTimer createBluetoothScanTimerLocked() {
8774             if (mBluetoothScanTimer == null) {
8775                 mBluetoothScanTimer = new DualTimer(mBsi.mClock, Uid.this, BLUETOOTH_SCAN_ON,
8776                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
8777                         mOnBatteryBackgroundTimeBase);
8778             }
8779             return mBluetoothScanTimer;
8780         }
8781 
createBluetoothUnoptimizedScanTimerLocked()8782         public DualTimer createBluetoothUnoptimizedScanTimerLocked() {
8783             if (mBluetoothUnoptimizedScanTimer == null) {
8784                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClock, Uid.this,
8785                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
8786                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8787             }
8788             return mBluetoothUnoptimizedScanTimer;
8789         }
8790 
noteBluetoothScanStartedLocked(long elapsedRealtimeMs, boolean isUnoptimized)8791         public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs,
8792                 boolean isUnoptimized) {
8793             createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
8794             if (isUnoptimized) {
8795                 createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
8796             }
8797         }
8798 
noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized)8799         public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
8800             if (mBluetoothScanTimer != null) {
8801                 mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
8802             }
8803             if (isUnoptimized && mBluetoothUnoptimizedScanTimer != null) {
8804                 mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs);
8805             }
8806         }
8807 
noteResetBluetoothScanLocked(long elapsedRealtimeMs)8808         public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
8809             if (mBluetoothScanTimer != null) {
8810                 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
8811             }
8812             if (mBluetoothUnoptimizedScanTimer != null) {
8813                 mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
8814             }
8815         }
8816 
createBluetoothScanResultCounterLocked()8817         public Counter createBluetoothScanResultCounterLocked() {
8818             if (mBluetoothScanResultCounter == null) {
8819                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase);
8820             }
8821             return mBluetoothScanResultCounter;
8822         }
8823 
createBluetoothScanResultBgCounterLocked()8824         public Counter createBluetoothScanResultBgCounterLocked() {
8825             if (mBluetoothScanResultBgCounter == null) {
8826                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase);
8827             }
8828             return mBluetoothScanResultBgCounter;
8829         }
8830 
noteBluetoothScanResultsLocked(int numNewResults)8831         public void noteBluetoothScanResultsLocked(int numNewResults) {
8832             createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
8833             // Uses background timebase, so the count will only be incremented if uid in background.
8834             createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults);
8835         }
8836 
8837         @Override
noteActivityResumedLocked(long elapsedRealtimeMs)8838         public void noteActivityResumedLocked(long elapsedRealtimeMs) {
8839             // We always start, since we want multiple foreground PIDs to nest
8840             createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
8841         }
8842 
8843         @Override
noteActivityPausedLocked(long elapsedRealtimeMs)8844         public void noteActivityPausedLocked(long elapsedRealtimeMs) {
8845             if (mForegroundActivityTimer != null) {
8846                 mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
8847             }
8848         }
8849 
noteForegroundServiceResumedLocked(long elapsedRealtimeMs)8850         public void noteForegroundServiceResumedLocked(long elapsedRealtimeMs) {
8851             createForegroundServiceTimerLocked().startRunningLocked(elapsedRealtimeMs);
8852         }
8853 
noteForegroundServicePausedLocked(long elapsedRealtimeMs)8854         public void noteForegroundServicePausedLocked(long elapsedRealtimeMs) {
8855             if (mForegroundServiceTimer != null) {
8856                 mForegroundServiceTimer.stopRunningLocked(elapsedRealtimeMs);
8857             }
8858         }
8859 
createVibratorOnTimerLocked()8860         public BatchTimer createVibratorOnTimerLocked() {
8861             if (mVibratorOnTimer == null) {
8862                 mVibratorOnTimer = new BatchTimer(mBsi.mClock, Uid.this, VIBRATOR_ON,
8863                         mBsi.mOnBatteryTimeBase);
8864             }
8865             return mVibratorOnTimer;
8866         }
8867 
noteVibratorOnLocked(long durationMillis, long elapsedRealtimeMs)8868         public void noteVibratorOnLocked(long durationMillis, long elapsedRealtimeMs) {
8869             createVibratorOnTimerLocked().addDuration(durationMillis, elapsedRealtimeMs);
8870         }
8871 
noteVibratorOffLocked(long elapsedRealtimeMs)8872         public void noteVibratorOffLocked(long elapsedRealtimeMs) {
8873             if (mVibratorOnTimer != null) {
8874                 mVibratorOnTimer.abortLastDuration(elapsedRealtimeMs);
8875             }
8876         }
8877 
8878         @Override
getWifiRunningTime(long elapsedRealtimeUs, int which)8879         public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
8880             if (mWifiRunningTimer == null) {
8881                 return 0;
8882             }
8883             return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8884         }
8885 
8886         @Override
getFullWifiLockTime(long elapsedRealtimeUs, int which)8887         public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
8888             if (mFullWifiLockTimer == null) {
8889                 return 0;
8890             }
8891             return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8892         }
8893 
8894         @Override
getWifiScanTime(long elapsedRealtimeUs, int which)8895         public long getWifiScanTime(long elapsedRealtimeUs, int which) {
8896             if (mWifiScanTimer == null) {
8897                 return 0;
8898             }
8899             return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8900         }
8901 
8902         @Override
getWifiScanCount(int which)8903         public int getWifiScanCount(int which) {
8904             if (mWifiScanTimer == null) {
8905                 return 0;
8906             }
8907             return mWifiScanTimer.getCountLocked(which);
8908         }
8909 
8910         @Override
getWifiScanTimer()8911         public Timer getWifiScanTimer() {
8912             return mWifiScanTimer;
8913         }
8914 
8915         @Override
getWifiScanBackgroundCount(int which)8916         public int getWifiScanBackgroundCount(int which) {
8917             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
8918                 return 0;
8919             }
8920             return mWifiScanTimer.getSubTimer().getCountLocked(which);
8921         }
8922 
8923         @Override
getWifiScanActualTime(final long elapsedRealtimeUs)8924         public long getWifiScanActualTime(final long elapsedRealtimeUs) {
8925             if (mWifiScanTimer == null) {
8926                 return 0;
8927             }
8928             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
8929             return mWifiScanTimer.getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
8930         }
8931 
8932         @Override
getWifiScanBackgroundTime(final long elapsedRealtimeUs)8933         public long getWifiScanBackgroundTime(final long elapsedRealtimeUs) {
8934             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
8935                 return 0;
8936             }
8937             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
8938             return mWifiScanTimer.getSubTimer().getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
8939         }
8940 
8941         @Override
getWifiScanBackgroundTimer()8942         public Timer getWifiScanBackgroundTimer() {
8943             if (mWifiScanTimer == null) {
8944                 return null;
8945             }
8946             return mWifiScanTimer.getSubTimer();
8947         }
8948 
8949         @Override
getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which)8950         public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
8951             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
8952             if (mWifiBatchedScanTimer[csphBin] == null) {
8953                 return 0;
8954             }
8955             return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
8956         }
8957 
8958         @Override
getWifiBatchedScanCount(int csphBin, int which)8959         public int getWifiBatchedScanCount(int csphBin, int which) {
8960             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
8961             if (mWifiBatchedScanTimer[csphBin] == null) {
8962                 return 0;
8963             }
8964             return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
8965         }
8966 
8967         @Override
getWifiMulticastTime(long elapsedRealtimeUs, int which)8968         public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
8969             if (mWifiMulticastTimer == null) {
8970                 return 0;
8971             }
8972             return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8973         }
8974 
8975         @Override
getAudioTurnedOnTimer()8976         public Timer getAudioTurnedOnTimer() {
8977             return mAudioTurnedOnTimer;
8978         }
8979 
8980         @Override
getVideoTurnedOnTimer()8981         public Timer getVideoTurnedOnTimer() {
8982             return mVideoTurnedOnTimer;
8983         }
8984 
8985         @Override
getFlashlightTurnedOnTimer()8986         public Timer getFlashlightTurnedOnTimer() {
8987             return mFlashlightTurnedOnTimer;
8988         }
8989 
8990         @Override
getCameraTurnedOnTimer()8991         public Timer getCameraTurnedOnTimer() {
8992             return mCameraTurnedOnTimer;
8993         }
8994 
8995         @Override
getForegroundActivityTimer()8996         public Timer getForegroundActivityTimer() {
8997             return mForegroundActivityTimer;
8998         }
8999 
9000         @Override
getForegroundServiceTimer()9001         public Timer getForegroundServiceTimer() {
9002             return mForegroundServiceTimer;
9003         }
9004 
9005         @Override
getBluetoothScanTimer()9006         public Timer getBluetoothScanTimer() {
9007             return mBluetoothScanTimer;
9008         }
9009 
9010         @Override
getBluetoothScanBackgroundTimer()9011         public Timer getBluetoothScanBackgroundTimer() {
9012             if (mBluetoothScanTimer == null) {
9013                 return null;
9014             }
9015             return mBluetoothScanTimer.getSubTimer();
9016         }
9017 
9018         @Override
getBluetoothUnoptimizedScanTimer()9019         public Timer getBluetoothUnoptimizedScanTimer() {
9020             return mBluetoothUnoptimizedScanTimer;
9021         }
9022 
9023         @Override
getBluetoothUnoptimizedScanBackgroundTimer()9024         public Timer getBluetoothUnoptimizedScanBackgroundTimer() {
9025             if (mBluetoothUnoptimizedScanTimer == null) {
9026                 return null;
9027             }
9028             return mBluetoothUnoptimizedScanTimer.getSubTimer();
9029         }
9030 
9031         @Override
getBluetoothScanResultCounter()9032         public Counter getBluetoothScanResultCounter() {
9033             return mBluetoothScanResultCounter;
9034         }
9035 
9036         @Override
getBluetoothScanResultBgCounter()9037         public Counter getBluetoothScanResultBgCounter() {
9038             return mBluetoothScanResultBgCounter;
9039         }
9040 
makeProcessState(int i, Parcel in)9041         void makeProcessState(int i, Parcel in) {
9042             if (i < 0 || i >= NUM_PROCESS_STATE) return;
9043 
9044             detachIfNotNull(mProcessStateTimer[i]);
9045             if (in == null) {
9046                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClock, this, PROCESS_STATE, null,
9047                         mBsi.mOnBatteryTimeBase);
9048             } else {
9049                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClock, this, PROCESS_STATE, null,
9050                         mBsi.mOnBatteryTimeBase, in);
9051             }
9052         }
9053 
9054         @Override
getProcessStateTime(int state, long elapsedRealtimeUs, int which)9055         public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
9056             if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
9057             if (mProcessStateTimer[state] == null) {
9058                 return 0;
9059             }
9060             return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
9061         }
9062 
9063         @Override
getProcessStateTimer(int state)9064         public Timer getProcessStateTimer(int state) {
9065             if (state < 0 || state >= NUM_PROCESS_STATE) return null;
9066             return mProcessStateTimer[state];
9067         }
9068 
9069         @Override
getVibratorOnTimer()9070         public Timer getVibratorOnTimer() {
9071             return mVibratorOnTimer;
9072         }
9073 
9074         @Override
noteUserActivityLocked(@owerManager.UserActivityEvent int event)9075         public void noteUserActivityLocked(@PowerManager.UserActivityEvent int event) {
9076             if (mUserActivityCounters == null) {
9077                 initUserActivityLocked();
9078             }
9079             if (event >= 0 && event < NUM_USER_ACTIVITY_TYPES) {
9080                 mUserActivityCounters[event].stepAtomic();
9081             } else {
9082                 Slog.w(TAG, "Unknown user activity type " + event + " was specified.",
9083                         new Throwable());
9084             }
9085         }
9086 
9087         @Override
hasUserActivity()9088         public boolean hasUserActivity() {
9089             return mUserActivityCounters != null;
9090         }
9091 
9092         @Override
getUserActivityCount(int type, int which)9093         public int getUserActivityCount(int type, int which) {
9094             if (mUserActivityCounters == null) {
9095                 return 0;
9096             }
9097             return mUserActivityCounters[type].getCountLocked(which);
9098         }
9099 
makeWifiBatchedScanBin(int i, Parcel in)9100         void makeWifiBatchedScanBin(int i, Parcel in) {
9101             if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
9102 
9103             ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
9104             if (collected == null) {
9105                 collected = new ArrayList<StopwatchTimer>();
9106                 mBsi.mWifiBatchedScanTimers.put(i, collected);
9107             }
9108             detachIfNotNull(mWifiBatchedScanTimer[i]);
9109             if (in == null) {
9110                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClock, this, WIFI_BATCHED_SCAN,
9111                         collected, mBsi.mOnBatteryTimeBase);
9112             } else {
9113                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClock, this, WIFI_BATCHED_SCAN,
9114                         collected, mBsi.mOnBatteryTimeBase, in);
9115             }
9116         }
9117 
9118 
initUserActivityLocked()9119         void initUserActivityLocked() {
9120             detachIfNotNull(mUserActivityCounters);
9121             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
9122             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
9123                 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
9124             }
9125         }
9126 
noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets)9127         void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
9128             ensureNetworkActivityLocked();
9129             if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
9130                 mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
9131                 mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
9132             } else {
9133                 Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
9134                         new Throwable());
9135             }
9136         }
9137 
noteMobileRadioActiveTimeLocked(long batteryUptimeDeltaUs, long elapsedTimeMs)9138         void noteMobileRadioActiveTimeLocked(long batteryUptimeDeltaUs, long elapsedTimeMs) {
9139             ensureNetworkActivityLocked();
9140             getMobileRadioActiveTimeCounter().increment(batteryUptimeDeltaUs, elapsedTimeMs);
9141             mMobileRadioActiveCount.addCountLocked(1);
9142         }
9143 
getMobileRadioActiveTimeCounter()9144         private TimeMultiStateCounter getMobileRadioActiveTimeCounter() {
9145             if (mMobileRadioActiveTime == null) {
9146                 final long timestampMs = mBsi.mClock.elapsedRealtime();
9147                 mMobileRadioActiveTime = new TimeMultiStateCounter(
9148                         mBsi.mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT, timestampMs);
9149                 mMobileRadioActiveTime.setState(
9150                         mapUidProcessStateToBatteryConsumerProcessState(mProcessState),
9151                         timestampMs);
9152                 mMobileRadioActiveTime.update(0, timestampMs);
9153             }
9154             return mMobileRadioActiveTime;
9155         }
9156 
9157         @Override
hasNetworkActivity()9158         public boolean hasNetworkActivity() {
9159             return mNetworkByteActivityCounters != null;
9160         }
9161 
9162         @Override
getNetworkActivityBytes(int type, int which)9163         public long getNetworkActivityBytes(int type, int which) {
9164             if (mNetworkByteActivityCounters != null && type >= 0
9165                     && type < mNetworkByteActivityCounters.length) {
9166                 return mNetworkByteActivityCounters[type].getCountLocked(which);
9167             } else {
9168                 return 0;
9169             }
9170         }
9171 
9172         @Override
getNetworkActivityPackets(int type, int which)9173         public long getNetworkActivityPackets(int type, int which) {
9174             if (mNetworkPacketActivityCounters != null && type >= 0
9175                     && type < mNetworkPacketActivityCounters.length) {
9176                 return mNetworkPacketActivityCounters[type].getCountLocked(which);
9177             } else {
9178                 return 0;
9179             }
9180         }
9181 
9182         @Override
getMobileRadioActiveTime(int which)9183         public long getMobileRadioActiveTime(int which) {
9184             return getMobileRadioActiveTimeInProcessState(BatteryConsumer.PROCESS_STATE_ANY);
9185         }
9186 
9187         @Override
getMobileRadioActiveTimeInProcessState( @atteryConsumer.ProcessState int processState)9188         public long getMobileRadioActiveTimeInProcessState(
9189                 @BatteryConsumer.ProcessState int processState) {
9190             if (mMobileRadioActiveTime == null) {
9191                 return 0;
9192             }
9193             if (processState == BatteryConsumer.PROCESS_STATE_ANY) {
9194                 return mMobileRadioActiveTime.getTotalCountLocked();
9195             } else {
9196                 return mMobileRadioActiveTime.getCountForProcessState(processState);
9197             }
9198         }
9199 
9200         @Override
getMobileRadioActiveCount(int which)9201         public int getMobileRadioActiveCount(int which) {
9202             return mMobileRadioActiveCount != null
9203                     ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
9204         }
9205 
9206         @Override
getUserCpuTimeUs(int which)9207         public long getUserCpuTimeUs(int which) {
9208             return mUserCpuTime.getCountLocked(which);
9209         }
9210 
9211         @Override
getSystemCpuTimeUs(int which)9212         public long getSystemCpuTimeUs(int which) {
9213             return mSystemCpuTime.getCountLocked(which);
9214         }
9215 
9216         @Override
getTimeAtCpuSpeed(int cluster, int step, int which)9217         public long getTimeAtCpuSpeed(int cluster, int step, int which) {
9218             if (mCpuClusterSpeedTimesUs != null) {
9219                 if (cluster >= 0 && cluster < mCpuClusterSpeedTimesUs.length) {
9220                     final LongSamplingCounter[] cpuSpeedTimesUs = mCpuClusterSpeedTimesUs[cluster];
9221                     if (cpuSpeedTimesUs != null) {
9222                         if (step >= 0 && step < cpuSpeedTimesUs.length) {
9223                             final LongSamplingCounter c = cpuSpeedTimesUs[step];
9224                             if (c != null) {
9225                                 return c.getCountLocked(which);
9226                             }
9227                         }
9228                     }
9229                 }
9230             }
9231             return 0;
9232         }
9233 
noteMobileRadioApWakeupLocked()9234         public void noteMobileRadioApWakeupLocked() {
9235             if (mMobileRadioApWakeupCount == null) {
9236                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9237             }
9238             mMobileRadioApWakeupCount.addCountLocked(1);
9239         }
9240 
9241         @Override
getMobileRadioApWakeupCount(int which)9242         public long getMobileRadioApWakeupCount(int which) {
9243             if (mMobileRadioApWakeupCount != null) {
9244                 return mMobileRadioApWakeupCount.getCountLocked(which);
9245             }
9246             return 0;
9247         }
9248 
noteWifiRadioApWakeupLocked()9249         public void noteWifiRadioApWakeupLocked() {
9250             if (mWifiRadioApWakeupCount == null) {
9251                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9252             }
9253             mWifiRadioApWakeupCount.addCountLocked(1);
9254         }
9255 
9256         @Override
getWifiRadioApWakeupCount(int which)9257         public long getWifiRadioApWakeupCount(int which) {
9258             if (mWifiRadioApWakeupCount != null) {
9259                 return mWifiRadioApWakeupCount.getCountLocked(which);
9260             }
9261             return 0;
9262         }
9263 
9264         @Override
getDeferredJobsCheckinLineLocked(StringBuilder sb, int which)9265         public void getDeferredJobsCheckinLineLocked(StringBuilder sb, int which) {
9266             sb.setLength(0);
9267             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
9268             if (deferredEventCount == 0) {
9269                 return;
9270             }
9271             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
9272             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
9273             sb.append(deferredEventCount); sb.append(',');
9274             sb.append(deferredCount); sb.append(',');
9275             sb.append(totalLatency);
9276             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
9277                 if (mJobsFreshnessBuckets[i] == null) {
9278                     sb.append(",0");
9279                 } else {
9280                     sb.append(",");
9281                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
9282                 }
9283             }
9284         }
9285 
9286         @Override
getDeferredJobsLineLocked(StringBuilder sb, int which)9287         public void getDeferredJobsLineLocked(StringBuilder sb, int which) {
9288             sb.setLength(0);
9289             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
9290             if (deferredEventCount == 0) {
9291                 return;
9292             }
9293             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
9294             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
9295             sb.append("times="); sb.append(deferredEventCount); sb.append(", ");
9296             sb.append("count="); sb.append(deferredCount); sb.append(", ");
9297             sb.append("totalLatencyMs="); sb.append(totalLatency); sb.append(", ");
9298             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
9299                 sb.append("<"); sb.append(JOB_FRESHNESS_BUCKETS[i]); sb.append("ms=");
9300                 if (mJobsFreshnessBuckets[i] == null) {
9301                     sb.append("0");
9302                 } else {
9303                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
9304                 }
9305                 sb.append(" ");
9306             }
9307         }
9308 
ensureNetworkActivityLocked()9309         void ensureNetworkActivityLocked() {
9310             if (mNetworkByteActivityCounters != null) {
9311                 return;
9312             }
9313 
9314             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
9315             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
9316             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9317                 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9318                 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9319             }
9320             mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
9321         }
9322 
9323         /**
9324          * Clear all stats for this uid.  Returns true if the uid is completely
9325          * inactive so can be dropped.
9326          */
9327         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
reset(long uptimeUs, long realtimeUs, int resetReason)9328         public boolean reset(long uptimeUs, long realtimeUs, int resetReason) {
9329             boolean active = false;
9330 
9331             mOnBatteryBackgroundTimeBase.init(uptimeUs, realtimeUs);
9332             mOnBatteryScreenOffBackgroundTimeBase.init(uptimeUs, realtimeUs);
9333 
9334             if (mWifiRunningTimer != null) {
9335                 active |= !mWifiRunningTimer.reset(false, realtimeUs);
9336                 active |= mWifiRunning;
9337             }
9338             if (mFullWifiLockTimer != null) {
9339                 active |= !mFullWifiLockTimer.reset(false, realtimeUs);
9340                 active |= mFullWifiLockOut;
9341             }
9342             if (mWifiScanTimer != null) {
9343                 active |= !mWifiScanTimer.reset(false, realtimeUs);
9344                 active |= mWifiScanStarted;
9345             }
9346             if (mWifiBatchedScanTimer != null) {
9347                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
9348                     if (mWifiBatchedScanTimer[i] != null) {
9349                         active |= !mWifiBatchedScanTimer[i].reset(false, realtimeUs);
9350                     }
9351                 }
9352                 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
9353             }
9354             if (mWifiMulticastTimer != null) {
9355                 active |= !mWifiMulticastTimer.reset(false, realtimeUs);
9356                 active |= (mWifiMulticastWakelockCount > 0);
9357             }
9358 
9359             active |= !resetIfNotNull(mAudioTurnedOnTimer, false, realtimeUs);
9360             active |= !resetIfNotNull(mVideoTurnedOnTimer, false, realtimeUs);
9361             active |= !resetIfNotNull(mFlashlightTurnedOnTimer, false, realtimeUs);
9362             active |= !resetIfNotNull(mCameraTurnedOnTimer, false, realtimeUs);
9363             active |= !resetIfNotNull(mForegroundActivityTimer, false, realtimeUs);
9364             active |= !resetIfNotNull(mForegroundServiceTimer, false, realtimeUs);
9365             active |= !resetIfNotNull(mAggregatedPartialWakelockTimer, false, realtimeUs);
9366             active |= !resetIfNotNull(mBluetoothScanTimer, false, realtimeUs);
9367             active |= !resetIfNotNull(mBluetoothUnoptimizedScanTimer, false, realtimeUs);
9368 
9369             resetIfNotNull(mBluetoothScanResultCounter, false, realtimeUs);
9370             resetIfNotNull(mBluetoothScanResultBgCounter, false, realtimeUs);
9371 
9372             if (mProcessStateTimer != null) {
9373                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
9374                     active |= !resetIfNotNull(mProcessStateTimer[i], false, realtimeUs);
9375                 }
9376                 active |= (mProcessState != Uid.PROCESS_STATE_NONEXISTENT);
9377             }
9378             if (mVibratorOnTimer != null) {
9379                 if (mVibratorOnTimer.reset(false, realtimeUs)) {
9380                     mVibratorOnTimer.detach();
9381                     mVibratorOnTimer = null;
9382                 } else {
9383                     active = true;
9384                 }
9385             }
9386 
9387             resetIfNotNull(mUserActivityCounters, false, realtimeUs);
9388 
9389             resetIfNotNull(mNetworkByteActivityCounters, false, realtimeUs);
9390             resetIfNotNull(mNetworkPacketActivityCounters, false, realtimeUs);
9391             resetIfNotNull(mMobileRadioActiveTime, false, realtimeUs);
9392             resetIfNotNull(mMobileRadioActiveCount, false, realtimeUs);
9393 
9394             resetIfNotNull(mWifiControllerActivity, false, realtimeUs);
9395             resetIfNotNull(mBluetoothControllerActivity, false, realtimeUs);
9396             resetIfNotNull(mModemControllerActivity, false, realtimeUs);
9397 
9398             if (resetReason == RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE) {
9399                 mUidEnergyConsumerStats = null;
9400             } else {
9401                 EnergyConsumerStats.resetIfNotNull(mUidEnergyConsumerStats);
9402             }
9403 
9404             resetIfNotNull(mUserCpuTime, false, realtimeUs);
9405             resetIfNotNull(mSystemCpuTime, false, realtimeUs);
9406 
9407             resetIfNotNull(mCpuClusterSpeedTimesUs, false, realtimeUs);
9408 
9409             resetIfNotNull(mCpuFreqTimeMs, false, realtimeUs /* unused */);
9410             resetIfNotNull(mScreenOffCpuFreqTimeMs, false, realtimeUs /* unused */);
9411 
9412 
9413             resetIfNotNull(mCpuActiveTimeMs, false, realtimeUs /* unused */);
9414             resetIfNotNull(mCpuClusterTimesMs, false, realtimeUs /* unused */);
9415 
9416             resetIfNotNull(mProcStateTimeMs, false, realtimeUs /* unused */);
9417 
9418             resetIfNotNull(mProcStateScreenOffTimeMs, false, realtimeUs /* unused */);
9419 
9420             resetIfNotNull(mMobileRadioApWakeupCount, false, realtimeUs);
9421 
9422             resetIfNotNull(mWifiRadioApWakeupCount, false, realtimeUs);
9423 
9424 
9425             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
9426             for (int iw=wakeStats.size()-1; iw>=0; iw--) {
9427                 Wakelock wl = wakeStats.valueAt(iw);
9428                 if (wl.reset(realtimeUs)) {
9429                     wakeStats.removeAt(iw);
9430                 } else {
9431                     active = true;
9432                 }
9433             }
9434             final long realtimeMs = realtimeUs / 1000;
9435             mWakelockStats.cleanup(realtimeMs);
9436             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
9437             for (int is=syncStats.size()-1; is>=0; is--) {
9438                 DualTimer timer = syncStats.valueAt(is);
9439                 if (timer.reset(false, realtimeUs)) {
9440                     syncStats.removeAt(is);
9441                     timer.detach();
9442                 } else {
9443                     active = true;
9444                 }
9445             }
9446             mSyncStats.cleanup(realtimeMs);
9447             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
9448             for (int ij=jobStats.size()-1; ij>=0; ij--) {
9449                 DualTimer timer = jobStats.valueAt(ij);
9450                 if (timer.reset(false, realtimeUs)) {
9451                     jobStats.removeAt(ij);
9452                     timer.detach();
9453                 } else {
9454                     active = true;
9455                 }
9456             }
9457             mJobStats.cleanup(realtimeMs);
9458             mJobCompletions.clear();
9459 
9460             resetIfNotNull(mJobsDeferredEventCount, false, realtimeUs);
9461             resetIfNotNull(mJobsDeferredCount, false, realtimeUs);
9462             resetIfNotNull(mJobsFreshnessTimeMs, false, realtimeUs /* unused */);
9463             resetIfNotNull(mJobsFreshnessBuckets, false, realtimeUs);
9464 
9465             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
9466                 Sensor s = mSensorStats.valueAt(ise);
9467                 if (s.reset(realtimeUs)) {
9468                     mSensorStats.removeAt(ise);
9469                 } else {
9470                     active = true;
9471                 }
9472             }
9473 
9474             for (int ip = mProcessStats.size() - 1; ip >= 0; ip--) {
9475                 Proc proc = mProcessStats.valueAt(ip);
9476                 proc.detach();
9477             }
9478             mProcessStats.clear();
9479 
9480             for (int i = mPids.size() - 1; i >= 0; i--) {
9481                 Pid pid = mPids.valueAt(i);
9482                 if (pid.mWakeNesting > 0) {
9483                     active = true;
9484                 } else {
9485                     mPids.removeAt(i);
9486                 }
9487             }
9488 
9489 
9490             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
9491                 Pkg p = mPackageStats.valueAt(i);
9492                 p.detach();
9493             }
9494             mPackageStats.clear();
9495 
9496             mBinderCallCount = 0;
9497             mBinderCallStats.clear();
9498 
9499             mProportionalSystemServiceUsage = 0;
9500 
9501             mLastStepUserTimeMs = mLastStepSystemTimeMs = 0;
9502             mCurStepUserTimeMs = mCurStepSystemTimeMs = 0;
9503 
9504 
9505             return !active;
9506         }
9507 
9508         /**
9509          * This method MUST be called whenever the Uid object is destructed, otherwise it is a
9510          * memory leak in {@link TimeBase#mObservers} list.
9511          * Typically the Uid object is destructed when it is removed from
9512          * {@link BatteryStatsImpl#mUidStats}
9513          */
detachFromTimeBase()9514         void detachFromTimeBase() {
9515             detachIfNotNull(mWifiRunningTimer);
9516             detachIfNotNull(mFullWifiLockTimer);
9517             detachIfNotNull(mWifiScanTimer);
9518             detachIfNotNull(mWifiBatchedScanTimer);
9519             detachIfNotNull(mWifiMulticastTimer);
9520             detachIfNotNull(mAudioTurnedOnTimer);
9521             detachIfNotNull(mVideoTurnedOnTimer);
9522             detachIfNotNull(mFlashlightTurnedOnTimer);
9523 
9524             detachIfNotNull(mCameraTurnedOnTimer);
9525             detachIfNotNull(mForegroundActivityTimer);
9526             detachIfNotNull(mForegroundServiceTimer);
9527 
9528             detachIfNotNull(mAggregatedPartialWakelockTimer);
9529 
9530             detachIfNotNull(mBluetoothScanTimer);
9531             detachIfNotNull(mBluetoothUnoptimizedScanTimer);
9532             detachIfNotNull(mBluetoothScanResultCounter);
9533             detachIfNotNull(mBluetoothScanResultBgCounter);
9534 
9535             detachIfNotNull(mProcessStateTimer);
9536 
9537             detachIfNotNull(mVibratorOnTimer);
9538 
9539             detachIfNotNull(mUserActivityCounters);
9540 
9541             detachIfNotNull(mNetworkByteActivityCounters);
9542             detachIfNotNull(mNetworkPacketActivityCounters);
9543 
9544             detachIfNotNull(mMobileRadioActiveTime);
9545             detachIfNotNull(mMobileRadioActiveCount);
9546             detachIfNotNull(mMobileRadioApWakeupCount);
9547             detachIfNotNull(mWifiRadioApWakeupCount);
9548 
9549             detachIfNotNull(mWifiControllerActivity);
9550             detachIfNotNull(mBluetoothControllerActivity);
9551             detachIfNotNull(mModemControllerActivity);
9552 
9553             mPids.clear();
9554 
9555             detachIfNotNull(mUserCpuTime);
9556             detachIfNotNull(mSystemCpuTime);
9557 
9558             detachIfNotNull(mCpuClusterSpeedTimesUs);
9559 
9560             detachIfNotNull(mCpuActiveTimeMs);
9561             detachIfNotNull(mCpuFreqTimeMs);
9562 
9563             detachIfNotNull(mScreenOffCpuFreqTimeMs);
9564 
9565             detachIfNotNull(mCpuClusterTimesMs);
9566 
9567             detachIfNotNull(mProcStateTimeMs);
9568 
9569             detachIfNotNull(mProcStateScreenOffTimeMs);
9570 
9571             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
9572             for (int iw = wakeStats.size() - 1; iw >= 0; iw--) {
9573                 Wakelock wl = wakeStats.valueAt(iw);
9574                 wl.detachFromTimeBase();
9575             }
9576             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
9577             for (int is = syncStats.size() - 1; is >= 0; is--) {
9578                 DualTimer timer = syncStats.valueAt(is);
9579                 detachIfNotNull(timer);
9580             }
9581             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
9582             for (int ij = jobStats.size() - 1; ij >= 0; ij--) {
9583                 DualTimer timer = jobStats.valueAt(ij);
9584                 detachIfNotNull(timer);
9585             }
9586 
9587             detachIfNotNull(mJobsDeferredEventCount);
9588             detachIfNotNull(mJobsDeferredCount);
9589             detachIfNotNull(mJobsFreshnessTimeMs);
9590             detachIfNotNull(mJobsFreshnessBuckets);
9591 
9592 
9593             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
9594                 Sensor s = mSensorStats.valueAt(ise);
9595                 s.detachFromTimeBase();
9596             }
9597 
9598             for (int ip= mProcessStats.size() - 1; ip >= 0; ip--) {
9599                 Proc proc = mProcessStats.valueAt(ip);
9600                 proc.detach();
9601             }
9602             mProcessStats.clear();
9603 
9604             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
9605                 Pkg p = mPackageStats.valueAt(i);
9606                 p.detach();
9607             }
9608             mPackageStats.clear();
9609         }
9610 
writeJobCompletionsToParcelLocked(Parcel out)9611         void writeJobCompletionsToParcelLocked(Parcel out) {
9612             int NJC = mJobCompletions.size();
9613             out.writeInt(NJC);
9614             for (int ijc=0; ijc<NJC; ijc++) {
9615                 out.writeString(mJobCompletions.keyAt(ijc));
9616                 SparseIntArray types = mJobCompletions.valueAt(ijc);
9617                 int NT = types.size();
9618                 out.writeInt(NT);
9619                 for (int it=0; it<NT; it++) {
9620                     out.writeInt(types.keyAt(it));
9621                     out.writeInt(types.valueAt(it));
9622                 }
9623             }
9624         }
9625 
readJobCompletionsFromParcelLocked(Parcel in)9626         void readJobCompletionsFromParcelLocked(Parcel in) {
9627             int numJobCompletions = in.readInt();
9628             mJobCompletions.clear();
9629             for (int j = 0; j < numJobCompletions; j++) {
9630                 String jobName = in.readString();
9631                 int numTypes = in.readInt();
9632                 if (numTypes > 0) {
9633                     SparseIntArray types = new SparseIntArray();
9634                     for (int k = 0; k < numTypes; k++) {
9635                         int type = in.readInt();
9636                         int count = in.readInt();
9637                         types.put(type, count);
9638                     }
9639                     mJobCompletions.put(jobName, types);
9640                 }
9641             }
9642         }
9643 
noteJobsDeferredLocked(int numDeferred, long sinceLast)9644         public void noteJobsDeferredLocked(int numDeferred, long sinceLast) {
9645             mJobsDeferredEventCount.addAtomic(1);
9646             mJobsDeferredCount.addAtomic(numDeferred);
9647             if (sinceLast != 0) {
9648                 // Add the total time, which can be divided by the event count to get an average
9649                 mJobsFreshnessTimeMs.addCountLocked(sinceLast);
9650                 // Also keep track of how many times there were in these different buckets.
9651                 for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
9652                     if (sinceLast < JOB_FRESHNESS_BUCKETS[i]) {
9653                         if (mJobsFreshnessBuckets[i] == null) {
9654                             mJobsFreshnessBuckets[i] = new Counter(
9655                                     mBsi.mOnBatteryTimeBase);
9656                         }
9657                         mJobsFreshnessBuckets[i].addAtomic(1);
9658                         break;
9659                     }
9660                 }
9661             }
9662         }
9663 
9664         // Reusable object used as a key to lookup values in mBinderCallStats
9665         private static BinderCallStats sTempBinderCallStats = new BinderCallStats();
9666 
9667         /**
9668          * Notes incoming binder call stats associated with this work source UID.
9669          */
noteBinderCallStatsLocked(long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats)9670         public void noteBinderCallStatsLocked(long incrementalCallCount,
9671                 Collection<BinderCallsStats.CallStat> callStats) {
9672             if (DEBUG) {
9673                 Slog.d(TAG, "noteBinderCalls() workSourceUid = [" + mUid + "], "
9674                         + " incrementalCallCount: " + incrementalCallCount + " callStats = ["
9675                         + new ArrayList<>(callStats) + "]");
9676             }
9677             mBinderCallCount += incrementalCallCount;
9678             for (BinderCallsStats.CallStat stat : callStats) {
9679                 BinderCallStats bcs;
9680                 sTempBinderCallStats.binderClass = stat.binderClass;
9681                 sTempBinderCallStats.transactionCode = stat.transactionCode;
9682                 int index = mBinderCallStats.indexOf(sTempBinderCallStats);
9683                 if (index >= 0) {
9684                     bcs = mBinderCallStats.valueAt(index);
9685                 } else {
9686                     bcs = new BinderCallStats();
9687                     bcs.binderClass = stat.binderClass;
9688                     bcs.transactionCode = stat.transactionCode;
9689                     mBinderCallStats.add(bcs);
9690                 }
9691 
9692                 bcs.callCount += stat.incrementalCallCount;
9693                 bcs.recordedCallCount = stat.recordedCallCount;
9694                 bcs.recordedCpuTimeMicros = stat.cpuTimeMicros;
9695             }
9696         }
9697 
9698         /**
9699          * The statistics associated with a particular wake lock.
9700          */
9701         public static class Wakelock extends BatteryStats.Uid.Wakelock {
9702             /**
9703              * BatteryStatsImpl that we are associated with.
9704              */
9705             protected BatteryStatsImpl mBsi;
9706 
9707             /**
9708              * BatteryStatsImpl that we are associated with.
9709              */
9710             protected Uid mUid;
9711 
9712             /**
9713              * How long (in ms) this uid has been keeping the device partially awake.
9714              * Tracks both the total time and the time while the app was in the background.
9715              */
9716             DualTimer mTimerPartial;
9717 
9718             /**
9719              * How long (in ms) this uid has been keeping the device fully awake.
9720              */
9721             StopwatchTimer mTimerFull;
9722 
9723             /**
9724              * How long (in ms) this uid has had a window keeping the device awake.
9725              */
9726             StopwatchTimer mTimerWindow;
9727 
9728             /**
9729              * How long (in ms) this uid has had a draw wake lock.
9730              */
9731             StopwatchTimer mTimerDraw;
9732 
Wakelock(BatteryStatsImpl bsi, Uid uid)9733             public Wakelock(BatteryStatsImpl bsi, Uid uid) {
9734                 mBsi = bsi;
9735                 mUid = uid;
9736             }
9737 
9738             /**
9739              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
9740              * proper timer pool from the given BatteryStatsImpl object.
9741              *
9742              * @param in the Parcel to be read from.
9743              * return a new Timer, or null.
9744              */
readStopwatchTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in)9745             private StopwatchTimer readStopwatchTimerFromParcel(int type,
9746                     ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
9747                 if (in.readInt() == 0) {
9748                     return null;
9749                 }
9750 
9751                 return new StopwatchTimer(mBsi.mClock, mUid, type, pool, timeBase, in);
9752             }
9753 
9754             /**
9755              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
9756              * proper timer pool from the given BatteryStatsImpl object.
9757              *
9758              * @param in the Parcel to be read from.
9759              * return a new Timer, or null.
9760              */
readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, TimeBase bgTimeBase, Parcel in)9761             private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
9762                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
9763                 if (in.readInt() == 0) {
9764                     return null;
9765                 }
9766 
9767                 return new DualTimer(mBsi.mClock, mUid, type, pool, timeBase, bgTimeBase, in);
9768             }
9769 
reset(long elapsedRealtimeUs)9770             boolean reset(long elapsedRealtimeUs) {
9771                 boolean wlactive = false;
9772 
9773                 wlactive |= !resetIfNotNull(mTimerFull, false, elapsedRealtimeUs);
9774                 wlactive |= !resetIfNotNull(mTimerPartial, false, elapsedRealtimeUs);
9775                 wlactive |= !resetIfNotNull(mTimerWindow, false, elapsedRealtimeUs);
9776                 wlactive |= !resetIfNotNull(mTimerDraw, false, elapsedRealtimeUs);
9777 
9778                 if (!wlactive) {
9779                     detachIfNotNull(mTimerFull);
9780                     mTimerFull = null;
9781 
9782                     detachIfNotNull(mTimerPartial);
9783                     mTimerPartial = null;
9784 
9785                     detachIfNotNull(mTimerWindow);
9786                     mTimerWindow = null;
9787 
9788                     detachIfNotNull(mTimerDraw);
9789                     mTimerDraw = null;
9790                 }
9791                 return !wlactive;
9792             }
9793 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, TimeBase screenOffBgTimeBase, Parcel in)9794             void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase,
9795                     TimeBase screenOffBgTimeBase, Parcel in) {
9796                 mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL,
9797                         mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in);
9798                 mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
9799                         mBsi.mFullTimers, timeBase, in);
9800                 mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
9801                         mBsi.mWindowTimers, timeBase, in);
9802                 mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
9803                         mBsi.mDrawTimers, timeBase, in);
9804             }
9805 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)9806             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
9807                 Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
9808                 Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
9809                 Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
9810                 Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
9811             }
9812 
9813             @Override
getWakeTime(int type)9814             public Timer getWakeTime(int type) {
9815                 switch (type) {
9816                 case WAKE_TYPE_FULL: return mTimerFull;
9817                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
9818                 case WAKE_TYPE_WINDOW: return mTimerWindow;
9819                 case WAKE_TYPE_DRAW: return mTimerDraw;
9820                 default: throw new IllegalArgumentException("type = " + type);
9821                 }
9822             }
9823 
detachFromTimeBase()9824             public void detachFromTimeBase() {
9825                 detachIfNotNull(mTimerPartial);
9826                 detachIfNotNull(mTimerFull);
9827                 detachIfNotNull(mTimerWindow);
9828                 detachIfNotNull(mTimerDraw);
9829             }
9830         }
9831 
9832         public static class Sensor extends BatteryStats.Uid.Sensor {
9833             /**
9834              * BatteryStatsImpl that we are associated with.
9835              */
9836             protected BatteryStatsImpl mBsi;
9837 
9838             /**
9839              * Uid that we are associated with.
9840              */
9841             protected Uid mUid;
9842 
9843             final int mHandle;
9844             DualTimer mTimer;
9845 
Sensor(BatteryStatsImpl bsi, Uid uid, int handle)9846             public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
9847                 mBsi = bsi;
9848                 mUid = uid;
9849                 mHandle = handle;
9850             }
9851 
readTimersFromParcel( TimeBase timeBase, TimeBase bgTimeBase, Parcel in)9852             private DualTimer readTimersFromParcel(
9853                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
9854                 if (in.readInt() == 0) {
9855                     return null;
9856                 }
9857 
9858                 ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
9859                 if (pool == null) {
9860                     pool = new ArrayList<StopwatchTimer>();
9861                     mBsi.mSensorTimers.put(mHandle, pool);
9862                 }
9863                 return new DualTimer(mBsi.mClock, mUid, 0, pool, timeBase, bgTimeBase, in);
9864             }
9865 
reset(long elapsedRealtimeUs)9866             boolean reset(long elapsedRealtimeUs) {
9867                 if (mTimer.reset(true, elapsedRealtimeUs)) {
9868                     mTimer = null;
9869                     return true;
9870                 }
9871                 return false;
9872             }
9873 
readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in)9874             void readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
9875                 mTimer = readTimersFromParcel(timeBase, bgTimeBase, in);
9876             }
9877 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)9878             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
9879                 Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
9880             }
9881 
9882             @Override
getSensorTime()9883             public Timer getSensorTime() {
9884                 return mTimer;
9885             }
9886 
9887             @Override
getSensorBackgroundTime()9888             public Timer getSensorBackgroundTime() {
9889                 if (mTimer == null) {
9890                     return null;
9891                 }
9892                 return mTimer.getSubTimer();
9893             }
9894 
9895             @Override
getHandle()9896             public int getHandle() {
9897                 return mHandle;
9898             }
9899 
detachFromTimeBase()9900             public void  detachFromTimeBase() {
9901                 detachIfNotNull(mTimer);
9902             }
9903         }
9904 
9905         /**
9906          * The statistics associated with a particular process.
9907          */
9908         public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
9909             /**
9910              * BatteryStatsImpl that we are associated with.
9911              */
9912             protected BatteryStatsImpl mBsi;
9913 
9914             /**
9915              * The name of this process.
9916              */
9917             final String mName;
9918 
9919             /**
9920              * Remains true until removed from the stats.
9921              */
9922             boolean mActive = true;
9923 
9924             /**
9925              * Total time (in ms) spent executing in user code.
9926              */
9927             long mUserTimeMs;
9928 
9929             /**
9930              * Total time (in ms) spent executing in kernel code.
9931              */
9932             long mSystemTimeMs;
9933 
9934             /**
9935              * Amount of time (in ms) the process was running in the foreground.
9936              */
9937             long mForegroundTimeMs;
9938 
9939             /**
9940              * Number of times the process has been started.
9941              */
9942             int mStarts;
9943 
9944             /**
9945              * Number of times the process has crashed.
9946              */
9947             int mNumCrashes;
9948 
9949             /**
9950              * Number of times the process has had an ANR.
9951              */
9952             int mNumAnrs;
9953 
9954             ArrayList<ExcessivePower> mExcessivePower;
9955 
Proc(BatteryStatsImpl bsi, String name)9956             public Proc(BatteryStatsImpl bsi, String name) {
9957                 mBsi = bsi;
9958                 mName = name;
9959                 mBsi.mOnBatteryTimeBase.add(this);
9960             }
9961 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)9962             public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
9963                     long baseRealtimeUs) {
9964             }
9965 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)9966             public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
9967                     long baseRealtimeUs) {
9968             }
9969 
9970             @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)9971             public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
9972                 if (detachIfReset) {
9973                     this.detach();
9974                 }
9975                 return true;
9976             }
9977 
9978             @Override
detach()9979             public void detach() {
9980                 mActive = false;
9981                 mBsi.mOnBatteryTimeBase.remove(this);
9982             }
9983 
countExcessivePowers()9984             public int countExcessivePowers() {
9985                 return mExcessivePower != null ? mExcessivePower.size() : 0;
9986             }
9987 
getExcessivePower(int i)9988             public ExcessivePower getExcessivePower(int i) {
9989                 if (mExcessivePower != null) {
9990                     return mExcessivePower.get(i);
9991                 }
9992                 return null;
9993             }
9994 
addExcessiveCpu(long overTimeMs, long usedTimeMs)9995             public void addExcessiveCpu(long overTimeMs, long usedTimeMs) {
9996                 if (mExcessivePower == null) {
9997                     mExcessivePower = new ArrayList<ExcessivePower>();
9998                 }
9999                 ExcessivePower ew = new ExcessivePower();
10000                 ew.type = ExcessivePower.TYPE_CPU;
10001                 ew.overTime = overTimeMs;
10002                 ew.usedTime = usedTimeMs;
10003                 mExcessivePower.add(ew);
10004             }
10005 
writeExcessivePowerToParcelLocked(Parcel out)10006             void writeExcessivePowerToParcelLocked(Parcel out) {
10007                 if (mExcessivePower == null) {
10008                     out.writeInt(0);
10009                     return;
10010                 }
10011 
10012                 final int N = mExcessivePower.size();
10013                 out.writeInt(N);
10014                 for (int i=0; i<N; i++) {
10015                     ExcessivePower ew = mExcessivePower.get(i);
10016                     out.writeInt(ew.type);
10017                     out.writeLong(ew.overTime);
10018                     out.writeLong(ew.usedTime);
10019                 }
10020             }
10021 
readExcessivePowerFromParcelLocked(Parcel in)10022             void readExcessivePowerFromParcelLocked(Parcel in) {
10023                 final int N = in.readInt();
10024                 if (N == 0) {
10025                     mExcessivePower = null;
10026                     return;
10027                 }
10028 
10029                 if (N > 10000) {
10030                     throw new ParcelFormatException(
10031                             "File corrupt: too many excessive power entries " + N);
10032                 }
10033 
10034                 mExcessivePower = new ArrayList<>();
10035                 for (int i=0; i<N; i++) {
10036                     ExcessivePower ew = new ExcessivePower();
10037                     ew.type = in.readInt();
10038                     ew.overTime = in.readLong();
10039                     ew.usedTime = in.readLong();
10040                     mExcessivePower.add(ew);
10041                 }
10042             }
10043 
writeToParcelLocked(Parcel out)10044             void writeToParcelLocked(Parcel out) {
10045                 out.writeLong(mUserTimeMs);
10046                 out.writeLong(mSystemTimeMs);
10047                 out.writeLong(mForegroundTimeMs);
10048                 out.writeInt(mStarts);
10049                 out.writeInt(mNumCrashes);
10050                 out.writeInt(mNumAnrs);
10051                 writeExcessivePowerToParcelLocked(out);
10052             }
10053 
readFromParcelLocked(Parcel in)10054             void readFromParcelLocked(Parcel in) {
10055                 mUserTimeMs = in.readLong();
10056                 mSystemTimeMs = in.readLong();
10057                 mForegroundTimeMs = in.readLong();
10058                 mStarts = in.readInt();
10059                 mNumCrashes = in.readInt();
10060                 mNumAnrs = in.readInt();
10061                 readExcessivePowerFromParcelLocked(in);
10062             }
10063 
addCpuTimeLocked(int utimeMs, int stimeMs)10064             public void addCpuTimeLocked(int utimeMs, int stimeMs) {
10065                 addCpuTimeLocked(utimeMs, stimeMs, mBsi.mOnBatteryTimeBase.isRunning());
10066             }
10067 
addCpuTimeLocked(int utimeMs, int stimeMs, boolean isRunning)10068             public void addCpuTimeLocked(int utimeMs, int stimeMs, boolean isRunning) {
10069                 if (isRunning) {
10070                     mUserTimeMs += utimeMs;
10071                     mSystemTimeMs += stimeMs;
10072                 }
10073             }
10074 
addForegroundTimeLocked(long ttimeMs)10075             public void addForegroundTimeLocked(long ttimeMs) {
10076                 mForegroundTimeMs += ttimeMs;
10077             }
10078 
incStartsLocked()10079             public void incStartsLocked() {
10080                 mStarts++;
10081             }
10082 
incNumCrashesLocked()10083             public void incNumCrashesLocked() {
10084                 mNumCrashes++;
10085             }
10086 
incNumAnrsLocked()10087             public void incNumAnrsLocked() {
10088                 mNumAnrs++;
10089             }
10090 
10091             @Override
isActive()10092             public boolean isActive() {
10093                 return mActive;
10094             }
10095 
10096             @Override
getUserTime(int which)10097             public long getUserTime(int which) {
10098                 return mUserTimeMs;
10099             }
10100 
10101             @Override
getSystemTime(int which)10102             public long getSystemTime(int which) {
10103                 return mSystemTimeMs;
10104             }
10105 
10106             @Override
getForegroundTime(int which)10107             public long getForegroundTime(int which) {
10108                 return mForegroundTimeMs;
10109             }
10110 
10111             @Override
getStarts(int which)10112             public int getStarts(int which) {
10113                 return mStarts;
10114             }
10115 
10116             @Override
getNumCrashes(int which)10117             public int getNumCrashes(int which) {
10118                 return mNumCrashes;
10119             }
10120 
10121             @Override
getNumAnrs(int which)10122             public int getNumAnrs(int which) {
10123                 return mNumAnrs;
10124             }
10125         }
10126 
10127         /**
10128          * The statistics associated with a particular package.
10129          */
10130         public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
10131             /**
10132              * BatteryStatsImpl that we are associated with.
10133              */
10134             protected BatteryStatsImpl mBsi;
10135 
10136             /**
10137              * Number of times wakeup alarms have occurred for this app.
10138              * On screen-off timebase starting in report v25.
10139              */
10140             ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
10141 
10142             /**
10143              * The statics we have collected for this package's services.
10144              */
10145             final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
10146 
Pkg(BatteryStatsImpl bsi)10147             public Pkg(BatteryStatsImpl bsi) {
10148                 mBsi = bsi;
10149                 mBsi.mOnBatteryScreenOffTimeBase.add(this);
10150             }
10151 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10152             public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
10153                     long baseRealtimeUs) {
10154             }
10155 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10156             public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
10157                     long baseRealtimeUs) {
10158             }
10159 
10160             @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)10161             public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
10162                 if (detachIfReset) {
10163                     this.detach();
10164                 }
10165                 return true;
10166             }
10167 
10168             @Override
detach()10169             public void detach() {
10170                 mBsi.mOnBatteryScreenOffTimeBase.remove(this);
10171                 for (int j = mWakeupAlarms.size() - 1; j >= 0; j--) {
10172                     detachIfNotNull(mWakeupAlarms.valueAt(j));
10173                 }
10174                 for (int j = mServiceStats.size() - 1; j >= 0; j--) {
10175                     detachIfNotNull(mServiceStats.valueAt(j));
10176                 }
10177             }
10178 
readFromParcelLocked(Parcel in)10179             void readFromParcelLocked(Parcel in) {
10180                 int numWA = in.readInt();
10181                 mWakeupAlarms.clear();
10182                 for (int i=0; i<numWA; i++) {
10183                     String tag = in.readString();
10184                     mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryScreenOffTimeBase, in));
10185                 }
10186 
10187                 int numServs = in.readInt();
10188                 mServiceStats.clear();
10189                 for (int m = 0; m < numServs; m++) {
10190                     String serviceName = in.readString();
10191                     Uid.Pkg.Serv serv = new Serv(mBsi);
10192                     mServiceStats.put(serviceName, serv);
10193 
10194                     serv.readFromParcelLocked(in);
10195                 }
10196             }
10197 
writeToParcelLocked(Parcel out)10198             void writeToParcelLocked(Parcel out) {
10199                 int numWA = mWakeupAlarms.size();
10200                 out.writeInt(numWA);
10201                 for (int i=0; i<numWA; i++) {
10202                     out.writeString(mWakeupAlarms.keyAt(i));
10203                     mWakeupAlarms.valueAt(i).writeToParcel(out);
10204                 }
10205 
10206                 final int NS = mServiceStats.size();
10207                 out.writeInt(NS);
10208                 for (int i=0; i<NS; i++) {
10209                     out.writeString(mServiceStats.keyAt(i));
10210                     Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
10211                     serv.writeToParcelLocked(out);
10212                 }
10213             }
10214 
10215             @Override
getWakeupAlarmStats()10216             public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
10217                 return mWakeupAlarms;
10218             }
10219 
noteWakeupAlarmLocked(String tag)10220             public void noteWakeupAlarmLocked(String tag) {
10221                 Counter c = mWakeupAlarms.get(tag);
10222                 if (c == null) {
10223                     c = new Counter(mBsi.mOnBatteryScreenOffTimeBase);
10224                     mWakeupAlarms.put(tag, c);
10225                 }
10226                 c.stepAtomic();
10227             }
10228 
10229             @Override
getServiceStats()10230             public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
10231                 return mServiceStats;
10232             }
10233 
10234             /**
10235              * The statistics associated with a particular service.
10236              */
10237             public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
10238                 /**
10239                  * BatteryStatsImpl that we are associated with.
10240                  */
10241                 protected BatteryStatsImpl mBsi;
10242 
10243                 /**
10244                  * The android package in which this service resides.
10245                  */
10246                 protected Pkg mPkg;
10247 
10248                 /**
10249                  * Total time (ms in battery uptime) the service has been left started.
10250                  */
10251                 protected long mStartTimeMs;
10252 
10253                 /**
10254                  * If service has been started and not yet stopped, this is
10255                  * when it was started.
10256                  */
10257                 protected long mRunningSinceMs;
10258 
10259                 /**
10260                  * True if we are currently running.
10261                  */
10262                 protected boolean mRunning;
10263 
10264                 /**
10265                  * Total number of times startService() has been called.
10266                  */
10267                 protected int mStarts;
10268 
10269                 /**
10270                  * Total time (ms in battery uptime) the service has been left launched.
10271                  */
10272                 protected long mLaunchedTimeMs;
10273 
10274                 /**
10275                  * If service has been launched and not yet exited, this is
10276                  * when it was launched (ms in battery uptime).
10277                  */
10278                 protected long mLaunchedSinceMs;
10279 
10280                 /**
10281                  * True if we are currently launched.
10282                  */
10283                 protected boolean mLaunched;
10284 
10285                 /**
10286                  * Total number times the service has been launched.
10287                  */
10288                 protected int mLaunches;
10289 
10290                 /**
10291                  * Construct a Serv. Also adds it to the on-battery time base as a listener.
10292                  */
Serv(BatteryStatsImpl bsi)10293                 public Serv(BatteryStatsImpl bsi) {
10294                     mBsi = bsi;
10295                     mBsi.mOnBatteryTimeBase.add(this);
10296                 }
10297 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10298                 public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
10299                         long baseRealtimeUs) {
10300                 }
10301 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10302                 public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
10303                         long baseRealtimeUs) {
10304                 }
10305 
10306                 @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)10307                 public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
10308                     if (detachIfReset) {
10309                         this.detach();
10310                     }
10311                     return true;
10312                 }
10313 
10314                 /**
10315                  * Remove this Serv as a listener from the time base.
10316                  Ms*/
10317                 @Override
detach()10318                 public void detach() {
10319                     mBsi.mOnBatteryTimeBase.remove(this);
10320                 }
10321 
readFromParcelLocked(Parcel in)10322                 public void readFromParcelLocked(Parcel in) {
10323                     mStartTimeMs = in.readLong();
10324                     mRunningSinceMs = in.readLong();
10325                     mRunning = in.readInt() != 0;
10326                     mStarts = in.readInt();
10327                     mLaunchedTimeMs = in.readLong();
10328                     mLaunchedSinceMs = in.readLong();
10329                     mLaunched = in.readInt() != 0;
10330                     mLaunches = in.readInt();
10331                 }
10332 
writeToParcelLocked(Parcel out)10333                 public void writeToParcelLocked(Parcel out) {
10334                     out.writeLong(mStartTimeMs);
10335                     out.writeLong(mRunningSinceMs);
10336                     out.writeInt(mRunning ? 1 : 0);
10337                     out.writeInt(mStarts);
10338                     out.writeLong(mLaunchedTimeMs);
10339                     out.writeLong(mLaunchedSinceMs);
10340                     out.writeInt(mLaunched ? 1 : 0);
10341                     out.writeInt(mLaunches);
10342                 }
10343 
getLaunchTimeToNowLocked(long batteryUptimeMs)10344                 public long getLaunchTimeToNowLocked(long batteryUptimeMs) {
10345                     if (!mLaunched) return mLaunchedTimeMs;
10346                     return mLaunchedTimeMs + batteryUptimeMs - mLaunchedSinceMs;
10347                 }
10348 
getStartTimeToNowLocked(long batteryUptimeMs)10349                 public long getStartTimeToNowLocked(long batteryUptimeMs) {
10350                     if (!mRunning) return mStartTimeMs;
10351                     return mStartTimeMs + batteryUptimeMs - mRunningSinceMs;
10352                 }
10353 
startLaunchedLocked()10354                 public void startLaunchedLocked() {
10355                     startLaunchedLocked(mBsi.mClock.uptimeMillis());
10356                 }
10357 
startLaunchedLocked(long uptimeMs)10358                 public void startLaunchedLocked(long uptimeMs) {
10359                     if (!mLaunched) {
10360                         mLaunches++;
10361                         mLaunchedSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000;
10362                         mLaunched = true;
10363                     }
10364                 }
10365 
stopLaunchedLocked()10366                 public void stopLaunchedLocked() {
10367                     stopLaunchedLocked(mBsi.mClock.uptimeMillis());
10368                 }
10369 
stopLaunchedLocked(long uptimeMs)10370                 public void stopLaunchedLocked(long uptimeMs) {
10371                     if (mLaunched) {
10372                         long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000
10373                                 - mLaunchedSinceMs;
10374                         if (timeMs > 0) {
10375                             mLaunchedTimeMs += timeMs;
10376                         } else {
10377                             mLaunches--;
10378                         }
10379                         mLaunched = false;
10380                     }
10381                 }
10382 
startRunningLocked()10383                 public void startRunningLocked() {
10384                     startRunningLocked(mBsi.mClock.uptimeMillis());
10385                 }
10386 
startRunningLocked(long uptimeMs)10387                 public void startRunningLocked(long uptimeMs) {
10388                     if (!mRunning) {
10389                         mStarts++;
10390                         mRunningSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000;
10391                         mRunning = true;
10392                     }
10393                 }
10394 
stopRunningLocked()10395                 public void stopRunningLocked() {
10396                     stopRunningLocked(mBsi.mClock.uptimeMillis());
10397                 }
10398 
stopRunningLocked(long uptimeMs)10399                 public void stopRunningLocked(long uptimeMs) {
10400                     if (mRunning) {
10401                         long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000
10402                                 - mRunningSinceMs;
10403                         if (timeMs > 0) {
10404                             mStartTimeMs += timeMs;
10405                         } else {
10406                             mStarts--;
10407                         }
10408                         mRunning = false;
10409                     }
10410                 }
10411 
getBatteryStats()10412                 public BatteryStatsImpl getBatteryStats() {
10413                     return mBsi;
10414                 }
10415 
10416                 @Override
getLaunches(int which)10417                 public int getLaunches(int which) {
10418                     return mLaunches;
10419                 }
10420 
10421                 @Override
getStartTime(long now, int which)10422                 public long getStartTime(long now, int which) {
10423                     return getStartTimeToNowLocked(now);
10424                 }
10425 
10426                 @Override
getStarts(int which)10427                 public int getStarts(int which) {
10428                     return mStarts;
10429                 }
10430             }
10431 
newServiceStatsLocked()10432             final Serv newServiceStatsLocked() {
10433                 return new Serv(mBsi);
10434             }
10435         }
10436 
10437         private class ChildUid {
10438             public final TimeMultiStateCounter cpuActiveCounter;
10439             public final LongArrayMultiStateCounter cpuTimeInFreqCounter;
10440 
ChildUid()10441             ChildUid() {
10442                 final long timestampMs = mBsi.mClock.elapsedRealtime();
10443                 cpuActiveCounter =
10444                         new TimeMultiStateCounter(mBsi.mOnBatteryTimeBase, 1, timestampMs);
10445                 cpuActiveCounter.setState(0, timestampMs);
10446 
10447                 if (mBsi.trackPerProcStateCpuTimes()) {
10448                     final int cpuFreqCount = mBsi.getCpuFreqCount();
10449 
10450                     cpuTimeInFreqCounter = new LongArrayMultiStateCounter(1, cpuFreqCount);
10451 
10452                     // Set initial values to all 0. This is a child UID and we want to include
10453                     // the entirety of its CPU time-in-freq stats into the parent's stats.
10454                     cpuTimeInFreqCounter.updateValues(
10455                             new LongArrayMultiStateCounter.LongArrayContainer(cpuFreqCount),
10456                             timestampMs);
10457                 } else {
10458                     cpuTimeInFreqCounter = null;
10459                 }
10460             }
10461         }
10462 
10463         /**
10464          * Retrieve the statistics object for a particular process, creating
10465          * if needed.
10466          */
getProcessStatsLocked(String name)10467         public Proc getProcessStatsLocked(String name) {
10468             Proc ps = mProcessStats.get(name);
10469             if (ps == null) {
10470                 ps = new Proc(mBsi, name);
10471                 mProcessStats.put(name, ps);
10472             }
10473 
10474             return ps;
10475         }
10476 
10477         @GuardedBy("mBsi")
updateUidProcessStateLocked(int procState, long elapsedRealtimeMs, long uptimeMs)10478         public void updateUidProcessStateLocked(int procState,
10479                 long elapsedRealtimeMs, long uptimeMs) {
10480             int uidRunningState;
10481             // Make special note of Foreground Services
10482             final boolean userAwareService =
10483                     (ActivityManager.isForegroundService(procState));
10484             uidRunningState = BatteryStats.mapToInternalProcessState(procState);
10485 
10486             if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
10487                 return;
10488             }
10489 
10490             if (mProcessState != uidRunningState) {
10491                 if (mProcessState != Uid.PROCESS_STATE_NONEXISTENT) {
10492                     mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
10493                 }
10494                 if (uidRunningState != Uid.PROCESS_STATE_NONEXISTENT) {
10495                     if (mProcessStateTimer[uidRunningState] == null) {
10496                         makeProcessState(uidRunningState, null);
10497                     }
10498                     mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
10499                 }
10500 
10501                 if (mBsi.trackPerProcStateCpuTimes()) {
10502                     mBsi.updateProcStateCpuTimesLocked(mUid, elapsedRealtimeMs, uptimeMs);
10503 
10504                     LongArrayMultiStateCounter onBatteryCounter =
10505                             getProcStateTimeCounter(elapsedRealtimeMs).getCounter();
10506                     LongArrayMultiStateCounter onBatteryScreenOffCounter =
10507                             getProcStateScreenOffTimeCounter(elapsedRealtimeMs).getCounter();
10508 
10509                     onBatteryCounter.setState(uidRunningState, elapsedRealtimeMs);
10510                     onBatteryScreenOffCounter.setState(uidRunningState, elapsedRealtimeMs);
10511                 }
10512 
10513                 final int prevBatteryConsumerProcessState =
10514                         mapUidProcessStateToBatteryConsumerProcessState(mProcessState);
10515 
10516                 mProcessState = uidRunningState;
10517 
10518                 updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
10519                 updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
10520 
10521                 final int batteryConsumerProcessState =
10522                         mapUidProcessStateToBatteryConsumerProcessState(uidRunningState);
10523                 getCpuActiveTimeCounter().setState(batteryConsumerProcessState, elapsedRealtimeMs);
10524 
10525                 getMobileRadioActiveTimeCounter()
10526                         .setState(batteryConsumerProcessState, elapsedRealtimeMs);
10527 
10528                 final ControllerActivityCounterImpl wifiControllerActivity =
10529                         getWifiControllerActivity();
10530                 if (wifiControllerActivity != null) {
10531                     wifiControllerActivity.setState(batteryConsumerProcessState, elapsedRealtimeMs);
10532                 }
10533 
10534                 final ControllerActivityCounterImpl bluetoothControllerActivity =
10535                         getBluetoothControllerActivity();
10536                 if (bluetoothControllerActivity != null) {
10537                     bluetoothControllerActivity.setState(batteryConsumerProcessState,
10538                             elapsedRealtimeMs);
10539                 }
10540 
10541                 final EnergyConsumerStats energyStats =
10542                         getOrCreateEnergyConsumerStatsIfSupportedLocked();
10543                 if (energyStats != null) {
10544                     energyStats.setState(batteryConsumerProcessState, elapsedRealtimeMs);
10545                 }
10546                 maybeScheduleExternalStatsSync(prevBatteryConsumerProcessState,
10547                         batteryConsumerProcessState);
10548             }
10549 
10550             if (userAwareService != mInForegroundService) {
10551                 if (userAwareService) {
10552                     noteForegroundServiceResumedLocked(elapsedRealtimeMs);
10553                 } else {
10554                     noteForegroundServicePausedLocked(elapsedRealtimeMs);
10555                 }
10556                 mInForegroundService = userAwareService;
10557             }
10558         }
10559 
10560         @GuardedBy("mBsi")
maybeScheduleExternalStatsSync( @atteryConsumer.ProcessState int oldProcessState, @BatteryConsumer.ProcessState int newProcessState)10561         private void maybeScheduleExternalStatsSync(
10562                 @BatteryConsumer.ProcessState int oldProcessState,
10563                 @BatteryConsumer.ProcessState int newProcessState) {
10564             if (oldProcessState == newProcessState) {
10565                 return;
10566             }
10567             // Transitions between BACKGROUND and such non-foreground states like cached
10568             // or nonexistent do not warrant doing a sync.  If some of the stats for those
10569             // proc states bleed into the PROCESS_STATE_BACKGROUND, that's ok.
10570             if ((oldProcessState == BatteryConsumer.PROCESS_STATE_UNSPECIFIED
10571                     && newProcessState == BatteryConsumer.PROCESS_STATE_BACKGROUND)
10572                     || (oldProcessState == BatteryConsumer.PROCESS_STATE_BACKGROUND
10573                     && newProcessState == BatteryConsumer.PROCESS_STATE_UNSPECIFIED)) {
10574                 return;
10575             }
10576 
10577             int flags = ExternalStatsSync.UPDATE_ON_PROC_STATE_CHANGE;
10578             // Skip querying for inactive radio, where power usage is probably negligible.
10579             if (!BatteryStatsImpl.isActiveRadioPowerState(mBsi.mMobileRadioPowerState)) {
10580                 flags &= ~ExternalStatsSync.UPDATE_RADIO;
10581             }
10582 
10583             mBsi.mExternalSync.scheduleSyncDueToProcessStateChange(flags,
10584                     mBsi.mConstants.PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
10585         }
10586 
10587         /** Whether to consider Uid to be in the background for background timebase purposes. */
isInBackground()10588         public boolean isInBackground() {
10589             // Note that PROCESS_STATE_CACHED and Uid.PROCESS_STATE_NONEXISTENT is
10590             // also considered to be 'background' for our purposes, because it's not foreground.
10591             return mProcessState >= PROCESS_STATE_BACKGROUND;
10592         }
10593 
updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs)10594         public boolean updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs) {
10595             boolean on = mBsi.mOnBatteryTimeBase.isRunning() && isInBackground();
10596             return mOnBatteryBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
10597         }
10598 
updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs)10599         public boolean updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs) {
10600             boolean on = mBsi.mOnBatteryScreenOffTimeBase.isRunning() && isInBackground();
10601             return mOnBatteryScreenOffBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
10602         }
10603 
getPidStats()10604         public SparseArray<? extends Pid> getPidStats() {
10605             return mPids;
10606         }
10607 
getPidStatsLocked(int pid)10608         public Pid getPidStatsLocked(int pid) {
10609             Pid p = mPids.get(pid);
10610             if (p == null) {
10611                 p = new Pid();
10612                 mPids.put(pid, p);
10613             }
10614             return p;
10615         }
10616 
10617         /**
10618          * Retrieve the statistics object for a particular service, creating
10619          * if needed.
10620          */
getPackageStatsLocked(String name)10621         public Pkg getPackageStatsLocked(String name) {
10622             Pkg ps = mPackageStats.get(name);
10623             if (ps == null) {
10624                 ps = new Pkg(mBsi);
10625                 mPackageStats.put(name, ps);
10626             }
10627 
10628             return ps;
10629         }
10630 
10631         /**
10632          * Retrieve the statistics object for a particular service, creating
10633          * if needed.
10634          */
getServiceStatsLocked(String pkg, String serv)10635         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
10636             Pkg ps = getPackageStatsLocked(pkg);
10637             Pkg.Serv ss = ps.mServiceStats.get(serv);
10638             if (ss == null) {
10639                 ss = ps.newServiceStatsLocked();
10640                 ps.mServiceStats.put(serv, ss);
10641             }
10642 
10643             return ss;
10644         }
10645 
readSyncSummaryFromParcelLocked(String name, Parcel in)10646         public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
10647             DualTimer timer = mSyncStats.instantiateObject();
10648             timer.readSummaryFromParcelLocked(in);
10649             mSyncStats.add(name, timer);
10650         }
10651 
readJobSummaryFromParcelLocked(String name, Parcel in)10652         public void readJobSummaryFromParcelLocked(String name, Parcel in) {
10653             DualTimer timer = mJobStats.instantiateObject();
10654             timer.readSummaryFromParcelLocked(in);
10655             mJobStats.add(name, timer);
10656         }
10657 
readWakeSummaryFromParcelLocked(String wlName, Parcel in)10658         public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
10659             Wakelock wl = new Wakelock(mBsi, this);
10660             mWakelockStats.add(wlName, wl);
10661             if (in.readInt() != 0) {
10662                 getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
10663             }
10664             if (in.readInt() != 0) {
10665                 getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
10666             }
10667             if (in.readInt() != 0) {
10668                 getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
10669             }
10670             if (in.readInt() != 0) {
10671                 getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
10672             }
10673         }
10674 
getSensorTimerLocked(int sensor, boolean create)10675         public DualTimer getSensorTimerLocked(int sensor, boolean create) {
10676             Sensor se = mSensorStats.get(sensor);
10677             if (se == null) {
10678                 if (!create) {
10679                     return null;
10680                 }
10681                 se = new Sensor(mBsi, this, sensor);
10682                 mSensorStats.put(sensor, se);
10683             }
10684             DualTimer t = se.mTimer;
10685             if (t != null) {
10686                 return t;
10687             }
10688             ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
10689             if (timers == null) {
10690                 timers = new ArrayList<StopwatchTimer>();
10691                 mBsi.mSensorTimers.put(sensor, timers);
10692             }
10693             t = new DualTimer(mBsi.mClock, this, BatteryStats.SENSOR, timers,
10694                     mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
10695             se.mTimer = t;
10696             return t;
10697         }
10698 
noteStartSyncLocked(String name, long elapsedRealtimeMs)10699         public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
10700             DualTimer t = mSyncStats.startObject(name, elapsedRealtimeMs);
10701             if (t != null) {
10702                 t.startRunningLocked(elapsedRealtimeMs);
10703             }
10704         }
10705 
noteStopSyncLocked(String name, long elapsedRealtimeMs)10706         public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
10707             DualTimer t = mSyncStats.stopObject(name, elapsedRealtimeMs);
10708             if (t != null) {
10709                 t.stopRunningLocked(elapsedRealtimeMs);
10710             }
10711         }
10712 
noteStartJobLocked(String name, long elapsedRealtimeMs)10713         public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
10714             DualTimer t = mJobStats.startObject(name, elapsedRealtimeMs);
10715             if (t != null) {
10716                 t.startRunningLocked(elapsedRealtimeMs);
10717             }
10718         }
10719 
noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason)10720         public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
10721             DualTimer t = mJobStats.stopObject(name, elapsedRealtimeMs);
10722             if (t != null) {
10723                 t.stopRunningLocked(elapsedRealtimeMs);
10724             }
10725             if (mBsi.mOnBatteryTimeBase.isRunning()) {
10726                 SparseIntArray types = mJobCompletions.get(name);
10727                 if (types == null) {
10728                     types = new SparseIntArray();
10729                     mJobCompletions.put(name, types);
10730                 }
10731                 int last = types.get(stopReason, 0);
10732                 types.put(stopReason, last + 1);
10733             }
10734         }
10735 
getWakelockTimerLocked(Wakelock wl, int type)10736         public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
10737             if (wl == null) {
10738                 return null;
10739             }
10740             switch (type) {
10741                 case WAKE_TYPE_PARTIAL: {
10742                     DualTimer t = wl.mTimerPartial;
10743                     if (t == null) {
10744                         t = new DualTimer(mBsi.mClock, this, WAKE_TYPE_PARTIAL,
10745                                 mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase,
10746                                 mOnBatteryScreenOffBackgroundTimeBase);
10747                         wl.mTimerPartial = t;
10748                     }
10749                     return t;
10750                 }
10751                 case WAKE_TYPE_FULL: {
10752                     StopwatchTimer t = wl.mTimerFull;
10753                     if (t == null) {
10754                         t = new StopwatchTimer(mBsi.mClock, this, WAKE_TYPE_FULL,
10755                                 mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
10756                         wl.mTimerFull = t;
10757                     }
10758                     return t;
10759                 }
10760                 case WAKE_TYPE_WINDOW: {
10761                     StopwatchTimer t = wl.mTimerWindow;
10762                     if (t == null) {
10763                         t = new StopwatchTimer(mBsi.mClock, this, WAKE_TYPE_WINDOW,
10764                                 mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
10765                         wl.mTimerWindow = t;
10766                     }
10767                     return t;
10768                 }
10769                 case WAKE_TYPE_DRAW: {
10770                     StopwatchTimer t = wl.mTimerDraw;
10771                     if (t == null) {
10772                         t = new StopwatchTimer(mBsi.mClock, this, WAKE_TYPE_DRAW,
10773                                 mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
10774                         wl.mTimerDraw = t;
10775                     }
10776                     return t;
10777                 }
10778                 default:
10779                     throw new IllegalArgumentException("type=" + type);
10780             }
10781         }
10782 
noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)10783         public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
10784             Wakelock wl = mWakelockStats.startObject(name, elapsedRealtimeMs);
10785             if (wl != null) {
10786                 getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
10787             }
10788             if (type == WAKE_TYPE_PARTIAL) {
10789                 createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
10790                 if (pid >= 0) {
10791                     Pid p = getPidStatsLocked(pid);
10792                     if (p.mWakeNesting++ == 0) {
10793                         p.mWakeStartMs = elapsedRealtimeMs;
10794                     }
10795                 }
10796             }
10797         }
10798 
noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)10799         public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
10800             Wakelock wl = mWakelockStats.stopObject(name, elapsedRealtimeMs);
10801             if (wl != null) {
10802                 StopwatchTimer wlt = getWakelockTimerLocked(wl, type);
10803                 wlt.stopRunningLocked(elapsedRealtimeMs);
10804             }
10805             if (type == WAKE_TYPE_PARTIAL) {
10806                 if (mAggregatedPartialWakelockTimer != null) {
10807                     mAggregatedPartialWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
10808                 }
10809                 if (pid >= 0) {
10810                     Pid p = mPids.get(pid);
10811                     if (p != null && p.mWakeNesting > 0) {
10812                         if (p.mWakeNesting-- == 1) {
10813                             p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
10814                             p.mWakeStartMs = 0;
10815                         }
10816                     }
10817                 }
10818             }
10819         }
10820 
reportExcessiveCpuLocked(String proc, long overTimeMs, long usedTimeMs)10821         public void reportExcessiveCpuLocked(String proc, long overTimeMs, long usedTimeMs) {
10822             Proc p = getProcessStatsLocked(proc);
10823             if (p != null) {
10824                 p.addExcessiveCpu(overTimeMs, usedTimeMs);
10825             }
10826         }
10827 
noteStartSensor(int sensor, long elapsedRealtimeMs)10828         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
10829             DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
10830             t.startRunningLocked(elapsedRealtimeMs);
10831         }
10832 
noteStopSensor(int sensor, long elapsedRealtimeMs)10833         public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
10834             // Don't create a timer if one doesn't already exist
10835             DualTimer t = getSensorTimerLocked(sensor, false);
10836             if (t != null) {
10837                 t.stopRunningLocked(elapsedRealtimeMs);
10838             }
10839         }
10840 
noteStartGps(long elapsedRealtimeMs)10841         public void noteStartGps(long elapsedRealtimeMs) {
10842             noteStartSensor(Sensor.GPS, elapsedRealtimeMs);
10843         }
10844 
noteStopGps(long elapsedRealtimeMs)10845         public void noteStopGps(long elapsedRealtimeMs) {
10846             noteStopSensor(Sensor.GPS, elapsedRealtimeMs);
10847         }
10848     }
10849 
10850     @GuardedBy("this")
10851     @Override
getCpuFreqs()10852     public long[] getCpuFreqs() {
10853         if (!mCpuFreqsInitialized) {
10854             mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
10855             mCpuFreqsInitialized = true;
10856         }
10857         return mCpuFreqs;
10858     }
10859 
10860     @GuardedBy("this")
10861     @Override
getCpuFreqCount()10862     public int getCpuFreqCount() {
10863         final long[] cpuFreqs = getCpuFreqs();
10864         return cpuFreqs != null ? cpuFreqs.length : 0;
10865     }
10866 
10867     @GuardedBy("this")
getCpuTimeInFreqContainer()10868     private LongArrayMultiStateCounter.LongArrayContainer getCpuTimeInFreqContainer() {
10869         if (mTmpCpuTimeInFreq == null) {
10870             mTmpCpuTimeInFreq =
10871                     new LongArrayMultiStateCounter.LongArrayContainer(getCpuFreqCount());
10872         }
10873         return mTmpCpuTimeInFreq;
10874     }
10875 
BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb, EnergyStatsRetriever energyStatsCb, UserInfoProvider userInfoProvider)10876     public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
10877             EnergyStatsRetriever energyStatsCb, UserInfoProvider userInfoProvider) {
10878         this(Clock.SYSTEM_CLOCK, systemDir, handler, cb, energyStatsCb, userInfoProvider);
10879     }
10880 
BatteryStatsImpl(Clock clock, File systemDir, Handler handler, PlatformIdleStateCallback cb, EnergyStatsRetriever energyStatsCb, UserInfoProvider userInfoProvider)10881     private BatteryStatsImpl(Clock clock, File systemDir, Handler handler,
10882             PlatformIdleStateCallback cb, EnergyStatsRetriever energyStatsCb,
10883             UserInfoProvider userInfoProvider) {
10884         init(clock);
10885 
10886         mHandler = new MyHandler(handler.getLooper());
10887         mConstants = new Constants(mHandler);
10888 
10889         if (systemDir == null) {
10890             mStatsFile = null;
10891             mCheckinFile = null;
10892             mDailyFile = null;
10893             mHistory = new BatteryStatsHistory(mConstants.MAX_HISTORY_FILES,
10894                     mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock);
10895         } else {
10896             mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
10897             mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
10898             mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
10899             mHistory = new BatteryStatsHistory(systemDir, mConstants.MAX_HISTORY_FILES,
10900                     mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock);
10901         }
10902         mStartCount++;
10903         initTimersAndCounters();
10904         mOnBattery = mOnBatteryInternal = false;
10905         long uptimeUs = mClock.uptimeMillis() * 1000;
10906         long realtimeUs = mClock.elapsedRealtime() * 1000;
10907         initTimes(uptimeUs, realtimeUs);
10908         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
10909         initDischarge(realtimeUs);
10910         updateDailyDeadlineLocked();
10911         mPlatformIdleStateCallback = cb;
10912         mEnergyConsumerRetriever = energyStatsCb;
10913         mUserInfoProvider = userInfoProvider;
10914 
10915         // Notify statsd that the system is initially not in doze.
10916         mDeviceIdleMode = DEVICE_IDLE_MODE_OFF;
10917         FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mDeviceIdleMode);
10918     }
10919 
10920     @VisibleForTesting
initTimersAndCounters()10921     protected void initTimersAndCounters() {
10922         mScreenOnTimer = new StopwatchTimer(mClock, null, -1, null, mOnBatteryTimeBase);
10923         mScreenDozeTimer = new StopwatchTimer(mClock, null, -1, null, mOnBatteryTimeBase);
10924         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10925             mScreenBrightnessTimer[i] = new StopwatchTimer(mClock, null, -100 - i, null,
10926                     mOnBatteryTimeBase);
10927         }
10928 
10929         mPerDisplayBatteryStats = new DisplayBatteryStats[1];
10930         mPerDisplayBatteryStats[0] = new DisplayBatteryStats(mClock, mOnBatteryTimeBase);
10931 
10932         mInteractiveTimer = new StopwatchTimer(mClock, null, -10, null, mOnBatteryTimeBase);
10933         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClock, null, -2, null,
10934                 mOnBatteryTimeBase);
10935         mDeviceIdleModeLightTimer = new StopwatchTimer(mClock, null, -11, null,
10936                 mOnBatteryTimeBase);
10937         mDeviceIdleModeFullTimer = new StopwatchTimer(mClock, null, -14, null, mOnBatteryTimeBase);
10938         mDeviceLightIdlingTimer = new StopwatchTimer(mClock, null, -15, null, mOnBatteryTimeBase);
10939         mDeviceIdlingTimer = new StopwatchTimer(mClock, null, -12, null, mOnBatteryTimeBase);
10940         mPhoneOnTimer = new StopwatchTimer(mClock, null, -3, null, mOnBatteryTimeBase);
10941         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
10942             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClock, null, -200 - i, null,
10943                     mOnBatteryTimeBase);
10944         }
10945         mPhoneSignalScanningTimer = new StopwatchTimer(mClock, null, -200 + 1, null,
10946                 mOnBatteryTimeBase);
10947         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10948             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClock, null, -300 - i, null,
10949                     mOnBatteryTimeBase);
10950         }
10951         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10952             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
10953             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
10954         }
10955         mWifiActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
10956                 NUM_WIFI_TX_LEVELS);
10957         mBluetoothActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
10958                 NUM_BT_TX_LEVELS);
10959         mModemActivity = new ControllerActivityCounterImpl(mClock, mOnBatteryTimeBase,
10960                 ModemActivityInfo.getNumTxPowerLevels());
10961         mMobileRadioActiveTimer = new StopwatchTimer(mClock, null, -400, null, mOnBatteryTimeBase);
10962         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClock, null, -401, null,
10963                 mOnBatteryTimeBase);
10964         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
10965         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
10966         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
10967         mWifiMulticastWakelockTimer = new StopwatchTimer(mClock, null,
10968                 WIFI_AGGREGATE_MULTICAST_ENABLED, null, mOnBatteryTimeBase);
10969         mWifiOnTimer = new StopwatchTimer(mClock, null, -4, null, mOnBatteryTimeBase);
10970         mGlobalWifiRunningTimer = new StopwatchTimer(mClock, null, -5, null, mOnBatteryTimeBase);
10971         for (int i=0; i<NUM_WIFI_STATES; i++) {
10972             mWifiStateTimer[i] = new StopwatchTimer(mClock, null, -600 - i, null,
10973                     mOnBatteryTimeBase);
10974         }
10975         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10976             mWifiSupplStateTimer[i] = new StopwatchTimer(mClock, null, -700 - i, null,
10977                     mOnBatteryTimeBase);
10978         }
10979         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10980             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClock, null, -800 - i, null,
10981                     mOnBatteryTimeBase);
10982         }
10983         mWifiActiveTimer = new StopwatchTimer(mClock, null, -900, null, mOnBatteryTimeBase);
10984         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
10985             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClock, null, -1000 - i, null,
10986                     mOnBatteryTimeBase);
10987         }
10988         mAudioOnTimer = new StopwatchTimer(mClock, null, -7, null, mOnBatteryTimeBase);
10989         mVideoOnTimer = new StopwatchTimer(mClock, null, -8, null, mOnBatteryTimeBase);
10990         mFlashlightOnTimer = new StopwatchTimer(mClock, null, -9, null, mOnBatteryTimeBase);
10991         mCameraOnTimer = new StopwatchTimer(mClock, null, -13, null, mOnBatteryTimeBase);
10992         mBluetoothScanTimer = new StopwatchTimer(mClock, null, -14, null, mOnBatteryTimeBase);
10993         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
10994         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10995         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10996         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10997         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10998         mDischargeUnplugLevel = 0;
10999         mDischargePlugLevel = -1;
11000         mDischargeCurrentLevel = 0;
11001         mBatteryLevel = 0;
11002     }
11003 
11004     /**
11005      * Injects a power profile.
11006      */
11007     @GuardedBy("this")
setPowerProfileLocked(PowerProfile profile)11008     public void setPowerProfileLocked(PowerProfile profile) {
11009         mPowerProfile = profile;
11010 
11011         int totalSpeedStepCount = 0;
11012 
11013         // We need to initialize the KernelCpuSpeedReaders to read from
11014         // the first cpu of each core. Once we have the PowerProfile, we have access to this
11015         // information.
11016         final int numClusters = mPowerProfile.getNumCpuClusters();
11017         mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
11018         int firstCpuOfCluster = 0;
11019         for (int i = 0; i < numClusters; i++) {
11020             final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
11021             mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
11022                     numSpeedSteps);
11023             firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
11024             totalSpeedStepCount += numSpeedSteps;
11025         }
11026 
11027         // Initialize CPU power bracket map, which combines CPU states (cluster/freq pairs)
11028         // into a small number of brackets
11029         mCpuPowerBracketMap = new int[totalSpeedStepCount];
11030         int index = 0;
11031         int numCpuClusters = mPowerProfile.getNumCpuClusters();
11032         for (int cluster = 0; cluster < numCpuClusters; cluster++) {
11033             int steps = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
11034             for (int step = 0; step < steps; step++) {
11035                 mCpuPowerBracketMap[index++] =
11036                         mPowerProfile.getPowerBracketForCpuCore(cluster, step);
11037             }
11038         }
11039 
11040         int cpuPowerBracketCount = mPowerProfile.getCpuPowerBracketCount();
11041         mCpuUsageDetails.cpuBracketDescriptions = new String[cpuPowerBracketCount];
11042         mCpuUsageDetails.cpuUsageMs = new long[cpuPowerBracketCount];
11043         for (int i = 0; i < cpuPowerBracketCount; i++) {
11044             mCpuUsageDetails.cpuBracketDescriptions[i] =
11045                     mPowerProfile.getCpuPowerBracketDescription(i);
11046         }
11047 
11048         if (mEstimatedBatteryCapacityMah == -1) {
11049             // Initialize the estimated battery capacity to a known preset one.
11050             mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
11051         }
11052 
11053         setDisplayCountLocked(mPowerProfile.getNumDisplays());
11054     }
11055 
getPowerProfile()11056     PowerProfile getPowerProfile() {
11057         return mPowerProfile;
11058     }
11059 
11060     /**
11061      * Injects BatteryStatsConfig
11062      */
setBatteryStatsConfig(BatteryStatsConfig config)11063     public void setBatteryStatsConfig(BatteryStatsConfig config) {
11064         synchronized (this) {
11065             mBatteryStatsConfig = config;
11066         }
11067     }
11068 
11069     /**
11070      * Starts tracking CPU time-in-state for threads of the system server process,
11071      * keeping a separate account of threads receiving incoming binder calls.
11072      */
startTrackingSystemServerCpuTime()11073     public void startTrackingSystemServerCpuTime() {
11074         mSystemServerCpuThreadReader.startTrackingThreadCpuTime();
11075     }
11076 
getSystemServiceCpuThreadTimes()11077     public SystemServiceCpuThreadTimes getSystemServiceCpuThreadTimes() {
11078         return mSystemServerCpuThreadReader.readAbsolute();
11079     }
11080 
setCallback(BatteryCallback cb)11081     public void setCallback(BatteryCallback cb) {
11082         mCallback = cb;
11083     }
11084 
setRadioScanningTimeoutLocked(long timeoutUs)11085     public void setRadioScanningTimeoutLocked(long timeoutUs) {
11086         if (mPhoneSignalScanningTimer != null) {
11087             mPhoneSignalScanningTimer.setTimeout(timeoutUs);
11088         }
11089     }
11090 
setExternalStatsSyncLocked(ExternalStatsSync sync)11091     public void setExternalStatsSyncLocked(ExternalStatsSync sync) {
11092         mExternalSync = sync;
11093     }
11094 
11095     /**
11096      * Initialize and set multi display timers and states.
11097      */
setDisplayCountLocked(int numDisplays)11098     public void setDisplayCountLocked(int numDisplays) {
11099         mPerDisplayBatteryStats = new DisplayBatteryStats[numDisplays];
11100         for (int i = 0; i < numDisplays; i++) {
11101             mPerDisplayBatteryStats[i] = new DisplayBatteryStats(mClock, mOnBatteryTimeBase);
11102         }
11103     }
11104 
updateDailyDeadlineLocked()11105     public void updateDailyDeadlineLocked() {
11106         // Get the current time.
11107         long currentTimeMs = mDailyStartTimeMs = mClock.currentTimeMillis();
11108         Calendar calDeadline = Calendar.getInstance();
11109         calDeadline.setTimeInMillis(currentTimeMs);
11110 
11111         // Move time up to the next day, ranging from 1am to 3pm.
11112         calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
11113         calDeadline.set(Calendar.MILLISECOND, 0);
11114         calDeadline.set(Calendar.SECOND, 0);
11115         calDeadline.set(Calendar.MINUTE, 0);
11116         calDeadline.set(Calendar.HOUR_OF_DAY, 1);
11117         mNextMinDailyDeadlineMs = calDeadline.getTimeInMillis();
11118         calDeadline.set(Calendar.HOUR_OF_DAY, 3);
11119         mNextMaxDailyDeadlineMs = calDeadline.getTimeInMillis();
11120     }
11121 
recordDailyStatsIfNeededLocked(boolean settled, long currentTimeMs)11122     public void recordDailyStatsIfNeededLocked(boolean settled, long currentTimeMs) {
11123         if (currentTimeMs >= mNextMaxDailyDeadlineMs) {
11124             recordDailyStatsLocked();
11125         } else if (settled && currentTimeMs >= mNextMinDailyDeadlineMs) {
11126             recordDailyStatsLocked();
11127         } else if (currentTimeMs < (mDailyStartTimeMs - (1000 * 60 * 60 * 24))) {
11128             recordDailyStatsLocked();
11129         }
11130     }
11131 
recordDailyStatsLocked()11132     public void recordDailyStatsLocked() {
11133         DailyItem item = new DailyItem();
11134         item.mStartTime = mDailyStartTimeMs;
11135         item.mEndTime = mClock.currentTimeMillis();
11136         boolean hasData = false;
11137         if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
11138             hasData = true;
11139             item.mDischargeSteps = new LevelStepTracker(
11140                     mDailyDischargeStepTracker.mNumStepDurations,
11141                     mDailyDischargeStepTracker.mStepDurations);
11142         }
11143         if (mDailyChargeStepTracker.mNumStepDurations > 0) {
11144             hasData = true;
11145             item.mChargeSteps = new LevelStepTracker(
11146                     mDailyChargeStepTracker.mNumStepDurations,
11147                     mDailyChargeStepTracker.mStepDurations);
11148         }
11149         if (mDailyPackageChanges != null) {
11150             hasData = true;
11151             item.mPackageChanges = mDailyPackageChanges;
11152             mDailyPackageChanges = null;
11153         }
11154         mDailyDischargeStepTracker.init();
11155         mDailyChargeStepTracker.init();
11156         updateDailyDeadlineLocked();
11157 
11158         if (hasData) {
11159             final long startTimeMs = SystemClock.uptimeMillis();
11160             mDailyItems.add(item);
11161             while (mDailyItems.size() > MAX_DAILY_ITEMS) {
11162                 mDailyItems.remove(0);
11163             }
11164             final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
11165             try {
11166                 TypedXmlSerializer out = Xml.resolveSerializer(memStream);
11167                 writeDailyItemsLocked(out);
11168                 final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs;
11169                 BackgroundThread.getHandler().post(new Runnable() {
11170                     @Override
11171                     public void run() {
11172                         synchronized (mCheckinFile) {
11173                             final long startTimeMs2 = SystemClock.uptimeMillis();
11174                             FileOutputStream stream = null;
11175                             try {
11176                                 stream = mDailyFile.startWrite();
11177                                 memStream.writeTo(stream);
11178                                 stream.flush();
11179                                 mDailyFile.finishWrite(stream);
11180                                 com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
11181                                         "batterystats-daily",
11182                                         initialTimeMs + SystemClock.uptimeMillis() - startTimeMs2);
11183                             } catch (IOException e) {
11184                                 Slog.w("BatteryStats",
11185                                         "Error writing battery daily items", e);
11186                                 mDailyFile.failWrite(stream);
11187                             }
11188                         }
11189                     }
11190                 });
11191             } catch (IOException e) {
11192             }
11193         }
11194     }
11195 
writeDailyItemsLocked(TypedXmlSerializer out)11196     private void writeDailyItemsLocked(TypedXmlSerializer out) throws IOException {
11197         StringBuilder sb = new StringBuilder(64);
11198         out.startDocument(null, true);
11199         out.startTag(null, "daily-items");
11200         for (int i=0; i<mDailyItems.size(); i++) {
11201             final DailyItem dit = mDailyItems.get(i);
11202             out.startTag(null, "item");
11203             out.attributeLong(null, "start", dit.mStartTime);
11204             out.attributeLong(null, "end", dit.mEndTime);
11205             writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
11206             writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
11207             if (dit.mPackageChanges != null) {
11208                 for (int j=0; j<dit.mPackageChanges.size(); j++) {
11209                     PackageChange pc = dit.mPackageChanges.get(j);
11210                     if (pc.mUpdate) {
11211                         out.startTag(null, "upd");
11212                         out.attribute(null, "pkg", pc.mPackageName);
11213                         out.attributeLong(null, "ver", pc.mVersionCode);
11214                         out.endTag(null, "upd");
11215                     } else {
11216                         out.startTag(null, "rem");
11217                         out.attribute(null, "pkg", pc.mPackageName);
11218                         out.endTag(null, "rem");
11219                     }
11220                 }
11221             }
11222             out.endTag(null, "item");
11223         }
11224         out.endTag(null, "daily-items");
11225         out.endDocument();
11226     }
11227 
writeDailyLevelSteps(TypedXmlSerializer out, String tag, LevelStepTracker steps, StringBuilder tmpBuilder)11228     private void writeDailyLevelSteps(TypedXmlSerializer out, String tag, LevelStepTracker steps,
11229             StringBuilder tmpBuilder) throws IOException {
11230         if (steps != null) {
11231             out.startTag(null, tag);
11232             out.attributeInt(null, "n", steps.mNumStepDurations);
11233             for (int i=0; i<steps.mNumStepDurations; i++) {
11234                 out.startTag(null, "s");
11235                 tmpBuilder.setLength(0);
11236                 steps.encodeEntryAt(i, tmpBuilder);
11237                 out.attribute(null, "v", tmpBuilder.toString());
11238                 out.endTag(null, "s");
11239             }
11240             out.endTag(null, tag);
11241         }
11242     }
11243 
11244     @GuardedBy("this")
readDailyStatsLocked()11245     public void readDailyStatsLocked() {
11246         Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
11247         mDailyItems.clear();
11248         FileInputStream stream;
11249         try {
11250             stream = mDailyFile.openRead();
11251         } catch (FileNotFoundException e) {
11252             return;
11253         }
11254         try {
11255             TypedXmlPullParser parser = Xml.resolvePullParser(stream);
11256             readDailyItemsLocked(parser);
11257         } catch (IOException e) {
11258         } finally {
11259             try {
11260                 stream.close();
11261             } catch (IOException e) {
11262             }
11263         }
11264     }
11265 
readDailyItemsLocked(TypedXmlPullParser parser)11266     private void readDailyItemsLocked(TypedXmlPullParser parser) {
11267         try {
11268             int type;
11269             while ((type = parser.next()) != XmlPullParser.START_TAG
11270                     && type != XmlPullParser.END_DOCUMENT) {
11271                 ;
11272             }
11273 
11274             if (type != XmlPullParser.START_TAG) {
11275                 throw new IllegalStateException("no start tag found");
11276             }
11277 
11278             int outerDepth = parser.getDepth();
11279             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11280                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11281                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11282                     continue;
11283                 }
11284 
11285                 String tagName = parser.getName();
11286                 if (tagName.equals("item")) {
11287                     readDailyItemTagLocked(parser);
11288                 } else {
11289                     Slog.w(TAG, "Unknown element under <daily-items>: "
11290                             + parser.getName());
11291                     XmlUtils.skipCurrentTag(parser);
11292                 }
11293             }
11294 
11295         } catch (IllegalStateException e) {
11296             Slog.w(TAG, "Failed parsing daily " + e);
11297         } catch (NullPointerException e) {
11298             Slog.w(TAG, "Failed parsing daily " + e);
11299         } catch (NumberFormatException e) {
11300             Slog.w(TAG, "Failed parsing daily " + e);
11301         } catch (XmlPullParserException e) {
11302             Slog.w(TAG, "Failed parsing daily " + e);
11303         } catch (IOException e) {
11304             Slog.w(TAG, "Failed parsing daily " + e);
11305         } catch (IndexOutOfBoundsException e) {
11306             Slog.w(TAG, "Failed parsing daily " + e);
11307         }
11308     }
11309 
readDailyItemTagLocked(TypedXmlPullParser parser)11310     void readDailyItemTagLocked(TypedXmlPullParser parser) throws NumberFormatException,
11311             XmlPullParserException, IOException {
11312         DailyItem dit = new DailyItem();
11313         dit.mStartTime = parser.getAttributeLong(null, "start", 0);
11314         dit.mEndTime = parser.getAttributeLong(null, "end", 0);
11315         int outerDepth = parser.getDepth();
11316         int type;
11317         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11318                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11319             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11320                 continue;
11321             }
11322 
11323             String tagName = parser.getName();
11324             if (tagName.equals("dis")) {
11325                 readDailyItemTagDetailsLocked(parser, dit, false, "dis");
11326             } else if (tagName.equals("chg")) {
11327                 readDailyItemTagDetailsLocked(parser, dit, true, "chg");
11328             } else if (tagName.equals("upd")) {
11329                 if (dit.mPackageChanges == null) {
11330                     dit.mPackageChanges = new ArrayList<>();
11331                 }
11332                 PackageChange pc = new PackageChange();
11333                 pc.mUpdate = true;
11334                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
11335                 pc.mVersionCode = parser.getAttributeLong(null, "ver", 0);
11336                 dit.mPackageChanges.add(pc);
11337                 XmlUtils.skipCurrentTag(parser);
11338             } else if (tagName.equals("rem")) {
11339                 if (dit.mPackageChanges == null) {
11340                     dit.mPackageChanges = new ArrayList<>();
11341                 }
11342                 PackageChange pc = new PackageChange();
11343                 pc.mUpdate = false;
11344                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
11345                 dit.mPackageChanges.add(pc);
11346                 XmlUtils.skipCurrentTag(parser);
11347             } else {
11348                 Slog.w(TAG, "Unknown element under <item>: "
11349                         + parser.getName());
11350                 XmlUtils.skipCurrentTag(parser);
11351             }
11352         }
11353         mDailyItems.add(dit);
11354     }
11355 
readDailyItemTagDetailsLocked(TypedXmlPullParser parser, DailyItem dit, boolean isCharge, String tag)11356     void readDailyItemTagDetailsLocked(TypedXmlPullParser parser, DailyItem dit, boolean isCharge,
11357             String tag)
11358             throws NumberFormatException, XmlPullParserException, IOException {
11359         final int num = parser.getAttributeInt(null, "n", -1);
11360         if (num == -1) {
11361             Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
11362             XmlUtils.skipCurrentTag(parser);
11363             return;
11364         }
11365         LevelStepTracker steps = new LevelStepTracker(num);
11366         if (isCharge) {
11367             dit.mChargeSteps = steps;
11368         } else {
11369             dit.mDischargeSteps = steps;
11370         }
11371         int i = 0;
11372         int outerDepth = parser.getDepth();
11373         int type;
11374         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11375                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11376             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11377                 continue;
11378             }
11379 
11380             String tagName = parser.getName();
11381             if ("s".equals(tagName)) {
11382                 if (i < num) {
11383                     String valueAttr = parser.getAttributeValue(null, "v");
11384                     if (valueAttr != null) {
11385                         steps.decodeEntryAt(i, valueAttr);
11386                         i++;
11387                     }
11388                 }
11389             } else {
11390                 Slog.w(TAG, "Unknown element under <" + tag + ">: "
11391                         + parser.getName());
11392                 XmlUtils.skipCurrentTag(parser);
11393             }
11394         }
11395         steps.mNumStepDurations = i;
11396     }
11397 
11398     @Override
getDailyItemLocked(int daysAgo)11399     public DailyItem getDailyItemLocked(int daysAgo) {
11400         int index = mDailyItems.size()-1-daysAgo;
11401         return index >= 0 ? mDailyItems.get(index) : null;
11402     }
11403 
11404     @Override
getCurrentDailyStartTime()11405     public long getCurrentDailyStartTime() {
11406         return mDailyStartTimeMs;
11407     }
11408 
11409     @Override
getNextMinDailyDeadline()11410     public long getNextMinDailyDeadline() {
11411         return mNextMinDailyDeadlineMs;
11412     }
11413 
11414     @Override
getNextMaxDailyDeadline()11415     public long getNextMaxDailyDeadline() {
11416         return mNextMaxDailyDeadlineMs;
11417     }
11418 
11419     @GuardedBy("this")
getHistoryTotalSize()11420     public int getHistoryTotalSize() {
11421         return mConstants.MAX_HISTORY_BUFFER * mConstants.MAX_HISTORY_FILES;
11422     }
11423 
getHistoryUsedSize()11424     public int getHistoryUsedSize() {
11425         return mHistory.getHistoryUsedSize();
11426     }
11427 
11428     /**
11429      * Creates an iterator for battery stats history.
11430      */
11431     @Override
iterateBatteryStatsHistory()11432     public BatteryStatsHistoryIterator iterateBatteryStatsHistory() {
11433         return mHistory.copy().iterate();
11434     }
11435 
11436     @Override
getHistoryStringPoolSize()11437     public int getHistoryStringPoolSize() {
11438         return mHistory.getHistoryStringPoolSize();
11439     }
11440 
11441     @Override
getHistoryStringPoolBytes()11442     public int getHistoryStringPoolBytes() {
11443         return mHistory.getHistoryStringPoolBytes();
11444     }
11445 
11446     @Override
getHistoryTagPoolString(int index)11447     public String getHistoryTagPoolString(int index) {
11448         return mHistory.getHistoryTagPoolString(index);
11449     }
11450 
11451     @Override
getHistoryTagPoolUid(int index)11452     public int getHistoryTagPoolUid(int index) {
11453         return mHistory.getHistoryTagPoolUid(index);
11454     }
11455 
11456     @Override
getStartCount()11457     public int getStartCount() {
11458         return mStartCount;
11459     }
11460 
isOnBattery()11461     public boolean isOnBattery() {
11462         return mOnBattery;
11463     }
11464 
isCharging()11465     public boolean isCharging() {
11466         return mCharging;
11467     }
11468 
initTimes(long uptimeUs, long realtimeUs)11469     void initTimes(long uptimeUs, long realtimeUs) {
11470         mStartClockTimeMs = mClock.currentTimeMillis();
11471         mOnBatteryTimeBase.init(uptimeUs, realtimeUs);
11472         mOnBatteryScreenOffTimeBase.init(uptimeUs, realtimeUs);
11473         mRealtimeUs = 0;
11474         mUptimeUs = 0;
11475         mRealtimeStartUs = realtimeUs;
11476         mUptimeStartUs = uptimeUs;
11477     }
11478 
initDischarge(long elapsedRealtimeUs)11479     void initDischarge(long elapsedRealtimeUs) {
11480         mLowDischargeAmountSinceCharge = 0;
11481         mHighDischargeAmountSinceCharge = 0;
11482         mDischargeAmountScreenOn = 0;
11483         mDischargeAmountScreenOnSinceCharge = 0;
11484         mDischargeAmountScreenOff = 0;
11485         mDischargeAmountScreenOffSinceCharge = 0;
11486         mDischargeAmountScreenDoze = 0;
11487         mDischargeAmountScreenDozeSinceCharge = 0;
11488         mDischargeStepTracker.init();
11489         mChargeStepTracker.init();
11490         mDischargeScreenOffCounter.reset(false, elapsedRealtimeUs);
11491         mDischargeScreenDozeCounter.reset(false, elapsedRealtimeUs);
11492         mDischargeLightDozeCounter.reset(false, elapsedRealtimeUs);
11493         mDischargeDeepDozeCounter.reset(false, elapsedRealtimeUs);
11494         mDischargeCounter.reset(false, elapsedRealtimeUs);
11495     }
11496 
setBatteryResetListener(BatteryResetListener batteryResetListener)11497     public void setBatteryResetListener(BatteryResetListener batteryResetListener) {
11498         mBatteryResetListener = batteryResetListener;
11499     }
11500 
11501     @GuardedBy("this")
resetAllStatsAndHistoryLocked(int reason)11502     public void resetAllStatsAndHistoryLocked(int reason) {
11503         final long mSecUptime = mClock.uptimeMillis();
11504         long uptimeUs = mSecUptime * 1000;
11505         long mSecRealtime = mClock.elapsedRealtime();
11506         long realtimeUs = mSecRealtime * 1000;
11507         resetAllStatsLocked(mSecUptime, mSecRealtime, reason);
11508         pullPendingStateUpdatesLocked();
11509         mHistory.writeHistoryItem(mSecRealtime, mSecUptime);
11510         mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel = mBatteryLevel;
11511         mOnBatteryTimeBase.reset(uptimeUs, realtimeUs);
11512         mOnBatteryScreenOffTimeBase.reset(uptimeUs, realtimeUs);
11513         if (!mBatteryPluggedIn) {
11514             if (Display.isOnState(mScreenState)) {
11515                 mDischargeScreenOnUnplugLevel = mBatteryLevel;
11516                 mDischargeScreenDozeUnplugLevel = 0;
11517                 mDischargeScreenOffUnplugLevel = 0;
11518             } else if (Display.isDozeState(mScreenState)) {
11519                 mDischargeScreenOnUnplugLevel = 0;
11520                 mDischargeScreenDozeUnplugLevel = mBatteryLevel;
11521                 mDischargeScreenOffUnplugLevel = 0;
11522             } else {
11523                 mDischargeScreenOnUnplugLevel = 0;
11524                 mDischargeScreenDozeUnplugLevel = 0;
11525                 mDischargeScreenOffUnplugLevel = mBatteryLevel;
11526             }
11527             mDischargeAmountScreenOn = 0;
11528             mDischargeAmountScreenOff = 0;
11529             mDischargeAmountScreenDoze = 0;
11530         }
11531         initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
11532     }
11533 
11534     @GuardedBy("this")
resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis, int resetReason)11535     private void resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis,
11536             int resetReason) {
11537         if (mBatteryResetListener != null) {
11538             mBatteryResetListener.prepareForBatteryStatsReset(resetReason);
11539         }
11540 
11541         final long uptimeUs = uptimeMillis * 1000;
11542         final long elapsedRealtimeUs = elapsedRealtimeMillis * 1000;
11543         mStartCount = 0;
11544         initTimes(uptimeUs, elapsedRealtimeUs);
11545         mScreenOnTimer.reset(false, elapsedRealtimeUs);
11546         mScreenDozeTimer.reset(false, elapsedRealtimeUs);
11547         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11548             mScreenBrightnessTimer[i].reset(false, elapsedRealtimeUs);
11549         }
11550 
11551         final int numDisplays = mPerDisplayBatteryStats.length;
11552         for (int i = 0; i < numDisplays; i++) {
11553             mPerDisplayBatteryStats[i].reset(elapsedRealtimeUs);
11554         }
11555 
11556         if (mPowerProfile != null) {
11557             mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
11558         } else {
11559             mEstimatedBatteryCapacityMah = -1;
11560         }
11561         mLastLearnedBatteryCapacityUah = -1;
11562         mMinLearnedBatteryCapacityUah = -1;
11563         mMaxLearnedBatteryCapacityUah = -1;
11564         mInteractiveTimer.reset(false, elapsedRealtimeUs);
11565         mPowerSaveModeEnabledTimer.reset(false, elapsedRealtimeUs);
11566         mLastIdleTimeStartMs = elapsedRealtimeMillis;
11567         mLongestLightIdleTimeMs = 0;
11568         mLongestFullIdleTimeMs = 0;
11569         mDeviceIdleModeLightTimer.reset(false, elapsedRealtimeUs);
11570         mDeviceIdleModeFullTimer.reset(false, elapsedRealtimeUs);
11571         mDeviceLightIdlingTimer.reset(false, elapsedRealtimeUs);
11572         mDeviceIdlingTimer.reset(false, elapsedRealtimeUs);
11573         mPhoneOnTimer.reset(false, elapsedRealtimeUs);
11574         mAudioOnTimer.reset(false, elapsedRealtimeUs);
11575         mVideoOnTimer.reset(false, elapsedRealtimeUs);
11576         mFlashlightOnTimer.reset(false, elapsedRealtimeUs);
11577         mCameraOnTimer.reset(false, elapsedRealtimeUs);
11578         mBluetoothScanTimer.reset(false, elapsedRealtimeUs);
11579         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
11580             mPhoneSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs);
11581         }
11582         mPhoneSignalScanningTimer.reset(false, elapsedRealtimeUs);
11583         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11584             mPhoneDataConnectionsTimer[i].reset(false, elapsedRealtimeUs);
11585         }
11586         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11587             mNetworkByteActivityCounters[i].reset(false, elapsedRealtimeUs);
11588             mNetworkPacketActivityCounters[i].reset(false, elapsedRealtimeUs);
11589         }
11590         for (int i = 0; i < RADIO_ACCESS_TECHNOLOGY_COUNT; i++) {
11591             final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[i];
11592             if (stats == null) continue;
11593             stats.reset(elapsedRealtimeUs);
11594         }
11595         mMobileRadioActiveTimer.reset(false, elapsedRealtimeUs);
11596         mMobileRadioActivePerAppTimer.reset(false, elapsedRealtimeUs);
11597         mMobileRadioActiveAdjustedTime.reset(false, elapsedRealtimeUs);
11598         mMobileRadioActiveUnknownTime.reset(false, elapsedRealtimeUs);
11599         mMobileRadioActiveUnknownCount.reset(false, elapsedRealtimeUs);
11600         mWifiOnTimer.reset(false, elapsedRealtimeUs);
11601         mGlobalWifiRunningTimer.reset(false, elapsedRealtimeUs);
11602         for (int i=0; i<NUM_WIFI_STATES; i++) {
11603             mWifiStateTimer[i].reset(false, elapsedRealtimeUs);
11604         }
11605         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11606             mWifiSupplStateTimer[i].reset(false, elapsedRealtimeUs);
11607         }
11608         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11609             mWifiSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs);
11610         }
11611         mWifiMulticastWakelockTimer.reset(false, elapsedRealtimeUs);
11612         mWifiActiveTimer.reset(false, elapsedRealtimeUs);
11613         mWifiActivity.reset(false, elapsedRealtimeUs);
11614         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
11615             mGpsSignalQualityTimer[i].reset(false, elapsedRealtimeUs);
11616         }
11617         mBluetoothActivity.reset(false, elapsedRealtimeUs);
11618         mModemActivity.reset(false, elapsedRealtimeUs);
11619         mNumConnectivityChange = 0;
11620 
11621         for (int i=0; i<mUidStats.size(); i++) {
11622             if (mUidStats.valueAt(i).reset(uptimeUs, elapsedRealtimeUs, resetReason)) {
11623                 mUidStats.valueAt(i).detachFromTimeBase();
11624                 mUidStats.remove(mUidStats.keyAt(i));
11625                 i--;
11626             }
11627         }
11628 
11629         if (mRpmStats.size() > 0) {
11630             for (SamplingTimer timer : mRpmStats.values()) {
11631                 mOnBatteryTimeBase.remove(timer);
11632             }
11633             mRpmStats.clear();
11634         }
11635         if (mScreenOffRpmStats.size() > 0) {
11636             for (SamplingTimer timer : mScreenOffRpmStats.values()) {
11637                 mOnBatteryScreenOffTimeBase.remove(timer);
11638             }
11639             mScreenOffRpmStats.clear();
11640         }
11641 
11642         if (mKernelWakelockStats.size() > 0) {
11643             for (SamplingTimer timer : mKernelWakelockStats.values()) {
11644                 mOnBatteryScreenOffTimeBase.remove(timer);
11645             }
11646             mKernelWakelockStats.clear();
11647         }
11648 
11649         if (mKernelMemoryStats.size() > 0) {
11650             for (int i = 0; i < mKernelMemoryStats.size(); i++) {
11651                 mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i));
11652             }
11653             mKernelMemoryStats.clear();
11654         }
11655 
11656         if (mWakeupReasonStats.size() > 0) {
11657             for (SamplingTimer timer : mWakeupReasonStats.values()) {
11658                 mOnBatteryTimeBase.remove(timer);
11659             }
11660             mWakeupReasonStats.clear();
11661         }
11662 
11663         mTmpRailStats.reset();
11664 
11665         EnergyConsumerStats.resetIfNotNull(mGlobalEnergyConsumerStats);
11666 
11667         resetIfNotNull(mBinderThreadCpuTimesUs, false, elapsedRealtimeUs);
11668 
11669         mNumAllUidCpuTimeReads = 0;
11670         mNumUidsRemoved = 0;
11671 
11672         initDischarge(elapsedRealtimeUs);
11673 
11674         mHistory.reset();
11675 
11676         // Store the empty state to disk to ensure consistency
11677         writeSyncLocked();
11678 
11679         // Flush external data, gathering snapshots, but don't process it since it is pre-reset data
11680         mIgnoreNextExternalStats = true;
11681         mExternalSync.scheduleSync("reset", ExternalStatsSync.UPDATE_ON_RESET);
11682 
11683         mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
11684     }
11685 
11686     @GuardedBy("this")
initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs)11687     private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
11688         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
11689             if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
11690                 // Not recording process starts/stops.
11691                 continue;
11692             }
11693             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
11694             if (active == null) {
11695                 continue;
11696             }
11697             for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
11698                 SparseIntArray uids = ent.getValue();
11699                 for (int j=0; j<uids.size(); j++) {
11700                     mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
11701                             uids.keyAt(j));
11702                 }
11703             }
11704         }
11705     }
11706 
11707     @GuardedBy("this")
updateDischargeScreenLevelsLocked(int oldState, int newState)11708     void updateDischargeScreenLevelsLocked(int oldState, int newState) {
11709         updateOldDischargeScreenLevelLocked(oldState);
11710         updateNewDischargeScreenLevelLocked(newState);
11711     }
11712 
11713     @GuardedBy("this")
updateOldDischargeScreenLevelLocked(int state)11714     private void updateOldDischargeScreenLevelLocked(int state) {
11715         if (Display.isOnState(state)) {
11716             int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
11717             if (diff > 0) {
11718                 mDischargeAmountScreenOn += diff;
11719                 mDischargeAmountScreenOnSinceCharge += diff;
11720             }
11721         } else if (Display.isDozeState(state)) {
11722             int diff = mDischargeScreenDozeUnplugLevel - mDischargeCurrentLevel;
11723             if (diff > 0) {
11724                 mDischargeAmountScreenDoze += diff;
11725                 mDischargeAmountScreenDozeSinceCharge += diff;
11726             }
11727         } else if (Display.isOffState(state)) {
11728             int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
11729             if (diff > 0) {
11730                 mDischargeAmountScreenOff += diff;
11731                 mDischargeAmountScreenOffSinceCharge += diff;
11732             }
11733         }
11734     }
11735 
11736     @GuardedBy("this")
updateNewDischargeScreenLevelLocked(int state)11737     private void updateNewDischargeScreenLevelLocked(int state) {
11738         if (Display.isOnState(state)) {
11739             mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
11740             mDischargeScreenOffUnplugLevel = 0;
11741             mDischargeScreenDozeUnplugLevel = 0;
11742         } else if (Display.isDozeState(state)) {
11743             mDischargeScreenOnUnplugLevel = 0;
11744             mDischargeScreenDozeUnplugLevel = mDischargeCurrentLevel;
11745             mDischargeScreenOffUnplugLevel = 0;
11746         } else if (Display.isOffState(state)) {
11747             mDischargeScreenOnUnplugLevel = 0;
11748             mDischargeScreenDozeUnplugLevel = 0;
11749             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
11750         }
11751     }
11752 
11753     @GuardedBy("this")
pullPendingStateUpdatesLocked()11754     public void pullPendingStateUpdatesLocked() {
11755         if (mOnBatteryInternal) {
11756             updateDischargeScreenLevelsLocked(mScreenState, mScreenState);
11757         }
11758     }
11759 
11760     private final Object mWifiNetworkLock = new Object();
11761 
11762     @GuardedBy("mWifiNetworkLock")
11763     private String[] mWifiIfaces = EmptyArray.STRING;
11764 
11765     @GuardedBy("mWifiNetworkLock")
11766     private NetworkStats mLastWifiNetworkStats = new NetworkStats(0, -1);
11767 
11768     private final Object mModemNetworkLock = new Object();
11769 
11770     @GuardedBy("mModemNetworkLock")
11771     private String[] mModemIfaces = EmptyArray.STRING;
11772 
11773     @GuardedBy("mModemNetworkLock")
11774     private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
11775 
11776     @VisibleForTesting
readMobileNetworkStatsLocked( @onNull NetworkStatsManager networkStatsManager)11777     protected NetworkStats readMobileNetworkStatsLocked(
11778             @NonNull NetworkStatsManager networkStatsManager) {
11779         return networkStatsManager.getMobileUidStats();
11780     }
11781 
11782     @VisibleForTesting
readWifiNetworkStatsLocked( @onNull NetworkStatsManager networkStatsManager)11783     protected NetworkStats readWifiNetworkStatsLocked(
11784             @NonNull NetworkStatsManager networkStatsManager) {
11785         return networkStatsManager.getWifiUidStats();
11786     }
11787 
11788     /**
11789      * Distribute WiFi energy info and network traffic to apps.
11790      * @param info The energy information from the WiFi controller.
11791      */
11792     @GuardedBy("this")
updateWifiState(@ullable final WifiActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs, @NonNull NetworkStatsManager networkStatsManager)11793     public void updateWifiState(@Nullable final WifiActivityEnergyInfo info,
11794             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs,
11795             @NonNull NetworkStatsManager networkStatsManager) {
11796         if (DEBUG_ENERGY) {
11797             synchronized (mWifiNetworkLock) {
11798                 Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
11799             }
11800         }
11801 
11802         // Grab a separate lock to acquire the network stats, which may do I/O.
11803         NetworkStats delta = null;
11804         synchronized (mWifiNetworkLock) {
11805             final NetworkStats latestStats = readWifiNetworkStatsLocked(networkStatsManager);
11806             if (latestStats != null) {
11807                 delta = latestStats.subtract(mLastWifiNetworkStats);
11808                 mLastWifiNetworkStats = latestStats;
11809             }
11810         }
11811 
11812         synchronized (this) {
11813             if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
11814                 if (mIgnoreNextExternalStats) {
11815                     // TODO: Strictly speaking, we should re-mark all 5 timers for each uid (and the
11816                     //  global one) here like we do for display. But I'm not sure it's worth the
11817                     //  complicated code for a codepath that shouldn't ever actually happen in real
11818                     //  life.
11819                 }
11820                 return;
11821             }
11822 
11823             final SparseDoubleArray uidEstimatedConsumptionMah =
11824                     (mGlobalEnergyConsumerStats != null
11825                             && mWifiPowerCalculator != null && consumedChargeUC > 0) ?
11826                             new SparseDoubleArray() : null;
11827             double totalEstimatedConsumptionMah = 0;
11828 
11829             SparseLongArray rxPackets = new SparseLongArray();
11830             SparseLongArray txPackets = new SparseLongArray();
11831             SparseLongArray rxTimesMs = new SparseLongArray();
11832             SparseLongArray txTimesMs = new SparseLongArray();
11833             long totalTxPackets = 0;
11834             long totalRxPackets = 0;
11835             if (delta != null) {
11836                 for (NetworkStats.Entry entry : delta) {
11837                     if (DEBUG_ENERGY) {
11838                         Slog.d(TAG, "Wifi uid " + entry.getUid()
11839                                 + ": delta rx=" + entry.getRxBytes()
11840                                 + " tx=" + entry.getTxBytes()
11841                                 + " rxPackets=" + entry.getRxPackets()
11842                                 + " txPackets=" + entry.getTxPackets());
11843                     }
11844 
11845                     if (entry.getRxBytes() == 0 && entry.getTxBytes() == 0) {
11846                         // Skip the lookup below since there is no work to do.
11847                         continue;
11848                     }
11849 
11850                     final int uid = mapUid(entry.getUid());
11851                     final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
11852                     if (entry.getRxBytes() != 0) {
11853                         u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.getRxBytes(),
11854                                 entry.getRxPackets());
11855                         if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
11856                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.getRxBytes(),
11857                                     entry.getRxPackets());
11858                         }
11859                         mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
11860                                 entry.getRxBytes());
11861                         mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
11862                                 entry.getRxPackets());
11863 
11864                         rxPackets.incrementValue(uid, entry.getRxPackets());
11865 
11866                         // Sum the total number of packets so that the Rx Power can
11867                         // be evenly distributed amongst the apps.
11868                         totalRxPackets += entry.getRxPackets();
11869                     }
11870 
11871                     if (entry.getTxBytes() != 0) {
11872                         u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.getTxBytes(),
11873                                 entry.getTxPackets());
11874                         if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
11875                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.getTxBytes(),
11876                                     entry.getTxPackets());
11877                         }
11878                         mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
11879                                 entry.getTxBytes());
11880                         mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
11881                                 entry.getTxPackets());
11882 
11883                         txPackets.incrementValue(uid, entry.getTxPackets());
11884 
11885                         // Sum the total number of packets so that the Tx Power can
11886                         // be evenly distributed amongst the apps.
11887                         totalTxPackets += entry.getTxPackets();
11888                     }
11889 
11890                     // Calculate consumed energy for this uid. Only do so if WifiReporting isn't
11891                     // enabled (if it is, we'll do it later instead using info).
11892                     if (uidEstimatedConsumptionMah != null && info == null && !mHasWifiReporting) {
11893                         final long uidRunningMs = u.mWifiRunningTimer
11894                                 .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
11895                         if (uidRunningMs > 0) u.mWifiRunningTimer.setMark(elapsedRealtimeMs);
11896 
11897                         final long uidScanMs = u.mWifiScanTimer
11898                                 .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
11899                         if (uidScanMs > 0) u.mWifiScanTimer.setMark(elapsedRealtimeMs);
11900 
11901                         long uidBatchScanMs = 0;
11902                         for (int bn = 0; bn < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bn++) {
11903                             if (u.mWifiBatchedScanTimer[bn] != null) {
11904                                 long bnMs = u.mWifiBatchedScanTimer[bn]
11905                                         .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
11906                                 if (bnMs > 0) {
11907                                     u.mWifiBatchedScanTimer[bn].setMark(elapsedRealtimeMs);
11908                                 }
11909                                 uidBatchScanMs += bnMs;
11910                             }
11911                         }
11912 
11913                         uidEstimatedConsumptionMah.incrementValue(u.getUid(),
11914                                 mWifiPowerCalculator.calcPowerWithoutControllerDataMah(
11915                                         entry.getRxPackets(), entry.getTxPackets(),
11916                                         uidRunningMs, uidScanMs, uidBatchScanMs));
11917                     }
11918                 }
11919                 delta = null;
11920             }
11921 
11922             if (info != null) {
11923                 mHasWifiReporting = true;
11924 
11925                 // Measured in mAms
11926                 final long txTimeMs = info.getControllerTxDurationMillis();
11927                 final long rxTimeMs = info.getControllerRxDurationMillis();
11928                 final long scanTimeMs = info.getControllerScanDurationMillis();
11929                 final long idleTimeMs = info.getControllerIdleDurationMillis();
11930                 final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
11931 
11932                 long leftOverRxTimeMs = rxTimeMs;
11933                 long leftOverTxTimeMs = txTimeMs;
11934 
11935                 if (DEBUG_ENERGY) {
11936                     Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
11937                     Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
11938                     Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
11939                     Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
11940                     Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
11941                     Slog.d(TAG, "  Scan Time:  " + scanTimeMs + " ms");
11942                 }
11943 
11944                 long totalWifiLockTimeMs = 0;
11945                 long totalScanTimeMs = 0;
11946 
11947                 // On the first pass, collect some totals so that we can normalize power
11948                 // calculations if we need to.
11949                 final int uidStatsSize = mUidStats.size();
11950                 for (int i = 0; i < uidStatsSize; i++) {
11951                     final Uid uid = mUidStats.valueAt(i);
11952 
11953                     // Sum the total scan power for all apps.
11954                     totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
11955                             elapsedRealtimeMs * 1000) / 1000;
11956 
11957                     // Sum the total time holding wifi lock for all apps.
11958                     totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
11959                             elapsedRealtimeMs * 1000) / 1000;
11960                 }
11961 
11962                 if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
11963                     Slog.d(TAG,
11964                             "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
11965                                     + rxTimeMs + " ms). Normalizing scan time.");
11966                 }
11967                 if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
11968                     Slog.d(TAG,
11969                             "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
11970                                     + txTimeMs + " ms). Normalizing scan time.");
11971                 }
11972 
11973                 // Actually assign and distribute power usage to apps.
11974                 for (int i = 0; i < uidStatsSize; i++) {
11975                     final Uid uid = mUidStats.valueAt(i);
11976 
11977                     final long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
11978                             elapsedRealtimeMs * 1000) / 1000;
11979                     long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
11980                     long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
11981                     if (scanTimeSinceMarkMs > 0) {
11982                         // Set the new mark so that next time we get new data since this point.
11983                         uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
11984 
11985                         // Our total scan time is more than the reported Tx/Rx time.
11986                         // This is possible because the cost of a scan is approximate.
11987                         // Let's normalize the result so that we evenly blame each app
11988                         // scanning.
11989                         //
11990                         // This means that we may have apps that transmitted/received packets not be
11991                         // blamed for this, but this is fine as scans are relatively more expensive.
11992                         if (totalScanTimeMs > rxTimeMs) {
11993                             scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
11994                                     totalScanTimeMs;
11995                         }
11996                         if (totalScanTimeMs > txTimeMs) {
11997                             scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
11998                                     totalScanTimeMs;
11999                         }
12000 
12001                         if (DEBUG_ENERGY) {
12002                             Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
12003                                     + scanRxTimeSinceMarkMs + " ms  Tx:"
12004                                     + scanTxTimeSinceMarkMs + " ms)");
12005                         }
12006 
12007                         rxTimesMs.incrementValue(uid.getUid(), scanRxTimeSinceMarkMs);
12008                         txTimesMs.incrementValue(uid.getUid(), scanTxTimeSinceMarkMs);
12009 
12010                         leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
12011                         leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
12012                     }
12013 
12014                     // Distribute evenly the power consumed while Idle to each app holding a WiFi
12015                     // lock.
12016                     long myIdleTimeMs = 0;
12017                     final long wifiLockTimeSinceMarkMs =
12018                             uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
12019                                     elapsedRealtimeMs * 1000) / 1000;
12020                     if (wifiLockTimeSinceMarkMs > 0) {
12021                         // Set the new mark so that next time we get new data since this point.
12022                         uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
12023 
12024                         myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs) / totalWifiLockTimeMs;
12025                         if (DEBUG_ENERGY) {
12026                             Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
12027                                     + myIdleTimeMs + " ms");
12028                         }
12029                         uid.getOrCreateWifiControllerActivityLocked().getOrCreateIdleTimeCounter()
12030                                 .increment(myIdleTimeMs, elapsedRealtimeMs);
12031                     }
12032 
12033                     if (uidEstimatedConsumptionMah != null) {
12034                         double uidEstMah = mWifiPowerCalculator.calcPowerFromControllerDataMah(
12035                                 scanRxTimeSinceMarkMs, scanTxTimeSinceMarkMs, myIdleTimeMs);
12036                         uidEstimatedConsumptionMah.incrementValue(uid.getUid(), uidEstMah);
12037                     }
12038                 }
12039 
12040                 if (DEBUG_ENERGY) {
12041                     Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
12042                     Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
12043                 }
12044 
12045                 // Distribute the remaining Tx power appropriately between all apps that transmitted
12046                 // packets.
12047                 for (int i = 0; i < txPackets.size(); i++) {
12048                     final int uid = txPackets.keyAt(i);
12049                     final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
12050                             / totalTxPackets;
12051                     txTimesMs.incrementValue(uid, myTxTimeMs);
12052                 }
12053 
12054                 // Distribute the remaining Rx power appropriately between all apps that received
12055                 // packets.
12056                 for (int i = 0; i < rxPackets.size(); i++) {
12057                     final int uid = rxPackets.keyAt(i);
12058                     final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
12059                             / totalRxPackets;
12060                     rxTimesMs.incrementValue(uid, myRxTimeMs);
12061                 }
12062 
12063                 for (int i = 0; i < txTimesMs.size(); i++) {
12064                     final int uid = txTimesMs.keyAt(i);
12065                     final long myTxTimeMs = txTimesMs.valueAt(i);
12066                     if (DEBUG_ENERGY) {
12067                         Slog.d(TAG, "  TxTime for UID " + uid + ": " + myTxTimeMs + " ms");
12068                     }
12069                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
12070                             .getOrCreateWifiControllerActivityLocked()
12071                             .getOrCreateTxTimeCounters()[0]
12072                             .increment(myTxTimeMs, elapsedRealtimeMs);
12073                     if (uidEstimatedConsumptionMah != null) {
12074                         uidEstimatedConsumptionMah.incrementValue(uid,
12075                                 mWifiPowerCalculator.calcPowerFromControllerDataMah(
12076                                         0, myTxTimeMs, 0));
12077                     }
12078                 }
12079 
12080                 for (int i = 0; i < rxTimesMs.size(); i++) {
12081                     final int uid = rxTimesMs.keyAt(i);
12082                     final long myRxTimeMs = rxTimesMs.valueAt(i);
12083                     if (DEBUG_ENERGY) {
12084                         Slog.d(TAG, "  RxTime for UID " + uid + ": " + myRxTimeMs + " ms");
12085                     }
12086 
12087                     getUidStatsLocked(rxTimesMs.keyAt(i), elapsedRealtimeMs, uptimeMs)
12088                             .getOrCreateWifiControllerActivityLocked()
12089                             .getOrCreateRxTimeCounter()
12090                             .increment(myRxTimeMs, elapsedRealtimeMs);
12091                     if (uidEstimatedConsumptionMah != null) {
12092                         uidEstimatedConsumptionMah.incrementValue(uid,
12093                                 mWifiPowerCalculator.calcPowerFromControllerDataMah(
12094                                         myRxTimeMs, 0, 0));
12095                     }
12096                 }
12097 
12098                 // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
12099 
12100                 // Update WiFi controller stats.
12101                 mWifiActivity.getOrCreateRxTimeCounter().increment(
12102                         info.getControllerRxDurationMillis(), elapsedRealtimeMs);
12103                 mWifiActivity.getOrCreateTxTimeCounters()[0].increment(
12104                         info.getControllerTxDurationMillis(), elapsedRealtimeMs);
12105                 mWifiActivity.getScanTimeCounter().addCountLocked(
12106                         info.getControllerScanDurationMillis());
12107                 mWifiActivity.getOrCreateIdleTimeCounter().increment(
12108                         info.getControllerIdleDurationMillis(), elapsedRealtimeMs);
12109 
12110                 // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
12111                 final double opVolt = mPowerProfile.getAveragePower(
12112                         PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
12113                 double controllerMaMs = 0;
12114                 if (opVolt != 0) {
12115                     // We store the power drain as mAms.
12116                     controllerMaMs = info.getControllerEnergyUsedMicroJoules() / opVolt;
12117                     mWifiActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
12118                 }
12119                 // Converting uWs to mAms.
12120                 // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
12121                 long monitoredRailChargeConsumedMaMs =
12122                         (long) (mTmpRailStats.getWifiTotalEnergyUseduWs() / opVolt);
12123                 mWifiActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
12124                         monitoredRailChargeConsumedMaMs);
12125                 mHistory.recordWifiConsumedCharge(elapsedRealtimeMs, uptimeMs,
12126                         (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR));
12127                 mTmpRailStats.resetWifiTotalEnergyUsed();
12128 
12129                 if (uidEstimatedConsumptionMah != null) {
12130                     totalEstimatedConsumptionMah = Math.max(controllerMaMs / MILLISECONDS_IN_HOUR,
12131                             mWifiPowerCalculator.calcPowerFromControllerDataMah(
12132                                     rxTimeMs, txTimeMs, idleTimeMs));
12133                 }
12134             }
12135 
12136             // Update the EnergyConsumerStats information.
12137             if (uidEstimatedConsumptionMah != null) {
12138                 mGlobalEnergyConsumerStats.updateStandardBucket(
12139                         EnergyConsumerStats.POWER_BUCKET_WIFI, consumedChargeUC);
12140 
12141                 // Now calculate the consumption for each uid, according to its proportional usage.
12142                 if (!mHasWifiReporting) {
12143                     final long globalTimeMs = mGlobalWifiRunningTimer
12144                             .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
12145                     mGlobalWifiRunningTimer.setMark(elapsedRealtimeMs);
12146                     totalEstimatedConsumptionMah = mWifiPowerCalculator
12147                             .calcGlobalPowerWithoutControllerDataMah(globalTimeMs);
12148                 }
12149                 distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_WIFI,
12150                         consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedConsumptionMah,
12151                         elapsedRealtimeMs);
12152             }
12153         }
12154     }
12155 
12156     private ModemActivityInfo mLastModemActivityInfo = null;
12157 
12158     /**
12159      * Distribute Cell radio energy info and network traffic to apps.
12160      */
noteModemControllerActivity(@ullable final ModemActivityInfo activityInfo, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs, @NonNull NetworkStatsManager networkStatsManager)12161     public void noteModemControllerActivity(@Nullable final ModemActivityInfo activityInfo,
12162             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs,
12163             @NonNull NetworkStatsManager networkStatsManager) {
12164         if (DEBUG_ENERGY) {
12165             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
12166         }
12167         ModemActivityInfo deltaInfo = mLastModemActivityInfo == null
12168                 ? (activityInfo == null ? null : activityInfo.getDelta(activityInfo))
12169                 : mLastModemActivityInfo.getDelta(activityInfo);
12170         mLastModemActivityInfo = activityInfo;
12171 
12172         // Add modem tx power to history.
12173         addModemTxPowerToHistory(deltaInfo, elapsedRealtimeMs, uptimeMs);
12174 
12175         // Grab a separate lock to acquire the network stats, which may do I/O.
12176         NetworkStats delta = null;
12177         synchronized (mModemNetworkLock) {
12178             final NetworkStats latestStats = readMobileNetworkStatsLocked(networkStatsManager);
12179             if (latestStats != null) {
12180                 delta = latestStats.subtract(mLastModemNetworkStats);
12181                 mLastModemNetworkStats = latestStats;
12182             }
12183         }
12184 
12185         synchronized (this) {
12186             final long totalRadioDurationMs =
12187                     mMobileRadioActiveTimer.getTimeSinceMarkLocked(
12188                             elapsedRealtimeMs * 1000) / 1000;
12189             mMobileRadioActiveTimer.setMark(elapsedRealtimeMs);
12190             final long phoneOnDurationMs = Math.min(totalRadioDurationMs,
12191                     mPhoneOnTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000);
12192             mPhoneOnTimer.setMark(elapsedRealtimeMs);
12193 
12194             if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
12195                 return;
12196             }
12197 
12198             final SparseDoubleArray uidEstimatedConsumptionMah;
12199             final long dataConsumedChargeUC;
12200             if (consumedChargeUC > 0 && isMobileRadioEnergyConsumerSupportedLocked()) {
12201                 final long phoneConsumedChargeUC;
12202                 if (totalRadioDurationMs == 0) {
12203                     phoneConsumedChargeUC = 0;
12204                 } else {
12205                     // Crudely attribute power consumption. Added (totalRadioDurationMs / 2) to the
12206                     // numerator for long rounding.
12207                     phoneConsumedChargeUC =
12208                             (consumedChargeUC * phoneOnDurationMs + totalRadioDurationMs / 2)
12209                                     / totalRadioDurationMs;
12210                 }
12211                 dataConsumedChargeUC = consumedChargeUC - phoneConsumedChargeUC;
12212 
12213                 mGlobalEnergyConsumerStats.updateStandardBucket(
12214                         EnergyConsumerStats.POWER_BUCKET_PHONE, phoneConsumedChargeUC);
12215                 mGlobalEnergyConsumerStats.updateStandardBucket(
12216                         EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO, dataConsumedChargeUC);
12217                 uidEstimatedConsumptionMah = new SparseDoubleArray();
12218             } else {
12219                 uidEstimatedConsumptionMah = null;
12220                 dataConsumedChargeUC = POWER_DATA_UNAVAILABLE;
12221             }
12222 
12223             RxTxConsumption rxTxConsumption = null;
12224             boolean attributeWithModemActivityInfo = false;
12225             if (deltaInfo != null) {
12226                 mHasModemReporting = true;
12227                 mModemActivity.getOrCreateIdleTimeCounter()
12228                         .increment(deltaInfo.getIdleTimeMillis(), elapsedRealtimeMs);
12229                 mModemActivity.getSleepTimeCounter().addCountLocked(
12230                         deltaInfo.getSleepTimeMillis());
12231                 mModemActivity.getOrCreateRxTimeCounter()
12232                         .increment(deltaInfo.getReceiveTimeMillis(), elapsedRealtimeMs);
12233                 for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels(); lvl++) {
12234                     mModemActivity.getOrCreateTxTimeCounters()[lvl]
12235                             .increment(deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl),
12236                                     elapsedRealtimeMs);
12237                 }
12238 
12239                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
12240                 final double opVolt = mPowerProfile.getAveragePower(
12241                     PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
12242                 if (opVolt != 0) {
12243                     double energyUsed =
12244                             deltaInfo.getSleepTimeMillis() *
12245                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
12246                             + deltaInfo.getIdleTimeMillis() *
12247                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
12248                             + deltaInfo.getReceiveTimeMillis() *
12249                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
12250                     for (int i = 0; i < Math.min(ModemActivityInfo.getNumTxPowerLevels(),
12251                             CellSignalStrength.getNumSignalStrengthLevels()); i++) {
12252                         energyUsed += deltaInfo.getTransmitDurationMillisAtPowerLevel(i)
12253                                 * mPowerProfile.getAveragePower(
12254                                         PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
12255                     }
12256 
12257                     // We store the power drain as mAms.
12258                     mModemActivity.getPowerCounter().addCountLocked((long) energyUsed);
12259                     // Converting uWs to mAms.
12260                     // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
12261                     long monitoredRailChargeConsumedMaMs =
12262                             (long) (mTmpRailStats.getCellularTotalEnergyUseduWs() / opVolt);
12263                     mModemActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
12264                             monitoredRailChargeConsumedMaMs);
12265                     mHistory.recordWifiConsumedCharge(elapsedRealtimeMs, uptimeMs,
12266                             (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR));
12267                     mTmpRailStats.resetCellularTotalEnergyUsed();
12268                 }
12269 
12270                 rxTxConsumption = incrementPerRatDataLocked(deltaInfo, elapsedRealtimeMs);
12271 
12272                 attributeWithModemActivityInfo = mConstants.PER_UID_MODEM_MODEL
12273                         == PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX
12274                         && rxTxConsumption != null;
12275             }
12276             long totalAppRadioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
12277                     elapsedRealtimeMs * 1000);
12278             mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
12279 
12280             long totalRxPackets = 0;
12281             long totalTxPackets = 0;
12282             if (delta != null) {
12283                 for (NetworkStats.Entry entry : delta) {
12284                     if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
12285                         continue;
12286                     }
12287 
12288                     if (DEBUG_ENERGY) {
12289                         Slog.d(TAG, "Mobile uid " + entry.getUid() + ": delta rx="
12290                                 + entry.getRxBytes() + " tx=" + entry.getTxBytes()
12291                                 + " rxPackets=" + entry.getRxPackets()
12292                                 + " txPackets=" + entry.getTxPackets());
12293                     }
12294 
12295                     totalRxPackets += entry.getRxPackets();
12296                     totalTxPackets += entry.getTxPackets();
12297 
12298                     final Uid u = getUidStatsLocked(
12299                             mapUid(entry.getUid()), elapsedRealtimeMs, uptimeMs);
12300                     u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.getRxBytes(),
12301                             entry.getRxPackets());
12302                     u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.getTxBytes(),
12303                             entry.getTxPackets());
12304                     if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
12305                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
12306                                 entry.getRxBytes(), entry.getRxPackets());
12307                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
12308                                 entry.getTxBytes(), entry.getTxPackets());
12309                     }
12310 
12311                     mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
12312                             entry.getRxBytes());
12313                     mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
12314                             entry.getTxBytes());
12315                     mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
12316                             entry.getRxPackets());
12317                     mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
12318                             entry.getTxPackets());
12319                 }
12320 
12321                 // Now distribute proportional blame to the apps that did networking.
12322                 long totalPackets = totalRxPackets + totalTxPackets;
12323                 if (totalPackets > 0) {
12324                     for (NetworkStats.Entry entry : delta) {
12325                         if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
12326                             continue;
12327                         }
12328 
12329                         final Uid u = getUidStatsLocked(mapUid(entry.getUid()),
12330                                 elapsedRealtimeMs, uptimeMs);
12331 
12332                         // Distribute total radio active time in to this app.
12333                         final long appPackets = entry.getRxPackets() + entry.getTxPackets();
12334                         final long appRadioTimeUs =
12335                                 (totalAppRadioTimeUs * appPackets) / totalPackets;
12336                         u.noteMobileRadioActiveTimeLocked(appRadioTimeUs, elapsedRealtimeMs);
12337 
12338                         if (uidEstimatedConsumptionMah != null) {
12339                             final double uidConsumptionMah;
12340                             if (attributeWithModemActivityInfo) {
12341                                 // Distribute measured mobile radio charge consumption based on
12342                                 // rx/tx packets and estimated rx/tx charge consumption.
12343                                 uidConsumptionMah = smearModemActivityInfoRxTxConsumptionMah(
12344                                         rxTxConsumption, entry.getRxPackets(), entry.getTxPackets(),
12345                                         totalRxPackets, totalTxPackets);
12346                             } else {
12347                                 // Distribute mobile radio charge consumption based on app radio
12348                                 // active time
12349                                 uidConsumptionMah =
12350                                     mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
12351                                                 appRadioTimeUs / 1000);
12352                             }
12353                             uidEstimatedConsumptionMah.incrementValue(u.getUid(),
12354                                     uidConsumptionMah);
12355                         }
12356 
12357                         // Remove this app from the totals, so that we don't lose any time
12358                         // due to rounding.
12359                         totalAppRadioTimeUs -= appRadioTimeUs;
12360                         totalPackets -= appPackets;
12361 
12362                         if (deltaInfo != null) {
12363                             ControllerActivityCounterImpl activityCounter =
12364                                     u.getOrCreateModemControllerActivityLocked();
12365                             if (totalRxPackets > 0 && entry.getRxPackets() > 0) {
12366                                 final long rxMs = (entry.getRxPackets()
12367                                     * deltaInfo.getReceiveTimeMillis()) / totalRxPackets;
12368                                 activityCounter.getOrCreateRxTimeCounter()
12369                                         .increment(rxMs, elapsedRealtimeMs);
12370                             }
12371 
12372                             if (totalTxPackets > 0 && entry.getTxPackets() > 0) {
12373                                 for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels();
12374                                         lvl++) {
12375                                     long txMs = entry.getTxPackets()
12376                                             * deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl);
12377                                     txMs /= totalTxPackets;
12378                                     activityCounter.getOrCreateTxTimeCounters()[lvl]
12379                                             .increment(txMs, elapsedRealtimeMs);
12380                                 }
12381                             }
12382                         }
12383                     }
12384                 }
12385 
12386                 if (totalAppRadioTimeUs > 0) {
12387                     // Whoops, there is some radio time we can't blame on an app!
12388                     mMobileRadioActiveUnknownTime.addCountLocked(totalAppRadioTimeUs);
12389                     mMobileRadioActiveUnknownCount.addCountLocked(1);
12390                 }
12391 
12392                 // Update the EnergyConsumerStats information.
12393                 if (uidEstimatedConsumptionMah != null) {
12394                     double totalEstimatedConsumptionMah = 0.0;
12395                     if (attributeWithModemActivityInfo) {
12396                         // Estimate inactive modem power consumption and combine with previously
12397                         // estimated active power consumption for an estimate of total modem
12398                         // power consumption.
12399                         final long sleepTimeMs = deltaInfo.getSleepTimeMillis();
12400                         final long idleTimeMs = deltaInfo.getIdleTimeMillis();
12401                         final double inactiveConsumptionMah =
12402                                 mMobileRadioPowerCalculator.calcInactiveStatePowerMah(sleepTimeMs,
12403                                         idleTimeMs);
12404                         totalEstimatedConsumptionMah += inactiveConsumptionMah;
12405                         totalEstimatedConsumptionMah += rxTxConsumption.rxConsumptionMah;
12406                         totalEstimatedConsumptionMah += rxTxConsumption.txConsumptionMah;
12407                     } else {
12408                         // Estimate total active radio power consumption since last mark.
12409                         totalEstimatedConsumptionMah +=
12410                                 mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
12411                                         totalRadioDurationMs);
12412 
12413                         // Estimate idle power consumption at each signal strength level
12414                         final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length;
12415                         for (int lvl = 0; lvl < numSignalStrengthLevels; lvl++) {
12416                             final long strengthLevelDurationMs =
12417                                     mPhoneSignalStrengthsTimer[lvl].getTimeSinceMarkLocked(
12418                                             elapsedRealtimeMs * 1000) / 1000;
12419                             mPhoneSignalStrengthsTimer[lvl].setMark(elapsedRealtimeMs);
12420 
12421                             totalEstimatedConsumptionMah +=
12422                                     mMobileRadioPowerCalculator.calcIdlePowerAtSignalStrengthMah(
12423                                             strengthLevelDurationMs, lvl);
12424                         }
12425 
12426                         // Estimate total active radio power consumption since last mark.
12427                         final long scanTimeMs = mPhoneSignalScanningTimer.getTimeSinceMarkLocked(
12428                                 elapsedRealtimeMs * 1000) / 1000;
12429                         mPhoneSignalScanningTimer.setMark(elapsedRealtimeMs);
12430                         totalEstimatedConsumptionMah +=
12431                                 mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs);
12432                     }
12433                     distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO,
12434                             dataConsumedChargeUC, uidEstimatedConsumptionMah,
12435                             totalEstimatedConsumptionMah, elapsedRealtimeMs);
12436                 }
12437             }
12438         }
12439     }
12440 
12441     private static class RxTxConsumption {
12442         public final double rxConsumptionMah;
12443         public final long rxDurationMs;
12444         public final double txConsumptionMah;
12445         public final long txDurationMs;
12446 
12447         /**
12448          * Represents the ratio between time spent transmitting and the total active time.
12449          */
12450         public final double txToTotalRatio;
12451 
RxTxConsumption(double rxMah, long rxMs, double txMah, long txMs)12452         RxTxConsumption(double rxMah, long rxMs, double txMah, long txMs) {
12453             rxConsumptionMah = rxMah;
12454             rxDurationMs = rxMs;
12455             txConsumptionMah = txMah;
12456             txDurationMs = txMs;
12457 
12458             final long activeDurationMs = txDurationMs + rxDurationMs;
12459             if (activeDurationMs == 0) {
12460                 txToTotalRatio = 0.0;
12461             } else {
12462                 txToTotalRatio = ((double) txDurationMs) / activeDurationMs;
12463             }
12464         }
12465     }
12466 
12467     @GuardedBy("this")
12468     @Nullable
incrementPerRatDataLocked(ModemActivityInfo deltaInfo, long elapsedRealtimeMs)12469     private RxTxConsumption incrementPerRatDataLocked(ModemActivityInfo deltaInfo,
12470             long elapsedRealtimeMs) {
12471         double rxConsumptionMah = 0.0;
12472         long rxDurationMs = 0;
12473         double txConsumptionMah = 0.0;
12474         long txDurationMs = 0;
12475 
12476         final int infoSize = deltaInfo.getSpecificInfoLength();
12477         if (infoSize == 1 && deltaInfo.getSpecificInfoRat(0)
12478                 == AccessNetworkConstants.AccessNetworkType.UNKNOWN
12479                 && deltaInfo.getSpecificInfoFrequencyRange(0)
12480                 == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
12481             // Specific info data unavailable. Proportionally smear Rx and Tx times across each RAT.
12482             final int levelCount = CellSignalStrength.getNumSignalStrengthLevels();
12483             long[] perSignalStrengthActiveTimeMs = new long[levelCount];
12484             long totalActiveTimeMs = 0;
12485 
12486             for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
12487                 final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
12488                 if (ratStats == null) continue;
12489 
12490                 final int freqCount = ratStats.getFrequencyRangeCount();
12491                 for (int freq = 0; freq < freqCount; freq++) {
12492                     for (int level = 0; level < levelCount; level++) {
12493                         final long durationMs = ratStats.getTimeSinceMark(freq, level,
12494                                 elapsedRealtimeMs);
12495                         perSignalStrengthActiveTimeMs[level] += durationMs;
12496                         totalActiveTimeMs += durationMs;
12497                     }
12498                 }
12499             }
12500             if (totalActiveTimeMs != 0) {
12501                 // Smear the provided Tx/Rx durations across each RAT, frequency, and signal
12502                 // strength.
12503                 for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
12504                     final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
12505                     if (ratStats == null) continue;
12506 
12507                     final int freqCount = ratStats.getFrequencyRangeCount();
12508                     for (int freq = 0; freq < freqCount; freq++) {
12509                         long frequencyDurationMs = 0;
12510                         for (int level = 0; level < levelCount; level++) {
12511                             final long durationMs = ratStats.getTimeSinceMark(freq, level,
12512                                     elapsedRealtimeMs);
12513                             final long totalLvlDurationMs =
12514                                     perSignalStrengthActiveTimeMs[level];
12515                             if (totalLvlDurationMs == 0) continue;
12516                             final long totalTxLvlDurations =
12517                                     deltaInfo.getTransmitDurationMillisAtPowerLevel(level);
12518                             // Smear HAL provided Tx power level duration based on active modem
12519                             // duration in a given state. (Add totalLvlDurationMs / 2 before
12520                             // the integer division with totalLvlDurationMs for rounding.)
12521                             final long proportionalTxDurationMs =
12522                                     (durationMs * totalTxLvlDurations
12523                                             + (totalLvlDurationMs / 2)) / totalLvlDurationMs;
12524                             ratStats.incrementTxDuration(freq, level, proportionalTxDurationMs);
12525                             frequencyDurationMs += durationMs;
12526 
12527                             if (isMobileRadioEnergyConsumerSupportedLocked()) {
12528                                 // Accumulate the power cost of time spent transmitting in a
12529                                 // particular state.
12530                                 final double txStatePowerConsumptionMah =
12531                                         mMobileRadioPowerCalculator.calcTxStatePowerMah(rat, freq,
12532                                                 level, proportionalTxDurationMs);
12533                                 txConsumptionMah += txStatePowerConsumptionMah;
12534                                 txDurationMs += proportionalTxDurationMs;
12535                             }
12536                         }
12537                         final long totalRxDuration = deltaInfo.getReceiveTimeMillis();
12538                         // Smear HAL provided Rx power duration based on active modem
12539                         // duration in a given state.  (Add totalActiveTimeMs / 2 before the
12540                         // integer division with totalActiveTimeMs for rounding.)
12541                         final long proportionalRxDurationMs =
12542                                 (frequencyDurationMs * totalRxDuration + (totalActiveTimeMs
12543                                         / 2)) / totalActiveTimeMs;
12544                         ratStats.incrementRxDuration(freq, proportionalRxDurationMs);
12545 
12546                         if (isMobileRadioEnergyConsumerSupportedLocked()) {
12547                             // Accumulate the power cost of time spent receiving in a particular
12548                             // state.
12549                             final double rxStatePowerConsumptionMah =
12550                                     mMobileRadioPowerCalculator.calcRxStatePowerMah(rat, freq,
12551                                             proportionalRxDurationMs);
12552                             rxConsumptionMah += rxStatePowerConsumptionMah;
12553                             rxDurationMs += proportionalRxDurationMs;
12554                         }
12555                     }
12556 
12557                 }
12558             }
12559         } else {
12560             // Specific data available.
12561             for (int index = 0; index < infoSize; index++) {
12562                 final int rat = deltaInfo.getSpecificInfoRat(index);
12563                 final int freq = deltaInfo.getSpecificInfoFrequencyRange(index);
12564 
12565                 // Map RadioAccessNetworkType to course grain RadioAccessTechnology.
12566                 final int ratBucket = mapRadioAccessNetworkTypeToRadioAccessTechnology(rat);
12567                 final RadioAccessTechnologyBatteryStats ratStats = getRatBatteryStatsLocked(
12568                         ratBucket);
12569 
12570                 final long rxTimeMs = deltaInfo.getReceiveTimeMillis(rat, freq);
12571                 final int[] txTimesMs = deltaInfo.getTransmitTimeMillis(rat, freq);
12572 
12573                 ratStats.incrementRxDuration(freq, rxTimeMs);
12574                 if (isMobileRadioEnergyConsumerSupportedLocked()) {
12575                     // Accumulate the power cost of time spent receiving in a particular state.
12576                     final double rxStatePowerConsumptionMah =
12577                             mMobileRadioPowerCalculator.calcRxStatePowerMah(ratBucket, freq,
12578                                     rxTimeMs);
12579                     rxConsumptionMah += rxStatePowerConsumptionMah;
12580                     rxDurationMs += rxTimeMs;
12581                 }
12582 
12583                 final int numTxLvl = txTimesMs.length;
12584                 for (int lvl = 0; lvl < numTxLvl; lvl++) {
12585                     final long txTimeMs = txTimesMs[lvl];
12586                     ratStats.incrementTxDuration(freq, lvl, txTimeMs);
12587                     if (isMobileRadioEnergyConsumerSupportedLocked()) {
12588                         // Accumulate the power cost of time spent transmitting in a particular
12589                         // state.
12590                         final double txStatePowerConsumptionMah =
12591                                 mMobileRadioPowerCalculator.calcTxStatePowerMah(ratBucket, freq,
12592                                         lvl, txTimeMs);
12593                         txConsumptionMah += txStatePowerConsumptionMah;
12594                         txDurationMs += txTimeMs;
12595                     }
12596                 }
12597             }
12598         }
12599 
12600         for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
12601             final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
12602             if (ratStats == null) continue;
12603             ratStats.setMark(elapsedRealtimeMs);
12604         }
12605 
12606         if (isMobileRadioEnergyConsumerSupportedLocked()) {
12607             return new RxTxConsumption(rxConsumptionMah, rxDurationMs, txConsumptionMah,
12608                     txDurationMs);
12609         } else {
12610             return null;
12611         }
12612     }
12613 
12614     /**
12615      * Smear modem Rx/Tx power consumption calculated from {@link ModemActivityInfo} using Rx/Tx
12616      * packets.
12617      *
12618      * @return the combine Rx/Tx smeared power consumption in milliamp-hours.
12619      */
smearModemActivityInfoRxTxConsumptionMah(RxTxConsumption rxTxConsumption, long rxPackets, long txPackets, long totalRxPackets, long totalTxPackets)12620     private double smearModemActivityInfoRxTxConsumptionMah(RxTxConsumption rxTxConsumption,
12621             long rxPackets, long txPackets, long totalRxPackets, long totalTxPackets) {
12622         // Distribute measured mobile radio charge consumption based on
12623         // rx/tx packets and estimated rx/tx charge consumption.
12624         double consumptionMah = 0.0;
12625         if (totalRxPackets != 0) {
12626             // Proportionally distribute receive battery consumption.
12627             consumptionMah += rxTxConsumption.rxConsumptionMah * rxPackets
12628                     / totalRxPackets;
12629         }
12630         if (totalTxPackets != 0 || (totalRxPackets != 0 && rxTxConsumption.txToTotalRatio != 0.0)) {
12631             // ModemActivityInfo Tx time represents time spent both transmitting and receiving.
12632             // There is currently no way to distinguish how many Rx packets were received during
12633             // Rx time vs Tx time.
12634             // Assumption: The number of packets received while transmitting is proportional
12635             // to the time spent transmitting over total active time.
12636             final double totalPacketsDuringTxTime =
12637                     totalTxPackets + rxTxConsumption.txToTotalRatio * totalRxPackets;
12638             final double packetsDuringTxTime =
12639                     txPackets + rxTxConsumption.txToTotalRatio * rxPackets;
12640             consumptionMah += rxTxConsumption.txConsumptionMah * packetsDuringTxTime
12641                     / totalPacketsDuringTxTime;
12642         }
12643         return consumptionMah;
12644     }
12645 
12646     /**
12647      * Add modem tx power to history
12648      * Device is said to be in high cellular transmit power when it has spent most of the transmit
12649      * time at the highest power level.
12650      * @param activityInfo
12651      */
addModemTxPowerToHistory(final ModemActivityInfo activityInfo, long elapsedRealtimeMs, long uptimeMs)12652     private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo,
12653             long elapsedRealtimeMs, long uptimeMs) {
12654         if (activityInfo == null) {
12655             return;
12656         }
12657         int levelMaxTimeSpent = 0;
12658         for (int i = 1; i < ModemActivityInfo.getNumTxPowerLevels(); i++) {
12659             if (activityInfo.getTransmitDurationMillisAtPowerLevel(i)
12660                     > activityInfo.getTransmitDurationMillisAtPowerLevel(levelMaxTimeSpent)) {
12661                 levelMaxTimeSpent = i;
12662             }
12663         }
12664         if (levelMaxTimeSpent == ModemActivityInfo.getNumTxPowerLevels() - 1) {
12665             mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
12666                     HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG);
12667         }
12668     }
12669 
12670     private final class BluetoothActivityInfoCache {
12671         long idleTimeMs;
12672         long rxTimeMs;
12673         long txTimeMs;
12674         long energy;
12675 
12676         SparseLongArray uidRxBytes = new SparseLongArray();
12677         SparseLongArray uidTxBytes = new SparseLongArray();
12678 
set(BluetoothActivityEnergyInfo info)12679         void set(BluetoothActivityEnergyInfo info) {
12680             idleTimeMs = info.getControllerIdleTimeMillis();
12681             rxTimeMs = info.getControllerRxTimeMillis();
12682             txTimeMs = info.getControllerTxTimeMillis();
12683             energy = info.getControllerEnergyUsed();
12684             if (!info.getUidTraffic().isEmpty()) {
12685                 for (UidTraffic traffic : info.getUidTraffic()) {
12686                     uidRxBytes.put(traffic.getUid(), traffic.getRxBytes());
12687                     uidTxBytes.put(traffic.getUid(), traffic.getTxBytes());
12688                 }
12689             }
12690         }
12691 
reset()12692         void reset() {
12693             idleTimeMs = 0;
12694             rxTimeMs = 0;
12695             txTimeMs = 0;
12696             energy = 0;
12697             uidRxBytes.clear();
12698             uidTxBytes.clear();
12699         }
12700     }
12701 
12702     private final BluetoothActivityInfoCache mLastBluetoothActivityInfo
12703             = new BluetoothActivityInfoCache();
12704 
12705     /**
12706      * Distribute Bluetooth energy info and network traffic to apps.
12707      *
12708      * @param info The accumulated energy information from the bluetooth controller.
12709      */
12710     @GuardedBy("this")
updateBluetoothStateLocked(@ullable final BluetoothActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs)12711     public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info,
12712             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
12713         if (DEBUG_ENERGY) {
12714             Slog.d(TAG, "Updating bluetooth stats: " + info);
12715         }
12716 
12717         if (info == null) {
12718             return;
12719         }
12720         if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
12721             mLastBluetoothActivityInfo.set(info);
12722             return;
12723         }
12724 
12725         mHasBluetoothReporting = true;
12726 
12727         if (info.getControllerRxTimeMillis() < mLastBluetoothActivityInfo.rxTimeMs
12728                 || info.getControllerTxTimeMillis() < mLastBluetoothActivityInfo.txTimeMs
12729                 || info.getControllerIdleTimeMillis() < mLastBluetoothActivityInfo.idleTimeMs
12730                 || info.getControllerEnergyUsed() < mLastBluetoothActivityInfo.energy) {
12731             // A drop in accumulated Bluetooth stats is a sign of a Bluetooth crash.
12732             // Reset the preserved previous snapshot in order to restart accumulating deltas.
12733             mLastBluetoothActivityInfo.reset();
12734         }
12735 
12736         final long rxTimeMs =
12737                 info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs;
12738         final long txTimeMs =
12739                 info.getControllerTxTimeMillis() - mLastBluetoothActivityInfo.txTimeMs;
12740         final long idleTimeMs =
12741                 info.getControllerIdleTimeMillis() - mLastBluetoothActivityInfo.idleTimeMs;
12742 
12743         if (DEBUG_ENERGY) {
12744             Slog.d(TAG, "------ BEGIN BLE power blaming ------");
12745             Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
12746             Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
12747             Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
12748         }
12749 
12750         final SparseDoubleArray uidEstimatedConsumptionMah =
12751                 (mGlobalEnergyConsumerStats != null
12752                         && mBluetoothPowerCalculator != null && consumedChargeUC > 0) ?
12753                         new SparseDoubleArray() : null;
12754 
12755         long totalScanTimeMs = 0;
12756 
12757         final int uidCount = mUidStats.size();
12758         for (int i = 0; i < uidCount; i++) {
12759             final Uid u = mUidStats.valueAt(i);
12760             if (u.mBluetoothScanTimer == null) {
12761                 continue;
12762             }
12763 
12764             totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
12765                     elapsedRealtimeMs * 1000) / 1000;
12766         }
12767 
12768         final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
12769         final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
12770 
12771         if (DEBUG_ENERGY) {
12772             Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
12773                     + " TX=" + normalizeScanTxTime);
12774         }
12775 
12776         long leftOverRxTimeMs = rxTimeMs;
12777         long leftOverTxTimeMs = txTimeMs;
12778 
12779         final SparseLongArray rxTimesMs = new SparseLongArray(uidCount);
12780         final SparseLongArray txTimesMs = new SparseLongArray(uidCount);
12781 
12782         for (int i = 0; i < uidCount; i++) {
12783             final Uid u = mUidStats.valueAt(i);
12784             if (u.mBluetoothScanTimer == null) {
12785                 continue;
12786             }
12787 
12788             long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
12789                     elapsedRealtimeMs * 1000) / 1000;
12790             if (scanTimeSinceMarkMs > 0) {
12791                 // Set the new mark so that next time we get new data since this point.
12792                 u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
12793 
12794                 long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
12795                 long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
12796 
12797                 if (normalizeScanRxTime) {
12798                     // Scan time is longer than the total rx time in the controller,
12799                     // so distribute the scan time proportionately. This means regular traffic
12800                     // will not blamed, but scans are more expensive anyways.
12801                     scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
12802                 }
12803 
12804                 if (normalizeScanTxTime) {
12805                     // Scan time is longer than the total tx time in the controller,
12806                     // so distribute the scan time proportionately. This means regular traffic
12807                     // will not blamed, but scans are more expensive anyways.
12808                     scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
12809                 }
12810 
12811                 rxTimesMs.incrementValue(u.getUid(), scanTimeRxSinceMarkMs);
12812                 txTimesMs.incrementValue(u.getUid(), scanTimeTxSinceMarkMs);
12813 
12814                 if (uidEstimatedConsumptionMah != null) {
12815                     uidEstimatedConsumptionMah.incrementValue(u.getUid(),
12816                             mBluetoothPowerCalculator.calculatePowerMah(
12817                                     scanTimeRxSinceMarkMs, scanTimeTxSinceMarkMs, 0));
12818                 }
12819 
12820                 leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
12821                 leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
12822             }
12823         }
12824 
12825         if (DEBUG_ENERGY) {
12826             Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX="
12827                     + leftOverTxTimeMs);
12828         }
12829 
12830         //
12831         // Now distribute blame to apps that did bluetooth traffic.
12832         //
12833 
12834         long totalTxBytes = 0;
12835         long totalRxBytes = 0;
12836 
12837         final List<UidTraffic> uidTraffic = info.getUidTraffic();
12838         final int numUids = uidTraffic.size();
12839         for (int i = 0; i < numUids; i++) {
12840             final UidTraffic traffic = uidTraffic.get(i);
12841             final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(
12842                     traffic.getUid());
12843             final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(
12844                     traffic.getUid());
12845 
12846             // Add to the global counters.
12847             mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(rxBytes);
12848             mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes);
12849 
12850             // Add to the UID counters.
12851             final Uid u = getUidStatsLocked(mapUid(traffic.getUid()), elapsedRealtimeMs, uptimeMs);
12852             u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0);
12853             u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0);
12854 
12855             // Calculate the total traffic.
12856             totalRxBytes += rxBytes;
12857             totalTxBytes += txBytes;
12858         }
12859 
12860         if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0
12861                 || leftOverTxTimeMs != 0)) {
12862             for (int i = 0; i < numUids; i++) {
12863                 final UidTraffic traffic = uidTraffic.get(i);
12864                 final int uid = traffic.getUid();
12865                 final long rxBytes =
12866                         traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid);
12867                 final long txBytes =
12868                         traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid);
12869 
12870                 final Uid u = getUidStatsLocked(mapUid(uid), elapsedRealtimeMs, uptimeMs);
12871                 final ControllerActivityCounterImpl counter =
12872                         u.getOrCreateBluetoothControllerActivityLocked();
12873 
12874                 if (totalRxBytes > 0 && rxBytes > 0) {
12875                     final long timeRxMs = (leftOverRxTimeMs * rxBytes) / totalRxBytes;
12876                     rxTimesMs.incrementValue(uid, timeRxMs);
12877                 }
12878 
12879                 if (totalTxBytes > 0 && txBytes > 0) {
12880                     final long timeTxMs = (leftOverTxTimeMs * txBytes) / totalTxBytes;
12881                     txTimesMs.incrementValue(uid, timeTxMs);
12882                 }
12883             }
12884 
12885             for (int i = 0; i < txTimesMs.size(); i++) {
12886                 final int uid = txTimesMs.keyAt(i);
12887                 final long myTxTimeMs = txTimesMs.valueAt(i);
12888                 if (DEBUG_ENERGY) {
12889                     Slog.d(TAG, "  TxTime for UID " + uid + ": " + myTxTimeMs + " ms");
12890                 }
12891                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
12892                         .getOrCreateBluetoothControllerActivityLocked()
12893                         .getOrCreateTxTimeCounters()[0]
12894                         .increment(myTxTimeMs, elapsedRealtimeMs);
12895                 if (uidEstimatedConsumptionMah != null) {
12896                     uidEstimatedConsumptionMah.incrementValue(uid,
12897                             mBluetoothPowerCalculator.calculatePowerMah(0, myTxTimeMs, 0));
12898                 }
12899             }
12900 
12901             for (int i = 0; i < rxTimesMs.size(); i++) {
12902                 final int uid = rxTimesMs.keyAt(i);
12903                 final long myRxTimeMs = rxTimesMs.valueAt(i);
12904                 if (DEBUG_ENERGY) {
12905                     Slog.d(TAG, "  RxTime for UID " + uid + ": " + myRxTimeMs + " ms");
12906                 }
12907 
12908                 getUidStatsLocked(rxTimesMs.keyAt(i), elapsedRealtimeMs, uptimeMs)
12909                         .getOrCreateBluetoothControllerActivityLocked()
12910                         .getOrCreateRxTimeCounter()
12911                         .increment(myRxTimeMs, elapsedRealtimeMs);
12912                 if (uidEstimatedConsumptionMah != null) {
12913                     uidEstimatedConsumptionMah.incrementValue(uid,
12914                             mBluetoothPowerCalculator.calculatePowerMah(myRxTimeMs, 0, 0));
12915                 }
12916             }
12917         }
12918 
12919         mBluetoothActivity.getOrCreateRxTimeCounter().increment(rxTimeMs, elapsedRealtimeMs);
12920         mBluetoothActivity.getOrCreateTxTimeCounters()[0].increment(txTimeMs, elapsedRealtimeMs);
12921         mBluetoothActivity.getOrCreateIdleTimeCounter().increment(idleTimeMs, elapsedRealtimeMs);
12922 
12923         // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
12924         final double opVolt = mPowerProfile.getAveragePower(
12925                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
12926         double controllerMaMs = 0;
12927         if (opVolt != 0) {
12928             controllerMaMs = (info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
12929                     / opVolt;
12930             // We store the power drain as mAms.
12931             mBluetoothActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
12932         }
12933 
12934         // Update the EnergyConsumerStats information.
12935         if (uidEstimatedConsumptionMah != null) {
12936             mGlobalEnergyConsumerStats.updateStandardBucket(
12937                     EnergyConsumerStats.POWER_BUCKET_BLUETOOTH, consumedChargeUC);
12938 
12939             double totalEstimatedMah
12940                     = mBluetoothPowerCalculator.calculatePowerMah(rxTimeMs, txTimeMs, idleTimeMs);
12941             totalEstimatedMah = Math.max(totalEstimatedMah, controllerMaMs / MILLISECONDS_IN_HOUR);
12942             distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_BLUETOOTH,
12943                     consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedMah,
12944                     elapsedRealtimeMs);
12945         }
12946 
12947         mLastBluetoothActivityInfo.set(info);
12948     }
12949     /**
12950      * Read Resource Power Manager (RPM) state and voter times.
12951      * If RPM stats were fetched more recently than RPM_STATS_UPDATE_FREQ_MS ago, uses the old data
12952      * instead of fetching it anew.
12953      *
12954      * Note: This should be called without synchronizing this BatteryStatsImpl object
12955      */
fillLowPowerStats()12956     public void fillLowPowerStats() {
12957         if (mPlatformIdleStateCallback == null) return;
12958 
12959         RpmStats rpmStats = new RpmStats();
12960         long now = SystemClock.elapsedRealtime();
12961         if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
12962             mPlatformIdleStateCallback.fillLowPowerStats(rpmStats);
12963             synchronized (this) {
12964                 mTmpRpmStats = rpmStats;
12965                 mLastRpmStatsUpdateTimeMs = now;
12966             }
12967         }
12968     }
12969 
12970     /**
12971      * Record Resource Power Manager (RPM) state and voter times.
12972      * TODO(b/185252376): Remove this logging. PowerStatsService logs the same data more
12973      * efficiently.
12974      */
updateRpmStatsLocked(long elapsedRealtimeUs)12975     public void updateRpmStatsLocked(long elapsedRealtimeUs) {
12976         if (mTmpRpmStats == null) return;
12977 
12978         for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate
12979                 : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) {
12980 
12981             // Update values for this platform state.
12982             final String pName = pstate.getKey();
12983             final long pTimeUs = pstate.getValue().mTimeMs * 1000;
12984             final int pCount = pstate.getValue().mCount;
12985             getRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs);
12986             if (SCREEN_OFF_RPM_STATS_ENABLED) {
12987                 getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs);
12988             }
12989 
12990             // Update values for each voter of this platform state.
12991             for (Map.Entry<String, RpmStats.PowerStateElement> voter
12992                     : pstate.getValue().mVoters.entrySet()) {
12993                 final String vName = pName + "." + voter.getKey();
12994                 final long vTimeUs = voter.getValue().mTimeMs * 1000;
12995                 final int vCount = voter.getValue().mCount;
12996                 getRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs);
12997                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
12998                     getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs);
12999                 }
13000             }
13001         }
13002 
13003         for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys
13004                 : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) {
13005 
13006             final String subsysName = subsys.getKey();
13007             for (Map.Entry<String, RpmStats.PowerStateElement> sstate
13008                     : subsys.getValue().mStates.entrySet()) {
13009                 final String name = subsysName + "." + sstate.getKey();
13010                 final long timeUs = sstate.getValue().mTimeMs * 1000;
13011                 final int count = sstate.getValue().mCount;
13012                 getRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs);
13013                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
13014                     getScreenOffRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs);
13015                 }
13016             }
13017         }
13018     }
13019 
13020     /**
13021      * Accumulate Cpu charge consumption and distribute it to the correct state and the apps.
13022      * Only call if device is on battery.
13023      *
13024      * @param clusterChargeUC amount of charge (microcoulombs) consumed by each Cpu Cluster
13025      * @param accumulator collection of calculated uid cpu power consumption to smear
13026      *                    clusterChargeUC against.
13027      */
13028     @GuardedBy("this")
13029     @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToStandardBucketLocked
updateCpuEnergyConsumerStatsLocked(@onNull long[] clusterChargeUC, @NonNull CpuDeltaPowerAccumulator accumulator)13030     private void updateCpuEnergyConsumerStatsLocked(@NonNull long[] clusterChargeUC,
13031             @NonNull CpuDeltaPowerAccumulator accumulator) {
13032         if (DEBUG_ENERGY) {
13033             Slog.d(TAG, "Updating cpu cluster stats: " + Arrays.toString(clusterChargeUC));
13034         }
13035         if (mGlobalEnergyConsumerStats == null) {
13036             return;
13037         }
13038 
13039         final int numClusters = clusterChargeUC.length;
13040         long totalCpuChargeUC = 0;
13041         for (int i = 0; i < numClusters; i++) {
13042             totalCpuChargeUC += clusterChargeUC[i];
13043         }
13044         if (totalCpuChargeUC <= 0) return;
13045 
13046         final long timestampMs = mClock.elapsedRealtime();
13047 
13048         mGlobalEnergyConsumerStats.updateStandardBucket(EnergyConsumerStats.POWER_BUCKET_CPU,
13049                 totalCpuChargeUC, timestampMs);
13050 
13051         // Calculate the microcoulombs/milliamp-hour charge ratio for each
13052         // cluster to normalize  each uid's estimated power usage against actual power usage for
13053         // a given cluster.
13054         final double[] clusterChargeRatio = new double[numClusters];
13055         for (int cluster = 0; cluster < numClusters; cluster++) {
13056 
13057             final double totalClusterChargeMah = accumulator.totalClusterChargesMah[cluster];
13058             if (totalClusterChargeMah <= 0.0) {
13059                 // This cluster did not have any work on it, since last update.
13060                 // Avoid dividing by zero.
13061                 clusterChargeRatio[cluster] = 0.0;
13062             } else {
13063                 clusterChargeRatio[cluster] =
13064                         clusterChargeUC[cluster] / accumulator.totalClusterChargesMah[cluster];
13065             }
13066         }
13067 
13068         // Assign and distribute power usage to apps based on their calculated cpu cluster charge.
13069         final long uidChargeArraySize = accumulator.perUidCpuClusterChargesMah.size();
13070         for (int i = 0; i < uidChargeArraySize; i++) {
13071             final Uid uid = accumulator.perUidCpuClusterChargesMah.keyAt(i);
13072             final double[] uidClusterChargesMah = accumulator.perUidCpuClusterChargesMah.valueAt(i);
13073 
13074             // Iterate each cpu cluster and sum the proportional cpu cluster charge to
13075             // get the total cpu charge consumed by a uid.
13076             long uidCpuChargeUC = 0;
13077             for (int cluster = 0; cluster < numClusters; cluster++) {
13078                 final double uidClusterChargeMah = uidClusterChargesMah[cluster];
13079 
13080                 // Proportionally allocate the cpu cluster charge to a uid using the
13081                 // cluster charge/charge ratio. Add 0.5 to round the proportional
13082                 // charge double to the nearest long value.
13083                 final long uidClusterChargeUC =
13084                         (long) (uidClusterChargeMah * clusterChargeRatio[cluster]
13085                                 + 0.5);
13086 
13087                 uidCpuChargeUC += uidClusterChargeUC;
13088             }
13089 
13090             if (uidCpuChargeUC < 0) {
13091                 Slog.wtf(TAG, "Unexpected proportional EnergyConsumer charge "
13092                         + "(" + uidCpuChargeUC + ") for uid " + uid.mUid);
13093                 continue;
13094             }
13095 
13096             uid.addChargeToStandardBucketLocked(uidCpuChargeUC,
13097                     EnergyConsumerStats.POWER_BUCKET_CPU, timestampMs);
13098         }
13099     }
13100 
13101     /**
13102      * Accumulate Display charge consumption and distribute it to the correct state and the apps.
13103      *
13104      * NOTE: The algorithm used makes the strong assumption that app foreground activity time
13105      * is always 0 when the screen is not "ON" and whenever the rail energy is 0 (if supported).
13106      * To the extent that those assumptions are violated, the algorithm will err.
13107      *
13108      * @param chargesUC amount of charge (microcoulombs) used by each Display since this was last
13109      *                 called.
13110      * @param screenStates each screen state at the time this data collection was scheduled
13111      */
13112     @GuardedBy("this")
updateDisplayEnergyConsumerStatsLocked(long[] chargesUC, int[] screenStates, long elapsedRealtimeMs)13113     public void updateDisplayEnergyConsumerStatsLocked(long[] chargesUC, int[] screenStates,
13114             long elapsedRealtimeMs) {
13115         if (DEBUG_ENERGY) Slog.d(TAG, "Updating display stats: " + Arrays.toString(chargesUC));
13116         if (mGlobalEnergyConsumerStats == null) {
13117             return;
13118         }
13119 
13120         final int numDisplays;
13121         if (mPerDisplayBatteryStats.length == screenStates.length) {
13122             numDisplays = screenStates.length;
13123         } else {
13124             // if this point is reached, it will be reached every display state change.
13125             // Rate limit the wtf logging to once every 100 display updates.
13126             if (mDisplayMismatchWtfCount++ % 100 == 0) {
13127                 Slog.wtf(TAG, "Mismatch between PowerProfile reported display count ("
13128                         + mPerDisplayBatteryStats.length
13129                         + ") and PowerStatsHal reported display count (" + screenStates.length
13130                         + ")");
13131             }
13132             // Keep the show going, use the shorter of the two.
13133             numDisplays = mPerDisplayBatteryStats.length < screenStates.length
13134                     ? mPerDisplayBatteryStats.length : screenStates.length;
13135         }
13136 
13137         final int[] oldScreenStates = new int[numDisplays];
13138         for (int i = 0; i < numDisplays; i++) {
13139             final int screenState = screenStates[i];
13140             oldScreenStates[i] = mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement;
13141             mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState;
13142         }
13143 
13144         if (!mOnBatteryInternal) {
13145             // There's nothing further to update.
13146             return;
13147         }
13148         if (mIgnoreNextExternalStats) {
13149             // Although under ordinary resets we won't get here, and typically a new sync will
13150             // happen right after the reset, strictly speaking we need to set all mark times to now.
13151             final int uidStatsSize = mUidStats.size();
13152             for (int i = 0; i < uidStatsSize; i++) {
13153                 final Uid uid = mUidStats.valueAt(i);
13154                 uid.markProcessForegroundTimeUs(elapsedRealtimeMs, false);
13155             }
13156             return;
13157         }
13158 
13159         long totalScreenOnChargeUC = 0;
13160         for (int i = 0; i < numDisplays; i++) {
13161             final long chargeUC = chargesUC[i];
13162             if (chargeUC <= 0) {
13163                 // There's nothing further to update.
13164                 continue;
13165             }
13166 
13167             final @StandardPowerBucket int powerBucket =
13168                     EnergyConsumerStats.getDisplayPowerBucket(oldScreenStates[i]);
13169             mGlobalEnergyConsumerStats.updateStandardBucket(powerBucket, chargeUC);
13170             if (powerBucket == EnergyConsumerStats.POWER_BUCKET_SCREEN_ON) {
13171                 totalScreenOnChargeUC += chargeUC;
13172             }
13173         }
13174 
13175         // Now we blame individual apps, but only if the display was ON.
13176         if (totalScreenOnChargeUC <= 0) {
13177             return;
13178         }
13179         // TODO(b/175726779): Consider unifying the code with the non-rail display power blaming.
13180 
13181         // NOTE: fg time is NOT pooled. If two uids are both somehow in fg, then that time is
13182         // 'double counted' and will simply exceed the realtime that elapsed.
13183         // TODO(b/175726779): collect per display uid visibility for display power attribution.
13184 
13185         // Collect total time since mark so that we can normalize power.
13186         final SparseDoubleArray fgTimeUsArray = new SparseDoubleArray();
13187         final long elapsedRealtimeUs = elapsedRealtimeMs * 1000;
13188         // TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
13189         final int uidStatsSize = mUidStats.size();
13190         for (int i = 0; i < uidStatsSize; i++) {
13191             final Uid uid = mUidStats.valueAt(i);
13192             final long fgTimeUs = uid.markProcessForegroundTimeUs(elapsedRealtimeMs, true);
13193             if (fgTimeUs == 0) continue;
13194             fgTimeUsArray.put(uid.getUid(), (double) fgTimeUs);
13195         }
13196         distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_SCREEN_ON,
13197                 totalScreenOnChargeUC, fgTimeUsArray, 0, elapsedRealtimeMs);
13198     }
13199 
13200     /**
13201      * Accumulate GNSS charge consumption and distribute it to the correct state and the apps.
13202      *
13203      * @param chargeUC amount of charge (microcoulombs) used by GNSS since this was last called.
13204      */
13205     @GuardedBy("this")
13206     public void updateGnssEnergyConsumerStatsLocked(long chargeUC, long elapsedRealtimeMs) {
13207         if (DEBUG_ENERGY) Slog.d(TAG, "Updating gnss stats: " + chargeUC);
13208         if (mGlobalEnergyConsumerStats == null) {
13209             return;
13210         }
13211 
13212         if (!mOnBatteryInternal || chargeUC <= 0) {
13213             // There's nothing further to update.
13214             return;
13215         }
13216         if (mIgnoreNextExternalStats) {
13217             // Although under ordinary resets we won't get here, and typically a new sync will
13218             // happen right after the reset, strictly speaking we need to set all mark times to now.
13219             final int uidStatsSize = mUidStats.size();
13220             for (int i = 0; i < uidStatsSize; i++) {
13221                 final Uid uid = mUidStats.valueAt(i);
13222                 uid.markGnssTimeUs(elapsedRealtimeMs);
13223             }
13224             return;
13225         }
13226 
13227         mGlobalEnergyConsumerStats.updateStandardBucket(EnergyConsumerStats.POWER_BUCKET_GNSS,
13228                 chargeUC);
13229 
13230         // Collect the per uid time since mark so that we can normalize power.
13231         final SparseDoubleArray gnssTimeUsArray = new SparseDoubleArray();
13232         // TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
13233         final int uidStatsSize = mUidStats.size();
13234         for (int i = 0; i < uidStatsSize; i++) {
13235             final Uid uid = mUidStats.valueAt(i);
13236             final long gnssTimeUs = uid.markGnssTimeUs(elapsedRealtimeMs);
13237             if (gnssTimeUs == 0) continue;
13238             gnssTimeUsArray.put(uid.getUid(), (double) gnssTimeUs);
13239         }
13240         distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_GNSS, chargeUC,
13241                 gnssTimeUsArray, 0, elapsedRealtimeMs);
13242     }
13243 
13244     /**
13245      * Accumulate camera charge consumption and distribute it to the correct state and the apps.
13246      *
13247      * @param chargeUC amount of charge (microcoulombs) used by the camera since this was last
13248      *         called.
13249      */
13250     @GuardedBy("this")
13251     public void updateCameraEnergyConsumerStatsLocked(long chargeUC, long elapsedRealtimeMs) {
13252         if (DEBUG_ENERGY) Slog.d(TAG, "Updating camera stats: " + chargeUC);
13253         if (mGlobalEnergyConsumerStats == null) {
13254             return;
13255         }
13256 
13257         if (!mOnBatteryInternal || chargeUC <= 0) {
13258             // There's nothing further to update.
13259             return;
13260         }
13261 
13262         if (mIgnoreNextExternalStats) {
13263             // Although under ordinary resets we won't get here, and typically a new sync will
13264             // happen right after the reset, strictly speaking we need to set all mark times to now.
13265             final int uidStatsSize = mUidStats.size();
13266             for (int i = 0; i < uidStatsSize; i++) {
13267                 final Uid uid = mUidStats.valueAt(i);
13268                 uid.markCameraTimeUs(elapsedRealtimeMs);
13269             }
13270             return;
13271         }
13272 
13273         mGlobalEnergyConsumerStats.updateStandardBucket(
13274                 EnergyConsumerStats.POWER_BUCKET_CAMERA, chargeUC);
13275 
13276         // Collect the per uid time since mark so that we can normalize power.
13277         final SparseDoubleArray cameraTimeUsArray = new SparseDoubleArray();
13278 
13279         // Note: Iterating over all UIDs may be suboptimal.
13280         final int uidStatsSize = mUidStats.size();
13281         for (int i = 0; i < uidStatsSize; i++) {
13282             final Uid uid = mUidStats.valueAt(i);
13283             final long cameraTimeUs = uid.markCameraTimeUs(elapsedRealtimeMs);
13284             if (cameraTimeUs == 0) continue;
13285             cameraTimeUsArray.put(uid.getUid(), (double) cameraTimeUs);
13286         }
13287         distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_CAMERA, chargeUC,
13288                 cameraTimeUsArray, 0, elapsedRealtimeMs);
13289     }
13290 
13291     /**
13292      * Accumulate Custom power bucket charge, globally and for each app.
13293      *
13294      * @param totalChargeUC charge (microcoulombs) used for this bucket since this was last called.
13295      * @param uidCharges map of uid->charge (microcoulombs) for this bucket since last called.
13296      *                    Data inside uidCharges will not be modified (treated immutable).
13297      *                    Uids not already known to BatteryStats will be ignored.
13298      */
13299     @GuardedBy("this")
13300     @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToCustomBucketLocked
13301     public void updateCustomEnergyConsumerStatsLocked(int customPowerBucket,
13302             long totalChargeUC, @Nullable SparseLongArray uidCharges) {
13303         if (DEBUG_ENERGY) {
13304             Slog.d(TAG, "Updating attributed EnergyConsumer stats for custom bucket "
13305                     + customPowerBucket
13306                     + " with total charge " + totalChargeUC
13307                     + " and uid charges " + uidCharges);
13308         }
13309         if (mGlobalEnergyConsumerStats == null) return;
13310         if (!mOnBatteryInternal || mIgnoreNextExternalStats || totalChargeUC <= 0) return;
13311 
13312         mGlobalEnergyConsumerStats.updateCustomBucket(customPowerBucket, totalChargeUC,
13313                 mClock.elapsedRealtime());
13314 
13315         if (uidCharges == null) return;
13316         final int numUids = uidCharges.size();
13317         for (int i = 0; i < numUids; i++) {
13318             final int uidInt = mapUid(uidCharges.keyAt(i));
13319             final long uidChargeUC = uidCharges.valueAt(i);
13320             if (uidChargeUC == 0) continue;
13321 
13322             final Uid uidObj = getAvailableUidStatsLocked(uidInt);
13323             if (uidObj != null) {
13324                 uidObj.addChargeToCustomBucketLocked(uidChargeUC, customPowerBucket);
13325             } else {
13326                 // Ignore any uid not already known to BatteryStats, rather than creating a new Uid.
13327                 // Otherwise we could end up reviving dead Uids. Note that the CPU data is updated
13328                 // first, so any uid that has used any CPU should already be known to BatteryStats.
13329                 // Recently removed uids (especially common for isolated uids) can reach this path
13330                 // and are ignored.
13331                 if (!Process.isIsolated(uidInt)) {
13332                     Slog.w(TAG, "Received EnergyConsumer charge " + totalChargeUC
13333                             + " for custom bucket " + customPowerBucket + " for non-existent uid "
13334                             + uidInt);
13335                 }
13336             }
13337         }
13338     }
13339 
13340     /**
13341      * Attributes energy (for the given bucket) to each uid according to the following formula:
13342      *     blamedEnergy[uid] = totalEnergy * ratioNumerators[uid] / ratioDenominator;
13343      * <p>Does nothing if ratioDenominator is 0.
13344      *
13345      * <p>Here, ratioDenominator = max(sumOfAllRatioNumerators, minRatioDenominator),
13346      * so if given minRatioDenominator <= 0, then sumOfAllRatioNumerators will be used implicitly.
13347      *
13348      * <p>Note that ratioNumerators and minRatioDenominator must use the same units, but need not
13349      * use the same units as totalConsumedChargeUC (which must be in microcoulombs).
13350      *
13351      * <p>A consequence of minRatioDenominator is that the sum over all uids might be less than
13352      * totalConsumedChargeUC. This is intentional; the remainder is purposefully unnaccounted rather
13353      * than incorrectly blamed on uids, and implies unknown (non-uid) sources of drain.
13354      *
13355      * <p>All uids in ratioNumerators must exist in mUidStats already.
13356      */
13357     @GuardedBy("this")
13358     @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToStandardBucketLocked
13359     private void distributeEnergyToUidsLocked(@StandardPowerBucket int bucket,
13360             long totalConsumedChargeUC, SparseDoubleArray ratioNumerators,
13361             double minRatioDenominator, long timestampMs) {
13362 
13363         // If the sum of all app usage was greater than the total, use that instead:
13364         double sumRatioNumerators = 0;
13365         for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
13366             sumRatioNumerators += ratioNumerators.valueAt(i);
13367         }
13368         final double ratioDenominator = Math.max(sumRatioNumerators, minRatioDenominator);
13369         if (ratioDenominator <= 0) return;
13370 
13371         for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
13372             final Uid uid = getAvailableUidStatsLocked(ratioNumerators.keyAt(i));
13373             final double ratioNumerator = ratioNumerators.valueAt(i);
13374             final long uidActualUC
13375                     = (long) (totalConsumedChargeUC * ratioNumerator / ratioDenominator + 0.5);
13376             uid.addChargeToStandardBucketLocked(uidActualUC, bucket, timestampMs);
13377         }
13378     }
13379 
13380     /**
13381      * Read and record Rail Energy data.
13382      */
13383     public void updateRailStatsLocked() {
13384         if (mEnergyConsumerRetriever == null || !mTmpRailStats.isRailStatsAvailable()) {
13385             return;
13386         }
13387         mEnergyConsumerRetriever.fillRailDataStats(mTmpRailStats);
13388     }
13389 
13390     /** Informs that external stats data has been completely flushed. */
13391     public void informThatAllExternalStatsAreFlushed() {
13392         synchronized (this) {
13393             // Any data from the pre-reset era is flushed, so we can henceforth process future data.
13394             mIgnoreNextExternalStats = false;
13395         }
13396     }
13397 
13398     /**
13399      * Read and distribute kernel wake lock use across apps.
13400      */
13401     public void updateKernelWakelocksLocked(long elapsedRealtimeUs) {
13402         final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
13403                 mTmpWakelockStats);
13404         if (wakelockStats == null) {
13405             // Not crashing might make board bringup easier.
13406             Slog.w(TAG, "Couldn't get kernel wake lock stats");
13407             return;
13408         }
13409 
13410         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
13411             String name = ent.getKey();
13412             KernelWakelockStats.Entry kws = ent.getValue();
13413 
13414             SamplingTimer kwlt = mKernelWakelockStats.get(name);
13415             if (kwlt == null) {
13416                 kwlt = new SamplingTimer(mClock, mOnBatteryScreenOffTimeBase);
13417                 mKernelWakelockStats.put(name, kwlt);
13418             }
13419 
13420             kwlt.update(kws.mTotalTime, kws.mCount, elapsedRealtimeUs);
13421             kwlt.setUpdateVersion(kws.mVersion);
13422         }
13423 
13424         int numWakelocksSetStale = 0;
13425         // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
13426         // this time.
13427         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
13428             SamplingTimer st = ent.getValue();
13429             if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
13430                 st.endSample(elapsedRealtimeUs);
13431                 numWakelocksSetStale++;
13432             }
13433         }
13434 
13435         // Record whether we've seen a non-zero time (for debugging b/22716723).
13436         if (wakelockStats.isEmpty()) {
13437             Slog.wtf(TAG, "All kernel wakelocks had time of zero");
13438         }
13439 
13440         if (numWakelocksSetStale == mKernelWakelockStats.size()) {
13441             Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
13442                     wakelockStats.kernelWakelockVersion);
13443         }
13444     }
13445 
13446     // We use an anonymous class to access these variables,
13447     // so they can't live on the stack or they'd have to be
13448     // final MutableLong objects (more allocations).
13449     // Used in updateCpuTimeLocked().
13450     long mTempTotalCpuUserTimeUs;
13451     long mTempTotalCpuSystemTimeUs;
13452     long[][] mWakeLockAllocationsUs;
13453 
13454     /**
13455      * Reads the newest memory stats from the kernel.
13456      */
13457     public void updateKernelMemoryBandwidthLocked(long elapsedRealtimeUs) {
13458         mKernelMemoryBandwidthStats.updateStats();
13459         LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
13460         final int bandwidthEntryCount = bandwidthEntries.size();
13461         int index;
13462         for (int i = 0; i < bandwidthEntryCount; i++) {
13463             SamplingTimer timer;
13464             if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) {
13465                 timer = mKernelMemoryStats.valueAt(index);
13466             } else {
13467                 timer = new SamplingTimer(mClock, mOnBatteryTimeBase);
13468                 mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
13469             }
13470             timer.update(bandwidthEntries.valueAt(i), 1, elapsedRealtimeUs);
13471             if (DEBUG_MEMORY) {
13472                 Slog.d(TAG, String.format("Added entry %d and updated timer to: "
13473                         + "mUnpluggedReportedTotalTimeUs %d size %d", bandwidthEntries.keyAt(i),
13474                         mKernelMemoryStats.get(
13475                                 bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTimeUs,
13476                         mKernelMemoryStats.size()));
13477             }
13478         }
13479     }
13480 
13481     public boolean isOnBatteryLocked() {
13482         return mOnBatteryTimeBase.isRunning();
13483     }
13484 
13485     public boolean isOnBatteryScreenOffLocked() {
13486         return mOnBatteryScreenOffTimeBase.isRunning();
13487     }
13488 
13489     /**
13490      * Object for calculating and accumulating the estimated cpu power used while reading the
13491      * various cpu kernel files.
13492      */
13493     @VisibleForTesting
13494     public static class CpuDeltaPowerAccumulator {
13495         // Keeps track of total charge used per cluster.
13496         public final double[] totalClusterChargesMah;
13497         // Keeps track of charge used per cluster per uid.
13498         public final ArrayMap<Uid, double[]> perUidCpuClusterChargesMah;
13499 
13500         private final CpuPowerCalculator mCalculator;
13501         private Uid mCachedUid = null;
13502         private double[] mUidClusterCache = null;
13503 
13504         CpuDeltaPowerAccumulator(CpuPowerCalculator calculator, int nClusters) {
13505             mCalculator = calculator;
13506             totalClusterChargesMah = new double[nClusters];
13507             perUidCpuClusterChargesMah = new ArrayMap<>();
13508         }
13509 
13510         /** Add per cpu cluster durations to the currently cached uid. */
13511         public void addCpuClusterDurationsMs(Uid uid, long[] durationsMs) {
13512             final double[] uidChargesMah = getOrCreateUidCpuClusterCharges(uid);
13513             for (int cluster = 0; cluster < durationsMs.length; cluster++) {
13514                 final double estimatedDeltaMah = mCalculator.calculatePerCpuClusterPowerMah(cluster,
13515                         durationsMs[cluster]);
13516                 uidChargesMah[cluster] += estimatedDeltaMah;
13517                 totalClusterChargesMah[cluster] += estimatedDeltaMah;
13518             }
13519         }
13520 
13521         /** Add per speed per cpu cluster durations to the currently cached uid. */
13522         public void addCpuClusterSpeedDurationsMs(Uid uid, int cluster, int speed,
13523                 long durationsMs) {
13524             final double[] uidChargesMah = getOrCreateUidCpuClusterCharges(uid);
13525             final double estimatedDeltaMah = mCalculator.calculatePerCpuFreqPowerMah(cluster, speed,
13526                     durationsMs);
13527             uidChargesMah[cluster] += estimatedDeltaMah;
13528             totalClusterChargesMah[cluster] += estimatedDeltaMah;
13529         }
13530 
13531         private double[] getOrCreateUidCpuClusterCharges(Uid uid) {
13532             // Repeated additions on the same uid is very likely.
13533             // Skip a lookup if getting the same uid as the last get.
13534             if (uid == mCachedUid) return mUidClusterCache;
13535 
13536             double[] uidChargesMah = perUidCpuClusterChargesMah.get(uid);
13537             if (uidChargesMah == null) {
13538                 uidChargesMah = new double[totalClusterChargesMah.length];
13539                 perUidCpuClusterChargesMah.put(uid, uidChargesMah);
13540             }
13541             mCachedUid = uid;
13542             mUidClusterCache = uidChargesMah;
13543             return uidChargesMah;
13544         }
13545     }
13546 
13547     /**
13548      * Read and distribute CPU usage across apps. If their are partial wakelocks being held
13549      * and we are on battery with screen off, we give more of the cpu time to those apps holding
13550      * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
13551      * It's possible this will be invoked after the internal battery/screen states are updated, so
13552      * passing the appropriate battery/screen states to try attribute the cpu times to correct
13553      * buckets.
13554      */
13555     @GuardedBy("this")
13556     public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff,
13557             long[] cpuClusterChargeUC) {
13558         if (mPowerProfile == null) {
13559             return;
13560         }
13561 
13562         if (DEBUG_ENERGY_CPU) {
13563             Slog.d(TAG, "!Cpu updating!");
13564         }
13565 
13566         if (mCpuFreqs == null) {
13567             mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
13568         }
13569 
13570         // Calculate the wakelocks we have to distribute amongst. The system is excluded as it is
13571         // usually holding the wakelock on behalf of an app.
13572         // And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
13573         ArrayList<StopwatchTimer> partialTimersToConsider = null;
13574         if (onBatteryScreenOff) {
13575             partialTimersToConsider = new ArrayList<>();
13576             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
13577                 final StopwatchTimer timer = mPartialTimers.get(i);
13578                 // Since the collection and blaming of wakelocks can be scheduled to run after
13579                 // some delay, the mPartialTimers list may have new entries. We can't blame
13580                 // the newly added timer for past cpu time, so we only consider timers that
13581                 // were present for one round of collection. Once a timer has gone through
13582                 // a round of collection, its mInList field is set to true.
13583                 if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
13584                     partialTimersToConsider.add(timer);
13585                 }
13586             }
13587         }
13588         markPartialTimersAsEligible();
13589 
13590         // When the battery is not on, we don't attribute the cpu times to any timers but we still
13591         // need to take the snapshots.
13592         if (!onBattery) {
13593             mCpuUidUserSysTimeReader.readDelta(false, null);
13594             mCpuUidFreqTimeReader.readDelta(false, null);
13595             mNumAllUidCpuTimeReads += 2;
13596             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
13597                 mCpuUidActiveTimeReader.readDelta(false, null);
13598                 mCpuUidClusterTimeReader.readDelta(false, null);
13599                 mNumAllUidCpuTimeReads += 2;
13600             }
13601             for (int cluster = mKernelCpuSpeedReaders.length - 1; cluster >= 0; --cluster) {
13602                 mKernelCpuSpeedReaders[cluster].readDelta();
13603             }
13604             mSystemServerCpuThreadReader.readDelta();
13605             return;
13606         }
13607 
13608         mUserInfoProvider.refreshUserIds();
13609         final SparseLongArray updatedUids = mCpuUidFreqTimeReader.perClusterTimesAvailable()
13610                 ? null : new SparseLongArray();
13611 
13612         final CpuDeltaPowerAccumulator powerAccumulator;
13613         if (mGlobalEnergyConsumerStats != null
13614                 && mGlobalEnergyConsumerStats.isStandardBucketSupported(
13615                 EnergyConsumerStats.POWER_BUCKET_CPU) && mCpuPowerCalculator != null) {
13616             if (cpuClusterChargeUC == null) {
13617                 Slog.wtf(TAG,
13618                         "POWER_BUCKET_CPU supported but no EnergyConsumer Cpu Cluster charge "
13619                                 + "reported on updateCpuTimeLocked!");
13620                 powerAccumulator = null;
13621             } else {
13622                 // Cpu EnergyConsumer is supported, create an object to accumulate the estimated
13623                 // charge consumption since the last cpu update
13624                 final int numClusters = mPowerProfile.getNumCpuClusters();
13625                 powerAccumulator = new CpuDeltaPowerAccumulator(mCpuPowerCalculator, numClusters);
13626             }
13627         } else {
13628             powerAccumulator = null;
13629         }
13630 
13631         readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
13632         // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
13633         // freqs, so no need to approximate these values.
13634         if (updatedUids != null) {
13635             updateClusterSpeedTimes(updatedUids, onBattery, powerAccumulator);
13636         }
13637         readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff,
13638                 powerAccumulator);
13639         mNumAllUidCpuTimeReads += 2;
13640         if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
13641             // Cpu Active times do not get any info ony how to attribute Cpu Cluster
13642             // charge, so not need to provide the powerAccumulator
13643             readKernelUidCpuActiveTimesLocked(onBattery);
13644             readKernelUidCpuClusterTimesLocked(onBattery, powerAccumulator);
13645             mNumAllUidCpuTimeReads += 2;
13646         }
13647 
13648         updateSystemServerThreadStats();
13649 
13650         if (powerAccumulator != null) {
13651             updateCpuEnergyConsumerStatsLocked(cpuClusterChargeUC, powerAccumulator);
13652         }
13653     }
13654 
13655     /**
13656      * Estimates the proportion of the System Server CPU activity (per cluster per speed)
13657      * spent on handling incoming binder calls.
13658      */
13659     @VisibleForTesting
13660     public void updateSystemServerThreadStats() {
13661         // There are some simplifying assumptions made in this algorithm
13662         // 1) We assume that if a thread handles incoming binder calls, all of its activity
13663         //    is spent doing that.  Most incoming calls are handled by threads allocated
13664         //    by the native layer in the binder thread pool, so this assumption is reasonable.
13665         // 2) We use the aggregate CPU time spent in different threads as a proxy for the CPU
13666         //    cost. In reality, in multi-core CPUs, the CPU cost may not be linearly
13667         //    affected by additional threads.
13668 
13669         SystemServerCpuThreadReader.SystemServiceCpuThreadTimes systemServiceCpuThreadTimes =
13670                     mSystemServerCpuThreadReader.readDelta();
13671         if (systemServiceCpuThreadTimes == null) {
13672             return;
13673         }
13674 
13675         if (mBinderThreadCpuTimesUs == null) {
13676             mBinderThreadCpuTimesUs = new LongSamplingCounterArray(mOnBatteryTimeBase);
13677         }
13678         mBinderThreadCpuTimesUs.addCountLocked(systemServiceCpuThreadTimes.binderThreadCpuTimesUs);
13679 
13680         if (DEBUG_BINDER_STATS) {
13681             Slog.d(TAG, "System server threads per CPU cluster (incoming binder threads)");
13682             long binderThreadTimeMs = 0;
13683             int cpuIndex = 0;
13684             final long[] binderThreadCpuTimesUs = mBinderThreadCpuTimesUs.getCountsLocked(
13685                     BatteryStats.STATS_SINCE_CHARGED);
13686             int index = 0;
13687             int numCpuClusters = mPowerProfile.getNumCpuClusters();
13688             for (int cluster = 0; cluster < numCpuClusters; cluster++) {
13689                 StringBuilder sb = new StringBuilder();
13690                 sb.append("cpu").append(cpuIndex).append(": [");
13691                 int numSpeeds = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
13692                 for (int speed = 0; speed < numSpeeds; speed++) {
13693                     if (speed != 0) {
13694                         sb.append(", ");
13695                     }
13696                     long binderCountMs = binderThreadCpuTimesUs[index] / 1000;
13697                     sb.append(TextUtils.formatSimple("%10d", binderCountMs));
13698 
13699                     binderThreadTimeMs += binderCountMs;
13700                     index++;
13701                 }
13702                 cpuIndex += mPowerProfile.getNumCoresInCpuCluster(cluster);
13703                 Slog.d(TAG, sb.toString());
13704             }
13705         }
13706     }
13707 
13708     /**
13709      * Mark the current partial timers as gone through a collection so that they will be
13710      * considered in the next cpu times distribution to wakelock holders.
13711      */
13712     @VisibleForTesting
13713     public void markPartialTimersAsEligible() {
13714         if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
13715             // No difference, so each timer is now considered for the next collection.
13716             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
13717                 mPartialTimers.get(i).mInList = true;
13718             }
13719         } else {
13720             // The lists are different, meaning we added (or removed a timer) since the last
13721             // collection.
13722             for (int i = mLastPartialTimers.size() - 1; i >= 0; --i) {
13723                 mLastPartialTimers.get(i).mInList = false;
13724             }
13725             mLastPartialTimers.clear();
13726 
13727             // Mark the current timers as gone through a collection.
13728             final int numPartialTimers = mPartialTimers.size();
13729             for (int i = 0; i < numPartialTimers; ++i) {
13730                 final StopwatchTimer timer = mPartialTimers.get(i);
13731                 timer.mInList = true;
13732                 mLastPartialTimers.add(timer);
13733             }
13734         }
13735     }
13736 
13737     /**
13738      * Take snapshot of cpu times (aggregated over all uids) at different frequencies and
13739      * calculate cpu times spent by each uid at different frequencies. Will also add estimated
13740      * power consumptions, if powerAccumulator data structure is provided.
13741      *
13742      * @param updatedUids  The uids for which times spent at different frequencies are calculated.
13743      * @param onBattery whether or not this is onBattery
13744      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
13745      */
13746     @VisibleForTesting
13747     public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery,
13748             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
13749         long totalCpuClustersTimeMs = 0;
13750         // Read the time spent for each cluster at various cpu frequencies.
13751         final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
13752         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
13753             clusterSpeedTimesMs[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
13754             if (clusterSpeedTimesMs[cluster] != null) {
13755                 for (int speed = clusterSpeedTimesMs[cluster].length - 1; speed >= 0; --speed) {
13756                     totalCpuClustersTimeMs += clusterSpeedTimesMs[cluster][speed];
13757                 }
13758             }
13759         }
13760         if (totalCpuClustersTimeMs != 0) {
13761             // We have cpu times per freq aggregated over all uids but we need the times per uid.
13762             // So, we distribute total time spent by an uid to different cpu freqs based on the
13763             // amount of time cpu was running at that freq.
13764             final int updatedUidsCount = updatedUids.size();
13765             final long elapsedRealtimeMs = mClock.elapsedRealtime();
13766             final long uptimeMs = mClock.uptimeMillis();
13767             for (int i = 0; i < updatedUidsCount; ++i) {
13768                 final Uid u = getUidStatsLocked(updatedUids.keyAt(i), elapsedRealtimeMs, uptimeMs);
13769                 final long appCpuTimeUs = updatedUids.valueAt(i);
13770                 // Add the cpu speeds to this UID.
13771                 final int numClusters = mPowerProfile.getNumCpuClusters();
13772                 if (u.mCpuClusterSpeedTimesUs == null ||
13773                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
13774                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
13775                 }
13776 
13777                 for (int cluster = 0; cluster < clusterSpeedTimesMs.length; cluster++) {
13778                     final int speedsInCluster = clusterSpeedTimesMs[cluster].length;
13779                     if (u.mCpuClusterSpeedTimesUs[cluster] == null || speedsInCluster !=
13780                             u.mCpuClusterSpeedTimesUs[cluster].length) {
13781                         u.mCpuClusterSpeedTimesUs[cluster]
13782                                 = new LongSamplingCounter[speedsInCluster];
13783                     }
13784 
13785                     final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeedTimesUs[cluster];
13786                     for (int speed = 0; speed < speedsInCluster; speed++) {
13787                         if (cpuSpeeds[speed] == null) {
13788                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
13789                         }
13790                         final long deltaSpeedCount = appCpuTimeUs
13791                                 * clusterSpeedTimesMs[cluster][speed]
13792                                 / totalCpuClustersTimeMs;
13793                         cpuSpeeds[speed].addCountLocked(deltaSpeedCount, onBattery);
13794 
13795                         if (powerAccumulator != null) {
13796                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
13797                                     speed, deltaSpeedCount);
13798                         }
13799                     }
13800                 }
13801             }
13802         }
13803     }
13804 
13805     /**
13806      * Take a snapshot of the cpu times spent by each uid and update the corresponding counters.
13807      * If {@param partialTimers} is not null and empty, then we assign a portion of cpu times to
13808      * wakelock holders.
13809      *
13810      * @param partialTimers The wakelock holders among which the cpu times will be distributed.
13811      * @param updatedUids If not null, then the uids found in the snapshot will be added to this.
13812      */
13813     @VisibleForTesting
13814     public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
13815             @Nullable SparseLongArray updatedUids, boolean onBattery) {
13816         mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
13817         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
13818         final long startTimeMs = mClock.uptimeMillis();
13819         final long elapsedRealtimeMs = mClock.elapsedRealtime();
13820 
13821         mCpuUidUserSysTimeReader.readDelta(false, (uid, timesUs) -> {
13822             long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
13823 
13824             uid = mapUid(uid);
13825             if (Process.isIsolated(uid)) {
13826                 // This could happen if the isolated uid mapping was removed before that process
13827                 // was actually killed.
13828                 if (DEBUG) Slog.d(TAG, "Got readings for an isolated uid: " + uid);
13829                 return;
13830             }
13831             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
13832                 if (DEBUG) Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
13833                 return;
13834             }
13835             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
13836 
13837             // Accumulate the total system and user time.
13838             mTempTotalCpuUserTimeUs += userTimeUs;
13839             mTempTotalCpuSystemTimeUs += systemTimeUs;
13840 
13841             StringBuilder sb = null;
13842             if (DEBUG_ENERGY_CPU) {
13843                 sb = new StringBuilder();
13844                 sb.append("  got time for uid=").append(u.mUid).append(": u=");
13845                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
13846                 sb.append(" s=");
13847                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
13848                 sb.append("\n");
13849             }
13850 
13851             if (numWakelocks > 0) {
13852                 // We have wakelocks being held, so only give a portion of the
13853                 // time to the process. The rest will be distributed among wakelock
13854                 // holders.
13855                 userTimeUs = (userTimeUs * WAKE_LOCK_WEIGHT) / 100;
13856                 systemTimeUs = (systemTimeUs * WAKE_LOCK_WEIGHT) / 100;
13857             }
13858 
13859             if (sb != null) {
13860                 sb.append("  adding to uid=").append(u.mUid).append(": u=");
13861                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
13862                 sb.append(" s=");
13863                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
13864                 Slog.d(TAG, sb.toString());
13865             }
13866 
13867             u.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
13868             u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
13869             if (updatedUids != null) {
13870                 updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
13871             }
13872         });
13873 
13874         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
13875         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
13876             Slog.d(TAG, "Reading cpu stats took " + elapsedTimeMs + "ms");
13877         }
13878 
13879         if (numWakelocks > 0) {
13880             // Distribute a portion of the total cpu time to wakelock holders.
13881             mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
13882             mTempTotalCpuSystemTimeUs =
13883                     (mTempTotalCpuSystemTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
13884 
13885             for (int i = 0; i < numWakelocks; ++i) {
13886                 final StopwatchTimer timer = partialTimers.get(i);
13887                 final int userTimeUs = (int) (mTempTotalCpuUserTimeUs / (numWakelocks - i));
13888                 final int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / (numWakelocks - i));
13889 
13890                 if (DEBUG_ENERGY_CPU) {
13891                     final StringBuilder sb = new StringBuilder();
13892                     sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
13893                             .append(": u=");
13894                     TimeUtils.formatDuration(userTimeUs / 1000, sb);
13895                     sb.append(" s=");
13896                     TimeUtils.formatDuration(systemTimeUs / 1000, sb);
13897                     Slog.d(TAG, sb.toString());
13898                 }
13899 
13900                 timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
13901                 timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
13902                 if (updatedUids != null) {
13903                     final int uid = timer.mUid.getUid();
13904                     updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
13905                 }
13906 
13907                 final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
13908                 proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery);
13909 
13910                 mTempTotalCpuUserTimeUs -= userTimeUs;
13911                 mTempTotalCpuSystemTimeUs -= systemTimeUs;
13912             }
13913         }
13914     }
13915 
13916     /**
13917      * Take a snapshot of the cpu times spent by each uid in each freq and update the
13918      * corresponding counters.  Will also add estimated power consumptions, if powerAccumulator
13919      * data structure is provided.
13920      *
13921      * @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
13922      * @param onBattery whether or not this is onBattery
13923      * @param onBatteryScreenOff whether or not this is onBattery with the screen off.
13924      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
13925      */
13926     @VisibleForTesting
13927     public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
13928             boolean onBattery, boolean onBatteryScreenOff,
13929             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
13930         final boolean perClusterTimesAvailable =
13931                 mCpuUidFreqTimeReader.perClusterTimesAvailable();
13932         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
13933         final int numClusters = mPowerProfile.getNumCpuClusters();
13934         mWakeLockAllocationsUs = null;
13935         final long startTimeMs = mClock.uptimeMillis();
13936         final long elapsedRealtimeMs = mClock.elapsedRealtime();
13937         // If power is being accumulated for attribution, data needs to be read immediately.
13938         final boolean forceRead = powerAccumulator != null;
13939         mCpuUidFreqTimeReader.readDelta(forceRead, (uid, cpuFreqTimeMs) -> {
13940             uid = mapUid(uid);
13941             if (Process.isIsolated(uid)) {
13942                 if (DEBUG) Slog.d(TAG, "Got freq readings for an isolated uid: " + uid);
13943                 return;
13944             }
13945             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
13946                 if (DEBUG) Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
13947                 return;
13948             }
13949             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
13950             if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
13951                 detachIfNotNull(u.mCpuFreqTimeMs);
13952                 u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
13953             }
13954             u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
13955             if (u.mScreenOffCpuFreqTimeMs == null ||
13956                     u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
13957                 detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
13958                 u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
13959                         mOnBatteryScreenOffTimeBase);
13960             }
13961             u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff);
13962 
13963             if (perClusterTimesAvailable) {
13964                 if (u.mCpuClusterSpeedTimesUs == null ||
13965                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
13966                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
13967                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
13968                 }
13969                 if (numWakelocks > 0 && mWakeLockAllocationsUs == null) {
13970                     mWakeLockAllocationsUs = new long[numClusters][];
13971                 }
13972 
13973                 int freqIndex = 0;
13974                 for (int cluster = 0; cluster < numClusters; ++cluster) {
13975                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
13976                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
13977                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
13978                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
13979                         u.mCpuClusterSpeedTimesUs[cluster]
13980                                 = new LongSamplingCounter[speedsInCluster];
13981                     }
13982                     if (numWakelocks > 0 && mWakeLockAllocationsUs[cluster] == null) {
13983                         mWakeLockAllocationsUs[cluster] = new long[speedsInCluster];
13984                     }
13985                     final LongSamplingCounter[] cpuTimesUs = u.mCpuClusterSpeedTimesUs[cluster];
13986                     for (int speed = 0; speed < speedsInCluster; ++speed) {
13987                         if (cpuTimesUs[speed] == null) {
13988                             cpuTimesUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
13989                         }
13990                         final long appAllocationUs;
13991                         if (mWakeLockAllocationsUs != null) {
13992                             appAllocationUs =
13993                                     (cpuFreqTimeMs[freqIndex] * 1000 * WAKE_LOCK_WEIGHT) / 100;
13994                             mWakeLockAllocationsUs[cluster][speed] +=
13995                                     (cpuFreqTimeMs[freqIndex] * 1000 - appAllocationUs);
13996                         } else {
13997                             appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
13998                         }
13999                         cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
14000 
14001                         if (powerAccumulator != null) {
14002                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
14003                                     speed, appAllocationUs / 1000);
14004                         }
14005                         freqIndex++;
14006                     }
14007                 }
14008             }
14009         });
14010 
14011         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
14012         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
14013             Slog.d(TAG, "Reading cpu freq times took " + elapsedTimeMs + "ms");
14014         }
14015 
14016         if (mWakeLockAllocationsUs != null) {
14017             for (int i = 0; i < numWakelocks; ++i) {
14018                 final Uid u = partialTimers.get(i).mUid;
14019                 if (u.mCpuClusterSpeedTimesUs == null ||
14020                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
14021                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
14022                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
14023                 }
14024 
14025                 for (int cluster = 0; cluster < numClusters; ++cluster) {
14026                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
14027                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
14028                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
14029                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
14030                         u.mCpuClusterSpeedTimesUs[cluster]
14031                                 = new LongSamplingCounter[speedsInCluster];
14032                     }
14033                     final LongSamplingCounter[] cpuTimeUs = u.mCpuClusterSpeedTimesUs[cluster];
14034                     for (int speed = 0; speed < speedsInCluster; ++speed) {
14035                         if (cpuTimeUs[speed] == null) {
14036                             cpuTimeUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
14037                         }
14038                         final long allocationUs =
14039                                 mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
14040                         cpuTimeUs[speed].addCountLocked(allocationUs, onBattery);
14041                         mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
14042 
14043                         if (powerAccumulator != null) {
14044                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
14045                                     speed, allocationUs / 1000);
14046                         }
14047                     }
14048                 }
14049             }
14050         }
14051     }
14052 
14053     /**
14054      * Take a snapshot of the cpu active times spent by each uid and update the corresponding
14055      * counters.
14056      */
14057     @VisibleForTesting
14058     public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
14059         final long startTimeMs = mClock.uptimeMillis();
14060         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14061         mCpuUidActiveTimeReader.readAbsolute((uid, cpuActiveTimesMs) -> {
14062             final int parentUid = mapUid(uid);
14063             if (Process.isIsolated(parentUid)) {
14064                 if (DEBUG) Slog.w(TAG, "Got active times for an isolated uid: " + uid);
14065                 return;
14066             }
14067             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
14068                 if (DEBUG) Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
14069                 return;
14070             }
14071             final Uid u = getUidStatsLocked(parentUid, elapsedRealtimeMs, startTimeMs);
14072             if (parentUid == uid) {
14073                 u.getCpuActiveTimeCounter().update(cpuActiveTimesMs, elapsedRealtimeMs);
14074             } else {
14075                 final SparseArray<Uid.ChildUid> childUids = u.mChildUids;
14076                 if (childUids == null) {
14077                     return;
14078                 }
14079 
14080                 Uid.ChildUid childUid = childUids.get(uid);
14081                 if (childUid != null) {
14082                     final long delta =
14083                             childUid.cpuActiveCounter.update(cpuActiveTimesMs, elapsedRealtimeMs);
14084                     u.getCpuActiveTimeCounter().increment(delta, elapsedRealtimeMs);
14085                 }
14086             }
14087         });
14088 
14089         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
14090         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
14091             Slog.d(TAG, "Reading cpu active times took " + elapsedTimeMs + "ms");
14092         }
14093     }
14094 
14095     /**
14096      * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding
14097      * counters. Will also add estimated power consumptions, if powerAccumulator data structure
14098      * is provided.
14099      *
14100      * @param onBattery whether or not this is onBattery
14101      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
14102      */
14103     @VisibleForTesting
14104     public void readKernelUidCpuClusterTimesLocked(boolean onBattery,
14105             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
14106         final long startTimeMs = mClock.uptimeMillis();
14107         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14108         // If power is being accumulated for attribution, data needs to be read immediately.
14109         final boolean forceRead = powerAccumulator != null;
14110         mCpuUidClusterTimeReader.readDelta(forceRead, (uid, cpuClusterTimesMs) -> {
14111             uid = mapUid(uid);
14112             if (Process.isIsolated(uid)) {
14113                 if (DEBUG) Slog.w(TAG, "Got cluster times for an isolated uid: " + uid);
14114                 return;
14115             }
14116             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
14117                 if (DEBUG) Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
14118                 return;
14119             }
14120             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
14121             u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesMs, onBattery);
14122 
14123             if (powerAccumulator != null) {
14124                 powerAccumulator.addCpuClusterDurationsMs(u, cpuClusterTimesMs);
14125             }
14126         });
14127 
14128         final long elapsedTimeMs = mClock.uptimeMillis() - startTimeMs;
14129         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
14130             Slog.d(TAG, "Reading cpu cluster times took " + elapsedTimeMs + "ms");
14131         }
14132     }
14133 
14134     boolean setChargingLocked(boolean charging) {
14135         // if the device is no longer charging, remove the callback
14136         // if the device is now charging, it means that this is either called
14137         // 1. directly when level >= 90
14138         // 2. or from within the runnable that we deferred
14139         // For 1. if we have an existing callback, remove it, since we will immediately send a
14140         // ACTION_CHARGING
14141         // For 2. we remove existing callback so we don't send multiple ACTION_CHARGING
14142         mHandler.removeCallbacks(mDeferSetCharging);
14143         if (mCharging != charging) {
14144             mCharging = charging;
14145             mHistory.setChargingState(charging);
14146             mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
14147             return true;
14148         }
14149         return false;
14150     }
14151 
14152     /**
14153      * Notifies BatteryStatsImpl that the system server is ready.
14154      */
14155     public void onSystemReady() {
14156         mSystemReady = true;
14157     }
14158 
14159     /**
14160      * Force recording of all history events regardless of the "charging" state.
14161      */
14162     @VisibleForTesting
14163     public void forceRecordAllHistory() {
14164         mHistory.forceRecordAllHistory();
14165         mRecordAllHistory = true;
14166     }
14167 
14168     /**
14169      * Might reset battery stats if conditions are met. Assumed the device is currently plugged in.
14170      */
14171     @VisibleForTesting
14172     @GuardedBy("this")
14173     public void maybeResetWhilePluggedInLocked() {
14174         final long elapsedRealtimeMs = mClock.elapsedRealtime();
14175         if (shouldResetWhilePluggedInLocked(elapsedRealtimeMs)) {
14176             Slog.i(TAG,
14177                     "Resetting due to long plug in duration. elapsed time = " + elapsedRealtimeMs
14178                             + " ms, last plug in time = " + mBatteryPluggedInRealTimeMs
14179                             + " ms, last reset time = " + mRealtimeStartUs / 1000);
14180             resetAllStatsAndHistoryLocked(RESET_REASON_PLUGGED_IN_FOR_LONG_DURATION);
14181         }
14182 
14183         scheduleNextResetWhilePluggedInCheck();
14184     }
14185 
14186     @GuardedBy("this")
14187     private void scheduleNextResetWhilePluggedInCheck() {
14188         if (mAlarmManager == null) return;
14189         final long timeoutMs = mClock.currentTimeMillis()
14190                 + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
14191                 * DateUtils.HOUR_IN_MILLIS;
14192         Calendar nextAlarm = Calendar.getInstance();
14193         nextAlarm.setTimeInMillis(timeoutMs);
14194 
14195         // Find the 2 AM the same day as the end of the minimum duration.
14196         // This logic does not handle a Daylight Savings transition, or a timezone change
14197         // while the alarm has been set. The need to reset after a long period while plugged
14198         // in is not strict enough to warrant a well architected out solution.
14199         nextAlarm.set(Calendar.MILLISECOND, 0);
14200         nextAlarm.set(Calendar.SECOND, 0);
14201         nextAlarm.set(Calendar.MINUTE, 0);
14202         nextAlarm.set(Calendar.HOUR_OF_DAY, 2);
14203         long possibleNextTimeMs = nextAlarm.getTimeInMillis();
14204         if (possibleNextTimeMs < timeoutMs) {
14205             // The 2AM on the day of the timeout, move on the next day.
14206             possibleNextTimeMs += DateUtils.DAY_IN_MILLIS;
14207         }
14208         final long nextTimeMs = possibleNextTimeMs;
14209         final AlarmManager am = mAlarmManager;
14210         mHandler.post(() -> am.setWindow(AlarmManager.RTC, nextTimeMs,
14211                 DateUtils.HOUR_IN_MILLIS,
14212                 TAG, mLongPlugInAlarmHandler, mHandler));
14213     }
14214 
14215 
14216     @GuardedBy("this")
14217     private boolean shouldResetWhilePluggedInLocked(long elapsedRealtimeMs) {
14218         if (mNoAutoReset) return false;
14219         if (!mSystemReady) return false;
14220         if (!mHistory.isResetEnabled()) return false;
14221 
14222         final long pluggedInThresholdMs = mBatteryPluggedInRealTimeMs
14223                 + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
14224                 * DateUtils.HOUR_IN_MILLIS;
14225         if (elapsedRealtimeMs >= pluggedInThresholdMs) {
14226             // The device has been plugged in for a long time.
14227             final long resetThresholdMs = mRealtimeStartUs / 1000
14228                     + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
14229                     * DateUtils.HOUR_IN_MILLIS;
14230             if (elapsedRealtimeMs >= resetThresholdMs) {
14231                 // And it has been a long time since the last reset.
14232                 return true;
14233             }
14234         }
14235 
14236         return false;
14237     }
14238 
14239     @GuardedBy("this")
14240     private boolean shouldResetOnUnplugLocked(int batteryStatus, int batteryLevel) {
14241         if (mNoAutoReset) return false;
14242         if (!mSystemReady) return false;
14243         if (!mHistory.isResetEnabled()) return false;
14244         if (mBatteryStatsConfig.shouldResetOnUnplugHighBatteryLevel()) {
14245             // Allow resetting due to currently being at high battery level
14246             if (batteryStatus == BatteryManager.BATTERY_STATUS_FULL) return true;
14247             if (batteryLevel >= 90) return true;
14248         }
14249         if (mBatteryStatsConfig.shouldResetOnUnplugAfterSignificantCharge()) {
14250             // Allow resetting after a significant charge (from a very low level to a now very
14251             // high level).
14252             if (mDischargePlugLevel < 20 && batteryLevel >= 80) return true;
14253         }
14254         if (getHighDischargeAmountSinceCharge() >= 200) {
14255             // Reset the stats if battery got partially charged and discharged repeatedly without
14256             // ever reaching the full charge.
14257             // This reset is done in order to prevent stats sessions from going on forever.
14258             // Exceedingly long battery sessions would lead to an overflow of
14259             // data structures such as mWakeupReasonStats.
14260             return true;
14261         }
14262 
14263         return false;
14264     }
14265 
14266     @GuardedBy("this")
14267     protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
14268             final boolean onBattery, final int oldStatus, final int level, final int chargeUah) {
14269         boolean doWrite = false;
14270         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
14271         m.arg1 = onBattery ? 1 : 0;
14272         mHandler.sendMessage(m);
14273 
14274         final long uptimeUs = mSecUptime * 1000;
14275         final long realtimeUs = mSecRealtime * 1000;
14276         final int screenState = mScreenState;
14277         if (onBattery) {
14278             boolean reset = false;
14279             if (shouldResetOnUnplugLocked(oldStatus, level)) {
14280                 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
14281                         + " dischargeLevel=" + mDischargePlugLevel
14282                         + " lowAmount=" + getLowDischargeAmountSinceCharge()
14283                         + " highAmount=" + getHighDischargeAmountSinceCharge());
14284                 // Before we write, collect a snapshot of the final aggregated
14285                 // stats to be reported in the next checkin.  Only do this if we have
14286                 // a sufficient amount of data to make it interesting.
14287                 if (getLowDischargeAmountSinceCharge() >= 20) {
14288                     final long startTimeMs = SystemClock.uptimeMillis();
14289                     final Parcel parcel = Parcel.obtain();
14290                     writeSummaryToParcel(parcel, true);
14291                     final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs;
14292                     BackgroundThread.getHandler().post(new Runnable() {
14293                         @Override public void run() {
14294                             synchronized (mCheckinFile) {
14295                                 final long startTimeMs2 = SystemClock.uptimeMillis();
14296                                 FileOutputStream stream = null;
14297                                 try {
14298                                     stream = mCheckinFile.startWrite();
14299                                     stream.write(parcel.marshall());
14300                                     stream.flush();
14301                                     mCheckinFile.finishWrite(stream);
14302                                     com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
14303                                             "batterystats-checkin", initialTimeMs
14304                                             + SystemClock.uptimeMillis() - startTimeMs2);
14305                                 } catch (IOException e) {
14306                                     Slog.w("BatteryStats",
14307                                             "Error writing checkin battery statistics", e);
14308                                     mCheckinFile.failWrite(stream);
14309                                 } finally {
14310                                     parcel.recycle();
14311                                 }
14312                             }
14313                         }
14314                     });
14315                 }
14316                 doWrite = true;
14317                 resetAllStatsLocked(mSecUptime, mSecRealtime, RESET_REASON_FULL_CHARGE);
14318                 if (chargeUah > 0 && level > 0) {
14319                     // Only use the reported coulomb charge value if it is supported and reported.
14320                     mEstimatedBatteryCapacityMah = (int) ((chargeUah / 1000) / (level / 100.0));
14321                 }
14322                 reset = true;
14323                 mDischargeStepTracker.init();
14324             }
14325             if (mCharging) {
14326                 setChargingLocked(false);
14327             }
14328             mOnBattery = mOnBatteryInternal = true;
14329             mLastDischargeStepLevel = level;
14330             mMinDischargeStepLevel = level;
14331             mDischargeStepTracker.clearTime();
14332             mDailyDischargeStepTracker.clearTime();
14333             mInitStepMode = mCurStepMode;
14334             mModStepMode = 0;
14335             pullPendingStateUpdatesLocked();
14336             if (reset) {
14337                 mHistory.startRecordingHistory(mSecRealtime, mSecUptime, reset);
14338                 initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
14339             }
14340             mBatteryPluggedIn = false;
14341             if (mAlarmManager != null) {
14342                 final AlarmManager am = mAlarmManager;
14343                 mHandler.post(() -> {
14344                     // No longer plugged in. Cancel the long plug in alarm.
14345                     am.cancel(mLongPlugInAlarmHandler);
14346                 });
14347             }
14348             mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
14349             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
14350             if (Display.isOnState(screenState)) {
14351                 mDischargeScreenOnUnplugLevel = level;
14352                 mDischargeScreenDozeUnplugLevel = 0;
14353                 mDischargeScreenOffUnplugLevel = 0;
14354             } else if (Display.isDozeState(screenState)) {
14355                 mDischargeScreenOnUnplugLevel = 0;
14356                 mDischargeScreenDozeUnplugLevel = level;
14357                 mDischargeScreenOffUnplugLevel = 0;
14358             } else {
14359                 mDischargeScreenOnUnplugLevel = 0;
14360                 mDischargeScreenDozeUnplugLevel = 0;
14361                 mDischargeScreenOffUnplugLevel = level;
14362             }
14363             mDischargeAmountScreenOn = 0;
14364             mDischargeAmountScreenDoze = 0;
14365             mDischargeAmountScreenOff = 0;
14366             updateTimeBasesLocked(true, screenState, uptimeUs, realtimeUs);
14367         } else {
14368             mOnBattery = mOnBatteryInternal = false;
14369             pullPendingStateUpdatesLocked();
14370             mBatteryPluggedIn = true;
14371             mBatteryPluggedInRealTimeMs = mSecRealtime;
14372             mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
14373             mDischargeCurrentLevel = mDischargePlugLevel = level;
14374             if (level < mDischargeUnplugLevel) {
14375                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
14376                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
14377             }
14378             updateDischargeScreenLevelsLocked(screenState, screenState);
14379             updateTimeBasesLocked(false, screenState, uptimeUs, realtimeUs);
14380             mChargeStepTracker.init();
14381             mLastChargeStepLevel = level;
14382             mMaxChargeStepLevel = level;
14383             mInitStepMode = mCurStepMode;
14384             mModStepMode = 0;
14385             scheduleNextResetWhilePluggedInCheck();
14386         }
14387         if (doWrite || (mLastWriteTimeMs + (60 * 1000)) < mSecRealtime) {
14388             if (mStatsFile != null && !mHistory.isReadOnly()) {
14389                 writeAsyncLocked();
14390             }
14391         }
14392     }
14393 
14394     private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
14395         if (mExternalSync != null) {
14396             mExternalSync.scheduleSync(reason, updateFlags);
14397         }
14398     }
14399 
14400     // This should probably be exposed in the API, though it's not critical
14401     public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
14402 
14403     @GuardedBy("this")
14404     public void setBatteryStateLocked(final int status, final int health, final int plugType,
14405             final int level, /* not final */ int temp, final int voltageMv, final int chargeUah,
14406             final int chargeFullUah, final long chargeTimeToFullSeconds,
14407             final long elapsedRealtimeMs, final long uptimeMs, final long currentTimeMs) {
14408         // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
14409         temp = Math.max(0, temp);
14410 
14411         reportChangesToStatsLog(status, plugType, level);
14412 
14413         final boolean onBattery = isOnBattery(plugType, status);
14414         if (!mHaveBatteryLevel) {
14415             mHaveBatteryLevel = true;
14416             // We start out assuming that the device is plugged in (not
14417             // on battery).  If our first report is now that we are indeed
14418             // plugged in, then twiddle our state to correctly reflect that
14419             // since we won't be going through the full setOnBattery().
14420             if (onBattery == mOnBattery) {
14421                 mHistory.setPluggedInState(!onBattery);
14422             }
14423             mBatteryStatus = status;
14424             mBatteryLevel = level;
14425             mBatteryChargeUah = chargeUah;
14426 
14427             // Always start out assuming charging, that will be updated later.
14428             mHistory.setBatteryState(true /* charging */, status, level, chargeUah);
14429 
14430             mMaxChargeStepLevel = mMinDischargeStepLevel =
14431                     mLastChargeStepLevel = mLastDischargeStepLevel = level;
14432         } else if (mBatteryLevel != level || mOnBattery != onBattery) {
14433             recordDailyStatsIfNeededLocked(level >= 100 && onBattery, currentTimeMs);
14434         }
14435         int oldStatus = mBatteryStatus;
14436         if (onBattery) {
14437             mDischargeCurrentLevel = level;
14438             if (!mHistory.isRecordingHistory()) {
14439                 mHistory.startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
14440             }
14441         } else if (level < 96 &&
14442                 status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
14443             if (!mHistory.isRecordingHistory()) {
14444                 mHistory.startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
14445             }
14446         }
14447         if (mDischargePlugLevel < 0) {
14448             mDischargePlugLevel = level;
14449         }
14450 
14451         if (onBattery != mOnBattery) {
14452             mBatteryLevel = level;
14453             mBatteryStatus = status;
14454             mBatteryHealth = health;
14455             mBatteryPlugType = plugType;
14456             mBatteryTemperature = temp;
14457             mBatteryVoltageMv = voltageMv;
14458             mHistory.setBatteryState(status, level, health, plugType, temp, voltageMv, chargeUah);
14459             if (chargeUah < mBatteryChargeUah) {
14460                 // Only record discharges
14461                 final long chargeDiff = (long) mBatteryChargeUah - chargeUah;
14462                 mDischargeCounter.addCountLocked(chargeDiff);
14463                 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
14464                 if (Display.isDozeState(mScreenState)) {
14465                     mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
14466                 }
14467                 if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
14468                     mDischargeLightDozeCounter.addCountLocked(chargeDiff);
14469                 } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
14470                     mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
14471                 }
14472             }
14473             mBatteryChargeUah = chargeUah;
14474             setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUah);
14475         } else {
14476             boolean changed = false;
14477             if (mBatteryLevel != level) {
14478                 mBatteryLevel = level;
14479                 changed = true;
14480 
14481                 // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
14482                 // which will pull external stats.
14483                 mExternalSync.scheduleSyncDueToBatteryLevelChange(
14484                         mConstants.BATTERY_LEVEL_COLLECTION_DELAY_MS);
14485             }
14486             if (mBatteryStatus != status) {
14487                 mBatteryStatus = status;
14488                 changed = true;
14489             }
14490             if (mBatteryHealth != health) {
14491                 mBatteryHealth = health;
14492                 changed = true;
14493             }
14494             if (mBatteryPlugType != plugType) {
14495                 mBatteryPlugType = plugType;
14496                 changed = true;
14497             }
14498             if (temp >= (mBatteryTemperature + 10)
14499                     || temp <= (mBatteryTemperature - 10)) {
14500                 mBatteryTemperature = temp;
14501                 changed = true;
14502             }
14503             if (voltageMv > (mBatteryVoltageMv + 20)
14504                     || voltageMv < (mBatteryVoltageMv - 20)) {
14505                 mBatteryVoltageMv = voltageMv;
14506                 changed = true;
14507             }
14508             if (chargeUah >= (mBatteryChargeUah + 10)
14509                     || chargeUah <= (mBatteryChargeUah - 10)) {
14510                 if (chargeUah < mBatteryChargeUah) {
14511                     // Only record discharges
14512                     final long chargeDiff = (long) mBatteryChargeUah - chargeUah;
14513                     mDischargeCounter.addCountLocked(chargeDiff);
14514                     mDischargeScreenOffCounter.addCountLocked(chargeDiff);
14515                     if (Display.isDozeState(mScreenState)) {
14516                         mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
14517                     }
14518                     if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
14519                         mDischargeLightDozeCounter.addCountLocked(chargeDiff);
14520                     } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
14521                         mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
14522                     }
14523                 }
14524                 mBatteryChargeUah = chargeUah;
14525                 changed = true;
14526             }
14527 
14528             long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
14529                     | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
14530                     | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
14531             if (onBattery) {
14532                 changed |= setChargingLocked(false);
14533                 if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
14534                     mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
14535                             modeBits, elapsedRealtimeMs);
14536                     mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
14537                             modeBits, elapsedRealtimeMs);
14538                     mLastDischargeStepLevel = level;
14539                     mMinDischargeStepLevel = level;
14540                     mInitStepMode = mCurStepMode;
14541                     mModStepMode = 0;
14542                 }
14543             } else {
14544                 if (level >= 90) {
14545                     // If the battery level is at least 90%, always consider the device to be
14546                     // charging even if it happens to go down a level.
14547                     changed |= setChargingLocked(true);
14548                 } else if (!mCharging) {
14549                     if (mLastChargeStepLevel < level) {
14550                         // We have not reported that we are charging, but the level has gone up,
14551                         // but we would like to not have tons of activity from charging-constraint
14552                         // jobs, so instead of reporting ACTION_CHARGING immediately, we defer it.
14553                         if (!mHandler.hasCallbacks(mDeferSetCharging)) {
14554                             mHandler.postDelayed(
14555                                     mDeferSetCharging,
14556                                     mConstants.BATTERY_CHARGED_DELAY_MS);
14557                         }
14558                     } else if (mLastChargeStepLevel > level) {
14559                         // if we had deferred a runnable due to charge level increasing, but then
14560                         // later the charge level drops (could be due to thermal issues), we don't
14561                         // want to trigger the deferred runnable, so remove it here
14562                         mHandler.removeCallbacks(mDeferSetCharging);
14563                     }
14564                 } else {
14565                     if (mLastChargeStepLevel > level) {
14566                         // We had reported that the device was charging, but here we are with
14567                         // power connected and the level going down.  Looks like the current
14568                         // power supplied isn't enough, so consider the device to now be
14569                         // discharging.
14570                         changed |= setChargingLocked(false);
14571                     }
14572                 }
14573                 if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
14574                     mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
14575                             modeBits, elapsedRealtimeMs);
14576                     mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
14577                             modeBits, elapsedRealtimeMs);
14578                     mMaxChargeStepLevel = level;
14579                     mInitStepMode = mCurStepMode;
14580                     mModStepMode = 0;
14581                 }
14582                 mLastChargeStepLevel = level;
14583             }
14584             if (changed) {
14585                 mHistory.setBatteryState(mBatteryStatus, mBatteryLevel, mBatteryHealth,
14586                         mBatteryPlugType, mBatteryTemperature, mBatteryVoltageMv,
14587                         mBatteryChargeUah);
14588                 mHistory.writeHistoryItem(elapsedRealtimeMs, uptimeMs);
14589             }
14590         }
14591         if (!onBattery &&
14592                 (status == BatteryManager.BATTERY_STATUS_FULL ||
14593                         status == BatteryManager.BATTERY_STATUS_UNKNOWN)) {
14594             // We don't record history while we are plugged in and fully charged
14595             // (or when battery is not present).  The next time we are
14596             // unplugged, history will be cleared.
14597             mHistory.setHistoryRecordingEnabled(DEBUG);
14598         }
14599 
14600         mLastLearnedBatteryCapacityUah = chargeFullUah;
14601         if (mMinLearnedBatteryCapacityUah == -1) {
14602             mMinLearnedBatteryCapacityUah = chargeFullUah;
14603         } else {
14604             mMinLearnedBatteryCapacityUah = Math.min(mMinLearnedBatteryCapacityUah, chargeFullUah);
14605         }
14606         mMaxLearnedBatteryCapacityUah = Math.max(mMaxLearnedBatteryCapacityUah, chargeFullUah);
14607 
14608         mBatteryTimeToFullSeconds = chargeTimeToFullSeconds;
14609     }
14610 
14611     public static boolean isOnBattery(int plugType, int status) {
14612         return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN;
14613     }
14614 
14615     // Inform StatsLog of setBatteryState changes.
14616     private void reportChangesToStatsLog(final int status, final int plugType, final int level) {
14617         if (!mHaveBatteryLevel || mBatteryStatus != status) {
14618             FrameworkStatsLog.write(FrameworkStatsLog.CHARGING_STATE_CHANGED, status);
14619         }
14620         if (!mHaveBatteryLevel || mBatteryPlugType != plugType) {
14621             FrameworkStatsLog.write(FrameworkStatsLog.PLUGGED_STATE_CHANGED, plugType);
14622         }
14623         if (!mHaveBatteryLevel || mBatteryLevel != level) {
14624             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_LEVEL_CHANGED, level);
14625         }
14626     }
14627 
14628     public long getAwakeTimeBattery() {
14629         // This previously evaluated to mOnBatteryTimeBase.getUptime(getBatteryUptimeLocked());
14630         // for over a decade, but surely that was a mistake.
14631         return getBatteryUptimeLocked(mClock.uptimeMillis());
14632     }
14633 
14634     public long getAwakeTimePlugged() {
14635         return (mClock.uptimeMillis() * 1000) - getAwakeTimeBattery();
14636     }
14637 
14638     @Override
14639     public long computeUptime(long curTimeUs, int which) {
14640         return mUptimeUs + (curTimeUs - mUptimeStartUs);
14641     }
14642 
14643     @Override
14644     public long computeRealtime(long curTimeUs, int which) {
14645         return mRealtimeUs + (curTimeUs - mRealtimeStartUs);
14646     }
14647 
14648     @Override
14649     public long computeBatteryUptime(long curTimeUs, int which) {
14650         return mOnBatteryTimeBase.computeUptime(curTimeUs, which);
14651     }
14652 
14653     @Override
14654     public long computeBatteryRealtime(long curTimeUs, int which) {
14655         return mOnBatteryTimeBase.computeRealtime(curTimeUs, which);
14656     }
14657 
14658     @Override
14659     public long computeBatteryScreenOffUptime(long curTimeUs, int which) {
14660         return mOnBatteryScreenOffTimeBase.computeUptime(curTimeUs, which);
14661     }
14662 
14663     @Override
14664     public long computeBatteryScreenOffRealtime(long curTimeUs, int which) {
14665         return mOnBatteryScreenOffTimeBase.computeRealtime(curTimeUs, which);
14666     }
14667 
14668     @Override
14669     public long computeBatteryTimeRemaining(long curTime) {
14670         if (!mOnBattery) {
14671             return -1;
14672         }
14673         /* Simple implementation just looks at the average discharge per level across the
14674            entire sample period.
14675         int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
14676         if (discharge < 2) {
14677             return -1;
14678         }
14679         long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
14680         if (duration < 1000*1000) {
14681             return -1;
14682         }
14683         long usPerLevel = duration/discharge;
14684         return usPerLevel * mCurrentBatteryLevel;
14685         */
14686         if (mDischargeStepTracker.mNumStepDurations < 1) {
14687             return -1;
14688         }
14689         long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
14690         if (msPerLevel <= 0) {
14691             return -1;
14692         }
14693         return (msPerLevel * mBatteryLevel) * 1000;
14694     }
14695 
14696     @Override
14697     public LevelStepTracker getDischargeLevelStepTracker() {
14698         return mDischargeStepTracker;
14699     }
14700 
14701     @Override
14702     public LevelStepTracker getDailyDischargeLevelStepTracker() {
14703         return mDailyDischargeStepTracker;
14704     }
14705 
14706     @Override
14707     public long computeChargeTimeRemaining(long curTime) {
14708         if (mOnBattery) {
14709             // Not yet working.
14710             return -1;
14711         }
14712         if (mBatteryTimeToFullSeconds >= 0) {
14713             return mBatteryTimeToFullSeconds * (1000 * 1000); // s to us
14714         }
14715         // Else use algorithmic approach
14716         if (mChargeStepTracker.mNumStepDurations < 1) {
14717             return -1;
14718         }
14719         long msPerLevel = mChargeStepTracker.computeTimePerLevel();
14720         if (msPerLevel <= 0) {
14721             return -1;
14722         }
14723         return (msPerLevel * (100 - mBatteryLevel)) * 1000;
14724     }
14725 
14726     /*@hide */
14727     public CellularBatteryStats getCellularBatteryStats() {
14728         final int which = STATS_SINCE_CHARGED;
14729         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
14730         final ControllerActivityCounter counter = getModemControllerActivity();
14731         final long sleepTimeMs = counter.getSleepTimeCounter().getCountLocked(which);
14732         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
14733         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
14734         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
14735         final long monitoredRailChargeConsumedMaMs =
14736                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
14737         long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
14738         for (int i = 0; i < timeInRatMs.length; i++) {
14739             timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTimeUs, which) / 1000;
14740         }
14741         long[] timeInRxSignalStrengthLevelMs =
14742                 new long[CellSignalStrength.getNumSignalStrengthLevels()];
14743         for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
14744             timeInRxSignalStrengthLevelMs[i] =
14745                 getPhoneSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
14746         }
14747         long[] txTimeMs = new long[Math.min(ModemActivityInfo.getNumTxPowerLevels(),
14748             counter.getTxTimeCounters().length)];
14749         long totalTxTimeMs = 0;
14750         for (int i = 0; i < txTimeMs.length; i++) {
14751             txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
14752             totalTxTimeMs += txTimeMs[i];
14753         }
14754 
14755         return new CellularBatteryStats(computeBatteryRealtime(rawRealTimeUs, which) / 1000,
14756                 getMobileRadioActiveTime(rawRealTimeUs, which) / 1000,
14757                 getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which),
14758                 getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which),
14759                 getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which),
14760                 getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which),
14761                 sleepTimeMs, idleTimeMs, rxTimeMs, energyConsumedMaMs, timeInRatMs,
14762                 timeInRxSignalStrengthLevelMs, txTimeMs,
14763                 monitoredRailChargeConsumedMaMs);
14764     }
14765 
14766     /*@hide */
14767     public WifiBatteryStats getWifiBatteryStats() {
14768         final int which = STATS_SINCE_CHARGED;
14769         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
14770         final ControllerActivityCounter counter = getWifiControllerActivity();
14771         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
14772         final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which);
14773         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
14774         final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which);
14775         final long totalControllerActivityTimeMs
14776                 = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000;
14777         final long sleepTimeMs
14778                 = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs);
14779         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
14780         final long monitoredRailChargeConsumedMaMs =
14781                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
14782         long numAppScanRequest = 0;
14783         for (int i = 0; i < mUidStats.size(); i++) {
14784             numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which);
14785         }
14786         long[] timeInStateMs = new long[NUM_WIFI_STATES];
14787         for (int i=0; i<NUM_WIFI_STATES; i++) {
14788             timeInStateMs[i] = getWifiStateTime(i, rawRealTimeUs, which) / 1000;
14789         }
14790         long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES];
14791         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14792             timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTimeUs, which) / 1000;
14793         }
14794         long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS];
14795         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14796             timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
14797         }
14798         return new WifiBatteryStats(
14799                 computeBatteryRealtime(rawRealTimeUs, which) / 1000,
14800                 getWifiActiveTime(rawRealTimeUs, which) / 1000,
14801                 getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which),
14802                 getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which),
14803                 getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which),
14804                 getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which),
14805                 sleepTimeMs, scanTimeMs, idleTimeMs, rxTimeMs, txTimeMs, energyConsumedMaMs,
14806                 numAppScanRequest, timeInStateMs, timeSignalStrengthTimeMs, timeInSupplStateMs,
14807                 monitoredRailChargeConsumedMaMs);
14808     }
14809 
14810     /*@hide */
14811     public GpsBatteryStats getGpsBatteryStats() {
14812         GpsBatteryStats s = new GpsBatteryStats();
14813         final int which = STATS_SINCE_CHARGED;
14814         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
14815         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTimeUs, which) / 1000);
14816         s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
14817         long[] time = new long[mGpsSignalQualityTimer.length];
14818         for (int i=0; i<time.length; i++) {
14819             time[i] = getGpsSignalQualityTime(i, rawRealTimeUs, which) / 1000;
14820         }
14821         s.setTimeInGpsSignalQualityLevel(time);
14822         return s;
14823     }
14824 
14825     @Override
14826     public LevelStepTracker getChargeLevelStepTracker() {
14827         return mChargeStepTracker;
14828     }
14829 
14830     @Override
14831     public LevelStepTracker getDailyChargeLevelStepTracker() {
14832         return mDailyChargeStepTracker;
14833     }
14834 
14835     @Override
14836     public ArrayList<PackageChange> getDailyPackageChanges() {
14837         return mDailyPackageChanges;
14838     }
14839 
14840     /**
14841      * @return battery uptime in microseconds
14842      */
14843     protected long getBatteryUptimeLocked(long uptimeMs) {
14844         return mOnBatteryTimeBase.getUptime(uptimeMs * 1000);
14845     }
14846 
14847     @Override
14848     public long getBatteryUptime(long curTimeUs) {
14849         return mOnBatteryTimeBase.getUptime(curTimeUs);
14850     }
14851 
14852     @Override
14853     public long getBatteryRealtime(long curTimeUs) {
14854         return mOnBatteryTimeBase.getRealtime(curTimeUs);
14855     }
14856 
14857     @Override
14858     public int getDischargeStartLevel() {
14859         synchronized(this) {
14860             return getDischargeStartLevelLocked();
14861         }
14862     }
14863 
14864     public int getDischargeStartLevelLocked() {
14865             return mDischargeUnplugLevel;
14866     }
14867 
14868     @Override
14869     public int getDischargeCurrentLevel() {
14870         synchronized(this) {
14871             return getDischargeCurrentLevelLocked();
14872         }
14873     }
14874 
14875     public int getDischargeCurrentLevelLocked() {
14876         return mDischargeCurrentLevel;
14877     }
14878 
14879     @Override
14880     public int getLowDischargeAmountSinceCharge() {
14881         synchronized(this) {
14882             int val = mLowDischargeAmountSinceCharge;
14883             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
14884                 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
14885             }
14886             return val;
14887         }
14888     }
14889 
14890     @Override
14891     public int getHighDischargeAmountSinceCharge() {
14892         synchronized(this) {
14893             int val = mHighDischargeAmountSinceCharge;
14894             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
14895                 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
14896             }
14897             return val;
14898         }
14899     }
14900 
14901     @Override
14902     public int getDischargeAmount(int which) {
14903         int dischargeAmount = which == STATS_SINCE_CHARGED
14904                 ? getHighDischargeAmountSinceCharge()
14905                 : (getDischargeStartLevel() - getDischargeCurrentLevel());
14906         if (dischargeAmount < 0) {
14907             dischargeAmount = 0;
14908         }
14909         return dischargeAmount;
14910     }
14911 
14912     @Override
14913     public int getDischargeAmountScreenOn() {
14914         synchronized(this) {
14915             int val = mDischargeAmountScreenOn;
14916             if (mOnBattery && Display.isOnState(mScreenState)
14917                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
14918                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
14919             }
14920             return val;
14921         }
14922     }
14923 
14924     @Override
14925     public int getDischargeAmountScreenOnSinceCharge() {
14926         synchronized(this) {
14927             int val = mDischargeAmountScreenOnSinceCharge;
14928             if (mOnBattery && Display.isOnState(mScreenState)
14929                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
14930                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
14931             }
14932             return val;
14933         }
14934     }
14935 
14936     @Override
14937     public int getDischargeAmountScreenOff() {
14938         synchronized(this) {
14939             int val = mDischargeAmountScreenOff;
14940             if (mOnBattery && Display.isOffState(mScreenState)
14941                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
14942                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
14943             }
14944             // For backward compatibility, doze discharge is counted into screen off.
14945             return val + getDischargeAmountScreenDoze();
14946         }
14947     }
14948 
14949     @Override
14950     public int getDischargeAmountScreenOffSinceCharge() {
14951         synchronized(this) {
14952             int val = mDischargeAmountScreenOffSinceCharge;
14953             if (mOnBattery && Display.isOffState(mScreenState)
14954                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
14955                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
14956             }
14957             // For backward compatibility, doze discharge is counted into screen off.
14958             return val + getDischargeAmountScreenDozeSinceCharge();
14959         }
14960     }
14961 
14962     @Override
14963     public int getDischargeAmountScreenDoze() {
14964         synchronized(this) {
14965             int val = mDischargeAmountScreenDoze;
14966             if (mOnBattery && Display.isDozeState(mScreenState)
14967                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
14968                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
14969             }
14970             return val;
14971         }
14972     }
14973 
14974     @Override
14975     public int getDischargeAmountScreenDozeSinceCharge() {
14976         synchronized(this) {
14977             int val = mDischargeAmountScreenDozeSinceCharge;
14978             if (mOnBattery && Display.isDozeState(mScreenState)
14979                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
14980                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
14981             }
14982             return val;
14983         }
14984     }
14985 
14986 
14987     /**
14988      * Estimates the time spent by the system server handling incoming binder requests.
14989      */
14990     @Override
14991     public long[] getSystemServiceTimeAtCpuSpeeds() {
14992         if (mBinderThreadCpuTimesUs == null) {
14993             return null;
14994         }
14995 
14996         return mBinderThreadCpuTimesUs.getCountsLocked(BatteryStats.STATS_SINCE_CHARGED);
14997     }
14998 
14999     /**
15000      * Retrieve the statistics object for a particular uid, creating if needed.
15001      */
15002     public Uid getUidStatsLocked(int uid) {
15003         return getUidStatsLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis());
15004     }
15005 
15006     public Uid getUidStatsLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
15007         Uid u = mUidStats.get(uid);
15008         if (u == null) {
15009             if (Process.isSdkSandboxUid(uid)) {
15010                 Log.wtf(TAG, "Tracking an SDK Sandbox UID");
15011             }
15012             u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
15013             mUidStats.put(uid, u);
15014         }
15015         return u;
15016     }
15017 
15018     /**
15019      * Retrieve the statistics object for a particular uid. Returns null if the object is not
15020      * available.
15021      */
15022     public Uid getAvailableUidStatsLocked(int uid) {
15023         Uid u = mUidStats.get(uid);
15024         return u;
15025     }
15026 
15027     @GuardedBy("this")
15028     public void onCleanupUserLocked(int userId, long elapsedRealtimeMs) {
15029         final int firstUidForUser = UserHandle.getUid(userId, 0);
15030         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
15031         mPendingRemovedUids.add(
15032                 new UidToRemove(firstUidForUser, lastUidForUser, elapsedRealtimeMs));
15033     }
15034 
15035     @GuardedBy("this")
15036     public void onUserRemovedLocked(int userId) {
15037         if (mExternalSync != null) {
15038             // Clear out the removed user's UIDs after a short delay. The delay is needed
15039             // because at the point that this method is called, some activities are still
15040             // being wrapped up by those UIDs
15041             mExternalSync.scheduleCleanupDueToRemovedUser(userId);
15042         }
15043     }
15044 
15045     /**
15046      * Removes battery stats for UIDs corresponding to a removed user.
15047      */
15048     @GuardedBy("this")
15049     public void clearRemovedUserUidsLocked(int userId) {
15050         final int firstUidForUser = UserHandle.getUid(userId, 0);
15051         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
15052         mUidStats.put(firstUidForUser, null);
15053         mUidStats.put(lastUidForUser, null);
15054         final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
15055         final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
15056         for (int i = firstIndex; i <= lastIndex; i++) {
15057             final Uid uid = mUidStats.valueAt(i);
15058             if (uid != null) {
15059                 uid.detachFromTimeBase();
15060             }
15061         }
15062         mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
15063         removeCpuStatsForUidRangeLocked(firstUidForUser, lastUidForUser);
15064     }
15065 
15066     /**
15067      * @see #removeUidStatsLocked(int)
15068      */
15069     @GuardedBy("this")
15070     public void removeUidStatsLocked(int uid, long elapsedRealtimeMs) {
15071         final Uid u = mUidStats.get(uid);
15072         if (u != null) {
15073             u.detachFromTimeBase();
15074         }
15075         mUidStats.remove(uid);
15076         mPendingRemovedUids.add(new UidToRemove(uid, elapsedRealtimeMs));
15077     }
15078 
15079     /**
15080      * Removes the data for the deleted UIDs from the underlying kernel eBPF tables.
15081      */
15082     @GuardedBy("this")
15083     private void removeCpuStatsForUidRangeLocked(int startUid, int endUid) {
15084         if (startUid == endUid) {
15085             mCpuUidUserSysTimeReader.removeUid(startUid);
15086             mCpuUidFreqTimeReader.removeUid(startUid);
15087             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
15088                 mCpuUidActiveTimeReader.removeUid(startUid);
15089                 mCpuUidClusterTimeReader.removeUid(startUid);
15090             }
15091             if (mKernelSingleUidTimeReader != null) {
15092                 mKernelSingleUidTimeReader.removeUid(startUid);
15093             }
15094             mNumUidsRemoved++;
15095         } else if (startUid < endUid) {
15096             mCpuUidFreqTimeReader.removeUidsInRange(startUid, endUid);
15097             mCpuUidUserSysTimeReader.removeUidsInRange(startUid, endUid);
15098             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
15099                 mCpuUidActiveTimeReader.removeUidsInRange(startUid, endUid);
15100                 mCpuUidClusterTimeReader.removeUidsInRange(startUid, endUid);
15101             }
15102             if (mKernelSingleUidTimeReader != null) {
15103                 mKernelSingleUidTimeReader.removeUidsInRange(startUid, endUid);
15104             }
15105             // Treat as one. We don't know how many uids there are in between.
15106             mNumUidsRemoved++;
15107         } else {
15108             Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
15109         }
15110     }
15111 
15112     /**
15113      * Retrieve the statistics object for a particular process, creating
15114      * if needed.
15115      */
15116     public Uid.Proc getProcessStatsLocked(int uid, String name,
15117             long elapsedRealtimeMs, long uptimeMs) {
15118         uid = mapUid(uid);
15119         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
15120         return u.getProcessStatsLocked(name);
15121     }
15122 
15123     /**
15124      * Retrieve the statistics object for a particular process, creating
15125      * if needed.
15126      */
15127     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
15128         return getPackageStatsLocked(uid, pkg, mClock.elapsedRealtime(), mClock.uptimeMillis());
15129     }
15130 
15131     /**
15132      * @see getPackageStatsLocked(int, String)
15133      */
15134     public Uid.Pkg getPackageStatsLocked(int uid, String pkg,
15135             long elapsedRealtimeMs, long uptimeMs) {
15136         uid = mapUid(uid);
15137         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
15138         return u.getPackageStatsLocked(pkg);
15139     }
15140 
15141     /**
15142      * Retrieve the statistics object for a particular service, creating
15143      * if needed.
15144      */
15145     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name,
15146             long elapsedRealtimeMs, long uptimeMs) {
15147         uid = mapUid(uid);
15148         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
15149         return u.getServiceStatsLocked(pkg, name);
15150     }
15151 
15152     @GuardedBy("this")
15153     public void shutdownLocked() {
15154         mHistory.recordShutdownEvent(mClock.elapsedRealtime(), mClock.uptimeMillis(),
15155                 mClock.currentTimeMillis());
15156         writeSyncLocked();
15157         mShuttingDown = true;
15158     }
15159 
15160     @GuardedBy("this")
15161     @Override
15162     public boolean isProcessStateDataAvailable() {
15163         return trackPerProcStateCpuTimes();
15164     }
15165 
15166     @GuardedBy("this")
15167     private boolean trackPerProcStateCpuTimes() {
15168         return mCpuUidFreqTimeReader.isFastCpuTimesReader();
15169     }
15170 
15171     @GuardedBy("this")
15172     boolean isUsageHistoryEnabled() {
15173         return mConstants.RECORD_USAGE_HISTORY;
15174     }
15175 
15176     @GuardedBy("this")
15177     public void systemServicesReady(Context context) {
15178         mConstants.startObserving(context.getContentResolver());
15179         registerUsbStateReceiver(context);
15180 
15181         synchronized (this) {
15182             mAlarmManager = context.getSystemService(AlarmManager.class);
15183             if (mBatteryPluggedIn) {
15184                 // Already plugged in. Schedule the long plug in alarm.
15185                 scheduleNextResetWhilePluggedInCheck();
15186             }
15187         }
15188     }
15189 
15190     /**
15191      * Initialize the EnergyConsumer stats data structures.
15192      *
15193      * @param supportedStandardBuckets boolean array indicating which {@link StandardPowerBucket}s
15194      *                                 are currently supported. If null, none are supported
15195      *                                 (regardless of customBucketNames).
15196      * @param customBucketNames        names of custom (OTHER) EnergyConsumers on this device
15197      */
15198     @GuardedBy("this")
15199     public void initEnergyConsumerStatsLocked(@Nullable boolean[] supportedStandardBuckets,
15200             String[] customBucketNames) {
15201         final int numDisplays = mPerDisplayBatteryStats.length;
15202         for (int i = 0; i < numDisplays; i++) {
15203             final int screenState = mPerDisplayBatteryStats[i].screenState;
15204             mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState;
15205         }
15206 
15207         final boolean compatibleConfig;
15208         if (supportedStandardBuckets != null) {
15209             final EnergyConsumerStats.Config config = new EnergyConsumerStats.Config(
15210                     supportedStandardBuckets, customBucketNames,
15211                     SUPPORTED_PER_PROCESS_STATE_STANDARD_ENERGY_BUCKETS,
15212                     getBatteryConsumerProcessStateNames());
15213 
15214             if (mEnergyConsumerStatsConfig == null) {
15215                 compatibleConfig = true;
15216             } else {
15217                 compatibleConfig = mEnergyConsumerStatsConfig.isCompatible(config);
15218             }
15219 
15220             mEnergyConsumerStatsConfig = config;
15221             mGlobalEnergyConsumerStats = new EnergyConsumerStats(config);
15222 
15223             if (supportedStandardBuckets[EnergyConsumerStats.POWER_BUCKET_BLUETOOTH]) {
15224                 mBluetoothPowerCalculator = new BluetoothPowerCalculator(mPowerProfile);
15225             }
15226             if (supportedStandardBuckets[EnergyConsumerStats.POWER_BUCKET_CPU]) {
15227                 mCpuPowerCalculator = new CpuPowerCalculator(mPowerProfile);
15228             }
15229             if (supportedStandardBuckets[EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO]) {
15230                 mMobileRadioPowerCalculator = new MobileRadioPowerCalculator(mPowerProfile);
15231             }
15232             if (supportedStandardBuckets[EnergyConsumerStats.POWER_BUCKET_WIFI]) {
15233                 mWifiPowerCalculator = new WifiPowerCalculator(mPowerProfile);
15234             }
15235         } else {
15236             compatibleConfig = (mEnergyConsumerStatsConfig == null);
15237             // EnergyConsumer no longer supported, wipe out the existing data.
15238             mEnergyConsumerStatsConfig = null;
15239             mGlobalEnergyConsumerStats = null;
15240         }
15241 
15242         if (!compatibleConfig) {
15243             // Supported power buckets changed since last boot.
15244             // Existing data is no longer reliable.
15245             resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
15246                     RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE);
15247         }
15248     }
15249 
15250     @GuardedBy("this")
15251     private boolean isMobileRadioEnergyConsumerSupportedLocked() {
15252         if (mGlobalEnergyConsumerStats == null) return false;
15253         return mGlobalEnergyConsumerStats.isStandardBucketSupported(
15254                 EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO);
15255     }
15256 
15257     @NonNull
15258     private static String[] getBatteryConsumerProcessStateNames() {
15259         String[] procStateNames = new String[BatteryConsumer.PROCESS_STATE_COUNT];
15260         for (int procState = 0; procState < BatteryConsumer.PROCESS_STATE_COUNT; procState++) {
15261             procStateNames[procState] = BatteryConsumer.processStateToString(procState);
15262         }
15263         return procStateNames;
15264     }
15265 
15266     /** Get the last known Battery voltage (in millivolts), returns -1 if unknown */
15267     @GuardedBy("this")
15268     public int getBatteryVoltageMvLocked() {
15269         return mBatteryVoltageMv;
15270     }
15271 
15272     @VisibleForTesting
15273     public final class Constants extends ContentObserver {
15274         public static final String KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME
15275                 = "track_cpu_active_cluster_time";
15276         public static final String KEY_KERNEL_UID_READERS_THROTTLE_TIME
15277                 = "kernel_uid_readers_throttle_time";
15278         public static final String KEY_UID_REMOVE_DELAY_MS
15279                 = "uid_remove_delay_ms";
15280         public static final String KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
15281                 = "external_stats_collection_rate_limit_ms";
15282         public static final String KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS
15283                 = "battery_level_collection_delay_ms";
15284         public static final String KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS =
15285                 "procstate_change_collection_delay_ms";
15286         public static final String KEY_MAX_HISTORY_FILES = "max_history_files";
15287         public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
15288         public static final String KEY_BATTERY_CHARGED_DELAY_MS =
15289                 "battery_charged_delay_ms";
15290         public static final String KEY_RECORD_USAGE_HISTORY =
15291                 "record_usage_history";
15292         public static final String KEY_PER_UID_MODEM_POWER_MODEL =
15293                 "per_uid_modem_power_model";
15294         public static final String KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION =
15295                 "phone_on_external_stats_collection";
15296         public static final String KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS =
15297                 "reset_while_plugged_in_minimum_duration_hours";
15298 
15299         public static final String PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME =
15300                 "mobile_radio_active_time";
15301         public static final String PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME =
15302                 "modem_activity_info_rx_tx";
15303 
15304         /** Convert {@link PerUidModemPowerModel} to string */
15305         public String getPerUidModemModelName(@PerUidModemPowerModel int model) {
15306             switch(model) {
15307                 case PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME:
15308                     return PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME;
15309                 case PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX:
15310                     return PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME;
15311                 default:
15312                     Slog.w(TAG, "Unexpected per uid modem model (" + model + ")");
15313                     return "unknown_" + model;
15314             }
15315         }
15316 
15317         /** Convert string to {@link PerUidModemPowerModel} */
15318         @PerUidModemPowerModel
15319         public int getPerUidModemModel(String name) {
15320             switch(name) {
15321                 case PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME:
15322                     return PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME;
15323                 case PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME:
15324                     return PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX;
15325                 default:
15326                     Slog.w(TAG, "Unexpected per uid modem model name (" + name + ")");
15327                     return DEFAULT_PER_UID_MODEM_MODEL;
15328             }
15329         }
15330 
15331         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
15332         private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000;
15333         private static final long DEFAULT_UID_REMOVE_DELAY_MS = 5L * 60L * 1000L;
15334         private static final long DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = 600_000;
15335         private static final long DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS = 300_000;
15336         private static final long DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS = 60_000;
15337         private static final int DEFAULT_MAX_HISTORY_FILES = 32;
15338         private static final int DEFAULT_MAX_HISTORY_BUFFER_KB = 128; /*Kilo Bytes*/
15339         private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64;
15340         private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
15341         private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
15342         private static final boolean DEFAULT_RECORD_USAGE_HISTORY = false;
15343         @PerUidModemPowerModel
15344         private static final int DEFAULT_PER_UID_MODEM_MODEL =
15345                 PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX;
15346         private static final boolean DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION = true;
15347         // Little less than 2 days
15348         private static final int DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS = 47;
15349 
15350         public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
15351         /* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
15352          * update when startObserving. */
15353         public long KERNEL_UID_READERS_THROTTLE_TIME;
15354         public long UID_REMOVE_DELAY_MS = DEFAULT_UID_REMOVE_DELAY_MS;
15355         public long EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
15356                 = DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
15357         public long BATTERY_LEVEL_COLLECTION_DELAY_MS
15358                 = DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS;
15359         public long PROC_STATE_CHANGE_COLLECTION_DELAY_MS =
15360                 DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS;
15361         public int MAX_HISTORY_FILES;
15362         public int MAX_HISTORY_BUFFER; /*Bytes*/
15363         public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
15364         public boolean RECORD_USAGE_HISTORY = DEFAULT_RECORD_USAGE_HISTORY;
15365         public int PER_UID_MODEM_MODEL = DEFAULT_PER_UID_MODEM_MODEL;
15366         public boolean PHONE_ON_EXTERNAL_STATS_COLLECTION =
15367                 DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION;
15368         public int RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS =
15369                 DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS;
15370 
15371         private ContentResolver mResolver;
15372         private final KeyValueListParser mParser = new KeyValueListParser(',');
15373 
15374         public Constants(Handler handler) {
15375             super(handler);
15376             if (ActivityManager.isLowRamDeviceStatic()) {
15377                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE;
15378                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB * 1024;
15379             } else {
15380                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES;
15381                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_KB * 1024;
15382             }
15383         }
15384 
15385         public void startObserving(ContentResolver resolver) {
15386             mResolver = resolver;
15387             mResolver.registerContentObserver(
15388                     Settings.Global.getUriFor(Settings.Global.BATTERY_STATS_CONSTANTS),
15389                     false /* notifyForDescendants */, this);
15390             mResolver.registerContentObserver(
15391                     Settings.Global.getUriFor(Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY),
15392                     false /* notifyForDescendants */, this);
15393             updateConstants();
15394         }
15395 
15396         @Override
15397         public void onChange(boolean selfChange, Uri uri) {
15398             if (uri.equals(
15399                     Settings.Global.getUriFor(
15400                             Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY))) {
15401                 synchronized (BatteryStatsImpl.this) {
15402                     updateBatteryChargedDelayMsLocked();
15403                 }
15404                 return;
15405             }
15406             updateConstants();
15407         }
15408 
15409         private void updateConstants() {
15410             synchronized (BatteryStatsImpl.this) {
15411                 try {
15412                     mParser.setString(Settings.Global.getString(mResolver,
15413                             Settings.Global.BATTERY_STATS_CONSTANTS));
15414                 } catch (IllegalArgumentException e) {
15415                     // Failed to parse the settings string, log this and move on
15416                     // with defaults.
15417                     Slog.e(TAG, "Bad batterystats settings", e);
15418                 }
15419 
15420                 TRACK_CPU_ACTIVE_CLUSTER_TIME = mParser.getBoolean(
15421                         KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME, DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME);
15422                 updateKernelUidReadersThrottleTime(KERNEL_UID_READERS_THROTTLE_TIME,
15423                         mParser.getLong(KEY_KERNEL_UID_READERS_THROTTLE_TIME,
15424                                 DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME));
15425                 updateUidRemoveDelay(
15426                         mParser.getLong(KEY_UID_REMOVE_DELAY_MS, DEFAULT_UID_REMOVE_DELAY_MS));
15427                 EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = mParser.getLong(
15428                         KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS,
15429                         DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
15430                 BATTERY_LEVEL_COLLECTION_DELAY_MS = mParser.getLong(
15431                         KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS,
15432                         DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS);
15433                 PROC_STATE_CHANGE_COLLECTION_DELAY_MS = mParser.getLong(
15434                         KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS,
15435                         DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
15436                 MAX_HISTORY_FILES = mParser.getInt(KEY_MAX_HISTORY_FILES,
15437                         ActivityManager.isLowRamDeviceStatic() ?
15438                                 DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE
15439                         : DEFAULT_MAX_HISTORY_FILES);
15440                 MAX_HISTORY_BUFFER = mParser.getInt(KEY_MAX_HISTORY_BUFFER_KB,
15441                         ActivityManager.isLowRamDeviceStatic() ?
15442                                 DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB
15443                                 : DEFAULT_MAX_HISTORY_BUFFER_KB)
15444                         * 1024;
15445                 RECORD_USAGE_HISTORY = mParser.getBoolean(
15446                         KEY_RECORD_USAGE_HISTORY, DEFAULT_RECORD_USAGE_HISTORY);
15447                 final String perUidModemModel = mParser.getString(KEY_PER_UID_MODEM_POWER_MODEL,
15448                         "");
15449                 PER_UID_MODEM_MODEL = getPerUidModemModel(perUidModemModel);
15450 
15451                 PHONE_ON_EXTERNAL_STATS_COLLECTION = mParser.getBoolean(
15452                         KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION,
15453                         DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION);
15454 
15455                 RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS = mParser.getInt(
15456                         KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS,
15457                         DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS);
15458 
15459                 updateBatteryChargedDelayMsLocked();
15460 
15461                 onChange();
15462             }
15463         }
15464 
15465         /**
15466          * Propagates changes in constant values.
15467          */
15468         @VisibleForTesting
15469         public void onChange() {
15470             mHistory.setMaxHistoryFiles(MAX_HISTORY_FILES);
15471             mHistory.setMaxHistoryBufferSize(MAX_HISTORY_BUFFER);
15472         }
15473 
15474         private void updateBatteryChargedDelayMsLocked() {
15475             // a negative value indicates that we should ignore this override
15476             final int delay = Settings.Global.getInt(mResolver,
15477                     Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
15478                     -1);
15479 
15480             BATTERY_CHARGED_DELAY_MS = delay >= 0 ? delay : mParser.getInt(
15481                     KEY_BATTERY_CHARGED_DELAY_MS,
15482                     DEFAULT_BATTERY_CHARGED_DELAY_MS);
15483 
15484             if (mHandler.hasCallbacks(mDeferSetCharging)) {
15485                 mHandler.removeCallbacks(mDeferSetCharging);
15486                 mHandler.postDelayed(mDeferSetCharging, BATTERY_CHARGED_DELAY_MS);
15487             }
15488         }
15489 
15490         private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
15491             KERNEL_UID_READERS_THROTTLE_TIME = newTimeMs;
15492             if (oldTimeMs != newTimeMs) {
15493                 mCpuUidUserSysTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
15494                 mCpuUidFreqTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
15495                 mCpuUidActiveTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
15496                 mCpuUidClusterTimeReader
15497                         .setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
15498             }
15499         }
15500 
15501         @GuardedBy("BatteryStatsImpl.this")
15502         private void updateUidRemoveDelay(long newTimeMs) {
15503             UID_REMOVE_DELAY_MS = newTimeMs;
15504             clearPendingRemovedUidsLocked();
15505         }
15506 
15507         public void dumpLocked(PrintWriter pw) {
15508             pw.print(KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME); pw.print("=");
15509             pw.println(TRACK_CPU_ACTIVE_CLUSTER_TIME);
15510             pw.print(KEY_KERNEL_UID_READERS_THROTTLE_TIME); pw.print("=");
15511             pw.println(KERNEL_UID_READERS_THROTTLE_TIME);
15512             pw.print(KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS); pw.print("=");
15513             pw.println(EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
15514             pw.print(KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS); pw.print("=");
15515             pw.println(BATTERY_LEVEL_COLLECTION_DELAY_MS);
15516             pw.print(KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS); pw.print("=");
15517             pw.println(PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
15518             pw.print(KEY_MAX_HISTORY_FILES); pw.print("=");
15519             pw.println(MAX_HISTORY_FILES);
15520             pw.print(KEY_MAX_HISTORY_BUFFER_KB); pw.print("=");
15521             pw.println(MAX_HISTORY_BUFFER/1024);
15522             pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("=");
15523             pw.println(BATTERY_CHARGED_DELAY_MS);
15524             pw.print(KEY_RECORD_USAGE_HISTORY); pw.print("=");
15525             pw.println(RECORD_USAGE_HISTORY);
15526             pw.print(KEY_PER_UID_MODEM_POWER_MODEL); pw.print("=");
15527             pw.println(getPerUidModemModelName(PER_UID_MODEM_MODEL));
15528             pw.print(KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION); pw.print("=");
15529             pw.println(PHONE_ON_EXTERNAL_STATS_COLLECTION);
15530             pw.print(KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS); pw.print("=");
15531             pw.println(RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS);
15532         }
15533     }
15534 
15535     public long getExternalStatsCollectionRateLimitMs() {
15536         synchronized (this) {
15537             return mConstants.EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
15538         }
15539     }
15540 
15541     @GuardedBy("this")
15542     public void dumpConstantsLocked(PrintWriter pw) {
15543         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
15544         iPw.println("BatteryStats constants:");
15545         iPw.increaseIndent();
15546         mConstants.dumpLocked(iPw);
15547         iPw.decreaseIndent();
15548     }
15549 
15550     @GuardedBy("this")
15551     public void dumpCpuStatsLocked(PrintWriter pw) {
15552         int size = mUidStats.size();
15553         pw.println("Per UID CPU user & system time in ms:");
15554         for (int i = 0; i < size; i++) {
15555             int u = mUidStats.keyAt(i);
15556             Uid uid = mUidStats.get(u);
15557             pw.print("  "); pw.print(u); pw.print(": ");
15558             pw.print(uid.getUserCpuTimeUs(STATS_SINCE_CHARGED) / 1000); pw.print(" ");
15559             pw.println(uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED) / 1000);
15560         }
15561 
15562         pw.println("Per UID CPU active time in ms:");
15563         for (int i = 0; i < size; i++) {
15564             int u = mUidStats.keyAt(i);
15565             Uid uid = mUidStats.get(u);
15566             if (uid.getCpuActiveTime() > 0) {
15567                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(uid.getCpuActiveTime());
15568             }
15569         }
15570         pw.println("Per UID CPU cluster time in ms:");
15571         for (int i = 0; i < size; i++) {
15572             int u = mUidStats.keyAt(i);
15573             long[] times = mUidStats.get(u).getCpuClusterTimes();
15574             if (times != null) {
15575                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
15576             }
15577         }
15578         pw.println("Per UID CPU frequency time in ms:");
15579         for (int i = 0; i < size; i++) {
15580             int u = mUidStats.keyAt(i);
15581             long[] times = mUidStats.get(u).getCpuFreqTimes(STATS_SINCE_CHARGED);
15582             if (times != null) {
15583                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
15584             }
15585         }
15586 
15587         updateSystemServiceCallStats();
15588         if (mBinderThreadCpuTimesUs != null) {
15589             pw.println("Per UID System server binder time in ms:");
15590             long[] systemServiceTimeAtCpuSpeeds = getSystemServiceTimeAtCpuSpeeds();
15591             for (int i = 0; i < size; i++) {
15592                 int u = mUidStats.keyAt(i);
15593                 Uid uid = mUidStats.get(u);
15594                 double proportionalSystemServiceUsage = uid.getProportionalSystemServiceUsage();
15595                 long timeUs = 0;
15596                 for (int j = systemServiceTimeAtCpuSpeeds.length - 1; j >= 0; j--) {
15597                     timeUs += systemServiceTimeAtCpuSpeeds[j] * proportionalSystemServiceUsage;
15598                 }
15599 
15600                 pw.print("  ");
15601                 pw.print(u);
15602                 pw.print(": ");
15603                 pw.println(timeUs / 1000);
15604             }
15605         }
15606     }
15607 
15608     @GuardedBy("this")
15609     private void dumpCpuPowerBracketsLocked(PrintWriter pw) {
15610         pw.println("CPU power brackets; cluster/freq in MHz(avg current in mA):");
15611         final int bracketCount = mPowerProfile.getCpuPowerBracketCount();
15612         for (int bracket = 0; bracket < bracketCount; bracket++) {
15613             pw.print("    ");
15614             pw.print(bracket);
15615             pw.print(": ");
15616             pw.println(mPowerProfile.getCpuPowerBracketDescription(bracket));
15617         }
15618     }
15619 
15620     /**
15621      * Dump EnergyConsumer stats
15622      */
15623     @GuardedBy("this")
15624     public void dumpEnergyConsumerStatsLocked(PrintWriter pw) {
15625         pw.printf("On-battery energy consumer stats (microcoulombs) \n");
15626         if (mGlobalEnergyConsumerStats == null) {
15627             pw.printf("    Not supported on this device.\n");
15628             return;
15629         }
15630 
15631         dumpEnergyConsumerStatsLocked(pw, "global usage", mGlobalEnergyConsumerStats);
15632 
15633         int size = mUidStats.size();
15634         for (int i = 0; i < size; i++) {
15635             final int u = mUidStats.keyAt(i);
15636             final Uid uid = mUidStats.get(u);
15637             final String name = "uid " + uid.mUid;
15638             dumpEnergyConsumerStatsLocked(pw, name, uid.mUidEnergyConsumerStats);
15639         }
15640     }
15641 
15642     /** Dump EnergyConsumer stats for the given uid */
15643     @GuardedBy("this")
15644     private void dumpEnergyConsumerStatsLocked(PrintWriter pw, String name,
15645             EnergyConsumerStats stats) {
15646         if (stats == null) return;
15647         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
15648         iPw.increaseIndent();
15649         iPw.printf("%s:\n", name);
15650         iPw.increaseIndent();
15651         stats.dump(iPw);
15652         iPw.decreaseIndent();
15653     }
15654 
15655     /**
15656      * Dump Power Profile
15657      */
15658     @GuardedBy("this")
15659     public void dumpPowerProfileLocked(PrintWriter pw) {
15660         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
15661         iPw.printf("Power Profile: \n");
15662         iPw.increaseIndent();
15663         mPowerProfile.dump(iPw);
15664         iPw.decreaseIndent();
15665     }
15666 
15667     private final Runnable mWriteAsyncRunnable = () -> {
15668         synchronized (BatteryStatsImpl.this) {
15669             writeSyncLocked();
15670         }
15671     };
15672 
15673     @GuardedBy("this")
15674     public void writeAsyncLocked() {
15675         BackgroundThread.getHandler().removeCallbacks(mWriteAsyncRunnable);
15676         BackgroundThread.getHandler().post(mWriteAsyncRunnable);
15677     }
15678 
15679     @GuardedBy("this")
15680     public void writeSyncLocked() {
15681         BackgroundThread.getHandler().removeCallbacks(mWriteAsyncRunnable);
15682         writeStatsLocked();
15683         writeHistoryLocked();
15684     }
15685 
15686     @GuardedBy("this")
15687     private void writeStatsLocked() {
15688         if (mStatsFile == null) {
15689             Slog.w(TAG,
15690                     "writeStatsLocked: no file associated with this instance");
15691             return;
15692         }
15693 
15694         if (mShuttingDown) {
15695             return;
15696         }
15697 
15698         final Parcel p = Parcel.obtain();
15699         try {
15700             final long start = SystemClock.uptimeMillis();
15701             writeSummaryToParcel(p, false/*history is in separate file*/);
15702             if (DEBUG) {
15703                 Slog.d(TAG, "writeSummaryToParcel duration ms:"
15704                         + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
15705             }
15706             mLastWriteTimeMs = mClock.elapsedRealtime();
15707             writeParcelToFileLocked(p, mStatsFile);
15708         } finally {
15709             p.recycle();
15710         }
15711     }
15712 
15713     private void writeHistoryLocked() {
15714         if (mShuttingDown) {
15715             return;
15716         }
15717 
15718         mHistory.writeHistory();
15719     }
15720 
15721     private final ReentrantLock mWriteLock = new ReentrantLock();
15722     private void writeParcelToFileLocked(Parcel p, AtomicFile file) {
15723         mWriteLock.lock();
15724         FileOutputStream fos = null;
15725         try {
15726             final long startTimeMs = SystemClock.uptimeMillis();
15727             fos = file.startWrite();
15728             fos.write(p.marshall());
15729             fos.flush();
15730             file.finishWrite(fos);
15731             if (DEBUG) {
15732                 Slog.d(TAG, "commitPendingDataToDisk file:" + file.getBaseFile().getPath()
15733                         + " duration ms:" + (SystemClock.uptimeMillis() - startTimeMs)
15734                         + " bytes:" + p.dataSize());
15735             }
15736             com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
15737                     "batterystats", SystemClock.uptimeMillis() - startTimeMs);
15738         } catch (IOException e) {
15739             Slog.w(TAG, "Error writing battery statistics", e);
15740             file.failWrite(fos);
15741         } finally {
15742             mWriteLock.unlock();
15743         }
15744     }
15745 
15746     @GuardedBy("this")
15747     public void readLocked() {
15748         if (mDailyFile != null) {
15749             readDailyStatsLocked();
15750         }
15751 
15752         if (mStatsFile == null) {
15753             Slog.w(TAG, "readLocked: no file associated with this instance");
15754             return;
15755         }
15756 
15757         mUidStats.clear();
15758 
15759         Parcel stats = Parcel.obtain();
15760         try {
15761             final long start = SystemClock.uptimeMillis();
15762             if (mStatsFile.exists()) {
15763                 byte[] raw = mStatsFile.readFully();
15764                 stats.unmarshall(raw, 0, raw.length);
15765                 stats.setDataPosition(0);
15766                 readSummaryFromParcel(stats);
15767                 if (DEBUG) {
15768                     Slog.d(TAG, "readLocked stats file:" + mStatsFile.getBaseFile().getPath()
15769                             + " bytes:" + raw.length + " took ms:" + (SystemClock.uptimeMillis()
15770                             - start));
15771                 }
15772             }
15773         } catch (Exception e) {
15774             Slog.e(TAG, "Error reading battery statistics", e);
15775             resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
15776                     RESET_REASON_CORRUPT_FILE);
15777         } finally {
15778             stats.recycle();
15779         }
15780 
15781         if (!mHistory.readSummary()) {
15782             resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
15783                     RESET_REASON_CORRUPT_FILE);
15784         }
15785 
15786         mEndPlatformVersion = Build.ID;
15787 
15788         mHistory.continueRecordingHistory();
15789 
15790         recordDailyStatsIfNeededLocked(false, mClock.currentTimeMillis());
15791     }
15792 
15793     @GuardedBy("this")
15794     public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
15795         final int version = in.readInt();
15796 
15797         if (version != VERSION) {
15798             Slog.w("BatteryStats", "readFromParcel: version got " + version
15799                 + ", expected " + VERSION + "; erasing old stats");
15800             return;
15801         }
15802 
15803         mHistory.readSummaryFromParcel(in);
15804 
15805         mStartCount = in.readInt();
15806         mUptimeUs = in.readLong();
15807         mRealtimeUs = in.readLong();
15808         mStartClockTimeMs = in.readLong();
15809         mStartPlatformVersion = in.readString();
15810         mEndPlatformVersion = in.readString();
15811         mOnBatteryTimeBase.readSummaryFromParcel(in);
15812         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
15813         mDischargeUnplugLevel = in.readInt();
15814         mDischargePlugLevel = in.readInt();
15815         mDischargeCurrentLevel = in.readInt();
15816         mBatteryLevel = in.readInt();
15817         mEstimatedBatteryCapacityMah = in.readInt();
15818         mLastLearnedBatteryCapacityUah = in.readInt();
15819         mMinLearnedBatteryCapacityUah = in.readInt();
15820         mMaxLearnedBatteryCapacityUah = in.readInt();
15821         mLowDischargeAmountSinceCharge = in.readInt();
15822         mHighDischargeAmountSinceCharge = in.readInt();
15823         mDischargeAmountScreenOnSinceCharge = in.readInt();
15824         mDischargeAmountScreenOffSinceCharge = in.readInt();
15825         mDischargeAmountScreenDozeSinceCharge = in.readInt();
15826         mDischargeStepTracker.readFromParcel(in);
15827         mChargeStepTracker.readFromParcel(in);
15828         mDailyDischargeStepTracker.readFromParcel(in);
15829         mDailyChargeStepTracker.readFromParcel(in);
15830         mDischargeCounter.readSummaryFromParcelLocked(in);
15831         mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
15832         mDischargeScreenDozeCounter.readSummaryFromParcelLocked(in);
15833         mDischargeLightDozeCounter.readSummaryFromParcelLocked(in);
15834         mDischargeDeepDozeCounter.readSummaryFromParcelLocked(in);
15835         int NPKG = in.readInt();
15836         if (NPKG > 0) {
15837             mDailyPackageChanges = new ArrayList<>(NPKG);
15838             while (NPKG > 0) {
15839                 NPKG--;
15840                 PackageChange pc = new PackageChange();
15841                 pc.mPackageName = in.readString();
15842                 pc.mUpdate = in.readInt() != 0;
15843                 pc.mVersionCode = in.readLong();
15844                 mDailyPackageChanges.add(pc);
15845             }
15846         } else {
15847             mDailyPackageChanges = null;
15848         }
15849         mDailyStartTimeMs = in.readLong();
15850         mNextMinDailyDeadlineMs = in.readLong();
15851         mNextMaxDailyDeadlineMs = in.readLong();
15852         mBatteryTimeToFullSeconds = in.readLong();
15853 
15854         final EnergyConsumerStats.Config config = EnergyConsumerStats.Config.createFromParcel(in);
15855         final EnergyConsumerStats energyConsumerStats =
15856                 EnergyConsumerStats.createAndReadSummaryFromParcel(mEnergyConsumerStatsConfig, in);
15857         if (config != null && Arrays.equals(config.getStateNames(),
15858                 getBatteryConsumerProcessStateNames())) {
15859             /**
15860              * WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled
15861              *          later when {@link #initEnergyConsumerStatsLocked} is called.
15862              */
15863             mEnergyConsumerStatsConfig = config;
15864             mGlobalEnergyConsumerStats = energyConsumerStats;
15865         }
15866 
15867         mStartCount++;
15868 
15869         mScreenState = Display.STATE_UNKNOWN;
15870         mScreenOnTimer.readSummaryFromParcelLocked(in);
15871         mScreenDozeTimer.readSummaryFromParcelLocked(in);
15872         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
15873             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
15874         }
15875         final int numDisplays = in.readInt();
15876         for (int i = 0; i < numDisplays; i++) {
15877             mPerDisplayBatteryStats[i].readSummaryFromParcel(in);
15878         }
15879         mInteractive = false;
15880         mInteractiveTimer.readSummaryFromParcelLocked(in);
15881         mPhoneOn = false;
15882         mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
15883         mLongestLightIdleTimeMs = in.readLong();
15884         mLongestFullIdleTimeMs = in.readLong();
15885         mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
15886         mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
15887         mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
15888         mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
15889         mPhoneOnTimer.readSummaryFromParcelLocked(in);
15890         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
15891             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
15892         }
15893         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
15894         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
15895             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
15896         }
15897         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
15898             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
15899             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
15900         }
15901 
15902         final int numRat = in.readInt();
15903         for (int i = 0; i < numRat; i++) {
15904             if (in.readInt() == 0) continue;
15905             getRatBatteryStatsLocked(i).readSummaryFromParcel(in);
15906         }
15907 
15908         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
15909         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
15910         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
15911         mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
15912         mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
15913         mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
15914         mWifiMulticastWakelockTimer.readSummaryFromParcelLocked(in);
15915         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
15916         mWifiOn = false;
15917         mWifiOnTimer.readSummaryFromParcelLocked(in);
15918         mGlobalWifiRunning = false;
15919         mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
15920         for (int i=0; i<NUM_WIFI_STATES; i++) {
15921             mWifiStateTimer[i].readSummaryFromParcelLocked(in);
15922         }
15923         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
15924             mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
15925         }
15926         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
15927             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
15928         }
15929         mWifiActiveTimer.readSummaryFromParcelLocked(in);
15930         mWifiActivity.readSummaryFromParcel(in);
15931         for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
15932             mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
15933         }
15934         mBluetoothActivity.readSummaryFromParcel(in);
15935         mModemActivity.readSummaryFromParcel(in);
15936         mHasWifiReporting = in.readInt() != 0;
15937         mHasBluetoothReporting = in.readInt() != 0;
15938         mHasModemReporting = in.readInt() != 0;
15939 
15940         mNumConnectivityChange = in.readInt();
15941         mFlashlightOnNesting = 0;
15942         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
15943         mCameraOnNesting = 0;
15944         mCameraOnTimer.readSummaryFromParcelLocked(in);
15945         mBluetoothScanNesting = 0;
15946         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
15947 
15948         int NRPMS = in.readInt();
15949         if (NRPMS > 10000) {
15950             throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS);
15951         }
15952         for (int irpm = 0; irpm < NRPMS; irpm++) {
15953             if (in.readInt() != 0) {
15954                 String rpmName = in.readString();
15955                 getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
15956             }
15957         }
15958         int NSORPMS = in.readInt();
15959         if (NSORPMS > 10000) {
15960             throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS);
15961         }
15962         for (int irpm = 0; irpm < NSORPMS; irpm++) {
15963             if (in.readInt() != 0) {
15964                 String rpmName = in.readString();
15965                 getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
15966             }
15967         }
15968         int NKW = in.readInt();
15969         if (NKW > 10000) {
15970             throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
15971         }
15972         for (int ikw = 0; ikw < NKW; ikw++) {
15973             if (in.readInt() != 0) {
15974                 String kwltName = in.readString();
15975                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
15976             }
15977         }
15978 
15979         int NWR = in.readInt();
15980         if (NWR > 10000) {
15981             throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
15982         }
15983         for (int iwr = 0; iwr < NWR; iwr++) {
15984             if (in.readInt() != 0) {
15985                 String reasonName = in.readString();
15986                 getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
15987             }
15988         }
15989 
15990         int NMS = in.readInt();
15991         for (int ims = 0; ims < NMS; ims++) {
15992             if (in.readInt() != 0) {
15993                 long kmstName = in.readLong();
15994                 getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
15995             }
15996         }
15997 
15998         final int NU = in.readInt();
15999         if (NU > 10000) {
16000             throw new ParcelFormatException("File corrupt: too many uids " + NU);
16001         }
16002         final long elapsedRealtimeMs = mClock.elapsedRealtime();
16003         final long uptimeMs = mClock.uptimeMillis();
16004         for (int iu = 0; iu < NU; iu++) {
16005             int uid = in.readInt();
16006             Uid u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
16007             mUidStats.put(uid, u);
16008 
16009             u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
16010             u.mOnBatteryScreenOffBackgroundTimeBase.readSummaryFromParcel(in);
16011 
16012             u.mWifiRunning = false;
16013             if (in.readInt() != 0) {
16014                 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
16015             }
16016             u.mFullWifiLockOut = false;
16017             if (in.readInt() != 0) {
16018                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
16019             }
16020             u.mWifiScanStarted = false;
16021             if (in.readInt() != 0) {
16022                 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
16023             }
16024             u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
16025             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
16026                 if (in.readInt() != 0) {
16027                     u.makeWifiBatchedScanBin(i, null);
16028                     u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
16029                 }
16030             }
16031             u.mWifiMulticastWakelockCount = 0;
16032             if (in.readInt() != 0) {
16033                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
16034             }
16035             if (in.readInt() != 0) {
16036                 u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
16037             }
16038             if (in.readInt() != 0) {
16039                 u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
16040             }
16041             if (in.readInt() != 0) {
16042                 u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
16043             }
16044             if (in.readInt() != 0) {
16045                 u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
16046             }
16047             if (in.readInt() != 0) {
16048                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
16049             }
16050             if (in.readInt() != 0) {
16051                 u.createForegroundServiceTimerLocked().readSummaryFromParcelLocked(in);
16052             }
16053             if (in.readInt() != 0) {
16054                 u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
16055             }
16056             if (in.readInt() != 0) {
16057                 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
16058             }
16059             if (in.readInt() != 0) {
16060                 u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in);
16061             }
16062             if (in.readInt() != 0) {
16063                 u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
16064             }
16065             if (in.readInt() != 0) {
16066                 u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in);
16067             }
16068             u.mProcessState = Uid.PROCESS_STATE_NONEXISTENT;
16069             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
16070                 if (in.readInt() != 0) {
16071                     u.makeProcessState(i, null);
16072                     u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
16073                 }
16074             }
16075             if (in.readInt() != 0) {
16076                 u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
16077             }
16078 
16079             if (in.readInt() != 0) {
16080                 if (u.mUserActivityCounters == null) {
16081                     u.initUserActivityLocked();
16082                 }
16083                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
16084                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
16085                 }
16086             }
16087 
16088             if (in.readInt() != 0) {
16089                 u.ensureNetworkActivityLocked();
16090                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
16091                     u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
16092                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
16093                 }
16094                 if (in.readBoolean()) {
16095                     u.mMobileRadioActiveTime = TimeMultiStateCounter.readFromParcel(in,
16096                             mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
16097                             elapsedRealtimeMs);
16098                 }
16099                 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
16100             }
16101 
16102             u.mUserCpuTime.readSummaryFromParcelLocked(in);
16103             u.mSystemCpuTime.readSummaryFromParcelLocked(in);
16104 
16105             if (in.readInt() != 0) {
16106                 final int numClusters = in.readInt();
16107                 if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
16108                     throw new ParcelFormatException("Incompatible cpu cluster arrangement");
16109                 }
16110                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
16111                 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
16112                 for (int cluster = 0; cluster < numClusters; cluster++) {
16113                     if (in.readInt() != 0) {
16114                         final int NSB = in.readInt();
16115                         if (mPowerProfile != null &&
16116                                 mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
16117                             throw new ParcelFormatException("File corrupt: too many speed bins " +
16118                                     NSB);
16119                         }
16120 
16121                         u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[NSB];
16122                         for (int speed = 0; speed < NSB; speed++) {
16123                             if (in.readInt() != 0) {
16124                                 u.mCpuClusterSpeedTimesUs[cluster][speed] = new LongSamplingCounter(
16125                                         mOnBatteryTimeBase);
16126                                 u.mCpuClusterSpeedTimesUs[cluster][speed].readSummaryFromParcelLocked(in);
16127                             }
16128                         }
16129                     } else {
16130                         u.mCpuClusterSpeedTimesUs[cluster] = null;
16131                     }
16132                 }
16133             } else {
16134                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
16135                 u.mCpuClusterSpeedTimesUs = null;
16136             }
16137 
16138             detachIfNotNull(u.mCpuFreqTimeMs);
16139             u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
16140                     in, mOnBatteryTimeBase);
16141             detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
16142             u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
16143                     in, mOnBatteryScreenOffTimeBase);
16144 
16145             int stateCount = in.readInt();
16146             if (stateCount != 0) {
16147                 u.mCpuActiveTimeMs = TimeMultiStateCounter.readFromParcel(in,
16148                         mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
16149                         mClock.elapsedRealtime());
16150             }
16151             u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
16152 
16153             detachIfNotNull(u.mProcStateTimeMs);
16154             u.mProcStateTimeMs = null;
16155 
16156             stateCount = in.readInt();
16157             if (stateCount != 0) {
16158                 detachIfNotNull(u.mProcStateTimeMs);
16159                 u.mProcStateTimeMs = TimeInFreqMultiStateCounter.readFromParcel(in,
16160                         mOnBatteryTimeBase, PROC_STATE_TIME_COUNTER_STATE_COUNT,
16161                         getCpuFreqCount(), mClock.elapsedRealtime());
16162             }
16163 
16164             detachIfNotNull(u.mProcStateScreenOffTimeMs);
16165             u.mProcStateScreenOffTimeMs = null;
16166 
16167             stateCount = in.readInt();
16168             if (stateCount != 0) {
16169                 detachIfNotNull(u.mProcStateScreenOffTimeMs);
16170                 u.mProcStateScreenOffTimeMs = TimeInFreqMultiStateCounter.readFromParcel(in,
16171                         mOnBatteryScreenOffTimeBase, PROC_STATE_TIME_COUNTER_STATE_COUNT,
16172                         getCpuFreqCount(), mClock.elapsedRealtime());
16173             }
16174 
16175             if (in.readInt() != 0) {
16176                 detachIfNotNull(u.mMobileRadioApWakeupCount);
16177                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
16178                 u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
16179             } else {
16180                 detachIfNotNull(u.mMobileRadioApWakeupCount);
16181                 u.mMobileRadioApWakeupCount = null;
16182             }
16183 
16184             if (in.readInt() != 0) {
16185                 detachIfNotNull(u.mWifiRadioApWakeupCount);
16186                 u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
16187                 u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
16188             } else {
16189                 detachIfNotNull(u.mWifiRadioApWakeupCount);
16190                 u.mWifiRadioApWakeupCount = null;
16191             }
16192 
16193             u.mUidEnergyConsumerStats = EnergyConsumerStats.createAndReadSummaryFromParcel(
16194                     mEnergyConsumerStatsConfig, in);
16195 
16196             int NW = in.readInt();
16197             if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
16198                 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
16199             }
16200             for (int iw = 0; iw < NW; iw++) {
16201                 String wlName = in.readString();
16202                 u.readWakeSummaryFromParcelLocked(wlName, in);
16203             }
16204 
16205             int NS = in.readInt();
16206             if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
16207                 throw new ParcelFormatException("File corrupt: too many syncs " + NS);
16208             }
16209             for (int is = 0; is < NS; is++) {
16210                 String name = in.readString();
16211                 u.readSyncSummaryFromParcelLocked(name, in);
16212             }
16213 
16214             int NJ = in.readInt();
16215             if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
16216                 throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
16217             }
16218             for (int ij = 0; ij < NJ; ij++) {
16219                 String name = in.readString();
16220                 u.readJobSummaryFromParcelLocked(name, in);
16221             }
16222 
16223             u.readJobCompletionsFromParcelLocked(in);
16224 
16225             u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in);
16226             u.mJobsDeferredCount.readSummaryFromParcelLocked(in);
16227             u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in);
16228             detachIfNotNull(u.mJobsFreshnessBuckets);
16229             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
16230                 if (in.readInt() != 0) {
16231                     u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase);
16232                     u.mJobsFreshnessBuckets[i].readSummaryFromParcelLocked(in);
16233                 }
16234             }
16235 
16236             int NP = in.readInt();
16237             if (NP > 1000) {
16238                 throw new ParcelFormatException("File corrupt: too many sensors " + NP);
16239             }
16240             for (int is = 0; is < NP; is++) {
16241                 int seNumber = in.readInt();
16242                 if (in.readInt() != 0) {
16243                     u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
16244                 }
16245             }
16246 
16247             NP = in.readInt();
16248             if (NP > 10000) {
16249                 throw new ParcelFormatException("File corrupt: too many processes " + NP);
16250             }
16251             for (int ip = 0; ip < NP; ip++) {
16252                 String procName = in.readString();
16253                 Uid.Proc p = u.getProcessStatsLocked(procName);
16254                 p.mUserTimeMs = in.readLong();
16255                 p.mSystemTimeMs = in.readLong();
16256                 p.mForegroundTimeMs = in.readLong();
16257                 p.mStarts = in.readInt();
16258                 p.mNumCrashes = in.readInt();
16259                 p.mNumAnrs = in.readInt();
16260                 p.readExcessivePowerFromParcelLocked(in);
16261             }
16262 
16263             NP = in.readInt();
16264             if (NP > 10000) {
16265                 throw new ParcelFormatException("File corrupt: too many packages " + NP);
16266             }
16267             for (int ip = 0; ip < NP; ip++) {
16268                 String pkgName = in.readString();
16269                 detachIfNotNull(u.mPackageStats.get(pkgName));
16270                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
16271                 final int NWA = in.readInt();
16272                 if (NWA > 10000) {
16273                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
16274                 }
16275                 p.mWakeupAlarms.clear();
16276                 for (int iwa = 0; iwa < NWA; iwa++) {
16277                     String tag = in.readString();
16278                     Counter c = new Counter(mOnBatteryScreenOffTimeBase);
16279                     c.readSummaryFromParcelLocked(in);
16280                     p.mWakeupAlarms.put(tag, c);
16281                 }
16282                 NS = in.readInt();
16283                 if (NS > 10000) {
16284                     throw new ParcelFormatException("File corrupt: too many services " + NS);
16285                 }
16286                 for (int is = 0; is < NS; is++) {
16287                     String servName = in.readString();
16288                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
16289                     s.mStartTimeMs = in.readLong();
16290                     s.mStarts = in.readInt();
16291                     s.mLaunches = in.readInt();
16292                 }
16293             }
16294         }
16295 
16296         mBinderThreadCpuTimesUs =
16297                 LongSamplingCounterArray.readSummaryFromParcelLocked(in, mOnBatteryTimeBase);
16298     }
16299 
16300     /**
16301      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
16302      * disk.  This format does not allow a lossless round-trip.
16303      *
16304      * @param out the Parcel to be written to.
16305      */
16306     @GuardedBy("this")
16307     public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
16308         pullPendingStateUpdatesLocked();
16309 
16310         // Pull the clock time.  This may update the time and make a new history entry
16311         // if we had originally pulled a time before the RTC was set.
16312         getStartClockTime();
16313 
16314         final long nowUptime = mClock.uptimeMillis() * 1000;
16315         final long nowRealtime = mClock.elapsedRealtime() * 1000;
16316 
16317         out.writeInt(VERSION);
16318 
16319         mHistory.writeSummaryToParcel(out, inclHistory);
16320 
16321         out.writeInt(mStartCount);
16322         out.writeLong(computeUptime(nowUptime, STATS_SINCE_CHARGED));
16323         out.writeLong(computeRealtime(nowRealtime, STATS_SINCE_CHARGED));
16324         out.writeLong(mStartClockTimeMs);
16325         out.writeString(mStartPlatformVersion);
16326         out.writeString(mEndPlatformVersion);
16327         mOnBatteryTimeBase.writeSummaryToParcel(out, nowUptime, nowRealtime);
16328         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, nowUptime, nowRealtime);
16329         out.writeInt(mDischargeUnplugLevel);
16330         out.writeInt(mDischargePlugLevel);
16331         out.writeInt(mDischargeCurrentLevel);
16332         out.writeInt(mBatteryLevel);
16333         out.writeInt(mEstimatedBatteryCapacityMah);
16334         out.writeInt(mLastLearnedBatteryCapacityUah);
16335         out.writeInt(mMinLearnedBatteryCapacityUah);
16336         out.writeInt(mMaxLearnedBatteryCapacityUah);
16337         out.writeInt(getLowDischargeAmountSinceCharge());
16338         out.writeInt(getHighDischargeAmountSinceCharge());
16339         out.writeInt(getDischargeAmountScreenOnSinceCharge());
16340         out.writeInt(getDischargeAmountScreenOffSinceCharge());
16341         out.writeInt(getDischargeAmountScreenDozeSinceCharge());
16342         mDischargeStepTracker.writeToParcel(out);
16343         mChargeStepTracker.writeToParcel(out);
16344         mDailyDischargeStepTracker.writeToParcel(out);
16345         mDailyChargeStepTracker.writeToParcel(out);
16346         mDischargeCounter.writeSummaryFromParcelLocked(out);
16347         mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
16348         mDischargeScreenDozeCounter.writeSummaryFromParcelLocked(out);
16349         mDischargeLightDozeCounter.writeSummaryFromParcelLocked(out);
16350         mDischargeDeepDozeCounter.writeSummaryFromParcelLocked(out);
16351         if (mDailyPackageChanges != null) {
16352             final int NPKG = mDailyPackageChanges.size();
16353             out.writeInt(NPKG);
16354             for (int i=0; i<NPKG; i++) {
16355                 PackageChange pc = mDailyPackageChanges.get(i);
16356                 out.writeString(pc.mPackageName);
16357                 out.writeInt(pc.mUpdate ? 1 : 0);
16358                 out.writeLong(pc.mVersionCode);
16359             }
16360         } else {
16361             out.writeInt(0);
16362         }
16363         out.writeLong(mDailyStartTimeMs);
16364         out.writeLong(mNextMinDailyDeadlineMs);
16365         out.writeLong(mNextMaxDailyDeadlineMs);
16366         out.writeLong(mBatteryTimeToFullSeconds);
16367 
16368         EnergyConsumerStats.Config.writeToParcel(mEnergyConsumerStatsConfig, out);
16369         EnergyConsumerStats.writeSummaryToParcel(mGlobalEnergyConsumerStats, out);
16370 
16371         mScreenOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16372         mScreenDozeTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16373         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
16374             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
16375         }
16376         final int numDisplays = mPerDisplayBatteryStats.length;
16377         out.writeInt(numDisplays);
16378         for (int i = 0; i < numDisplays; i++) {
16379             mPerDisplayBatteryStats[i].writeSummaryToParcel(out, nowRealtime);
16380         }
16381         mInteractiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16382         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16383         out.writeLong(mLongestLightIdleTimeMs);
16384         out.writeLong(mLongestFullIdleTimeMs);
16385         mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16386         mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16387         mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16388         mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16389         mPhoneOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16390         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
16391             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
16392         }
16393         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16394         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
16395             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
16396         }
16397         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
16398             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
16399             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
16400         }
16401         final int numRat = mPerRatBatteryStats.length;
16402         out.writeInt(numRat);
16403         for (int i = 0; i < numRat; i++) {
16404             final RadioAccessTechnologyBatteryStats ratStat = mPerRatBatteryStats[i];
16405             if (ratStat == null) {
16406                 out.writeInt(0);
16407                 continue;
16408             }
16409             out.writeInt(1);
16410             ratStat.writeSummaryToParcel(out, nowRealtime);
16411         }
16412         mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16413         mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16414         mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
16415         mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
16416         mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
16417         mWifiMulticastWakelockTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16418         mWifiOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16419         mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16420         for (int i=0; i<NUM_WIFI_STATES; i++) {
16421             mWifiStateTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
16422         }
16423         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
16424             mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
16425         }
16426         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
16427             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
16428         }
16429         mWifiActiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16430         mWifiActivity.writeSummaryToParcel(out);
16431         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
16432             mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
16433         }
16434         mBluetoothActivity.writeSummaryToParcel(out);
16435         mModemActivity.writeSummaryToParcel(out);
16436         out.writeInt(mHasWifiReporting ? 1 : 0);
16437         out.writeInt(mHasBluetoothReporting ? 1 : 0);
16438         out.writeInt(mHasModemReporting ? 1 : 0);
16439 
16440         out.writeInt(mNumConnectivityChange);
16441         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16442         mCameraOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16443         mBluetoothScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16444 
16445         out.writeInt(mRpmStats.size());
16446         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
16447             Timer rpmt = ent.getValue();
16448             if (rpmt != null) {
16449                 out.writeInt(1);
16450                 out.writeString(ent.getKey());
16451                 rpmt.writeSummaryFromParcelLocked(out, nowRealtime);
16452             } else {
16453                 out.writeInt(0);
16454             }
16455         }
16456         out.writeInt(mScreenOffRpmStats.size());
16457         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
16458             Timer rpmt = ent.getValue();
16459             if (rpmt != null) {
16460                 out.writeInt(1);
16461                 out.writeString(ent.getKey());
16462                 rpmt.writeSummaryFromParcelLocked(out, nowRealtime);
16463             } else {
16464                 out.writeInt(0);
16465             }
16466         }
16467 
16468         out.writeInt(mKernelWakelockStats.size());
16469         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
16470             Timer kwlt = ent.getValue();
16471             if (kwlt != null) {
16472                 out.writeInt(1);
16473                 out.writeString(ent.getKey());
16474                 kwlt.writeSummaryFromParcelLocked(out, nowRealtime);
16475             } else {
16476                 out.writeInt(0);
16477             }
16478         }
16479 
16480         out.writeInt(mWakeupReasonStats.size());
16481         for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
16482             SamplingTimer timer = ent.getValue();
16483             if (timer != null) {
16484                 out.writeInt(1);
16485                 out.writeString(ent.getKey());
16486                 timer.writeSummaryFromParcelLocked(out, nowRealtime);
16487             } else {
16488                 out.writeInt(0);
16489             }
16490         }
16491 
16492         out.writeInt(mKernelMemoryStats.size());
16493         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
16494             Timer kmt = mKernelMemoryStats.valueAt(i);
16495             if (kmt != null) {
16496                 out.writeInt(1);
16497                 out.writeLong(mKernelMemoryStats.keyAt(i));
16498                 kmt.writeSummaryFromParcelLocked(out, nowRealtime);
16499             } else {
16500                 out.writeInt(0);
16501             }
16502         }
16503 
16504         final int NU = mUidStats.size();
16505         out.writeInt(NU);
16506         for (int iu = 0; iu < NU; iu++) {
16507             out.writeInt(mUidStats.keyAt(iu));
16508             Uid u = mUidStats.valueAt(iu);
16509 
16510             u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, nowUptime, nowRealtime);
16511             u.mOnBatteryScreenOffBackgroundTimeBase.writeSummaryToParcel(out, nowUptime,
16512                     nowRealtime);
16513 
16514             if (u.mWifiRunningTimer != null) {
16515                 out.writeInt(1);
16516                 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16517             } else {
16518                 out.writeInt(0);
16519             }
16520             if (u.mFullWifiLockTimer != null) {
16521                 out.writeInt(1);
16522                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16523             } else {
16524                 out.writeInt(0);
16525             }
16526             if (u.mWifiScanTimer != null) {
16527                 out.writeInt(1);
16528                 u.mWifiScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16529             } else {
16530                 out.writeInt(0);
16531             }
16532             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
16533                 if (u.mWifiBatchedScanTimer[i] != null) {
16534                     out.writeInt(1);
16535                     u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
16536                 } else {
16537                     out.writeInt(0);
16538                 }
16539             }
16540             if (u.mWifiMulticastTimer != null) {
16541                 out.writeInt(1);
16542                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16543             } else {
16544                 out.writeInt(0);
16545             }
16546             if (u.mAudioTurnedOnTimer != null) {
16547                 out.writeInt(1);
16548                 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16549             } else {
16550                 out.writeInt(0);
16551             }
16552             if (u.mVideoTurnedOnTimer != null) {
16553                 out.writeInt(1);
16554                 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16555             } else {
16556                 out.writeInt(0);
16557             }
16558             if (u.mFlashlightTurnedOnTimer != null) {
16559                 out.writeInt(1);
16560                 u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16561             } else {
16562                 out.writeInt(0);
16563             }
16564             if (u.mCameraTurnedOnTimer != null) {
16565                 out.writeInt(1);
16566                 u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16567             } else {
16568                 out.writeInt(0);
16569             }
16570             if (u.mForegroundActivityTimer != null) {
16571                 out.writeInt(1);
16572                 u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16573             } else {
16574                 out.writeInt(0);
16575             }
16576             if (u.mForegroundServiceTimer != null) {
16577                 out.writeInt(1);
16578                 u.mForegroundServiceTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16579             } else {
16580                 out.writeInt(0);
16581             }
16582             if (u.mAggregatedPartialWakelockTimer != null) {
16583                 out.writeInt(1);
16584                 u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16585             } else {
16586                 out.writeInt(0);
16587             }
16588             if (u.mBluetoothScanTimer != null) {
16589                 out.writeInt(1);
16590                 u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16591             } else {
16592                 out.writeInt(0);
16593             }
16594             if (u.mBluetoothUnoptimizedScanTimer != null) {
16595                 out.writeInt(1);
16596                 u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16597             } else {
16598                 out.writeInt(0);
16599             }
16600             if (u.mBluetoothScanResultCounter != null) {
16601                 out.writeInt(1);
16602                 u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
16603             } else {
16604                 out.writeInt(0);
16605             }
16606             if (u.mBluetoothScanResultBgCounter != null) {
16607                 out.writeInt(1);
16608                 u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out);
16609             } else {
16610                 out.writeInt(0);
16611             }
16612             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
16613                 if (u.mProcessStateTimer[i] != null) {
16614                     out.writeInt(1);
16615                     u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, nowRealtime);
16616                 } else {
16617                     out.writeInt(0);
16618                 }
16619             }
16620             if (u.mVibratorOnTimer != null) {
16621                 out.writeInt(1);
16622                 u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16623             } else {
16624                 out.writeInt(0);
16625             }
16626 
16627             if (u.mUserActivityCounters == null) {
16628                 out.writeInt(0);
16629             } else {
16630                 out.writeInt(1);
16631                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
16632                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
16633                 }
16634             }
16635 
16636             if (u.mNetworkByteActivityCounters == null) {
16637                 out.writeInt(0);
16638             } else {
16639                 out.writeInt(1);
16640                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
16641                     u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
16642                     u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
16643                 }
16644                 if (u.mMobileRadioActiveTime != null) {
16645                     out.writeBoolean(true);
16646                     u.mMobileRadioActiveTime.writeToParcel(out);
16647                 } else {
16648                     out.writeBoolean(false);
16649                 }
16650                 u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
16651             }
16652 
16653             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
16654             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
16655 
16656             if (u.mCpuClusterSpeedTimesUs != null) {
16657                 out.writeInt(1);
16658                 out.writeInt(u.mCpuClusterSpeedTimesUs.length);
16659                 for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeedTimesUs) {
16660                     if (cpuSpeeds != null) {
16661                         out.writeInt(1);
16662                         out.writeInt(cpuSpeeds.length);
16663                         for (LongSamplingCounter c : cpuSpeeds) {
16664                             if (c != null) {
16665                                 out.writeInt(1);
16666                                 c.writeSummaryFromParcelLocked(out);
16667                             } else {
16668                                 out.writeInt(0);
16669                             }
16670                         }
16671                     } else {
16672                         out.writeInt(0);
16673                     }
16674                 }
16675             } else {
16676                 out.writeInt(0);
16677             }
16678 
16679             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
16680             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
16681 
16682             if (u.mCpuActiveTimeMs != null) {
16683                 out.writeInt(u.mCpuActiveTimeMs.getStateCount());
16684                 u.mCpuActiveTimeMs.writeToParcel(out);
16685             } else {
16686                 out.writeInt(0);
16687             }
16688 
16689             u.mCpuClusterTimesMs.writeSummaryToParcelLocked(out);
16690 
16691             if (u.mProcStateTimeMs != null) {
16692                 out.writeInt(u.mProcStateTimeMs.getStateCount());
16693                 u.mProcStateTimeMs.writeToParcel(out);
16694             } else {
16695                 out.writeInt(0);
16696             }
16697 
16698             if (u.mProcStateScreenOffTimeMs != null) {
16699                 out.writeInt(u.mProcStateScreenOffTimeMs.getStateCount());
16700                 u.mProcStateScreenOffTimeMs.writeToParcel(out);
16701             } else {
16702                 out.writeInt(0);
16703             }
16704 
16705             if (u.mMobileRadioApWakeupCount != null) {
16706                 out.writeInt(1);
16707                 u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
16708             } else {
16709                 out.writeInt(0);
16710             }
16711 
16712             if (u.mWifiRadioApWakeupCount != null) {
16713                 out.writeInt(1);
16714                 u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
16715             } else {
16716                 out.writeInt(0);
16717             }
16718 
16719             EnergyConsumerStats.writeSummaryToParcel(u.mUidEnergyConsumerStats, out);
16720 
16721             final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
16722             int NW = wakeStats.size();
16723             out.writeInt(NW);
16724             for (int iw=0; iw<NW; iw++) {
16725                 out.writeString(wakeStats.keyAt(iw));
16726                 Uid.Wakelock wl = wakeStats.valueAt(iw);
16727                 if (wl.mTimerFull != null) {
16728                     out.writeInt(1);
16729                     wl.mTimerFull.writeSummaryFromParcelLocked(out, nowRealtime);
16730                 } else {
16731                     out.writeInt(0);
16732                 }
16733                 if (wl.mTimerPartial != null) {
16734                     out.writeInt(1);
16735                     wl.mTimerPartial.writeSummaryFromParcelLocked(out, nowRealtime);
16736                 } else {
16737                     out.writeInt(0);
16738                 }
16739                 if (wl.mTimerWindow != null) {
16740                     out.writeInt(1);
16741                     wl.mTimerWindow.writeSummaryFromParcelLocked(out, nowRealtime);
16742                 } else {
16743                     out.writeInt(0);
16744                 }
16745                 if (wl.mTimerDraw != null) {
16746                     out.writeInt(1);
16747                     wl.mTimerDraw.writeSummaryFromParcelLocked(out, nowRealtime);
16748                 } else {
16749                     out.writeInt(0);
16750                 }
16751             }
16752 
16753             final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
16754             int NS = syncStats.size();
16755             out.writeInt(NS);
16756             for (int is=0; is<NS; is++) {
16757                 out.writeString(syncStats.keyAt(is));
16758                 syncStats.valueAt(is).writeSummaryFromParcelLocked(out, nowRealtime);
16759             }
16760 
16761             final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
16762             int NJ = jobStats.size();
16763             out.writeInt(NJ);
16764             for (int ij=0; ij<NJ; ij++) {
16765                 out.writeString(jobStats.keyAt(ij));
16766                 jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, nowRealtime);
16767             }
16768 
16769             u.writeJobCompletionsToParcelLocked(out);
16770 
16771             u.mJobsDeferredEventCount.writeSummaryFromParcelLocked(out);
16772             u.mJobsDeferredCount.writeSummaryFromParcelLocked(out);
16773             u.mJobsFreshnessTimeMs.writeSummaryFromParcelLocked(out);
16774             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
16775                 if (u.mJobsFreshnessBuckets[i] != null) {
16776                     out.writeInt(1);
16777                     u.mJobsFreshnessBuckets[i].writeSummaryFromParcelLocked(out);
16778                 } else {
16779                     out.writeInt(0);
16780                 }
16781             }
16782 
16783             int NSE = u.mSensorStats.size();
16784             out.writeInt(NSE);
16785             for (int ise=0; ise<NSE; ise++) {
16786                 out.writeInt(u.mSensorStats.keyAt(ise));
16787                 Uid.Sensor se = u.mSensorStats.valueAt(ise);
16788                 if (se.mTimer != null) {
16789                     out.writeInt(1);
16790                     se.mTimer.writeSummaryFromParcelLocked(out, nowRealtime);
16791                 } else {
16792                     out.writeInt(0);
16793                 }
16794             }
16795 
16796             int NP = u.mProcessStats.size();
16797             out.writeInt(NP);
16798             for (int ip=0; ip<NP; ip++) {
16799                 out.writeString(u.mProcessStats.keyAt(ip));
16800                 Uid.Proc ps = u.mProcessStats.valueAt(ip);
16801                 out.writeLong(ps.mUserTimeMs);
16802                 out.writeLong(ps.mSystemTimeMs);
16803                 out.writeLong(ps.mForegroundTimeMs);
16804                 out.writeInt(ps.mStarts);
16805                 out.writeInt(ps.mNumCrashes);
16806                 out.writeInt(ps.mNumAnrs);
16807                 ps.writeExcessivePowerToParcelLocked(out);
16808             }
16809 
16810             NP = u.mPackageStats.size();
16811             out.writeInt(NP);
16812             if (NP > 0) {
16813                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
16814                     : u.mPackageStats.entrySet()) {
16815                     out.writeString(ent.getKey());
16816                     Uid.Pkg ps = ent.getValue();
16817                     final int NWA = ps.mWakeupAlarms.size();
16818                     out.writeInt(NWA);
16819                     for (int iwa=0; iwa<NWA; iwa++) {
16820                         out.writeString(ps.mWakeupAlarms.keyAt(iwa));
16821                         ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
16822                     }
16823                     NS = ps.mServiceStats.size();
16824                     out.writeInt(NS);
16825                     for (int is=0; is<NS; is++) {
16826                         out.writeString(ps.mServiceStats.keyAt(is));
16827                         BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
16828                         long time = ss.getStartTimeToNowLocked(
16829                                 mOnBatteryTimeBase.getUptime(nowUptime) / 1000);
16830                         out.writeLong(time);
16831                         out.writeInt(ss.mStarts);
16832                         out.writeInt(ss.mLaunches);
16833                     }
16834                 }
16835             }
16836         }
16837 
16838         LongSamplingCounterArray.writeSummaryToParcelLocked(out, mBinderThreadCpuTimesUs);
16839     }
16840 
16841     @GuardedBy("this")
16842     public void prepareForDumpLocked() {
16843         // Need to retrieve current kernel wake lock stats before printing.
16844         pullPendingStateUpdatesLocked();
16845 
16846         // Pull the clock time.  This may update the time and make a new history entry
16847         // if we had originally pulled a time before the RTC was set.
16848         getStartClockTime();
16849 
16850         updateSystemServiceCallStats();
16851     }
16852 
16853     @GuardedBy("this")
16854     public void dump(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
16855         if (DEBUG) {
16856             pw.println("mOnBatteryTimeBase:");
16857             mOnBatteryTimeBase.dump(pw, "  ");
16858             pw.println("mOnBatteryScreenOffTimeBase:");
16859             mOnBatteryScreenOffTimeBase.dump(pw, "  ");
16860             Printer pr = new PrintWriterPrinter(pw);
16861             pr.println("*** Screen on timer:");
16862             mScreenOnTimer.logState(pr, "  ");
16863             pr.println("*** Screen doze timer:");
16864             mScreenDozeTimer.logState(pr, "  ");
16865             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
16866                 pr.println("*** Screen brightness #" + i + ":");
16867                 mScreenBrightnessTimer[i].logState(pr, "  ");
16868             }
16869             pr.println("*** Interactive timer:");
16870             mInteractiveTimer.logState(pr, "  ");
16871             pr.println("*** Power save mode timer:");
16872             mPowerSaveModeEnabledTimer.logState(pr, "  ");
16873             pr.println("*** Device idle mode light timer:");
16874             mDeviceIdleModeLightTimer.logState(pr, "  ");
16875             pr.println("*** Device idle mode full timer:");
16876             mDeviceIdleModeFullTimer.logState(pr, "  ");
16877             pr.println("*** Device light idling timer:");
16878             mDeviceLightIdlingTimer.logState(pr, "  ");
16879             pr.println("*** Device idling timer:");
16880             mDeviceIdlingTimer.logState(pr, "  ");
16881             pr.println("*** Phone timer:");
16882             mPhoneOnTimer.logState(pr, "  ");
16883             for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
16884                 pr.println("*** Phone signal strength #" + i + ":");
16885                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
16886             }
16887             pr.println("*** Signal scanning :");
16888             mPhoneSignalScanningTimer.logState(pr, "  ");
16889             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
16890                 pr.println("*** Data connection type #" + i + ":");
16891                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
16892             }
16893             pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
16894             pr.println("*** Mobile network active timer:");
16895             mMobileRadioActiveTimer.logState(pr, "  ");
16896             pr.println("*** Mobile network active adjusted timer:");
16897             mMobileRadioActiveAdjustedTime.logState(pr, "  ");
16898             pr.println("*** Wifi Multicast WakeLock Timer:");
16899             mWifiMulticastWakelockTimer.logState(pr, "  ");
16900             pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
16901             pr.println("*** Wifi timer:");
16902             mWifiOnTimer.logState(pr, "  ");
16903             pr.println("*** WifiRunning timer:");
16904             mGlobalWifiRunningTimer.logState(pr, "  ");
16905             for (int i=0; i<NUM_WIFI_STATES; i++) {
16906                 pr.println("*** Wifi state #" + i + ":");
16907                 mWifiStateTimer[i].logState(pr, "  ");
16908             }
16909             for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
16910                 pr.println("*** Wifi suppl state #" + i + ":");
16911                 mWifiSupplStateTimer[i].logState(pr, "  ");
16912             }
16913             for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
16914                 pr.println("*** Wifi signal strength #" + i + ":");
16915                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
16916             }
16917             for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
16918                 pr.println("*** GPS signal quality #" + i + ":");
16919                 mGpsSignalQualityTimer[i].logState(pr, "  ");
16920             }
16921             pr.println("*** Flashlight timer:");
16922             mFlashlightOnTimer.logState(pr, "  ");
16923             pr.println("*** Camera timer:");
16924             mCameraOnTimer.logState(pr, "  ");
16925         }
16926         super.dump(context, pw, flags, reqUid, histStart);
16927 
16928         synchronized (this) {
16929             pw.print("Per process state tracking available: ");
16930             pw.println(trackPerProcStateCpuTimes());
16931             pw.print("Total cpu time reads: ");
16932             pw.println(mNumSingleUidCpuTimeReads);
16933             pw.print("Batching Duration (min): ");
16934             pw.println((mClock.uptimeMillis() - mCpuTimeReadsTrackingStartTimeMs) / (60 * 1000));
16935             pw.print("All UID cpu time reads since the later of device start or stats reset: ");
16936             pw.println(mNumAllUidCpuTimeReads);
16937             pw.print("UIDs removed since the later of device start or stats reset: ");
16938             pw.println(mNumUidsRemoved);
16939 
16940             pw.println("Currently mapped isolated uids:");
16941             final int numIsolatedUids = mIsolatedUids.size();
16942             for (int i = 0; i < numIsolatedUids; i++) {
16943                 final int isolatedUid = mIsolatedUids.keyAt(i);
16944                 final int ownerUid = mIsolatedUids.valueAt(i);
16945                 final int refCount = mIsolatedUidRefCounts.get(isolatedUid);
16946                 pw.println(
16947                         "  " + isolatedUid + "->" + ownerUid + " (ref count = " + refCount + ")");
16948             }
16949 
16950             pw.println();
16951             dumpConstantsLocked(pw);
16952 
16953             pw.println();
16954             dumpCpuPowerBracketsLocked(pw);
16955 
16956             pw.println();
16957             dumpEnergyConsumerStatsLocked(pw);
16958         }
16959     }
16960 
16961     @Override
16962     protected BatteryUsageStats getBatteryUsageStats(Context context, boolean detailed) {
16963         final BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(context, this);
16964         BatteryUsageStatsQuery.Builder builder = new BatteryUsageStatsQuery.Builder()
16965                 .setMaxStatsAgeMs(0);
16966         if (detailed) {
16967             builder.includePowerModels().includeProcessStateData().includeVirtualUids();
16968         }
16969         return provider.getBatteryUsageStats(builder.build());
16970     }
16971 }
16972