• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006-2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.os;
18 
19 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
20 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
21 import static android.os.BatteryStatsManager.NUM_WIFI_STATES;
22 import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;
23 
24 import android.annotation.IntDef;
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.app.ActivityManager;
28 import android.bluetooth.BluetoothActivityEnergyInfo;
29 import android.bluetooth.UidTraffic;
30 import android.compat.annotation.UnsupportedAppUsage;
31 import android.content.BroadcastReceiver;
32 import android.content.ContentResolver;
33 import android.content.Context;
34 import android.content.Intent;
35 import android.content.IntentFilter;
36 import android.database.ContentObserver;
37 import android.hardware.usb.UsbManager;
38 import android.location.GnssSignalQuality;
39 import android.net.INetworkStatsService;
40 import android.net.NetworkStats;
41 import android.net.Uri;
42 import android.net.wifi.WifiManager;
43 import android.os.BatteryConsumer;
44 import android.os.BatteryManager;
45 import android.os.BatteryStats;
46 import android.os.Binder;
47 import android.os.Build;
48 import android.os.Handler;
49 import android.os.IBatteryPropertiesRegistrar;
50 import android.os.Looper;
51 import android.os.Message;
52 import android.os.OsProtoEnums;
53 import android.os.Parcel;
54 import android.os.ParcelFormatException;
55 import android.os.Parcelable;
56 import android.os.PowerManager;
57 import android.os.Process;
58 import android.os.RemoteException;
59 import android.os.ServiceManager;
60 import android.os.SystemClock;
61 import android.os.UserHandle;
62 import android.os.WorkSource;
63 import android.os.WorkSource.WorkChain;
64 import android.os.connectivity.CellularBatteryStats;
65 import android.os.connectivity.GpsBatteryStats;
66 import android.os.connectivity.WifiActivityEnergyInfo;
67 import android.os.connectivity.WifiBatteryStats;
68 import android.provider.Settings;
69 import android.telephony.CellSignalStrength;
70 import android.telephony.DataConnectionRealTimeInfo;
71 import android.telephony.ModemActivityInfo;
72 import android.telephony.ServiceState;
73 import android.telephony.SignalStrength;
74 import android.telephony.TelephonyManager;
75 import android.text.TextUtils;
76 import android.util.ArrayMap;
77 import android.util.ArraySet;
78 import android.util.AtomicFile;
79 import android.util.IndentingPrintWriter;
80 import android.util.IntArray;
81 import android.util.KeyValueListParser;
82 import android.util.Log;
83 import android.util.LongSparseArray;
84 import android.util.LongSparseLongArray;
85 import android.util.MutableInt;
86 import android.util.Pools;
87 import android.util.PrintWriterPrinter;
88 import android.util.Printer;
89 import android.util.Slog;
90 import android.util.SparseArray;
91 import android.util.SparseDoubleArray;
92 import android.util.SparseIntArray;
93 import android.util.SparseLongArray;
94 import android.util.TimeUtils;
95 import android.util.TypedXmlPullParser;
96 import android.util.TypedXmlSerializer;
97 import android.util.Xml;
98 import android.view.Display;
99 
100 import com.android.internal.annotations.GuardedBy;
101 import com.android.internal.annotations.VisibleForTesting;
102 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
103 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
104 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
105 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
106 import com.android.internal.os.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
107 import com.android.internal.power.MeasuredEnergyStats;
108 import com.android.internal.power.MeasuredEnergyStats.StandardPowerBucket;
109 import com.android.internal.util.ArrayUtils;
110 import com.android.internal.util.FrameworkStatsLog;
111 import com.android.internal.util.XmlUtils;
112 import com.android.net.module.util.NetworkCapabilitiesUtils;
113 
114 import libcore.util.EmptyArray;
115 
116 import org.xmlpull.v1.XmlPullParser;
117 import org.xmlpull.v1.XmlPullParserException;
118 
119 import java.io.ByteArrayOutputStream;
120 import java.io.File;
121 import java.io.FileInputStream;
122 import java.io.FileNotFoundException;
123 import java.io.FileOutputStream;
124 import java.io.IOException;
125 import java.io.PrintWriter;
126 import java.lang.annotation.Retention;
127 import java.lang.annotation.RetentionPolicy;
128 import java.util.ArrayList;
129 import java.util.Arrays;
130 import java.util.Calendar;
131 import java.util.Collection;
132 import java.util.Comparator;
133 import java.util.HashMap;
134 import java.util.HashSet;
135 import java.util.Iterator;
136 import java.util.LinkedList;
137 import java.util.List;
138 import java.util.Map;
139 import java.util.Queue;
140 import java.util.concurrent.Future;
141 import java.util.concurrent.atomic.AtomicInteger;
142 import java.util.concurrent.locks.ReentrantLock;
143 
144 /**
145  * All information we are collecting about things that can happen that impact
146  * battery life.  All times are represented in microseconds except where indicated
147  * otherwise.
148  */
149 public class BatteryStatsImpl extends BatteryStats {
150     private static final String TAG = "BatteryStatsImpl";
151     private static final boolean DEBUG = false;
152     public static final boolean DEBUG_ENERGY = false;
153     private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
154     private static final boolean DEBUG_BINDER_STATS = false;
155     private static final boolean DEBUG_MEMORY = false;
156     private static final boolean DEBUG_HISTORY = false;
157 
158     // TODO: remove "tcp" from network methods, since we measure total stats.
159 
160     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
161     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
162 
163     // Current on-disk Parcel version
164     static final int VERSION = 200;
165 
166     // The maximum number of names wakelocks we will keep track of
167     // per uid; once the limit is reached, we batch the remaining wakelocks
168     // in to one common name.
169     private static final int MAX_WAKELOCKS_PER_UID;
170 
171     static {
172         if (ActivityManager.isLowRamDeviceStatic()) {
173             MAX_WAKELOCKS_PER_UID = 40;
174         } else {
175             MAX_WAKELOCKS_PER_UID = 200;
176         }
177     }
178 
179     // Number of transmit power states the Wifi controller can be in.
180     private static final int NUM_WIFI_TX_LEVELS = 1;
181 
182     // Number of transmit power states the Bluetooth controller can be in.
183     private static final int NUM_BT_TX_LEVELS = 1;
184 
185     /**
186      * Holding a wakelock costs more than just using the cpu.
187      * Currently, we assign only half the cpu time to an app that is running but
188      * not holding a wakelock. The apps holding wakelocks get the rest of the blame.
189      * If no app is holding a wakelock, then the distribution is normal.
190      */
191     @VisibleForTesting
192     public static final int WAKE_LOCK_WEIGHT = 50;
193 
194     public static final int RESET_REASON_CORRUPT_FILE = 1;
195     public static final int RESET_REASON_ADB_COMMAND = 2;
196     public static final int RESET_REASON_FULL_CHARGE = 3;
197     public static final int RESET_REASON_MEASURED_ENERGY_BUCKETS_CHANGE = 4;
198 
199     protected Clocks mClocks;
200 
201     private final AtomicFile mStatsFile;
202     public final AtomicFile mCheckinFile;
203     public final AtomicFile mDailyFile;
204 
205     static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1;
206     static final int MSG_REPORT_POWER_CHANGE = 2;
207     static final int MSG_REPORT_CHARGING = 3;
208     static final int MSG_REPORT_RESET_STATS = 4;
209     static final long DELAY_UPDATE_WAKELOCKS = 60 * 1000;
210 
211     private static final double MILLISECONDS_IN_HOUR = 3600 * 1000;
212     private static final long MILLISECONDS_IN_YEAR = 365 * 24 * 3600 * 1000L;
213 
214     private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
215     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
216 
217     @VisibleForTesting
218     protected KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader =
219             new KernelCpuUidUserSysTimeReader(true);
220     @VisibleForTesting
221     protected KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
222     @VisibleForTesting
223     protected KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader =
224             new KernelCpuUidFreqTimeReader(true);
225     @VisibleForTesting
226     protected KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader =
227             new KernelCpuUidActiveTimeReader(true);
228     @VisibleForTesting
229     protected KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader =
230             new KernelCpuUidClusterTimeReader(true);
231     @VisibleForTesting
232     protected KernelSingleUidTimeReader mKernelSingleUidTimeReader;
233     @VisibleForTesting
234     protected SystemServerCpuThreadReader mSystemServerCpuThreadReader =
235             SystemServerCpuThreadReader.create();
236 
237     private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats
238             = new KernelMemoryBandwidthStats();
239     private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>();
240 
getKernelMemoryStats()241     public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
242         return mKernelMemoryStats;
243     }
244 
245     @GuardedBy("this")
246     public boolean mPerProcStateCpuTimesAvailable = true;
247 
248     /**
249      * When per process state cpu times tracking is off, cpu times in KernelSingleUidTimeReader are
250      * not updated. So, when the setting is turned on later, we would end up with huge cpu time
251      * deltas. This flag tracks the case where tracking is turned on from off so that we won't
252      * end up attributing the huge deltas to wrong buckets.
253      */
254     @GuardedBy("this")
255     private boolean mIsPerProcessStateCpuDataStale;
256 
257     /**
258      * Uids for which per-procstate cpu times need to be updated.
259      *
260      * Contains uid -> procState mappings.
261      */
262     @GuardedBy("this")
263     @VisibleForTesting
264     protected final SparseIntArray mPendingUids = new SparseIntArray();
265 
266     @GuardedBy("this")
267     private long mNumSingleUidCpuTimeReads;
268     @GuardedBy("this")
269     private long mNumBatchedSingleUidCpuTimeReads;
270     @GuardedBy("this")
271     private long mCpuTimeReadsTrackingStartTimeMs = SystemClock.uptimeMillis();
272     @GuardedBy("this")
273     private int mNumUidsRemoved;
274     @GuardedBy("this")
275     private int mNumAllUidCpuTimeReads;
276 
277     /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
278     private RpmStats mTmpRpmStats = null;
279     /** The soonest the RPM stats can be updated after it was last updated. */
280     private static final long RPM_STATS_UPDATE_FREQ_MS = 1000;
281     /** Last time that RPM stats were updated by updateRpmStatsLocked. */
282     private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
283 
284     /** Container for Rail Energy Data stats. */
285     private final RailStats mTmpRailStats = new RailStats();
286 
287     /**
288      * Use a queue to delay removing UIDs from {@link KernelCpuUidUserSysTimeReader},
289      * {@link KernelCpuUidActiveTimeReader}, {@link KernelCpuUidClusterTimeReader},
290      * {@link KernelCpuUidFreqTimeReader} and from the Kernel.
291      *
292      * Isolated and invalid UID info must be removed to conserve memory. However, STATSD and
293      * Batterystats both need to access UID cpu time. To resolve this race condition, only
294      * Batterystats shall remove UIDs, and a delay {@link Constants#UID_REMOVE_DELAY_MS} is
295      * implemented so that STATSD can capture those UID times before they are deleted.
296      */
297     @GuardedBy("this")
298     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
299     protected Queue<UidToRemove> mPendingRemovedUids = new LinkedList<>();
300 
301     @VisibleForTesting
302     public final class UidToRemove {
303         int startUid;
304         int endUid;
305         long mTimeAddedInQueueMs;
306 
307         /** Remove just one UID */
UidToRemove(int uid, long timestamp)308         public UidToRemove(int uid, long timestamp) {
309             this(uid, uid, timestamp);
310         }
311 
312         /** Remove a range of UIDs, startUid must be smaller than endUid. */
UidToRemove(int startUid, int endUid, long timestamp)313         public UidToRemove(int startUid, int endUid, long timestamp) {
314             this.startUid = startUid;
315             this.endUid = endUid;
316             mTimeAddedInQueueMs = timestamp;
317         }
318 
remove()319         void remove() {
320             if (startUid == endUid) {
321                 mCpuUidUserSysTimeReader.removeUid(startUid);
322                 mCpuUidFreqTimeReader.removeUid(startUid);
323                 if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
324                     mCpuUidActiveTimeReader.removeUid(startUid);
325                     mCpuUidClusterTimeReader.removeUid(startUid);
326                 }
327                 if (mKernelSingleUidTimeReader != null) {
328                     mKernelSingleUidTimeReader.removeUid(startUid);
329                 }
330                 mNumUidsRemoved++;
331             } else if (startUid < endUid) {
332                 mCpuUidFreqTimeReader.removeUidsInRange(startUid, endUid);
333                 mCpuUidUserSysTimeReader.removeUidsInRange(startUid, endUid);
334                 if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
335                     mCpuUidActiveTimeReader.removeUidsInRange(startUid, endUid);
336                     mCpuUidClusterTimeReader.removeUidsInRange(startUid, endUid);
337                 }
338                 if (mKernelSingleUidTimeReader != null) {
339                     mKernelSingleUidTimeReader.removeUidsInRange(startUid, endUid);
340                 }
341                 // Treat as one. We don't know how many uids there are in between.
342                 mNumUidsRemoved++;
343             } else {
344                 Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
345             }
346         }
347     }
348 
349     /**
350      * Listener for the battery stats reset.
351      */
352     public interface BatteryResetListener {
353 
354         /**
355          * Callback invoked immediately prior to resetting battery stats.
356          * @param resetReason One of the RESET_REASON_* constants.
357          */
prepareForBatteryStatsReset(int resetReason)358         void prepareForBatteryStatsReset(int resetReason);
359     }
360 
361     private BatteryResetListener mBatteryResetListener;
362 
363     public interface BatteryCallback {
batteryNeedsCpuUpdate()364         public void batteryNeedsCpuUpdate();
batteryPowerChanged(boolean onBattery)365         public void batteryPowerChanged(boolean onBattery);
batterySendBroadcast(Intent intent)366         public void batterySendBroadcast(Intent intent);
batteryStatsReset()367         public void batteryStatsReset();
368     }
369 
370     public interface PlatformIdleStateCallback {
fillLowPowerStats(RpmStats rpmStats)371         public void fillLowPowerStats(RpmStats rpmStats);
getSubsystemLowPowerStats()372         public String getSubsystemLowPowerStats();
373     }
374 
375     /** interface to update rail information for power monitor */
376     public interface MeasuredEnergyRetriever {
377         /** Function to fill the map for the rail data stats
378          * Used for power monitoring feature
379          * @param railStats
380          */
fillRailDataStats(RailStats railStats)381         void fillRailDataStats(RailStats railStats);
382     }
383 
384     public static abstract class UserInfoProvider {
385         private int[] userIds;
getUserIds()386         protected abstract @Nullable int[] getUserIds();
387         @VisibleForTesting
refreshUserIds()388         public final void refreshUserIds() {
389             userIds = getUserIds();
390         }
391         @VisibleForTesting
exists(int userId)392         public boolean exists(int userId) {
393             return userIds != null ? ArrayUtils.contains(userIds, userId) : true;
394         }
395     }
396 
397     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
398 
399     private final Runnable mDeferSetCharging = new Runnable() {
400         @Override
401         public void run() {
402             synchronized (BatteryStatsImpl.this) {
403                 if (mOnBattery) {
404                     // if the device gets unplugged in the time between this runnable being
405                     // executed and the lock being taken, we don't want to set charging state
406                     return;
407                 }
408                 boolean changed = setChargingLocked(true);
409                 if (changed) {
410                     final long uptimeMs = mClocks.uptimeMillis();
411                     final long elapsedRealtimeMs = mClocks.elapsedRealtime();
412                     addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
413                 }
414             }
415         }
416     };
417 
418     public final MeasuredEnergyRetriever mMeasuredEnergyRetriever;
419 
420     /**
421      * This handler is running on {@link BackgroundThread}.
422      */
423     final class MyHandler extends Handler {
MyHandler(Looper looper)424         public MyHandler(Looper looper) {
425             super(looper, null, true);
426         }
427 
428         @Override
handleMessage(Message msg)429         public void handleMessage(Message msg) {
430             BatteryCallback cb = mCallback;
431             switch (msg.what) {
432                 case MSG_REPORT_CPU_UPDATE_NEEDED:
433                     if (cb != null) {
434                         cb.batteryNeedsCpuUpdate();
435                     }
436                     break;
437                 case MSG_REPORT_POWER_CHANGE:
438                     if (cb != null) {
439                         cb.batteryPowerChanged(msg.arg1 != 0);
440                     }
441                     break;
442                 case MSG_REPORT_CHARGING:
443                     if (cb != null) {
444                         final String action;
445                         synchronized (BatteryStatsImpl.this) {
446                             action = mCharging ? BatteryManager.ACTION_CHARGING
447                                     : BatteryManager.ACTION_DISCHARGING;
448                         }
449                         Intent intent = new Intent(action);
450                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
451                         cb.batterySendBroadcast(intent);
452                     }
453                     break;
454                 case MSG_REPORT_RESET_STATS:
455                     if (cb != null) {
456                         cb.batteryStatsReset();
457                     }
458                 }
459         }
460     }
461 
postBatteryNeedsCpuUpdateMsg()462     public void postBatteryNeedsCpuUpdateMsg() {
463         mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED);
464     }
465 
466     /**
467      * Update per-freq cpu times for all the uids in {@link #mPendingUids}.
468      */
updateProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff)469     public void updateProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
470         final SparseIntArray uidStates;
471         synchronized (BatteryStatsImpl.this) {
472             if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
473                 return;
474             }
475             if(!initKernelSingleUidTimeReaderLocked()) {
476                 return;
477             }
478             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
479             // compute deltas since it might result in mis-attributing cpu times to wrong states.
480             if (mIsPerProcessStateCpuDataStale) {
481                 mPendingUids.clear();
482                 return;
483             }
484 
485             if (mPendingUids.size() == 0) {
486                 return;
487             }
488             uidStates = mPendingUids.clone();
489             mPendingUids.clear();
490         }
491         for (int i = uidStates.size() - 1; i >= 0; --i) {
492             final int uid = uidStates.keyAt(i);
493             final int procState = uidStates.valueAt(i);
494             final int[] isolatedUids;
495             final Uid u;
496             synchronized (BatteryStatsImpl.this) {
497                 // It's possible that uid no longer exists and any internal references have
498                 // already been deleted, so using {@link #getAvailableUidStatsLocked} to avoid
499                 // creating an UidStats object if it doesn't already exist.
500                 u = getAvailableUidStatsLocked(uid);
501                 if (u == null) {
502                     continue;
503                 }
504                 if (u.mChildUids == null) {
505                     isolatedUids = null;
506                 } else {
507                     isolatedUids = u.mChildUids.toArray();
508                     for (int j = isolatedUids.length - 1; j >= 0; --j) {
509                         isolatedUids[j] = u.mChildUids.get(j);
510                     }
511                 }
512             }
513             long[] cpuTimesMs = mKernelSingleUidTimeReader.readDeltaMs(uid);
514             if (isolatedUids != null) {
515                 for (int j = isolatedUids.length - 1; j >= 0; --j) {
516                     cpuTimesMs = addCpuTimes(cpuTimesMs,
517                             mKernelSingleUidTimeReader.readDeltaMs(isolatedUids[j]));
518                 }
519             }
520             if (onBattery && cpuTimesMs != null) {
521                 synchronized (BatteryStatsImpl.this) {
522                     u.addProcStateTimesMs(procState, cpuTimesMs, onBattery);
523                     u.addProcStateScreenOffTimesMs(procState, cpuTimesMs, onBatteryScreenOff);
524                 }
525             }
526         }
527     }
528 
clearPendingRemovedUids()529     public void clearPendingRemovedUids() {
530         long cutOffTimeMs = mClocks.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS;
531         while (!mPendingRemovedUids.isEmpty()
532                 && mPendingRemovedUids.peek().mTimeAddedInQueueMs < cutOffTimeMs) {
533             mPendingRemovedUids.poll().remove();
534         }
535     }
536 
copyFromAllUidsCpuTimes()537     public void copyFromAllUidsCpuTimes() {
538         synchronized (BatteryStatsImpl.this) {
539             copyFromAllUidsCpuTimes(
540                     mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
541         }
542     }
543 
544     /**
545      * When the battery/screen state changes, we don't attribute the cpu times to any process
546      * but we still need to snapshots of all uids to get correct deltas later on. Since we
547      * already read this data for updating per-freq cpu times, we can use the same data for
548      * per-procstate cpu times.
549      */
copyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff)550     public void copyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
551         synchronized (BatteryStatsImpl.this) {
552             if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
553                 return;
554             }
555             if(!initKernelSingleUidTimeReaderLocked()) {
556                 return;
557             }
558 
559             final SparseArray<long[]> allUidCpuFreqTimesMs =
560                     mCpuUidFreqTimeReader.getAllUidCpuFreqTimeMs();
561             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
562             // compute deltas since it might result in mis-attributing cpu times to wrong states.
563             if (mIsPerProcessStateCpuDataStale) {
564                 mKernelSingleUidTimeReader.setAllUidsCpuTimesMs(allUidCpuFreqTimesMs);
565                 mIsPerProcessStateCpuDataStale = false;
566                 mPendingUids.clear();
567                 return;
568             }
569             for (int i = allUidCpuFreqTimesMs.size() - 1; i >= 0; --i) {
570                 final int uid = allUidCpuFreqTimesMs.keyAt(i);
571                 final Uid u = getAvailableUidStatsLocked(mapUid(uid));
572                 if (u == null) {
573                     continue;
574                 }
575                 final long[] cpuTimesMs = allUidCpuFreqTimesMs.valueAt(i);
576                 if (cpuTimesMs == null) {
577                     continue;
578                 }
579                 final long[] deltaTimesMs = mKernelSingleUidTimeReader.computeDelta(
580                         uid, cpuTimesMs.clone());
581                 if (onBattery && deltaTimesMs != null) {
582                     final int procState;
583                     final int idx = mPendingUids.indexOfKey(uid);
584                     if (idx >= 0) {
585                         procState = mPendingUids.valueAt(idx);
586                         mPendingUids.removeAt(idx);
587                     } else {
588                         procState = u.mProcessState;
589                     }
590                     if (procState >= 0 && procState < Uid.NUM_PROCESS_STATE) {
591                         u.addProcStateTimesMs(procState, deltaTimesMs, onBattery);
592                         u.addProcStateScreenOffTimesMs(procState, deltaTimesMs, onBatteryScreenOff);
593                     }
594                 }
595             }
596         }
597     }
598 
599     @VisibleForTesting
addCpuTimes(long[] timesA, long[] timesB)600     public static long[] addCpuTimes(long[] timesA, long[] timesB) {
601         if (timesA != null && timesB != null) {
602             for (int i = timesA.length - 1; i >= 0; --i) {
603                 timesA[i] += timesB[i];
604             }
605             return timesA;
606         }
607         return timesA == null ? (timesB == null ? null : timesB) : timesA;
608     }
609 
610     @GuardedBy("this")
initKernelSingleUidTimeReaderLocked()611     private boolean initKernelSingleUidTimeReaderLocked() {
612         if (mKernelSingleUidTimeReader == null) {
613             if (mPowerProfile == null) {
614                 return false;
615             }
616             if (mCpuFreqs == null) {
617                 mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
618             }
619             if (mCpuFreqs != null) {
620                 mKernelSingleUidTimeReader = new KernelSingleUidTimeReader(mCpuFreqs.length);
621             } else {
622                 mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.allUidTimesAvailable();
623                 return false;
624             }
625         }
626         mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.allUidTimesAvailable()
627                 && mKernelSingleUidTimeReader.singleUidCpuTimesAvailable();
628         return true;
629     }
630 
631     public interface Clocks {
632         /** Elapsed Realtime, see SystemClock.elapsedRealtime() */
elapsedRealtime()633         long elapsedRealtime();
634 
635         /** Uptime, see SystemClock.uptimeMillis() */
uptimeMillis()636         long uptimeMillis();
637 
638         /** Wall-clock time as per System.currentTimeMillis() */
currentTimeMillis()639         long currentTimeMillis();
640     }
641 
642     public static class SystemClocks implements Clocks {
643 
644         @Override
elapsedRealtime()645         public long elapsedRealtime() {
646             return SystemClock.elapsedRealtime();
647         }
648 
649         @Override
uptimeMillis()650         public long uptimeMillis() {
651             return SystemClock.uptimeMillis();
652         }
653 
654         @Override
currentTimeMillis()655         public long currentTimeMillis() {
656             return System.currentTimeMillis();
657         }
658     }
659 
660     public interface ExternalStatsSync {
661         int UPDATE_CPU = 0x01;
662         int UPDATE_WIFI = 0x02;
663         int UPDATE_RADIO = 0x04;
664         int UPDATE_BT = 0x08;
665         int UPDATE_RPM = 0x10;
666         int UPDATE_DISPLAY = 0x20;
667         int UPDATE_ALL =
668                 UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM | UPDATE_DISPLAY;
669 
670         @IntDef(flag = true, prefix = "UPDATE_", value = {
671                 UPDATE_CPU,
672                 UPDATE_WIFI,
673                 UPDATE_RADIO,
674                 UPDATE_BT,
675                 UPDATE_RPM,
676                 UPDATE_DISPLAY,
677                 UPDATE_ALL,
678         })
679         @Retention(RetentionPolicy.SOURCE)
680         public @interface ExternalUpdateFlag {
681         }
682 
scheduleSync(String reason, int flags)683         Future<?> scheduleSync(String reason, int flags);
scheduleCpuSyncDueToRemovedUid(int uid)684         Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff, long delayMillis)685         Future<?> scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff,
686                 long delayMillis);
scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff)687         Future<?> scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff);
scheduleCpuSyncDueToSettingChange()688         Future<?> scheduleCpuSyncDueToSettingChange();
689         /**
690          * Schedule a sync because of a screen state change.
691          */
scheduleSyncDueToScreenStateChange(int flags, boolean onBattery, boolean onBatteryScreenOff, int screenState)692         Future<?> scheduleSyncDueToScreenStateChange(int flags, boolean onBattery,
693                 boolean onBatteryScreenOff, int screenState);
scheduleCpuSyncDueToWakelockChange(long delayMillis)694         Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis);
cancelCpuSyncDueToWakelockChange()695         void cancelCpuSyncDueToWakelockChange();
scheduleSyncDueToBatteryLevelChange(long delayMillis)696         Future<?> scheduleSyncDueToBatteryLevelChange(long delayMillis);
697     }
698 
699     public Handler mHandler;
700     private ExternalStatsSync mExternalSync = null;
701     @VisibleForTesting
702     protected UserInfoProvider mUserInfoProvider = null;
703 
704     private BatteryCallback mCallback;
705 
706     /**
707      * Mapping isolated uids to the actual owning app uid.
708      */
709     final SparseIntArray mIsolatedUids = new SparseIntArray();
710 
711     /**
712      * The statistics we have collected organized by uids.
713      */
714     final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
715 
716     // A set of pools of currently active timers.  When a timer is queried, we will divide the
717     // elapsed time by the number of active timers to arrive at that timer's share of the time.
718     // In order to do this, we must refresh each timer whenever the number of active timers
719     // changes.
720     @VisibleForTesting
721     @UnsupportedAppUsage
722     protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
723     @UnsupportedAppUsage
724     final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
725     @UnsupportedAppUsage
726     final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
727     final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
728     final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
729     final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
730     final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
731     final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
732     final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
733     final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers = new SparseArray<>();
734     final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
735     final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
736     final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
737     final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
738     final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
739 
740     // Last partial timers we use for distributing CPU usage.
741     @VisibleForTesting
742     protected ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
743 
744     // These are the objects that will want to do something when the device
745     // is unplugged from power.
746     protected final TimeBase mOnBatteryTimeBase = new TimeBase(true);
747 
748     // These are the objects that will want to do something when the device
749     // is unplugged from power *and* the screen is off or doze.
750     protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(true);
751 
752     // Set to true when we want to distribute CPU across wakelocks for the next
753     // CPU update, even if we aren't currently running wake locks.
754     boolean mDistributeWakelockCpu;
755 
756     private boolean mSystemReady;
757     boolean mShuttingDown;
758 
759     final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
760 
761     long mHistoryBaseTimeMs;
762     protected boolean mHaveBatteryLevel = false;
763     protected boolean mRecordingHistory = false;
764     int mNumHistoryItems;
765 
766     final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
767     final Parcel mHistoryBuffer = Parcel.obtain();
768     final HistoryItem mHistoryLastWritten = new HistoryItem();
769     final HistoryItem mHistoryLastLastWritten = new HistoryItem();
770     final HistoryItem mHistoryAddTmp = new HistoryItem();
771     int mNextHistoryTagIdx = 0;
772     int mNumHistoryTagChars = 0;
773     int mHistoryBufferLastPos = -1;
774     int mActiveHistoryStates = 0xffffffff;
775     int mActiveHistoryStates2 = 0xffffffff;
776     long mLastHistoryElapsedRealtimeMs = 0;
777     long mTrackRunningHistoryElapsedRealtimeMs = 0;
778     long mTrackRunningHistoryUptimeMs = 0;
779 
780     @NonNull
781     final BatteryStatsHistory mBatteryStatsHistory;
782 
783     final HistoryItem mHistoryCur = new HistoryItem();
784 
785     HistoryItem mHistory;
786     HistoryItem mHistoryEnd;
787     HistoryItem mHistoryLastEnd;
788     HistoryItem mHistoryCache;
789 
790     // Used by computeHistoryStepDetails
791     HistoryStepDetails mLastHistoryStepDetails = null;
792     byte mLastHistoryStepLevel = 0;
793     final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
794     final HistoryStepDetails mReadHistoryStepDetails = new HistoryStepDetails();
795     final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
796 
797     /**
798      * Total time (in milliseconds) spent executing in user code.
799      */
800     long mLastStepCpuUserTimeMs;
801     long mCurStepCpuUserTimeMs;
802     /**
803      * Total time (in milliseconds) spent executing in kernel code.
804      */
805     long mLastStepCpuSystemTimeMs;
806     long mCurStepCpuSystemTimeMs;
807     /**
808      * Times from /proc/stat (but measured in milliseconds).
809      */
810     long mLastStepStatUserTimeMs;
811     long mLastStepStatSystemTimeMs;
812     long mLastStepStatIOWaitTimeMs;
813     long mLastStepStatIrqTimeMs;
814     long mLastStepStatSoftIrqTimeMs;
815     long mLastStepStatIdleTimeMs;
816     long mCurStepStatUserTimeMs;
817     long mCurStepStatSystemTimeMs;
818     long mCurStepStatIOWaitTimeMs;
819     long mCurStepStatIrqTimeMs;
820     long mCurStepStatSoftIrqTimeMs;
821     long mCurStepStatIdleTimeMs;
822 
823     private BatteryStatsHistoryIterator mBatteryStatsHistoryIterator;
824     private HistoryItem mHistoryIterator;
825     private boolean mReadOverflow;
826 
827     int mStartCount;
828 
829     /**
830      * Set to true when a reset occurs, informing us that the next time BatteryExternalStatsWorker
831      * gives us data, we mustn't process it since this data includes pre-reset-period data.
832      */
833     @GuardedBy("this")
834     boolean mIgnoreNextExternalStats = false;
835 
836     long mStartClockTimeMs;
837     String mStartPlatformVersion;
838     String mEndPlatformVersion;
839 
840     long mUptimeUs;
841     long mUptimeStartUs;
842     long mRealtimeUs;
843     long mRealtimeStartUs;
844 
845     int mWakeLockNesting;
846     boolean mWakeLockImportant;
847     public boolean mRecordAllHistory;
848     boolean mNoAutoReset;
849 
850     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
851     protected int mScreenState = Display.STATE_UNKNOWN;
852     StopwatchTimer mScreenOnTimer;
853     StopwatchTimer mScreenDozeTimer;
854 
855     int mScreenBrightnessBin = -1;
856     final StopwatchTimer[] mScreenBrightnessTimer =
857             new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
858 
859     boolean mPretendScreenOff;
860 
861     boolean mInteractive;
862     StopwatchTimer mInteractiveTimer;
863 
864     boolean mPowerSaveModeEnabled;
865     StopwatchTimer mPowerSaveModeEnabledTimer;
866 
867     boolean mDeviceIdling;
868     StopwatchTimer mDeviceIdlingTimer;
869 
870     boolean mDeviceLightIdling;
871     StopwatchTimer mDeviceLightIdlingTimer;
872 
873     int mDeviceIdleMode;
874     long mLastIdleTimeStartMs;
875     long mLongestLightIdleTimeMs;
876     long mLongestFullIdleTimeMs;
877     StopwatchTimer mDeviceIdleModeLightTimer;
878     StopwatchTimer mDeviceIdleModeFullTimer;
879 
880     boolean mPhoneOn;
881     StopwatchTimer mPhoneOnTimer;
882 
883     int mAudioOnNesting;
884     StopwatchTimer mAudioOnTimer;
885 
886     int mVideoOnNesting;
887     StopwatchTimer mVideoOnTimer;
888 
889     int mFlashlightOnNesting;
890     StopwatchTimer mFlashlightOnTimer;
891 
892     int mCameraOnNesting;
893     StopwatchTimer mCameraOnTimer;
894 
895     private static final int USB_DATA_UNKNOWN = 0;
896     private static final int USB_DATA_DISCONNECTED = 1;
897     private static final int USB_DATA_CONNECTED = 2;
898     int mUsbDataState = USB_DATA_UNKNOWN;
899 
900     int mGpsSignalQualityBin = -1;
901     final StopwatchTimer[] mGpsSignalQualityTimer =
902         new StopwatchTimer[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
903 
904     int mPhoneSignalStrengthBin = -1;
905     int mPhoneSignalStrengthBinRaw = -1;
906     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
907             new StopwatchTimer[CellSignalStrength.getNumSignalStrengthLevels()];
908 
909     StopwatchTimer mPhoneSignalScanningTimer;
910 
911     int mPhoneDataConnectionType = -1;
912     final StopwatchTimer[] mPhoneDataConnectionsTimer =
913             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
914 
915     final LongSamplingCounter[] mNetworkByteActivityCounters =
916             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
917 
918     final LongSamplingCounter[] mNetworkPacketActivityCounters =
919             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
920 
921     /**
922      * The WiFi Overall wakelock timer
923      * This timer tracks the actual aggregate time for which MC wakelocks are enabled
924      * since addition of per UID timers would not result in an accurate value due to overlapp of
925      * per uid wakelock timers
926      */
927     StopwatchTimer mWifiMulticastWakelockTimer;
928 
929     /**
930      * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
931      */
932     ControllerActivityCounterImpl mWifiActivity;
933 
934     /**
935      * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
936      */
937     ControllerActivityCounterImpl mBluetoothActivity;
938 
939     /**
940      * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
941      */
942     ControllerActivityCounterImpl mModemActivity;
943 
944     /**
945      * Whether the device supports WiFi controller energy reporting. This is set to true on
946      * the first WiFi energy report. See {@link #mWifiActivity}.
947      */
948     boolean mHasWifiReporting = false;
949 
950     /**
951      * Whether the device supports Bluetooth controller energy reporting. This is set to true on
952      * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
953      */
954     boolean mHasBluetoothReporting = false;
955 
956     /**
957      * Whether the device supports Modem controller energy reporting. This is set to true on
958      * the first Modem energy report. See {@link #mModemActivity}.
959      */
960     boolean mHasModemReporting = false;
961 
962     boolean mWifiOn;
963     StopwatchTimer mWifiOnTimer;
964 
965     boolean mGlobalWifiRunning;
966     StopwatchTimer mGlobalWifiRunningTimer;
967 
968     int mWifiState = -1;
969     final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
970 
971     int mWifiSupplState = -1;
972     final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
973 
974     int mWifiSignalStrengthBin = -1;
975     final StopwatchTimer[] mWifiSignalStrengthsTimer =
976             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
977 
978     StopwatchTimer mWifiActiveTimer;
979 
980     int mBluetoothScanNesting;
981     StopwatchTimer mBluetoothScanTimer;
982 
983     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
984     long mMobileRadioActiveStartTimeMs;
985     StopwatchTimer mMobileRadioActiveTimer;
986     StopwatchTimer mMobileRadioActivePerAppTimer;
987     LongSamplingCounter mMobileRadioActiveAdjustedTime;
988     LongSamplingCounter mMobileRadioActiveUnknownTime;
989     LongSamplingCounter mMobileRadioActiveUnknownCount;
990 
991     int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
992 
993     /**
994      * Accumulated global (generally, device-wide total) charge consumption of various consumers
995      * while on battery.
996      * Its '<b>custom</b> power buckets' correspond to the
997      * {@link android.hardware.power.stats.EnergyConsumer.ordinal}s of (custom) energy consumer
998      * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
999      *
1000      * If energy consumer data is completely unavailable this will be null.
1001      */
1002     @GuardedBy("this")
1003     @VisibleForTesting
1004     protected @Nullable MeasuredEnergyStats mGlobalMeasuredEnergyStats;
1005     /** Last known screen state. Needed for apportioning display energy. */
1006     int mScreenStateAtLastEnergyMeasurement = Display.STATE_UNKNOWN;
1007     /** Bluetooth Power calculator for attributing measured bluetooth charge consumption to uids */
1008     @Nullable BluetoothPowerCalculator mBluetoothPowerCalculator = null;
1009     /** Cpu Power calculator for attributing measured cpu charge consumption to uids */
1010     @Nullable CpuPowerCalculator mCpuPowerCalculator = null;
1011     /** Mobile Radio Power calculator for attributing measured radio charge consumption to uids */
1012     @Nullable
1013     MobileRadioPowerCalculator mMobileRadioPowerCalculator = null;
1014     /** Wifi Power calculator for attributing measured wifi charge consumption to uids */
1015     @Nullable WifiPowerCalculator mWifiPowerCalculator = null;
1016 
1017     /**
1018      * These provide time bases that discount the time the device is plugged
1019      * in to power.
1020      */
1021     boolean mOnBattery;
1022     @VisibleForTesting
1023     protected boolean mOnBatteryInternal;
1024 
1025     /**
1026      * External reporting of whether the device is actually charging.
1027      */
1028     boolean mCharging = true;
1029     int mLastChargingStateLevel;
1030 
1031     /*
1032      * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
1033      */
1034     int mDischargeStartLevel;
1035     int mDischargeUnplugLevel;
1036     int mDischargePlugLevel;
1037     int mDischargeCurrentLevel;
1038     int mCurrentBatteryLevel;
1039     int mLowDischargeAmountSinceCharge;
1040     int mHighDischargeAmountSinceCharge;
1041     int mDischargeScreenOnUnplugLevel;
1042     int mDischargeScreenOffUnplugLevel;
1043     int mDischargeScreenDozeUnplugLevel;
1044     int mDischargeAmountScreenOn;
1045     int mDischargeAmountScreenOnSinceCharge;
1046     int mDischargeAmountScreenOff;
1047     int mDischargeAmountScreenOffSinceCharge;
1048     int mDischargeAmountScreenDoze;
1049     int mDischargeAmountScreenDozeSinceCharge;
1050 
1051     private LongSamplingCounter mDischargeScreenOffCounter;
1052     private LongSamplingCounter mDischargeScreenDozeCounter;
1053     private LongSamplingCounter mDischargeCounter;
1054     private LongSamplingCounter mDischargeLightDozeCounter;
1055     private LongSamplingCounter mDischargeDeepDozeCounter;
1056 
1057     static final int MAX_LEVEL_STEPS = 200;
1058 
1059     int mInitStepMode = 0;
1060     int mCurStepMode = 0;
1061     int mModStepMode = 0;
1062 
1063     int mLastDischargeStepLevel;
1064     int mMinDischargeStepLevel;
1065     final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
1066     final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
1067     ArrayList<PackageChange> mDailyPackageChanges;
1068 
1069     int mLastChargeStepLevel;
1070     int mMaxChargeStepLevel;
1071     final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
1072     final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
1073 
1074     static final int MAX_DAILY_ITEMS = 10;
1075 
1076     long mDailyStartTimeMs = 0;
1077     long mNextMinDailyDeadlineMs = 0;
1078     long mNextMaxDailyDeadlineMs = 0;
1079 
1080     final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
1081 
1082     long mLastWriteTimeMs = 0; // Milliseconds
1083 
1084     private int mPhoneServiceState = -1;
1085     private int mPhoneServiceStateRaw = -1;
1086     private int mPhoneSimStateRaw = -1;
1087 
1088     private int mNumConnectivityChange;
1089 
1090     private int mBatteryVoltageMv = -1;
1091     private int mEstimatedBatteryCapacityMah = -1;
1092 
1093     private int mLastLearnedBatteryCapacityUah = -1;
1094     private int mMinLearnedBatteryCapacityUah = -1;
1095     private int mMaxLearnedBatteryCapacityUah = -1;
1096 
1097     private long mBatteryTimeToFullSeconds = -1;
1098 
1099     private long[] mCpuFreqs;
1100 
1101     /**
1102      * Times spent by the system server threads handling incoming binder requests.
1103      */
1104     private LongSamplingCounterArray mBinderThreadCpuTimesUs;
1105 
1106     @VisibleForTesting
1107     protected PowerProfile mPowerProfile;
1108 
1109     @VisibleForTesting
1110     @GuardedBy("this")
1111     protected final Constants mConstants;
1112 
1113     /*
1114      * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
1115      * recording their times when on-battery (regardless of screen state).
1116      */
1117     private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>();
1118     /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */
1119     private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>();
1120 
1121     @Override
getRpmStats()1122     public Map<String, ? extends Timer> getRpmStats() {
1123         return mRpmStats;
1124     }
1125 
1126     // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED.
1127     @Override
getScreenOffRpmStats()1128     public Map<String, ? extends Timer> getScreenOffRpmStats() {
1129         return mScreenOffRpmStats;
1130     }
1131 
1132     /*
1133      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
1134      */
1135     private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
1136 
1137     @UnsupportedAppUsage
getKernelWakelockStats()1138     public Map<String, ? extends Timer> getKernelWakelockStats() {
1139         return mKernelWakelockStats;
1140     }
1141 
1142     String mLastWakeupReason = null;
1143     long mLastWakeupUptimeMs = 0;
1144     private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
1145 
getWakeupReasonStats()1146     public Map<String, ? extends Timer> getWakeupReasonStats() {
1147         return mWakeupReasonStats;
1148     }
1149 
1150     @Override
getUahDischarge(int which)1151     public long getUahDischarge(int which) {
1152         return mDischargeCounter.getCountLocked(which);
1153     }
1154 
1155     @Override
getUahDischargeScreenOff(int which)1156     public long getUahDischargeScreenOff(int which) {
1157         return mDischargeScreenOffCounter.getCountLocked(which);
1158     }
1159 
1160     @Override
getUahDischargeScreenDoze(int which)1161     public long getUahDischargeScreenDoze(int which) {
1162         return mDischargeScreenDozeCounter.getCountLocked(which);
1163     }
1164 
1165     @Override
getUahDischargeLightDoze(int which)1166     public long getUahDischargeLightDoze(int which) {
1167         return mDischargeLightDozeCounter.getCountLocked(which);
1168     }
1169 
1170     @Override
getUahDischargeDeepDoze(int which)1171     public long getUahDischargeDeepDoze(int which) {
1172         return mDischargeDeepDozeCounter.getCountLocked(which);
1173     }
1174 
1175     @Override
getEstimatedBatteryCapacity()1176     public int getEstimatedBatteryCapacity() {
1177         return mEstimatedBatteryCapacityMah;
1178     }
1179 
1180     @Override
getLearnedBatteryCapacity()1181     public int getLearnedBatteryCapacity() {
1182         return mLastLearnedBatteryCapacityUah;
1183     }
1184 
1185     @Override
getMinLearnedBatteryCapacity()1186     public int getMinLearnedBatteryCapacity() {
1187         return mMinLearnedBatteryCapacityUah;
1188     }
1189 
1190     @Override
getMaxLearnedBatteryCapacity()1191     public int getMaxLearnedBatteryCapacity() {
1192         return mMaxLearnedBatteryCapacityUah;
1193     }
1194 
BatteryStatsImpl()1195     public BatteryStatsImpl() {
1196         this(new SystemClocks());
1197     }
1198 
BatteryStatsImpl(Clocks clocks)1199     public BatteryStatsImpl(Clocks clocks) {
1200         init(clocks);
1201         mStartClockTimeMs = clocks.currentTimeMillis();
1202         mStatsFile = null;
1203         mCheckinFile = null;
1204         mDailyFile = null;
1205         mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
1206         mHandler = null;
1207         mPlatformIdleStateCallback = null;
1208         mMeasuredEnergyRetriever = null;
1209         mUserInfoProvider = null;
1210         mConstants = new Constants(mHandler);
1211         clearHistoryLocked();
1212     }
1213 
init(Clocks clocks)1214     private void init(Clocks clocks) {
1215         mClocks = clocks;
1216     }
1217 
1218     /**
1219      * TimeBase observer.
1220      */
1221     public interface TimeBaseObs {
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1222         void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs);
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1223         void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs);
1224 
1225         /**
1226          * Reset the observer's state, returns true if the timer/counter is inactive
1227          * so it can be destroyed.
1228          * @param detachIfReset detach if true, no-op if false.
1229          * @return Returns true if the timer/counter is inactive and can be destroyed.
1230          */
reset(boolean detachIfReset)1231         default boolean reset(boolean detachIfReset) {
1232             return reset(detachIfReset, SystemClock.elapsedRealtime() * 1000);
1233         }
1234 
1235         /**
1236          * @see #reset(boolean)
1237          * @param detachIfReset detach if true, no-op if false.
1238          * @param elapsedRealtimeUs the timestamp when this reset is actually reequested
1239          * @return Returns true if the timer/counter is inactive and can be destroyed.
1240          */
reset(boolean detachIfReset, long elapsedRealtimeUs)1241         boolean reset(boolean detachIfReset, long elapsedRealtimeUs);
1242 
1243         /**
1244          * Detach the observer from TimeBase.
1245          */
detach()1246         void detach();
1247     }
1248 
1249     // methods are protected not private to be VisibleForTesting
1250     public static class TimeBase {
1251         protected final Collection<TimeBaseObs> mObservers;
1252 
1253         // All below time metrics are in microseconds.
1254         protected long mUptimeUs;
1255         protected long mRealtimeUs;
1256 
1257         protected boolean mRunning;
1258 
1259         protected long mPastUptimeUs;
1260         protected long mUptimeStartUs;
1261         protected long mPastRealtimeUs;
1262         protected long mRealtimeStartUs;
1263         protected long mUnpluggedUptimeUs;
1264         protected long mUnpluggedRealtimeUs;
1265 
dump(PrintWriter pw, String prefix)1266         public void dump(PrintWriter pw, String prefix) {
1267             StringBuilder sb = new StringBuilder(128);
1268             pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
1269             sb.setLength(0);
1270             sb.append(prefix);
1271                     sb.append("mUptime=");
1272                     formatTimeMs(sb, mUptimeUs / 1000);
1273             pw.println(sb.toString());
1274             sb.setLength(0);
1275             sb.append(prefix);
1276                     sb.append("mRealtime=");
1277                     formatTimeMs(sb, mRealtimeUs / 1000);
1278             pw.println(sb.toString());
1279             sb.setLength(0);
1280             sb.append(prefix);
1281                     sb.append("mPastUptime=");
1282                     formatTimeMs(sb, mPastUptimeUs / 1000); sb.append("mUptimeStart=");
1283                     formatTimeMs(sb, mUptimeStartUs / 1000);
1284                     sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptimeUs / 1000);
1285             pw.println(sb.toString());
1286             sb.setLength(0);
1287             sb.append(prefix);
1288                     sb.append("mPastRealtime=");
1289                     formatTimeMs(sb, mPastRealtimeUs / 1000); sb.append("mRealtimeStart=");
1290                     formatTimeMs(sb, mRealtimeStartUs / 1000);
1291                     sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtimeUs / 1000);
1292             pw.println(sb.toString());
1293         }
1294         /**
1295          * The mObservers of TimeBase in BatteryStatsImpl object can contain up to 20k entries.
1296          * The mObservers of TimeBase in BatteryStatsImpl.Uid object only contains a few or tens of
1297          * entries.
1298          * mObservers must have good performance on add(), remove(), also be memory efficient.
1299          * This is why we provide isLongList parameter for long and short list user cases.
1300          * @param isLongList If true, use HashSet for mObservers list.
1301          *                   If false, use ArrayList for mObservers list.
1302         */
TimeBase(boolean isLongList)1303         public TimeBase(boolean isLongList) {
1304             mObservers = isLongList ? new HashSet<>() : new ArrayList<>();
1305         }
1306 
TimeBase()1307         public TimeBase() {
1308             this(false);
1309         }
1310 
add(TimeBaseObs observer)1311         public void add(TimeBaseObs observer) {
1312             mObservers.add(observer);
1313         }
1314 
remove(TimeBaseObs observer)1315         public void remove(TimeBaseObs observer) {
1316             mObservers.remove(observer);
1317         }
1318 
hasObserver(TimeBaseObs observer)1319         public boolean hasObserver(TimeBaseObs observer) {
1320             return mObservers.contains(observer);
1321         }
1322 
init(long uptimeUs, long elapsedRealtimeUs)1323         public void init(long uptimeUs, long elapsedRealtimeUs) {
1324             mRealtimeUs = 0;
1325             mUptimeUs = 0;
1326             mPastUptimeUs = 0;
1327             mPastRealtimeUs = 0;
1328             mUptimeStartUs = uptimeUs;
1329             mRealtimeStartUs = elapsedRealtimeUs;
1330             mUnpluggedUptimeUs = getUptime(mUptimeStartUs);
1331             mUnpluggedRealtimeUs = getRealtime(mRealtimeStartUs);
1332         }
1333 
reset(long uptimeUs, long elapsedRealtimeUs)1334         public void reset(long uptimeUs, long elapsedRealtimeUs) {
1335             if (!mRunning) {
1336                 mPastUptimeUs = 0;
1337                 mPastRealtimeUs = 0;
1338             } else {
1339                 mUptimeStartUs = uptimeUs;
1340                 mRealtimeStartUs = elapsedRealtimeUs;
1341                 // TODO: Since mUptimeStartUs was just reset and we are running, getUptime will
1342                 // just return mPastUptimeUs. Also, are we sure we don't want to reset that?
1343                 mUnpluggedUptimeUs = getUptime(uptimeUs);
1344                 // TODO: likewise.
1345                 mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs);
1346             }
1347         }
1348 
computeUptime(long curTimeUs, int which)1349         public long computeUptime(long curTimeUs, int which) {
1350             return mUptimeUs + getUptime(curTimeUs);
1351         }
1352 
computeRealtime(long curTimeUs, int which)1353         public long computeRealtime(long curTimeUs, int which) {
1354             return mRealtimeUs + getRealtime(curTimeUs);
1355         }
1356 
getUptime(long curTimeUs)1357         public long getUptime(long curTimeUs) {
1358             long time = mPastUptimeUs;
1359             if (mRunning) {
1360                 time += curTimeUs - mUptimeStartUs;
1361             }
1362             return time;
1363         }
1364 
getRealtime(long curTimeUs)1365         public long getRealtime(long curTimeUs) {
1366             long time = mPastRealtimeUs;
1367             if (mRunning) {
1368                 time += curTimeUs - mRealtimeStartUs;
1369             }
1370             return time;
1371         }
1372 
getUptimeStart()1373         public long getUptimeStart() {
1374             return mUptimeStartUs;
1375         }
1376 
getRealtimeStart()1377         public long getRealtimeStart() {
1378             return mRealtimeStartUs;
1379         }
1380 
isRunning()1381         public boolean isRunning() {
1382             return mRunning;
1383         }
1384 
setRunning(boolean running, long uptimeUs, long elapsedRealtimeUs)1385         public boolean setRunning(boolean running, long uptimeUs, long elapsedRealtimeUs) {
1386             if (mRunning != running) {
1387                 mRunning = running;
1388                 if (running) {
1389                     mUptimeStartUs = uptimeUs;
1390                     mRealtimeStartUs = elapsedRealtimeUs;
1391                     long batteryUptimeUs = mUnpluggedUptimeUs = getUptime(uptimeUs);
1392                     long batteryRealtimeUs = mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs);
1393                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
1394                     // Iterator object, here is an exception because mObservers' type is Collection
1395                     // instead of list.
1396                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
1397                     while (iter.hasNext()) {
1398                         iter.next().onTimeStarted(
1399                                 elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs);
1400                     }
1401                 } else {
1402                     mPastUptimeUs += uptimeUs - mUptimeStartUs;
1403                     mPastRealtimeUs += elapsedRealtimeUs - mRealtimeStartUs;
1404                     long batteryUptimeUs = getUptime(uptimeUs);
1405                     long batteryRealtimeUs = getRealtime(elapsedRealtimeUs);
1406                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
1407                     // Iterator object, here is an exception because mObservers' type is Collection
1408                     // instead of list.
1409                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
1410                     while (iter.hasNext()) {
1411                         iter.next().onTimeStopped(
1412                                 elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs);
1413                     }
1414                 }
1415                 return true;
1416             }
1417             return false;
1418         }
1419 
readSummaryFromParcel(Parcel in)1420         public void readSummaryFromParcel(Parcel in) {
1421             mUptimeUs = in.readLong();
1422             mRealtimeUs = in.readLong();
1423         }
1424 
writeSummaryToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs)1425         public void writeSummaryToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
1426             out.writeLong(computeUptime(uptimeUs, STATS_SINCE_CHARGED));
1427             out.writeLong(computeRealtime(elapsedRealtimeUs, STATS_SINCE_CHARGED));
1428         }
1429 
readFromParcel(Parcel in)1430         public void readFromParcel(Parcel in) {
1431             mRunning = false;
1432             mUptimeUs = in.readLong();
1433             mPastUptimeUs = in.readLong();
1434             mUptimeStartUs = in.readLong();
1435             mRealtimeUs = in.readLong();
1436             mPastRealtimeUs = in.readLong();
1437             mRealtimeStartUs = in.readLong();
1438             mUnpluggedUptimeUs = in.readLong();
1439             mUnpluggedRealtimeUs = in.readLong();
1440         }
1441 
writeToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs)1442         public void writeToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
1443             final long runningUptime = getUptime(uptimeUs);
1444             final long runningRealtime = getRealtime(elapsedRealtimeUs);
1445             out.writeLong(mUptimeUs);
1446             out.writeLong(runningUptime);
1447             out.writeLong(mUptimeStartUs);
1448             out.writeLong(mRealtimeUs);
1449             out.writeLong(runningRealtime);
1450             out.writeLong(mRealtimeStartUs);
1451             out.writeLong(mUnpluggedUptimeUs);
1452             out.writeLong(mUnpluggedRealtimeUs);
1453         }
1454     }
1455 
1456     /**
1457      * State for keeping track of counting information.
1458      */
1459     public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
1460         @UnsupportedAppUsage
1461         final AtomicInteger mCount = new AtomicInteger();
1462         final TimeBase mTimeBase;
1463 
Counter(TimeBase timeBase, Parcel in)1464         public Counter(TimeBase timeBase, Parcel in) {
1465             mTimeBase = timeBase;
1466             mCount.set(in.readInt());
1467             timeBase.add(this);
1468         }
1469 
Counter(TimeBase timeBase)1470         public Counter(TimeBase timeBase) {
1471             mTimeBase = timeBase;
1472             timeBase.add(this);
1473         }
1474 
writeToParcel(Parcel out)1475         public void writeToParcel(Parcel out) {
1476             out.writeInt(mCount.get());
1477         }
1478 
1479         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1480         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
1481         }
1482 
1483         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1484         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
1485         }
1486 
1487         /**
1488          * Writes a possibly null Counter to a Parcel.
1489          *
1490          * @param out the Parcel to be written to.
1491          * @param counter a Counter, or null.
1492          */
writeCounterToParcel(Parcel out, @Nullable Counter counter)1493         public static void writeCounterToParcel(Parcel out, @Nullable Counter counter) {
1494             if (counter == null) {
1495                 out.writeInt(0); // indicates null
1496                 return;
1497             }
1498             out.writeInt(1); // indicates non-null
1499 
1500             counter.writeToParcel(out);
1501         }
1502 
1503         /**
1504          * Reads a Counter that was written using {@link #writeCounterToParcel(Parcel, Counter)}.
1505          * @param timeBase the timebase to assign to the Counter
1506          * @param in the parcel to read from
1507          * @return the Counter or null.
1508          */
1509         @Nullable
readCounterFromParcel(TimeBase timeBase, Parcel in)1510         public static Counter readCounterFromParcel(TimeBase timeBase, Parcel in) {
1511             if (in.readInt() == 0) {
1512                 return null;
1513             }
1514             return new Counter(timeBase, in);
1515         }
1516 
1517         @Override
getCountLocked(int which)1518         public int getCountLocked(int which) {
1519             return mCount.get();
1520         }
1521 
logState(Printer pw, String prefix)1522         public void logState(Printer pw, String prefix) {
1523             pw.println(prefix + "mCount=" + mCount.get());
1524         }
1525 
1526         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
stepAtomic()1527         public void stepAtomic() {
1528             if (mTimeBase.isRunning()) {
1529                 mCount.incrementAndGet();
1530             }
1531         }
1532 
addAtomic(int delta)1533         void addAtomic(int delta) {
1534             if (mTimeBase.isRunning()) {
1535                 mCount.addAndGet(delta);
1536             }
1537         }
1538 
1539         /**
1540          * Clear state of this counter.
1541          */
1542         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )1543         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
1544             mCount.set(0);
1545             if (detachIfReset) {
1546                 detach();
1547             }
1548             return true;
1549         }
1550 
1551         @Override
detach()1552         public void detach() {
1553             mTimeBase.remove(this);
1554         }
1555 
1556         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
writeSummaryFromParcelLocked(Parcel out)1557         public void writeSummaryFromParcelLocked(Parcel out) {
1558             out.writeInt(mCount.get());
1559         }
1560 
1561         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
readSummaryFromParcelLocked(Parcel in)1562         public void readSummaryFromParcelLocked(Parcel in) {
1563             mCount.set(in.readInt());
1564         }
1565     }
1566 
1567     @VisibleForTesting
1568     public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
1569         final TimeBase mTimeBase;
1570         public long[] mCounts;
1571 
LongSamplingCounterArray(TimeBase timeBase, Parcel in)1572         private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
1573             mTimeBase = timeBase;
1574             mCounts = in.createLongArray();
1575             timeBase.add(this);
1576         }
1577 
LongSamplingCounterArray(TimeBase timeBase)1578         public LongSamplingCounterArray(TimeBase timeBase) {
1579             mTimeBase = timeBase;
1580             timeBase.add(this);
1581         }
1582 
writeToParcel(Parcel out)1583         private void writeToParcel(Parcel out) {
1584             out.writeLongArray(mCounts);
1585         }
1586 
1587         @Override
onTimeStarted(long elapsedRealTimeUs, long baseUptimeUs, long baseRealtimeUs)1588         public void onTimeStarted(long elapsedRealTimeUs, long baseUptimeUs, long baseRealtimeUs) {
1589         }
1590 
1591         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1592         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
1593         }
1594 
1595         @Override
getCountsLocked(int which)1596         public long[] getCountsLocked(int which) {
1597             return mCounts == null ? null : Arrays.copyOf(mCounts, mCounts.length);
1598         }
1599 
1600         @Override
logState(Printer pw, String prefix)1601         public void logState(Printer pw, String prefix) {
1602             pw.println(prefix + "mCounts=" + Arrays.toString(mCounts));
1603         }
1604 
addCountLocked(long[] counts)1605         public void addCountLocked(long[] counts) {
1606             addCountLocked(counts, mTimeBase.isRunning());
1607         }
1608 
addCountLocked(long[] counts, boolean isRunning)1609         public void addCountLocked(long[] counts, boolean isRunning) {
1610             if (counts == null) {
1611                 return;
1612             }
1613             if (isRunning) {
1614                 if (mCounts == null) {
1615                     mCounts = new long[counts.length];
1616                 }
1617                 for (int i = 0; i < counts.length; ++i) {
1618                     mCounts[i] += counts[i];
1619                 }
1620             }
1621         }
1622 
getSize()1623         public int getSize() {
1624             return mCounts == null ? 0 : mCounts.length;
1625         }
1626 
1627         /**
1628          * Clear state of this counter.
1629          */
1630         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )1631         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
1632             if (mCounts != null) {
1633                 Arrays.fill(mCounts, 0);
1634             }
1635             if (detachIfReset) {
1636                 detach();
1637             }
1638             return true;
1639         }
1640 
1641         @Override
detach()1642         public void detach() {
1643             mTimeBase.remove(this);
1644         }
1645 
writeSummaryToParcelLocked(Parcel out)1646         private void writeSummaryToParcelLocked(Parcel out) {
1647             out.writeLongArray(mCounts);
1648         }
1649 
readSummaryFromParcelLocked(Parcel in)1650         private void readSummaryFromParcelLocked(Parcel in) {
1651             mCounts = in.createLongArray();
1652         }
1653 
writeToParcel(Parcel out, LongSamplingCounterArray counterArray)1654         public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
1655             if (counterArray != null) {
1656                 out.writeInt(1);
1657                 counterArray.writeToParcel(out);
1658             } else {
1659                 out.writeInt(0);
1660             }
1661         }
1662 
readFromParcel(Parcel in, TimeBase timeBase)1663         public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
1664             if (in.readInt() != 0) {
1665                 return new LongSamplingCounterArray(timeBase, in);
1666             } else {
1667                 return null;
1668             }
1669         }
1670 
writeSummaryToParcelLocked(Parcel out, LongSamplingCounterArray counterArray)1671         public static void writeSummaryToParcelLocked(Parcel out,
1672                 LongSamplingCounterArray counterArray) {
1673             if (counterArray != null) {
1674                 out.writeInt(1);
1675                 counterArray.writeSummaryToParcelLocked(out);
1676             } else {
1677                 out.writeInt(0);
1678             }
1679         }
1680 
readSummaryFromParcelLocked(Parcel in, TimeBase timeBase)1681         public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
1682                 TimeBase timeBase) {
1683             if (in.readInt() != 0) {
1684                 final LongSamplingCounterArray counterArray
1685                         = new LongSamplingCounterArray(timeBase);
1686                 counterArray.readSummaryFromParcelLocked(in);
1687                 return counterArray;
1688             } else {
1689                 return null;
1690             }
1691         }
1692     }
1693 
1694     @VisibleForTesting
1695     public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
1696         final TimeBase mTimeBase;
1697         private long mCount;
1698 
LongSamplingCounter(TimeBase timeBase, Parcel in)1699         public LongSamplingCounter(TimeBase timeBase, Parcel in) {
1700             mTimeBase = timeBase;
1701             mCount = in.readLong();
1702             timeBase.add(this);
1703         }
1704 
LongSamplingCounter(TimeBase timeBase)1705         public LongSamplingCounter(TimeBase timeBase) {
1706             mTimeBase = timeBase;
1707             timeBase.add(this);
1708         }
1709 
writeToParcel(Parcel out)1710         public void writeToParcel(Parcel out) {
1711             out.writeLong(mCount);
1712         }
1713 
1714         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1715         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
1716         }
1717 
1718         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1719         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
1720         }
1721 
getCountLocked(int which)1722         public long getCountLocked(int which) {
1723             return mCount;
1724         }
1725 
1726         @Override
logState(Printer pw, String prefix)1727         public void logState(Printer pw, String prefix) {
1728             pw.println(prefix + "mCount=" + mCount);
1729         }
1730 
addCountLocked(long count)1731         public void addCountLocked(long count) {
1732             addCountLocked(count, mTimeBase.isRunning());
1733         }
1734 
addCountLocked(long count, boolean isRunning)1735         public void addCountLocked(long count, boolean isRunning) {
1736             if (isRunning) {
1737                 mCount += count;
1738             }
1739         }
1740 
1741         /**
1742          * Clear state of this counter.
1743          */
1744         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )1745         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
1746             mCount = 0;
1747             if (detachIfReset) {
1748                 detach();
1749             }
1750             return true;
1751         }
1752 
1753         @Override
detach()1754         public void detach() {
1755             mTimeBase.remove(this);
1756         }
1757 
writeSummaryFromParcelLocked(Parcel out)1758         public void writeSummaryFromParcelLocked(Parcel out) {
1759             out.writeLong(mCount);
1760         }
1761 
readSummaryFromParcelLocked(Parcel in)1762         public void readSummaryFromParcelLocked(Parcel in) {
1763             mCount = in.readLong();
1764         }
1765     }
1766 
1767     /**
1768      * State for keeping track of timing information.
1769      */
1770     public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
1771         protected final Clocks mClocks;
1772         protected final int mType;
1773         protected final TimeBase mTimeBase;
1774 
1775         protected int mCount;
1776 
1777         // Times are in microseconds for better accuracy when dividing by the
1778         // lock count, and are in "battery realtime" units.
1779 
1780         /**
1781          * The total time we have accumulated since the start of the original
1782          * boot, to the last time something interesting happened in the
1783          * current run.
1784          */
1785         protected long mTotalTimeUs;
1786 
1787         /**
1788          * The total time this timer has been running until the latest mark has been set.
1789          * Subtract this from mTotalTimeUs to get the time spent running since the mark was set.
1790          */
1791         protected long mTimeBeforeMarkUs;
1792 
1793         /**
1794          * Constructs from a parcel.
1795          * @param type
1796          * @param timeBase
1797          * @param in
1798          */
Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in)1799         public Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in) {
1800             mClocks = clocks;
1801             mType = type;
1802             mTimeBase = timeBase;
1803 
1804             mCount = in.readInt();
1805             mTotalTimeUs = in.readLong();
1806             mTimeBeforeMarkUs = in.readLong();
1807             timeBase.add(this);
1808             if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTimeUs);
1809         }
1810 
Timer(Clocks clocks, int type, TimeBase timeBase)1811         public Timer(Clocks clocks, int type, TimeBase timeBase) {
1812             mClocks = clocks;
1813             mType = type;
1814             mTimeBase = timeBase;
1815             timeBase.add(this);
1816         }
1817 
writeToParcel(Parcel out, long elapsedRealtimeUs)1818         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1819             if (DEBUG) {
1820                 Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
1821                         + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
1822                                 elapsedRealtimeUs));
1823             }
1824             out.writeInt(computeCurrentCountLocked());
1825             out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
1826                         elapsedRealtimeUs));
1827             out.writeLong(mTimeBeforeMarkUs);
1828         }
1829 
computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs)1830         protected abstract long computeRunTimeLocked(long curBatteryRealtime,
1831                 long elapsedRealtimeUs);
1832 
computeCurrentCountLocked()1833         protected abstract int computeCurrentCountLocked();
1834 
1835         /**
1836          * Clear state of this timer.  Returns true if the timer is inactive
1837          * so can be completely dropped.
1838          */
1839         @Override
reset(boolean detachIfReset)1840         public boolean reset(boolean detachIfReset) {
1841             return reset(detachIfReset, mClocks.elapsedRealtime() * 1000);
1842         }
1843 
1844         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs )1845         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) {
1846             mTotalTimeUs = mTimeBeforeMarkUs = 0;
1847             mCount = 0;
1848             if (detachIfReset) {
1849                 detach();
1850             }
1851             return true;
1852         }
1853 
1854         @Override
detach()1855         public void detach() {
1856             mTimeBase.remove(this);
1857         }
1858 
1859         @Override
onTimeStarted(long elapsedRealtimeUs, long timeBaseUptimeUs, long baseRealtimeUs)1860         public void onTimeStarted(long elapsedRealtimeUs, long timeBaseUptimeUs,
1861                 long baseRealtimeUs) {
1862         }
1863 
1864         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)1865         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
1866             if (DEBUG && mType < 0) {
1867                 Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtimeUs
1868                         + " old mTotalTime=" + mTotalTimeUs);
1869             }
1870             mTotalTimeUs = computeRunTimeLocked(baseRealtimeUs, elapsedRealtimeUs);
1871             mCount = computeCurrentCountLocked();
1872             if (DEBUG && mType < 0) {
1873                 Log.v(TAG, "plug #" + mType + ": new mTotalTime=" + mTotalTimeUs);
1874             }
1875         }
1876 
1877         /**
1878          * Writes a possibly null Timer to a Parcel.
1879          *
1880          * @param out the Parcel to be written to.
1881          * @param timer a Timer, or null.
1882          */
1883         @UnsupportedAppUsage
writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs)1884         public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
1885             if (timer == null) {
1886                 out.writeInt(0); // indicates null
1887                 return;
1888             }
1889             out.writeInt(1); // indicates non-null
1890             timer.writeToParcel(out, elapsedRealtimeUs);
1891         }
1892 
1893         @Override
1894         @UnsupportedAppUsage
getTotalTimeLocked(long elapsedRealtimeUs, int which)1895         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
1896             return computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
1897                     elapsedRealtimeUs);
1898         }
1899 
1900         @Override
1901         @UnsupportedAppUsage
getCountLocked(int which)1902         public int getCountLocked(int which) {
1903             return computeCurrentCountLocked();
1904         }
1905 
1906         @Override
getTimeSinceMarkLocked(long elapsedRealtimeUs)1907         public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
1908             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
1909                     elapsedRealtimeUs);
1910             return val - mTimeBeforeMarkUs;
1911         }
1912 
1913         @Override
logState(Printer pw, String prefix)1914         public void logState(Printer pw, String prefix) {
1915             pw.println(prefix + "mCount=" + mCount);
1916             pw.println(prefix + "mTotalTime=" + mTotalTimeUs);
1917         }
1918 
1919 
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)1920         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
1921             long runTimeUs = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs),
1922                     elapsedRealtimeUs);
1923             out.writeLong(runTimeUs);
1924             out.writeInt(computeCurrentCountLocked());
1925         }
1926 
readSummaryFromParcelLocked(Parcel in)1927         public void readSummaryFromParcelLocked(Parcel in) {
1928             // Multiply by 1000 for backwards compatibility
1929             mTotalTimeUs = in.readLong();
1930             mCount = in.readInt();
1931             // When reading the summary, we set the mark to be the latest information.
1932             mTimeBeforeMarkUs = mTotalTimeUs;
1933         }
1934     }
1935 
1936     /**
1937      * A counter meant to accept monotonically increasing values to its {@link #update(long, int)}
1938      * method. The state of the timer according to its {@link TimeBase} will determine how much
1939      * of the value is recorded.
1940      *
1941      * If the value being recorded resets, {@link #endSample()} can be called in order to
1942      * account for the change. If the value passed in to {@link #update(long, int)} decreased
1943      * between calls, the {@link #endSample()} is automatically called and the new value is
1944      * expected to increase monotonically from that point on.
1945      */
1946     public static class SamplingTimer extends Timer {
1947 
1948         /**
1949          * The most recent reported count from /proc/wakelocks.
1950          */
1951         int mCurrentReportedCount;
1952 
1953         /**
1954          * The reported count from /proc/wakelocks when unplug() was last
1955          * called.
1956          */
1957         int mUnpluggedReportedCount;
1958 
1959         /**
1960          * The most recent reported total_time from /proc/wakelocks.
1961          */
1962         long mCurrentReportedTotalTimeUs;
1963 
1964 
1965         /**
1966          * The reported total_time from /proc/wakelocks when unplug() was last
1967          * called.
1968          */
1969         long mUnpluggedReportedTotalTimeUs;
1970 
1971         /**
1972          * Whether we are currently in a discharge cycle.
1973          */
1974         boolean mTimeBaseRunning;
1975 
1976         /**
1977          * Whether we are currently recording reported values.
1978          */
1979         boolean mTrackingReportedValues;
1980 
1981         /*
1982          * A sequence counter, incremented once for each update of the stats.
1983          */
1984         int mUpdateVersion;
1985 
1986         @VisibleForTesting
SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in)1987         public SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in) {
1988             super(clocks, 0, timeBase, in);
1989             mCurrentReportedCount = in.readInt();
1990             mUnpluggedReportedCount = in.readInt();
1991             mCurrentReportedTotalTimeUs = in.readLong();
1992             mUnpluggedReportedTotalTimeUs = in.readLong();
1993             mTrackingReportedValues = in.readInt() == 1;
1994             mTimeBaseRunning = timeBase.isRunning();
1995         }
1996 
1997         @VisibleForTesting
SamplingTimer(Clocks clocks, TimeBase timeBase)1998         public SamplingTimer(Clocks clocks, TimeBase timeBase) {
1999             super(clocks, 0, timeBase);
2000             mTrackingReportedValues = false;
2001             mTimeBaseRunning = timeBase.isRunning();
2002         }
2003 
2004         /**
2005          * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to
2006          * be less than the values used for a previous invocation.
2007          */
endSample()2008         public void endSample() {
2009             endSample(mClocks.elapsedRealtime() * 1000);
2010         }
2011 
2012         /**
2013          * @see #endSample()
2014          */
endSample(long elapsedRealtimeUs)2015         public void endSample(long elapsedRealtimeUs) {
2016             mTotalTimeUs = computeRunTimeLocked(0 /* unused by us */, elapsedRealtimeUs);
2017             mCount = computeCurrentCountLocked();
2018             mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs = 0;
2019             mUnpluggedReportedCount = mCurrentReportedCount = 0;
2020             mTrackingReportedValues = false;
2021         }
2022 
setUpdateVersion(int version)2023         public void setUpdateVersion(int version) {
2024             mUpdateVersion = version;
2025         }
2026 
getUpdateVersion()2027         public int getUpdateVersion() {
2028             return mUpdateVersion;
2029         }
2030 
2031         /**
2032          * Updates the current recorded values. These are meant to be monotonically increasing
2033          * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}.
2034          *
2035          * If the values being recorded have been reset, the monotonically increasing requirement
2036          * will be broken. In this case, {@link #endSample()} is automatically called and
2037          * the total value of totalTimeUs and count are recorded, starting a new monotonically
2038          * increasing sample.
2039          *
2040          * @param totalTimeUs total time of sample in microseconds.
2041          * @param count total number of times the event being sampled occurred.
2042          */
updated(long totalTimeUs, int count)2043         public void updated(long totalTimeUs, int count) {
2044             update(totalTimeUs, count, mClocks.elapsedRealtime() * 1000);
2045         }
2046 
2047         /**
2048          * @see #update(long, int)
2049          */
update(long totalTimeUs, int count, long elapsedRealtimeUs)2050         public void update(long totalTimeUs, int count, long elapsedRealtimeUs) {
2051             if (mTimeBaseRunning && !mTrackingReportedValues) {
2052                 // Updating the reported value for the first time.
2053                 mUnpluggedReportedTotalTimeUs = totalTimeUs;
2054                 mUnpluggedReportedCount = count;
2055             }
2056 
2057             mTrackingReportedValues = true;
2058 
2059             if (totalTimeUs < mCurrentReportedTotalTimeUs || count < mCurrentReportedCount) {
2060                 endSample(elapsedRealtimeUs);
2061             }
2062 
2063             mCurrentReportedTotalTimeUs = totalTimeUs;
2064             mCurrentReportedCount = count;
2065         }
2066 
2067         /**
2068          * Adds deltaTime and deltaCount to the current sample.
2069          *
2070          * @param deltaTime additional time recorded since the last sampled event, in microseconds.
2071          * @param deltaCount additional number of times the event being sampled occurred.
2072          */
add(long deltaTimeUs, int deltaCount)2073         public void add(long deltaTimeUs, int deltaCount) {
2074             add(deltaTimeUs, deltaCount, mClocks.elapsedRealtime() * 1000);
2075         }
2076 
2077         /**
2078          * @see #add(long, int)
2079          */
add(long deltaTimeUs, int deltaCount, long elapsedRealtimeUs)2080         public void add(long deltaTimeUs, int deltaCount, long elapsedRealtimeUs) {
2081             update(mCurrentReportedTotalTimeUs + deltaTimeUs, mCurrentReportedCount + deltaCount,
2082                     elapsedRealtimeUs);
2083         }
2084 
2085         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2086         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2087             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2088             if (mTrackingReportedValues) {
2089                 mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs;
2090                 mUnpluggedReportedCount = mCurrentReportedCount;
2091             }
2092             mTimeBaseRunning = true;
2093         }
2094 
2095         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2096         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2097             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2098             mTimeBaseRunning = false;
2099         }
2100 
2101         @Override
logState(Printer pw, String prefix)2102         public void logState(Printer pw, String prefix) {
2103             super.logState(pw, prefix);
2104             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
2105                     + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
2106                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTimeUs
2107                     + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTimeUs);
2108         }
2109 
2110         @Override
computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs)2111         protected long computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs) {
2112             return mTotalTimeUs + (mTimeBaseRunning && mTrackingReportedValues
2113                     ? mCurrentReportedTotalTimeUs - mUnpluggedReportedTotalTimeUs : 0);
2114         }
2115 
2116         @Override
computeCurrentCountLocked()2117         protected int computeCurrentCountLocked() {
2118             return mCount + (mTimeBaseRunning && mTrackingReportedValues
2119                     ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
2120         }
2121 
2122         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2123         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2124             super.writeToParcel(out, elapsedRealtimeUs);
2125             out.writeInt(mCurrentReportedCount);
2126             out.writeInt(mUnpluggedReportedCount);
2127             out.writeLong(mCurrentReportedTotalTimeUs);
2128             out.writeLong(mUnpluggedReportedTotalTimeUs);
2129             out.writeInt(mTrackingReportedValues ? 1 : 0);
2130         }
2131 
2132         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)2133         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
2134             super.reset(detachIfReset, elapsedRealtimeUs);
2135             mTrackingReportedValues = false;
2136             mUnpluggedReportedTotalTimeUs = 0;
2137             mUnpluggedReportedCount = 0;
2138             return true;
2139         }
2140     }
2141 
2142     /**
2143      * A timer that increments in batches.  It does not run for durations, but just jumps
2144      * for a pre-determined amount.
2145      */
2146     public static class BatchTimer extends Timer {
2147         final Uid mUid;
2148 
2149         /**
2150          * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
2151          */
2152         long mLastAddedTimeUs;
2153 
2154         /**
2155          * The last duration that we added to the timer.  This is in microseconds.
2156          */
2157         long mLastAddedDurationUs;
2158 
2159         /**
2160          * Whether we are currently in a discharge cycle.
2161          */
2162         boolean mInDischarge;
2163 
BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in)2164         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in) {
2165             super(clocks, type, timeBase, in);
2166             mUid = uid;
2167             mLastAddedTimeUs = in.readLong();
2168             mLastAddedDurationUs = in.readLong();
2169             mInDischarge = timeBase.isRunning();
2170         }
2171 
BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase)2172         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase) {
2173             super(clocks, type, timeBase);
2174             mUid = uid;
2175             mInDischarge = timeBase.isRunning();
2176         }
2177 
2178         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2179         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2180             super.writeToParcel(out, elapsedRealtimeUs);
2181             out.writeLong(mLastAddedTimeUs);
2182             out.writeLong(mLastAddedDurationUs);
2183         }
2184 
2185         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2186         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2187             recomputeLastDuration(elapsedRealtimeUs, false);
2188             mInDischarge = false;
2189             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2190         }
2191 
2192         @Override
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2193         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2194             recomputeLastDuration(elapsedRealtimeUs, false);
2195             mInDischarge = true;
2196             // If we are still within the last added duration, then re-added whatever remains.
2197             if (mLastAddedTimeUs == elapsedRealtimeUs) {
2198                 mTotalTimeUs += mLastAddedDurationUs;
2199             }
2200             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2201         }
2202 
2203         @Override
logState(Printer pw, String prefix)2204         public void logState(Printer pw, String prefix) {
2205             super.logState(pw, prefix);
2206             pw.println(prefix + "mLastAddedTime=" + mLastAddedTimeUs
2207                     + " mLastAddedDuration=" + mLastAddedDurationUs);
2208         }
2209 
computeOverage(long curTimeUs)2210         private long computeOverage(long curTimeUs) {
2211             if (mLastAddedTimeUs > 0) {
2212                 return mLastAddedDurationUs - curTimeUs;
2213             }
2214             return 0;
2215         }
2216 
recomputeLastDuration(long curTimeUs, boolean abort)2217         private void recomputeLastDuration(long curTimeUs, boolean abort) {
2218             final long overage = computeOverage(curTimeUs);
2219             if (overage > 0) {
2220                 // Aborting before the duration ran out -- roll back the remaining
2221                 // duration.  Only do this if currently discharging; otherwise we didn't
2222                 // actually add the time.
2223                 if (mInDischarge) {
2224                     mTotalTimeUs -= overage;
2225                 }
2226                 if (abort) {
2227                     mLastAddedTimeUs = 0;
2228                 } else {
2229                     mLastAddedTimeUs = curTimeUs;
2230                     mLastAddedDurationUs -= overage;
2231                 }
2232             }
2233         }
2234 
addDuration(BatteryStatsImpl stats, long durationMs)2235         public void addDuration(BatteryStatsImpl stats, long durationMs) {
2236             addDuration(stats, durationMs, mClocks.elapsedRealtime());
2237         }
2238 
addDuration(BatteryStatsImpl stats, long durationMs, long elapsedRealtimeMs)2239         public void addDuration(BatteryStatsImpl stats, long durationMs, long elapsedRealtimeMs) {
2240             final long nowUs = elapsedRealtimeMs * 1000;
2241             recomputeLastDuration(nowUs, true);
2242             mLastAddedTimeUs = nowUs;
2243             mLastAddedDurationUs = durationMs * 1000;
2244             if (mInDischarge) {
2245                 mTotalTimeUs += mLastAddedDurationUs;
2246                 mCount++;
2247             }
2248         }
2249 
abortLastDuration(BatteryStatsImpl stats)2250         public void abortLastDuration(BatteryStatsImpl stats) {
2251             abortLastDuration(stats, mClocks.elapsedRealtime());
2252         }
2253 
abortLastDuration(BatteryStatsImpl stats, long elapsedRealtimeMs)2254         public void abortLastDuration(BatteryStatsImpl stats, long elapsedRealtimeMs) {
2255             final long nowUs = elapsedRealtimeMs * 1000;
2256             recomputeLastDuration(nowUs, true);
2257         }
2258 
2259         @Override
computeCurrentCountLocked()2260         protected int computeCurrentCountLocked() {
2261             return mCount;
2262         }
2263 
2264         @Override
computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs)2265         protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) {
2266             final long overage = computeOverage(elapsedRealtimeUs);
2267             if (overage > 0) {
2268                 return mTotalTimeUs = overage;
2269             }
2270             return mTotalTimeUs;
2271         }
2272 
2273         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)2274         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
2275             recomputeLastDuration(elapsedRealtimeUs, true);
2276             boolean stillActive = mLastAddedTimeUs == elapsedRealtimeUs;
2277             super.reset(!stillActive && detachIfReset, elapsedRealtimeUs);
2278             return !stillActive;
2279         }
2280     }
2281 
2282 
2283     /**
2284      * A StopwatchTimer that also tracks the total and max individual
2285      * time spent active according to the given timebase.  Whereas
2286      * StopwatchTimer apportions the time amongst all in the pool,
2287      * the total and max durations are not apportioned.
2288      */
2289     public static class DurationTimer extends StopwatchTimer {
2290         /**
2291          * The time (in ms) that the timer was last acquired or the time base
2292          * last (re-)started. Increasing the nesting depth does not reset this time.
2293          *
2294          * -1 if the timer is currently not running or the time base is not running.
2295          *
2296          * If written to a parcel, the start time is reset, as is mNesting in the base class
2297          * StopwatchTimer.
2298          */
2299         long mStartTimeMs = -1;
2300 
2301         /**
2302          * The longest time period (in ms) that the timer has been active. Not pooled.
2303          */
2304         long mMaxDurationMs;
2305 
2306         /**
2307          * The time (in ms) that that the timer has been active since most recent
2308          * stopRunningLocked() or reset(). Not pooled.
2309          */
2310         long mCurrentDurationMs;
2311 
2312         /**
2313          * The total time (in ms) that that the timer has been active since most recent reset()
2314          * prior to the current startRunningLocked. This is the sum of all past currentDurations
2315          * (but not including the present currentDuration) since reset. Not pooled.
2316          */
2317         long mTotalDurationMs;
2318 
DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)2319         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2320                 TimeBase timeBase, Parcel in) {
2321             super(clocks, uid, type, timerPool, timeBase, in);
2322             mMaxDurationMs = in.readLong();
2323             mTotalDurationMs = in.readLong();
2324             mCurrentDurationMs = in.readLong();
2325         }
2326 
DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)2327         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2328                 TimeBase timeBase) {
2329             super(clocks, uid, type, timerPool, timeBase);
2330         }
2331 
2332         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2333         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2334             super.writeToParcel(out, elapsedRealtimeUs);
2335             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2336             out.writeLong(mTotalDurationMs);
2337             out.writeLong(getCurrentDurationMsLocked(elapsedRealtimeUs / 1000));
2338         }
2339 
2340         /**
2341          * Write the summary to the parcel.
2342          *
2343          * Since the time base is probably meaningless after we come back, reading
2344          * from this will have the effect of stopping the timer. So here all we write
2345          * is the max and total durations.
2346          */
2347         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2348         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2349             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2350             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2351             out.writeLong(getTotalDurationMsLocked(elapsedRealtimeUs / 1000));
2352         }
2353 
2354         /**
2355          * Read the summary parcel.
2356          *
2357          * Has the side effect of stopping the timer.
2358          */
2359         @Override
readSummaryFromParcelLocked(Parcel in)2360         public void readSummaryFromParcelLocked(Parcel in) {
2361             super.readSummaryFromParcelLocked(in);
2362             mMaxDurationMs = in.readLong();
2363             mTotalDurationMs = in.readLong();
2364             mStartTimeMs = -1;
2365             mCurrentDurationMs = 0;
2366         }
2367 
2368         /**
2369          * The TimeBase time started (again).
2370          *
2371          * If the timer is also running, store the start time.
2372          */
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2373         public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2374             super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2375             if (mNesting > 0) {
2376                 mStartTimeMs = baseRealtimeUs / 1000;
2377             }
2378         }
2379 
2380         /**
2381          * The TimeBase stopped running.
2382          *
2383          * If the timer is running, add the duration into mCurrentDurationMs.
2384          */
2385         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2386         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2387             super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2388             if (mNesting > 0) {
2389                 // baseRealtimeUs has already been converted to the timebase's realtime.
2390                 mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
2391             }
2392             mStartTimeMs = -1;
2393         }
2394 
2395         @Override
logState(Printer pw, String prefix)2396         public void logState(Printer pw, String prefix) {
2397             super.logState(pw, prefix);
2398         }
2399 
2400         @Override
startRunningLocked(long elapsedRealtimeMs)2401         public void startRunningLocked(long elapsedRealtimeMs) {
2402             super.startRunningLocked(elapsedRealtimeMs);
2403             if (mNesting == 1 && mTimeBase.isRunning()) {
2404                 // Just started
2405                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000;
2406             }
2407         }
2408 
2409         /**
2410          * Decrements the mNesting ref-count on this timer.
2411          *
2412          * If it actually stopped (mNesting went to 0), then possibly update
2413          * mMaxDuration if the current duration was the longest ever.
2414          */
2415         @Override
stopRunningLocked(long elapsedRealtimeMs)2416         public void stopRunningLocked(long elapsedRealtimeMs) {
2417             if (mNesting == 1) {
2418                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2419                 mTotalDurationMs += durationMs;
2420                 if (durationMs > mMaxDurationMs) {
2421                     mMaxDurationMs = durationMs;
2422                 }
2423                 mStartTimeMs = -1;
2424                 mCurrentDurationMs = 0;
2425             }
2426             // super method decrements mNesting, which getCurrentDurationMsLocked relies on,
2427             // so call super.stopRunningLocked after calling getCurrentDurationMsLocked.
2428             super.stopRunningLocked(elapsedRealtimeMs);
2429         }
2430 
2431         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)2432         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
2433             boolean result = super.reset(detachIfReset, elapsedRealtimeUs);
2434             mMaxDurationMs = 0;
2435             mTotalDurationMs = 0;
2436             mCurrentDurationMs = 0;
2437             if (mNesting > 0) {
2438                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeUs) / 1000;
2439             } else {
2440                 mStartTimeMs = -1;
2441             }
2442             return result;
2443         }
2444 
2445         /**
2446          * Returns the max duration that this timer has ever seen.
2447          *
2448          * Note that this time is NOT split between the timers in the timer group that
2449          * this timer is attached to.  It is the TOTAL time.
2450          */
2451         @Override
getMaxDurationMsLocked(long elapsedRealtimeMs)2452         public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
2453             if (mNesting > 0) {
2454                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2455                 if (durationMs > mMaxDurationMs) {
2456                     return durationMs;
2457                 }
2458             }
2459             return mMaxDurationMs;
2460         }
2461 
2462         /**
2463          * Returns the time since the timer was started.
2464          * Returns 0 if the timer is not currently running.
2465          *
2466          * Note that this time is NOT split between the timers in the timer group that
2467          * this timer is attached to.  It is the TOTAL time.
2468          *
2469          * Note that if running timer is parceled and unparceled, this method will return
2470          * current duration value at the time of parceling even though timer may not be
2471          * currently running.
2472          */
2473         @Override
getCurrentDurationMsLocked(long elapsedRealtimeMs)2474         public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
2475             long durationMs = mCurrentDurationMs;
2476             if (mNesting > 0 && mTimeBase.isRunning()) {
2477                 durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000)
2478                         - mStartTimeMs;
2479             }
2480             return durationMs;
2481         }
2482 
2483         /**
2484          * Returns the total cumulative duration that this timer has been on since reset().
2485          * If mTimerPool == null, this should be the same
2486          * as getTotalTimeLocked(elapsedRealtimeMs*1000, STATS_SINCE_CHARGED)/1000.
2487          *
2488          * Note that this time is NOT split between the timers in the timer group that
2489          * this timer is attached to.  It is the TOTAL time. For this reason, if mTimerPool != null,
2490          * the result will not be equivalent to getTotalTimeLocked.
2491          */
2492         @Override
getTotalDurationMsLocked(long elapsedRealtimeMs)2493         public long getTotalDurationMsLocked(long elapsedRealtimeMs) {
2494             return mTotalDurationMs + getCurrentDurationMsLocked(elapsedRealtimeMs);
2495         }
2496     }
2497 
2498     /**
2499      * State for keeping track of timing information.
2500      */
2501     public static class StopwatchTimer extends Timer {
2502         final Uid mUid;
2503         final ArrayList<StopwatchTimer> mTimerPool;
2504 
2505         int mNesting;
2506 
2507         /**
2508          * The last time at which we updated the timer.  If mNesting is > 0,
2509          * subtract this from the current battery time to find the amount of
2510          * time we have been running since we last computed an update.
2511          */
2512         long mUpdateTimeUs;
2513 
2514         /**
2515          * The total time at which the timer was acquired, to determine if it
2516          * was actually held for an interesting duration. If time base was not running when timer
2517          * was acquired, will be -1.
2518          */
2519         long mAcquireTimeUs = -1;
2520 
2521         long mTimeoutUs;
2522 
2523         /**
2524          * For partial wake locks, keep track of whether we are in the list
2525          * to consume CPU cycles.
2526          */
2527         @VisibleForTesting
2528         public boolean mInList;
2529 
StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)2530         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2531                 TimeBase timeBase, Parcel in) {
2532             super(clocks, type, timeBase, in);
2533             mUid = uid;
2534             mTimerPool = timerPool;
2535             mUpdateTimeUs = in.readLong();
2536         }
2537 
StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)2538         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2539                 TimeBase timeBase) {
2540             super(clocks, type, timeBase);
2541             mUid = uid;
2542             mTimerPool = timerPool;
2543         }
2544 
setTimeout(long timeoutUs)2545         public void setTimeout(long timeoutUs) {
2546             mTimeoutUs = timeoutUs;
2547         }
2548 
writeToParcel(Parcel out, long elapsedRealtimeUs)2549         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2550             super.writeToParcel(out, elapsedRealtimeUs);
2551             out.writeLong(mUpdateTimeUs);
2552         }
2553 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)2554         public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) {
2555             if (mNesting > 0) {
2556                 if (DEBUG && mType < 0) {
2557                     Log.v(TAG, "old mUpdateTime=" + mUpdateTimeUs);
2558                 }
2559                 super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs);
2560                 mUpdateTimeUs = baseRealtimeUs;
2561                 if (DEBUG && mType < 0) {
2562                     Log.v(TAG, "new mUpdateTime=" + mUpdateTimeUs);
2563                 }
2564             }
2565         }
2566 
logState(Printer pw, String prefix)2567         public void logState(Printer pw, String prefix) {
2568             super.logState(pw, prefix);
2569             pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTimeUs
2570                     + " mAcquireTime=" + mAcquireTimeUs);
2571         }
2572 
startRunningLocked(long elapsedRealtimeMs)2573         public void startRunningLocked(long elapsedRealtimeMs) {
2574             if (mNesting++ == 0) {
2575                 final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2576                 mUpdateTimeUs = batteryRealtimeUs;
2577                 if (mTimerPool != null) {
2578                     // Accumulate time to all currently active timers before adding
2579                     // this new one to the pool.
2580                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, null);
2581                     // Add this timer to the active pool
2582                     mTimerPool.add(this);
2583                 }
2584                 if (mTimeBase.isRunning()) {
2585                     // Increment the count
2586                     mCount++;
2587                     mAcquireTimeUs = mTotalTimeUs;
2588                 } else {
2589                     mAcquireTimeUs = -1;
2590                 }
2591                 if (DEBUG && mType < 0) {
2592                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTimeUs
2593                             + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount
2594                             + " mAcquireTime=" + mAcquireTimeUs);
2595                 }
2596             }
2597         }
2598 
isRunningLocked()2599         public boolean isRunningLocked() {
2600             return mNesting > 0;
2601         }
2602 
stopRunningLocked(long elapsedRealtimeMs)2603         public void stopRunningLocked(long elapsedRealtimeMs) {
2604             // Ignore attempt to stop a timer that isn't running
2605             if (mNesting == 0) {
2606                 return;
2607             }
2608             if (--mNesting == 0) {
2609                 final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2610                 if (mTimerPool != null) {
2611                     // Accumulate time to all active counters, scaled by the total
2612                     // active in the pool, before taking this one out of the pool.
2613                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, null);
2614                     // Remove this timer from the active pool
2615                     mTimerPool.remove(this);
2616                 } else {
2617                     mNesting = 1;
2618                     mTotalTimeUs = computeRunTimeLocked(batteryRealtimeUs,
2619                             elapsedRealtimeMs * 1000);
2620                     mNesting = 0;
2621                 }
2622 
2623                 if (DEBUG && mType < 0) {
2624                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTimeUs
2625                             + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount
2626                             + " mAcquireTime=" + mAcquireTimeUs);
2627                 }
2628 
2629                 if (mAcquireTimeUs >= 0 && mTotalTimeUs == mAcquireTimeUs) {
2630                     // If there was no change in the time, then discard this
2631                     // count.  A somewhat cheezy strategy, but hey.
2632                     mCount--;
2633                 }
2634             }
2635         }
2636 
stopAllRunningLocked(long elapsedRealtimeMs)2637         public void stopAllRunningLocked(long elapsedRealtimeMs) {
2638             if (mNesting > 0) {
2639                 mNesting = 1;
2640                 stopRunningLocked(elapsedRealtimeMs);
2641             }
2642         }
2643 
2644         // Update the total time for all other running Timers with the same type as this Timer
2645         // due to a change in timer count
refreshTimersLocked(long batteryRealtimeUs, final ArrayList<StopwatchTimer> pool, StopwatchTimer self)2646         private static long refreshTimersLocked(long batteryRealtimeUs,
2647                 final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
2648             long selfTimeUs = 0;
2649             final int N = pool.size();
2650             for (int i=N-1; i>= 0; i--) {
2651                 final StopwatchTimer t = pool.get(i);
2652                 long heldTimeUs = batteryRealtimeUs - t.mUpdateTimeUs;
2653                 if (heldTimeUs > 0) {
2654                     final long myTimeUs = heldTimeUs / N;
2655                     if (t == self) {
2656                         selfTimeUs = myTimeUs;
2657                     }
2658                     t.mTotalTimeUs += myTimeUs;
2659                 }
2660                 t.mUpdateTimeUs = batteryRealtimeUs;
2661             }
2662             return selfTimeUs;
2663         }
2664 
2665         @Override
computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs)2666         protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) {
2667             if (mTimeoutUs > 0 && curBatteryRealtimeUs > mUpdateTimeUs + mTimeoutUs) {
2668                 curBatteryRealtimeUs = mUpdateTimeUs + mTimeoutUs;
2669             }
2670             return mTotalTimeUs + (mNesting > 0
2671                     ? (curBatteryRealtimeUs - mUpdateTimeUs)
2672                             / (mTimerPool != null ? mTimerPool.size() : 1)
2673                     : 0);
2674         }
2675 
2676         @Override
computeCurrentCountLocked()2677         protected int computeCurrentCountLocked() {
2678             return mCount;
2679         }
2680 
2681         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)2682         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
2683             boolean canDetach = mNesting <= 0;
2684             super.reset(canDetach && detachIfReset, elapsedRealtimeUs);
2685             if (mNesting > 0) {
2686                 mUpdateTimeUs = mTimeBase.getRealtime(elapsedRealtimeUs);
2687             }
2688             // To ensure mCount isn't decreased to -1 if timer is stopped later.
2689             mAcquireTimeUs = -1;
2690             return canDetach;
2691         }
2692 
2693         @Override
2694         @UnsupportedAppUsage
detach()2695         public void detach() {
2696             super.detach();
2697             if (mTimerPool != null) {
2698                 mTimerPool.remove(this);
2699             }
2700         }
2701 
2702         @Override
readSummaryFromParcelLocked(Parcel in)2703         public void readSummaryFromParcelLocked(Parcel in) {
2704             super.readSummaryFromParcelLocked(in);
2705             mNesting = 0;
2706         }
2707 
2708         /**
2709          * Set the mark so that we can query later for the total time the timer has
2710          * accumulated since this point. The timer can be running or not.
2711          *
2712          * @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
2713          */
setMark(long elapsedRealtimeMs)2714         public void setMark(long elapsedRealtimeMs) {
2715             final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2716             if (mNesting > 0) {
2717                 // We are running.
2718                 if (mTimerPool != null) {
2719                     refreshTimersLocked(batteryRealtimeUs, mTimerPool, this);
2720                 } else {
2721                     mTotalTimeUs += batteryRealtimeUs - mUpdateTimeUs;
2722                     mUpdateTimeUs = batteryRealtimeUs;
2723                 }
2724             }
2725             mTimeBeforeMarkUs = mTotalTimeUs;
2726         }
2727     }
2728 
2729     /**
2730      * State for keeping track of two DurationTimers with different TimeBases, presumably where one
2731      * TimeBase is effectively a subset of the other.
2732      */
2733     public static class DualTimer extends DurationTimer {
2734         // This class both is a DurationTimer and also holds a second DurationTimer.
2735         // The main timer (this) typically tracks the total time. It may be pooled (but since it's a
2736         // durationTimer, it also has the unpooled getTotalDurationMsLocked() for
2737         // STATS_SINCE_CHARGED).
2738         // mSubTimer typically tracks only part of the total time, such as background time, as
2739         // determined by a subTimeBase. It is NOT pooled.
2740         private final DurationTimer mSubTimer;
2741 
2742         /**
2743          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2744          * The main timer (this) is based on the given timeBase and timerPool.
2745          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2746          * the main timer is.
2747          */
DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase, Parcel in)2748         public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2749                 TimeBase timeBase, TimeBase subTimeBase, Parcel in) {
2750             super(clocks, uid, type, timerPool, timeBase, in);
2751             mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase, in);
2752         }
2753 
2754         /**
2755          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2756          * The main timer (this) is based on the given timeBase and timerPool.
2757          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2758          * the main timer is.
2759          */
DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase)2760         public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2761                 TimeBase timeBase, TimeBase subTimeBase) {
2762             super(clocks, uid, type, timerPool, timeBase);
2763             mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase);
2764         }
2765 
2766         /** Get the secondary timer. */
2767         @Override
getSubTimer()2768         public DurationTimer getSubTimer() {
2769             return mSubTimer;
2770         }
2771 
2772         @Override
startRunningLocked(long elapsedRealtimeMs)2773         public void startRunningLocked(long elapsedRealtimeMs) {
2774             super.startRunningLocked(elapsedRealtimeMs);
2775             mSubTimer.startRunningLocked(elapsedRealtimeMs);
2776         }
2777 
2778         @Override
stopRunningLocked(long elapsedRealtimeMs)2779         public void stopRunningLocked(long elapsedRealtimeMs) {
2780             super.stopRunningLocked(elapsedRealtimeMs);
2781             mSubTimer.stopRunningLocked(elapsedRealtimeMs);
2782         }
2783 
2784         @Override
stopAllRunningLocked(long elapsedRealtimeMs)2785         public void stopAllRunningLocked(long elapsedRealtimeMs) {
2786             super.stopAllRunningLocked(elapsedRealtimeMs);
2787             mSubTimer.stopAllRunningLocked(elapsedRealtimeMs);
2788         }
2789 
2790         @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)2791         public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
2792             boolean active = false;
2793             // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
2794             active |= !mSubTimer.reset(false, elapsedRealtimeUs);
2795             active |= !super.reset(detachIfReset, elapsedRealtimeUs);
2796             return !active;
2797         }
2798 
2799         @Override
detach()2800         public void detach() {
2801             mSubTimer.detach();
2802             super.detach();
2803         }
2804 
2805         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2806         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2807             super.writeToParcel(out, elapsedRealtimeUs);
2808             mSubTimer.writeToParcel(out, elapsedRealtimeUs);
2809         }
2810 
2811         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2812         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2813             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2814             mSubTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2815         }
2816 
2817         @Override
readSummaryFromParcelLocked(Parcel in)2818         public void readSummaryFromParcelLocked(Parcel in) {
2819             super.readSummaryFromParcelLocked(in);
2820             mSubTimer.readSummaryFromParcelLocked(in);
2821         }
2822     }
2823 
2824 
2825     public abstract class OverflowArrayMap<T> {
2826         private static final String OVERFLOW_NAME = "*overflow*";
2827 
2828         final int mUid;
2829         final ArrayMap<String, T> mMap = new ArrayMap<>();
2830         T mCurOverflow;
2831         ArrayMap<String, MutableInt> mActiveOverflow;
2832         long mLastOverflowTimeMs;
2833         long mLastOverflowFinishTimeMs;
2834         long mLastClearTimeMs;
2835         long mLastCleanupTimeMs;
2836 
OverflowArrayMap(int uid)2837         public OverflowArrayMap(int uid) {
2838             mUid = uid;
2839         }
2840 
getMap()2841         public ArrayMap<String, T> getMap() {
2842             return mMap;
2843         }
2844 
clear()2845         public void clear() {
2846             mLastClearTimeMs = SystemClock.elapsedRealtime();
2847             mMap.clear();
2848             mCurOverflow = null;
2849             mActiveOverflow = null;
2850         }
2851 
add(String name, T obj)2852         public void add(String name, T obj) {
2853             if (name == null) {
2854                 name = "";
2855             }
2856             mMap.put(name, obj);
2857             if (OVERFLOW_NAME.equals(name)) {
2858                 mCurOverflow = obj;
2859             }
2860         }
2861 
cleanup(long elapsedRealtimeMs)2862         public void cleanup(long elapsedRealtimeMs) {
2863             mLastCleanupTimeMs = elapsedRealtimeMs;
2864             if (mActiveOverflow != null) {
2865                 if (mActiveOverflow.size() == 0) {
2866                     mActiveOverflow = null;
2867                 }
2868             }
2869             if (mActiveOverflow == null) {
2870                 // There is no currently active overflow, so we should no longer have
2871                 // an overflow entry.
2872                 if (mMap.containsKey(OVERFLOW_NAME)) {
2873                     Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
2874                             + mMap.get(OVERFLOW_NAME));
2875                     mMap.remove(OVERFLOW_NAME);
2876                 }
2877                 mCurOverflow = null;
2878             } else {
2879                 // There is currently active overflow, so we should still have an overflow entry.
2880                 if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
2881                     Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
2882                             + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
2883                 }
2884             }
2885         }
2886 
startObject(String name, long elapsedRealtimeMs)2887         public T startObject(String name, long elapsedRealtimeMs) {
2888             if (name == null) {
2889                 name = "";
2890             }
2891             T obj = mMap.get(name);
2892             if (obj != null) {
2893                 return obj;
2894             }
2895 
2896             // No object exists for the given name, but do we currently have it
2897             // running as part of the overflow?
2898             if (mActiveOverflow != null) {
2899                 MutableInt over = mActiveOverflow.get(name);
2900                 if (over != null) {
2901                     // We are already actively counting this name in the overflow object.
2902                     obj = mCurOverflow;
2903                     if (obj == null) {
2904                         // Shouldn't be here, but we'll try to recover.
2905                         Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
2906                         obj = mCurOverflow = instantiateObject();
2907                         mMap.put(OVERFLOW_NAME, obj);
2908                     }
2909                     over.value++;
2910                     return obj;
2911                 }
2912             }
2913 
2914             // No object exists for given name nor in the overflow; we need to make
2915             // a new one.
2916             final int N = mMap.size();
2917             if (N >= MAX_WAKELOCKS_PER_UID) {
2918                 // Went over the limit on number of objects to track; this one goes
2919                 // in to the overflow.
2920                 obj = mCurOverflow;
2921                 if (obj == null) {
2922                     // Need to start overflow now...
2923                     obj = mCurOverflow = instantiateObject();
2924                     mMap.put(OVERFLOW_NAME, obj);
2925                 }
2926                 if (mActiveOverflow == null) {
2927                     mActiveOverflow = new ArrayMap<>();
2928                 }
2929                 mActiveOverflow.put(name, new MutableInt(1));
2930                 mLastOverflowTimeMs = elapsedRealtimeMs;
2931                 return obj;
2932             }
2933 
2934             // Normal case where we just need to make a new object.
2935             obj = instantiateObject();
2936             mMap.put(name, obj);
2937             return obj;
2938         }
2939 
stopObject(String name, long elapsedRealtimeMs)2940         public T stopObject(String name, long elapsedRealtimeMs) {
2941             if (name == null) {
2942                 name = "";
2943             }
2944             T obj = mMap.get(name);
2945             if (obj != null) {
2946                 return obj;
2947             }
2948 
2949             // No object exists for the given name, but do we currently have it
2950             // running as part of the overflow?
2951             if (mActiveOverflow != null) {
2952                 MutableInt over = mActiveOverflow.get(name);
2953                 if (over != null) {
2954                     // We are already actively counting this name in the overflow object.
2955                     obj = mCurOverflow;
2956                     if (obj != null) {
2957                         over.value--;
2958                         if (over.value <= 0) {
2959                             mActiveOverflow.remove(name);
2960                             mLastOverflowFinishTimeMs = elapsedRealtimeMs;
2961                         }
2962                         return obj;
2963                     }
2964                 }
2965             }
2966 
2967             // Huh, they are stopping an active operation but we can't find one!
2968             // That's not good.
2969             StringBuilder sb = new StringBuilder();
2970             sb.append("Unable to find object for ");
2971             sb.append(name);
2972             sb.append(" in uid ");
2973             sb.append(mUid);
2974             sb.append(" mapsize=");
2975             sb.append(mMap.size());
2976             sb.append(" activeoverflow=");
2977             sb.append(mActiveOverflow);
2978             sb.append(" curoverflow=");
2979             sb.append(mCurOverflow);
2980             long now = elapsedRealtimeMs;
2981             if (mLastOverflowTimeMs != 0) {
2982                 sb.append(" lastOverflowTime=");
2983                 TimeUtils.formatDuration(mLastOverflowTimeMs - now, sb);
2984             }
2985             if (mLastOverflowFinishTimeMs != 0) {
2986                 sb.append(" lastOverflowFinishTime=");
2987                 TimeUtils.formatDuration(mLastOverflowFinishTimeMs - now, sb);
2988             }
2989             if (mLastClearTimeMs != 0) {
2990                 sb.append(" lastClearTime=");
2991                 TimeUtils.formatDuration(mLastClearTimeMs - now, sb);
2992             }
2993             if (mLastCleanupTimeMs != 0) {
2994                 sb.append(" lastCleanupTime=");
2995                 TimeUtils.formatDuration(mLastCleanupTimeMs - now, sb);
2996             }
2997             Slog.wtf(TAG, sb.toString());
2998             return null;
2999         }
3000 
instantiateObject()3001         public abstract T instantiateObject();
3002     }
3003 
3004     public static class ControllerActivityCounterImpl extends ControllerActivityCounter
3005             implements Parcelable {
3006         private final LongSamplingCounter mIdleTimeMillis;
3007         private final LongSamplingCounter mScanTimeMillis;
3008         private final LongSamplingCounter mSleepTimeMillis;
3009         private final LongSamplingCounter mRxTimeMillis;
3010         private final LongSamplingCounter[] mTxTimeMillis;
3011         private final LongSamplingCounter mPowerDrainMaMs;
3012         private final LongSamplingCounter mMonitoredRailChargeConsumedMaMs;
3013 
ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates)3014         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates) {
3015             mIdleTimeMillis = new LongSamplingCounter(timeBase);
3016             mScanTimeMillis = new LongSamplingCounter(timeBase);
3017             mSleepTimeMillis = new LongSamplingCounter(timeBase);
3018             mRxTimeMillis = new LongSamplingCounter(timeBase);
3019             mTxTimeMillis = new LongSamplingCounter[numTxStates];
3020             for (int i = 0; i < numTxStates; i++) {
3021                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase);
3022             }
3023             mPowerDrainMaMs = new LongSamplingCounter(timeBase);
3024             mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase);
3025         }
3026 
ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in)3027         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in) {
3028             mIdleTimeMillis = new LongSamplingCounter(timeBase, in);
3029             mScanTimeMillis = new LongSamplingCounter(timeBase, in);
3030             mSleepTimeMillis = new LongSamplingCounter(timeBase, in);
3031             mRxTimeMillis = new LongSamplingCounter(timeBase, in);
3032             final int recordedTxStates = in.readInt();
3033             if (recordedTxStates != numTxStates) {
3034                 throw new ParcelFormatException("inconsistent tx state lengths");
3035             }
3036 
3037             mTxTimeMillis = new LongSamplingCounter[numTxStates];
3038             for (int i = 0; i < numTxStates; i++) {
3039                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase, in);
3040             }
3041             mPowerDrainMaMs = new LongSamplingCounter(timeBase, in);
3042             mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase, in);
3043         }
3044 
readSummaryFromParcel(Parcel in)3045         public void readSummaryFromParcel(Parcel in) {
3046             mIdleTimeMillis.readSummaryFromParcelLocked(in);
3047             mScanTimeMillis.readSummaryFromParcelLocked(in);
3048             mSleepTimeMillis.readSummaryFromParcelLocked(in);
3049             mRxTimeMillis.readSummaryFromParcelLocked(in);
3050             final int recordedTxStates = in.readInt();
3051             if (recordedTxStates != mTxTimeMillis.length) {
3052                 throw new ParcelFormatException("inconsistent tx state lengths");
3053             }
3054             for (LongSamplingCounter counter : mTxTimeMillis) {
3055                 counter.readSummaryFromParcelLocked(in);
3056             }
3057             mPowerDrainMaMs.readSummaryFromParcelLocked(in);
3058             mMonitoredRailChargeConsumedMaMs.readSummaryFromParcelLocked(in);
3059         }
3060 
3061         @Override
describeContents()3062         public int describeContents() {
3063             return 0;
3064         }
3065 
writeSummaryToParcel(Parcel dest)3066         public void writeSummaryToParcel(Parcel dest) {
3067             mIdleTimeMillis.writeSummaryFromParcelLocked(dest);
3068             mScanTimeMillis.writeSummaryFromParcelLocked(dest);
3069             mSleepTimeMillis.writeSummaryFromParcelLocked(dest);
3070             mRxTimeMillis.writeSummaryFromParcelLocked(dest);
3071             dest.writeInt(mTxTimeMillis.length);
3072             for (LongSamplingCounter counter : mTxTimeMillis) {
3073                 counter.writeSummaryFromParcelLocked(dest);
3074             }
3075             mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
3076             mMonitoredRailChargeConsumedMaMs.writeSummaryFromParcelLocked(dest);
3077         }
3078 
3079         @Override
writeToParcel(Parcel dest, int flags)3080         public void writeToParcel(Parcel dest, int flags) {
3081             mIdleTimeMillis.writeToParcel(dest);
3082             mScanTimeMillis.writeToParcel(dest);
3083             mSleepTimeMillis.writeToParcel(dest);
3084             mRxTimeMillis.writeToParcel(dest);
3085             dest.writeInt(mTxTimeMillis.length);
3086             for (LongSamplingCounter counter : mTxTimeMillis) {
3087                 counter.writeToParcel(dest);
3088             }
3089             mPowerDrainMaMs.writeToParcel(dest);
3090             mMonitoredRailChargeConsumedMaMs.writeToParcel(dest);
3091         }
3092 
reset(boolean detachIfReset, long elapsedRealtimeUs)3093         public void reset(boolean detachIfReset, long elapsedRealtimeUs) {
3094             mIdleTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
3095             mScanTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
3096             mSleepTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
3097             mRxTimeMillis.reset(detachIfReset, elapsedRealtimeUs);
3098             for (LongSamplingCounter counter : mTxTimeMillis) {
3099                 counter.reset(detachIfReset, elapsedRealtimeUs);
3100             }
3101             mPowerDrainMaMs.reset(detachIfReset, elapsedRealtimeUs);
3102             mMonitoredRailChargeConsumedMaMs.reset(detachIfReset, elapsedRealtimeUs);
3103         }
3104 
detach()3105         public void detach() {
3106             mIdleTimeMillis.detach();
3107             mScanTimeMillis.detach();
3108             mSleepTimeMillis.detach();
3109             mRxTimeMillis.detach();
3110             for (LongSamplingCounter counter : mTxTimeMillis) {
3111                 counter.detach();
3112             }
3113             mPowerDrainMaMs.detach();
3114             mMonitoredRailChargeConsumedMaMs.detach();
3115         }
3116 
3117         /**
3118          * @return a LongSamplingCounter, measuring time spent in the idle state in
3119          * milliseconds.
3120          */
3121         @Override
getIdleTimeCounter()3122         public LongSamplingCounter getIdleTimeCounter() {
3123             return mIdleTimeMillis;
3124         }
3125 
3126         /**
3127          * @return a LongSamplingCounter, measuring time spent in the scan state in
3128          * milliseconds.
3129          */
3130         @Override
getScanTimeCounter()3131         public LongSamplingCounter getScanTimeCounter() {
3132             return mScanTimeMillis;
3133         }
3134 
3135         /**
3136          * @return a LongSamplingCounter, measuring time spent in the sleep state in
3137          * milliseconds.
3138          */
3139         @Override
getSleepTimeCounter()3140         public LongSamplingCounter getSleepTimeCounter() {
3141             return mSleepTimeMillis;
3142         }
3143 
3144         /**
3145          * @return a LongSamplingCounter, measuring time spent in the receive state in
3146          * milliseconds.
3147          */
3148         @Override
getRxTimeCounter()3149         public LongSamplingCounter getRxTimeCounter() {
3150             return mRxTimeMillis;
3151         }
3152 
3153         /**
3154          * @return a LongSamplingCounter[], measuring time spent in various transmit states in
3155          * milliseconds.
3156          */
3157         @Override
getTxTimeCounters()3158         public LongSamplingCounter[] getTxTimeCounters() {
3159             return mTxTimeMillis;
3160         }
3161 
3162         /**
3163          * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
3164          */
3165         @Override
getPowerCounter()3166         public LongSamplingCounter getPowerCounter() {
3167             return mPowerDrainMaMs;
3168         }
3169 
3170         /**
3171          * @return a LongSamplingCounter, measuring actual monitored rail energy consumed
3172          * milli-ampere milli-seconds (mAmS).
3173          */
3174         @Override
getMonitoredRailChargeConsumedMaMs()3175         public LongSamplingCounter getMonitoredRailChargeConsumedMaMs() {
3176             return mMonitoredRailChargeConsumedMaMs;
3177         }
3178     }
3179 
3180     /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */
getRpmTimerLocked(String name)3181     public SamplingTimer getRpmTimerLocked(String name) {
3182         SamplingTimer rpmt = mRpmStats.get(name);
3183         if (rpmt == null) {
3184             rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3185             mRpmStats.put(name, rpmt);
3186         }
3187         return rpmt;
3188     }
3189 
3190     /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */
getScreenOffRpmTimerLocked(String name)3191     public SamplingTimer getScreenOffRpmTimerLocked(String name) {
3192         SamplingTimer rpmt = mScreenOffRpmStats.get(name);
3193         if (rpmt == null) {
3194             rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
3195             mScreenOffRpmStats.put(name, rpmt);
3196         }
3197         return rpmt;
3198     }
3199 
3200     /*
3201      * Get the wakeup reason counter, and create a new one if one
3202      * doesn't already exist.
3203      */
getWakeupReasonTimerLocked(String name)3204     public SamplingTimer getWakeupReasonTimerLocked(String name) {
3205         SamplingTimer timer = mWakeupReasonStats.get(name);
3206         if (timer == null) {
3207             timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3208             mWakeupReasonStats.put(name, timer);
3209         }
3210         return timer;
3211     }
3212 
3213     /*
3214      * Get the KernelWakelockTimer associated with name, and create a new one if one
3215      * doesn't already exist.
3216      */
getKernelWakelockTimerLocked(String name)3217     public SamplingTimer getKernelWakelockTimerLocked(String name) {
3218         SamplingTimer kwlt = mKernelWakelockStats.get(name);
3219         if (kwlt == null) {
3220             kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
3221             mKernelWakelockStats.put(name, kwlt);
3222         }
3223         return kwlt;
3224     }
3225 
getKernelMemoryTimerLocked(long bucket)3226     public SamplingTimer getKernelMemoryTimerLocked(long bucket) {
3227         SamplingTimer kmt = mKernelMemoryStats.get(bucket);
3228         if (kmt == null) {
3229             kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3230             mKernelMemoryStats.put(bucket, kmt);
3231         }
3232         return kmt;
3233     }
3234 
writeHistoryTag(HistoryTag tag)3235     private int writeHistoryTag(HistoryTag tag) {
3236         Integer idxObj = mHistoryTagPool.get(tag);
3237         int idx;
3238         if (idxObj != null) {
3239             idx = idxObj;
3240         } else {
3241             idx = mNextHistoryTagIdx;
3242             HistoryTag key = new HistoryTag();
3243             key.setTo(tag);
3244             tag.poolIdx = idx;
3245             mHistoryTagPool.put(key, idx);
3246             mNextHistoryTagIdx++;
3247             mNumHistoryTagChars += key.string.length() + 1;
3248         }
3249         return idx;
3250     }
3251 
3252     /*
3253         The history delta format uses flags to denote further data in subsequent ints in the parcel.
3254 
3255         There is always the first token, which may contain the delta time, or an indicator of
3256         the length of the time (int or long) following this token.
3257 
3258         First token: always present,
3259         31              23              15               7             0
3260         █M|L|K|J|I|H|G|F█E|D|C|B|A|T|T|T█T|T|T|T|T|T|T|T█T|T|T|T|T|T|T|T█
3261 
3262         T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
3263            follows containing the time, and 0x7ffff indicates a long immediately follows with the
3264            delta time.
3265         A: battery level changed and an int follows with battery data.
3266         B: state changed and an int follows with state change data.
3267         C: state2 has changed and an int follows with state2 change data.
3268         D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
3269         E: event data has changed and an event struct follows.
3270         F: battery charge in coulombs has changed and an int with the charge follows.
3271         G: state flag denoting that the mobile radio was active.
3272         H: state flag denoting that the wifi radio was active.
3273         I: state flag denoting that a wifi scan occurred.
3274         J: state flag denoting that a wifi full lock was held.
3275         K: state flag denoting that the gps was on.
3276         L: state flag denoting that a wakelock was held.
3277         M: state flag denoting that the cpu was running.
3278 
3279         Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
3280         with the time delta.
3281 
3282         Battery level int: if A in the first token is set,
3283         31              23              15               7             0
3284         █L|L|L|L|L|L|L|T█T|T|T|T|T|T|T|T█T|V|V|V|V|V|V|V█V|V|V|V|V|V|V|D█
3285 
3286         D: indicates that extra history details follow.
3287         V: the battery voltage.
3288         T: the battery temperature.
3289         L: the battery level (out of 100).
3290 
3291         State change int: if B in the first token is set,
3292         31              23              15               7             0
3293         █S|S|S|H|H|H|P|P█F|E|D|C|B| | |A█ | | | | | | | █ | | | | | | | █
3294 
3295         A: wifi multicast was on.
3296         B: battery was plugged in.
3297         C: screen was on.
3298         D: phone was scanning for signal.
3299         E: audio was on.
3300         F: a sensor was active.
3301 
3302         State2 change int: if C in the first token is set,
3303         31              23              15               7             0
3304         █M|L|K|J|I|H|H|G█F|E|D|C| | | | █ | | | | | | | █ |B|B|B|A|A|A|A█
3305 
3306         A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
3307         B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
3308         C: a bluetooth scan was active.
3309         D: the camera was active.
3310         E: bluetooth was on.
3311         F: a phone call was active.
3312         G: the device was charging.
3313         H: 2 bits indicating the device-idle (doze) state: off, light, full
3314         I: the flashlight was on.
3315         J: wifi was on.
3316         K: wifi was running.
3317         L: video was playing.
3318         M: power save mode was on.
3319 
3320         Wakelock/wakereason struct: if D in the first token is set,
3321         TODO(adamlesinski): describe wakelock/wakereason struct.
3322 
3323         Event struct: if E in the first token is set,
3324         TODO(adamlesinski): describe the event struct.
3325 
3326         History step details struct: if D in the battery level int is set,
3327         TODO(adamlesinski): describe the history step details struct.
3328 
3329         Battery charge int: if F in the first token is set, an int representing the battery charge
3330         in coulombs follows.
3331      */
3332 
3333     // Part of initial delta int that specifies the time delta.
3334     static final int DELTA_TIME_MASK = 0x7ffff;
3335     static final int DELTA_TIME_LONG = 0x7ffff;   // The delta is a following long
3336     static final int DELTA_TIME_INT = 0x7fffe;    // The delta is a following int
3337     static final int DELTA_TIME_ABS = 0x7fffd;    // Following is an entire abs update.
3338     // Flag in delta int: a new battery level int follows.
3339     static final int DELTA_BATTERY_LEVEL_FLAG               = 0x00080000;
3340     // Flag in delta int: a new full state and battery status int follows.
3341     static final int DELTA_STATE_FLAG                       = 0x00100000;
3342     // Flag in delta int: a new full state2 int follows.
3343     static final int DELTA_STATE2_FLAG                      = 0x00200000;
3344     // Flag in delta int: contains a wakelock or wakeReason tag.
3345     static final int DELTA_WAKELOCK_FLAG                    = 0x00400000;
3346     // Flag in delta int: contains an event description.
3347     static final int DELTA_EVENT_FLAG                       = 0x00800000;
3348     // Flag in delta int: contains the battery charge count in uAh.
3349     static final int DELTA_BATTERY_CHARGE_FLAG              = 0x01000000;
3350     // These upper bits are the frequently changing state bits.
3351     static final int DELTA_STATE_MASK                       = 0xfe000000;
3352 
3353     // These are the pieces of battery state that are packed in to the upper bits of
3354     // the state int that have been packed in to the first delta int.  They must fit
3355     // in STATE_BATTERY_MASK.
3356     static final int STATE_BATTERY_MASK         = 0xff000000;
3357     static final int STATE_BATTERY_STATUS_MASK  = 0x00000007;
3358     static final int STATE_BATTERY_STATUS_SHIFT = 29;
3359     static final int STATE_BATTERY_HEALTH_MASK  = 0x00000007;
3360     static final int STATE_BATTERY_HEALTH_SHIFT = 26;
3361     static final int STATE_BATTERY_PLUG_MASK    = 0x00000003;
3362     static final int STATE_BATTERY_PLUG_SHIFT   = 24;
3363 
3364     // We use the low bit of the battery state int to indicate that we have full details
3365     // from a battery level change.
3366     static final int BATTERY_DELTA_LEVEL_FLAG   = 0x00000001;
3367 
writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last)3368     public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
3369         if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
3370             dest.writeInt(DELTA_TIME_ABS);
3371             cur.writeToParcel(dest, 0);
3372             return;
3373         }
3374 
3375         final long deltaTime = cur.time - last.time;
3376         final int lastBatteryLevelInt = buildBatteryLevelInt(last);
3377         final int lastStateInt = buildStateInt(last);
3378 
3379         int deltaTimeToken;
3380         if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
3381             deltaTimeToken = DELTA_TIME_LONG;
3382         } else if (deltaTime >= DELTA_TIME_ABS) {
3383             deltaTimeToken = DELTA_TIME_INT;
3384         } else {
3385             deltaTimeToken = (int)deltaTime;
3386         }
3387         int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
3388         final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
3389                 ? BATTERY_DELTA_LEVEL_FLAG : 0;
3390         final boolean computeStepDetails = includeStepDetails != 0
3391                 || mLastHistoryStepDetails == null;
3392         final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
3393         final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
3394         if (batteryLevelIntChanged) {
3395             firstToken |= DELTA_BATTERY_LEVEL_FLAG;
3396         }
3397         final int stateInt = buildStateInt(cur);
3398         final boolean stateIntChanged = stateInt != lastStateInt;
3399         if (stateIntChanged) {
3400             firstToken |= DELTA_STATE_FLAG;
3401         }
3402         final boolean state2IntChanged = cur.states2 != last.states2;
3403         if (state2IntChanged) {
3404             firstToken |= DELTA_STATE2_FLAG;
3405         }
3406         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
3407             firstToken |= DELTA_WAKELOCK_FLAG;
3408         }
3409         if (cur.eventCode != HistoryItem.EVENT_NONE) {
3410             firstToken |= DELTA_EVENT_FLAG;
3411         }
3412 
3413         final boolean batteryChargeChanged = cur.batteryChargeUah != last.batteryChargeUah;
3414         if (batteryChargeChanged) {
3415             firstToken |= DELTA_BATTERY_CHARGE_FLAG;
3416         }
3417         dest.writeInt(firstToken);
3418         if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
3419                 + " deltaTime=" + deltaTime);
3420 
3421         if (deltaTimeToken >= DELTA_TIME_INT) {
3422             if (deltaTimeToken == DELTA_TIME_INT) {
3423                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
3424                 dest.writeInt((int)deltaTime);
3425             } else {
3426                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
3427                 dest.writeLong(deltaTime);
3428             }
3429         }
3430         if (batteryLevelIntChanged) {
3431             dest.writeInt(batteryLevelInt);
3432             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
3433                     + Integer.toHexString(batteryLevelInt)
3434                     + " batteryLevel=" + cur.batteryLevel
3435                     + " batteryTemp=" + cur.batteryTemperature
3436                     + " batteryVolt=" + (int)cur.batteryVoltage);
3437         }
3438         if (stateIntChanged) {
3439             dest.writeInt(stateInt);
3440             if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
3441                     + Integer.toHexString(stateInt)
3442                     + " batteryStatus=" + cur.batteryStatus
3443                     + " batteryHealth=" + cur.batteryHealth
3444                     + " batteryPlugType=" + cur.batteryPlugType
3445                     + " states=0x" + Integer.toHexString(cur.states));
3446         }
3447         if (state2IntChanged) {
3448             dest.writeInt(cur.states2);
3449             if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x"
3450                     + Integer.toHexString(cur.states2));
3451         }
3452         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
3453             int wakeLockIndex;
3454             int wakeReasonIndex;
3455             if (cur.wakelockTag != null) {
3456                 wakeLockIndex = writeHistoryTag(cur.wakelockTag);
3457                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
3458                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
3459             } else {
3460                 wakeLockIndex = 0xffff;
3461             }
3462             if (cur.wakeReasonTag != null) {
3463                 wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
3464                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
3465                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
3466             } else {
3467                 wakeReasonIndex = 0xffff;
3468             }
3469             dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
3470         }
3471         if (cur.eventCode != HistoryItem.EVENT_NONE) {
3472             int index = writeHistoryTag(cur.eventTag);
3473             int codeAndIndex = (cur.eventCode&0xffff) | (index<<16);
3474             dest.writeInt(codeAndIndex);
3475             if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
3476                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
3477                     + cur.eventTag.string);
3478         }
3479         if (computeStepDetails) {
3480             if (mPlatformIdleStateCallback != null) {
3481                 mCurHistoryStepDetails.statSubsystemPowerState =
3482                         mPlatformIdleStateCallback.getSubsystemLowPowerStats();
3483                 if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
3484                         mCurHistoryStepDetails.statSubsystemPowerState);
3485 
3486             }
3487             computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
3488             if (includeStepDetails != 0) {
3489                 mCurHistoryStepDetails.writeToParcel(dest);
3490             }
3491             cur.stepDetails = mCurHistoryStepDetails;
3492             mLastHistoryStepDetails = mCurHistoryStepDetails;
3493         } else {
3494             cur.stepDetails = null;
3495         }
3496         if (mLastHistoryStepLevel < cur.batteryLevel) {
3497             mLastHistoryStepDetails = null;
3498         }
3499         mLastHistoryStepLevel = cur.batteryLevel;
3500 
3501         if (batteryChargeChanged) {
3502             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUah=" + cur.batteryChargeUah);
3503             dest.writeInt(cur.batteryChargeUah);
3504         }
3505         dest.writeDouble(cur.modemRailChargeMah);
3506         dest.writeDouble(cur.wifiRailChargeMah);
3507     }
3508 
buildBatteryLevelInt(HistoryItem h)3509     private int buildBatteryLevelInt(HistoryItem h) {
3510         return ((((int)h.batteryLevel)<<25)&0xfe000000)
3511                 | ((((int)h.batteryTemperature)<<15)&0x01ff8000)
3512                 | ((((int)h.batteryVoltage)<<1)&0x00007ffe);
3513     }
3514 
readBatteryLevelInt(int batteryLevelInt, HistoryItem out)3515     private void readBatteryLevelInt(int batteryLevelInt, HistoryItem out) {
3516         out.batteryLevel = (byte)((batteryLevelInt & 0xfe000000) >>> 25);
3517         out.batteryTemperature = (short)((batteryLevelInt & 0x01ff8000) >>> 15);
3518         out.batteryVoltage = (char)((batteryLevelInt & 0x00007ffe) >>> 1);
3519     }
3520 
buildStateInt(HistoryItem h)3521     private int buildStateInt(HistoryItem h) {
3522         int plugType = 0;
3523         if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
3524             plugType = 1;
3525         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
3526             plugType = 2;
3527         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
3528             plugType = 3;
3529         }
3530         return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT)
3531                 | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT)
3532                 | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT)
3533                 | (h.states&(~STATE_BATTERY_MASK));
3534     }
3535 
computeHistoryStepDetails(final HistoryStepDetails out, final HistoryStepDetails last)3536     private void computeHistoryStepDetails(final HistoryStepDetails out,
3537             final HistoryStepDetails last) {
3538         final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
3539 
3540         // Perform a CPU update right after we do this collection, so we have started
3541         // collecting good data for the next step.
3542         requestImmediateCpuUpdate();
3543 
3544         if (last == null) {
3545             // We are not generating a delta, so all we need to do is reset the stats
3546             // we will later be doing a delta from.
3547             final int NU = mUidStats.size();
3548             for (int i=0; i<NU; i++) {
3549                 final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3550                 uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
3551                 uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
3552             }
3553             mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
3554             mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
3555             mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
3556             mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
3557             mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
3558             mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
3559             mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
3560             mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
3561             tmp.clear();
3562             return;
3563         }
3564         if (DEBUG) {
3565             Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTimeMs + " sys="
3566                     + mLastStepStatSystemTimeMs + " io=" + mLastStepStatIOWaitTimeMs
3567                     + " irq=" + mLastStepStatIrqTimeMs + " sirq="
3568                     + mLastStepStatSoftIrqTimeMs + " idle=" + mLastStepStatIdleTimeMs);
3569             Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTimeMs + " sys="
3570                     + mCurStepStatSystemTimeMs + " io=" + mCurStepStatIOWaitTimeMs
3571                     + " irq=" + mCurStepStatIrqTimeMs + " sirq="
3572                     + mCurStepStatSoftIrqTimeMs + " idle=" + mCurStepStatIdleTimeMs);
3573         }
3574         out.userTime = (int) (mCurStepCpuUserTimeMs - mLastStepCpuUserTimeMs);
3575         out.systemTime = (int) (mCurStepCpuSystemTimeMs - mLastStepCpuSystemTimeMs);
3576         out.statUserTime = (int) (mCurStepStatUserTimeMs - mLastStepStatUserTimeMs);
3577         out.statSystemTime = (int) (mCurStepStatSystemTimeMs - mLastStepStatSystemTimeMs);
3578         out.statIOWaitTime = (int) (mCurStepStatIOWaitTimeMs - mLastStepStatIOWaitTimeMs);
3579         out.statIrqTime = (int) (mCurStepStatIrqTimeMs - mLastStepStatIrqTimeMs);
3580         out.statSoftIrqTime = (int) (mCurStepStatSoftIrqTimeMs - mLastStepStatSoftIrqTimeMs);
3581         out.statIdlTime = (int) (mCurStepStatIdleTimeMs - mLastStepStatIdleTimeMs);
3582         out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
3583         out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
3584         out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
3585         final int NU = mUidStats.size();
3586         for (int i=0; i<NU; i++) {
3587             final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3588             final int totalUTimeMs = (int) (uid.mCurStepUserTimeMs - uid.mLastStepUserTimeMs);
3589             final int totalSTimeMs = (int) (uid.mCurStepSystemTimeMs - uid.mLastStepSystemTimeMs);
3590             final int totalTimeMs = totalUTimeMs + totalSTimeMs;
3591             uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
3592             uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
3593             if (totalTimeMs <= (out.appCpuUTime3 + out.appCpuSTime3)) {
3594                 continue;
3595             }
3596             if (totalTimeMs <= (out.appCpuUTime2 + out.appCpuSTime2)) {
3597                 out.appCpuUid3 = uid.mUid;
3598                 out.appCpuUTime3 = totalUTimeMs;
3599                 out.appCpuSTime3 = totalSTimeMs;
3600             } else {
3601                 out.appCpuUid3 = out.appCpuUid2;
3602                 out.appCpuUTime3 = out.appCpuUTime2;
3603                 out.appCpuSTime3 = out.appCpuSTime2;
3604                 if (totalTimeMs <= (out.appCpuUTime1 + out.appCpuSTime1)) {
3605                     out.appCpuUid2 = uid.mUid;
3606                     out.appCpuUTime2 = totalUTimeMs;
3607                     out.appCpuSTime2 = totalSTimeMs;
3608                 } else {
3609                     out.appCpuUid2 = out.appCpuUid1;
3610                     out.appCpuUTime2 = out.appCpuUTime1;
3611                     out.appCpuSTime2 = out.appCpuSTime1;
3612                     out.appCpuUid1 = uid.mUid;
3613                     out.appCpuUTime1 = totalUTimeMs;
3614                     out.appCpuSTime1 = totalSTimeMs;
3615                 }
3616             }
3617         }
3618         mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
3619         mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
3620         mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
3621         mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
3622         mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
3623         mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
3624         mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
3625         mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
3626     }
3627 
3628     @Override
commitCurrentHistoryBatchLocked()3629     public void commitCurrentHistoryBatchLocked() {
3630         mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
3631     }
3632 
createFakeHistoryEvents(long numEvents)3633     public void createFakeHistoryEvents(long numEvents) {
3634         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
3635         final long uptimeMs = mClocks.uptimeMillis();
3636         for(long i = 0; i < numEvents; i++) {
3637             noteLongPartialWakelockStart("name1", "historyName1", 1000,
3638                     elapsedRealtimeMs, uptimeMs);
3639             noteLongPartialWakelockFinish("name1", "historyName1", 1000,
3640                     elapsedRealtimeMs, uptimeMs);
3641         }
3642     }
3643 
addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur)3644     void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
3645         if (!mHaveBatteryLevel || !mRecordingHistory) {
3646             return;
3647         }
3648 
3649         final long timeDiffMs = (mHistoryBaseTimeMs + elapsedRealtimeMs) - mHistoryLastWritten.time;
3650         final int diffStates = mHistoryLastWritten.states^(cur.states&mActiveHistoryStates);
3651         final int diffStates2 = mHistoryLastWritten.states2^(cur.states2&mActiveHistoryStates2);
3652         final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
3653         final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
3654         if (DEBUG) {
3655             Slog.i(TAG, "ADD: tdelta=" + timeDiffMs + " diff="
3656                     + Integer.toHexString(diffStates) + " lastDiff="
3657                     + Integer.toHexString(lastDiffStates) + " diff2="
3658                     + Integer.toHexString(diffStates2) + " lastDiff2="
3659                     + Integer.toHexString(lastDiffStates2));
3660         }
3661         if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
3662                 && timeDiffMs < 1000 && (diffStates & lastDiffStates) == 0
3663                 && (diffStates2&lastDiffStates2) == 0
3664                 && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
3665                 && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
3666                 && mHistoryLastWritten.stepDetails == null
3667                 && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
3668                         || cur.eventCode == HistoryItem.EVENT_NONE)
3669                 && mHistoryLastWritten.batteryLevel == cur.batteryLevel
3670                 && mHistoryLastWritten.batteryStatus == cur.batteryStatus
3671                 && mHistoryLastWritten.batteryHealth == cur.batteryHealth
3672                 && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
3673                 && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
3674                 && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
3675             // We can merge this new change in with the last one.  Merging is
3676             // allowed as long as only the states have changed, and within those states
3677             // as long as no bit has changed both between now and the last entry, as
3678             // well as the last entry and the one before it (so we capture any toggles).
3679             if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
3680             mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
3681             mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
3682             mHistoryBufferLastPos = -1;
3683             elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTimeMs;
3684             // If the last written history had a wakelock tag, we need to retain it.
3685             // Note that the condition above made sure that we aren't in a case where
3686             // both it and the current history item have a wakelock tag.
3687             if (mHistoryLastWritten.wakelockTag != null) {
3688                 cur.wakelockTag = cur.localWakelockTag;
3689                 cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
3690             }
3691             // If the last written history had a wake reason tag, we need to retain it.
3692             // Note that the condition above made sure that we aren't in a case where
3693             // both it and the current history item have a wakelock tag.
3694             if (mHistoryLastWritten.wakeReasonTag != null) {
3695                 cur.wakeReasonTag = cur.localWakeReasonTag;
3696                 cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
3697             }
3698             // If the last written history had an event, we need to retain it.
3699             // Note that the condition above made sure that we aren't in a case where
3700             // both it and the current history item have an event.
3701             if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
3702                 cur.eventCode = mHistoryLastWritten.eventCode;
3703                 cur.eventTag = cur.localEventTag;
3704                 cur.eventTag.setTo(mHistoryLastWritten.eventTag);
3705             }
3706             mHistoryLastWritten.setTo(mHistoryLastLastWritten);
3707         }
3708         final int dataSize = mHistoryBuffer.dataSize();
3709 
3710         if (dataSize >= mConstants.MAX_HISTORY_BUFFER) {
3711             //open a new history file.
3712             final long start = SystemClock.uptimeMillis();
3713             writeHistoryLocked(true);
3714             if (DEBUG) {
3715                 Slog.d(TAG, "addHistoryBufferLocked writeHistoryLocked takes ms:"
3716                         + (SystemClock.uptimeMillis() - start));
3717             }
3718             mBatteryStatsHistory.startNextFile();
3719             mHistoryBuffer.setDataSize(0);
3720             mHistoryBuffer.setDataPosition(0);
3721             mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
3722             mHistoryBufferLastPos = -1;
3723             HistoryItem newItem = new HistoryItem();
3724             newItem.setTo(cur);
3725             startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
3726             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, newItem);
3727             return;
3728         }
3729 
3730         if (dataSize == 0) {
3731             // The history is currently empty; we need it to start with a time stamp.
3732             cur.currentTime = mClocks.currentTimeMillis();
3733             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
3734         }
3735         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3736     }
3737 
addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur)3738     private void addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur) {
3739         if (mBatteryStatsHistoryIterator != null) {
3740             throw new IllegalStateException("Can't do this while iterating history!");
3741         }
3742         mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
3743         mHistoryLastLastWritten.setTo(mHistoryLastWritten);
3744         mHistoryLastWritten.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur);
3745         mHistoryLastWritten.states &= mActiveHistoryStates;
3746         mHistoryLastWritten.states2 &= mActiveHistoryStates2;
3747         writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
3748         mLastHistoryElapsedRealtimeMs = elapsedRealtimeMs;
3749         cur.wakelockTag = null;
3750         cur.wakeReasonTag = null;
3751         cur.eventCode = HistoryItem.EVENT_NONE;
3752         cur.eventTag = null;
3753         if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
3754                 + " now " + mHistoryBuffer.dataPosition()
3755                 + " size is now " + mHistoryBuffer.dataSize());
3756     }
3757 
3758     int mChangedStates = 0;
3759     int mChangedStates2 = 0;
3760 
addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs)3761     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
3762         if (mTrackRunningHistoryElapsedRealtimeMs != 0) {
3763             final long diffElapsedMs = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtimeMs;
3764             final long diffUptimeMs = uptimeMs - mTrackRunningHistoryUptimeMs;
3765             if (diffUptimeMs < (diffElapsedMs - 20)) {
3766                 final long wakeElapsedTimeMs = elapsedRealtimeMs - (diffElapsedMs - diffUptimeMs);
3767                 mHistoryAddTmp.setTo(mHistoryLastWritten);
3768                 mHistoryAddTmp.wakelockTag = null;
3769                 mHistoryAddTmp.wakeReasonTag = null;
3770                 mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
3771                 mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
3772                 addHistoryRecordInnerLocked(wakeElapsedTimeMs, uptimeMs, mHistoryAddTmp);
3773             }
3774         }
3775         mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
3776         mTrackRunningHistoryElapsedRealtimeMs = elapsedRealtimeMs;
3777         mTrackRunningHistoryUptimeMs = uptimeMs;
3778         addHistoryRecordInnerLocked(elapsedRealtimeMs, uptimeMs, mHistoryCur);
3779     }
3780 
addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur)3781     void addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
3782         addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, cur);
3783     }
3784 
addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code, String name, int uid)3785     public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
3786             String name, int uid) {
3787         mHistoryCur.eventCode = code;
3788         mHistoryCur.eventTag = mHistoryCur.localEventTag;
3789         mHistoryCur.eventTag.string = name;
3790         mHistoryCur.eventTag.uid = uid;
3791         addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
3792     }
3793 
addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur)3794     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) {
3795         HistoryItem rec = mHistoryCache;
3796         if (rec != null) {
3797             mHistoryCache = rec.next;
3798         } else {
3799             rec = new HistoryItem();
3800         }
3801         rec.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur);
3802 
3803         addHistoryRecordLocked(rec);
3804     }
3805 
addHistoryRecordLocked(HistoryItem rec)3806     void addHistoryRecordLocked(HistoryItem rec) {
3807         mNumHistoryItems++;
3808         rec.next = null;
3809         mHistoryLastEnd = mHistoryEnd;
3810         if (mHistoryEnd != null) {
3811             mHistoryEnd.next = rec;
3812             mHistoryEnd = rec;
3813         } else {
3814             mHistory = mHistoryEnd = rec;
3815         }
3816     }
3817 
clearHistoryLocked()3818     void clearHistoryLocked() {
3819         if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
3820         mHistoryBaseTimeMs = 0;
3821         mLastHistoryElapsedRealtimeMs = 0;
3822         mTrackRunningHistoryElapsedRealtimeMs = 0;
3823         mTrackRunningHistoryUptimeMs = 0;
3824 
3825         mHistoryBuffer.setDataSize(0);
3826         mHistoryBuffer.setDataPosition(0);
3827         mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
3828         mHistoryLastLastWritten.clear();
3829         mHistoryLastWritten.clear();
3830         mHistoryTagPool.clear();
3831         mNextHistoryTagIdx = 0;
3832         mNumHistoryTagChars = 0;
3833         mHistoryBufferLastPos = -1;
3834         mActiveHistoryStates = 0xffffffff;
3835         mActiveHistoryStates2 = 0xffffffff;
3836     }
3837 
3838     @GuardedBy("this")
updateTimeBasesLocked(boolean unplugged, int screenState, long uptimeUs, long realtimeUs)3839     public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptimeUs,
3840             long realtimeUs) {
3841         final boolean screenOff = !Display.isOnState(screenState);
3842         final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
3843         final boolean updateOnBatteryScreenOffTimeBase =
3844                 (unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
3845 
3846         if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) {
3847             if (updateOnBatteryScreenOffTimeBase) {
3848                 updateKernelWakelocksLocked(realtimeUs);
3849                 updateBatteryPropertiesLocked();
3850             }
3851             // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
3852             // updateRpmStatsLocked is too slow to run each screen change. When the speed is
3853             // improved, remove the surrounding if{}.
3854             if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
3855                 // if either OnBattery or OnBatteryScreenOfftimebase changes.
3856                 updateRpmStatsLocked(realtimeUs);
3857             }
3858             if (DEBUG_ENERGY_CPU) {
3859                 Slog.d(TAG, "Updating cpu time because screen is now "
3860                         + Display.stateToString(screenState)
3861                         + " and battery is " + (unplugged ? "on" : "off"));
3862             }
3863 
3864             mOnBatteryTimeBase.setRunning(unplugged, uptimeUs, realtimeUs);
3865             if (updateOnBatteryTimeBase) {
3866                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
3867                     mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptimeUs, realtimeUs);
3868                 }
3869             }
3870             if (updateOnBatteryScreenOffTimeBase) {
3871                 mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff,
3872                         uptimeUs, realtimeUs);
3873                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
3874                     mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptimeUs, realtimeUs);
3875                 }
3876             }
3877         }
3878     }
3879 
updateBatteryPropertiesLocked()3880     private void updateBatteryPropertiesLocked() {
3881         try {
3882             IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
3883                     ServiceManager.getService("batteryproperties"));
3884             if (registrar != null) {
3885                 registrar.scheduleUpdate();
3886             }
3887         } catch (RemoteException e) {
3888             // Ignore.
3889         }
3890     }
3891 
addIsolatedUidLocked(int isolatedUid, int appUid)3892     public void addIsolatedUidLocked(int isolatedUid, int appUid) {
3893         addIsolatedUidLocked(isolatedUid, appUid,
3894                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
3895     }
3896 
addIsolatedUidLocked(int isolatedUid, int appUid, long elapsedRealtimeMs, long uptimeMs)3897     public void addIsolatedUidLocked(int isolatedUid, int appUid,
3898             long elapsedRealtimeMs, long uptimeMs) {
3899         mIsolatedUids.put(isolatedUid, appUid);
3900         final Uid u = getUidStatsLocked(appUid, elapsedRealtimeMs, uptimeMs);
3901         u.addIsolatedUid(isolatedUid);
3902     }
3903 
3904     /**
3905      * Schedules a read of the latest cpu times before removing the isolated UID.
3906      * @see #removeIsolatedUidLocked(int, int, int)
3907      */
scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid)3908     public void scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid) {
3909         int curUid = mIsolatedUids.get(isolatedUid, -1);
3910         if (curUid == appUid) {
3911             if (mExternalSync != null) {
3912                 mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
3913             }
3914         }
3915     }
3916 
3917     /**
3918      * This should only be called after the cpu times have been read.
3919      * @see #scheduleRemoveIsolatedUidLocked(int, int)
3920      */
3921     @GuardedBy("this")
removeIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs, long uptimeMs)3922     public void removeIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs, long uptimeMs) {
3923         final int idx = mIsolatedUids.indexOfKey(isolatedUid);
3924         if (idx >= 0) {
3925             final int ownerUid = mIsolatedUids.valueAt(idx);
3926             final Uid u = getUidStatsLocked(ownerUid, elapsedRealtimeMs, uptimeMs);
3927             u.removeIsolatedUid(isolatedUid);
3928             mIsolatedUids.removeAt(idx);
3929         }
3930         mPendingRemovedUids.add(new UidToRemove(isolatedUid, elapsedRealtimeMs));
3931     }
3932 
mapUid(int uid)3933     public int mapUid(int uid) {
3934         int isolated = mIsolatedUids.get(uid, -1);
3935         return isolated > 0 ? isolated : uid;
3936     }
3937 
noteEventLocked(int code, String name, int uid)3938     public void noteEventLocked(int code, String name, int uid) {
3939         noteEventLocked(code, name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
3940     }
3941 
noteEventLocked(int code, String name, int uid, long elapsedRealtimeMs, long uptimeMs)3942     public void noteEventLocked(int code, String name, int uid,
3943             long elapsedRealtimeMs, long uptimeMs) {
3944         uid = mapUid(uid);
3945         if (!mActiveEvents.updateState(code, name, uid, 0)) {
3946             return;
3947         }
3948         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, code, name, uid);
3949     }
3950 
noteCurrentTimeChangedLocked()3951     public void noteCurrentTimeChangedLocked() {
3952         final long currentTime = mClocks.currentTimeMillis();
3953         final long elapsedRealtime = mClocks.elapsedRealtime();
3954         final long uptime = mClocks.uptimeMillis();
3955         noteCurrentTimeChangedLocked(currentTime, elapsedRealtime, uptime);
3956     }
3957 
noteCurrentTimeChangedLocked(long currentTimeMs, long elapsedRealtimeMs, long uptimeMs)3958     public void noteCurrentTimeChangedLocked(long currentTimeMs,
3959             long elapsedRealtimeMs, long uptimeMs) {
3960         recordCurrentTimeChangeLocked(currentTimeMs, elapsedRealtimeMs, uptimeMs);
3961     }
3962 
noteProcessStartLocked(String name, int uid)3963     public void noteProcessStartLocked(String name, int uid) {
3964         noteProcessStartLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
3965     }
3966 
noteProcessStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)3967     public void noteProcessStartLocked(String name, int uid,
3968             long elapsedRealtimeMs, long uptimeMs) {
3969         uid = mapUid(uid);
3970         if (isOnBattery()) {
3971             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
3972             u.getProcessStatsLocked(name).incStartsLocked();
3973         }
3974         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
3975             return;
3976         }
3977         if (!mRecordAllHistory) {
3978             return;
3979         }
3980         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid);
3981     }
3982 
noteProcessCrashLocked(String name, int uid)3983     public void noteProcessCrashLocked(String name, int uid) {
3984         noteProcessCrashLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
3985     }
3986 
noteProcessCrashLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)3987     public void noteProcessCrashLocked(String name, int uid,
3988             long elapsedRealtimeMs, long uptimeMs) {
3989         uid = mapUid(uid);
3990         if (isOnBattery()) {
3991             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
3992             u.getProcessStatsLocked(name).incNumCrashesLocked();
3993         }
3994     }
3995 
noteProcessAnrLocked(String name, int uid)3996     public void noteProcessAnrLocked(String name, int uid) {
3997         noteProcessAnrLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
3998     }
3999 
noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4000     public void noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4001         uid = mapUid(uid);
4002         if (isOnBattery()) {
4003             Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
4004             u.getProcessStatsLocked(name).incNumAnrsLocked();
4005         }
4006     }
4007 
noteUidProcessStateLocked(int uid, int state)4008     public void noteUidProcessStateLocked(int uid, int state) {
4009         noteUidProcessStateLocked(uid, state, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4010     }
4011 
noteUidProcessStateLocked(int uid, int state, long elapsedRealtimeMs, long uptimeMs)4012     public void noteUidProcessStateLocked(int uid, int state,
4013             long elapsedRealtimeMs, long uptimeMs) {
4014         int parentUid = mapUid(uid);
4015         if (uid != parentUid) {
4016             // Isolated UIDs process state is already rolled up into parent, so no need to track
4017             // Otherwise the parent's process state will get downgraded incorrectly
4018             return;
4019         }
4020         // TODO(b/155216561): It is possible for isolated uids to be in a higher
4021         // state than its parent uid. We should track the highest state within the union of host
4022         // and isolated uids rather than only the parent uid.
4023         FrameworkStatsLog.write(FrameworkStatsLog.UID_PROCESS_STATE_CHANGED, uid,
4024                 ActivityManager.processStateAmToProto(state));
4025         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4026                 .updateUidProcessStateLocked(state, elapsedRealtimeMs, uptimeMs);
4027     }
4028 
noteProcessFinishLocked(String name, int uid)4029     public void noteProcessFinishLocked(String name, int uid) {
4030         noteProcessFinishLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4031     }
4032 
noteProcessFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4033     public void noteProcessFinishLocked(String name, int uid,
4034             long elapsedRealtimeMs, long uptimeMs) {
4035         uid = mapUid(uid);
4036         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
4037             return;
4038         }
4039         if (!mRecordAllHistory) {
4040             return;
4041         }
4042         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH,
4043                 name, uid);
4044     }
4045 
noteSyncStartLocked(String name, int uid)4046     public void noteSyncStartLocked(String name, int uid) {
4047         noteSyncStartLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4048     }
4049 
noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4050     public void noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4051         uid = mapUid(uid);
4052         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4053                 .noteStartSyncLocked(name, elapsedRealtimeMs);
4054         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
4055             return;
4056         }
4057         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid);
4058     }
4059 
noteSyncFinishLocked(String name, int uid)4060     public void noteSyncFinishLocked(String name, int uid) {
4061         noteSyncFinishLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4062     }
4063 
noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4064     public void noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4065         uid = mapUid(uid);
4066         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4067                 .noteStopSyncLocked(name, elapsedRealtimeMs);
4068         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
4069             return;
4070         }
4071         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH,
4072                 name, uid);
4073     }
4074 
noteJobStartLocked(String name, int uid)4075     public void noteJobStartLocked(String name, int uid) {
4076         noteJobStartLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4077     }
4078 
noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs)4079     public void noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) {
4080         uid = mapUid(uid);
4081         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4082                 .noteStartJobLocked(name, elapsedRealtimeMs);
4083         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
4084             return;
4085         }
4086         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid);
4087     }
4088 
noteJobFinishLocked(String name, int uid, int stopReason)4089     public void noteJobFinishLocked(String name, int uid, int stopReason) {
4090         noteJobFinishLocked(name, uid, stopReason,
4091                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4092     }
4093 
noteJobFinishLocked(String name, int uid, int stopReason, long elapsedRealtimeMs, long uptimeMs)4094     public void noteJobFinishLocked(String name, int uid, int stopReason,
4095             long elapsedRealtimeMs, long uptimeMs) {
4096         uid = mapUid(uid);
4097         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4098                 .noteStopJobLocked(name, elapsedRealtimeMs, stopReason);
4099         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
4100             return;
4101         }
4102         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid);
4103     }
4104 
noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast)4105     public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast) {
4106         noteJobsDeferredLocked(uid, numDeferred, sinceLast,
4107                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4108     }
4109 
noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast, long elapsedRealtimeMs, long uptimeMs)4110     public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast,
4111             long elapsedRealtimeMs, long uptimeMs) {
4112         uid = mapUid(uid);
4113         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4114                 .noteJobsDeferredLocked(numDeferred, sinceLast);
4115     }
4116 
noteAlarmStartLocked(String name, WorkSource workSource, int uid)4117     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
4118         noteAlarmStartLocked(name, workSource, uid,
4119                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4120     }
4121 
noteAlarmStartLocked(String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4122     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid,
4123             long elapsedRealtimeMs, long uptimeMs) {
4124         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid,
4125                 elapsedRealtimeMs, uptimeMs);
4126     }
4127 
noteAlarmFinishLocked(String name, WorkSource workSource, int uid)4128     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
4129         noteAlarmFinishLocked(name, workSource, uid,
4130                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4131     }
4132 
noteAlarmFinishLocked(String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4133     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid,
4134             long elapsedRealtimeMs, long uptimeMs) {
4135         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid,
4136                 elapsedRealtimeMs, uptimeMs);
4137     }
4138 
noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, int uid)4139     private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
4140             int uid) {
4141         noteAlarmStartOrFinishLocked(historyItem, name, workSource, uid,
4142                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4143     }
4144 
noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs)4145     private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
4146             int uid, long elapsedRealtimeMs, long uptimeMs) {
4147         if (!mRecordAllHistory) {
4148             return;
4149         }
4150 
4151         if (workSource != null) {
4152             for (int i = 0; i < workSource.size(); ++i) {
4153                 uid = mapUid(workSource.getUid(i));
4154                 if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4155                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4156                 }
4157             }
4158 
4159             List<WorkChain> workChains = workSource.getWorkChains();
4160             if (workChains != null) {
4161                 for (int i = 0; i < workChains.size(); ++i) {
4162                     uid = mapUid(workChains.get(i).getAttributionUid());
4163                     if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4164                         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4165                     }
4166                 }
4167             }
4168         } else {
4169             uid = mapUid(uid);
4170 
4171             if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4172                 addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
4173             }
4174         }
4175     }
4176 
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag)4177     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4178             String tag) {
4179         noteWakupAlarmLocked(packageName, uid, workSource, tag,
4180                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4181     }
4182 
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag, long elapsedRealtimeMs, long uptimeMs)4183     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4184             String tag, long elapsedRealtimeMs, long uptimeMs) {
4185         if (workSource != null) {
4186             for (int i = 0; i < workSource.size(); ++i) {
4187                 uid = workSource.getUid(i);
4188                 final String workSourceName = workSource.getPackageName(i);
4189 
4190                 if (isOnBattery()) {
4191                     BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
4192                             workSourceName != null ? workSourceName : packageName,
4193                             elapsedRealtimeMs, uptimeMs);
4194                     pkg.noteWakeupAlarmLocked(tag);
4195                 }
4196             }
4197 
4198             List<WorkChain> workChains = workSource.getWorkChains();
4199             if (workChains != null) {
4200                 for (int i = 0; i < workChains.size(); ++i) {
4201                     final WorkChain wc = workChains.get(i);
4202                     uid = wc.getAttributionUid();
4203 
4204                     if (isOnBattery()) {
4205                         BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName,
4206                                 elapsedRealtimeMs, uptimeMs);
4207                         pkg.noteWakeupAlarmLocked(tag);
4208                     }
4209                 }
4210             }
4211         } else {
4212             if (isOnBattery()) {
4213                 BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName,
4214                         elapsedRealtimeMs, uptimeMs);
4215                 pkg.noteWakeupAlarmLocked(tag);
4216             }
4217         }
4218     }
4219 
requestWakelockCpuUpdate()4220     private void requestWakelockCpuUpdate() {
4221         mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS);
4222     }
4223 
requestImmediateCpuUpdate()4224     private void requestImmediateCpuUpdate() {
4225         mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
4226     }
4227 
setRecordAllHistoryLocked(boolean enabled)4228     public void setRecordAllHistoryLocked(boolean enabled) {
4229         mRecordAllHistory = enabled;
4230         if (!enabled) {
4231             // Clear out any existing state.
4232             mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
4233             mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
4234             // Record the currently running processes as stopping, now that we are no
4235             // longer tracking them.
4236             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4237                     HistoryItem.EVENT_PROC);
4238             if (active != null) {
4239                 long mSecRealtime = mClocks.elapsedRealtime();
4240                 final long mSecUptime = mClocks.uptimeMillis();
4241                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4242                     SparseIntArray uids = ent.getValue();
4243                     for (int j=0; j<uids.size(); j++) {
4244                         addHistoryEventLocked(mSecRealtime, mSecUptime,
4245                                 HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
4246                     }
4247                 }
4248             }
4249         } else {
4250             // Record the currently running processes as starting, now that we are tracking them.
4251             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4252                     HistoryItem.EVENT_PROC);
4253             if (active != null) {
4254                 long mSecRealtime = mClocks.elapsedRealtime();
4255                 final long mSecUptime = mClocks.uptimeMillis();
4256                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4257                     SparseIntArray uids = ent.getValue();
4258                     for (int j=0; j<uids.size(); j++) {
4259                         addHistoryEventLocked(mSecRealtime, mSecUptime,
4260                                 HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
4261                     }
4262                 }
4263             }
4264         }
4265     }
4266 
setNoAutoReset(boolean enabled)4267     public void setNoAutoReset(boolean enabled) {
4268         mNoAutoReset = enabled;
4269     }
4270 
setPretendScreenOff(boolean pretendScreenOff)4271     public void setPretendScreenOff(boolean pretendScreenOff) {
4272         if (mPretendScreenOff != pretendScreenOff) {
4273             mPretendScreenOff = pretendScreenOff;
4274             noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON,
4275                     mClocks.elapsedRealtime(), mClocks.uptimeMillis(), mClocks.currentTimeMillis());
4276         }
4277     }
4278 
4279     private String mInitialAcquireWakeName;
4280     private int mInitialAcquireWakeUid = -1;
4281 
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging)4282     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4283             int type, boolean unimportantForLogging) {
4284         noteStartWakeLocked(uid, pid, wc, name, historyName, type, unimportantForLogging,
4285                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4286     }
4287 
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs)4288     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4289             int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs) {
4290         uid = mapUid(uid);
4291         if (type == WAKE_TYPE_PARTIAL) {
4292             // Only care about partial wake locks, since full wake locks
4293             // will be canceled when the user puts the screen to sleep.
4294             aggregateLastWakeupUptimeLocked(elapsedRealtimeMs, uptimeMs);
4295             if (historyName == null) {
4296                 historyName = name;
4297             }
4298             if (mRecordAllHistory) {
4299                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
4300                         uid, 0)) {
4301                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
4302                             HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
4303                 }
4304             }
4305             if (mWakeLockNesting == 0) {
4306                 mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
4307                 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
4308                         + Integer.toHexString(mHistoryCur.states));
4309                 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
4310                 mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
4311                 mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
4312                 mWakeLockImportant = !unimportantForLogging;
4313                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4314             } else if (!mWakeLockImportant && !unimportantForLogging
4315                     && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
4316                 if (mHistoryLastWritten.wakelockTag != null) {
4317                     // We'll try to update the last tag.
4318                     mHistoryLastWritten.wakelockTag = null;
4319                     mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
4320                     mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
4321                     mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
4322                     addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4323                 }
4324                 mWakeLockImportant = true;
4325             }
4326             mWakeLockNesting++;
4327         }
4328         if (uid >= 0) {
4329             if (mOnBatteryScreenOffTimeBase.isRunning()) {
4330                 // We only update the cpu time when a wake lock is acquired if the screen is off.
4331                 // If the screen is on, we don't distribute the power amongst partial wakelocks.
4332                 if (DEBUG_ENERGY_CPU) {
4333                     Slog.d(TAG, "Updating cpu time because of +wake_lock");
4334                 }
4335                 requestWakelockCpuUpdate();
4336             }
4337 
4338             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4339                     .noteStartWakeLocked(pid, name, type, elapsedRealtimeMs);
4340 
4341             if (wc != null) {
4342                 FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(),
4343                         wc.getTags(), getPowerManagerWakeLockLevel(type), name,
4344                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
4345             } else {
4346                 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, uid,
4347                         null, getPowerManagerWakeLockLevel(type), name,
4348                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
4349             }
4350         }
4351     }
4352 
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type)4353     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4354             int type) {
4355         noteStopWakeLocked(uid, pid, wc, name, historyName, type,
4356                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4357     }
4358 
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs)4359     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4360             int type, long elapsedRealtimeMs, long uptimeMs) {
4361         uid = mapUid(uid);
4362         if (type == WAKE_TYPE_PARTIAL) {
4363             mWakeLockNesting--;
4364             if (mRecordAllHistory) {
4365                 if (historyName == null) {
4366                     historyName = name;
4367                 }
4368                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
4369                         uid, 0)) {
4370                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
4371                             HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
4372                 }
4373             }
4374             if (mWakeLockNesting == 0) {
4375                 mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
4376                 if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
4377                         + Integer.toHexString(mHistoryCur.states));
4378                 mInitialAcquireWakeName = null;
4379                 mInitialAcquireWakeUid = -1;
4380                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4381             }
4382         }
4383         if (uid >= 0) {
4384             if (mOnBatteryScreenOffTimeBase.isRunning()) {
4385                 if (DEBUG_ENERGY_CPU) {
4386                     Slog.d(TAG, "Updating cpu time because of -wake_lock");
4387                 }
4388                 requestWakelockCpuUpdate();
4389             }
4390 
4391             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4392                     .noteStopWakeLocked(pid, name, type, elapsedRealtimeMs);
4393             if (wc != null) {
4394                 FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(),
4395                         wc.getTags(), getPowerManagerWakeLockLevel(type), name,
4396                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
4397             } else {
4398                 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, uid,
4399                         null, getPowerManagerWakeLockLevel(type), name,
4400                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
4401             }
4402         }
4403     }
4404 
4405     /**
4406      * Converts BatteryStats wakelock types back into PowerManager wakelock levels.
4407      * This is the inverse map of Notifier.getBatteryStatsWakeLockMonitorType().
4408      * These are estimations, since batterystats loses some of the original data.
4409      * TODO: Delete this. Instead, FrameworkStatsLog.write should be called from
4410      * PowerManager's Notifier.
4411      */
getPowerManagerWakeLockLevel(int battertStatsWakelockType)4412     private int getPowerManagerWakeLockLevel(int battertStatsWakelockType) {
4413         switch (battertStatsWakelockType) {
4414             // PowerManager.PARTIAL_WAKE_LOCK or PROXIMITY_SCREEN_OFF_WAKE_LOCK
4415             case BatteryStats.WAKE_TYPE_PARTIAL:
4416                 return PowerManager.PARTIAL_WAKE_LOCK;
4417 
4418             // PowerManager.SCREEN_DIM_WAKE_LOCK or SCREEN_BRIGHT_WAKE_LOCK
4419             case BatteryStats.WAKE_TYPE_FULL:
4420                 return PowerManager.FULL_WAKE_LOCK;
4421 
4422             case BatteryStats.WAKE_TYPE_DRAW:
4423                 return PowerManager.DRAW_WAKE_LOCK;
4424 
4425             // It appears that nothing can ever make a Window and PowerManager lacks an equivalent.
4426             case BatteryStats.WAKE_TYPE_WINDOW:
4427                 Slog.e(TAG, "Illegal window wakelock type observed in batterystats.");
4428                 return -1;
4429 
4430             default:
4431                 Slog.e(TAG, "Illegal wakelock type in batterystats: " + battertStatsWakelockType);
4432                 return -1;
4433         }
4434     }
4435 
noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging)4436     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
4437             String historyName, int type, boolean unimportantForLogging) {
4438         noteStartWakeFromSourceLocked(ws, pid, name, historyName, type, unimportantForLogging,
4439                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4440     }
4441 
noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs)4442     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
4443             String historyName, int type, boolean unimportantForLogging,
4444             long elapsedRealtimeMs, long uptimeMs) {
4445         final int N = ws.size();
4446         for (int i=0; i<N; i++) {
4447             noteStartWakeLocked(ws.getUid(i), pid, null, name, historyName, type,
4448                     unimportantForLogging, elapsedRealtimeMs, uptimeMs);
4449         }
4450 
4451         List<WorkChain> wcs = ws.getWorkChains();
4452         if (wcs != null) {
4453             for (int i = 0; i < wcs.size(); ++i) {
4454                 final WorkChain wc = wcs.get(i);
4455                 noteStartWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4456                         unimportantForLogging, elapsedRealtimeMs, uptimeMs);
4457             }
4458         }
4459     }
4460 
noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, WorkSource newWs, int newPid, String newName, String newHistoryName, int newType, boolean newUnimportantForLogging)4461     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
4462             String historyName, int type, WorkSource newWs, int newPid, String newName,
4463             String newHistoryName, int newType, boolean newUnimportantForLogging) {
4464         noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type, newWs, newPid,
4465                 newName, newHistoryName, newType, newUnimportantForLogging,
4466                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4467     }
4468 
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)4469     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
4470             String historyName, int type, WorkSource newWs, int newPid, String newName,
4471             String newHistoryName, int newType, boolean newUnimportantForLogging,
4472             long elapsedRealtimeMs, long uptimeMs) {
4473         List<WorkChain>[] wcs = WorkSource.diffChains(ws, newWs);
4474 
4475         // For correct semantics, we start the need worksources first, so that we won't
4476         // make inappropriate history items as if all wake locks went away and new ones
4477         // appeared.  This is okay because tracking of wake locks allows nesting.
4478         //
4479         // First the starts :
4480         final int NN = newWs.size();
4481         for (int i=0; i<NN; i++) {
4482             noteStartWakeLocked(newWs.getUid(i), newPid, null, newName, newHistoryName, newType,
4483                     newUnimportantForLogging, elapsedRealtimeMs, uptimeMs);
4484         }
4485         if (wcs != null) {
4486             List<WorkChain> newChains = wcs[0];
4487             if (newChains != null) {
4488                 for (int i = 0; i < newChains.size(); ++i) {
4489                     final WorkChain newChain = newChains.get(i);
4490                     noteStartWakeLocked(newChain.getAttributionUid(), newPid, newChain, newName,
4491                             newHistoryName, newType, newUnimportantForLogging, elapsedRealtimeMs,
4492                             uptimeMs);
4493                 }
4494             }
4495         }
4496 
4497         // Then the stops :
4498         final int NO = ws.size();
4499         for (int i=0; i<NO; i++) {
4500             noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs,
4501                     uptimeMs);
4502         }
4503         if (wcs != null) {
4504             List<WorkChain> goneChains = wcs[1];
4505             if (goneChains != null) {
4506                 for (int i = 0; i < goneChains.size(); ++i) {
4507                     final WorkChain goneChain = goneChains.get(i);
4508                     noteStopWakeLocked(goneChain.getAttributionUid(), pid, goneChain, name,
4509                             historyName, type, elapsedRealtimeMs, uptimeMs);
4510                 }
4511             }
4512         }
4513     }
4514 
noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type)4515     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
4516             String historyName, int type) {
4517         noteStopWakeFromSourceLocked(ws, pid, name, historyName, type,
4518                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4519     }
4520 
noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs)4521     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
4522             String historyName, int type, long elapsedRealtimeMs, long uptimeMs) {
4523         final int N = ws.size();
4524         for (int i=0; i<N; i++) {
4525             noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs,
4526                     uptimeMs);
4527         }
4528 
4529         List<WorkChain> wcs = ws.getWorkChains();
4530         if (wcs != null) {
4531             for (int i = 0; i < wcs.size(); ++i) {
4532                 final WorkChain wc = wcs.get(i);
4533                 noteStopWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4534                         elapsedRealtimeMs, uptimeMs);
4535             }
4536         }
4537     }
4538 
noteLongPartialWakelockStart(String name, String historyName, int uid)4539     public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
4540         noteLongPartialWakelockStart(name, historyName, uid,
4541                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4542     }
4543 
noteLongPartialWakelockStart(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)4544     public void noteLongPartialWakelockStart(String name, String historyName, int uid,
4545             long elapsedRealtimeMs, long uptimeMs) {
4546         uid = mapUid(uid);
4547         noteLongPartialWakeLockStartInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
4548     }
4549 
noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource)4550     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
4551             WorkSource workSource) {
4552         noteLongPartialWakelockStartFromSource(name, historyName, workSource,
4553                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4554     }
4555 
noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource, long elapsedRealtimeMs, long uptimeMs)4556     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
4557             WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
4558         final int N = workSource.size();
4559         for (int i = 0; i < N; ++i) {
4560             final int uid = mapUid(workSource.getUid(i));
4561             noteLongPartialWakeLockStartInternal(name, historyName, uid,
4562                     elapsedRealtimeMs, uptimeMs);
4563         }
4564 
4565         final List<WorkChain> workChains = workSource.getWorkChains();
4566         if (workChains != null) {
4567             for (int i = 0; i < workChains.size(); ++i) {
4568                 final WorkChain workChain = workChains.get(i);
4569                 final int uid = workChain.getAttributionUid();
4570                 noteLongPartialWakeLockStartInternal(name, historyName, uid,
4571                         elapsedRealtimeMs, uptimeMs);
4572             }
4573         }
4574     }
4575 
noteLongPartialWakeLockStartInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)4576     private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid,
4577             long elapsedRealtimeMs, long uptimeMs) {
4578         if (historyName == null) {
4579             historyName = name;
4580         }
4581         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid,
4582                 0)) {
4583             return;
4584         }
4585         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
4586                 historyName, uid);
4587     }
4588 
noteLongPartialWakelockFinish(String name, String historyName, int uid)4589     public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
4590         noteLongPartialWakelockFinish(name, historyName, uid,
4591                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4592     }
4593 
noteLongPartialWakelockFinish(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)4594     public void noteLongPartialWakelockFinish(String name, String historyName, int uid,
4595             long elapsedRealtimeMs, long uptimeMs) {
4596         uid = mapUid(uid);
4597         noteLongPartialWakeLockFinishInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs);
4598     }
4599 
noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource)4600     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
4601             WorkSource workSource) {
4602         noteLongPartialWakelockFinishFromSource(name, historyName, workSource,
4603                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4604     }
4605 
noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource, long elapsedRealtimeMs, long uptimeMs)4606     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
4607             WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) {
4608         final int N = workSource.size();
4609         for (int i = 0; i < N; ++i) {
4610             final int uid = mapUid(workSource.getUid(i));
4611             noteLongPartialWakeLockFinishInternal(name, historyName, uid,
4612                     elapsedRealtimeMs, uptimeMs);
4613         }
4614 
4615         final List<WorkChain> workChains = workSource.getWorkChains();
4616         if (workChains != null) {
4617             for (int i = 0; i < workChains.size(); ++i) {
4618                 final WorkChain workChain = workChains.get(i);
4619                 final int uid = workChain.getAttributionUid();
4620                 noteLongPartialWakeLockFinishInternal(name, historyName, uid,
4621                         elapsedRealtimeMs, uptimeMs);
4622             }
4623         }
4624     }
4625 
noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs)4626     private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid,
4627             long elapsedRealtimeMs, long uptimeMs) {
4628         if (historyName == null) {
4629             historyName = name;
4630         }
4631         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid,
4632                 0)) {
4633             return;
4634         }
4635         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
4636                 historyName, uid);
4637     }
4638 
aggregateLastWakeupUptimeLocked(long elapsedRealtimeMs, long uptimeMs)4639     void aggregateLastWakeupUptimeLocked(long elapsedRealtimeMs, long uptimeMs) {
4640         if (mLastWakeupReason != null) {
4641             long deltaUptimeMs = uptimeMs - mLastWakeupUptimeMs;
4642             SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
4643             timer.add(deltaUptimeMs * 1000, 1, elapsedRealtimeMs); // time in in microseconds
4644             FrameworkStatsLog.write(FrameworkStatsLog.KERNEL_WAKEUP_REPORTED, mLastWakeupReason,
4645                     /* duration_usec */ deltaUptimeMs * 1000);
4646             mLastWakeupReason = null;
4647         }
4648     }
4649 
noteWakeupReasonLocked(String reason)4650     public void noteWakeupReasonLocked(String reason) {
4651         noteWakeupReasonLocked(reason, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4652     }
4653 
noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs)4654     public void noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs) {
4655         if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
4656                 + Integer.toHexString(mHistoryCur.states));
4657         aggregateLastWakeupUptimeLocked(elapsedRealtimeMs, uptimeMs);
4658         mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
4659         mHistoryCur.wakeReasonTag.string = reason;
4660         mHistoryCur.wakeReasonTag.uid = 0;
4661         mLastWakeupReason = reason;
4662         mLastWakeupUptimeMs = uptimeMs;
4663         addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4664     }
4665 
startAddingCpuLocked()4666     public boolean startAddingCpuLocked() {
4667         mExternalSync.cancelCpuSyncDueToWakelockChange();
4668         return mOnBatteryInternal;
4669     }
4670 
finishAddingCpuLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs, int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs, int statSoftIrqTimeMs, int statIdleTimeMs)4671     public void finishAddingCpuLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs,
4672                                       int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
4673                                       int statSoftIrqTimeMs, int statIdleTimeMs) {
4674         if (DEBUG) {
4675             Slog.d(TAG, "Adding cpu: tuser=" + totalUTimeMs + " tsys=" + totalSTimeMs
4676                     + " user=" + statUserTimeMs + " sys=" + statSystemTimeMs
4677                     + " io=" + statIOWaitTimeMs + " irq=" + statIrqTimeMs
4678                     + " sirq=" + statSoftIrqTimeMs + " idle=" + statIdleTimeMs);
4679         }
4680         mCurStepCpuUserTimeMs += totalUTimeMs;
4681         mCurStepCpuSystemTimeMs += totalSTimeMs;
4682         mCurStepStatUserTimeMs += statUserTimeMs;
4683         mCurStepStatSystemTimeMs += statSystemTimeMs;
4684         mCurStepStatIOWaitTimeMs += statIOWaitTimeMs;
4685         mCurStepStatIrqTimeMs += statIrqTimeMs;
4686         mCurStepStatSoftIrqTimeMs += statSoftIrqTimeMs;
4687         mCurStepStatIdleTimeMs += statIdleTimeMs;
4688     }
4689 
noteProcessDiedLocked(int uid, int pid)4690     public void noteProcessDiedLocked(int uid, int pid) {
4691         uid = mapUid(uid);
4692         Uid u = mUidStats.get(uid);
4693         if (u != null) {
4694             u.mPids.remove(pid);
4695         }
4696     }
4697 
getProcessWakeTime(int uid, int pid, long realtimeMs)4698     public long getProcessWakeTime(int uid, int pid, long realtimeMs) {
4699         uid = mapUid(uid);
4700         Uid u = mUidStats.get(uid);
4701         if (u != null) {
4702             Uid.Pid p = u.mPids.get(pid);
4703             if (p != null) {
4704                 return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtimeMs - p.mWakeStartMs) : 0);
4705             }
4706         }
4707         return 0;
4708     }
4709 
reportExcessiveCpuLocked(int uid, String proc, long overTimeMs, long usedTimeMs)4710     public void reportExcessiveCpuLocked(int uid, String proc, long overTimeMs, long usedTimeMs) {
4711         uid = mapUid(uid);
4712         Uid u = mUidStats.get(uid);
4713         if (u != null) {
4714             u.reportExcessiveCpuLocked(proc, overTimeMs, usedTimeMs);
4715         }
4716     }
4717 
4718     int mSensorNesting;
4719 
noteStartSensorLocked(int uid, int sensor)4720     public void noteStartSensorLocked(int uid, int sensor) {
4721         noteStartSensorLocked(uid, sensor, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4722     }
4723 
noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs)4724     public void noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
4725         uid = mapUid(uid);
4726         if (mSensorNesting == 0) {
4727             mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
4728             if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
4729                     + Integer.toHexString(mHistoryCur.states));
4730             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4731         }
4732         mSensorNesting++;
4733         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4734                 .noteStartSensor(sensor, elapsedRealtimeMs);
4735     }
4736 
noteStopSensorLocked(int uid, int sensor)4737     public void noteStopSensorLocked(int uid, int sensor) {
4738         noteStopSensorLocked(uid, sensor, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4739     }
4740 
noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs)4741     public void noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
4742         uid = mapUid(uid);
4743         mSensorNesting--;
4744         if (mSensorNesting == 0) {
4745             mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
4746             if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
4747                     + Integer.toHexString(mHistoryCur.states));
4748             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4749         }
4750         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
4751                 .noteStopSensor(sensor, elapsedRealtimeMs);
4752     }
4753 
4754     int mGpsNesting;
4755 
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs)4756     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
4757         noteGpsChangedLocked(oldWs, newWs, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4758     }
4759 
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs, long elapsedRealtimeMs, long uptimeMs)4760     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs,
4761             long elapsedRealtimeMs, long uptimeMs) {
4762         for (int i = 0; i < newWs.size(); ++i) {
4763             noteStartGpsLocked(newWs.getUid(i), null, elapsedRealtimeMs, uptimeMs);
4764         }
4765 
4766         for (int i = 0; i < oldWs.size(); ++i) {
4767             noteStopGpsLocked((oldWs.getUid(i)), null, elapsedRealtimeMs, uptimeMs);
4768         }
4769 
4770         List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
4771         if (wcs != null) {
4772             if (wcs[0] != null) {
4773                 final List<WorkChain> newChains = wcs[0];
4774                 for (int i = 0; i < newChains.size(); ++i) {
4775                     noteStartGpsLocked(-1, newChains.get(i), elapsedRealtimeMs, uptimeMs);
4776                 }
4777             }
4778 
4779             if (wcs[1] != null) {
4780                 final List<WorkChain> goneChains = wcs[1];
4781                 for (int i = 0; i < goneChains.size(); ++i) {
4782                     noteStopGpsLocked(-1, goneChains.get(i), elapsedRealtimeMs, uptimeMs);
4783                 }
4784             }
4785         }
4786     }
4787 
noteStartGpsLocked(int uid, WorkChain workChain, long elapsedRealtimeMs, long uptimeMs)4788     private void noteStartGpsLocked(int uid, WorkChain workChain,
4789             long elapsedRealtimeMs, long uptimeMs) {
4790         uid = getAttributionUid(uid, workChain);
4791         if (mGpsNesting == 0) {
4792             mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
4793             if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
4794                     + Integer.toHexString(mHistoryCur.states));
4795             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4796         }
4797         mGpsNesting++;
4798 
4799         if (workChain == null) {
4800             FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
4801                     FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
4802         } else {
4803             FrameworkStatsLog.write(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
4804                     workChain.getUids(), workChain.getTags(),
4805                     FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
4806         }
4807 
4808         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteStartGps(elapsedRealtimeMs);
4809     }
4810 
noteStopGpsLocked(int uid, WorkChain workChain, long elapsedRealtimeMs, long uptimeMs)4811     private void noteStopGpsLocked(int uid, WorkChain workChain,
4812             long elapsedRealtimeMs, long uptimeMs) {
4813         uid = getAttributionUid(uid, workChain);
4814         mGpsNesting--;
4815         if (mGpsNesting == 0) {
4816             mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
4817             if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
4818                     + Integer.toHexString(mHistoryCur.states));
4819             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4820             stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
4821             mGpsSignalQualityBin = -1;
4822         }
4823 
4824         if (workChain == null) {
4825             FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
4826                     FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
4827         } else {
4828             FrameworkStatsLog.write(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(),
4829                     workChain.getTags(), FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
4830         }
4831 
4832         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteStopGps(elapsedRealtimeMs);
4833     }
4834 
noteGpsSignalQualityLocked(int signalLevel)4835     public void noteGpsSignalQualityLocked(int signalLevel) {
4836         noteGpsSignalQualityLocked(signalLevel, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4837     }
4838 
noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs)4839     public void noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs) {
4840         if (mGpsNesting == 0) {
4841             return;
4842         }
4843         if (signalLevel < 0 || signalLevel >= mGpsSignalQualityTimer.length) {
4844             stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
4845             return;
4846         }
4847         if (mGpsSignalQualityBin != signalLevel) {
4848             if (mGpsSignalQualityBin >= 0) {
4849                 mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtimeMs);
4850             }
4851             if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
4852                 mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtimeMs);
4853             }
4854             mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
4855                     | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
4856             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4857             mGpsSignalQualityBin = signalLevel;
4858         }
4859         return;
4860     }
4861 
4862     @GuardedBy("this")
noteScreenStateLocked(int state)4863     public void noteScreenStateLocked(int state) {
4864         noteScreenStateLocked(state, mClocks.elapsedRealtime(), mClocks.uptimeMillis(),
4865                 mClocks.currentTimeMillis());
4866     }
4867 
4868     @GuardedBy("this")
noteScreenStateLocked(int state, long elapsedRealtimeMs, long uptimeMs, long currentTimeMs)4869     public void noteScreenStateLocked(int state,
4870             long elapsedRealtimeMs, long uptimeMs, long currentTimeMs) {
4871         state = mPretendScreenOff ? Display.STATE_OFF : state;
4872 
4873         // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
4874         // original 4 are mapped to one of the originals.
4875         if (state > MAX_TRACKED_SCREEN_STATE) {
4876             switch (state) {
4877                 case Display.STATE_VR:
4878                     state = Display.STATE_ON;
4879                     break;
4880                 default:
4881                     Slog.wtf(TAG, "Unknown screen state (not mapped): " + state);
4882                     break;
4883             }
4884         }
4885 
4886         if (mScreenState != state) {
4887             recordDailyStatsIfNeededLocked(true, currentTimeMs);
4888             final int oldState = mScreenState;
4889             mScreenState = state;
4890             if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
4891                     + ", newState=" + Display.stateToString(state));
4892 
4893             if (state != Display.STATE_UNKNOWN) {
4894                 int stepState = state-1;
4895                 if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
4896                     mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
4897                     mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
4898                 } else {
4899                     Slog.wtf(TAG, "Unexpected screen state: " + state);
4900                 }
4901             }
4902 
4903             boolean updateHistory = false;
4904             if (Display.isDozeState(state) && !Display.isDozeState(oldState)) {
4905                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
4906                 mScreenDozeTimer.startRunningLocked(elapsedRealtimeMs);
4907                 updateHistory = true;
4908             } else if (Display.isDozeState(oldState) && !Display.isDozeState(state)) {
4909                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG;
4910                 mScreenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
4911                 updateHistory = true;
4912             }
4913             if (Display.isOnState(state)) {
4914                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
4915                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
4916                         + Integer.toHexString(mHistoryCur.states));
4917                 mScreenOnTimer.startRunningLocked(elapsedRealtimeMs);
4918                 if (mScreenBrightnessBin >= 0) {
4919                     mScreenBrightnessTimer[mScreenBrightnessBin]
4920                             .startRunningLocked(elapsedRealtimeMs);
4921                 }
4922                 updateHistory = true;
4923             } else if (Display.isOnState(oldState)) {
4924                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
4925                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
4926                         + Integer.toHexString(mHistoryCur.states));
4927                 mScreenOnTimer.stopRunningLocked(elapsedRealtimeMs);
4928                 if (mScreenBrightnessBin >= 0) {
4929                     mScreenBrightnessTimer[mScreenBrightnessBin]
4930                             .stopRunningLocked(elapsedRealtimeMs);
4931                 }
4932                 updateHistory = true;
4933             }
4934             if (updateHistory) {
4935                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: "
4936                         + Display.stateToString(state));
4937                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4938             }
4939             // TODO: (Probably overkill) Have mGlobalMeasuredEnergyStats store supported flags and
4940             //       only update DISPLAY if it is. Currently overkill since CPU is scheduled anyway.
4941             final int updateFlag = ExternalStatsSync.UPDATE_CPU | ExternalStatsSync.UPDATE_DISPLAY;
4942             mExternalSync.scheduleSyncDueToScreenStateChange(updateFlag,
4943                     mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning(), state);
4944             if (Display.isOnState(state)) {
4945                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
4946                         uptimeMs * 1000, elapsedRealtimeMs * 1000);
4947                 // Fake a wake lock, so we consider the device waked as long as the screen is on.
4948                 noteStartWakeLocked(-1, -1, null, "screen", null, WAKE_TYPE_PARTIAL, false,
4949                         elapsedRealtimeMs, uptimeMs);
4950             } else if (Display.isOnState(oldState)) {
4951                 noteStopWakeLocked(-1, -1, null, "screen", "screen", WAKE_TYPE_PARTIAL,
4952                         elapsedRealtimeMs, uptimeMs);
4953                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
4954                         uptimeMs * 1000, elapsedRealtimeMs * 1000);
4955             }
4956             // Update discharge amounts.
4957             if (mOnBatteryInternal) {
4958                 updateDischargeScreenLevelsLocked(oldState, state);
4959             }
4960         }
4961     }
4962 
4963     @UnsupportedAppUsage
noteScreenBrightnessLocked(int brightness)4964     public void noteScreenBrightnessLocked(int brightness) {
4965         noteScreenBrightnessLocked(brightness, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4966     }
4967 
noteScreenBrightnessLocked(int brightness, long elapsedRealtimeMs, long uptimeMs)4968     public void noteScreenBrightnessLocked(int brightness, long elapsedRealtimeMs, long uptimeMs) {
4969         // Bin the brightness.
4970         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
4971         if (bin < 0) bin = 0;
4972         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
4973         if (mScreenBrightnessBin != bin) {
4974             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
4975                     | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
4976             if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
4977                     + Integer.toHexString(mHistoryCur.states));
4978             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
4979             if (mScreenState == Display.STATE_ON) {
4980                 if (mScreenBrightnessBin >= 0) {
4981                     mScreenBrightnessTimer[mScreenBrightnessBin]
4982                             .stopRunningLocked(elapsedRealtimeMs);
4983                 }
4984                 mScreenBrightnessTimer[bin]
4985                         .startRunningLocked(elapsedRealtimeMs);
4986             }
4987             mScreenBrightnessBin = bin;
4988         }
4989     }
4990 
4991     @UnsupportedAppUsage
noteUserActivityLocked(int uid, int event)4992     public void noteUserActivityLocked(int uid, int event) {
4993         noteUserActivityLocked(uid, event, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
4994     }
4995 
noteUserActivityLocked(int uid, int event, long elapsedRealtimeMs, long uptimeMs)4996     public void noteUserActivityLocked(int uid, int event, long elapsedRealtimeMs, long uptimeMs) {
4997         if (mOnBatteryInternal) {
4998             uid = mapUid(uid);
4999             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteUserActivityLocked(event);
5000         }
5001     }
5002 
noteWakeUpLocked(String reason, int reasonUid)5003     public void noteWakeUpLocked(String reason, int reasonUid) {
5004         noteWakeUpLocked(reason, reasonUid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5005     }
5006 
noteWakeUpLocked(String reason, int reasonUid, long elapsedRealtimeMs, long uptimeMs)5007     public void noteWakeUpLocked(String reason, int reasonUid,
5008             long elapsedRealtimeMs, long uptimeMs) {
5009         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP,
5010                 reason, reasonUid);
5011     }
5012 
noteInteractiveLocked(boolean interactive)5013     public void noteInteractiveLocked(boolean interactive) {
5014         noteInteractiveLocked(interactive, mClocks.elapsedRealtime());
5015     }
5016 
noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs)5017     public void noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs) {
5018         if (mInteractive != interactive) {
5019             mInteractive = interactive;
5020             if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
5021             if (interactive) {
5022                 mInteractiveTimer.startRunningLocked(elapsedRealtimeMs);
5023             } else {
5024                 mInteractiveTimer.stopRunningLocked(elapsedRealtimeMs);
5025             }
5026         }
5027     }
5028 
noteConnectivityChangedLocked(int type, String extra)5029     public void noteConnectivityChangedLocked(int type, String extra) {
5030         noteConnectivityChangedLocked(type, extra,
5031                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5032     }
5033 
noteConnectivityChangedLocked(int type, String extra, long elapsedRealtimeMs, long uptimeMs)5034     public void noteConnectivityChangedLocked(int type, String extra,
5035             long elapsedRealtimeMs, long uptimeMs) {
5036         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
5037                 extra, type);
5038         mNumConnectivityChange++;
5039     }
5040 
noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)5041     private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
5042             final long uptimeMillis, int uid) {
5043         uid = mapUid(uid);
5044         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
5045                 uid);
5046         getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteMobileRadioApWakeupLocked();
5047     }
5048 
5049     /**
5050      * Updates the radio power state and returns true if an external stats collection should occur.
5051      */
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid)5052     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
5053         return noteMobileRadioPowerStateLocked(powerState, timestampNs, uid,
5054                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5055     }
5056 
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid, long elapsedRealtimeMs, long uptimeMs)5057     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid,
5058             long elapsedRealtimeMs, long uptimeMs) {
5059         if (mMobileRadioPowerState != powerState) {
5060             long realElapsedRealtimeMs;
5061             final boolean active =
5062                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
5063                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
5064             if (active) {
5065                 if (uid > 0) {
5066                     noteMobileRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
5067                 }
5068 
5069                 mMobileRadioActiveStartTimeMs = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
5070                 mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
5071             } else {
5072                 realElapsedRealtimeMs = timestampNs / (1000*1000);
5073                 long lastUpdateTimeMs = mMobileRadioActiveStartTimeMs;
5074                 if (realElapsedRealtimeMs < lastUpdateTimeMs) {
5075                     Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
5076                             + " is before start time " + lastUpdateTimeMs);
5077                     realElapsedRealtimeMs = elapsedRealtimeMs;
5078                 } else if (realElapsedRealtimeMs < elapsedRealtimeMs) {
5079                     mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtimeMs
5080                             - realElapsedRealtimeMs);
5081                 }
5082                 mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
5083             }
5084             if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
5085                     + Integer.toHexString(mHistoryCur.states));
5086             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5087             mMobileRadioPowerState = powerState;
5088             if (active) {
5089                 mMobileRadioActiveTimer.startRunningLocked(elapsedRealtimeMs);
5090                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtimeMs);
5091             } else {
5092                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
5093                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
5094                 // Tell the caller to collect radio network/power stats.
5095                 return true;
5096             }
5097         }
5098         return false;
5099     }
5100 
notePowerSaveModeLocked(boolean enabled)5101     public void notePowerSaveModeLocked(boolean enabled) {
5102         notePowerSaveModeLocked(enabled, mClocks.elapsedRealtime(), mClocks.uptimeMillis(), false);
5103     }
5104 
5105     /**
5106      * Handles power save mode state changes.
5107      */
notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs, boolean forceLog)5108     public void notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs,
5109             boolean forceLog) {
5110         if (mPowerSaveModeEnabled != enabled) {
5111             int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
5112             mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
5113             mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
5114             mPowerSaveModeEnabled = enabled;
5115             if (enabled) {
5116                 mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
5117                 if (DEBUG_HISTORY) {
5118                     Slog.v(TAG, "Power save mode enabled to: "
5119                             + Integer.toHexString(mHistoryCur.states2));
5120                 }
5121                 mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtimeMs);
5122             } else {
5123                 mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
5124                 if (DEBUG_HISTORY) {
5125                     Slog.v(TAG, "Power save mode disabled to: "
5126                             + Integer.toHexString(mHistoryCur.states2));
5127                 }
5128                 mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtimeMs);
5129             }
5130             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5131             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
5132                     enabled
5133                             ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
5134                             : FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
5135         } else if (forceLog) {
5136             // Log an initial value for BATTERY_SAVER_MODE_STATE_CHANGED in order to
5137             // allow the atom to read all future state changes.
5138             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
5139                     enabled
5140                             ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
5141                             : FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
5142         }
5143     }
5144 
noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid)5145     public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid) {
5146         noteDeviceIdleModeLocked(mode, activeReason, activeUid,
5147                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5148     }
5149 
noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid, long elapsedRealtimeMs, long uptimeMs)5150     public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid,
5151             long elapsedRealtimeMs, long uptimeMs) {
5152         boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
5153         if (mDeviceIdling && !nowIdling && activeReason == null) {
5154             // We don't go out of general idling mode until explicitly taken out of
5155             // device idle through going active or significant motion.
5156             nowIdling = true;
5157         }
5158         boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
5159         if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
5160             // We don't go out of general light idling mode until explicitly taken out of
5161             // device idle through going active or significant motion.
5162             nowLightIdling = true;
5163         }
5164         if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
5165             addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE,
5166                     activeReason, activeUid);
5167         }
5168         if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
5169             int statsmode;
5170             if (nowIdling)           statsmode = DEVICE_IDLE_MODE_DEEP;
5171             else if (nowLightIdling) statsmode = DEVICE_IDLE_MODE_LIGHT;
5172             else                     statsmode = DEVICE_IDLE_MODE_OFF;
5173             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLING_MODE_STATE_CHANGED, statsmode);
5174         }
5175         if (mDeviceIdling != nowIdling) {
5176             mDeviceIdling = nowIdling;
5177             int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
5178             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
5179             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
5180             if (nowIdling) {
5181                 mDeviceIdlingTimer.startRunningLocked(elapsedRealtimeMs);
5182             } else {
5183                 mDeviceIdlingTimer.stopRunningLocked(elapsedRealtimeMs);
5184             }
5185         }
5186         if (mDeviceLightIdling != nowLightIdling) {
5187             mDeviceLightIdling = nowLightIdling;
5188             if (nowLightIdling) {
5189                 mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtimeMs);
5190             } else {
5191                 mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtimeMs);
5192             }
5193         }
5194         if (mDeviceIdleMode != mode) {
5195             mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
5196                     | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
5197             if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
5198                     + Integer.toHexString(mHistoryCur.states2));
5199             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5200             long lastDuration = elapsedRealtimeMs - mLastIdleTimeStartMs;
5201             mLastIdleTimeStartMs = elapsedRealtimeMs;
5202             if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
5203                 if (lastDuration > mLongestLightIdleTimeMs) {
5204                     mLongestLightIdleTimeMs = lastDuration;
5205                 }
5206                 mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtimeMs);
5207             } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
5208                 if (lastDuration > mLongestFullIdleTimeMs) {
5209                     mLongestFullIdleTimeMs = lastDuration;
5210                 }
5211                 mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtimeMs);
5212             }
5213             if (mode == DEVICE_IDLE_MODE_LIGHT) {
5214                 mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtimeMs);
5215             } else if (mode == DEVICE_IDLE_MODE_DEEP) {
5216                 mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtimeMs);
5217             }
5218             mDeviceIdleMode = mode;
5219             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mode);
5220         }
5221     }
5222 
notePackageInstalledLocked(String pkgName, long versionCode)5223     public void notePackageInstalledLocked(String pkgName, long versionCode) {
5224         notePackageInstalledLocked(pkgName, versionCode,
5225                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5226     }
5227 
notePackageInstalledLocked(String pkgName, long versionCode, long elapsedRealtimeMs, long uptimeMs)5228     public void notePackageInstalledLocked(String pkgName, long versionCode,
5229             long elapsedRealtimeMs, long uptimeMs) {
5230         // XXX need to figure out what to do with long version codes.
5231         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED,
5232                 pkgName, (int)versionCode);
5233         PackageChange pc = new PackageChange();
5234         pc.mPackageName = pkgName;
5235         pc.mUpdate = true;
5236         pc.mVersionCode = versionCode;
5237         addPackageChange(pc);
5238     }
5239 
notePackageUninstalledLocked(String pkgName)5240     public void notePackageUninstalledLocked(String pkgName) {
5241         notePackageUninstalledLocked(pkgName, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5242     }
5243 
notePackageUninstalledLocked(String pkgName, long elapsedRealtimeMs, long uptimeMs)5244     public void notePackageUninstalledLocked(String pkgName,
5245             long elapsedRealtimeMs, long uptimeMs) {
5246         addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
5247                 HistoryItem.EVENT_PACKAGE_UNINSTALLED, pkgName, 0);
5248         PackageChange pc = new PackageChange();
5249         pc.mPackageName = pkgName;
5250         pc.mUpdate = true;
5251         addPackageChange(pc);
5252     }
5253 
addPackageChange(PackageChange pc)5254     private void addPackageChange(PackageChange pc) {
5255         if (mDailyPackageChanges == null) {
5256             mDailyPackageChanges = new ArrayList<>();
5257         }
5258         mDailyPackageChanges.add(pc);
5259     }
5260 
stopAllGpsSignalQualityTimersLocked(int except)5261     void stopAllGpsSignalQualityTimersLocked(int except) {
5262         stopAllGpsSignalQualityTimersLocked(except, mClocks.elapsedRealtime());
5263     }
5264 
stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs)5265     void stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs) {
5266         for (int i = 0; i < mGpsSignalQualityTimer.length; i++) {
5267             if (i == except) {
5268                 continue;
5269             }
5270             while (mGpsSignalQualityTimer[i].isRunningLocked()) {
5271                 mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtimeMs);
5272             }
5273         }
5274     }
5275 
5276     @UnsupportedAppUsage
notePhoneOnLocked()5277     public void notePhoneOnLocked() {
5278         notePhoneOnLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5279     }
5280 
notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs)5281     public void notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs) {
5282         if (!mPhoneOn) {
5283             mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
5284             if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
5285                     + Integer.toHexString(mHistoryCur.states));
5286             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5287             mPhoneOn = true;
5288             mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs);
5289         }
5290     }
5291 
5292     @UnsupportedAppUsage
notePhoneOffLocked()5293     public void notePhoneOffLocked() {
5294         notePhoneOffLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5295     }
5296 
notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs)5297     public void notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs) {
5298         if (mPhoneOn) {
5299             mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
5300             if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
5301                     + Integer.toHexString(mHistoryCur.states));
5302             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5303             mPhoneOn = false;
5304             mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs);
5305         }
5306     }
5307 
registerUsbStateReceiver(Context context)5308     private void registerUsbStateReceiver(Context context) {
5309         final IntentFilter usbStateFilter = new IntentFilter();
5310         usbStateFilter.addAction(UsbManager.ACTION_USB_STATE);
5311         context.registerReceiver(new BroadcastReceiver() {
5312             @Override
5313             public void onReceive(Context context, Intent intent) {
5314                 final boolean state = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
5315                 synchronized (BatteryStatsImpl.this) {
5316                     noteUsbConnectionStateLocked(state, mClocks.elapsedRealtime(),
5317                             mClocks.uptimeMillis());
5318                 }
5319             }
5320         }, usbStateFilter);
5321         synchronized (this) {
5322             if (mUsbDataState == USB_DATA_UNKNOWN) {
5323                 final Intent usbState = context.registerReceiver(null, usbStateFilter);
5324                 final boolean initState = usbState != null && usbState.getBooleanExtra(
5325                         UsbManager.USB_CONNECTED, false);
5326                 noteUsbConnectionStateLocked(initState, mClocks.elapsedRealtime(),
5327                         mClocks.uptimeMillis());
5328             }
5329         }
5330     }
5331 
noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs, long uptimeMs)5332     private void noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs,
5333             long uptimeMs) {
5334         int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED;
5335         if (mUsbDataState != newState) {
5336             mUsbDataState = newState;
5337             if (connected) {
5338                 mHistoryCur.states2 |= HistoryItem.STATE2_USB_DATA_LINK_FLAG;
5339             } else {
5340                 mHistoryCur.states2 &= ~HistoryItem.STATE2_USB_DATA_LINK_FLAG;
5341             }
5342             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5343         }
5344     }
5345 
stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs)5346     void stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
5347         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
5348             if (i == except) {
5349                 continue;
5350             }
5351             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
5352                 mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs);
5353             }
5354         }
5355     }
5356 
fixPhoneServiceState(int state, int signalBin)5357     private int fixPhoneServiceState(int state, int signalBin) {
5358         if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
5359             // In this case we will always be STATE_OUT_OF_SERVICE, so need
5360             // to infer that we are scanning from other data.
5361             if (state == ServiceState.STATE_OUT_OF_SERVICE
5362                     && signalBin > CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5363                 state = ServiceState.STATE_IN_SERVICE;
5364             }
5365         }
5366 
5367         return state;
5368     }
5369 
updateAllPhoneStateLocked(int state, int simState, int strengthBin, long elapsedRealtimeMs, long uptimeMs)5370     private void updateAllPhoneStateLocked(int state, int simState, int strengthBin,
5371             long elapsedRealtimeMs, long uptimeMs) {
5372         boolean scanning = false;
5373         boolean newHistory = false;
5374 
5375         mPhoneServiceStateRaw = state;
5376         mPhoneSimStateRaw = simState;
5377         mPhoneSignalStrengthBinRaw = strengthBin;
5378 
5379         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
5380             // In this case we will always be STATE_OUT_OF_SERVICE, so need
5381             // to infer that we are scanning from other data.
5382             if (state == ServiceState.STATE_OUT_OF_SERVICE
5383                     && strengthBin > CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5384                 state = ServiceState.STATE_IN_SERVICE;
5385             }
5386         }
5387 
5388         // If the phone is powered off, stop all timers.
5389         if (state == ServiceState.STATE_POWER_OFF) {
5390             strengthBin = -1;
5391 
5392         // If we are in service, make sure the correct signal string timer is running.
5393         } else if (state == ServiceState.STATE_IN_SERVICE) {
5394             // Bin will be changed below.
5395 
5396         // If we're out of service, we are in the lowest signal strength
5397         // bin and have the scanning bit set.
5398         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
5399             scanning = true;
5400             strengthBin = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
5401             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
5402                 mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
5403                 newHistory = true;
5404                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
5405                         + Integer.toHexString(mHistoryCur.states));
5406                 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtimeMs);
5407                 FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
5408                         simState, strengthBin);
5409             }
5410         }
5411 
5412         if (!scanning) {
5413             // If we are no longer scanning, then stop the scanning timer.
5414             if (mPhoneSignalScanningTimer.isRunningLocked()) {
5415                 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
5416                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
5417                         + Integer.toHexString(mHistoryCur.states));
5418                 newHistory = true;
5419                 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtimeMs);
5420                 FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
5421                         simState, strengthBin);
5422             }
5423         }
5424 
5425         if (mPhoneServiceState != state) {
5426             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
5427                     | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
5428             if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
5429                     + Integer.toHexString(mHistoryCur.states));
5430             newHistory = true;
5431             mPhoneServiceState = state;
5432         }
5433 
5434         if (mPhoneSignalStrengthBin != strengthBin) {
5435             if (mPhoneSignalStrengthBin >= 0) {
5436                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
5437                         elapsedRealtimeMs);
5438             }
5439             if (strengthBin >= 0) {
5440                 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
5441                     mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
5442                 }
5443                 mHistoryCur.states =
5444                         (mHistoryCur.states & ~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
5445                         | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
5446                 if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
5447                         + Integer.toHexString(mHistoryCur.states));
5448                 newHistory = true;
5449                 FrameworkStatsLog.write(
5450                         FrameworkStatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
5451             } else {
5452                 stopAllPhoneSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
5453             }
5454             mPhoneSignalStrengthBin = strengthBin;
5455         }
5456 
5457         if (newHistory) {
5458             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5459         }
5460     }
5461 
5462     /**
5463      * Telephony stack updates the phone state.
5464      * @param state phone state from ServiceState.getState()
5465      */
notePhoneStateLocked(int state, int simState)5466     public void notePhoneStateLocked(int state, int simState) {
5467         notePhoneStateLocked(state, simState, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5468     }
5469 
notePhoneStateLocked(int state, int simState, long elapsedRealtimeMs, long uptimeMs)5470     public void notePhoneStateLocked(int state, int simState,
5471             long elapsedRealtimeMs, long uptimeMs) {
5472         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw,
5473                 elapsedRealtimeMs, uptimeMs);
5474     }
5475 
5476     @UnsupportedAppUsage
notePhoneSignalStrengthLocked(SignalStrength signalStrength)5477     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
5478         notePhoneSignalStrengthLocked(signalStrength,
5479                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5480     }
5481 
notePhoneSignalStrengthLocked(SignalStrength signalStrength, long elapsedRealtimeMs, long uptimeMs)5482     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength,
5483             long elapsedRealtimeMs, long uptimeMs) {
5484         // Bin the strength.
5485         int bin = signalStrength.getLevel();
5486         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin,
5487                 elapsedRealtimeMs, uptimeMs);
5488     }
5489 
5490     @UnsupportedAppUsage
notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType)5491     public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType) {
5492         notePhoneDataConnectionStateLocked(dataType, hasData, serviceType,
5493                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5494     }
5495 
notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType, long elapsedRealtimeMs, long uptimeMs)5496     public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType,
5497             long elapsedRealtimeMs, long uptimeMs) {
5498         // BatteryStats uses 0 to represent no network type.
5499         // Telephony does not have a concept of no network type, and uses 0 to represent unknown.
5500         // Unknown is included in DATA_CONNECTION_OTHER.
5501         int bin = DATA_CONNECTION_OUT_OF_SERVICE;
5502         if (hasData) {
5503             if (dataType > 0 && dataType <= TelephonyManager.getAllNetworkTypes().length) {
5504                 bin = dataType;
5505             } else {
5506                 switch (serviceType) {
5507                     case ServiceState.STATE_OUT_OF_SERVICE:
5508                         bin = DATA_CONNECTION_OUT_OF_SERVICE;
5509                         break;
5510                     case ServiceState.STATE_EMERGENCY_ONLY:
5511                         bin = DATA_CONNECTION_EMERGENCY_SERVICE;
5512                         break;
5513                     default:
5514                         bin = DATA_CONNECTION_OTHER;
5515                         break;
5516                 }
5517             }
5518         }
5519         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
5520         if (mPhoneDataConnectionType != bin) {
5521             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
5522                     | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
5523             if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
5524                     + Integer.toHexString(mHistoryCur.states));
5525             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5526             if (mPhoneDataConnectionType >= 0) {
5527                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
5528                         elapsedRealtimeMs);
5529             }
5530             mPhoneDataConnectionType = bin;
5531             mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtimeMs);
5532         }
5533     }
5534 
noteWifiOnLocked()5535     public void noteWifiOnLocked() {
5536         noteWifiOnLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5537     }
5538 
noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs)5539     public void noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs) {
5540         if (!mWifiOn) {
5541             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
5542             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
5543                     + Integer.toHexString(mHistoryCur.states));
5544             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5545             mWifiOn = true;
5546             mWifiOnTimer.startRunningLocked(elapsedRealtimeMs);
5547             scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
5548         }
5549     }
5550 
noteWifiOffLocked()5551     public void noteWifiOffLocked() {
5552         noteWifiOffLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5553     }
5554 
noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs)5555     public void noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs) {
5556         if (mWifiOn) {
5557             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
5558             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
5559                     + Integer.toHexString(mHistoryCur.states));
5560             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5561             mWifiOn = false;
5562             mWifiOnTimer.stopRunningLocked(elapsedRealtimeMs);
5563             scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
5564         }
5565     }
5566 
5567     @UnsupportedAppUsage
noteAudioOnLocked(int uid)5568     public void noteAudioOnLocked(int uid) {
5569         noteAudioOnLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5570     }
5571 
noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)5572     public void noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
5573         uid = mapUid(uid);
5574         if (mAudioOnNesting == 0) {
5575             mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
5576             if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
5577                     + Integer.toHexString(mHistoryCur.states));
5578             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5579             mAudioOnTimer.startRunningLocked(elapsedRealtimeMs);
5580         }
5581         mAudioOnNesting++;
5582         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5583                 .noteAudioTurnedOnLocked(elapsedRealtimeMs);
5584     }
5585 
5586     @UnsupportedAppUsage
noteAudioOffLocked(int uid)5587     public void noteAudioOffLocked(int uid) {
5588         noteAudioOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5589     }
5590 
noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)5591     public void noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
5592         if (mAudioOnNesting == 0) {
5593             return;
5594         }
5595         uid = mapUid(uid);
5596         if (--mAudioOnNesting == 0) {
5597             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
5598             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
5599                     + Integer.toHexString(mHistoryCur.states));
5600             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5601             mAudioOnTimer.stopRunningLocked(elapsedRealtimeMs);
5602         }
5603         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5604                 .noteAudioTurnedOffLocked(elapsedRealtimeMs);
5605     }
5606 
5607     @UnsupportedAppUsage
noteVideoOnLocked(int uid)5608     public void noteVideoOnLocked(int uid) {
5609         noteVideoOnLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5610     }
5611 
noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)5612     public void noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
5613         uid = mapUid(uid);
5614         if (mVideoOnNesting == 0) {
5615             mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
5616             if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
5617                     + Integer.toHexString(mHistoryCur.states));
5618             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5619             mVideoOnTimer.startRunningLocked(elapsedRealtimeMs);
5620         }
5621         mVideoOnNesting++;
5622         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5623                 .noteVideoTurnedOnLocked(elapsedRealtimeMs);
5624     }
5625 
5626     @UnsupportedAppUsage
noteVideoOffLocked(int uid)5627     public void noteVideoOffLocked(int uid) {
5628         noteVideoOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5629     }
5630 
noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)5631     public void noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
5632         if (mVideoOnNesting == 0) {
5633             return;
5634         }
5635         uid = mapUid(uid);
5636         if (--mVideoOnNesting == 0) {
5637             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
5638             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
5639                     + Integer.toHexString(mHistoryCur.states));
5640             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5641             mVideoOnTimer.stopRunningLocked(elapsedRealtimeMs);
5642         }
5643         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5644                 .noteVideoTurnedOffLocked(elapsedRealtimeMs);
5645     }
5646 
noteResetAudioLocked()5647     public void noteResetAudioLocked() {
5648         noteResetAudioLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5649     }
5650 
noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs)5651     public void noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs) {
5652         if (mAudioOnNesting > 0) {
5653             mAudioOnNesting = 0;
5654             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
5655             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
5656                     + Integer.toHexString(mHistoryCur.states));
5657             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5658             mAudioOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
5659             for (int i=0; i<mUidStats.size(); i++) {
5660                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5661                 uid.noteResetAudioLocked(elapsedRealtimeMs);
5662             }
5663         }
5664     }
5665 
noteResetVideoLocked()5666     public void noteResetVideoLocked() {
5667         noteResetVideoLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5668     }
5669 
noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs)5670     public void noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs) {
5671         if (mVideoOnNesting > 0) {
5672             mVideoOnNesting = 0;
5673             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
5674             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
5675                     + Integer.toHexString(mHistoryCur.states));
5676             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5677             mVideoOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
5678             for (int i=0; i<mUidStats.size(); i++) {
5679                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5680                 uid.noteResetVideoLocked(elapsedRealtimeMs);
5681             }
5682         }
5683     }
5684 
noteActivityResumedLocked(int uid)5685     public void noteActivityResumedLocked(int uid) {
5686         noteActivityResumedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5687     }
5688 
noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)5689     public void noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
5690         uid = mapUid(uid);
5691         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5692                 .noteActivityResumedLocked(elapsedRealtimeMs);
5693     }
5694 
noteActivityPausedLocked(int uid)5695     public void noteActivityPausedLocked(int uid) {
5696         noteActivityPausedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5697     }
5698 
noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)5699     public void noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
5700         uid = mapUid(uid);
5701         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5702                 .noteActivityPausedLocked(elapsedRealtimeMs);
5703     }
5704 
noteVibratorOnLocked(int uid, long durationMillis)5705     public void noteVibratorOnLocked(int uid, long durationMillis) {
5706         noteVibratorOnLocked(uid, durationMillis,
5707                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5708     }
5709 
noteVibratorOnLocked(int uid, long durationMillis, long elapsedRealtimeMs, long uptimeMs)5710     public void noteVibratorOnLocked(int uid, long durationMillis,
5711             long elapsedRealtimeMs, long uptimeMs) {
5712         uid = mapUid(uid);
5713         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5714                 .noteVibratorOnLocked(durationMillis, elapsedRealtimeMs);
5715     }
5716 
noteVibratorOffLocked(int uid)5717     public void noteVibratorOffLocked(int uid) {
5718         noteVibratorOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5719     }
5720 
noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)5721     public void noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
5722         uid = mapUid(uid);
5723         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5724                 .noteVibratorOffLocked(elapsedRealtimeMs);
5725     }
5726 
noteFlashlightOnLocked(int uid)5727     public void noteFlashlightOnLocked(int uid) {
5728         noteFlashlightOnLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5729     }
5730 
noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)5731     public void noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
5732         uid = mapUid(uid);
5733         if (mFlashlightOnNesting++ == 0) {
5734             mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
5735             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
5736                     + Integer.toHexString(mHistoryCur.states2));
5737             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5738             mFlashlightOnTimer.startRunningLocked(elapsedRealtimeMs);
5739         }
5740         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5741                 .noteFlashlightTurnedOnLocked(elapsedRealtimeMs);
5742     }
5743 
noteFlashlightOffLocked(int uid)5744     public void noteFlashlightOffLocked(int uid) {
5745         noteFlashlightOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5746     }
5747 
noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)5748     public void noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
5749         if (mFlashlightOnNesting == 0) {
5750             return;
5751         }
5752         uid = mapUid(uid);
5753         if (--mFlashlightOnNesting == 0) {
5754             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
5755             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
5756                     + Integer.toHexString(mHistoryCur.states2));
5757             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5758             mFlashlightOnTimer.stopRunningLocked(elapsedRealtimeMs);
5759         }
5760         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5761                 .noteFlashlightTurnedOffLocked(elapsedRealtimeMs);
5762     }
5763 
noteCameraOnLocked(int uid)5764     public void noteCameraOnLocked(int uid) {
5765         noteCameraOnLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5766     }
5767 
noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs)5768     public void noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
5769         uid = mapUid(uid);
5770         if (mCameraOnNesting++ == 0) {
5771             mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
5772             if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
5773                     + Integer.toHexString(mHistoryCur.states2));
5774             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5775             mCameraOnTimer.startRunningLocked(elapsedRealtimeMs);
5776         }
5777         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5778                 .noteCameraTurnedOnLocked(elapsedRealtimeMs);
5779     }
5780 
noteCameraOffLocked(int uid)5781     public void noteCameraOffLocked(int uid) {
5782         noteCameraOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5783     }
5784 
noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs)5785     public void noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
5786         if (mCameraOnNesting == 0) {
5787             return;
5788         }
5789         uid = mapUid(uid);
5790         if (--mCameraOnNesting == 0) {
5791             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
5792             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
5793                     + Integer.toHexString(mHistoryCur.states2));
5794             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5795             mCameraOnTimer.stopRunningLocked(elapsedRealtimeMs);
5796         }
5797         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5798                 .noteCameraTurnedOffLocked(elapsedRealtimeMs);
5799     }
5800 
noteResetCameraLocked()5801     public void noteResetCameraLocked() {
5802         noteResetCameraLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5803     }
5804 
noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs)5805     public void noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs) {
5806         if (mCameraOnNesting > 0) {
5807             mCameraOnNesting = 0;
5808             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
5809             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
5810                     + Integer.toHexString(mHistoryCur.states2));
5811             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5812             mCameraOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
5813             for (int i=0; i<mUidStats.size(); i++) {
5814                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5815                 uid.noteResetCameraLocked(elapsedRealtimeMs);
5816             }
5817         }
5818     }
5819 
noteResetFlashlightLocked()5820     public void noteResetFlashlightLocked() {
5821         noteResetFlashlightLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5822     }
5823 
noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs)5824     public void noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs) {
5825         if (mFlashlightOnNesting > 0) {
5826             mFlashlightOnNesting = 0;
5827             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
5828             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
5829                     + Integer.toHexString(mHistoryCur.states2));
5830             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5831             mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
5832             for (int i=0; i<mUidStats.size(); i++) {
5833                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5834                 uid.noteResetFlashlightLocked(elapsedRealtimeMs);
5835             }
5836         }
5837     }
5838 
noteBluetoothScanStartedLocked(WorkChain workChain, int uid, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)5839     private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
5840             boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
5841         uid = getAttributionUid(uid, workChain);
5842         if (mBluetoothScanNesting == 0) {
5843             mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5844             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
5845                     + Integer.toHexString(mHistoryCur.states2));
5846             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5847             mBluetoothScanTimer.startRunningLocked(elapsedRealtimeMs);
5848         }
5849         mBluetoothScanNesting++;
5850         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5851                 .noteBluetoothScanStartedLocked(elapsedRealtimeMs, isUnoptimized);
5852     }
5853 
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized)5854     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
5855         noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized,
5856                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5857     }
5858 
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)5859     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
5860             long elapsedRealtimeMs, long uptimeMs) {
5861         final int N = ws.size();
5862         for (int i = 0; i < N; i++) {
5863             noteBluetoothScanStartedLocked(null, ws.getUid(i), isUnoptimized,
5864                     elapsedRealtimeMs, uptimeMs);
5865         }
5866 
5867         final List<WorkChain> workChains = ws.getWorkChains();
5868         if (workChains != null) {
5869             for (int i = 0; i < workChains.size(); ++i) {
5870                 noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized,
5871                         elapsedRealtimeMs, uptimeMs);
5872             }
5873         }
5874     }
5875 
noteBluetoothScanStoppedLocked(WorkChain workChain, int uid, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)5876     private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
5877             boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) {
5878         uid = getAttributionUid(uid, workChain);
5879         mBluetoothScanNesting--;
5880         if (mBluetoothScanNesting == 0) {
5881             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5882             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
5883                     + Integer.toHexString(mHistoryCur.states2));
5884             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5885             mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
5886         }
5887         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5888                 .noteBluetoothScanStoppedLocked(elapsedRealtimeMs, isUnoptimized);
5889     }
5890 
getAttributionUid(int uid, WorkChain workChain)5891     private int getAttributionUid(int uid, WorkChain workChain) {
5892         if (workChain != null) {
5893             return mapUid(workChain.getAttributionUid());
5894         }
5895 
5896         return mapUid(uid);
5897     }
5898 
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized)5899     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
5900         noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized,
5901                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5902     }
5903 
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs)5904     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized,
5905             long elapsedRealtimeMs, long uptimeMs) {
5906         final int N = ws.size();
5907         for (int i = 0; i < N; i++) {
5908             noteBluetoothScanStoppedLocked(null, ws.getUid(i), isUnoptimized,
5909                     elapsedRealtimeMs, uptimeMs);
5910         }
5911 
5912         final List<WorkChain> workChains = ws.getWorkChains();
5913         if (workChains != null) {
5914             for (int i = 0; i < workChains.size(); ++i) {
5915                 noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized,
5916                         elapsedRealtimeMs, uptimeMs);
5917             }
5918         }
5919     }
5920 
noteResetBluetoothScanLocked()5921     public void noteResetBluetoothScanLocked() {
5922         noteResetBluetoothScanLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5923     }
5924 
noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs)5925     public void noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs) {
5926         if (mBluetoothScanNesting > 0) {
5927             mBluetoothScanNesting = 0;
5928             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5929             if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
5930                     + Integer.toHexString(mHistoryCur.states2));
5931             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5932             mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
5933             for (int i=0; i<mUidStats.size(); i++) {
5934                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5935                 uid.noteResetBluetoothScanLocked(elapsedRealtimeMs);
5936             }
5937         }
5938     }
5939 
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults)5940     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
5941         noteBluetoothScanResultsFromSourceLocked(ws, numNewResults,
5942                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5943     }
5944 
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults, long elapsedRealtimeMs, long uptimeMs)5945     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults,
5946             long elapsedRealtimeMs, long uptimeMs) {
5947         final int N = ws.size();
5948         for (int i = 0; i < N; i++) {
5949             int uid = mapUid(ws.getUid(i));
5950             getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5951                     .noteBluetoothScanResultsLocked(numNewResults);
5952         }
5953 
5954         final List<WorkChain> workChains = ws.getWorkChains();
5955         if (workChains != null) {
5956             for (int i = 0; i < workChains.size(); ++i) {
5957                 final WorkChain wc = workChains.get(i);
5958                 int uid = mapUid(wc.getAttributionUid());
5959                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
5960                         .noteBluetoothScanResultsLocked(numNewResults);
5961             }
5962         }
5963     }
5964 
noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)5965     private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
5966             final long uptimeMillis, int uid) {
5967         uid = mapUid(uid);
5968         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
5969                 uid);
5970         getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteWifiRadioApWakeupLocked();
5971     }
5972 
noteWifiRadioPowerState(int powerState, long timestampNs, int uid)5973     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) {
5974         noteWifiRadioPowerState(powerState, timestampNs, uid,
5975                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5976     }
5977 
noteWifiRadioPowerState(int powerState, long timestampNs, int uid, long elapsedRealtimeMs, long uptimeMs)5978     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid,
5979             long elapsedRealtimeMs, long uptimeMs) {
5980         if (mWifiRadioPowerState != powerState) {
5981             final boolean active =
5982                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
5983                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
5984             if (active) {
5985                 if (uid > 0) {
5986                     noteWifiRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
5987                 }
5988                 mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
5989                 mWifiActiveTimer.startRunningLocked(elapsedRealtimeMs);
5990             } else {
5991                 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
5992                 mWifiActiveTimer.stopRunningLocked(timestampNs / (1000 * 1000));
5993             }
5994             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
5995                     + Integer.toHexString(mHistoryCur.states));
5996             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
5997             mWifiRadioPowerState = powerState;
5998         }
5999     }
6000 
noteWifiRunningLocked(WorkSource ws)6001     public void noteWifiRunningLocked(WorkSource ws) {
6002         noteWifiRunningLocked(ws, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6003     }
6004 
noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6005     public void noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
6006         if (!mGlobalWifiRunning) {
6007             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
6008             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
6009                     + Integer.toHexString(mHistoryCur.states));
6010             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6011             mGlobalWifiRunning = true;
6012             mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
6013             int N = ws.size();
6014             for (int i=0; i<N; i++) {
6015                 int uid = mapUid(ws.getUid(i));
6016                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6017                         .noteWifiRunningLocked(elapsedRealtimeMs);
6018             }
6019 
6020             List<WorkChain> workChains = ws.getWorkChains();
6021             if (workChains != null) {
6022                 for (int i = 0; i < workChains.size(); ++i) {
6023                     int uid = mapUid(workChains.get(i).getAttributionUid());
6024                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6025                             .noteWifiRunningLocked(elapsedRealtimeMs);
6026                 }
6027             }
6028 
6029             scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
6030         } else {
6031             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
6032         }
6033     }
6034 
noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs)6035     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
6036         noteWifiRunningChangedLocked(oldWs, newWs,
6037                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6038     }
6039 
noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs, long elapsedRealtimeMs, long uptimeMs)6040     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs,
6041             long elapsedRealtimeMs, long uptimeMs) {
6042         if (mGlobalWifiRunning) {
6043             int N = oldWs.size();
6044             for (int i=0; i<N; i++) {
6045                 int uid = mapUid(oldWs.getUid(i));
6046                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6047                         .noteWifiStoppedLocked(elapsedRealtimeMs);
6048             }
6049 
6050             List<WorkChain> workChains = oldWs.getWorkChains();
6051             if (workChains != null) {
6052                 for (int i = 0; i < workChains.size(); ++i) {
6053                     int uid = mapUid(workChains.get(i).getAttributionUid());
6054                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6055                             .noteWifiStoppedLocked(elapsedRealtimeMs);
6056                 }
6057             }
6058 
6059             N = newWs.size();
6060             for (int i=0; i<N; i++) {
6061                 int uid = mapUid(newWs.getUid(i));
6062                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6063                         .noteWifiRunningLocked(elapsedRealtimeMs);
6064             }
6065 
6066             workChains = newWs.getWorkChains();
6067             if (workChains != null) {
6068                 for (int i = 0; i < workChains.size(); ++i) {
6069                     int uid = mapUid(workChains.get(i).getAttributionUid());
6070                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6071                             .noteWifiRunningLocked(elapsedRealtimeMs);
6072                 }
6073             }
6074         } else {
6075             Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
6076         }
6077     }
6078 
noteWifiStoppedLocked(WorkSource ws)6079     public void noteWifiStoppedLocked(WorkSource ws) {
6080         noteWifiStoppedLocked(ws, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6081     }
6082 
noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6083     public void noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
6084         if (mGlobalWifiRunning) {
6085             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
6086             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
6087                     + Integer.toHexString(mHistoryCur.states));
6088             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6089             mGlobalWifiRunning = false;
6090             mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
6091             int N = ws.size();
6092             for (int i=0; i<N; i++) {
6093                 int uid = mapUid(ws.getUid(i));
6094                 getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6095                         .noteWifiStoppedLocked(elapsedRealtimeMs);
6096             }
6097 
6098             List<WorkChain> workChains = ws.getWorkChains();
6099             if (workChains != null) {
6100                 for (int i = 0; i < workChains.size(); ++i) {
6101                     int uid = mapUid(workChains.get(i).getAttributionUid());
6102                     getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6103                             .noteWifiStoppedLocked(elapsedRealtimeMs);
6104                 }
6105             }
6106 
6107             scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
6108         } else {
6109             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
6110         }
6111     }
6112 
noteWifiStateLocked(int wifiState, String accessPoint)6113     public void noteWifiStateLocked(int wifiState, String accessPoint) {
6114         noteWifiStateLocked(wifiState, accessPoint, mClocks.elapsedRealtime());
6115     }
6116 
noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs)6117     public void noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs) {
6118         if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
6119         if (mWifiState != wifiState) {
6120             if (mWifiState >= 0) {
6121                 mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtimeMs);
6122             }
6123             mWifiState = wifiState;
6124             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtimeMs);
6125             scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
6126         }
6127     }
6128 
noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth)6129     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
6130         noteWifiSupplicantStateChangedLocked(supplState, failedAuth,
6131                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6132     }
6133 
noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth, long elapsedRealtimeMs, long uptimeMs)6134     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth,
6135             long elapsedRealtimeMs, long uptimeMs) {
6136         if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
6137         if (mWifiSupplState != supplState) {
6138             if (mWifiSupplState >= 0) {
6139                 mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtimeMs);
6140             }
6141             mWifiSupplState = supplState;
6142             mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtimeMs);
6143             mHistoryCur.states2 =
6144                     (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
6145                     | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
6146             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
6147                     + Integer.toHexString(mHistoryCur.states2));
6148             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6149         }
6150     }
6151 
stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs)6152     void stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) {
6153         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
6154             if (i == except) {
6155                 continue;
6156             }
6157             while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
6158                 mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs);
6159             }
6160         }
6161     }
6162 
noteWifiRssiChangedLocked(int newRssi)6163     public void noteWifiRssiChangedLocked(int newRssi) {
6164         noteWifiRssiChangedLocked(newRssi, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6165     }
6166 
noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs)6167     public void noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs) {
6168         int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
6169         if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
6170         if (mWifiSignalStrengthBin != strengthBin) {
6171             if (mWifiSignalStrengthBin >= 0) {
6172                 mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
6173                         elapsedRealtimeMs);
6174             }
6175             if (strengthBin >= 0) {
6176                 if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
6177                     mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
6178                 }
6179                 mHistoryCur.states2 =
6180                         (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
6181                         | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
6182                 if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
6183                         + Integer.toHexString(mHistoryCur.states2));
6184                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6185             } else {
6186                 stopAllWifiSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
6187             }
6188             mWifiSignalStrengthBin = strengthBin;
6189         }
6190     }
6191 
6192     int mWifiFullLockNesting = 0;
6193 
6194     @UnsupportedAppUsage
noteFullWifiLockAcquiredLocked(int uid)6195     public void noteFullWifiLockAcquiredLocked(int uid) {
6196         noteFullWifiLockAcquiredLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6197     }
6198 
noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6199     public void noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6200         if (mWifiFullLockNesting == 0) {
6201             mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
6202             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
6203                     + Integer.toHexString(mHistoryCur.states));
6204             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6205         }
6206         mWifiFullLockNesting++;
6207         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6208                 .noteFullWifiLockAcquiredLocked(elapsedRealtimeMs);
6209     }
6210 
6211     @UnsupportedAppUsage
noteFullWifiLockReleasedLocked(int uid)6212     public void noteFullWifiLockReleasedLocked(int uid) {
6213         noteFullWifiLockReleasedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6214     }
6215 
noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6216     public void noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6217         mWifiFullLockNesting--;
6218         if (mWifiFullLockNesting == 0) {
6219             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
6220             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
6221                     + Integer.toHexString(mHistoryCur.states));
6222             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6223         }
6224         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6225                 .noteFullWifiLockReleasedLocked(elapsedRealtimeMs);
6226     }
6227 
6228     int mWifiScanNesting = 0;
6229 
noteWifiScanStartedLocked(int uid)6230     public void noteWifiScanStartedLocked(int uid) {
6231         noteWifiScanStartedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6232     }
6233 
noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6234     public void noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6235         if (mWifiScanNesting == 0) {
6236             mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
6237             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
6238                     + Integer.toHexString(mHistoryCur.states));
6239             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6240         }
6241         mWifiScanNesting++;
6242         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6243                 .noteWifiScanStartedLocked(elapsedRealtimeMs);
6244     }
6245 
noteWifiScanStoppedLocked(int uid)6246     public void noteWifiScanStoppedLocked(int uid) {
6247         noteWifiScanStoppedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6248     }
6249 
noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6250     public void noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6251         mWifiScanNesting--;
6252         if (mWifiScanNesting == 0) {
6253             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
6254             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
6255                     + Integer.toHexString(mHistoryCur.states));
6256             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6257         }
6258         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6259                 .noteWifiScanStoppedLocked(elapsedRealtimeMs);
6260     }
6261 
noteWifiBatchedScanStartedLocked(int uid, int csph)6262     public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
6263         noteWifiBatchedScanStartedLocked(uid, csph,
6264                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6265     }
6266 
noteWifiBatchedScanStartedLocked(int uid, int csph, long elapsedRealtimeMs, long uptimeMs)6267     public void noteWifiBatchedScanStartedLocked(int uid, int csph,
6268             long elapsedRealtimeMs, long uptimeMs) {
6269         uid = mapUid(uid);
6270         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6271                 .noteWifiBatchedScanStartedLocked(csph, elapsedRealtimeMs);
6272     }
6273 
noteWifiBatchedScanStoppedLocked(int uid)6274     public void noteWifiBatchedScanStoppedLocked(int uid) {
6275         noteWifiBatchedScanStoppedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6276     }
6277 
noteWifiBatchedScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6278     public void noteWifiBatchedScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6279         uid = mapUid(uid);
6280         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6281                 .noteWifiBatchedScanStoppedLocked(elapsedRealtimeMs);
6282     }
6283 
6284     int mWifiMulticastNesting = 0;
6285 
6286     @UnsupportedAppUsage
noteWifiMulticastEnabledLocked(int uid)6287     public void noteWifiMulticastEnabledLocked(int uid) {
6288         noteWifiMulticastEnabledLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6289     }
6290 
noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6291     public void noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6292         uid = mapUid(uid);
6293         if (mWifiMulticastNesting == 0) {
6294             mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
6295             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
6296                     + Integer.toHexString(mHistoryCur.states));
6297             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6298 
6299             // Start Wifi Multicast overall timer
6300             if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
6301                 if (DEBUG_HISTORY) Slog.v(TAG, "WiFi Multicast Overall Timer Started");
6302                 mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtimeMs);
6303             }
6304         }
6305         mWifiMulticastNesting++;
6306         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6307                 .noteWifiMulticastEnabledLocked(elapsedRealtimeMs);
6308     }
6309 
6310     @UnsupportedAppUsage
noteWifiMulticastDisabledLocked(int uid)6311     public void noteWifiMulticastDisabledLocked(int uid) {
6312         noteWifiMulticastDisabledLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6313     }
6314 
noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs)6315     public void noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
6316         uid = mapUid(uid);
6317         mWifiMulticastNesting--;
6318         if (mWifiMulticastNesting == 0) {
6319             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
6320             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
6321                     + Integer.toHexString(mHistoryCur.states));
6322             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
6323 
6324             // Stop Wifi Multicast overall timer
6325             if (mWifiMulticastWakelockTimer.isRunningLocked()) {
6326                 if (DEBUG_HISTORY) Slog.v(TAG, "Multicast Overall Timer Stopped");
6327                 mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
6328             }
6329         }
6330         getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
6331                 .noteWifiMulticastDisabledLocked(elapsedRealtimeMs);
6332     }
6333 
noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws)6334     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
6335         noteFullWifiLockAcquiredFromSourceLocked(ws,
6336                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6337     }
6338 
noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6339     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws,
6340             long elapsedRealtimeMs, long uptimeMs) {
6341         int N = ws.size();
6342         for (int i=0; i<N; i++) {
6343             final int uid = mapUid(ws.getUid(i));
6344             noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs);
6345         }
6346 
6347         final List<WorkChain> workChains = ws.getWorkChains();
6348         if (workChains != null) {
6349             for (int i = 0; i < workChains.size(); ++i) {
6350                 final WorkChain workChain = workChains.get(i);
6351                 final int uid = mapUid(workChain.getAttributionUid());
6352                 noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs);
6353             }
6354         }
6355     }
6356 
noteFullWifiLockReleasedFromSourceLocked(WorkSource ws)6357     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
6358         noteFullWifiLockReleasedFromSourceLocked(ws,
6359                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6360     }
6361 
noteFullWifiLockReleasedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6362     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws,
6363             long elapsedRealtimeMs, long uptimeMs) {
6364         int N = ws.size();
6365         for (int i=0; i<N; i++) {
6366             final int uid = mapUid(ws.getUid(i));
6367             noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs);
6368         }
6369 
6370         final List<WorkChain> workChains = ws.getWorkChains();
6371         if (workChains != null) {
6372             for (int i = 0; i < workChains.size(); ++i) {
6373                 final WorkChain workChain = workChains.get(i);
6374                 final int uid = mapUid(workChain.getAttributionUid());
6375                 noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs);
6376             }
6377         }
6378     }
6379 
noteWifiScanStartedFromSourceLocked(WorkSource ws)6380     public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
6381         noteWifiScanStartedFromSourceLocked(ws, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6382     }
6383 
noteWifiScanStartedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6384     public void noteWifiScanStartedFromSourceLocked(WorkSource ws,
6385             long elapsedRealtimeMs, long uptimeMs) {
6386         int N = ws.size();
6387         for (int i=0; i<N; i++) {
6388             final int uid = mapUid(ws.getUid(i));
6389             noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs);
6390         }
6391 
6392         final List<WorkChain> workChains = ws.getWorkChains();
6393         if (workChains != null) {
6394             for (int i = 0; i < workChains.size(); ++i) {
6395                 final WorkChain workChain = workChains.get(i);
6396                 final int uid = mapUid(workChain.getAttributionUid());
6397                 noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs);
6398             }
6399         }
6400     }
6401 
noteWifiScanStoppedFromSourceLocked(WorkSource ws)6402     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
6403         noteWifiScanStoppedFromSourceLocked(ws, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6404     }
6405 
noteWifiScanStoppedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6406     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws,
6407             long elapsedRealtimeMs, long uptimeMs) {
6408         int N = ws.size();
6409         for (int i=0; i<N; i++) {
6410             final int uid = mapUid(ws.getUid(i));
6411             noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs);
6412         }
6413 
6414         final List<WorkChain> workChains = ws.getWorkChains();
6415         if (workChains != null) {
6416             for (int i = 0; i < workChains.size(); ++i) {
6417                 final WorkChain workChain = workChains.get(i);
6418                 final int uid = mapUid(workChain.getAttributionUid());
6419                 noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs);
6420             }
6421         }
6422     }
6423 
noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph)6424     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
6425         noteWifiBatchedScanStartedFromSourceLocked(ws, csph,
6426                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6427     }
6428 
noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph, long elapsedRealtimeMs, long uptimeMs)6429     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph,
6430             long elapsedRealtimeMs, long uptimeMs) {
6431         int N = ws.size();
6432         for (int i=0; i<N; i++) {
6433             noteWifiBatchedScanStartedLocked(ws.getUid(i), csph, elapsedRealtimeMs, uptimeMs);
6434         }
6435 
6436         final List<WorkChain> workChains = ws.getWorkChains();
6437         if (workChains != null) {
6438             for (int i = 0; i < workChains.size(); ++i) {
6439                 noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph,
6440                         elapsedRealtimeMs, uptimeMs);
6441             }
6442         }
6443     }
6444 
noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws)6445     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
6446         noteWifiBatchedScanStoppedFromSourceLocked(ws,
6447                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6448     }
noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs)6449     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws,
6450             long elapsedRealtimeMs, long uptimeMs) {
6451         int N = ws.size();
6452         for (int i=0; i<N; i++) {
6453             noteWifiBatchedScanStoppedLocked(ws.getUid(i), elapsedRealtimeMs, uptimeMs);
6454         }
6455 
6456         final List<WorkChain> workChains = ws.getWorkChains();
6457         if (workChains != null) {
6458             for (int i = 0; i < workChains.size(); ++i) {
6459                 noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid(),
6460                         elapsedRealtimeMs, uptimeMs);
6461             }
6462         }
6463     }
6464 
includeInStringArray(String[] array, String str)6465     private static String[] includeInStringArray(String[] array, String str) {
6466         if (ArrayUtils.indexOf(array, str) >= 0) {
6467             return array;
6468         }
6469         String[] newArray = new String[array.length+1];
6470         System.arraycopy(array, 0, newArray, 0, array.length);
6471         newArray[array.length] = str;
6472         return newArray;
6473     }
6474 
excludeFromStringArray(String[] array, String str)6475     private static String[] excludeFromStringArray(String[] array, String str) {
6476         int index = ArrayUtils.indexOf(array, str);
6477         if (index >= 0) {
6478             String[] newArray = new String[array.length-1];
6479             if (index > 0) {
6480                 System.arraycopy(array, 0, newArray, 0, index);
6481             }
6482             if (index < array.length-1) {
6483                 System.arraycopy(array, index+1, newArray, index, array.length-index-1);
6484             }
6485             return newArray;
6486         }
6487         return array;
6488     }
6489 
6490     /** @hide */
noteNetworkInterfaceForTransports(String iface, int[] transportTypes)6491     public void noteNetworkInterfaceForTransports(String iface, int[] transportTypes) {
6492         if (TextUtils.isEmpty(iface)) return;
6493         final int displayTransport = NetworkCapabilitiesUtils.getDisplayTransport(transportTypes);
6494 
6495         synchronized (mModemNetworkLock) {
6496             if (displayTransport == TRANSPORT_CELLULAR) {
6497                 mModemIfaces = includeInStringArray(mModemIfaces, iface);
6498                 if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mModemIfaces);
6499             } else {
6500                 mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
6501                 if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mModemIfaces);
6502             }
6503         }
6504 
6505         synchronized (mWifiNetworkLock) {
6506             if (displayTransport == TRANSPORT_WIFI) {
6507                 mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
6508                 if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
6509             } else {
6510                 mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
6511                 if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
6512             }
6513         }
6514     }
6515 
6516     /**
6517      * Records timing data related to an incoming Binder call in order to attribute
6518      * the power consumption to the calling app.
6519      */
noteBinderCallStats(int workSourceUid, long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats)6520     public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
6521             Collection<BinderCallsStats.CallStat> callStats) {
6522         noteBinderCallStats(workSourceUid, incrementalCallCount, callStats,
6523                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
6524     }
6525 
noteBinderCallStats(int workSourceUid, long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats, long elapsedRealtimeMs, long uptimeMs)6526     public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
6527             Collection<BinderCallsStats.CallStat> callStats,
6528             long elapsedRealtimeMs, long uptimeMs) {
6529         synchronized (this) {
6530             getUidStatsLocked(workSourceUid, elapsedRealtimeMs, uptimeMs)
6531                     .noteBinderCallStatsLocked(incrementalCallCount, callStats);
6532         }
6533     }
6534 
6535     /**
6536      * Takes note of native IDs of threads taking incoming binder calls. The CPU time
6537      * of these threads is attributed to the apps making those binder calls.
6538      */
noteBinderThreadNativeIds(int[] binderThreadNativeTids)6539     public void noteBinderThreadNativeIds(int[] binderThreadNativeTids) {
6540         mSystemServerCpuThreadReader.setBinderThreadNativeTids(binderThreadNativeTids);
6541     }
6542 
6543     /**
6544      * Estimates the proportion of system server CPU activity handling incoming binder calls
6545      * that can be attributed to each app
6546      */
6547     @VisibleForTesting
updateSystemServiceCallStats()6548     public void updateSystemServiceCallStats() {
6549         // Start off by computing the average duration of recorded binder calls,
6550         // regardless of which binder or transaction. We will use this as a fallback
6551         // for calls that were not sampled at all.
6552         int totalRecordedCallCount = 0;
6553         long totalRecordedCallTimeMicros = 0;
6554         for (int i = 0; i < mUidStats.size(); i++) {
6555             Uid uid = mUidStats.valueAt(i);
6556             ArraySet<BinderCallStats> binderCallStats = uid.mBinderCallStats;
6557             for (int j = binderCallStats.size() - 1; j >= 0; j--) {
6558                 BinderCallStats stats = binderCallStats.valueAt(j);
6559                 totalRecordedCallCount += stats.recordedCallCount;
6560                 totalRecordedCallTimeMicros += stats.recordedCpuTimeMicros;
6561             }
6562         }
6563 
6564         long totalSystemServiceTimeMicros = 0;
6565 
6566         // For every UID, use recorded durations of sampled binder calls to estimate
6567         // the total time the system server spent handling requests from this UID.
6568         for (int i = 0; i < mUidStats.size(); i++) {
6569             Uid uid = mUidStats.valueAt(i);
6570 
6571             long totalTimeForUidUs = 0;
6572             int totalCallCountForUid = 0;
6573             ArraySet<BinderCallStats> binderCallStats = uid.mBinderCallStats;
6574             for (int j = binderCallStats.size() - 1; j >= 0; j--) {
6575                 BinderCallStats stats = binderCallStats.valueAt(j);
6576                 totalCallCountForUid += stats.callCount;
6577                 if (stats.recordedCallCount > 0) {
6578                     totalTimeForUidUs +=
6579                             stats.callCount * stats.recordedCpuTimeMicros / stats.recordedCallCount;
6580                 } else if (totalRecordedCallCount > 0) {
6581                     totalTimeForUidUs +=
6582                             stats.callCount * totalRecordedCallTimeMicros / totalRecordedCallCount;
6583                 }
6584             }
6585 
6586             if (totalCallCountForUid < uid.mBinderCallCount && totalRecordedCallCount > 0) {
6587                 // Estimate remaining calls, which were not tracked because of binder call
6588                 // stats sampling
6589                 totalTimeForUidUs +=
6590                         (uid.mBinderCallCount - totalCallCountForUid) * totalRecordedCallTimeMicros
6591                                 / totalRecordedCallCount;
6592             }
6593 
6594             uid.mSystemServiceTimeUs = totalTimeForUidUs;
6595             totalSystemServiceTimeMicros += totalTimeForUidUs;
6596         }
6597 
6598         for (int i = 0; i < mUidStats.size(); i++) {
6599             Uid uid = mUidStats.valueAt(i);
6600             if (totalSystemServiceTimeMicros > 0) {
6601                 uid.mProportionalSystemServiceUsage =
6602                         (double) uid.mSystemServiceTimeUs / totalSystemServiceTimeMicros;
6603             } else {
6604                 uid.mProportionalSystemServiceUsage = 0;
6605             }
6606         }
6607     }
6608 
getWifiIfaces()6609     public String[] getWifiIfaces() {
6610         synchronized (mWifiNetworkLock) {
6611             return mWifiIfaces;
6612         }
6613     }
6614 
getMobileIfaces()6615     public String[] getMobileIfaces() {
6616         synchronized (mModemNetworkLock) {
6617             return mModemIfaces;
6618         }
6619     }
6620 
6621     @UnsupportedAppUsage
getScreenOnTime(long elapsedRealtimeUs, int which)6622     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
6623         return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6624     }
6625 
getScreenOnCount(int which)6626     @Override public int getScreenOnCount(int which) {
6627         return mScreenOnTimer.getCountLocked(which);
6628     }
6629 
getScreenDozeTime(long elapsedRealtimeUs, int which)6630     @Override public long getScreenDozeTime(long elapsedRealtimeUs, int which) {
6631         return mScreenDozeTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6632     }
6633 
getScreenDozeCount(int which)6634     @Override public int getScreenDozeCount(int which) {
6635         return mScreenDozeTimer.getCountLocked(which);
6636     }
6637 
6638     @UnsupportedAppUsage
getScreenBrightnessTime(int brightnessBin, long elapsedRealtimeUs, int which)6639     @Override public long getScreenBrightnessTime(int brightnessBin,
6640             long elapsedRealtimeUs, int which) {
6641         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
6642                 elapsedRealtimeUs, which);
6643     }
6644 
getScreenBrightnessTimer(int brightnessBin)6645     @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
6646         return mScreenBrightnessTimer[brightnessBin];
6647     }
6648 
getInteractiveTime(long elapsedRealtimeUs, int which)6649     @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
6650         return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6651     }
6652 
getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which)6653     @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
6654         return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6655     }
6656 
getPowerSaveModeEnabledCount(int which)6657     @Override public int getPowerSaveModeEnabledCount(int which) {
6658         return mPowerSaveModeEnabledTimer.getCountLocked(which);
6659     }
6660 
getDeviceIdleModeTime(int mode, long elapsedRealtimeUs, int which)6661     @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
6662             int which) {
6663         switch (mode) {
6664             case DEVICE_IDLE_MODE_LIGHT:
6665                 return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6666             case DEVICE_IDLE_MODE_DEEP:
6667                 return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6668         }
6669         return 0;
6670     }
6671 
getDeviceIdleModeCount(int mode, int which)6672     @Override public int getDeviceIdleModeCount(int mode, int which) {
6673         switch (mode) {
6674             case DEVICE_IDLE_MODE_LIGHT:
6675                 return mDeviceIdleModeLightTimer.getCountLocked(which);
6676             case DEVICE_IDLE_MODE_DEEP:
6677                 return mDeviceIdleModeFullTimer.getCountLocked(which);
6678         }
6679         return 0;
6680     }
6681 
getLongestDeviceIdleModeTime(int mode)6682     @Override public long getLongestDeviceIdleModeTime(int mode) {
6683         switch (mode) {
6684             case DEVICE_IDLE_MODE_LIGHT:
6685                 return mLongestLightIdleTimeMs;
6686             case DEVICE_IDLE_MODE_DEEP:
6687                 return mLongestFullIdleTimeMs;
6688         }
6689         return 0;
6690     }
6691 
getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which)6692     @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
6693         switch (mode) {
6694             case DEVICE_IDLE_MODE_LIGHT:
6695                 return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6696             case DEVICE_IDLE_MODE_DEEP:
6697                 return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6698         }
6699         return 0;
6700     }
6701 
getDeviceIdlingCount(int mode, int which)6702     @Override public int getDeviceIdlingCount(int mode, int which) {
6703         switch (mode) {
6704             case DEVICE_IDLE_MODE_LIGHT:
6705                 return mDeviceLightIdlingTimer.getCountLocked(which);
6706             case DEVICE_IDLE_MODE_DEEP:
6707                 return mDeviceIdlingTimer.getCountLocked(which);
6708         }
6709         return 0;
6710     }
6711 
getNumConnectivityChange(int which)6712     @Override public int getNumConnectivityChange(int which) {
6713         return mNumConnectivityChange;
6714     }
6715 
getGpsSignalQualityTime(int strengthBin, long elapsedRealtimeUs, int which)6716     @Override public long getGpsSignalQualityTime(int strengthBin,
6717             long elapsedRealtimeUs, int which) {
6718         if (strengthBin < 0 || strengthBin >= mGpsSignalQualityTimer.length) {
6719             return 0;
6720         }
6721         return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
6722                 elapsedRealtimeUs, which);
6723     }
6724 
getGpsBatteryDrainMaMs()6725     @Override public long getGpsBatteryDrainMaMs() {
6726         final double opVolt = mPowerProfile.getAveragePower(
6727             PowerProfile.POWER_GPS_OPERATING_VOLTAGE) / 1000.0;
6728         if (opVolt == 0) {
6729             return 0;
6730         }
6731         double energyUsedMaMs = 0.0;
6732         final int which = STATS_SINCE_CHARGED;
6733         final long rawRealtimeUs = SystemClock.elapsedRealtime() * 1000;
6734         for(int i=0; i < mGpsSignalQualityTimer.length; i++) {
6735             energyUsedMaMs
6736                     += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
6737                     * (getGpsSignalQualityTime(i, rawRealtimeUs, which) / 1000);
6738         }
6739         return (long) energyUsedMaMs;
6740     }
6741 
6742     @UnsupportedAppUsage
getPhoneOnTime(long elapsedRealtimeUs, int which)6743     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
6744         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6745     }
6746 
getPhoneOnCount(int which)6747     @Override public int getPhoneOnCount(int which) {
6748         return mPhoneOnTimer.getCountLocked(which);
6749     }
6750 
6751     @UnsupportedAppUsage
getPhoneSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)6752     @Override public long getPhoneSignalStrengthTime(int strengthBin,
6753             long elapsedRealtimeUs, int which) {
6754         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
6755                 elapsedRealtimeUs, which);
6756     }
6757 
6758     @UnsupportedAppUsage
getPhoneSignalScanningTime( long elapsedRealtimeUs, int which)6759     @Override public long getPhoneSignalScanningTime(
6760             long elapsedRealtimeUs, int which) {
6761         return mPhoneSignalScanningTimer.getTotalTimeLocked(
6762                 elapsedRealtimeUs, which);
6763     }
6764 
getPhoneSignalScanningTimer()6765     @Override public Timer getPhoneSignalScanningTimer() {
6766         return mPhoneSignalScanningTimer;
6767     }
6768 
6769     @UnsupportedAppUsage
getPhoneSignalStrengthCount(int strengthBin, int which)6770     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
6771         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
6772     }
6773 
getPhoneSignalStrengthTimer(int strengthBin)6774     @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
6775         return mPhoneSignalStrengthsTimer[strengthBin];
6776     }
6777 
6778     @UnsupportedAppUsage
getPhoneDataConnectionTime(int dataType, long elapsedRealtimeUs, int which)6779     @Override public long getPhoneDataConnectionTime(int dataType,
6780             long elapsedRealtimeUs, int which) {
6781         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
6782                 elapsedRealtimeUs, which);
6783     }
6784 
6785     @UnsupportedAppUsage
getPhoneDataConnectionCount(int dataType, int which)6786     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
6787         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
6788     }
6789 
getPhoneDataConnectionTimer(int dataType)6790     @Override public Timer getPhoneDataConnectionTimer(int dataType) {
6791         return mPhoneDataConnectionsTimer[dataType];
6792     }
6793 
6794     @UnsupportedAppUsage
getMobileRadioActiveTime(long elapsedRealtimeUs, int which)6795     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
6796         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6797     }
6798 
getMobileRadioActiveCount(int which)6799     @Override public int getMobileRadioActiveCount(int which) {
6800         return mMobileRadioActiveTimer.getCountLocked(which);
6801     }
6802 
getMobileRadioActiveAdjustedTime(int which)6803     @Override public long getMobileRadioActiveAdjustedTime(int which) {
6804         return mMobileRadioActiveAdjustedTime.getCountLocked(which);
6805     }
6806 
getMobileRadioActiveUnknownTime(int which)6807     @Override public long getMobileRadioActiveUnknownTime(int which) {
6808         return mMobileRadioActiveUnknownTime.getCountLocked(which);
6809     }
6810 
getMobileRadioActiveUnknownCount(int which)6811     @Override public int getMobileRadioActiveUnknownCount(int which) {
6812         return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
6813     }
6814 
getWifiMulticastWakelockTime( long elapsedRealtimeUs, int which)6815     @Override public long getWifiMulticastWakelockTime(
6816             long elapsedRealtimeUs, int which) {
6817         return mWifiMulticastWakelockTimer.getTotalTimeLocked(
6818                 elapsedRealtimeUs, which);
6819     }
6820 
getWifiMulticastWakelockCount(int which)6821     @Override public int getWifiMulticastWakelockCount(int which) {
6822         return mWifiMulticastWakelockTimer.getCountLocked(which);
6823     }
6824 
6825     @UnsupportedAppUsage
getWifiOnTime(long elapsedRealtimeUs, int which)6826     @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
6827         return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6828     }
6829 
getWifiActiveTime(long elapsedRealtimeUs, int which)6830     @Override public long getWifiActiveTime(long elapsedRealtimeUs, int which) {
6831         return mWifiActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6832     }
6833 
6834     @UnsupportedAppUsage
getGlobalWifiRunningTime(long elapsedRealtimeUs, int which)6835     @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
6836         return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6837     }
6838 
getWifiStateTime(int wifiState, long elapsedRealtimeUs, int which)6839     @Override public long getWifiStateTime(int wifiState,
6840             long elapsedRealtimeUs, int which) {
6841         return mWifiStateTimer[wifiState].getTotalTimeLocked(
6842                 elapsedRealtimeUs, which);
6843     }
6844 
getWifiStateCount(int wifiState, int which)6845     @Override public int getWifiStateCount(int wifiState, int which) {
6846         return mWifiStateTimer[wifiState].getCountLocked(which);
6847     }
6848 
getWifiStateTimer(int wifiState)6849     @Override public Timer getWifiStateTimer(int wifiState) {
6850         return mWifiStateTimer[wifiState];
6851     }
6852 
getWifiSupplStateTime(int state, long elapsedRealtimeUs, int which)6853     @Override public long getWifiSupplStateTime(int state,
6854             long elapsedRealtimeUs, int which) {
6855         return mWifiSupplStateTimer[state].getTotalTimeLocked(
6856                 elapsedRealtimeUs, which);
6857     }
6858 
getWifiSupplStateCount(int state, int which)6859     @Override public int getWifiSupplStateCount(int state, int which) {
6860         return mWifiSupplStateTimer[state].getCountLocked(which);
6861     }
6862 
getWifiSupplStateTimer(int state)6863     @Override public Timer getWifiSupplStateTimer(int state) {
6864         return mWifiSupplStateTimer[state];
6865     }
6866 
getWifiSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)6867     @Override public long getWifiSignalStrengthTime(int strengthBin,
6868             long elapsedRealtimeUs, int which) {
6869         return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
6870                 elapsedRealtimeUs, which);
6871     }
6872 
getWifiSignalStrengthCount(int strengthBin, int which)6873     @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
6874         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
6875     }
6876 
getWifiSignalStrengthTimer(int strengthBin)6877     @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
6878         return mWifiSignalStrengthsTimer[strengthBin];
6879     }
6880 
6881     @Override
getBluetoothControllerActivity()6882     public ControllerActivityCounter getBluetoothControllerActivity() {
6883         return mBluetoothActivity;
6884     }
6885 
6886     @Override
getWifiControllerActivity()6887     public ControllerActivityCounter getWifiControllerActivity() {
6888         return mWifiActivity;
6889     }
6890 
6891     @Override
getModemControllerActivity()6892     public ControllerActivityCounter getModemControllerActivity() {
6893         return mModemActivity;
6894     }
6895 
6896     @Override
hasBluetoothActivityReporting()6897     public boolean hasBluetoothActivityReporting() {
6898         return mHasBluetoothReporting;
6899     }
6900 
6901     @Override
hasWifiActivityReporting()6902     public boolean hasWifiActivityReporting() {
6903         return mHasWifiReporting;
6904     }
6905 
6906     @Override
hasModemActivityReporting()6907     public boolean hasModemActivityReporting() {
6908         return mHasModemReporting;
6909     }
6910 
6911     @Override
getFlashlightOnTime(long elapsedRealtimeUs, int which)6912     public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
6913         return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6914     }
6915 
6916     @Override
getFlashlightOnCount(int which)6917     public long getFlashlightOnCount(int which) {
6918         return mFlashlightOnTimer.getCountLocked(which);
6919     }
6920 
6921     @Override
getCameraOnTime(long elapsedRealtimeUs, int which)6922     public long getCameraOnTime(long elapsedRealtimeUs, int which) {
6923         return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6924     }
6925 
6926     @Override
getBluetoothScanTime(long elapsedRealtimeUs, int which)6927     public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
6928         return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6929     }
6930 
6931     @Override
6932     @UnsupportedAppUsage
getNetworkActivityBytes(int type, int which)6933     public long getNetworkActivityBytes(int type, int which) {
6934         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
6935             return mNetworkByteActivityCounters[type].getCountLocked(which);
6936         } else {
6937             return 0;
6938         }
6939     }
6940 
6941     @Override
getNetworkActivityPackets(int type, int which)6942     public long getNetworkActivityPackets(int type, int which) {
6943         if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
6944             return mNetworkPacketActivityCounters[type].getCountLocked(which);
6945         } else {
6946             return 0;
6947         }
6948     }
6949 
6950     @Override
getBluetoothMeasuredBatteryConsumptionUC()6951     public long getBluetoothMeasuredBatteryConsumptionUC() {
6952         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH);
6953     }
6954 
6955     @Override
getCpuMeasuredBatteryConsumptionUC()6956     public long getCpuMeasuredBatteryConsumptionUC() {
6957         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
6958     }
6959 
6960     @Override
getGnssMeasuredBatteryConsumptionUC()6961     public long getGnssMeasuredBatteryConsumptionUC() {
6962         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_GNSS);
6963     }
6964 
6965     @Override
getMobileRadioMeasuredBatteryConsumptionUC()6966     public long getMobileRadioMeasuredBatteryConsumptionUC() {
6967         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO);
6968     }
6969 
6970     @Override
getScreenOnMeasuredBatteryConsumptionUC()6971     public long getScreenOnMeasuredBatteryConsumptionUC() {
6972         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON);
6973     }
6974 
6975     @Override
getScreenDozeMeasuredBatteryConsumptionUC()6976     public long getScreenDozeMeasuredBatteryConsumptionUC() {
6977         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_DOZE);
6978     }
6979 
6980     @Override
getWifiMeasuredBatteryConsumptionUC()6981     public long getWifiMeasuredBatteryConsumptionUC() {
6982         return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_WIFI);
6983     }
6984 
6985     /**
6986      * Returns the consumption (in microcoulombs) that the given standard power bucket consumed.
6987      * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable
6988      *
6989      * @param bucket standard power bucket of interest
6990      * @return charge (in microcoulombs) used for this power bucket
6991      */
getPowerBucketConsumptionUC(@tandardPowerBucket int bucket)6992     private long getPowerBucketConsumptionUC(@StandardPowerBucket int bucket) {
6993         if (mGlobalMeasuredEnergyStats == null) {
6994             return POWER_DATA_UNAVAILABLE;
6995         }
6996         return mGlobalMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket);
6997     }
6998 
6999     @Override
getCustomConsumerMeasuredBatteryConsumptionUC()7000     public @Nullable long[] getCustomConsumerMeasuredBatteryConsumptionUC() {
7001         if (mGlobalMeasuredEnergyStats == null) {
7002             return null;
7003         }
7004         return mGlobalMeasuredEnergyStats.getAccumulatedCustomBucketCharges();
7005     }
7006 
7007     /**
7008      * Returns the names of custom power components.
7009      */
7010     @Override
getCustomEnergyConsumerNames()7011     public @NonNull String[] getCustomEnergyConsumerNames() {
7012         if (mGlobalMeasuredEnergyStats == null) {
7013             return new String[0];
7014         }
7015         final String[] names = mGlobalMeasuredEnergyStats.getCustomBucketNames();
7016         for (int i = 0; i < names.length; i++) {
7017             if (TextUtils.isEmpty(names[i])) {
7018                 names[i] = "CUSTOM_" + BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + i;
7019             }
7020         }
7021         return names;
7022     }
7023 
getStartClockTime()7024     @Override public long getStartClockTime() {
7025         final long currentTimeMs = mClocks.currentTimeMillis();
7026         if ((currentTimeMs > MILLISECONDS_IN_YEAR
7027                 && mStartClockTimeMs < (currentTimeMs - MILLISECONDS_IN_YEAR))
7028                 || (mStartClockTimeMs > currentTimeMs)) {
7029             // If the start clock time has changed by more than a year, then presumably
7030             // the previous time was completely bogus.  So we are going to figure out a
7031             // new time based on how much time has elapsed since we started counting.
7032             recordCurrentTimeChangeLocked(currentTimeMs, mClocks.elapsedRealtime(),
7033                     mClocks.uptimeMillis());
7034             return currentTimeMs - (mClocks.elapsedRealtime() - (mRealtimeStartUs / 1000));
7035         }
7036         return mStartClockTimeMs;
7037     }
7038 
getStartPlatformVersion()7039     @Override public String getStartPlatformVersion() {
7040         return mStartPlatformVersion;
7041     }
7042 
getEndPlatformVersion()7043     @Override public String getEndPlatformVersion() {
7044         return mEndPlatformVersion;
7045     }
7046 
getParcelVersion()7047     @Override public int getParcelVersion() {
7048         return VERSION;
7049     }
7050 
getIsOnBattery()7051     @Override public boolean getIsOnBattery() {
7052         return mOnBattery;
7053     }
7054 
getStatsStartRealtime()7055     @Override public long getStatsStartRealtime() {
7056         return mRealtimeStartUs;
7057     }
7058 
7059     @UnsupportedAppUsage
getUidStats()7060     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
7061         return mUidStats;
7062     }
7063 
resetIfNotNull(T t, boolean detachIfReset, long elapsedRealtimeUs)7064     private static <T extends TimeBaseObs> boolean resetIfNotNull(T t, boolean detachIfReset,
7065             long elapsedRealtimeUs) {
7066         if (t != null) {
7067             return t.reset(detachIfReset, elapsedRealtimeUs);
7068         }
7069         return true;
7070     }
7071 
resetIfNotNull(T[] t, boolean detachIfReset, long elapsedRealtimeUs)7072     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[] t, boolean detachIfReset,
7073             long elapsedRealtimeUs) {
7074         if (t != null) {
7075             boolean ret = true;
7076             for (int i = 0; i < t.length; i++) {
7077                 ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs);
7078             }
7079             return ret;
7080         }
7081         return true;
7082     }
7083 
resetIfNotNull(T[][] t, boolean detachIfReset, long elapsedRealtimeUs)7084     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[][] t, boolean detachIfReset,
7085             long elapsedRealtimeUs) {
7086         if (t != null) {
7087             boolean ret = true;
7088             for (int i = 0; i < t.length; i++) {
7089                 ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs);
7090             }
7091             return ret;
7092         }
7093         return true;
7094     }
7095 
resetIfNotNull(ControllerActivityCounterImpl counter, boolean detachIfReset, long elapsedRealtimeUs)7096     private static boolean resetIfNotNull(ControllerActivityCounterImpl counter,
7097             boolean detachIfReset, long elapsedRealtimeUs) {
7098         if (counter != null) {
7099             counter.reset(detachIfReset, elapsedRealtimeUs);
7100         }
7101         return true;
7102     }
7103 
detachIfNotNull(T t)7104     private static <T extends TimeBaseObs> void detachIfNotNull(T t) {
7105         if (t != null) {
7106             t.detach();
7107         }
7108     }
7109 
detachIfNotNull(T[] t)7110     private static <T extends TimeBaseObs> void detachIfNotNull(T[] t) {
7111         if (t != null) {
7112             for (int i = 0; i < t.length; i++) {
7113                 detachIfNotNull(t[i]);
7114             }
7115         }
7116     }
7117 
detachIfNotNull(T[][] t)7118     private static <T extends TimeBaseObs> void detachIfNotNull(T[][] t) {
7119         if (t != null) {
7120             for (int i = 0; i < t.length; i++) {
7121                 detachIfNotNull(t[i]);
7122             }
7123         }
7124     }
7125 
detachIfNotNull(ControllerActivityCounterImpl counter)7126     private static void detachIfNotNull(ControllerActivityCounterImpl counter) {
7127         if (counter != null) {
7128             counter.detach();
7129         }
7130     }
7131 
7132     /**
7133      * Accumulates stats for a specific binder transaction.
7134      */
7135     @VisibleForTesting
7136     protected static class BinderCallStats {
7137         static final Comparator<BinderCallStats> COMPARATOR =
7138                 Comparator.comparing(BinderCallStats::getClassName)
7139                         .thenComparing(BinderCallStats::getMethodName);
7140 
7141         public Class<? extends Binder> binderClass;
7142         public int transactionCode;
7143         public String methodName;
7144 
7145         public long callCount;
7146         public long recordedCallCount;
7147         public long recordedCpuTimeMicros;
7148 
7149 
7150         @Override
hashCode()7151         public int hashCode() {
7152             return binderClass.hashCode() * 31 + transactionCode;
7153         }
7154 
7155         @Override
equals(Object obj)7156         public boolean equals(Object obj) {
7157             if (!(obj instanceof BinderCallStats)) {
7158                 return false;
7159             }
7160             BinderCallStats bcsk = (BinderCallStats) obj;
7161             return binderClass.equals(bcsk.binderClass) && transactionCode == bcsk.transactionCode;
7162         }
7163 
getClassName()7164         public String getClassName() {
7165             return binderClass.getName();
7166         }
7167 
getMethodName()7168         public String getMethodName() {
7169             return methodName;
7170         }
7171 
7172         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
ensureMethodName(BinderTransactionNameResolver resolver)7173         public void ensureMethodName(BinderTransactionNameResolver resolver) {
7174             if (methodName == null) {
7175                 methodName = resolver.getMethodName(binderClass, transactionCode);
7176             }
7177         }
7178 
7179         @Override
toString()7180         public String toString() {
7181             return "BinderCallStats{"
7182                     + binderClass
7183                     + " transaction=" + transactionCode
7184                     + " callCount=" + callCount
7185                     + " recordedCallCount=" + recordedCallCount
7186                     + " recorderCpuTimeMicros=" + recordedCpuTimeMicros
7187                     + "}";
7188         }
7189     }
7190 
7191     /**
7192      * The statistics associated with a particular uid.
7193      */
7194     public static class Uid extends BatteryStats.Uid {
7195         /**
7196          * BatteryStatsImpl that we are associated with.
7197          */
7198         protected BatteryStatsImpl mBsi;
7199 
7200         final int mUid;
7201 
7202         /** TimeBase for when uid is in background and device is on battery. */
7203         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
7204         public final TimeBase mOnBatteryBackgroundTimeBase;
7205         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
7206         public final TimeBase mOnBatteryScreenOffBackgroundTimeBase;
7207 
7208         boolean mWifiRunning;
7209         StopwatchTimer mWifiRunningTimer;
7210 
7211         boolean mFullWifiLockOut;
7212         StopwatchTimer mFullWifiLockTimer;
7213 
7214         boolean mWifiScanStarted;
7215         DualTimer mWifiScanTimer;
7216 
7217         static final int NO_BATCHED_SCAN_STARTED = -1;
7218         int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
7219         StopwatchTimer[] mWifiBatchedScanTimer;
7220 
7221         int mWifiMulticastWakelockCount;
7222         StopwatchTimer mWifiMulticastTimer;
7223 
7224         StopwatchTimer mAudioTurnedOnTimer;
7225         StopwatchTimer mVideoTurnedOnTimer;
7226         StopwatchTimer mFlashlightTurnedOnTimer;
7227         StopwatchTimer mCameraTurnedOnTimer;
7228         StopwatchTimer mForegroundActivityTimer;
7229         StopwatchTimer mForegroundServiceTimer;
7230         /** Total time spent by the uid holding any partial wakelocks. */
7231         DualTimer mAggregatedPartialWakelockTimer;
7232         DualTimer mBluetoothScanTimer;
7233         DualTimer mBluetoothUnoptimizedScanTimer;
7234         Counter mBluetoothScanResultCounter;
7235         Counter mBluetoothScanResultBgCounter;
7236 
7237         int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
7238         StopwatchTimer[] mProcessStateTimer;
7239 
7240         boolean mInForegroundService = false;
7241 
7242         BatchTimer mVibratorOnTimer;
7243 
7244         Counter[] mUserActivityCounters;
7245 
7246         LongSamplingCounter[] mNetworkByteActivityCounters;
7247         LongSamplingCounter[] mNetworkPacketActivityCounters;
7248         LongSamplingCounter mMobileRadioActiveTime;
7249         LongSamplingCounter mMobileRadioActiveCount;
7250 
7251         /**
7252          * How many times this UID woke up the Application Processor due to a Mobile radio packet.
7253          */
7254         private LongSamplingCounter mMobileRadioApWakeupCount;
7255 
7256         /**
7257          * How many times this UID woke up the Application Processor due to a Wifi packet.
7258          */
7259         private LongSamplingCounter mWifiRadioApWakeupCount;
7260 
7261         /**
7262          * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
7263          * Can be null if the UID has had no such activity.
7264          */
7265         private ControllerActivityCounterImpl mWifiControllerActivity;
7266 
7267         /**
7268          * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
7269          * Can be null if the UID has had no such activity.
7270          */
7271         private ControllerActivityCounterImpl mBluetoothControllerActivity;
7272 
7273         /**
7274          * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
7275          * Can be null if the UID has had no such activity.
7276          */
7277         private ControllerActivityCounterImpl mModemControllerActivity;
7278 
7279         /**
7280          * The CPU times we had at the last history details update.
7281          */
7282         long mLastStepUserTimeMs;
7283         long mLastStepSystemTimeMs;
7284         long mCurStepUserTimeMs;
7285         long mCurStepSystemTimeMs;
7286 
7287         LongSamplingCounter mUserCpuTime;
7288         LongSamplingCounter mSystemCpuTime;
7289         LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
7290         LongSamplingCounter mCpuActiveTimeMs;
7291 
7292         LongSamplingCounterArray mCpuFreqTimeMs;
7293         LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
7294         LongSamplingCounterArray mCpuClusterTimesMs;
7295 
7296         LongSamplingCounterArray[] mProcStateTimeMs;
7297         LongSamplingCounterArray[] mProcStateScreenOffTimeMs;
7298 
7299         IntArray mChildUids;
7300 
7301         /**
7302          * The statistics we have collected for this uid's wake locks.
7303          */
7304         final OverflowArrayMap<Wakelock> mWakelockStats;
7305 
7306         /**
7307          * The statistics we have collected for this uid's syncs.
7308          */
7309         final OverflowArrayMap<DualTimer> mSyncStats;
7310 
7311         /**
7312          * The statistics we have collected for this uid's jobs.
7313          */
7314         final OverflowArrayMap<DualTimer> mJobStats;
7315 
7316         /**
7317          * Count of the jobs that have completed and the reasons why they completed.
7318          */
7319         final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
7320 
7321         /**
7322          * Count of app launch events that had associated deferred job counts or info about
7323          * last time a job was run.
7324          */
7325         Counter mJobsDeferredEventCount;
7326 
7327         /**
7328          * Count of deferred jobs that were pending when the app was launched or brought to
7329          * the foreground through a user interaction.
7330          */
7331         Counter mJobsDeferredCount;
7332 
7333         /**
7334          * Sum of time since the last time a job was run for this app before it was launched.
7335          */
7336         LongSamplingCounter mJobsFreshnessTimeMs;
7337 
7338         /**
7339          * Array of counts of instances where the time since the last job was run for the app
7340          * fell within one of the thresholds in {@link #JOB_FRESHNESS_BUCKETS}.
7341          */
7342         final Counter[] mJobsFreshnessBuckets;
7343 
7344         /**
7345          * The statistics we have collected for this uid's sensor activations.
7346          */
7347         final SparseArray<Sensor> mSensorStats = new SparseArray<>();
7348 
7349         /**
7350          * The statistics we have collected for this uid's processes.
7351          */
7352         final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
7353 
7354         /**
7355          * The statistics we have collected for this uid's processes.
7356          */
7357         final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
7358 
7359         /**
7360          * The transient wake stats we have collected for this uid's pids.
7361          */
7362         final SparseArray<Pid> mPids = new SparseArray<>();
7363 
7364         /**
7365          * Grand total of system server binder calls made by this uid.
7366          */
7367         private long mBinderCallCount;
7368 
7369         /**
7370          * Detailed information about system server binder calls made by this uid.
7371          */
7372         private final ArraySet<BinderCallStats> mBinderCallStats = new ArraySet<>();
7373 
7374         /**
7375          * Measured charge consumption by this uid while on battery.
7376          * Its '<b>custom</b> power buckets' correspond to the
7377          * {@link android.hardware.power.stats.EnergyConsumer.ordinal}s of (custom) energy consumer
7378          * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
7379          *
7380          * Will be null if energy consumer data is completely unavailable (in which case
7381          * {@link #mGlobalMeasuredEnergyStats} will also be null) or if the power usage by this uid
7382          * is 0 for every bucket.
7383          */
7384         private MeasuredEnergyStats mUidMeasuredEnergyStats;
7385 
7386         /**
7387          * Estimated total time spent by the system server handling requests from this uid.
7388          */
7389         private long mSystemServiceTimeUs;
7390 
7391         /**
7392          * Estimated proportion of system server binder call CPU cost for this uid.
7393          */
7394         private double mProportionalSystemServiceUsage;
7395 
Uid(BatteryStatsImpl bsi, int uid)7396         public Uid(BatteryStatsImpl bsi, int uid) {
7397             this(bsi, uid, bsi.mClocks.elapsedRealtime(), bsi.mClocks.uptimeMillis());
7398         }
7399 
Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs)7400         public Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs) {
7401             mBsi = bsi;
7402             mUid = uid;
7403 
7404             /* Observer list of TimeBase object in Uid is short */
7405             mOnBatteryBackgroundTimeBase = new TimeBase(false);
7406             mOnBatteryBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
7407             /* Observer list of TimeBase object in Uid is short */
7408             mOnBatteryScreenOffBackgroundTimeBase = new TimeBase(false);
7409             mOnBatteryScreenOffBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
7410 
7411             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7412             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7413             mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7414             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase);
7415 
7416             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
7417                 @Override public Wakelock instantiateObject() {
7418                     return new Wakelock(mBsi, Uid.this);
7419                 }
7420             };
7421             mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
7422                 @Override public DualTimer instantiateObject() {
7423                     return new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
7424                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
7425                 }
7426             };
7427             mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
7428                 @Override public DualTimer instantiateObject() {
7429                     return new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
7430                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
7431                 }
7432             };
7433 
7434             mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_RUNNING,
7435                     mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
7436             mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, this, FULL_WIFI_LOCK,
7437                     mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
7438             mWifiScanTimer = new DualTimer(mBsi.mClocks, this, WIFI_SCAN,
7439                     mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
7440             mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
7441             mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_MULTICAST_ENABLED,
7442                     mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
7443             mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
7444             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase);
7445             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase);
7446             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7447             mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length];
7448         }
7449 
7450         @VisibleForTesting
setProcessStateForTest(int procState)7451         public void setProcessStateForTest(int procState) {
7452             mProcessState = procState;
7453         }
7454 
7455         @Override
getCpuFreqTimes(int which)7456         public long[] getCpuFreqTimes(int which) {
7457             return nullIfAllZeros(mCpuFreqTimeMs, which);
7458         }
7459 
7460         @Override
getScreenOffCpuFreqTimes(int which)7461         public long[] getScreenOffCpuFreqTimes(int which) {
7462             return nullIfAllZeros(mScreenOffCpuFreqTimeMs, which);
7463         }
7464 
7465         @Override
getCpuActiveTime()7466         public long getCpuActiveTime() {
7467             return mCpuActiveTimeMs.getCountLocked(STATS_SINCE_CHARGED);
7468         }
7469 
7470         @Override
getCpuClusterTimes()7471         public long[] getCpuClusterTimes() {
7472             return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
7473         }
7474 
7475         @Override
getCpuFreqTimes(int which, int procState)7476         public long[] getCpuFreqTimes(int which, int procState) {
7477             if (which < 0 || which >= NUM_PROCESS_STATE) {
7478                 return null;
7479             }
7480             if (mProcStateTimeMs == null) {
7481                 return null;
7482             }
7483             if (!mBsi.mPerProcStateCpuTimesAvailable) {
7484                 mProcStateTimeMs = null;
7485                 return null;
7486             }
7487             return nullIfAllZeros(mProcStateTimeMs[procState], which);
7488         }
7489 
7490         @Override
getScreenOffCpuFreqTimes(int which, int procState)7491         public long[] getScreenOffCpuFreqTimes(int which, int procState) {
7492             if (which < 0 || which >= NUM_PROCESS_STATE) {
7493                 return null;
7494             }
7495             if (mProcStateScreenOffTimeMs == null) {
7496                 return null;
7497             }
7498             if (!mBsi.mPerProcStateCpuTimesAvailable) {
7499                 mProcStateScreenOffTimeMs = null;
7500                 return null;
7501             }
7502             return nullIfAllZeros(mProcStateScreenOffTimeMs[procState], which);
7503         }
7504 
getBinderCallCount()7505         public long getBinderCallCount() {
7506             return mBinderCallCount;
7507         }
7508 
7509         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
getBinderCallStats()7510         public ArraySet<BinderCallStats> getBinderCallStats() {
7511             return mBinderCallStats;
7512         }
7513 
7514         @Override
getProportionalSystemServiceUsage()7515         public  double getProportionalSystemServiceUsage() {
7516             return mProportionalSystemServiceUsage;
7517         }
7518 
addIsolatedUid(int isolatedUid)7519         public void addIsolatedUid(int isolatedUid) {
7520             if (mChildUids == null) {
7521                 mChildUids = new IntArray();
7522             } else if (mChildUids.indexOf(isolatedUid) >= 0) {
7523                 return;
7524             }
7525             mChildUids.add(isolatedUid);
7526         }
7527 
removeIsolatedUid(int isolatedUid)7528         public void removeIsolatedUid(int isolatedUid) {
7529             final int idx = mChildUids == null ? -1 : mChildUids.indexOf(isolatedUid);
7530             if (idx < 0) {
7531                 return;
7532             }
7533             mChildUids.remove(idx);
7534         }
7535 
nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which)7536         private long[] nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which) {
7537             if (cpuTimesMs == null) {
7538                 return null;
7539             }
7540             final long[] counts = cpuTimesMs.getCountsLocked(which);
7541             if (counts == null) {
7542                 return null;
7543             }
7544             // Return counts only if at least one of the elements is non-zero.
7545             for (int i = counts.length - 1; i >= 0; --i) {
7546                 if (counts[i] != 0) {
7547                     return counts;
7548                 }
7549             }
7550             return null;
7551         }
7552 
addProcStateTimesMs(int procState, long[] cpuTimesMs, boolean onBattery)7553         private void addProcStateTimesMs(int procState, long[] cpuTimesMs, boolean onBattery) {
7554             if (mProcStateTimeMs == null) {
7555                 mProcStateTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
7556             }
7557             if (mProcStateTimeMs[procState] == null
7558                     || mProcStateTimeMs[procState].getSize() != cpuTimesMs.length) {
7559                 detachIfNotNull(mProcStateTimeMs[procState]);
7560                 mProcStateTimeMs[procState] = new LongSamplingCounterArray(
7561                         mBsi.mOnBatteryTimeBase);
7562             }
7563             mProcStateTimeMs[procState].addCountLocked(cpuTimesMs, onBattery);
7564         }
7565 
addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs, boolean onBatteryScreenOff)7566         private void addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs,
7567                 boolean onBatteryScreenOff) {
7568             if (mProcStateScreenOffTimeMs == null) {
7569                 mProcStateScreenOffTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
7570             }
7571             if (mProcStateScreenOffTimeMs[procState] == null
7572                     || mProcStateScreenOffTimeMs[procState].getSize() != cpuTimesMs.length) {
7573                 detachIfNotNull(mProcStateScreenOffTimeMs[procState]);
7574                 mProcStateScreenOffTimeMs[procState] = new LongSamplingCounterArray(
7575                         mBsi.mOnBatteryScreenOffTimeBase);
7576             }
7577             mProcStateScreenOffTimeMs[procState].addCountLocked(cpuTimesMs, onBatteryScreenOff);
7578         }
7579 
7580         @Override
getAggregatedPartialWakelockTimer()7581         public Timer getAggregatedPartialWakelockTimer() {
7582             return mAggregatedPartialWakelockTimer;
7583         }
7584 
7585         @Override
7586         @UnsupportedAppUsage
getWakelockStats()7587         public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
7588             return mWakelockStats.getMap();
7589         }
7590 
7591         @Override
getMulticastWakelockStats()7592         public Timer getMulticastWakelockStats() {
7593             return mWifiMulticastTimer;
7594         }
7595 
7596         @Override
getSyncStats()7597         public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
7598             return mSyncStats.getMap();
7599         }
7600 
7601         @Override
getJobStats()7602         public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
7603             return mJobStats.getMap();
7604         }
7605 
7606         @Override
getJobCompletionStats()7607         public ArrayMap<String, SparseIntArray> getJobCompletionStats() {
7608             return mJobCompletions;
7609         }
7610 
7611         @Override
7612         @UnsupportedAppUsage
getSensorStats()7613         public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
7614             return mSensorStats;
7615         }
7616 
7617         @Override
7618         @UnsupportedAppUsage
getProcessStats()7619         public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
7620             return mProcessStats;
7621         }
7622 
7623         @Override
getPackageStats()7624         public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
7625             return mPackageStats;
7626         }
7627 
7628         @Override
7629         @UnsupportedAppUsage
getUid()7630         public int getUid() {
7631             return mUid;
7632         }
7633 
7634         @Override
noteWifiRunningLocked(long elapsedRealtimeMs)7635         public void noteWifiRunningLocked(long elapsedRealtimeMs) {
7636             if (!mWifiRunning) {
7637                 mWifiRunning = true;
7638                 if (mWifiRunningTimer == null) {
7639                     mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
7640                             mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
7641                 }
7642                 mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
7643             }
7644         }
7645 
7646         @Override
noteWifiStoppedLocked(long elapsedRealtimeMs)7647         public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
7648             if (mWifiRunning) {
7649                 mWifiRunning = false;
7650                 mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
7651             }
7652         }
7653 
7654         @Override
noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs)7655         public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
7656             if (!mFullWifiLockOut) {
7657                 mFullWifiLockOut = true;
7658                 if (mFullWifiLockTimer == null) {
7659                     mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
7660                             mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
7661                 }
7662                 mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
7663             }
7664         }
7665 
7666         @Override
noteFullWifiLockReleasedLocked(long elapsedRealtimeMs)7667         public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
7668             if (mFullWifiLockOut) {
7669                 mFullWifiLockOut = false;
7670                 mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
7671             }
7672         }
7673 
7674         @Override
noteWifiScanStartedLocked(long elapsedRealtimeMs)7675         public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
7676             if (!mWifiScanStarted) {
7677                 mWifiScanStarted = true;
7678                 if (mWifiScanTimer == null) {
7679                     mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
7680                             mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase,
7681                             mOnBatteryBackgroundTimeBase);
7682                 }
7683                 mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
7684             }
7685         }
7686 
7687         @Override
noteWifiScanStoppedLocked(long elapsedRealtimeMs)7688         public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
7689             if (mWifiScanStarted) {
7690                 mWifiScanStarted = false;
7691                 mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
7692             }
7693         }
7694 
7695         @Override
noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs)7696         public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
7697             int bin = 0;
7698             while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
7699                 csph = csph >> 3;
7700                 bin++;
7701             }
7702 
7703             if (mWifiBatchedScanBinStarted == bin) return;
7704 
7705             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
7706                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
7707                         stopRunningLocked(elapsedRealtimeMs);
7708             }
7709             mWifiBatchedScanBinStarted = bin;
7710             if (mWifiBatchedScanTimer[bin] == null) {
7711                 makeWifiBatchedScanBin(bin, null);
7712             }
7713             mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
7714         }
7715 
7716         @Override
noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs)7717         public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
7718             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
7719                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
7720                         stopRunningLocked(elapsedRealtimeMs);
7721                 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
7722             }
7723         }
7724 
7725         @Override
noteWifiMulticastEnabledLocked(long elapsedRealtimeMs)7726         public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
7727             if (mWifiMulticastWakelockCount == 0) {
7728                 if (mWifiMulticastTimer == null) {
7729                     mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7730                             WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
7731                 }
7732                 mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
7733             }
7734             mWifiMulticastWakelockCount++;
7735         }
7736 
7737         @Override
noteWifiMulticastDisabledLocked(long elapsedRealtimeMs)7738         public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
7739             if (mWifiMulticastWakelockCount == 0) {
7740                 return;
7741             }
7742 
7743             mWifiMulticastWakelockCount--;
7744             if (mWifiMulticastWakelockCount == 0) {
7745                 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
7746             }
7747         }
7748 
7749         @Override
getWifiControllerActivity()7750         public ControllerActivityCounter getWifiControllerActivity() {
7751             return mWifiControllerActivity;
7752         }
7753 
7754         @Override
getBluetoothControllerActivity()7755         public ControllerActivityCounter getBluetoothControllerActivity() {
7756             return mBluetoothControllerActivity;
7757         }
7758 
7759         @Override
getModemControllerActivity()7760         public ControllerActivityCounter getModemControllerActivity() {
7761             return mModemControllerActivity;
7762         }
7763 
getOrCreateWifiControllerActivityLocked()7764         public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
7765             if (mWifiControllerActivity == null) {
7766                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7767                         NUM_BT_TX_LEVELS);
7768             }
7769             return mWifiControllerActivity;
7770         }
7771 
getOrCreateBluetoothControllerActivityLocked()7772         public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
7773             if (mBluetoothControllerActivity == null) {
7774                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7775                         NUM_BT_TX_LEVELS);
7776             }
7777             return mBluetoothControllerActivity;
7778         }
7779 
getOrCreateModemControllerActivityLocked()7780         public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
7781             if (mModemControllerActivity == null) {
7782                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7783                         ModemActivityInfo.getNumTxPowerLevels());
7784             }
7785             return mModemControllerActivity;
7786         }
7787 
getOrCreateMeasuredEnergyStatsLocked()7788         private MeasuredEnergyStats getOrCreateMeasuredEnergyStatsLocked() {
7789             if (mUidMeasuredEnergyStats == null) {
7790                 mUidMeasuredEnergyStats =
7791                         MeasuredEnergyStats.createFromTemplate(mBsi.mGlobalMeasuredEnergyStats);
7792             }
7793             return mUidMeasuredEnergyStats;
7794         }
7795 
7796         /** Adds the given charge to the given standard power bucket for this uid. */
addChargeToStandardBucketLocked(long chargeDeltaUC, @StandardPowerBucket int powerBucket)7797         private void addChargeToStandardBucketLocked(long chargeDeltaUC,
7798                 @StandardPowerBucket int powerBucket) {
7799             getOrCreateMeasuredEnergyStatsLocked().updateStandardBucket(powerBucket, chargeDeltaUC);
7800         }
7801 
7802         /** Adds the given charge to the given custom power bucket for this uid. */
addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket)7803         private void addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket) {
7804             getOrCreateMeasuredEnergyStatsLocked().updateCustomBucket(powerBucket, chargeDeltaUC);
7805         }
7806 
7807         /**
7808          * Returns the battery consumption (in microcoulomb) of this uid for a standard power bucket
7809          * of interest.
7810          * @param bucket standard power bucket of interest
7811          * @return consumption (in microcolombs) used by this uid for this power bucket
7812          */
getMeasuredBatteryConsumptionUC(@tandardPowerBucket int bucket)7813         public long getMeasuredBatteryConsumptionUC(@StandardPowerBucket int bucket) {
7814             if (mBsi.mGlobalMeasuredEnergyStats == null
7815                     || !mBsi.mGlobalMeasuredEnergyStats.isStandardBucketSupported(bucket)) {
7816                 return POWER_DATA_UNAVAILABLE;
7817             }
7818             if (mUidMeasuredEnergyStats == null) {
7819                 return 0L; // It is supported, but was never filled, so it must be 0
7820             }
7821             return mUidMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket);
7822         }
7823 
7824         @Override
getCustomConsumerMeasuredBatteryConsumptionUC()7825         public long[] getCustomConsumerMeasuredBatteryConsumptionUC() {
7826             if (mBsi.mGlobalMeasuredEnergyStats == null) {
7827                 return null;
7828             }
7829             if (mUidMeasuredEnergyStats == null) {
7830                 // Custom buckets may exist. But all values for this uid are 0 so we report all 0s.
7831                 return new long[mBsi.mGlobalMeasuredEnergyStats.getNumberCustomPowerBuckets()];
7832             }
7833             return mUidMeasuredEnergyStats.getAccumulatedCustomBucketCharges();
7834         }
7835 
7836         @Override
getBluetoothMeasuredBatteryConsumptionUC()7837         public long getBluetoothMeasuredBatteryConsumptionUC() {
7838             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH);
7839         }
7840 
7841         @Override
getCpuMeasuredBatteryConsumptionUC()7842         public long getCpuMeasuredBatteryConsumptionUC() {
7843             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
7844         }
7845 
7846         @Override
getGnssMeasuredBatteryConsumptionUC()7847         public long getGnssMeasuredBatteryConsumptionUC() {
7848             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_GNSS);
7849         }
7850 
7851         @Override
getMobileRadioMeasuredBatteryConsumptionUC()7852         public long getMobileRadioMeasuredBatteryConsumptionUC() {
7853             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO);
7854         }
7855 
7856         @Override
getScreenOnMeasuredBatteryConsumptionUC()7857         public long getScreenOnMeasuredBatteryConsumptionUC() {
7858             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON);
7859         }
7860 
7861         @Override
getWifiMeasuredBatteryConsumptionUC()7862         public long getWifiMeasuredBatteryConsumptionUC() {
7863             return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_WIFI);
7864         }
7865 
7866         /**
7867          * Gets the minimum of the uid's foreground activity time and its PROCESS_STATE_TOP time
7868          * since last marked. Also sets the mark time for both these timers.
7869          *
7870          * @see BatteryStatsHelper#getProcessForegroundTimeMs
7871          *
7872          * @param doCalc if true, then calculate the minimum; else don't bother and return 0. Either
7873          *               way, the mark is set.
7874          */
markProcessForegroundTimeUs(long elapsedRealtimeMs, boolean doCalc)7875         private long markProcessForegroundTimeUs(long elapsedRealtimeMs,
7876                 boolean doCalc) {
7877             long fgTimeUs = 0;
7878             final StopwatchTimer fgTimer = mForegroundActivityTimer;
7879             if (fgTimer != null) {
7880                 if (doCalc) fgTimeUs = fgTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
7881                 fgTimer.setMark(elapsedRealtimeMs);
7882             }
7883 
7884             long topTimeUs = 0;
7885             final StopwatchTimer topTimer = mProcessStateTimer[PROCESS_STATE_TOP];
7886             if (topTimer != null) {
7887                 if (doCalc) topTimeUs = topTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
7888                 topTimer.setMark(elapsedRealtimeMs);
7889             }
7890 
7891             // Return the min of the two
7892             return (topTimeUs < fgTimeUs) ? topTimeUs : fgTimeUs;
7893         }
7894 
7895 
7896         /**
7897          * Gets the uid's time spent using the GNSS since last marked. Also sets the mark time for
7898          * the GNSS timer.
7899          */
markGnssTimeUs(long elapsedRealtimeMs)7900         private long markGnssTimeUs(long elapsedRealtimeMs) {
7901             final Sensor sensor = mSensorStats.get(Sensor.GPS);
7902             if (sensor == null) {
7903                 return 0;
7904             }
7905 
7906             final StopwatchTimer timer = sensor.mTimer;
7907             if (timer == null) {
7908                 return 0;
7909             }
7910 
7911             final long gnssTimeUs = timer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
7912             timer.setMark(elapsedRealtimeMs);
7913             return gnssTimeUs;
7914         }
7915 
createAudioTurnedOnTimerLocked()7916         public StopwatchTimer createAudioTurnedOnTimerLocked() {
7917             if (mAudioTurnedOnTimer == null) {
7918                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
7919                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7920             }
7921             return mAudioTurnedOnTimer;
7922         }
7923 
noteAudioTurnedOnLocked(long elapsedRealtimeMs)7924         public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
7925             createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7926         }
7927 
noteAudioTurnedOffLocked(long elapsedRealtimeMs)7928         public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
7929             if (mAudioTurnedOnTimer != null) {
7930                 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7931             }
7932         }
7933 
noteResetAudioLocked(long elapsedRealtimeMs)7934         public void noteResetAudioLocked(long elapsedRealtimeMs) {
7935             if (mAudioTurnedOnTimer != null) {
7936                 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7937             }
7938         }
7939 
createVideoTurnedOnTimerLocked()7940         public StopwatchTimer createVideoTurnedOnTimerLocked() {
7941             if (mVideoTurnedOnTimer == null) {
7942                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
7943                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7944             }
7945             return mVideoTurnedOnTimer;
7946         }
7947 
noteVideoTurnedOnLocked(long elapsedRealtimeMs)7948         public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
7949             createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7950         }
7951 
noteVideoTurnedOffLocked(long elapsedRealtimeMs)7952         public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
7953             if (mVideoTurnedOnTimer != null) {
7954                 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7955             }
7956         }
7957 
noteResetVideoLocked(long elapsedRealtimeMs)7958         public void noteResetVideoLocked(long elapsedRealtimeMs) {
7959             if (mVideoTurnedOnTimer != null) {
7960                 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7961             }
7962         }
7963 
createFlashlightTurnedOnTimerLocked()7964         public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
7965             if (mFlashlightTurnedOnTimer == null) {
7966                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7967                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7968             }
7969             return mFlashlightTurnedOnTimer;
7970         }
7971 
noteFlashlightTurnedOnLocked(long elapsedRealtimeMs)7972         public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
7973             createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7974         }
7975 
noteFlashlightTurnedOffLocked(long elapsedRealtimeMs)7976         public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
7977             if (mFlashlightTurnedOnTimer != null) {
7978                 mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7979             }
7980         }
7981 
noteResetFlashlightLocked(long elapsedRealtimeMs)7982         public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
7983             if (mFlashlightTurnedOnTimer != null) {
7984                 mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7985             }
7986         }
7987 
createCameraTurnedOnTimerLocked()7988         public StopwatchTimer createCameraTurnedOnTimerLocked() {
7989             if (mCameraTurnedOnTimer == null) {
7990                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
7991                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7992             }
7993             return mCameraTurnedOnTimer;
7994         }
7995 
noteCameraTurnedOnLocked(long elapsedRealtimeMs)7996         public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
7997             createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7998         }
7999 
noteCameraTurnedOffLocked(long elapsedRealtimeMs)8000         public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
8001             if (mCameraTurnedOnTimer != null) {
8002                 mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
8003             }
8004         }
8005 
noteResetCameraLocked(long elapsedRealtimeMs)8006         public void noteResetCameraLocked(long elapsedRealtimeMs) {
8007             if (mCameraTurnedOnTimer != null) {
8008                 mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
8009             }
8010         }
8011 
createForegroundActivityTimerLocked()8012         public StopwatchTimer createForegroundActivityTimerLocked() {
8013             if (mForegroundActivityTimer == null) {
8014                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8015                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
8016             }
8017             return mForegroundActivityTimer;
8018         }
8019 
createForegroundServiceTimerLocked()8020         public StopwatchTimer createForegroundServiceTimerLocked() {
8021             if (mForegroundServiceTimer == null) {
8022                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8023                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase);
8024             }
8025             return mForegroundServiceTimer;
8026         }
8027 
createAggregatedPartialWakelockTimerLocked()8028         public DualTimer createAggregatedPartialWakelockTimerLocked() {
8029             if (mAggregatedPartialWakelockTimer == null) {
8030                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
8031                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
8032                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase);
8033             }
8034             return mAggregatedPartialWakelockTimer;
8035         }
8036 
createBluetoothScanTimerLocked()8037         public DualTimer createBluetoothScanTimerLocked() {
8038             if (mBluetoothScanTimer == null) {
8039                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
8040                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
8041                         mOnBatteryBackgroundTimeBase);
8042             }
8043             return mBluetoothScanTimer;
8044         }
8045 
createBluetoothUnoptimizedScanTimerLocked()8046         public DualTimer createBluetoothUnoptimizedScanTimerLocked() {
8047             if (mBluetoothUnoptimizedScanTimer == null) {
8048                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
8049                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
8050                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8051             }
8052             return mBluetoothUnoptimizedScanTimer;
8053         }
8054 
noteBluetoothScanStartedLocked(long elapsedRealtimeMs, boolean isUnoptimized)8055         public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs,
8056                 boolean isUnoptimized) {
8057             createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
8058             if (isUnoptimized) {
8059                 createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
8060             }
8061         }
8062 
noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized)8063         public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
8064             if (mBluetoothScanTimer != null) {
8065                 mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
8066             }
8067             if (isUnoptimized && mBluetoothUnoptimizedScanTimer != null) {
8068                 mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs);
8069             }
8070         }
8071 
noteResetBluetoothScanLocked(long elapsedRealtimeMs)8072         public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
8073             if (mBluetoothScanTimer != null) {
8074                 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
8075             }
8076             if (mBluetoothUnoptimizedScanTimer != null) {
8077                 mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
8078             }
8079         }
8080 
createBluetoothScanResultCounterLocked()8081         public Counter createBluetoothScanResultCounterLocked() {
8082             if (mBluetoothScanResultCounter == null) {
8083                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase);
8084             }
8085             return mBluetoothScanResultCounter;
8086         }
8087 
createBluetoothScanResultBgCounterLocked()8088         public Counter createBluetoothScanResultBgCounterLocked() {
8089             if (mBluetoothScanResultBgCounter == null) {
8090                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase);
8091             }
8092             return mBluetoothScanResultBgCounter;
8093         }
8094 
noteBluetoothScanResultsLocked(int numNewResults)8095         public void noteBluetoothScanResultsLocked(int numNewResults) {
8096             createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
8097             // Uses background timebase, so the count will only be incremented if uid in background.
8098             createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults);
8099         }
8100 
8101         @Override
noteActivityResumedLocked(long elapsedRealtimeMs)8102         public void noteActivityResumedLocked(long elapsedRealtimeMs) {
8103             // We always start, since we want multiple foreground PIDs to nest
8104             createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
8105         }
8106 
8107         @Override
noteActivityPausedLocked(long elapsedRealtimeMs)8108         public void noteActivityPausedLocked(long elapsedRealtimeMs) {
8109             if (mForegroundActivityTimer != null) {
8110                 mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
8111             }
8112         }
8113 
noteForegroundServiceResumedLocked(long elapsedRealtimeMs)8114         public void noteForegroundServiceResumedLocked(long elapsedRealtimeMs) {
8115             createForegroundServiceTimerLocked().startRunningLocked(elapsedRealtimeMs);
8116         }
8117 
noteForegroundServicePausedLocked(long elapsedRealtimeMs)8118         public void noteForegroundServicePausedLocked(long elapsedRealtimeMs) {
8119             if (mForegroundServiceTimer != null) {
8120                 mForegroundServiceTimer.stopRunningLocked(elapsedRealtimeMs);
8121             }
8122         }
8123 
createVibratorOnTimerLocked()8124         public BatchTimer createVibratorOnTimerLocked() {
8125             if (mVibratorOnTimer == null) {
8126                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
8127                         mBsi.mOnBatteryTimeBase);
8128             }
8129             return mVibratorOnTimer;
8130         }
8131 
noteVibratorOnLocked(long durationMillis, long elapsedRealtimeMs)8132         public void noteVibratorOnLocked(long durationMillis, long elapsedRealtimeMs) {
8133             createVibratorOnTimerLocked().addDuration(mBsi, durationMillis, elapsedRealtimeMs);
8134         }
8135 
noteVibratorOffLocked(long elapsedRealtimeMs)8136         public void noteVibratorOffLocked(long elapsedRealtimeMs) {
8137             if (mVibratorOnTimer != null) {
8138                 mVibratorOnTimer.abortLastDuration(mBsi, elapsedRealtimeMs);
8139             }
8140         }
8141 
8142         @Override
8143         @UnsupportedAppUsage
getWifiRunningTime(long elapsedRealtimeUs, int which)8144         public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
8145             if (mWifiRunningTimer == null) {
8146                 return 0;
8147             }
8148             return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8149         }
8150 
8151         @Override
getFullWifiLockTime(long elapsedRealtimeUs, int which)8152         public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
8153             if (mFullWifiLockTimer == null) {
8154                 return 0;
8155             }
8156             return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8157         }
8158 
8159         @Override
8160         @UnsupportedAppUsage
getWifiScanTime(long elapsedRealtimeUs, int which)8161         public long getWifiScanTime(long elapsedRealtimeUs, int which) {
8162             if (mWifiScanTimer == null) {
8163                 return 0;
8164             }
8165             return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8166         }
8167 
8168         @Override
getWifiScanCount(int which)8169         public int getWifiScanCount(int which) {
8170             if (mWifiScanTimer == null) {
8171                 return 0;
8172             }
8173             return mWifiScanTimer.getCountLocked(which);
8174         }
8175 
8176         @Override
getWifiScanTimer()8177         public Timer getWifiScanTimer() {
8178             return mWifiScanTimer;
8179         }
8180 
8181         @Override
getWifiScanBackgroundCount(int which)8182         public int getWifiScanBackgroundCount(int which) {
8183             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
8184                 return 0;
8185             }
8186             return mWifiScanTimer.getSubTimer().getCountLocked(which);
8187         }
8188 
8189         @Override
getWifiScanActualTime(final long elapsedRealtimeUs)8190         public long getWifiScanActualTime(final long elapsedRealtimeUs) {
8191             if (mWifiScanTimer == null) {
8192                 return 0;
8193             }
8194             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
8195             return mWifiScanTimer.getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
8196         }
8197 
8198         @Override
getWifiScanBackgroundTime(final long elapsedRealtimeUs)8199         public long getWifiScanBackgroundTime(final long elapsedRealtimeUs) {
8200             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
8201                 return 0;
8202             }
8203             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
8204             return mWifiScanTimer.getSubTimer().getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
8205         }
8206 
8207         @Override
getWifiScanBackgroundTimer()8208         public Timer getWifiScanBackgroundTimer() {
8209             if (mWifiScanTimer == null) {
8210                 return null;
8211             }
8212             return mWifiScanTimer.getSubTimer();
8213         }
8214 
8215         @Override
getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which)8216         public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
8217             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
8218             if (mWifiBatchedScanTimer[csphBin] == null) {
8219                 return 0;
8220             }
8221             return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
8222         }
8223 
8224         @Override
getWifiBatchedScanCount(int csphBin, int which)8225         public int getWifiBatchedScanCount(int csphBin, int which) {
8226             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
8227             if (mWifiBatchedScanTimer[csphBin] == null) {
8228                 return 0;
8229             }
8230             return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
8231         }
8232 
8233         @Override
getWifiMulticastTime(long elapsedRealtimeUs, int which)8234         public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
8235             if (mWifiMulticastTimer == null) {
8236                 return 0;
8237             }
8238             return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
8239         }
8240 
8241         @Override
getAudioTurnedOnTimer()8242         public Timer getAudioTurnedOnTimer() {
8243             return mAudioTurnedOnTimer;
8244         }
8245 
8246         @Override
getVideoTurnedOnTimer()8247         public Timer getVideoTurnedOnTimer() {
8248             return mVideoTurnedOnTimer;
8249         }
8250 
8251         @Override
getFlashlightTurnedOnTimer()8252         public Timer getFlashlightTurnedOnTimer() {
8253             return mFlashlightTurnedOnTimer;
8254         }
8255 
8256         @Override
getCameraTurnedOnTimer()8257         public Timer getCameraTurnedOnTimer() {
8258             return mCameraTurnedOnTimer;
8259         }
8260 
8261         @Override
getForegroundActivityTimer()8262         public Timer getForegroundActivityTimer() {
8263             return mForegroundActivityTimer;
8264         }
8265 
8266         @Override
getForegroundServiceTimer()8267         public Timer getForegroundServiceTimer() {
8268             return mForegroundServiceTimer;
8269         }
8270 
8271         @Override
getBluetoothScanTimer()8272         public Timer getBluetoothScanTimer() {
8273             return mBluetoothScanTimer;
8274         }
8275 
8276         @Override
getBluetoothScanBackgroundTimer()8277         public Timer getBluetoothScanBackgroundTimer() {
8278             if (mBluetoothScanTimer == null) {
8279                 return null;
8280             }
8281             return mBluetoothScanTimer.getSubTimer();
8282         }
8283 
8284         @Override
getBluetoothUnoptimizedScanTimer()8285         public Timer getBluetoothUnoptimizedScanTimer() {
8286             return mBluetoothUnoptimizedScanTimer;
8287         }
8288 
8289         @Override
getBluetoothUnoptimizedScanBackgroundTimer()8290         public Timer getBluetoothUnoptimizedScanBackgroundTimer() {
8291             if (mBluetoothUnoptimizedScanTimer == null) {
8292                 return null;
8293             }
8294             return mBluetoothUnoptimizedScanTimer.getSubTimer();
8295         }
8296 
8297         @Override
getBluetoothScanResultCounter()8298         public Counter getBluetoothScanResultCounter() {
8299             return mBluetoothScanResultCounter;
8300         }
8301 
8302         @Override
getBluetoothScanResultBgCounter()8303         public Counter getBluetoothScanResultBgCounter() {
8304             return mBluetoothScanResultBgCounter;
8305         }
8306 
makeProcessState(int i, Parcel in)8307         void makeProcessState(int i, Parcel in) {
8308             if (i < 0 || i >= NUM_PROCESS_STATE) return;
8309 
8310             detachIfNotNull(mProcessStateTimer[i]);
8311             if (in == null) {
8312                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
8313                         mBsi.mOnBatteryTimeBase);
8314             } else {
8315                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
8316                         mBsi.mOnBatteryTimeBase, in);
8317             }
8318         }
8319 
8320         @Override
getProcessStateTime(int state, long elapsedRealtimeUs, int which)8321         public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
8322             if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
8323             if (mProcessStateTimer[state] == null) {
8324                 return 0;
8325             }
8326             return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
8327         }
8328 
8329         @Override
getProcessStateTimer(int state)8330         public Timer getProcessStateTimer(int state) {
8331             if (state < 0 || state >= NUM_PROCESS_STATE) return null;
8332             return mProcessStateTimer[state];
8333         }
8334 
8335         @Override
getVibratorOnTimer()8336         public Timer getVibratorOnTimer() {
8337             return mVibratorOnTimer;
8338         }
8339 
8340         @Override
noteUserActivityLocked(int type)8341         public void noteUserActivityLocked(int type) {
8342             if (mUserActivityCounters == null) {
8343                 initUserActivityLocked();
8344             }
8345             if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
8346                 mUserActivityCounters[type].stepAtomic();
8347             } else {
8348                 Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
8349                         new Throwable());
8350             }
8351         }
8352 
8353         @Override
hasUserActivity()8354         public boolean hasUserActivity() {
8355             return mUserActivityCounters != null;
8356         }
8357 
8358         @Override
getUserActivityCount(int type, int which)8359         public int getUserActivityCount(int type, int which) {
8360             if (mUserActivityCounters == null) {
8361                 return 0;
8362             }
8363             return mUserActivityCounters[type].getCountLocked(which);
8364         }
8365 
makeWifiBatchedScanBin(int i, Parcel in)8366         void makeWifiBatchedScanBin(int i, Parcel in) {
8367             if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
8368 
8369             ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
8370             if (collected == null) {
8371                 collected = new ArrayList<StopwatchTimer>();
8372                 mBsi.mWifiBatchedScanTimers.put(i, collected);
8373             }
8374             detachIfNotNull(mWifiBatchedScanTimer[i]);
8375             if (in == null) {
8376                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
8377                         collected, mBsi.mOnBatteryTimeBase);
8378             } else {
8379                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
8380                         collected, mBsi.mOnBatteryTimeBase, in);
8381             }
8382         }
8383 
8384 
initUserActivityLocked()8385         void initUserActivityLocked() {
8386             detachIfNotNull(mUserActivityCounters);
8387             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
8388             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8389                 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
8390             }
8391         }
8392 
noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets)8393         void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
8394             if (mNetworkByteActivityCounters == null) {
8395                 initNetworkActivityLocked();
8396             }
8397             if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
8398                 mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
8399                 mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
8400             } else {
8401                 Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
8402                         new Throwable());
8403             }
8404         }
8405 
noteMobileRadioActiveTimeLocked(long batteryUptime)8406         void noteMobileRadioActiveTimeLocked(long batteryUptime) {
8407             if (mNetworkByteActivityCounters == null) {
8408                 initNetworkActivityLocked();
8409             }
8410             mMobileRadioActiveTime.addCountLocked(batteryUptime);
8411             mMobileRadioActiveCount.addCountLocked(1);
8412         }
8413 
8414         @Override
hasNetworkActivity()8415         public boolean hasNetworkActivity() {
8416             return mNetworkByteActivityCounters != null;
8417         }
8418 
8419         @Override
getNetworkActivityBytes(int type, int which)8420         public long getNetworkActivityBytes(int type, int which) {
8421             if (mNetworkByteActivityCounters != null && type >= 0
8422                     && type < mNetworkByteActivityCounters.length) {
8423                 return mNetworkByteActivityCounters[type].getCountLocked(which);
8424             } else {
8425                 return 0;
8426             }
8427         }
8428 
8429         @Override
getNetworkActivityPackets(int type, int which)8430         public long getNetworkActivityPackets(int type, int which) {
8431             if (mNetworkPacketActivityCounters != null && type >= 0
8432                     && type < mNetworkPacketActivityCounters.length) {
8433                 return mNetworkPacketActivityCounters[type].getCountLocked(which);
8434             } else {
8435                 return 0;
8436             }
8437         }
8438 
8439         @Override
getMobileRadioActiveTime(int which)8440         public long getMobileRadioActiveTime(int which) {
8441             return mMobileRadioActiveTime != null
8442                     ? mMobileRadioActiveTime.getCountLocked(which) : 0;
8443         }
8444 
8445         @Override
getMobileRadioActiveCount(int which)8446         public int getMobileRadioActiveCount(int which) {
8447             return mMobileRadioActiveCount != null
8448                     ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
8449         }
8450 
8451         @Override
getUserCpuTimeUs(int which)8452         public long getUserCpuTimeUs(int which) {
8453             return mUserCpuTime.getCountLocked(which);
8454         }
8455 
8456         @Override
getSystemCpuTimeUs(int which)8457         public long getSystemCpuTimeUs(int which) {
8458             return mSystemCpuTime.getCountLocked(which);
8459         }
8460 
8461         @Override
getTimeAtCpuSpeed(int cluster, int step, int which)8462         public long getTimeAtCpuSpeed(int cluster, int step, int which) {
8463             if (mCpuClusterSpeedTimesUs != null) {
8464                 if (cluster >= 0 && cluster < mCpuClusterSpeedTimesUs.length) {
8465                     final LongSamplingCounter[] cpuSpeedTimesUs = mCpuClusterSpeedTimesUs[cluster];
8466                     if (cpuSpeedTimesUs != null) {
8467                         if (step >= 0 && step < cpuSpeedTimesUs.length) {
8468                             final LongSamplingCounter c = cpuSpeedTimesUs[step];
8469                             if (c != null) {
8470                                 return c.getCountLocked(which);
8471                             }
8472                         }
8473                     }
8474                 }
8475             }
8476             return 0;
8477         }
8478 
noteMobileRadioApWakeupLocked()8479         public void noteMobileRadioApWakeupLocked() {
8480             if (mMobileRadioApWakeupCount == null) {
8481                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8482             }
8483             mMobileRadioApWakeupCount.addCountLocked(1);
8484         }
8485 
8486         @Override
getMobileRadioApWakeupCount(int which)8487         public long getMobileRadioApWakeupCount(int which) {
8488             if (mMobileRadioApWakeupCount != null) {
8489                 return mMobileRadioApWakeupCount.getCountLocked(which);
8490             }
8491             return 0;
8492         }
8493 
noteWifiRadioApWakeupLocked()8494         public void noteWifiRadioApWakeupLocked() {
8495             if (mWifiRadioApWakeupCount == null) {
8496                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8497             }
8498             mWifiRadioApWakeupCount.addCountLocked(1);
8499         }
8500 
8501         @Override
getWifiRadioApWakeupCount(int which)8502         public long getWifiRadioApWakeupCount(int which) {
8503             if (mWifiRadioApWakeupCount != null) {
8504                 return mWifiRadioApWakeupCount.getCountLocked(which);
8505             }
8506             return 0;
8507         }
8508 
8509         @Override
getDeferredJobsCheckinLineLocked(StringBuilder sb, int which)8510         public void getDeferredJobsCheckinLineLocked(StringBuilder sb, int which) {
8511             sb.setLength(0);
8512             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
8513             if (deferredEventCount == 0) {
8514                 return;
8515             }
8516             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
8517             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
8518             sb.append(deferredEventCount); sb.append(',');
8519             sb.append(deferredCount); sb.append(',');
8520             sb.append(totalLatency);
8521             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8522                 if (mJobsFreshnessBuckets[i] == null) {
8523                     sb.append(",0");
8524                 } else {
8525                     sb.append(",");
8526                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
8527                 }
8528             }
8529         }
8530 
8531         @Override
getDeferredJobsLineLocked(StringBuilder sb, int which)8532         public void getDeferredJobsLineLocked(StringBuilder sb, int which) {
8533             sb.setLength(0);
8534             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
8535             if (deferredEventCount == 0) {
8536                 return;
8537             }
8538             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
8539             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
8540             sb.append("times="); sb.append(deferredEventCount); sb.append(", ");
8541             sb.append("count="); sb.append(deferredCount); sb.append(", ");
8542             sb.append("totalLatencyMs="); sb.append(totalLatency); sb.append(", ");
8543             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8544                 sb.append("<"); sb.append(JOB_FRESHNESS_BUCKETS[i]); sb.append("ms=");
8545                 if (mJobsFreshnessBuckets[i] == null) {
8546                     sb.append("0");
8547                 } else {
8548                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
8549                 }
8550                 sb.append(" ");
8551             }
8552         }
8553 
initNetworkActivityLocked()8554         void initNetworkActivityLocked() {
8555             detachIfNotNull(mNetworkByteActivityCounters);
8556             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
8557             detachIfNotNull(mNetworkPacketActivityCounters);
8558             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
8559             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8560                 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8561                 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8562             }
8563             detachIfNotNull(mMobileRadioActiveTime);
8564             mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8565             detachIfNotNull(mMobileRadioActiveCount);
8566             mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
8567         }
8568 
8569         /**
8570          * Clear all stats for this uid.  Returns true if the uid is completely
8571          * inactive so can be dropped.
8572          */
8573         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
reset(long uptimeUs, long realtimeUs)8574         public boolean reset(long uptimeUs, long realtimeUs) {
8575             boolean active = false;
8576 
8577             mOnBatteryBackgroundTimeBase.init(uptimeUs, realtimeUs);
8578             mOnBatteryScreenOffBackgroundTimeBase.init(uptimeUs, realtimeUs);
8579 
8580             if (mWifiRunningTimer != null) {
8581                 active |= !mWifiRunningTimer.reset(false, realtimeUs);
8582                 active |= mWifiRunning;
8583             }
8584             if (mFullWifiLockTimer != null) {
8585                 active |= !mFullWifiLockTimer.reset(false, realtimeUs);
8586                 active |= mFullWifiLockOut;
8587             }
8588             if (mWifiScanTimer != null) {
8589                 active |= !mWifiScanTimer.reset(false, realtimeUs);
8590                 active |= mWifiScanStarted;
8591             }
8592             if (mWifiBatchedScanTimer != null) {
8593                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8594                     if (mWifiBatchedScanTimer[i] != null) {
8595                         active |= !mWifiBatchedScanTimer[i].reset(false, realtimeUs);
8596                     }
8597                 }
8598                 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
8599             }
8600             if (mWifiMulticastTimer != null) {
8601                 active |= !mWifiMulticastTimer.reset(false, realtimeUs);
8602                 active |= (mWifiMulticastWakelockCount > 0);
8603             }
8604 
8605             active |= !resetIfNotNull(mAudioTurnedOnTimer, false, realtimeUs);
8606             active |= !resetIfNotNull(mVideoTurnedOnTimer, false, realtimeUs);
8607             active |= !resetIfNotNull(mFlashlightTurnedOnTimer, false, realtimeUs);
8608             active |= !resetIfNotNull(mCameraTurnedOnTimer, false, realtimeUs);
8609             active |= !resetIfNotNull(mForegroundActivityTimer, false, realtimeUs);
8610             active |= !resetIfNotNull(mForegroundServiceTimer, false, realtimeUs);
8611             active |= !resetIfNotNull(mAggregatedPartialWakelockTimer, false, realtimeUs);
8612             active |= !resetIfNotNull(mBluetoothScanTimer, false, realtimeUs);
8613             active |= !resetIfNotNull(mBluetoothUnoptimizedScanTimer, false, realtimeUs);
8614 
8615             resetIfNotNull(mBluetoothScanResultCounter, false, realtimeUs);
8616             resetIfNotNull(mBluetoothScanResultBgCounter, false, realtimeUs);
8617 
8618             if (mProcessStateTimer != null) {
8619                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
8620                     active |= !resetIfNotNull(mProcessStateTimer[i], false, realtimeUs);
8621                 }
8622                 active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
8623             }
8624             if (mVibratorOnTimer != null) {
8625                 if (mVibratorOnTimer.reset(false, realtimeUs)) {
8626                     mVibratorOnTimer.detach();
8627                     mVibratorOnTimer = null;
8628                 } else {
8629                     active = true;
8630                 }
8631             }
8632 
8633             resetIfNotNull(mUserActivityCounters, false, realtimeUs);
8634 
8635             resetIfNotNull(mNetworkByteActivityCounters, false, realtimeUs);
8636             resetIfNotNull(mNetworkPacketActivityCounters, false, realtimeUs);
8637             resetIfNotNull(mMobileRadioActiveTime, false, realtimeUs);
8638             resetIfNotNull(mMobileRadioActiveCount, false, realtimeUs);
8639 
8640             resetIfNotNull(mWifiControllerActivity, false, realtimeUs);
8641             resetIfNotNull(mBluetoothControllerActivity, false, realtimeUs);
8642             resetIfNotNull(mModemControllerActivity, false, realtimeUs);
8643 
8644             MeasuredEnergyStats.resetIfNotNull(mUidMeasuredEnergyStats);
8645 
8646             resetIfNotNull(mUserCpuTime, false, realtimeUs);
8647             resetIfNotNull(mSystemCpuTime, false, realtimeUs);
8648 
8649             resetIfNotNull(mCpuClusterSpeedTimesUs, false, realtimeUs);
8650 
8651             resetIfNotNull(mCpuFreqTimeMs, false, realtimeUs /* unused */);
8652             resetIfNotNull(mScreenOffCpuFreqTimeMs, false, realtimeUs /* unused */);
8653 
8654 
8655             resetIfNotNull(mCpuActiveTimeMs, false, realtimeUs /* unused */);
8656             resetIfNotNull(mCpuClusterTimesMs, false, realtimeUs /* unused */);
8657 
8658             resetIfNotNull(mProcStateTimeMs, false, realtimeUs /* unused */);
8659 
8660             resetIfNotNull(mProcStateScreenOffTimeMs, false, realtimeUs /* unused */);
8661 
8662             resetIfNotNull(mMobileRadioApWakeupCount, false, realtimeUs);
8663 
8664             resetIfNotNull(mWifiRadioApWakeupCount, false, realtimeUs);
8665 
8666 
8667             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
8668             for (int iw=wakeStats.size()-1; iw>=0; iw--) {
8669                 Wakelock wl = wakeStats.valueAt(iw);
8670                 if (wl.reset(realtimeUs)) {
8671                     wakeStats.removeAt(iw);
8672                 } else {
8673                     active = true;
8674                 }
8675             }
8676             final long realtimeMs = realtimeUs / 1000;
8677             mWakelockStats.cleanup(realtimeMs);
8678             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
8679             for (int is=syncStats.size()-1; is>=0; is--) {
8680                 DualTimer timer = syncStats.valueAt(is);
8681                 if (timer.reset(false, realtimeUs)) {
8682                     syncStats.removeAt(is);
8683                     timer.detach();
8684                 } else {
8685                     active = true;
8686                 }
8687             }
8688             mSyncStats.cleanup(realtimeMs);
8689             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
8690             for (int ij=jobStats.size()-1; ij>=0; ij--) {
8691                 DualTimer timer = jobStats.valueAt(ij);
8692                 if (timer.reset(false, realtimeUs)) {
8693                     jobStats.removeAt(ij);
8694                     timer.detach();
8695                 } else {
8696                     active = true;
8697                 }
8698             }
8699             mJobStats.cleanup(realtimeMs);
8700             mJobCompletions.clear();
8701 
8702             resetIfNotNull(mJobsDeferredEventCount, false, realtimeUs);
8703             resetIfNotNull(mJobsDeferredCount, false, realtimeUs);
8704             resetIfNotNull(mJobsFreshnessTimeMs, false, realtimeUs /* unused */);
8705             resetIfNotNull(mJobsFreshnessBuckets, false, realtimeUs);
8706 
8707             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
8708                 Sensor s = mSensorStats.valueAt(ise);
8709                 if (s.reset(realtimeUs)) {
8710                     mSensorStats.removeAt(ise);
8711                 } else {
8712                     active = true;
8713                 }
8714             }
8715 
8716             for (int ip = mProcessStats.size() - 1; ip >= 0; ip--) {
8717                 Proc proc = mProcessStats.valueAt(ip);
8718                 proc.detach();
8719             }
8720             mProcessStats.clear();
8721 
8722             for (int i = mPids.size() - 1; i >= 0; i--) {
8723                 Pid pid = mPids.valueAt(i);
8724                 if (pid.mWakeNesting > 0) {
8725                     active = true;
8726                 } else {
8727                     mPids.removeAt(i);
8728                 }
8729             }
8730 
8731 
8732             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
8733                 Pkg p = mPackageStats.valueAt(i);
8734                 p.detach();
8735             }
8736             mPackageStats.clear();
8737 
8738             mBinderCallCount = 0;
8739             mBinderCallStats.clear();
8740 
8741             mProportionalSystemServiceUsage = 0;
8742 
8743             mLastStepUserTimeMs = mLastStepSystemTimeMs = 0;
8744             mCurStepUserTimeMs = mCurStepSystemTimeMs = 0;
8745 
8746 
8747             return !active;
8748         }
8749 
8750         /**
8751          * This method MUST be called whenever the Uid object is destructed, otherwise it is a
8752          * memory leak in {@link TimeBase#mObservers} list.
8753          * Typically the Uid object is destructed when it is removed from
8754          * {@link BatteryStatsImpl#mUidStats}
8755          */
detachFromTimeBase()8756         void detachFromTimeBase() {
8757             detachIfNotNull(mWifiRunningTimer);
8758             detachIfNotNull(mFullWifiLockTimer);
8759             detachIfNotNull(mWifiScanTimer);
8760             detachIfNotNull(mWifiBatchedScanTimer);
8761             detachIfNotNull(mWifiMulticastTimer);
8762             detachIfNotNull(mAudioTurnedOnTimer);
8763             detachIfNotNull(mVideoTurnedOnTimer);
8764             detachIfNotNull(mFlashlightTurnedOnTimer);
8765 
8766             detachIfNotNull(mCameraTurnedOnTimer);
8767             detachIfNotNull(mForegroundActivityTimer);
8768             detachIfNotNull(mForegroundServiceTimer);
8769 
8770             detachIfNotNull(mAggregatedPartialWakelockTimer);
8771 
8772             detachIfNotNull(mBluetoothScanTimer);
8773             detachIfNotNull(mBluetoothUnoptimizedScanTimer);
8774             detachIfNotNull(mBluetoothScanResultCounter);
8775             detachIfNotNull(mBluetoothScanResultBgCounter);
8776 
8777             detachIfNotNull(mProcessStateTimer);
8778 
8779             detachIfNotNull(mVibratorOnTimer);
8780 
8781             detachIfNotNull(mUserActivityCounters);
8782 
8783             detachIfNotNull(mNetworkByteActivityCounters);
8784             detachIfNotNull(mNetworkPacketActivityCounters);
8785 
8786             detachIfNotNull(mMobileRadioActiveTime);
8787             detachIfNotNull(mMobileRadioActiveCount);
8788             detachIfNotNull(mMobileRadioApWakeupCount);
8789             detachIfNotNull(mWifiRadioApWakeupCount);
8790 
8791             detachIfNotNull(mWifiControllerActivity);
8792             detachIfNotNull(mBluetoothControllerActivity);
8793             detachIfNotNull(mModemControllerActivity);
8794 
8795             mPids.clear();
8796 
8797             detachIfNotNull(mUserCpuTime);
8798             detachIfNotNull(mSystemCpuTime);
8799 
8800             detachIfNotNull(mCpuClusterSpeedTimesUs);
8801 
8802             detachIfNotNull(mCpuActiveTimeMs);
8803             detachIfNotNull(mCpuFreqTimeMs);
8804 
8805             detachIfNotNull(mScreenOffCpuFreqTimeMs);
8806 
8807             detachIfNotNull(mCpuClusterTimesMs);
8808 
8809             detachIfNotNull(mProcStateTimeMs);
8810 
8811             detachIfNotNull(mProcStateScreenOffTimeMs);
8812 
8813             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
8814             for (int iw = wakeStats.size() - 1; iw >= 0; iw--) {
8815                 Wakelock wl = wakeStats.valueAt(iw);
8816                 wl.detachFromTimeBase();
8817             }
8818             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
8819             for (int is = syncStats.size() - 1; is >= 0; is--) {
8820                 DualTimer timer = syncStats.valueAt(is);
8821                 detachIfNotNull(timer);
8822             }
8823             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
8824             for (int ij = jobStats.size() - 1; ij >= 0; ij--) {
8825                 DualTimer timer = jobStats.valueAt(ij);
8826                 detachIfNotNull(timer);
8827             }
8828 
8829             detachIfNotNull(mJobsDeferredEventCount);
8830             detachIfNotNull(mJobsDeferredCount);
8831             detachIfNotNull(mJobsFreshnessTimeMs);
8832             detachIfNotNull(mJobsFreshnessBuckets);
8833 
8834 
8835             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
8836                 Sensor s = mSensorStats.valueAt(ise);
8837                 s.detachFromTimeBase();
8838             }
8839 
8840             for (int ip= mProcessStats.size() - 1; ip >= 0; ip--) {
8841                 Proc proc = mProcessStats.valueAt(ip);
8842                 proc.detach();
8843             }
8844             mProcessStats.clear();
8845 
8846             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
8847                 Pkg p = mPackageStats.valueAt(i);
8848                 p.detach();
8849             }
8850             mPackageStats.clear();
8851         }
8852 
writeJobCompletionsToParcelLocked(Parcel out)8853         void writeJobCompletionsToParcelLocked(Parcel out) {
8854             int NJC = mJobCompletions.size();
8855             out.writeInt(NJC);
8856             for (int ijc=0; ijc<NJC; ijc++) {
8857                 out.writeString(mJobCompletions.keyAt(ijc));
8858                 SparseIntArray types = mJobCompletions.valueAt(ijc);
8859                 int NT = types.size();
8860                 out.writeInt(NT);
8861                 for (int it=0; it<NT; it++) {
8862                     out.writeInt(types.keyAt(it));
8863                     out.writeInt(types.valueAt(it));
8864                 }
8865             }
8866         }
8867 
writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs)8868         void writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
8869             mOnBatteryBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
8870             mOnBatteryScreenOffBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
8871 
8872             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
8873             int NW = wakeStats.size();
8874             out.writeInt(NW);
8875             for (int iw=0; iw<NW; iw++) {
8876                 out.writeString(wakeStats.keyAt(iw));
8877                 Uid.Wakelock wakelock = wakeStats.valueAt(iw);
8878                 wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
8879             }
8880 
8881             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
8882             int NS = syncStats.size();
8883             out.writeInt(NS);
8884             for (int is=0; is<NS; is++) {
8885                 out.writeString(syncStats.keyAt(is));
8886                 DualTimer timer = syncStats.valueAt(is);
8887                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
8888             }
8889 
8890             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
8891             int NJ = jobStats.size();
8892             out.writeInt(NJ);
8893             for (int ij=0; ij<NJ; ij++) {
8894                 out.writeString(jobStats.keyAt(ij));
8895                 DualTimer timer = jobStats.valueAt(ij);
8896                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
8897             }
8898 
8899             writeJobCompletionsToParcelLocked(out);
8900 
8901             mJobsDeferredEventCount.writeToParcel(out);
8902             mJobsDeferredCount.writeToParcel(out);
8903             mJobsFreshnessTimeMs.writeToParcel(out);
8904             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8905                 Counter.writeCounterToParcel(out, mJobsFreshnessBuckets[i]);
8906             }
8907 
8908             int NSE = mSensorStats.size();
8909             out.writeInt(NSE);
8910             for (int ise=0; ise<NSE; ise++) {
8911                 out.writeInt(mSensorStats.keyAt(ise));
8912                 Uid.Sensor sensor = mSensorStats.valueAt(ise);
8913                 sensor.writeToParcelLocked(out, elapsedRealtimeUs);
8914             }
8915 
8916             int NP = mProcessStats.size();
8917             out.writeInt(NP);
8918             for (int ip=0; ip<NP; ip++) {
8919                 out.writeString(mProcessStats.keyAt(ip));
8920                 Uid.Proc proc = mProcessStats.valueAt(ip);
8921                 proc.writeToParcelLocked(out);
8922             }
8923 
8924             out.writeInt(mPackageStats.size());
8925             for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
8926                 out.writeString(pkgEntry.getKey());
8927                 Uid.Pkg pkg = pkgEntry.getValue();
8928                 pkg.writeToParcelLocked(out);
8929             }
8930 
8931             if (mWifiRunningTimer != null) {
8932                 out.writeInt(1);
8933                 mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
8934             } else {
8935                 out.writeInt(0);
8936             }
8937             if (mFullWifiLockTimer != null) {
8938                 out.writeInt(1);
8939                 mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
8940             } else {
8941                 out.writeInt(0);
8942             }
8943             if (mWifiScanTimer != null) {
8944                 out.writeInt(1);
8945                 mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
8946             } else {
8947                 out.writeInt(0);
8948             }
8949             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8950                 if (mWifiBatchedScanTimer[i] != null) {
8951                     out.writeInt(1);
8952                     mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
8953                 } else {
8954                     out.writeInt(0);
8955                 }
8956             }
8957             if (mWifiMulticastTimer != null) {
8958                 out.writeInt(1);
8959                 mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
8960             } else {
8961                 out.writeInt(0);
8962             }
8963 
8964             if (mAudioTurnedOnTimer != null) {
8965                 out.writeInt(1);
8966                 mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8967             } else {
8968                 out.writeInt(0);
8969             }
8970             if (mVideoTurnedOnTimer != null) {
8971                 out.writeInt(1);
8972                 mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8973             } else {
8974                 out.writeInt(0);
8975             }
8976             if (mFlashlightTurnedOnTimer != null) {
8977                 out.writeInt(1);
8978                 mFlashlightTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8979             } else {
8980                 out.writeInt(0);
8981             }
8982             if (mCameraTurnedOnTimer != null) {
8983                 out.writeInt(1);
8984                 mCameraTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8985             } else {
8986                 out.writeInt(0);
8987             }
8988             if (mForegroundActivityTimer != null) {
8989                 out.writeInt(1);
8990                 mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
8991             } else {
8992                 out.writeInt(0);
8993             }
8994             if (mForegroundServiceTimer != null) {
8995                 out.writeInt(1);
8996                 mForegroundServiceTimer.writeToParcel(out, elapsedRealtimeUs);
8997             } else {
8998                 out.writeInt(0);
8999             }
9000             if (mAggregatedPartialWakelockTimer != null) {
9001                 out.writeInt(1);
9002                 mAggregatedPartialWakelockTimer.writeToParcel(out, elapsedRealtimeUs);
9003             } else {
9004                 out.writeInt(0);
9005             }
9006             if (mBluetoothScanTimer != null) {
9007                 out.writeInt(1);
9008                 mBluetoothScanTimer.writeToParcel(out, elapsedRealtimeUs);
9009             } else {
9010                 out.writeInt(0);
9011             }
9012             if (mBluetoothUnoptimizedScanTimer != null) {
9013                 out.writeInt(1);
9014                 mBluetoothUnoptimizedScanTimer.writeToParcel(out, elapsedRealtimeUs);
9015             } else {
9016                 out.writeInt(0);
9017             }
9018             if (mBluetoothScanResultCounter != null) {
9019                 out.writeInt(1);
9020                 mBluetoothScanResultCounter.writeToParcel(out);
9021             } else {
9022                 out.writeInt(0);
9023             }
9024             if (mBluetoothScanResultBgCounter != null) {
9025                 out.writeInt(1);
9026                 mBluetoothScanResultBgCounter.writeToParcel(out);
9027             } else {
9028                 out.writeInt(0);
9029             }
9030             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
9031                 if (mProcessStateTimer[i] != null) {
9032                     out.writeInt(1);
9033                     mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
9034                 } else {
9035                     out.writeInt(0);
9036                 }
9037             }
9038             if (mVibratorOnTimer != null) {
9039                 out.writeInt(1);
9040                 mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
9041             } else {
9042                 out.writeInt(0);
9043             }
9044             if (mUserActivityCounters != null) {
9045                 out.writeInt(1);
9046                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
9047                     mUserActivityCounters[i].writeToParcel(out);
9048                 }
9049             } else {
9050                 out.writeInt(0);
9051             }
9052             if (mNetworkByteActivityCounters != null) {
9053                 out.writeInt(1);
9054                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9055                     mNetworkByteActivityCounters[i].writeToParcel(out);
9056                     mNetworkPacketActivityCounters[i].writeToParcel(out);
9057                 }
9058                 mMobileRadioActiveTime.writeToParcel(out);
9059                 mMobileRadioActiveCount.writeToParcel(out);
9060             } else {
9061                 out.writeInt(0);
9062             }
9063 
9064             if (mWifiControllerActivity != null) {
9065                 out.writeInt(1);
9066                 mWifiControllerActivity.writeToParcel(out, 0);
9067             } else {
9068                 out.writeInt(0);
9069             }
9070 
9071             if (mBluetoothControllerActivity != null) {
9072                 out.writeInt(1);
9073                 mBluetoothControllerActivity.writeToParcel(out, 0);
9074             } else {
9075                 out.writeInt(0);
9076             }
9077 
9078             if (mModemControllerActivity != null) {
9079                 out.writeInt(1);
9080                 mModemControllerActivity.writeToParcel(out, 0);
9081             } else {
9082                 out.writeInt(0);
9083             }
9084 
9085             if (mUidMeasuredEnergyStats != null) {
9086                 out.writeInt(1);
9087                 mUidMeasuredEnergyStats.writeToParcel(out);
9088             } else {
9089                 out.writeInt(0);
9090             }
9091 
9092             mUserCpuTime.writeToParcel(out);
9093             mSystemCpuTime.writeToParcel(out);
9094 
9095             mBsi.writeCpuSpeedCountersToParcel(out, mCpuClusterSpeedTimesUs);
9096 
9097             LongSamplingCounterArray.writeToParcel(out, mCpuFreqTimeMs);
9098             LongSamplingCounterArray.writeToParcel(out, mScreenOffCpuFreqTimeMs);
9099 
9100             mCpuActiveTimeMs.writeToParcel(out);
9101             mCpuClusterTimesMs.writeToParcel(out);
9102 
9103             if (mProcStateTimeMs != null) {
9104                 out.writeInt(mProcStateTimeMs.length);
9105                 for (LongSamplingCounterArray counters : mProcStateTimeMs) {
9106                     LongSamplingCounterArray.writeToParcel(out, counters);
9107                 }
9108             } else {
9109                 out.writeInt(0);
9110             }
9111             if (mProcStateScreenOffTimeMs != null) {
9112                 out.writeInt(mProcStateScreenOffTimeMs.length);
9113                 for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
9114                     LongSamplingCounterArray.writeToParcel(out, counters);
9115                 }
9116             } else {
9117                 out.writeInt(0);
9118             }
9119 
9120             if (mMobileRadioApWakeupCount != null) {
9121                 out.writeInt(1);
9122                 mMobileRadioApWakeupCount.writeToParcel(out);
9123             } else {
9124                 out.writeInt(0);
9125             }
9126 
9127             if (mWifiRadioApWakeupCount != null) {
9128                 out.writeInt(1);
9129                 mWifiRadioApWakeupCount.writeToParcel(out);
9130             } else {
9131                 out.writeInt(0);
9132             }
9133             out.writeDouble(mProportionalSystemServiceUsage);
9134         }
9135 
readJobCompletionsFromParcelLocked(Parcel in)9136         void readJobCompletionsFromParcelLocked(Parcel in) {
9137             int numJobCompletions = in.readInt();
9138             mJobCompletions.clear();
9139             for (int j = 0; j < numJobCompletions; j++) {
9140                 String jobName = in.readString();
9141                 int numTypes = in.readInt();
9142                 if (numTypes > 0) {
9143                     SparseIntArray types = new SparseIntArray();
9144                     for (int k = 0; k < numTypes; k++) {
9145                         int type = in.readInt();
9146                         int count = in.readInt();
9147                         types.put(type, count);
9148                     }
9149                     mJobCompletions.put(jobName, types);
9150                 }
9151             }
9152         }
9153 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in)9154         void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
9155             mOnBatteryBackgroundTimeBase.readFromParcel(in);
9156             mOnBatteryScreenOffBackgroundTimeBase.readFromParcel(in);
9157 
9158             int numWakelocks = in.readInt();
9159             mWakelockStats.clear();
9160             for (int j = 0; j < numWakelocks; j++) {
9161                 String wakelockName = in.readString();
9162                 Uid.Wakelock wakelock = new Wakelock(mBsi, this);
9163                 wakelock.readFromParcelLocked(
9164                         timeBase, screenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase, in);
9165                 mWakelockStats.add(wakelockName, wakelock);
9166             }
9167 
9168             int numSyncs = in.readInt();
9169             mSyncStats.clear();
9170             for (int j = 0; j < numSyncs; j++) {
9171                 String syncName = in.readString();
9172                 if (in.readInt() != 0) {
9173                     mSyncStats.add(syncName, new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
9174                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
9175                 }
9176             }
9177 
9178             int numJobs = in.readInt();
9179             mJobStats.clear();
9180             for (int j = 0; j < numJobs; j++) {
9181                 String jobName = in.readString();
9182                 if (in.readInt() != 0) {
9183                     mJobStats.add(jobName, new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
9184                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
9185                 }
9186             }
9187 
9188             readJobCompletionsFromParcelLocked(in);
9189 
9190             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase, in);
9191             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase, in);
9192             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9193             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
9194                 mJobsFreshnessBuckets[i] = Counter.readCounterFromParcel(mBsi.mOnBatteryTimeBase,
9195                         in);
9196             }
9197 
9198             int numSensors = in.readInt();
9199             mSensorStats.clear();
9200             for (int k = 0; k < numSensors; k++) {
9201                 int sensorNumber = in.readInt();
9202                 Uid.Sensor sensor = new Sensor(mBsi, this, sensorNumber);
9203                 sensor.readFromParcelLocked(mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
9204                         in);
9205                 mSensorStats.put(sensorNumber, sensor);
9206             }
9207 
9208             int numProcs = in.readInt();
9209             mProcessStats.clear();
9210             for (int k = 0; k < numProcs; k++) {
9211                 String processName = in.readString();
9212                 Uid.Proc proc = new Proc(mBsi, processName);
9213                 proc.readFromParcelLocked(in);
9214                 mProcessStats.put(processName, proc);
9215             }
9216 
9217             int numPkgs = in.readInt();
9218             mPackageStats.clear();
9219             for (int l = 0; l < numPkgs; l++) {
9220                 String packageName = in.readString();
9221                 Uid.Pkg pkg = new Pkg(mBsi);
9222                 pkg.readFromParcelLocked(in);
9223                 mPackageStats.put(packageName, pkg);
9224             }
9225 
9226             mWifiRunning = false;
9227             if (in.readInt() != 0) {
9228                 mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
9229                         mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase, in);
9230             } else {
9231                 mWifiRunningTimer = null;
9232             }
9233             mFullWifiLockOut = false;
9234             if (in.readInt() != 0) {
9235                 mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
9236                         mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase, in);
9237             } else {
9238                 mFullWifiLockTimer = null;
9239             }
9240             mWifiScanStarted = false;
9241             if (in.readInt() != 0) {
9242                 mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
9243                         mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
9244                         in);
9245             } else {
9246                 mWifiScanTimer = null;
9247             }
9248             mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
9249             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
9250                 if (in.readInt() != 0) {
9251                     makeWifiBatchedScanBin(i, in);
9252                 } else {
9253                     mWifiBatchedScanTimer[i] = null;
9254                 }
9255             }
9256             mWifiMulticastWakelockCount = 0;
9257             if (in.readInt() != 0) {
9258                 mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_MULTICAST_ENABLED,
9259                         mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase, in);
9260             } else {
9261                 mWifiMulticastTimer = null;
9262             }
9263             if (in.readInt() != 0) {
9264                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
9265                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
9266             } else {
9267                 mAudioTurnedOnTimer = null;
9268             }
9269             if (in.readInt() != 0) {
9270                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
9271                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
9272             } else {
9273                 mVideoTurnedOnTimer = null;
9274             }
9275             if (in.readInt() != 0) {
9276                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
9277                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
9278             } else {
9279                 mFlashlightTurnedOnTimer = null;
9280             }
9281             if (in.readInt() != 0) {
9282                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
9283                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
9284             } else {
9285                 mCameraTurnedOnTimer = null;
9286             }
9287             if (in.readInt() != 0) {
9288                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
9289                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase, in);
9290             } else {
9291                 mForegroundActivityTimer = null;
9292             }
9293             if (in.readInt() != 0) {
9294                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
9295                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase, in);
9296             } else {
9297                 mForegroundServiceTimer = null;
9298             }
9299             if (in.readInt() != 0) {
9300                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
9301                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
9302                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase,
9303                         in);
9304             } else {
9305                 mAggregatedPartialWakelockTimer = null;
9306             }
9307             if (in.readInt() != 0) {
9308                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
9309                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
9310                         mOnBatteryBackgroundTimeBase, in);
9311             } else {
9312                 mBluetoothScanTimer = null;
9313             }
9314             if (in.readInt() != 0) {
9315                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
9316                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
9317                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in);
9318             } else {
9319                 mBluetoothUnoptimizedScanTimer = null;
9320             }
9321             if (in.readInt() != 0) {
9322                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase, in);
9323             } else {
9324                 mBluetoothScanResultCounter = null;
9325             }
9326             if (in.readInt() != 0) {
9327                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase, in);
9328             } else {
9329                 mBluetoothScanResultBgCounter = null;
9330             }
9331             mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
9332             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
9333                 if (in.readInt() != 0) {
9334                     makeProcessState(i, in);
9335                 } else {
9336                     mProcessStateTimer[i] = null;
9337                 }
9338             }
9339             if (in.readInt() != 0) {
9340                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
9341                         mBsi.mOnBatteryTimeBase, in);
9342             } else {
9343                 mVibratorOnTimer = null;
9344             }
9345             if (in.readInt() != 0) {
9346                 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
9347                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
9348                     mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase, in);
9349                 }
9350             } else {
9351                 mUserActivityCounters = null;
9352             }
9353             if (in.readInt() != 0) {
9354                 mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
9355                 mNetworkPacketActivityCounters
9356                         = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
9357                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9358                     mNetworkByteActivityCounters[i]
9359                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9360                     mNetworkPacketActivityCounters[i]
9361                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9362                 }
9363                 mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9364                 mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9365             } else {
9366                 mNetworkByteActivityCounters = null;
9367                 mNetworkPacketActivityCounters = null;
9368             }
9369 
9370             if (in.readInt() != 0) {
9371                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
9372                         NUM_WIFI_TX_LEVELS, in);
9373             } else {
9374                 mWifiControllerActivity = null;
9375             }
9376 
9377             if (in.readInt() != 0) {
9378                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
9379                         NUM_BT_TX_LEVELS, in);
9380             } else {
9381                 mBluetoothControllerActivity = null;
9382             }
9383 
9384             if (in.readInt() != 0) {
9385                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
9386                         ModemActivityInfo.getNumTxPowerLevels(), in);
9387             } else {
9388                 mModemControllerActivity = null;
9389             }
9390 
9391             if (in.readInt() != 0) {
9392                 mUidMeasuredEnergyStats = new MeasuredEnergyStats(in);
9393             }
9394 
9395             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9396             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9397 
9398             mCpuClusterSpeedTimesUs = mBsi.readCpuSpeedCountersFromParcel(in);
9399 
9400             mCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(in, mBsi.mOnBatteryTimeBase);
9401             mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(
9402                     in, mBsi.mOnBatteryScreenOffTimeBase);
9403 
9404             mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9405             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
9406 
9407             int length = in.readInt();
9408             if (length == NUM_PROCESS_STATE) {
9409                 mProcStateTimeMs = new LongSamplingCounterArray[length];
9410                 for (int procState = 0; procState < length; ++procState) {
9411                     mProcStateTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
9412                             in, mBsi.mOnBatteryTimeBase);
9413                 }
9414             } else {
9415                 mProcStateTimeMs = null;
9416             }
9417             length = in.readInt();
9418             if (length == NUM_PROCESS_STATE) {
9419                 mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
9420                 for (int procState = 0; procState < length; ++procState) {
9421                     mProcStateScreenOffTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
9422                             in, mBsi.mOnBatteryScreenOffTimeBase);
9423                 }
9424             } else {
9425                 mProcStateScreenOffTimeMs = null;
9426             }
9427 
9428             if (in.readInt() != 0) {
9429                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9430             } else {
9431                 mMobileRadioApWakeupCount = null;
9432             }
9433 
9434             if (in.readInt() != 0) {
9435                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
9436             } else {
9437                 mWifiRadioApWakeupCount = null;
9438             }
9439 
9440             mProportionalSystemServiceUsage = in.readDouble();
9441         }
9442 
noteJobsDeferredLocked(int numDeferred, long sinceLast)9443         public void noteJobsDeferredLocked(int numDeferred, long sinceLast) {
9444             mJobsDeferredEventCount.addAtomic(1);
9445             mJobsDeferredCount.addAtomic(numDeferred);
9446             if (sinceLast != 0) {
9447                 // Add the total time, which can be divided by the event count to get an average
9448                 mJobsFreshnessTimeMs.addCountLocked(sinceLast);
9449                 // Also keep track of how many times there were in these different buckets.
9450                 for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
9451                     if (sinceLast < JOB_FRESHNESS_BUCKETS[i]) {
9452                         if (mJobsFreshnessBuckets[i] == null) {
9453                             mJobsFreshnessBuckets[i] = new Counter(
9454                                     mBsi.mOnBatteryTimeBase);
9455                         }
9456                         mJobsFreshnessBuckets[i].addAtomic(1);
9457                         break;
9458                     }
9459                 }
9460             }
9461         }
9462 
9463         // Reusable object used as a key to lookup values in mBinderCallStats
9464         private static BinderCallStats sTempBinderCallStats = new BinderCallStats();
9465 
9466         /**
9467          * Notes incoming binder call stats associated with this work source UID.
9468          */
noteBinderCallStatsLocked(long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats)9469         public void noteBinderCallStatsLocked(long incrementalCallCount,
9470                 Collection<BinderCallsStats.CallStat> callStats) {
9471             if (DEBUG) {
9472                 Slog.d(TAG, "noteBinderCalls() workSourceUid = [" + mUid + "], "
9473                         + " incrementalCallCount: " + incrementalCallCount + " callStats = ["
9474                         + new ArrayList<>(callStats) + "]");
9475             }
9476             mBinderCallCount += incrementalCallCount;
9477             for (BinderCallsStats.CallStat stat : callStats) {
9478                 BinderCallStats bcs;
9479                 sTempBinderCallStats.binderClass = stat.binderClass;
9480                 sTempBinderCallStats.transactionCode = stat.transactionCode;
9481                 int index = mBinderCallStats.indexOf(sTempBinderCallStats);
9482                 if (index >= 0) {
9483                     bcs = mBinderCallStats.valueAt(index);
9484                 } else {
9485                     bcs = new BinderCallStats();
9486                     bcs.binderClass = stat.binderClass;
9487                     bcs.transactionCode = stat.transactionCode;
9488                     mBinderCallStats.add(bcs);
9489                 }
9490 
9491                 bcs.callCount += stat.incrementalCallCount;
9492                 bcs.recordedCallCount = stat.recordedCallCount;
9493                 bcs.recordedCpuTimeMicros = stat.cpuTimeMicros;
9494             }
9495         }
9496 
9497         /**
9498          * The statistics associated with a particular wake lock.
9499          */
9500         public static class Wakelock extends BatteryStats.Uid.Wakelock {
9501             /**
9502              * BatteryStatsImpl that we are associated with.
9503              */
9504             protected BatteryStatsImpl mBsi;
9505 
9506             /**
9507              * BatteryStatsImpl that we are associated with.
9508              */
9509             protected Uid mUid;
9510 
9511             /**
9512              * How long (in ms) this uid has been keeping the device partially awake.
9513              * Tracks both the total time and the time while the app was in the background.
9514              */
9515             DualTimer mTimerPartial;
9516 
9517             /**
9518              * How long (in ms) this uid has been keeping the device fully awake.
9519              */
9520             StopwatchTimer mTimerFull;
9521 
9522             /**
9523              * How long (in ms) this uid has had a window keeping the device awake.
9524              */
9525             StopwatchTimer mTimerWindow;
9526 
9527             /**
9528              * How long (in ms) this uid has had a draw wake lock.
9529              */
9530             StopwatchTimer mTimerDraw;
9531 
Wakelock(BatteryStatsImpl bsi, Uid uid)9532             public Wakelock(BatteryStatsImpl bsi, Uid uid) {
9533                 mBsi = bsi;
9534                 mUid = uid;
9535             }
9536 
9537             /**
9538              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
9539              * proper timer pool from the given BatteryStatsImpl object.
9540              *
9541              * @param in the Parcel to be read from.
9542              * return a new Timer, or null.
9543              */
readStopwatchTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in)9544             private StopwatchTimer readStopwatchTimerFromParcel(int type,
9545                     ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
9546                 if (in.readInt() == 0) {
9547                     return null;
9548                 }
9549 
9550                 return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
9551             }
9552 
9553             /**
9554              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
9555              * proper timer pool from the given BatteryStatsImpl object.
9556              *
9557              * @param in the Parcel to be read from.
9558              * return a new Timer, or null.
9559              */
readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, TimeBase bgTimeBase, Parcel in)9560             private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
9561                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
9562                 if (in.readInt() == 0) {
9563                     return null;
9564                 }
9565 
9566                 return new DualTimer(mBsi.mClocks, mUid, type, pool, timeBase, bgTimeBase, in);
9567             }
9568 
reset(long elapsedRealtimeUs)9569             boolean reset(long elapsedRealtimeUs) {
9570                 boolean wlactive = false;
9571 
9572                 wlactive |= !resetIfNotNull(mTimerFull, false, elapsedRealtimeUs);
9573                 wlactive |= !resetIfNotNull(mTimerPartial, false, elapsedRealtimeUs);
9574                 wlactive |= !resetIfNotNull(mTimerWindow, false, elapsedRealtimeUs);
9575                 wlactive |= !resetIfNotNull(mTimerDraw, false, elapsedRealtimeUs);
9576 
9577                 if (!wlactive) {
9578                     detachIfNotNull(mTimerFull);
9579                     mTimerFull = null;
9580 
9581                     detachIfNotNull(mTimerPartial);
9582                     mTimerPartial = null;
9583 
9584                     detachIfNotNull(mTimerWindow);
9585                     mTimerWindow = null;
9586 
9587                     detachIfNotNull(mTimerDraw);
9588                     mTimerDraw = null;
9589                 }
9590                 return !wlactive;
9591             }
9592 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, TimeBase screenOffBgTimeBase, Parcel in)9593             void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase,
9594                     TimeBase screenOffBgTimeBase, Parcel in) {
9595                 mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL,
9596                         mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in);
9597                 mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
9598                         mBsi.mFullTimers, timeBase, in);
9599                 mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
9600                         mBsi.mWindowTimers, timeBase, in);
9601                 mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
9602                         mBsi.mDrawTimers, timeBase, in);
9603             }
9604 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)9605             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
9606                 Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
9607                 Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
9608                 Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
9609                 Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
9610             }
9611 
9612             @Override
9613             @UnsupportedAppUsage
getWakeTime(int type)9614             public Timer getWakeTime(int type) {
9615                 switch (type) {
9616                 case WAKE_TYPE_FULL: return mTimerFull;
9617                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
9618                 case WAKE_TYPE_WINDOW: return mTimerWindow;
9619                 case WAKE_TYPE_DRAW: return mTimerDraw;
9620                 default: throw new IllegalArgumentException("type = " + type);
9621                 }
9622             }
9623 
detachFromTimeBase()9624             public void detachFromTimeBase() {
9625                 detachIfNotNull(mTimerPartial);
9626                 detachIfNotNull(mTimerFull);
9627                 detachIfNotNull(mTimerWindow);
9628                 detachIfNotNull(mTimerDraw);
9629             }
9630         }
9631 
9632         public static class Sensor extends BatteryStats.Uid.Sensor {
9633             /**
9634              * BatteryStatsImpl that we are associated with.
9635              */
9636             protected BatteryStatsImpl mBsi;
9637 
9638             /**
9639              * Uid that we are associated with.
9640              */
9641             protected Uid mUid;
9642 
9643             final int mHandle;
9644             DualTimer mTimer;
9645 
Sensor(BatteryStatsImpl bsi, Uid uid, int handle)9646             public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
9647                 mBsi = bsi;
9648                 mUid = uid;
9649                 mHandle = handle;
9650             }
9651 
readTimersFromParcel( TimeBase timeBase, TimeBase bgTimeBase, Parcel in)9652             private DualTimer readTimersFromParcel(
9653                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
9654                 if (in.readInt() == 0) {
9655                     return null;
9656                 }
9657 
9658                 ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
9659                 if (pool == null) {
9660                     pool = new ArrayList<StopwatchTimer>();
9661                     mBsi.mSensorTimers.put(mHandle, pool);
9662                 }
9663                 return new DualTimer(mBsi.mClocks, mUid, 0, pool, timeBase, bgTimeBase, in);
9664             }
9665 
reset(long elapsedRealtimeUs)9666             boolean reset(long elapsedRealtimeUs) {
9667                 if (mTimer.reset(true, elapsedRealtimeUs)) {
9668                     mTimer = null;
9669                     return true;
9670                 }
9671                 return false;
9672             }
9673 
readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in)9674             void readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
9675                 mTimer = readTimersFromParcel(timeBase, bgTimeBase, in);
9676             }
9677 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)9678             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
9679                 Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
9680             }
9681 
9682             @Override
9683             @UnsupportedAppUsage
getSensorTime()9684             public Timer getSensorTime() {
9685                 return mTimer;
9686             }
9687 
9688             @Override
getSensorBackgroundTime()9689             public Timer getSensorBackgroundTime() {
9690                 if (mTimer == null) {
9691                     return null;
9692                 }
9693                 return mTimer.getSubTimer();
9694             }
9695 
9696             @Override
9697             @UnsupportedAppUsage
getHandle()9698             public int getHandle() {
9699                 return mHandle;
9700             }
9701 
detachFromTimeBase()9702             public void  detachFromTimeBase() {
9703                 detachIfNotNull(mTimer);
9704             }
9705         }
9706 
9707         /**
9708          * The statistics associated with a particular process.
9709          */
9710         public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
9711             /**
9712              * BatteryStatsImpl that we are associated with.
9713              */
9714             protected BatteryStatsImpl mBsi;
9715 
9716             /**
9717              * The name of this process.
9718              */
9719             final String mName;
9720 
9721             /**
9722              * Remains true until removed from the stats.
9723              */
9724             boolean mActive = true;
9725 
9726             /**
9727              * Total time (in ms) spent executing in user code.
9728              */
9729             long mUserTimeMs;
9730 
9731             /**
9732              * Total time (in ms) spent executing in kernel code.
9733              */
9734             long mSystemTimeMs;
9735 
9736             /**
9737              * Amount of time (in ms) the process was running in the foreground.
9738              */
9739             long mForegroundTimeMs;
9740 
9741             /**
9742              * Number of times the process has been started.
9743              */
9744             int mStarts;
9745 
9746             /**
9747              * Number of times the process has crashed.
9748              */
9749             int mNumCrashes;
9750 
9751             /**
9752              * Number of times the process has had an ANR.
9753              */
9754             int mNumAnrs;
9755 
9756             ArrayList<ExcessivePower> mExcessivePower;
9757 
Proc(BatteryStatsImpl bsi, String name)9758             public Proc(BatteryStatsImpl bsi, String name) {
9759                 mBsi = bsi;
9760                 mName = name;
9761                 mBsi.mOnBatteryTimeBase.add(this);
9762             }
9763 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)9764             public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
9765                     long baseRealtimeUs) {
9766             }
9767 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)9768             public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
9769                     long baseRealtimeUs) {
9770             }
9771 
9772             @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)9773             public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
9774                 if (detachIfReset) {
9775                     this.detach();
9776                 }
9777                 return true;
9778             }
9779 
9780             @Override
detach()9781             public void detach() {
9782                 mActive = false;
9783                 mBsi.mOnBatteryTimeBase.remove(this);
9784             }
9785 
countExcessivePowers()9786             public int countExcessivePowers() {
9787                 return mExcessivePower != null ? mExcessivePower.size() : 0;
9788             }
9789 
getExcessivePower(int i)9790             public ExcessivePower getExcessivePower(int i) {
9791                 if (mExcessivePower != null) {
9792                     return mExcessivePower.get(i);
9793                 }
9794                 return null;
9795             }
9796 
addExcessiveCpu(long overTimeMs, long usedTimeMs)9797             public void addExcessiveCpu(long overTimeMs, long usedTimeMs) {
9798                 if (mExcessivePower == null) {
9799                     mExcessivePower = new ArrayList<ExcessivePower>();
9800                 }
9801                 ExcessivePower ew = new ExcessivePower();
9802                 ew.type = ExcessivePower.TYPE_CPU;
9803                 ew.overTime = overTimeMs;
9804                 ew.usedTime = usedTimeMs;
9805                 mExcessivePower.add(ew);
9806             }
9807 
writeExcessivePowerToParcelLocked(Parcel out)9808             void writeExcessivePowerToParcelLocked(Parcel out) {
9809                 if (mExcessivePower == null) {
9810                     out.writeInt(0);
9811                     return;
9812                 }
9813 
9814                 final int N = mExcessivePower.size();
9815                 out.writeInt(N);
9816                 for (int i=0; i<N; i++) {
9817                     ExcessivePower ew = mExcessivePower.get(i);
9818                     out.writeInt(ew.type);
9819                     out.writeLong(ew.overTime);
9820                     out.writeLong(ew.usedTime);
9821                 }
9822             }
9823 
readExcessivePowerFromParcelLocked(Parcel in)9824             void readExcessivePowerFromParcelLocked(Parcel in) {
9825                 final int N = in.readInt();
9826                 if (N == 0) {
9827                     mExcessivePower = null;
9828                     return;
9829                 }
9830 
9831                 if (N > 10000) {
9832                     throw new ParcelFormatException(
9833                             "File corrupt: too many excessive power entries " + N);
9834                 }
9835 
9836                 mExcessivePower = new ArrayList<>();
9837                 for (int i=0; i<N; i++) {
9838                     ExcessivePower ew = new ExcessivePower();
9839                     ew.type = in.readInt();
9840                     ew.overTime = in.readLong();
9841                     ew.usedTime = in.readLong();
9842                     mExcessivePower.add(ew);
9843                 }
9844             }
9845 
writeToParcelLocked(Parcel out)9846             void writeToParcelLocked(Parcel out) {
9847                 out.writeLong(mUserTimeMs);
9848                 out.writeLong(mSystemTimeMs);
9849                 out.writeLong(mForegroundTimeMs);
9850                 out.writeInt(mStarts);
9851                 out.writeInt(mNumCrashes);
9852                 out.writeInt(mNumAnrs);
9853                 writeExcessivePowerToParcelLocked(out);
9854             }
9855 
readFromParcelLocked(Parcel in)9856             void readFromParcelLocked(Parcel in) {
9857                 mUserTimeMs = in.readLong();
9858                 mSystemTimeMs = in.readLong();
9859                 mForegroundTimeMs = in.readLong();
9860                 mStarts = in.readInt();
9861                 mNumCrashes = in.readInt();
9862                 mNumAnrs = in.readInt();
9863                 readExcessivePowerFromParcelLocked(in);
9864             }
9865 
9866             @UnsupportedAppUsage
addCpuTimeLocked(int utimeMs, int stimeMs)9867             public void addCpuTimeLocked(int utimeMs, int stimeMs) {
9868                 addCpuTimeLocked(utimeMs, stimeMs, mBsi.mOnBatteryTimeBase.isRunning());
9869             }
9870 
addCpuTimeLocked(int utimeMs, int stimeMs, boolean isRunning)9871             public void addCpuTimeLocked(int utimeMs, int stimeMs, boolean isRunning) {
9872                 if (isRunning) {
9873                     mUserTimeMs += utimeMs;
9874                     mSystemTimeMs += stimeMs;
9875                 }
9876             }
9877 
9878             @UnsupportedAppUsage
addForegroundTimeLocked(long ttimeMs)9879             public void addForegroundTimeLocked(long ttimeMs) {
9880                 mForegroundTimeMs += ttimeMs;
9881             }
9882 
9883             @UnsupportedAppUsage
incStartsLocked()9884             public void incStartsLocked() {
9885                 mStarts++;
9886             }
9887 
incNumCrashesLocked()9888             public void incNumCrashesLocked() {
9889                 mNumCrashes++;
9890             }
9891 
incNumAnrsLocked()9892             public void incNumAnrsLocked() {
9893                 mNumAnrs++;
9894             }
9895 
9896             @Override
isActive()9897             public boolean isActive() {
9898                 return mActive;
9899             }
9900 
9901             @Override
9902             @UnsupportedAppUsage
getUserTime(int which)9903             public long getUserTime(int which) {
9904                 return mUserTimeMs;
9905             }
9906 
9907             @Override
9908             @UnsupportedAppUsage
getSystemTime(int which)9909             public long getSystemTime(int which) {
9910                 return mSystemTimeMs;
9911             }
9912 
9913             @Override
9914             @UnsupportedAppUsage
getForegroundTime(int which)9915             public long getForegroundTime(int which) {
9916                 return mForegroundTimeMs;
9917             }
9918 
9919             @Override
9920             @UnsupportedAppUsage
getStarts(int which)9921             public int getStarts(int which) {
9922                 return mStarts;
9923             }
9924 
9925             @Override
getNumCrashes(int which)9926             public int getNumCrashes(int which) {
9927                 return mNumCrashes;
9928             }
9929 
9930             @Override
getNumAnrs(int which)9931             public int getNumAnrs(int which) {
9932                 return mNumAnrs;
9933             }
9934         }
9935 
9936         /**
9937          * The statistics associated with a particular package.
9938          */
9939         public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
9940             /**
9941              * BatteryStatsImpl that we are associated with.
9942              */
9943             protected BatteryStatsImpl mBsi;
9944 
9945             /**
9946              * Number of times wakeup alarms have occurred for this app.
9947              * On screen-off timebase starting in report v25.
9948              */
9949             ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
9950 
9951             /**
9952              * The statics we have collected for this package's services.
9953              */
9954             final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
9955 
Pkg(BatteryStatsImpl bsi)9956             public Pkg(BatteryStatsImpl bsi) {
9957                 mBsi = bsi;
9958                 mBsi.mOnBatteryScreenOffTimeBase.add(this);
9959             }
9960 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)9961             public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
9962                     long baseRealtimeUs) {
9963             }
9964 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)9965             public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
9966                     long baseRealtimeUs) {
9967             }
9968 
9969             @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)9970             public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
9971                 if (detachIfReset) {
9972                     this.detach();
9973                 }
9974                 return true;
9975             }
9976 
9977             @Override
detach()9978             public void detach() {
9979                 mBsi.mOnBatteryScreenOffTimeBase.remove(this);
9980                 for (int j = mWakeupAlarms.size() - 1; j >= 0; j--) {
9981                     detachIfNotNull(mWakeupAlarms.valueAt(j));
9982                 }
9983                 for (int j = mServiceStats.size() - 1; j >= 0; j--) {
9984                     detachIfNotNull(mServiceStats.valueAt(j));
9985                 }
9986             }
9987 
readFromParcelLocked(Parcel in)9988             void readFromParcelLocked(Parcel in) {
9989                 int numWA = in.readInt();
9990                 mWakeupAlarms.clear();
9991                 for (int i=0; i<numWA; i++) {
9992                     String tag = in.readString();
9993                     mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryScreenOffTimeBase, in));
9994                 }
9995 
9996                 int numServs = in.readInt();
9997                 mServiceStats.clear();
9998                 for (int m = 0; m < numServs; m++) {
9999                     String serviceName = in.readString();
10000                     Uid.Pkg.Serv serv = new Serv(mBsi);
10001                     mServiceStats.put(serviceName, serv);
10002 
10003                     serv.readFromParcelLocked(in);
10004                 }
10005             }
10006 
writeToParcelLocked(Parcel out)10007             void writeToParcelLocked(Parcel out) {
10008                 int numWA = mWakeupAlarms.size();
10009                 out.writeInt(numWA);
10010                 for (int i=0; i<numWA; i++) {
10011                     out.writeString(mWakeupAlarms.keyAt(i));
10012                     mWakeupAlarms.valueAt(i).writeToParcel(out);
10013                 }
10014 
10015                 final int NS = mServiceStats.size();
10016                 out.writeInt(NS);
10017                 for (int i=0; i<NS; i++) {
10018                     out.writeString(mServiceStats.keyAt(i));
10019                     Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
10020                     serv.writeToParcelLocked(out);
10021                 }
10022             }
10023 
10024             @Override
getWakeupAlarmStats()10025             public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
10026                 return mWakeupAlarms;
10027             }
10028 
noteWakeupAlarmLocked(String tag)10029             public void noteWakeupAlarmLocked(String tag) {
10030                 Counter c = mWakeupAlarms.get(tag);
10031                 if (c == null) {
10032                     c = new Counter(mBsi.mOnBatteryScreenOffTimeBase);
10033                     mWakeupAlarms.put(tag, c);
10034                 }
10035                 c.stepAtomic();
10036             }
10037 
10038             @Override
getServiceStats()10039             public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
10040                 return mServiceStats;
10041             }
10042 
10043             /**
10044              * The statistics associated with a particular service.
10045              */
10046             public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
10047                 /**
10048                  * BatteryStatsImpl that we are associated with.
10049                  */
10050                 protected BatteryStatsImpl mBsi;
10051 
10052                 /**
10053                  * The android package in which this service resides.
10054                  */
10055                 protected Pkg mPkg;
10056 
10057                 /**
10058                  * Total time (ms in battery uptime) the service has been left started.
10059                  */
10060                 protected long mStartTimeMs;
10061 
10062                 /**
10063                  * If service has been started and not yet stopped, this is
10064                  * when it was started.
10065                  */
10066                 protected long mRunningSinceMs;
10067 
10068                 /**
10069                  * True if we are currently running.
10070                  */
10071                 protected boolean mRunning;
10072 
10073                 /**
10074                  * Total number of times startService() has been called.
10075                  */
10076                 protected int mStarts;
10077 
10078                 /**
10079                  * Total time (ms in battery uptime) the service has been left launched.
10080                  */
10081                 protected long mLaunchedTimeMs;
10082 
10083                 /**
10084                  * If service has been launched and not yet exited, this is
10085                  * when it was launched (ms in battery uptime).
10086                  */
10087                 protected long mLaunchedSinceMs;
10088 
10089                 /**
10090                  * True if we are currently launched.
10091                  */
10092                 protected boolean mLaunched;
10093 
10094                 /**
10095                  * Total number times the service has been launched.
10096                  */
10097                 protected int mLaunches;
10098 
10099                 /**
10100                  * Construct a Serv. Also adds it to the on-battery time base as a listener.
10101                  */
Serv(BatteryStatsImpl bsi)10102                 public Serv(BatteryStatsImpl bsi) {
10103                     mBsi = bsi;
10104                     mBsi.mOnBatteryTimeBase.add(this);
10105                 }
10106 
onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10107                 public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs,
10108                         long baseRealtimeUs) {
10109                 }
10110 
onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs)10111                 public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs,
10112                         long baseRealtimeUs) {
10113                 }
10114 
10115                 @Override
reset(boolean detachIfReset, long elapsedRealtimeUs)10116                 public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) {
10117                     if (detachIfReset) {
10118                         this.detach();
10119                     }
10120                     return true;
10121                 }
10122 
10123                 /**
10124                  * Remove this Serv as a listener from the time base.
10125                  Ms*/
10126                 @Override
detach()10127                 public void detach() {
10128                     mBsi.mOnBatteryTimeBase.remove(this);
10129                 }
10130 
readFromParcelLocked(Parcel in)10131                 public void readFromParcelLocked(Parcel in) {
10132                     mStartTimeMs = in.readLong();
10133                     mRunningSinceMs = in.readLong();
10134                     mRunning = in.readInt() != 0;
10135                     mStarts = in.readInt();
10136                     mLaunchedTimeMs = in.readLong();
10137                     mLaunchedSinceMs = in.readLong();
10138                     mLaunched = in.readInt() != 0;
10139                     mLaunches = in.readInt();
10140                 }
10141 
writeToParcelLocked(Parcel out)10142                 public void writeToParcelLocked(Parcel out) {
10143                     out.writeLong(mStartTimeMs);
10144                     out.writeLong(mRunningSinceMs);
10145                     out.writeInt(mRunning ? 1 : 0);
10146                     out.writeInt(mStarts);
10147                     out.writeLong(mLaunchedTimeMs);
10148                     out.writeLong(mLaunchedSinceMs);
10149                     out.writeInt(mLaunched ? 1 : 0);
10150                     out.writeInt(mLaunches);
10151                 }
10152 
getLaunchTimeToNowLocked(long batteryUptimeMs)10153                 public long getLaunchTimeToNowLocked(long batteryUptimeMs) {
10154                     if (!mLaunched) return mLaunchedTimeMs;
10155                     return mLaunchedTimeMs + batteryUptimeMs - mLaunchedSinceMs;
10156                 }
10157 
getStartTimeToNowLocked(long batteryUptimeMs)10158                 public long getStartTimeToNowLocked(long batteryUptimeMs) {
10159                     if (!mRunning) return mStartTimeMs;
10160                     return mStartTimeMs + batteryUptimeMs - mRunningSinceMs;
10161                 }
10162 
10163                 @UnsupportedAppUsage
startLaunchedLocked()10164                 public void startLaunchedLocked() {
10165                     startLaunchedLocked(mBsi.mClocks.uptimeMillis());
10166                 }
10167 
startLaunchedLocked(long uptimeMs)10168                 public void startLaunchedLocked(long uptimeMs) {
10169                     if (!mLaunched) {
10170                         mLaunches++;
10171                         mLaunchedSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000;
10172                         mLaunched = true;
10173                     }
10174                 }
10175 
10176                 @UnsupportedAppUsage
stopLaunchedLocked()10177                 public void stopLaunchedLocked() {
10178                     stopLaunchedLocked(mBsi.mClocks.uptimeMillis());
10179                 }
10180 
stopLaunchedLocked(long uptimeMs)10181                 public void stopLaunchedLocked(long uptimeMs) {
10182                     if (mLaunched) {
10183                         long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000
10184                                 - mLaunchedSinceMs;
10185                         if (timeMs > 0) {
10186                             mLaunchedTimeMs += timeMs;
10187                         } else {
10188                             mLaunches--;
10189                         }
10190                         mLaunched = false;
10191                     }
10192                 }
10193 
10194                 @UnsupportedAppUsage
startRunningLocked()10195                 public void startRunningLocked() {
10196                     startRunningLocked(mBsi.mClocks.uptimeMillis());
10197                 }
10198 
startRunningLocked(long uptimeMs)10199                 public void startRunningLocked(long uptimeMs) {
10200                     if (!mRunning) {
10201                         mStarts++;
10202                         mRunningSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000;
10203                         mRunning = true;
10204                     }
10205                 }
10206 
10207                 @UnsupportedAppUsage
stopRunningLocked()10208                 public void stopRunningLocked() {
10209                     stopRunningLocked(mBsi.mClocks.uptimeMillis());
10210                 }
10211 
stopRunningLocked(long uptimeMs)10212                 public void stopRunningLocked(long uptimeMs) {
10213                     if (mRunning) {
10214                         long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000
10215                                 - mRunningSinceMs;
10216                         if (timeMs > 0) {
10217                             mStartTimeMs += timeMs;
10218                         } else {
10219                             mStarts--;
10220                         }
10221                         mRunning = false;
10222                     }
10223                 }
10224 
10225                 @UnsupportedAppUsage
getBatteryStats()10226                 public BatteryStatsImpl getBatteryStats() {
10227                     return mBsi;
10228                 }
10229 
10230                 @Override
getLaunches(int which)10231                 public int getLaunches(int which) {
10232                     return mLaunches;
10233                 }
10234 
10235                 @Override
getStartTime(long now, int which)10236                 public long getStartTime(long now, int which) {
10237                     return getStartTimeToNowLocked(now);
10238                 }
10239 
10240                 @Override
getStarts(int which)10241                 public int getStarts(int which) {
10242                     return mStarts;
10243                 }
10244             }
10245 
newServiceStatsLocked()10246             final Serv newServiceStatsLocked() {
10247                 return new Serv(mBsi);
10248             }
10249         }
10250 
10251         /**
10252          * Retrieve the statistics object for a particular process, creating
10253          * if needed.
10254          */
getProcessStatsLocked(String name)10255         public Proc getProcessStatsLocked(String name) {
10256             Proc ps = mProcessStats.get(name);
10257             if (ps == null) {
10258                 ps = new Proc(mBsi, name);
10259                 mProcessStats.put(name, ps);
10260             }
10261 
10262             return ps;
10263         }
10264 
10265         @GuardedBy("mBsi")
updateUidProcessStateLocked(int procState)10266         public void updateUidProcessStateLocked(int procState) {
10267             updateUidProcessStateLocked(procState,
10268                     mBsi.mClocks.elapsedRealtime(), mBsi.mClocks.uptimeMillis());
10269         }
10270 
updateUidProcessStateLocked(int procState, long elapsedRealtimeMs, long uptimeMs)10271         public void updateUidProcessStateLocked(int procState,
10272                 long elapsedRealtimeMs, long uptimeMs) {
10273             int uidRunningState;
10274             // Make special note of Foreground Services
10275             final boolean userAwareService =
10276                     (ActivityManager.isForegroundService(procState));
10277             uidRunningState = BatteryStats.mapToInternalProcessState(procState);
10278 
10279             if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
10280                 return;
10281             }
10282 
10283             if (mProcessState != uidRunningState) {
10284                 if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
10285                     mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
10286 
10287                     if (mBsi.trackPerProcStateCpuTimes()) {
10288                         if (mBsi.mPendingUids.size() == 0) {
10289                             mBsi.mExternalSync.scheduleReadProcStateCpuTimes(
10290                                     mBsi.mOnBatteryTimeBase.isRunning(),
10291                                     mBsi.mOnBatteryScreenOffTimeBase.isRunning(),
10292                                     mBsi.mConstants.PROC_STATE_CPU_TIMES_READ_DELAY_MS);
10293                             mBsi.mNumSingleUidCpuTimeReads++;
10294                         } else {
10295                             mBsi.mNumBatchedSingleUidCpuTimeReads++;
10296                         }
10297                         if (mBsi.mPendingUids.indexOfKey(mUid) < 0
10298                                 || ArrayUtils.contains(CRITICAL_PROC_STATES, mProcessState)) {
10299                             mBsi.mPendingUids.put(mUid, mProcessState);
10300                         }
10301                     } else {
10302                         mBsi.mPendingUids.clear();
10303                     }
10304                 }
10305                 mProcessState = uidRunningState;
10306                 if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
10307                     if (mProcessStateTimer[uidRunningState] == null) {
10308                         makeProcessState(uidRunningState, null);
10309                     }
10310                     mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
10311                 }
10312 
10313                 updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
10314                 updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
10315             }
10316 
10317             if (userAwareService != mInForegroundService) {
10318                 if (userAwareService) {
10319                     noteForegroundServiceResumedLocked(elapsedRealtimeMs);
10320                 } else {
10321                     noteForegroundServicePausedLocked(elapsedRealtimeMs);
10322                 }
10323                 mInForegroundService = userAwareService;
10324             }
10325         }
10326 
10327         /** Whether to consider Uid to be in the background for background timebase purposes. */
isInBackground()10328         public boolean isInBackground() {
10329             // Note that PROCESS_STATE_CACHED and ActivityManager.PROCESS_STATE_NONEXISTENT is
10330             // also considered to be 'background' for our purposes, because it's not foreground.
10331             return mProcessState >= PROCESS_STATE_BACKGROUND;
10332         }
10333 
updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs)10334         public boolean updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs) {
10335             boolean on = mBsi.mOnBatteryTimeBase.isRunning() && isInBackground();
10336             return mOnBatteryBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
10337         }
10338 
updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs)10339         public boolean updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs) {
10340             boolean on = mBsi.mOnBatteryScreenOffTimeBase.isRunning() && isInBackground();
10341             return mOnBatteryScreenOffBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
10342         }
10343 
getPidStats()10344         public SparseArray<? extends Pid> getPidStats() {
10345             return mPids;
10346         }
10347 
getPidStatsLocked(int pid)10348         public Pid getPidStatsLocked(int pid) {
10349             Pid p = mPids.get(pid);
10350             if (p == null) {
10351                 p = new Pid();
10352                 mPids.put(pid, p);
10353             }
10354             return p;
10355         }
10356 
10357         /**
10358          * Retrieve the statistics object for a particular service, creating
10359          * if needed.
10360          */
getPackageStatsLocked(String name)10361         public Pkg getPackageStatsLocked(String name) {
10362             Pkg ps = mPackageStats.get(name);
10363             if (ps == null) {
10364                 ps = new Pkg(mBsi);
10365                 mPackageStats.put(name, ps);
10366             }
10367 
10368             return ps;
10369         }
10370 
10371         /**
10372          * Retrieve the statistics object for a particular service, creating
10373          * if needed.
10374          */
getServiceStatsLocked(String pkg, String serv)10375         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
10376             Pkg ps = getPackageStatsLocked(pkg);
10377             Pkg.Serv ss = ps.mServiceStats.get(serv);
10378             if (ss == null) {
10379                 ss = ps.newServiceStatsLocked();
10380                 ps.mServiceStats.put(serv, ss);
10381             }
10382 
10383             return ss;
10384         }
10385 
readSyncSummaryFromParcelLocked(String name, Parcel in)10386         public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
10387             DualTimer timer = mSyncStats.instantiateObject();
10388             timer.readSummaryFromParcelLocked(in);
10389             mSyncStats.add(name, timer);
10390         }
10391 
readJobSummaryFromParcelLocked(String name, Parcel in)10392         public void readJobSummaryFromParcelLocked(String name, Parcel in) {
10393             DualTimer timer = mJobStats.instantiateObject();
10394             timer.readSummaryFromParcelLocked(in);
10395             mJobStats.add(name, timer);
10396         }
10397 
readWakeSummaryFromParcelLocked(String wlName, Parcel in)10398         public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
10399             Wakelock wl = new Wakelock(mBsi, this);
10400             mWakelockStats.add(wlName, wl);
10401             if (in.readInt() != 0) {
10402                 getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
10403             }
10404             if (in.readInt() != 0) {
10405                 getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
10406             }
10407             if (in.readInt() != 0) {
10408                 getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
10409             }
10410             if (in.readInt() != 0) {
10411                 getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
10412             }
10413         }
10414 
getSensorTimerLocked(int sensor, boolean create)10415         public DualTimer getSensorTimerLocked(int sensor, boolean create) {
10416             Sensor se = mSensorStats.get(sensor);
10417             if (se == null) {
10418                 if (!create) {
10419                     return null;
10420                 }
10421                 se = new Sensor(mBsi, this, sensor);
10422                 mSensorStats.put(sensor, se);
10423             }
10424             DualTimer t = se.mTimer;
10425             if (t != null) {
10426                 return t;
10427             }
10428             ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
10429             if (timers == null) {
10430                 timers = new ArrayList<StopwatchTimer>();
10431                 mBsi.mSensorTimers.put(sensor, timers);
10432             }
10433             t = new DualTimer(mBsi.mClocks, this, BatteryStats.SENSOR, timers,
10434                     mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
10435             se.mTimer = t;
10436             return t;
10437         }
10438 
noteStartSyncLocked(String name, long elapsedRealtimeMs)10439         public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
10440             DualTimer t = mSyncStats.startObject(name, elapsedRealtimeMs);
10441             if (t != null) {
10442                 t.startRunningLocked(elapsedRealtimeMs);
10443             }
10444         }
10445 
noteStopSyncLocked(String name, long elapsedRealtimeMs)10446         public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
10447             DualTimer t = mSyncStats.stopObject(name, elapsedRealtimeMs);
10448             if (t != null) {
10449                 t.stopRunningLocked(elapsedRealtimeMs);
10450             }
10451         }
10452 
noteStartJobLocked(String name, long elapsedRealtimeMs)10453         public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
10454             DualTimer t = mJobStats.startObject(name, elapsedRealtimeMs);
10455             if (t != null) {
10456                 t.startRunningLocked(elapsedRealtimeMs);
10457             }
10458         }
10459 
noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason)10460         public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
10461             DualTimer t = mJobStats.stopObject(name, elapsedRealtimeMs);
10462             if (t != null) {
10463                 t.stopRunningLocked(elapsedRealtimeMs);
10464             }
10465             if (mBsi.mOnBatteryTimeBase.isRunning()) {
10466                 SparseIntArray types = mJobCompletions.get(name);
10467                 if (types == null) {
10468                     types = new SparseIntArray();
10469                     mJobCompletions.put(name, types);
10470                 }
10471                 int last = types.get(stopReason, 0);
10472                 types.put(stopReason, last + 1);
10473             }
10474         }
10475 
getWakelockTimerLocked(Wakelock wl, int type)10476         public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
10477             if (wl == null) {
10478                 return null;
10479             }
10480             switch (type) {
10481                 case WAKE_TYPE_PARTIAL: {
10482                     DualTimer t = wl.mTimerPartial;
10483                     if (t == null) {
10484                         t = new DualTimer(mBsi.mClocks, this, WAKE_TYPE_PARTIAL,
10485                                 mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase,
10486                                 mOnBatteryScreenOffBackgroundTimeBase);
10487                         wl.mTimerPartial = t;
10488                     }
10489                     return t;
10490                 }
10491                 case WAKE_TYPE_FULL: {
10492                     StopwatchTimer t = wl.mTimerFull;
10493                     if (t == null) {
10494                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_FULL,
10495                                 mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
10496                         wl.mTimerFull = t;
10497                     }
10498                     return t;
10499                 }
10500                 case WAKE_TYPE_WINDOW: {
10501                     StopwatchTimer t = wl.mTimerWindow;
10502                     if (t == null) {
10503                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_WINDOW,
10504                                 mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
10505                         wl.mTimerWindow = t;
10506                     }
10507                     return t;
10508                 }
10509                 case WAKE_TYPE_DRAW: {
10510                     StopwatchTimer t = wl.mTimerDraw;
10511                     if (t == null) {
10512                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_DRAW,
10513                                 mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
10514                         wl.mTimerDraw = t;
10515                     }
10516                     return t;
10517                 }
10518                 default:
10519                     throw new IllegalArgumentException("type=" + type);
10520             }
10521         }
10522 
noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)10523         public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
10524             Wakelock wl = mWakelockStats.startObject(name, elapsedRealtimeMs);
10525             if (wl != null) {
10526                 getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
10527             }
10528             if (type == WAKE_TYPE_PARTIAL) {
10529                 createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
10530                 if (pid >= 0) {
10531                     Pid p = getPidStatsLocked(pid);
10532                     if (p.mWakeNesting++ == 0) {
10533                         p.mWakeStartMs = elapsedRealtimeMs;
10534                     }
10535                 }
10536             }
10537         }
10538 
noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)10539         public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
10540             Wakelock wl = mWakelockStats.stopObject(name, elapsedRealtimeMs);
10541             if (wl != null) {
10542                 StopwatchTimer wlt = getWakelockTimerLocked(wl, type);
10543                 wlt.stopRunningLocked(elapsedRealtimeMs);
10544             }
10545             if (type == WAKE_TYPE_PARTIAL) {
10546                 if (mAggregatedPartialWakelockTimer != null) {
10547                     mAggregatedPartialWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
10548                 }
10549                 if (pid >= 0) {
10550                     Pid p = mPids.get(pid);
10551                     if (p != null && p.mWakeNesting > 0) {
10552                         if (p.mWakeNesting-- == 1) {
10553                             p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
10554                             p.mWakeStartMs = 0;
10555                         }
10556                     }
10557                 }
10558             }
10559         }
10560 
reportExcessiveCpuLocked(String proc, long overTimeMs, long usedTimeMs)10561         public void reportExcessiveCpuLocked(String proc, long overTimeMs, long usedTimeMs) {
10562             Proc p = getProcessStatsLocked(proc);
10563             if (p != null) {
10564                 p.addExcessiveCpu(overTimeMs, usedTimeMs);
10565             }
10566         }
10567 
noteStartSensor(int sensor, long elapsedRealtimeMs)10568         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
10569             DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
10570             t.startRunningLocked(elapsedRealtimeMs);
10571         }
10572 
noteStopSensor(int sensor, long elapsedRealtimeMs)10573         public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
10574             // Don't create a timer if one doesn't already exist
10575             DualTimer t = getSensorTimerLocked(sensor, false);
10576             if (t != null) {
10577                 t.stopRunningLocked(elapsedRealtimeMs);
10578             }
10579         }
10580 
noteStartGps(long elapsedRealtimeMs)10581         public void noteStartGps(long elapsedRealtimeMs) {
10582             noteStartSensor(Sensor.GPS, elapsedRealtimeMs);
10583         }
10584 
noteStopGps(long elapsedRealtimeMs)10585         public void noteStopGps(long elapsedRealtimeMs) {
10586             noteStopSensor(Sensor.GPS, elapsedRealtimeMs);
10587         }
10588 
getBatteryStats()10589         public BatteryStatsImpl getBatteryStats() {
10590             return mBsi;
10591         }
10592     }
10593 
getCpuFreqs()10594     public long[] getCpuFreqs() {
10595         return mCpuFreqs;
10596     }
10597 
BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb, MeasuredEnergyRetriever energyStatsCb, UserInfoProvider userInfoProvider)10598     public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
10599             MeasuredEnergyRetriever energyStatsCb, UserInfoProvider userInfoProvider) {
10600         this(new SystemClocks(), systemDir, handler, cb, energyStatsCb, userInfoProvider);
10601     }
10602 
BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler, PlatformIdleStateCallback cb, MeasuredEnergyRetriever energyStatsCb, UserInfoProvider userInfoProvider)10603     private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
10604             PlatformIdleStateCallback cb, MeasuredEnergyRetriever energyStatsCb,
10605             UserInfoProvider userInfoProvider) {
10606         init(clocks);
10607 
10608         if (systemDir == null) {
10609             mStatsFile = null;
10610             mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
10611         } else {
10612             mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
10613             mBatteryStatsHistory = new BatteryStatsHistory(this, systemDir, mHistoryBuffer);
10614         }
10615         mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
10616         mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
10617         mHandler = new MyHandler(handler.getLooper());
10618         mConstants = new Constants(mHandler);
10619         mStartCount++;
10620         initTimersAndCounters();
10621         mOnBattery = mOnBatteryInternal = false;
10622         long uptimeUs = mClocks.uptimeMillis() * 1000;
10623         long realtimeUs = mClocks.elapsedRealtime() * 1000;
10624         initTimes(uptimeUs, realtimeUs);
10625         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
10626         initDischarge(realtimeUs);
10627         clearHistoryLocked();
10628         updateDailyDeadlineLocked();
10629         mPlatformIdleStateCallback = cb;
10630         mMeasuredEnergyRetriever = energyStatsCb;
10631         mUserInfoProvider = userInfoProvider;
10632 
10633         // Notify statsd that the system is initially not in doze.
10634         mDeviceIdleMode = DEVICE_IDLE_MODE_OFF;
10635         FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mDeviceIdleMode);
10636     }
10637 
10638     @VisibleForTesting
initTimersAndCounters()10639     protected void initTimersAndCounters() {
10640         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
10641         mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
10642         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10643             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
10644                     mOnBatteryTimeBase);
10645         }
10646         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase);
10647         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
10648                 mOnBatteryTimeBase);
10649         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -11, null,
10650                 mOnBatteryTimeBase);
10651         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
10652         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null, mOnBatteryTimeBase);
10653         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase);
10654         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase);
10655         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
10656             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i, null,
10657                     mOnBatteryTimeBase);
10658         }
10659         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
10660                 mOnBatteryTimeBase);
10661         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10662             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i, null,
10663                     mOnBatteryTimeBase);
10664         }
10665         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10666             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
10667             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
10668         }
10669         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
10670         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
10671                 NUM_BT_TX_LEVELS);
10672         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
10673                 ModemActivityInfo.getNumTxPowerLevels());
10674         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase);
10675         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
10676                 mOnBatteryTimeBase);
10677         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
10678         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
10679         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
10680         mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null,
10681                 WIFI_AGGREGATE_MULTICAST_ENABLED, null, mOnBatteryTimeBase);
10682         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase);
10683         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null, mOnBatteryTimeBase);
10684         for (int i=0; i<NUM_WIFI_STATES; i++) {
10685             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i, null,
10686                     mOnBatteryTimeBase);
10687         }
10688         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10689             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i, null,
10690                     mOnBatteryTimeBase);
10691         }
10692         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10693             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
10694                     mOnBatteryTimeBase);
10695         }
10696         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null, mOnBatteryTimeBase);
10697         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
10698             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i, null,
10699                 mOnBatteryTimeBase);
10700         }
10701         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
10702         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
10703         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
10704         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase);
10705         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
10706         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
10707         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10708         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10709         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10710         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10711         mDischargeStartLevel = 0;
10712         mDischargeUnplugLevel = 0;
10713         mDischargePlugLevel = -1;
10714         mDischargeCurrentLevel = 0;
10715         mCurrentBatteryLevel = 0;
10716     }
10717 
10718     @UnsupportedAppUsage
BatteryStatsImpl(Parcel p)10719     public BatteryStatsImpl(Parcel p) {
10720         this(new SystemClocks(), p);
10721     }
10722 
BatteryStatsImpl(Clocks clocks, Parcel p)10723     public BatteryStatsImpl(Clocks clocks, Parcel p) {
10724         init(clocks);
10725         mStatsFile = null;
10726         mCheckinFile = null;
10727         mDailyFile = null;
10728         mHandler = null;
10729         mExternalSync = null;
10730         mConstants = new Constants(mHandler);
10731         clearHistoryLocked();
10732         mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
10733         readFromParcel(p);
10734         mPlatformIdleStateCallback = null;
10735         mMeasuredEnergyRetriever = null;
10736     }
10737 
setPowerProfileLocked(PowerProfile profile)10738     public void setPowerProfileLocked(PowerProfile profile) {
10739         mPowerProfile = profile;
10740 
10741         // We need to initialize the KernelCpuSpeedReaders to read from
10742         // the first cpu of each core. Once we have the PowerProfile, we have access to this
10743         // information.
10744         final int numClusters = mPowerProfile.getNumCpuClusters();
10745         mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
10746         int firstCpuOfCluster = 0;
10747         for (int i = 0; i < numClusters; i++) {
10748             final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
10749             mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
10750                     numSpeedSteps);
10751             firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
10752         }
10753 
10754         if (mEstimatedBatteryCapacityMah == -1) {
10755             // Initialize the estimated battery capacity to a known preset one.
10756             mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
10757         }
10758     }
10759 
getPowerProfile()10760     PowerProfile getPowerProfile() {
10761         return mPowerProfile;
10762     }
10763 
10764     /**
10765      * Starts tracking CPU time-in-state for threads of the system server process,
10766      * keeping a separate account of threads receiving incoming binder calls.
10767      */
startTrackingSystemServerCpuTime()10768     public void startTrackingSystemServerCpuTime() {
10769         mSystemServerCpuThreadReader.startTrackingThreadCpuTime();
10770     }
10771 
getSystemServiceCpuThreadTimes()10772     public SystemServiceCpuThreadTimes getSystemServiceCpuThreadTimes() {
10773         return mSystemServerCpuThreadReader.readAbsolute();
10774     }
10775 
setCallback(BatteryCallback cb)10776     public void setCallback(BatteryCallback cb) {
10777         mCallback = cb;
10778     }
10779 
setRadioScanningTimeoutLocked(long timeoutUs)10780     public void setRadioScanningTimeoutLocked(long timeoutUs) {
10781         if (mPhoneSignalScanningTimer != null) {
10782             mPhoneSignalScanningTimer.setTimeout(timeoutUs);
10783         }
10784     }
10785 
setExternalStatsSyncLocked(ExternalStatsSync sync)10786     public void setExternalStatsSyncLocked(ExternalStatsSync sync) {
10787         mExternalSync = sync;
10788     }
10789 
updateDailyDeadlineLocked()10790     public void updateDailyDeadlineLocked() {
10791         // Get the current time.
10792         long currentTimeMs = mDailyStartTimeMs = mClocks.currentTimeMillis();
10793         Calendar calDeadline = Calendar.getInstance();
10794         calDeadline.setTimeInMillis(currentTimeMs);
10795 
10796         // Move time up to the next day, ranging from 1am to 3pm.
10797         calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
10798         calDeadline.set(Calendar.MILLISECOND, 0);
10799         calDeadline.set(Calendar.SECOND, 0);
10800         calDeadline.set(Calendar.MINUTE, 0);
10801         calDeadline.set(Calendar.HOUR_OF_DAY, 1);
10802         mNextMinDailyDeadlineMs = calDeadline.getTimeInMillis();
10803         calDeadline.set(Calendar.HOUR_OF_DAY, 3);
10804         mNextMaxDailyDeadlineMs = calDeadline.getTimeInMillis();
10805     }
10806 
recordDailyStatsIfNeededLocked(boolean settled, long currentTimeMs)10807     public void recordDailyStatsIfNeededLocked(boolean settled, long currentTimeMs) {
10808         if (currentTimeMs >= mNextMaxDailyDeadlineMs) {
10809             recordDailyStatsLocked();
10810         } else if (settled && currentTimeMs >= mNextMinDailyDeadlineMs) {
10811             recordDailyStatsLocked();
10812         } else if (currentTimeMs < (mDailyStartTimeMs - (1000 * 60 * 60 * 24))) {
10813             recordDailyStatsLocked();
10814         }
10815     }
10816 
recordDailyStatsLocked()10817     public void recordDailyStatsLocked() {
10818         DailyItem item = new DailyItem();
10819         item.mStartTime = mDailyStartTimeMs;
10820         item.mEndTime = mClocks.currentTimeMillis();
10821         boolean hasData = false;
10822         if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
10823             hasData = true;
10824             item.mDischargeSteps = new LevelStepTracker(
10825                     mDailyDischargeStepTracker.mNumStepDurations,
10826                     mDailyDischargeStepTracker.mStepDurations);
10827         }
10828         if (mDailyChargeStepTracker.mNumStepDurations > 0) {
10829             hasData = true;
10830             item.mChargeSteps = new LevelStepTracker(
10831                     mDailyChargeStepTracker.mNumStepDurations,
10832                     mDailyChargeStepTracker.mStepDurations);
10833         }
10834         if (mDailyPackageChanges != null) {
10835             hasData = true;
10836             item.mPackageChanges = mDailyPackageChanges;
10837             mDailyPackageChanges = null;
10838         }
10839         mDailyDischargeStepTracker.init();
10840         mDailyChargeStepTracker.init();
10841         updateDailyDeadlineLocked();
10842 
10843         if (hasData) {
10844             final long startTimeMs = SystemClock.uptimeMillis();
10845             mDailyItems.add(item);
10846             while (mDailyItems.size() > MAX_DAILY_ITEMS) {
10847                 mDailyItems.remove(0);
10848             }
10849             final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
10850             try {
10851                 TypedXmlSerializer out = Xml.resolveSerializer(memStream);
10852                 writeDailyItemsLocked(out);
10853                 final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs;
10854                 BackgroundThread.getHandler().post(new Runnable() {
10855                     @Override
10856                     public void run() {
10857                         synchronized (mCheckinFile) {
10858                             final long startTimeMs2 = SystemClock.uptimeMillis();
10859                             FileOutputStream stream = null;
10860                             try {
10861                                 stream = mDailyFile.startWrite();
10862                                 memStream.writeTo(stream);
10863                                 stream.flush();
10864                                 mDailyFile.finishWrite(stream);
10865                                 com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
10866                                         "batterystats-daily",
10867                                         initialTimeMs + SystemClock.uptimeMillis() - startTimeMs2);
10868                             } catch (IOException e) {
10869                                 Slog.w("BatteryStats",
10870                                         "Error writing battery daily items", e);
10871                                 mDailyFile.failWrite(stream);
10872                             }
10873                         }
10874                     }
10875                 });
10876             } catch (IOException e) {
10877             }
10878         }
10879     }
10880 
writeDailyItemsLocked(TypedXmlSerializer out)10881     private void writeDailyItemsLocked(TypedXmlSerializer out) throws IOException {
10882         StringBuilder sb = new StringBuilder(64);
10883         out.startDocument(null, true);
10884         out.startTag(null, "daily-items");
10885         for (int i=0; i<mDailyItems.size(); i++) {
10886             final DailyItem dit = mDailyItems.get(i);
10887             out.startTag(null, "item");
10888             out.attributeLong(null, "start", dit.mStartTime);
10889             out.attributeLong(null, "end", dit.mEndTime);
10890             writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
10891             writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
10892             if (dit.mPackageChanges != null) {
10893                 for (int j=0; j<dit.mPackageChanges.size(); j++) {
10894                     PackageChange pc = dit.mPackageChanges.get(j);
10895                     if (pc.mUpdate) {
10896                         out.startTag(null, "upd");
10897                         out.attribute(null, "pkg", pc.mPackageName);
10898                         out.attributeLong(null, "ver", pc.mVersionCode);
10899                         out.endTag(null, "upd");
10900                     } else {
10901                         out.startTag(null, "rem");
10902                         out.attribute(null, "pkg", pc.mPackageName);
10903                         out.endTag(null, "rem");
10904                     }
10905                 }
10906             }
10907             out.endTag(null, "item");
10908         }
10909         out.endTag(null, "daily-items");
10910         out.endDocument();
10911     }
10912 
writeDailyLevelSteps(TypedXmlSerializer out, String tag, LevelStepTracker steps, StringBuilder tmpBuilder)10913     private void writeDailyLevelSteps(TypedXmlSerializer out, String tag, LevelStepTracker steps,
10914             StringBuilder tmpBuilder) throws IOException {
10915         if (steps != null) {
10916             out.startTag(null, tag);
10917             out.attributeInt(null, "n", steps.mNumStepDurations);
10918             for (int i=0; i<steps.mNumStepDurations; i++) {
10919                 out.startTag(null, "s");
10920                 tmpBuilder.setLength(0);
10921                 steps.encodeEntryAt(i, tmpBuilder);
10922                 out.attribute(null, "v", tmpBuilder.toString());
10923                 out.endTag(null, "s");
10924             }
10925             out.endTag(null, tag);
10926         }
10927     }
10928 
readDailyStatsLocked()10929     public void readDailyStatsLocked() {
10930         Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
10931         mDailyItems.clear();
10932         FileInputStream stream;
10933         try {
10934             stream = mDailyFile.openRead();
10935         } catch (FileNotFoundException e) {
10936             return;
10937         }
10938         try {
10939             TypedXmlPullParser parser = Xml.resolvePullParser(stream);
10940             readDailyItemsLocked(parser);
10941         } catch (IOException e) {
10942         } finally {
10943             try {
10944                 stream.close();
10945             } catch (IOException e) {
10946             }
10947         }
10948     }
10949 
readDailyItemsLocked(TypedXmlPullParser parser)10950     private void readDailyItemsLocked(TypedXmlPullParser parser) {
10951         try {
10952             int type;
10953             while ((type = parser.next()) != XmlPullParser.START_TAG
10954                     && type != XmlPullParser.END_DOCUMENT) {
10955                 ;
10956             }
10957 
10958             if (type != XmlPullParser.START_TAG) {
10959                 throw new IllegalStateException("no start tag found");
10960             }
10961 
10962             int outerDepth = parser.getDepth();
10963             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10964                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10965                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10966                     continue;
10967                 }
10968 
10969                 String tagName = parser.getName();
10970                 if (tagName.equals("item")) {
10971                     readDailyItemTagLocked(parser);
10972                 } else {
10973                     Slog.w(TAG, "Unknown element under <daily-items>: "
10974                             + parser.getName());
10975                     XmlUtils.skipCurrentTag(parser);
10976                 }
10977             }
10978 
10979         } catch (IllegalStateException e) {
10980             Slog.w(TAG, "Failed parsing daily " + e);
10981         } catch (NullPointerException e) {
10982             Slog.w(TAG, "Failed parsing daily " + e);
10983         } catch (NumberFormatException e) {
10984             Slog.w(TAG, "Failed parsing daily " + e);
10985         } catch (XmlPullParserException e) {
10986             Slog.w(TAG, "Failed parsing daily " + e);
10987         } catch (IOException e) {
10988             Slog.w(TAG, "Failed parsing daily " + e);
10989         } catch (IndexOutOfBoundsException e) {
10990             Slog.w(TAG, "Failed parsing daily " + e);
10991         }
10992     }
10993 
readDailyItemTagLocked(TypedXmlPullParser parser)10994     void readDailyItemTagLocked(TypedXmlPullParser parser) throws NumberFormatException,
10995             XmlPullParserException, IOException {
10996         DailyItem dit = new DailyItem();
10997         dit.mStartTime = parser.getAttributeLong(null, "start", 0);
10998         dit.mEndTime = parser.getAttributeLong(null, "end", 0);
10999         int outerDepth = parser.getDepth();
11000         int type;
11001         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11002                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11003             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11004                 continue;
11005             }
11006 
11007             String tagName = parser.getName();
11008             if (tagName.equals("dis")) {
11009                 readDailyItemTagDetailsLocked(parser, dit, false, "dis");
11010             } else if (tagName.equals("chg")) {
11011                 readDailyItemTagDetailsLocked(parser, dit, true, "chg");
11012             } else if (tagName.equals("upd")) {
11013                 if (dit.mPackageChanges == null) {
11014                     dit.mPackageChanges = new ArrayList<>();
11015                 }
11016                 PackageChange pc = new PackageChange();
11017                 pc.mUpdate = true;
11018                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
11019                 pc.mVersionCode = parser.getAttributeLong(null, "ver", 0);
11020                 dit.mPackageChanges.add(pc);
11021                 XmlUtils.skipCurrentTag(parser);
11022             } else if (tagName.equals("rem")) {
11023                 if (dit.mPackageChanges == null) {
11024                     dit.mPackageChanges = new ArrayList<>();
11025                 }
11026                 PackageChange pc = new PackageChange();
11027                 pc.mUpdate = false;
11028                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
11029                 dit.mPackageChanges.add(pc);
11030                 XmlUtils.skipCurrentTag(parser);
11031             } else {
11032                 Slog.w(TAG, "Unknown element under <item>: "
11033                         + parser.getName());
11034                 XmlUtils.skipCurrentTag(parser);
11035             }
11036         }
11037         mDailyItems.add(dit);
11038     }
11039 
readDailyItemTagDetailsLocked(TypedXmlPullParser parser, DailyItem dit, boolean isCharge, String tag)11040     void readDailyItemTagDetailsLocked(TypedXmlPullParser parser, DailyItem dit, boolean isCharge,
11041             String tag)
11042             throws NumberFormatException, XmlPullParserException, IOException {
11043         final int num = parser.getAttributeInt(null, "n", -1);
11044         if (num == -1) {
11045             Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
11046             XmlUtils.skipCurrentTag(parser);
11047             return;
11048         }
11049         LevelStepTracker steps = new LevelStepTracker(num);
11050         if (isCharge) {
11051             dit.mChargeSteps = steps;
11052         } else {
11053             dit.mDischargeSteps = steps;
11054         }
11055         int i = 0;
11056         int outerDepth = parser.getDepth();
11057         int type;
11058         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
11059                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
11060             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
11061                 continue;
11062             }
11063 
11064             String tagName = parser.getName();
11065             if ("s".equals(tagName)) {
11066                 if (i < num) {
11067                     String valueAttr = parser.getAttributeValue(null, "v");
11068                     if (valueAttr != null) {
11069                         steps.decodeEntryAt(i, valueAttr);
11070                         i++;
11071                     }
11072                 }
11073             } else {
11074                 Slog.w(TAG, "Unknown element under <" + tag + ">: "
11075                         + parser.getName());
11076                 XmlUtils.skipCurrentTag(parser);
11077             }
11078         }
11079         steps.mNumStepDurations = i;
11080     }
11081 
11082     @Override
getDailyItemLocked(int daysAgo)11083     public DailyItem getDailyItemLocked(int daysAgo) {
11084         int index = mDailyItems.size()-1-daysAgo;
11085         return index >= 0 ? mDailyItems.get(index) : null;
11086     }
11087 
11088     @Override
getCurrentDailyStartTime()11089     public long getCurrentDailyStartTime() {
11090         return mDailyStartTimeMs;
11091     }
11092 
11093     @Override
getNextMinDailyDeadline()11094     public long getNextMinDailyDeadline() {
11095         return mNextMinDailyDeadlineMs;
11096     }
11097 
11098     @Override
getNextMaxDailyDeadline()11099     public long getNextMaxDailyDeadline() {
11100         return mNextMaxDailyDeadlineMs;
11101     }
11102 
getHistoryTotalSize()11103     public int getHistoryTotalSize() {
11104         return mConstants.MAX_HISTORY_BUFFER * mConstants.MAX_HISTORY_FILES;
11105     }
11106 
getHistoryUsedSize()11107     public int getHistoryUsedSize() {
11108         return mBatteryStatsHistory.getHistoryUsedSize();
11109     }
11110 
11111     @Override
11112     @UnsupportedAppUsage
startIteratingHistoryLocked()11113     public boolean startIteratingHistoryLocked() {
11114         mReadOverflow = false;
11115         mBatteryStatsHistoryIterator = createBatteryStatsHistoryIterator();
11116         return true;
11117     }
11118 
11119     /**
11120      * Creates an iterator for battery stats history.
11121      */
11122     @VisibleForTesting
createBatteryStatsHistoryIterator()11123     public BatteryStatsHistoryIterator createBatteryStatsHistoryIterator() {
11124         ArrayList<HistoryTag> tags = new ArrayList<>(mHistoryTagPool.size());
11125         for (Map.Entry<HistoryTag, Integer> entry: mHistoryTagPool.entrySet()) {
11126             final HistoryTag tag = entry.getKey();
11127             tag.poolIdx = entry.getValue();
11128             tags.add(tag);
11129         }
11130 
11131         return new BatteryStatsHistoryIterator(mBatteryStatsHistory, tags);
11132     }
11133 
11134     @Override
getHistoryStringPoolSize()11135     public int getHistoryStringPoolSize() {
11136         return mBatteryStatsHistoryIterator.getHistoryStringPoolSize();
11137     }
11138 
11139     @Override
getHistoryStringPoolBytes()11140     public int getHistoryStringPoolBytes() {
11141         return mBatteryStatsHistoryIterator.getHistoryStringPoolBytes();
11142     }
11143 
11144     @Override
getHistoryTagPoolString(int index)11145     public String getHistoryTagPoolString(int index) {
11146         return mBatteryStatsHistoryIterator.getHistoryTagPoolString(index);
11147     }
11148 
11149     @Override
getHistoryTagPoolUid(int index)11150     public int getHistoryTagPoolUid(int index) {
11151         return mBatteryStatsHistoryIterator.getHistoryTagPoolUid(index);
11152     }
11153 
11154     @Override
11155     @UnsupportedAppUsage
getNextHistoryLocked(HistoryItem out)11156     public boolean getNextHistoryLocked(HistoryItem out) {
11157         return mBatteryStatsHistoryIterator.next(out);
11158     }
11159 
11160     @Override
finishIteratingHistoryLocked()11161     public void finishIteratingHistoryLocked() {
11162         mBatteryStatsHistoryIterator = null;
11163     }
11164 
11165     @Override
getHistoryBaseTime()11166     public long getHistoryBaseTime() {
11167         return mHistoryBaseTimeMs;
11168     }
11169 
11170     @Override
getStartCount()11171     public int getStartCount() {
11172         return mStartCount;
11173     }
11174 
11175     @UnsupportedAppUsage
isOnBattery()11176     public boolean isOnBattery() {
11177         return mOnBattery;
11178     }
11179 
isCharging()11180     public boolean isCharging() {
11181         return mCharging;
11182     }
11183 
initTimes(long uptimeUs, long realtimeUs)11184     void initTimes(long uptimeUs, long realtimeUs) {
11185         mStartClockTimeMs = mClocks.currentTimeMillis();
11186         mOnBatteryTimeBase.init(uptimeUs, realtimeUs);
11187         mOnBatteryScreenOffTimeBase.init(uptimeUs, realtimeUs);
11188         mRealtimeUs = 0;
11189         mUptimeUs = 0;
11190         mRealtimeStartUs = realtimeUs;
11191         mUptimeStartUs = uptimeUs;
11192     }
11193 
initDischarge(long elapsedRealtimeUs)11194     void initDischarge(long elapsedRealtimeUs) {
11195         mLowDischargeAmountSinceCharge = 0;
11196         mHighDischargeAmountSinceCharge = 0;
11197         mDischargeAmountScreenOn = 0;
11198         mDischargeAmountScreenOnSinceCharge = 0;
11199         mDischargeAmountScreenOff = 0;
11200         mDischargeAmountScreenOffSinceCharge = 0;
11201         mDischargeAmountScreenDoze = 0;
11202         mDischargeAmountScreenDozeSinceCharge = 0;
11203         mDischargeStepTracker.init();
11204         mChargeStepTracker.init();
11205         mDischargeScreenOffCounter.reset(false, elapsedRealtimeUs);
11206         mDischargeScreenDozeCounter.reset(false, elapsedRealtimeUs);
11207         mDischargeLightDozeCounter.reset(false, elapsedRealtimeUs);
11208         mDischargeDeepDozeCounter.reset(false, elapsedRealtimeUs);
11209         mDischargeCounter.reset(false, elapsedRealtimeUs);
11210     }
11211 
setBatteryResetListener(BatteryResetListener batteryResetListener)11212     public void setBatteryResetListener(BatteryResetListener batteryResetListener) {
11213         mBatteryResetListener = batteryResetListener;
11214     }
11215 
resetAllStatsCmdLocked()11216     public void resetAllStatsCmdLocked() {
11217         final long mSecUptime = mClocks.uptimeMillis();
11218         long uptimeUs = mSecUptime * 1000;
11219         long mSecRealtime = mClocks.elapsedRealtime();
11220         long realtimeUs = mSecRealtime * 1000;
11221         resetAllStatsLocked(mSecUptime, mSecRealtime, RESET_REASON_ADB_COMMAND);
11222         mDischargeStartLevel = mHistoryCur.batteryLevel;
11223         pullPendingStateUpdatesLocked();
11224         addHistoryRecordLocked(mSecRealtime, mSecUptime);
11225         mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
11226                 = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
11227         mOnBatteryTimeBase.reset(uptimeUs, realtimeUs);
11228         mOnBatteryScreenOffTimeBase.reset(uptimeUs, realtimeUs);
11229         if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
11230             if (Display.isOnState(mScreenState)) {
11231                 mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
11232                 mDischargeScreenDozeUnplugLevel = 0;
11233                 mDischargeScreenOffUnplugLevel = 0;
11234             } else if (Display.isDozeState(mScreenState)) {
11235                 mDischargeScreenOnUnplugLevel = 0;
11236                 mDischargeScreenDozeUnplugLevel = mHistoryCur.batteryLevel;
11237                 mDischargeScreenOffUnplugLevel = 0;
11238             } else {
11239                 mDischargeScreenOnUnplugLevel = 0;
11240                 mDischargeScreenDozeUnplugLevel = 0;
11241                 mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
11242             }
11243             mDischargeAmountScreenOn = 0;
11244             mDischargeAmountScreenOff = 0;
11245             mDischargeAmountScreenDoze = 0;
11246         }
11247         initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
11248     }
11249 
resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis, int resetReason)11250     private void resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis,
11251             int resetReason) {
11252         if (mBatteryResetListener != null) {
11253             mBatteryResetListener.prepareForBatteryStatsReset(resetReason);
11254         }
11255 
11256         final long uptimeUs = uptimeMillis * 1000;
11257         final long elapsedRealtimeUs = elapsedRealtimeMillis * 1000;
11258         mStartCount = 0;
11259         initTimes(uptimeUs, elapsedRealtimeUs);
11260         mScreenOnTimer.reset(false, elapsedRealtimeUs);
11261         mScreenDozeTimer.reset(false, elapsedRealtimeUs);
11262         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11263             mScreenBrightnessTimer[i].reset(false, elapsedRealtimeUs);
11264         }
11265 
11266         if (mPowerProfile != null) {
11267             mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
11268         } else {
11269             mEstimatedBatteryCapacityMah = -1;
11270         }
11271         mLastLearnedBatteryCapacityUah = -1;
11272         mMinLearnedBatteryCapacityUah = -1;
11273         mMaxLearnedBatteryCapacityUah = -1;
11274         mInteractiveTimer.reset(false, elapsedRealtimeUs);
11275         mPowerSaveModeEnabledTimer.reset(false, elapsedRealtimeUs);
11276         mLastIdleTimeStartMs = elapsedRealtimeMillis;
11277         mLongestLightIdleTimeMs = 0;
11278         mLongestFullIdleTimeMs = 0;
11279         mDeviceIdleModeLightTimer.reset(false, elapsedRealtimeUs);
11280         mDeviceIdleModeFullTimer.reset(false, elapsedRealtimeUs);
11281         mDeviceLightIdlingTimer.reset(false, elapsedRealtimeUs);
11282         mDeviceIdlingTimer.reset(false, elapsedRealtimeUs);
11283         mPhoneOnTimer.reset(false, elapsedRealtimeUs);
11284         mAudioOnTimer.reset(false, elapsedRealtimeUs);
11285         mVideoOnTimer.reset(false, elapsedRealtimeUs);
11286         mFlashlightOnTimer.reset(false, elapsedRealtimeUs);
11287         mCameraOnTimer.reset(false, elapsedRealtimeUs);
11288         mBluetoothScanTimer.reset(false, elapsedRealtimeUs);
11289         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
11290             mPhoneSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs);
11291         }
11292         mPhoneSignalScanningTimer.reset(false, elapsedRealtimeUs);
11293         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11294             mPhoneDataConnectionsTimer[i].reset(false, elapsedRealtimeUs);
11295         }
11296         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11297             mNetworkByteActivityCounters[i].reset(false, elapsedRealtimeUs);
11298             mNetworkPacketActivityCounters[i].reset(false, elapsedRealtimeUs);
11299         }
11300         mMobileRadioActiveTimer.reset(false, elapsedRealtimeUs);
11301         mMobileRadioActivePerAppTimer.reset(false, elapsedRealtimeUs);
11302         mMobileRadioActiveAdjustedTime.reset(false, elapsedRealtimeUs);
11303         mMobileRadioActiveUnknownTime.reset(false, elapsedRealtimeUs);
11304         mMobileRadioActiveUnknownCount.reset(false, elapsedRealtimeUs);
11305         mWifiOnTimer.reset(false, elapsedRealtimeUs);
11306         mGlobalWifiRunningTimer.reset(false, elapsedRealtimeUs);
11307         for (int i=0; i<NUM_WIFI_STATES; i++) {
11308             mWifiStateTimer[i].reset(false, elapsedRealtimeUs);
11309         }
11310         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11311             mWifiSupplStateTimer[i].reset(false, elapsedRealtimeUs);
11312         }
11313         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11314             mWifiSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs);
11315         }
11316         mWifiMulticastWakelockTimer.reset(false, elapsedRealtimeUs);
11317         mWifiActiveTimer.reset(false, elapsedRealtimeUs);
11318         mWifiActivity.reset(false, elapsedRealtimeUs);
11319         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
11320             mGpsSignalQualityTimer[i].reset(false, elapsedRealtimeUs);
11321         }
11322         mBluetoothActivity.reset(false, elapsedRealtimeUs);
11323         mModemActivity.reset(false, elapsedRealtimeUs);
11324         mNumConnectivityChange = 0;
11325 
11326         for (int i=0; i<mUidStats.size(); i++) {
11327             if (mUidStats.valueAt(i).reset(uptimeUs, elapsedRealtimeUs)) {
11328                 mUidStats.valueAt(i).detachFromTimeBase();
11329                 mUidStats.remove(mUidStats.keyAt(i));
11330                 i--;
11331             }
11332         }
11333 
11334         if (mRpmStats.size() > 0) {
11335             for (SamplingTimer timer : mRpmStats.values()) {
11336                 mOnBatteryTimeBase.remove(timer);
11337             }
11338             mRpmStats.clear();
11339         }
11340         if (mScreenOffRpmStats.size() > 0) {
11341             for (SamplingTimer timer : mScreenOffRpmStats.values()) {
11342                 mOnBatteryScreenOffTimeBase.remove(timer);
11343             }
11344             mScreenOffRpmStats.clear();
11345         }
11346 
11347         if (mKernelWakelockStats.size() > 0) {
11348             for (SamplingTimer timer : mKernelWakelockStats.values()) {
11349                 mOnBatteryScreenOffTimeBase.remove(timer);
11350             }
11351             mKernelWakelockStats.clear();
11352         }
11353 
11354         if (mKernelMemoryStats.size() > 0) {
11355             for (int i = 0; i < mKernelMemoryStats.size(); i++) {
11356                 mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i));
11357             }
11358             mKernelMemoryStats.clear();
11359         }
11360 
11361         if (mWakeupReasonStats.size() > 0) {
11362             for (SamplingTimer timer : mWakeupReasonStats.values()) {
11363                 mOnBatteryTimeBase.remove(timer);
11364             }
11365             mWakeupReasonStats.clear();
11366         }
11367 
11368         mTmpRailStats.reset();
11369 
11370         MeasuredEnergyStats.resetIfNotNull(mGlobalMeasuredEnergyStats);
11371 
11372         resetIfNotNull(mBinderThreadCpuTimesUs, false, elapsedRealtimeUs);
11373 
11374         mLastHistoryStepDetails = null;
11375         mLastStepCpuUserTimeMs = mLastStepCpuSystemTimeMs = 0;
11376         mCurStepCpuUserTimeMs = mCurStepCpuSystemTimeMs = 0;
11377         mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs = 0;
11378         mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs = 0;
11379         mLastStepStatUserTimeMs = mCurStepStatUserTimeMs = 0;
11380         mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs = 0;
11381         mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs = 0;
11382         mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs = 0;
11383         mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs = 0;
11384         mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs = 0;
11385 
11386         mNumAllUidCpuTimeReads = 0;
11387         mNumUidsRemoved = 0;
11388 
11389         initDischarge(elapsedRealtimeUs);
11390 
11391         clearHistoryLocked();
11392         if (mBatteryStatsHistory != null) {
11393             mBatteryStatsHistory.resetAllFiles();
11394         }
11395 
11396         // Flush external data, gathering snapshots, but don't process it since it is pre-reset data
11397         mIgnoreNextExternalStats = true;
11398         mExternalSync.scheduleSync("reset", ExternalStatsSync.UPDATE_ALL);
11399 
11400         mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
11401     }
11402 
initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs)11403     private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
11404         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
11405             if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
11406                 // Not recording process starts/stops.
11407                 continue;
11408             }
11409             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
11410             if (active == null) {
11411                 continue;
11412             }
11413             for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
11414                 SparseIntArray uids = ent.getValue();
11415                 for (int j=0; j<uids.size(); j++) {
11416                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
11417                             uids.keyAt(j));
11418                 }
11419             }
11420         }
11421     }
11422 
updateDischargeScreenLevelsLocked(int oldState, int newState)11423     void updateDischargeScreenLevelsLocked(int oldState, int newState) {
11424         updateOldDischargeScreenLevelLocked(oldState);
11425         updateNewDischargeScreenLevelLocked(newState);
11426     }
11427 
updateOldDischargeScreenLevelLocked(int state)11428     private void updateOldDischargeScreenLevelLocked(int state) {
11429         if (Display.isOnState(state)) {
11430             int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
11431             if (diff > 0) {
11432                 mDischargeAmountScreenOn += diff;
11433                 mDischargeAmountScreenOnSinceCharge += diff;
11434             }
11435         } else if (Display.isDozeState(state)) {
11436             int diff = mDischargeScreenDozeUnplugLevel - mDischargeCurrentLevel;
11437             if (diff > 0) {
11438                 mDischargeAmountScreenDoze += diff;
11439                 mDischargeAmountScreenDozeSinceCharge += diff;
11440             }
11441         } else if (Display.isOffState(state)) {
11442             int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
11443             if (diff > 0) {
11444                 mDischargeAmountScreenOff += diff;
11445                 mDischargeAmountScreenOffSinceCharge += diff;
11446             }
11447         }
11448     }
11449 
updateNewDischargeScreenLevelLocked(int state)11450     private void updateNewDischargeScreenLevelLocked(int state) {
11451         if (Display.isOnState(state)) {
11452             mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
11453             mDischargeScreenOffUnplugLevel = 0;
11454             mDischargeScreenDozeUnplugLevel = 0;
11455         } else if (Display.isDozeState(state)) {
11456             mDischargeScreenOnUnplugLevel = 0;
11457             mDischargeScreenDozeUnplugLevel = mDischargeCurrentLevel;
11458             mDischargeScreenOffUnplugLevel = 0;
11459         } else if (Display.isOffState(state)) {
11460             mDischargeScreenOnUnplugLevel = 0;
11461             mDischargeScreenDozeUnplugLevel = 0;
11462             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
11463         }
11464     }
11465 
pullPendingStateUpdatesLocked()11466     public void pullPendingStateUpdatesLocked() {
11467         if (mOnBatteryInternal) {
11468             updateDischargeScreenLevelsLocked(mScreenState, mScreenState);
11469         }
11470     }
11471 
11472     private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6);
11473 
11474     private final Object mWifiNetworkLock = new Object();
11475 
11476     @GuardedBy("mWifiNetworkLock")
11477     private String[] mWifiIfaces = EmptyArray.STRING;
11478 
11479     @GuardedBy("mWifiNetworkLock")
11480     private NetworkStats mLastWifiNetworkStats = new NetworkStats(0, -1);
11481 
11482     private final Object mModemNetworkLock = new Object();
11483 
11484     @GuardedBy("mModemNetworkLock")
11485     private String[] mModemIfaces = EmptyArray.STRING;
11486 
11487     @GuardedBy("mModemNetworkLock")
11488     private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
11489 
11490     @VisibleForTesting
readNetworkStatsLocked(String[] ifaces)11491     protected NetworkStats readNetworkStatsLocked(String[] ifaces) {
11492         try {
11493             if (!ArrayUtils.isEmpty(ifaces)) {
11494                 INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
11495                         ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
11496                 if (statsService != null) {
11497                     return statsService.getDetailedUidStats(ifaces);
11498                 } else {
11499                     Slog.e(TAG, "Failed to get networkStatsService ");
11500                 }
11501             }
11502         } catch (RemoteException e) {
11503             Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces) + e);
11504         }
11505         return null;
11506     }
11507 
11508     /**
11509      * Distribute WiFi energy info and network traffic to apps.
11510      * @param info The energy information from the WiFi controller.
11511      */
updateWifiState(@ullable final WifiActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs)11512     public void updateWifiState(@Nullable final WifiActivityEnergyInfo info,
11513             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
11514         if (DEBUG_ENERGY) {
11515             Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
11516         }
11517 
11518         // Grab a separate lock to acquire the network stats, which may do I/O.
11519         NetworkStats delta = null;
11520         synchronized (mWifiNetworkLock) {
11521             final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces);
11522             if (latestStats != null) {
11523                 delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null,
11524                         mNetworkStatsPool.acquire());
11525                 mNetworkStatsPool.release(mLastWifiNetworkStats);
11526                 mLastWifiNetworkStats = latestStats;
11527             }
11528         }
11529 
11530         synchronized (this) {
11531             if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
11532                 if (delta != null) {
11533                     mNetworkStatsPool.release(delta);
11534                 }
11535                 if (mIgnoreNextExternalStats) {
11536                     // TODO: Strictly speaking, we should re-mark all 5 timers for each uid (and the
11537                     //  global one) here like we do for display. But I'm not sure it's worth the
11538                     //  complicated code for a codepath that shouldn't ever actually happen in real
11539                     //  life.
11540                 }
11541                 return;
11542             }
11543 
11544             final SparseDoubleArray uidEstimatedConsumptionMah =
11545                     (mGlobalMeasuredEnergyStats != null
11546                             && mWifiPowerCalculator != null && consumedChargeUC > 0) ?
11547                             new SparseDoubleArray() : null;
11548             double totalEstimatedConsumptionMah = 0;
11549 
11550             SparseLongArray rxPackets = new SparseLongArray();
11551             SparseLongArray txPackets = new SparseLongArray();
11552             long totalTxPackets = 0;
11553             long totalRxPackets = 0;
11554             if (delta != null) {
11555                 NetworkStats.Entry entry = new NetworkStats.Entry();
11556                 final int size = delta.size();
11557                 for (int i = 0; i < size; i++) {
11558                     entry = delta.getValues(i, entry);
11559 
11560                     if (DEBUG_ENERGY) {
11561                         Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
11562                                 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
11563                                 + " txPackets=" + entry.txPackets);
11564                     }
11565 
11566                     if (entry.rxBytes == 0 && entry.txBytes == 0) {
11567                         // Skip the lookup below since there is no work to do.
11568                         continue;
11569                     }
11570 
11571                     final Uid u = getUidStatsLocked(mapUid(entry.uid), elapsedRealtimeMs, uptimeMs);
11572                     if (entry.rxBytes != 0) {
11573                         u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
11574                                 entry.rxPackets);
11575                         if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11576                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
11577                                     entry.rxPackets);
11578                         }
11579                         mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
11580                                 entry.rxBytes);
11581                         mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
11582                                 entry.rxPackets);
11583 
11584                         // TODO(b/182845426): What if u was a mapped isolated uid? Shouldn't we sum?
11585                         rxPackets.put(u.getUid(), entry.rxPackets);
11586 
11587                         // Sum the total number of packets so that the Rx Power can
11588                         // be evenly distributed amongst the apps.
11589                         totalRxPackets += entry.rxPackets;
11590                     }
11591 
11592                     if (entry.txBytes != 0) {
11593                         u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
11594                                 entry.txPackets);
11595                         if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11596                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
11597                                     entry.txPackets);
11598                         }
11599                         mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
11600                                 entry.txBytes);
11601                         mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
11602                                 entry.txPackets);
11603 
11604                         // TODO(b/182845426): What if u was a mapped isolated uid? Shouldn't we sum?
11605                         txPackets.put(u.getUid(), entry.txPackets);
11606 
11607                         // Sum the total number of packets so that the Tx Power can
11608                         // be evenly distributed amongst the apps.
11609                         totalTxPackets += entry.txPackets;
11610                     }
11611 
11612                     // Calculate consumed energy for this uid. Only do so if WifiReporting isn't
11613                     // enabled (if it is, we'll do it later instead using info).
11614                     if (uidEstimatedConsumptionMah != null && info == null && !mHasWifiReporting) {
11615                         final long uidRunningMs = u.mWifiRunningTimer
11616                                 .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
11617                         if (uidRunningMs > 0) u.mWifiRunningTimer.setMark(elapsedRealtimeMs);
11618 
11619                         final long uidScanMs = u.mWifiScanTimer
11620                                 .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
11621                         if (uidScanMs > 0) u.mWifiScanTimer.setMark(elapsedRealtimeMs);
11622 
11623                         long uidBatchScanMs = 0;
11624                         for (int bn = 0; bn < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bn++) {
11625                             if (u.mWifiBatchedScanTimer[bn] != null) {
11626                                 long bnMs = u.mWifiBatchedScanTimer[bn]
11627                                         .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
11628                                 if (bnMs > 0) {
11629                                     u.mWifiBatchedScanTimer[bn].setMark(elapsedRealtimeMs);
11630                                 }
11631                                 uidBatchScanMs += bnMs;
11632                             }
11633                         }
11634 
11635                         uidEstimatedConsumptionMah.add(u.getUid(),
11636                                 mWifiPowerCalculator.calcPowerWithoutControllerDataMah(
11637                                         entry.rxPackets, entry.txPackets,
11638                                         uidRunningMs, uidScanMs, uidBatchScanMs));
11639                     }
11640                 }
11641                 mNetworkStatsPool.release(delta);
11642                 delta = null;
11643             }
11644 
11645             if (info != null) {
11646                 mHasWifiReporting = true;
11647 
11648                 // Measured in mAms
11649                 final long txTimeMs = info.getControllerTxDurationMillis();
11650                 final long rxTimeMs = info.getControllerRxDurationMillis();
11651                 final long scanTimeMs = info.getControllerScanDurationMillis();
11652                 final long idleTimeMs = info.getControllerIdleDurationMillis();
11653                 final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
11654 
11655                 long leftOverRxTimeMs = rxTimeMs;
11656                 long leftOverTxTimeMs = txTimeMs;
11657 
11658                 if (DEBUG_ENERGY) {
11659                     Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
11660                     Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
11661                     Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
11662                     Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
11663                     Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
11664                     Slog.d(TAG, "  Scan Time:  " + scanTimeMs + " ms");
11665                 }
11666 
11667                 long totalWifiLockTimeMs = 0;
11668                 long totalScanTimeMs = 0;
11669 
11670                 // On the first pass, collect some totals so that we can normalize power
11671                 // calculations if we need to.
11672                 final int uidStatsSize = mUidStats.size();
11673                 for (int i = 0; i < uidStatsSize; i++) {
11674                     final Uid uid = mUidStats.valueAt(i);
11675 
11676                     // Sum the total scan power for all apps.
11677                     totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
11678                             elapsedRealtimeMs * 1000) / 1000;
11679 
11680                     // Sum the total time holding wifi lock for all apps.
11681                     totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
11682                             elapsedRealtimeMs * 1000) / 1000;
11683                 }
11684 
11685                 if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
11686                     Slog.d(TAG,
11687                             "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
11688                                     + rxTimeMs + " ms). Normalizing scan time.");
11689                 }
11690                 if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
11691                     Slog.d(TAG,
11692                             "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
11693                                     + txTimeMs + " ms). Normalizing scan time.");
11694                 }
11695 
11696                 // Actually assign and distribute power usage to apps.
11697                 for (int i = 0; i < uidStatsSize; i++) {
11698                     final Uid uid = mUidStats.valueAt(i);
11699 
11700                     final long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
11701                             elapsedRealtimeMs * 1000) / 1000;
11702                     long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
11703                     long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
11704                     if (scanTimeSinceMarkMs > 0) {
11705                         // Set the new mark so that next time we get new data since this point.
11706                         uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
11707 
11708                         // Our total scan time is more than the reported Tx/Rx time.
11709                         // This is possible because the cost of a scan is approximate.
11710                         // Let's normalize the result so that we evenly blame each app
11711                         // scanning.
11712                         //
11713                         // This means that we may have apps that transmitted/received packets not be
11714                         // blamed for this, but this is fine as scans are relatively more expensive.
11715                         if (totalScanTimeMs > rxTimeMs) {
11716                             scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
11717                                     totalScanTimeMs;
11718                         }
11719                         if (totalScanTimeMs > txTimeMs) {
11720                             scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
11721                                     totalScanTimeMs;
11722                         }
11723 
11724                         if (DEBUG_ENERGY) {
11725                             Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
11726                                     + scanRxTimeSinceMarkMs + " ms  Tx:"
11727                                     + scanTxTimeSinceMarkMs + " ms)");
11728                         }
11729 
11730                         ControllerActivityCounterImpl activityCounter =
11731                                 uid.getOrCreateWifiControllerActivityLocked();
11732                         activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
11733                         activityCounter.getTxTimeCounters()[0].addCountLocked(
11734                                 scanTxTimeSinceMarkMs);
11735                         leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
11736                         leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
11737                     }
11738 
11739                     // Distribute evenly the power consumed while Idle to each app holding a WiFi
11740                     // lock.
11741                     long myIdleTimeMs = 0;
11742                     final long wifiLockTimeSinceMarkMs =
11743                             uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
11744                                     elapsedRealtimeMs * 1000) / 1000;
11745                     if (wifiLockTimeSinceMarkMs > 0) {
11746                         // Set the new mark so that next time we get new data since this point.
11747                         uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
11748 
11749                         myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs) / totalWifiLockTimeMs;
11750                         if (DEBUG_ENERGY) {
11751                             Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
11752                                     + myIdleTimeMs + " ms");
11753                         }
11754                         uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
11755                                 .addCountLocked(myIdleTimeMs);
11756                     }
11757 
11758                     if (uidEstimatedConsumptionMah != null) {
11759                         double uidEstMah = mWifiPowerCalculator.calcPowerFromControllerDataMah(
11760                                 scanRxTimeSinceMarkMs, scanTxTimeSinceMarkMs, myIdleTimeMs);
11761                         uidEstimatedConsumptionMah.add(uid.getUid(), uidEstMah);
11762                     }
11763                 }
11764 
11765                 if (DEBUG_ENERGY) {
11766                     Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
11767                     Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
11768                 }
11769 
11770                 // Distribute the remaining Tx power appropriately between all apps that transmitted
11771                 // packets.
11772                 for (int i = 0; i < txPackets.size(); i++) {
11773                     final Uid uid = getUidStatsLocked(txPackets.keyAt(i),
11774                             elapsedRealtimeMs, uptimeMs);
11775                     final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
11776                             / totalTxPackets;
11777                     if (DEBUG_ENERGY) {
11778                         Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
11779                     }
11780                     uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
11781                             .addCountLocked(myTxTimeMs);
11782                     if (uidEstimatedConsumptionMah != null) {
11783                         uidEstimatedConsumptionMah.add(uid.getUid(),
11784                                 mWifiPowerCalculator.calcPowerFromControllerDataMah(
11785                                         0, myTxTimeMs, 0));
11786                     }
11787                 }
11788 
11789                 // Distribute the remaining Rx power appropriately between all apps that received
11790                 // packets.
11791                 for (int i = 0; i < rxPackets.size(); i++) {
11792                     final Uid uid = getUidStatsLocked(rxPackets.keyAt(i),
11793                             elapsedRealtimeMs, uptimeMs);
11794                     final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
11795                             / totalRxPackets;
11796                     if (DEBUG_ENERGY) {
11797                         Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
11798                     }
11799                     uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
11800                             .addCountLocked(myRxTimeMs);
11801                     if (uidEstimatedConsumptionMah != null) {
11802                         uidEstimatedConsumptionMah.add(uid.getUid(),
11803                                 mWifiPowerCalculator.calcPowerFromControllerDataMah(
11804                                         myRxTimeMs, 0, 0));
11805                     }
11806                 }
11807 
11808                 // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
11809 
11810 
11811                 // Update WiFi controller stats.
11812                 mWifiActivity.getRxTimeCounter().addCountLocked(
11813                         info.getControllerRxDurationMillis());
11814                 mWifiActivity.getTxTimeCounters()[0].addCountLocked(
11815                         info.getControllerTxDurationMillis());
11816                 mWifiActivity.getScanTimeCounter().addCountLocked(
11817                         info.getControllerScanDurationMillis());
11818                 mWifiActivity.getIdleTimeCounter().addCountLocked(
11819                         info.getControllerIdleDurationMillis());
11820 
11821                 // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11822                 final double opVolt = mPowerProfile.getAveragePower(
11823                         PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11824                 double controllerMaMs = 0;
11825                 if (opVolt != 0) {
11826                     // We store the power drain as mAms.
11827                     controllerMaMs = info.getControllerEnergyUsedMicroJoules() / opVolt;
11828                     mWifiActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
11829                 }
11830                 // Converting uWs to mAms.
11831                 // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
11832                 long monitoredRailChargeConsumedMaMs =
11833                         (long) (mTmpRailStats.getWifiTotalEnergyUseduWs() / opVolt);
11834                 mWifiActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
11835                         monitoredRailChargeConsumedMaMs);
11836                 mHistoryCur.wifiRailChargeMah +=
11837                         (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
11838                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
11839                 mTmpRailStats.resetWifiTotalEnergyUsed();
11840 
11841                 if (uidEstimatedConsumptionMah != null) {
11842                     totalEstimatedConsumptionMah = Math.max(controllerMaMs / MILLISECONDS_IN_HOUR,
11843                             mWifiPowerCalculator.calcPowerFromControllerDataMah(
11844                                     rxTimeMs, txTimeMs, idleTimeMs));
11845                 }
11846             }
11847 
11848             // Update the MeasuredEnergyStats information.
11849             if (uidEstimatedConsumptionMah != null) {
11850                 mGlobalMeasuredEnergyStats.updateStandardBucket(
11851                         MeasuredEnergyStats.POWER_BUCKET_WIFI, consumedChargeUC);
11852 
11853                 // Now calculate the consumption for each uid, according to its proportional usage.
11854                 if (!mHasWifiReporting) {
11855                     final long globalTimeMs = mGlobalWifiRunningTimer
11856                             .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
11857                     mGlobalWifiRunningTimer.setMark(elapsedRealtimeMs);
11858                     totalEstimatedConsumptionMah = mWifiPowerCalculator
11859                             .calcGlobalPowerWithoutControllerDataMah(globalTimeMs);
11860                 }
11861                 distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_WIFI,
11862                         consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedConsumptionMah);
11863             }
11864         }
11865     }
11866 
11867     private ModemActivityInfo mLastModemActivityInfo = null;
11868 
11869     /**
11870      * Distribute Cell radio energy info and network traffic to apps.
11871      */
noteModemControllerActivity(@ullable final ModemActivityInfo activityInfo, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs)11872     public void noteModemControllerActivity(@Nullable final ModemActivityInfo activityInfo,
11873             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
11874         if (DEBUG_ENERGY) {
11875             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
11876         }
11877         ModemActivityInfo deltaInfo = mLastModemActivityInfo == null ? activityInfo
11878                 : mLastModemActivityInfo.getDelta(activityInfo);
11879         mLastModemActivityInfo = activityInfo;
11880 
11881         // Add modem tx power to history.
11882         addModemTxPowerToHistory(deltaInfo, elapsedRealtimeMs, uptimeMs);
11883 
11884         // Grab a separate lock to acquire the network stats, which may do I/O.
11885         NetworkStats delta = null;
11886         synchronized (mModemNetworkLock) {
11887             final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces);
11888             if (latestStats != null) {
11889                 delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null,
11890                         mNetworkStatsPool.acquire());
11891                 mNetworkStatsPool.release(mLastModemNetworkStats);
11892                 mLastModemNetworkStats = latestStats;
11893             }
11894         }
11895 
11896         synchronized (this) {
11897             if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
11898                 if (delta != null) {
11899                     mNetworkStatsPool.release(delta);
11900                 }
11901                 return;
11902             }
11903 
11904             final SparseDoubleArray uidEstimatedConsumptionMah;
11905             if (consumedChargeUC > 0 && mMobileRadioPowerCalculator != null
11906                     && mGlobalMeasuredEnergyStats != null) {
11907                 mGlobalMeasuredEnergyStats.updateStandardBucket(
11908                         MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO, consumedChargeUC);
11909                 uidEstimatedConsumptionMah = new SparseDoubleArray();
11910             } else {
11911                 uidEstimatedConsumptionMah = null;
11912             }
11913 
11914             if (deltaInfo != null) {
11915                 mHasModemReporting = true;
11916                 mModemActivity.getIdleTimeCounter().addCountLocked(
11917                         deltaInfo.getIdleTimeMillis());
11918                 mModemActivity.getSleepTimeCounter().addCountLocked(
11919                         deltaInfo.getSleepTimeMillis());
11920                 mModemActivity.getRxTimeCounter().addCountLocked(deltaInfo.getReceiveTimeMillis());
11921                 for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels(); lvl++) {
11922                     mModemActivity.getTxTimeCounters()[lvl]
11923                         .addCountLocked(deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl));
11924                 }
11925 
11926                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11927                 final double opVolt = mPowerProfile.getAveragePower(
11928                     PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11929                 if (opVolt != 0) {
11930                     double energyUsed =
11931                             deltaInfo.getSleepTimeMillis() *
11932                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
11933                             + deltaInfo.getIdleTimeMillis() *
11934                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
11935                             + deltaInfo.getReceiveTimeMillis() *
11936                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
11937                     for (int i = 0; i < Math.min(ModemActivityInfo.getNumTxPowerLevels(),
11938                             CellSignalStrength.getNumSignalStrengthLevels()); i++) {
11939                         energyUsed += deltaInfo.getTransmitDurationMillisAtPowerLevel(i)
11940                                 * mPowerProfile.getAveragePower(
11941                                         PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
11942                     }
11943 
11944                     // We store the power drain as mAms.
11945                     mModemActivity.getPowerCounter().addCountLocked((long) energyUsed);
11946                     // Converting uWs to mAms.
11947                     // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
11948                     long monitoredRailChargeConsumedMaMs =
11949                             (long) (mTmpRailStats.getCellularTotalEnergyUseduWs() / opVolt);
11950                     mModemActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
11951                             monitoredRailChargeConsumedMaMs);
11952                     mHistoryCur.modemRailChargeMah +=
11953                             (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
11954                     addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
11955                     mTmpRailStats.resetCellularTotalEnergyUsed();
11956                 }
11957             }
11958             long totalAppRadioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
11959                     elapsedRealtimeMs * 1000);
11960             mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
11961 
11962             long totalRxPackets = 0;
11963             long totalTxPackets = 0;
11964             if (delta != null) {
11965                 NetworkStats.Entry entry = new NetworkStats.Entry();
11966                 final int size = delta.size();
11967                 for (int i = 0; i < size; i++) {
11968                     entry = delta.getValues(i, entry);
11969                     if (entry.rxPackets == 0 && entry.txPackets == 0) {
11970                         continue;
11971                     }
11972 
11973                     if (DEBUG_ENERGY) {
11974                         Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
11975                                 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
11976                                 + " txPackets=" + entry.txPackets);
11977                     }
11978 
11979                     totalRxPackets += entry.rxPackets;
11980                     totalTxPackets += entry.txPackets;
11981 
11982                     final Uid u = getUidStatsLocked(mapUid(entry.uid), elapsedRealtimeMs, uptimeMs);
11983                     u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
11984                             entry.rxPackets);
11985                     u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
11986                             entry.txPackets);
11987                     if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11988                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
11989                                 entry.rxBytes, entry.rxPackets);
11990                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
11991                                 entry.txBytes, entry.txPackets);
11992                     }
11993 
11994                     mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
11995                             entry.rxBytes);
11996                     mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
11997                             entry.txBytes);
11998                     mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
11999                             entry.rxPackets);
12000                     mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
12001                             entry.txPackets);
12002                 }
12003 
12004                 // Now distribute proportional blame to the apps that did networking.
12005                 long totalPackets = totalRxPackets + totalTxPackets;
12006                 if (totalPackets > 0) {
12007                     for (int i = 0; i < size; i++) {
12008                         entry = delta.getValues(i, entry);
12009                         if (entry.rxPackets == 0 && entry.txPackets == 0) {
12010                             continue;
12011                         }
12012 
12013                         final Uid u = getUidStatsLocked(mapUid(entry.uid),
12014                                 elapsedRealtimeMs, uptimeMs);
12015 
12016                         // Distribute total radio active time in to this app.
12017                         final long appPackets = entry.rxPackets + entry.txPackets;
12018                         final long appRadioTimeUs =
12019                                 (totalAppRadioTimeUs * appPackets) / totalPackets;
12020                         u.noteMobileRadioActiveTimeLocked(appRadioTimeUs);
12021 
12022                         // Distribute measured mobile radio charge consumption based on app radio
12023                         // active time
12024                         if (uidEstimatedConsumptionMah != null) {
12025                             uidEstimatedConsumptionMah.add(u.getUid(),
12026                                     mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
12027                                             appRadioTimeUs / 1000));
12028                         }
12029 
12030                         // Remove this app from the totals, so that we don't lose any time
12031                         // due to rounding.
12032                         totalAppRadioTimeUs -= appRadioTimeUs;
12033                         totalPackets -= appPackets;
12034 
12035                         if (deltaInfo != null) {
12036                             ControllerActivityCounterImpl activityCounter =
12037                                     u.getOrCreateModemControllerActivityLocked();
12038                             if (totalRxPackets > 0 && entry.rxPackets > 0) {
12039                                 final long rxMs = (entry.rxPackets
12040                                     * deltaInfo.getReceiveTimeMillis()) / totalRxPackets;
12041                                 activityCounter.getRxTimeCounter().addCountLocked(rxMs);
12042                             }
12043 
12044                             if (totalTxPackets > 0 && entry.txPackets > 0) {
12045                                 for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels();
12046                                         lvl++) {
12047                                     long txMs = entry.txPackets
12048                                             * deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl);
12049                                     txMs /= totalTxPackets;
12050                                     activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
12051                                 }
12052                             }
12053                         }
12054                     }
12055                 }
12056 
12057                 if (totalAppRadioTimeUs > 0) {
12058                     // Whoops, there is some radio time we can't blame on an app!
12059                     mMobileRadioActiveUnknownTime.addCountLocked(totalAppRadioTimeUs);
12060                     mMobileRadioActiveUnknownCount.addCountLocked(1);
12061                 }
12062 
12063 
12064                 // Update the MeasuredEnergyStats information.
12065                 if (uidEstimatedConsumptionMah != null) {
12066                     double totalEstimatedConsumptionMah = 0.0;
12067 
12068                     // Estimate total active radio power consumption since last mark.
12069                     final long totalRadioTimeMs = mMobileRadioActiveTimer.getTimeSinceMarkLocked(
12070                             elapsedRealtimeMs * 1000) / 1000;
12071                     mMobileRadioActiveTimer.setMark(elapsedRealtimeMs);
12072                     totalEstimatedConsumptionMah +=
12073                             mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
12074                                     totalRadioTimeMs);
12075 
12076                     // Estimate idle power consumption at each signal strength level
12077                     final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length;
12078                     for (int strengthLevel = 0; strengthLevel < numSignalStrengthLevels;
12079                             strengthLevel++) {
12080                         final long strengthLevelDurationMs =
12081                                 mPhoneSignalStrengthsTimer[strengthLevel].getTimeSinceMarkLocked(
12082                                         elapsedRealtimeMs * 1000) / 1000;
12083                         mPhoneSignalStrengthsTimer[strengthLevel].setMark(elapsedRealtimeMs);
12084 
12085                         totalEstimatedConsumptionMah +=
12086                                 mMobileRadioPowerCalculator.calcIdlePowerAtSignalStrengthMah(
12087                                         strengthLevelDurationMs, strengthLevel);
12088                     }
12089 
12090                     // Estimate total active radio power consumption since last mark.
12091                     final long scanTimeMs = mPhoneSignalScanningTimer.getTimeSinceMarkLocked(
12092                             elapsedRealtimeMs * 1000) / 1000;
12093                     mPhoneSignalScanningTimer.setMark(elapsedRealtimeMs);
12094                     totalEstimatedConsumptionMah +=
12095                             mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs);
12096 
12097                     distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO,
12098                             consumedChargeUC, uidEstimatedConsumptionMah,
12099                             totalEstimatedConsumptionMah);
12100                 }
12101 
12102                 mNetworkStatsPool.release(delta);
12103                 delta = null;
12104             }
12105         }
12106     }
12107 
12108     /**
12109      * Add modem tx power to history
12110      * Device is said to be in high cellular transmit power when it has spent most of the transmit
12111      * time at the highest power level.
12112      * @param activityInfo
12113      */
addModemTxPowerToHistory(final ModemActivityInfo activityInfo, long elapsedRealtimeMs, long uptimeMs)12114     private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo,
12115             long elapsedRealtimeMs, long uptimeMs) {
12116         if (activityInfo == null) {
12117             return;
12118         }
12119         int levelMaxTimeSpent = 0;
12120         for (int i = 1; i < ModemActivityInfo.getNumTxPowerLevels(); i++) {
12121             if (activityInfo.getTransmitDurationMillisAtPowerLevel(i)
12122                     > activityInfo.getTransmitDurationMillisAtPowerLevel(levelMaxTimeSpent)) {
12123                 levelMaxTimeSpent = i;
12124             }
12125         }
12126         if (levelMaxTimeSpent == ModemActivityInfo.getNumTxPowerLevels() - 1) {
12127             mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
12128             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
12129         }
12130     }
12131 
12132     private final class BluetoothActivityInfoCache {
12133         long idleTimeMs;
12134         long rxTimeMs;
12135         long txTimeMs;
12136         long energy;
12137 
12138         SparseLongArray uidRxBytes = new SparseLongArray();
12139         SparseLongArray uidTxBytes = new SparseLongArray();
12140 
set(BluetoothActivityEnergyInfo info)12141         void set(BluetoothActivityEnergyInfo info) {
12142             idleTimeMs = info.getControllerIdleTimeMillis();
12143             rxTimeMs = info.getControllerRxTimeMillis();
12144             txTimeMs = info.getControllerTxTimeMillis();
12145             energy = info.getControllerEnergyUsed();
12146             if (info.getUidTraffic() != null) {
12147                 for (UidTraffic traffic : info.getUidTraffic()) {
12148                     uidRxBytes.put(traffic.getUid(), traffic.getRxBytes());
12149                     uidTxBytes.put(traffic.getUid(), traffic.getTxBytes());
12150                 }
12151             }
12152         }
12153 
reset()12154         void reset() {
12155             idleTimeMs = 0;
12156             rxTimeMs = 0;
12157             txTimeMs = 0;
12158             energy = 0;
12159             uidRxBytes.clear();
12160             uidTxBytes.clear();
12161         }
12162     }
12163 
12164     private final BluetoothActivityInfoCache mLastBluetoothActivityInfo
12165             = new BluetoothActivityInfoCache();
12166 
12167     /**
12168      * Distribute Bluetooth energy info and network traffic to apps.
12169      *
12170      * @param info The accumulated energy information from the bluetooth controller.
12171      */
updateBluetoothStateLocked(@ullable final BluetoothActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs)12172     public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info,
12173             final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
12174         if (DEBUG_ENERGY) {
12175             Slog.d(TAG, "Updating bluetooth stats: " + info);
12176         }
12177 
12178         if (info == null) {
12179             return;
12180         }
12181         if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
12182             mLastBluetoothActivityInfo.set(info);
12183             return;
12184         }
12185 
12186         mHasBluetoothReporting = true;
12187 
12188         if (info.getControllerRxTimeMillis() < mLastBluetoothActivityInfo.rxTimeMs
12189                 || info.getControllerTxTimeMillis() < mLastBluetoothActivityInfo.txTimeMs
12190                 || info.getControllerIdleTimeMillis() < mLastBluetoothActivityInfo.idleTimeMs
12191                 || info.getControllerEnergyUsed() < mLastBluetoothActivityInfo.energy) {
12192             // A drop in accumulated Bluetooth stats is a sign of a Bluetooth crash.
12193             // Reset the preserved previous snapshot in order to restart accumulating deltas.
12194             mLastBluetoothActivityInfo.reset();
12195         }
12196 
12197         final long rxTimeMs =
12198                 info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs;
12199         final long txTimeMs =
12200                 info.getControllerTxTimeMillis() - mLastBluetoothActivityInfo.txTimeMs;
12201         final long idleTimeMs =
12202                 info.getControllerIdleTimeMillis() - mLastBluetoothActivityInfo.idleTimeMs;
12203 
12204         if (DEBUG_ENERGY) {
12205             Slog.d(TAG, "------ BEGIN BLE power blaming ------");
12206             Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
12207             Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
12208             Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
12209         }
12210 
12211         final SparseDoubleArray uidEstimatedConsumptionMah =
12212                 (mGlobalMeasuredEnergyStats != null
12213                         && mBluetoothPowerCalculator != null && consumedChargeUC > 0) ?
12214                         new SparseDoubleArray() : null;
12215 
12216         long totalScanTimeMs = 0;
12217 
12218         final int uidCount = mUidStats.size();
12219         for (int i = 0; i < uidCount; i++) {
12220             final Uid u = mUidStats.valueAt(i);
12221             if (u.mBluetoothScanTimer == null) {
12222                 continue;
12223             }
12224 
12225             totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
12226                     elapsedRealtimeMs * 1000) / 1000;
12227         }
12228 
12229         final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
12230         final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
12231 
12232         if (DEBUG_ENERGY) {
12233             Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
12234                     + " TX=" + normalizeScanTxTime);
12235         }
12236 
12237         long leftOverRxTimeMs = rxTimeMs;
12238         long leftOverTxTimeMs = txTimeMs;
12239 
12240         for (int i = 0; i < uidCount; i++) {
12241             final Uid u = mUidStats.valueAt(i);
12242             if (u.mBluetoothScanTimer == null) {
12243                 continue;
12244             }
12245 
12246             long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
12247                     elapsedRealtimeMs * 1000) / 1000;
12248             if (scanTimeSinceMarkMs > 0) {
12249                 // Set the new mark so that next time we get new data since this point.
12250                 u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
12251 
12252                 long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
12253                 long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
12254 
12255                 if (normalizeScanRxTime) {
12256                     // Scan time is longer than the total rx time in the controller,
12257                     // so distribute the scan time proportionately. This means regular traffic
12258                     // will not blamed, but scans are more expensive anyways.
12259                     scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
12260                 }
12261 
12262                 if (normalizeScanTxTime) {
12263                     // Scan time is longer than the total tx time in the controller,
12264                     // so distribute the scan time proportionately. This means regular traffic
12265                     // will not blamed, but scans are more expensive anyways.
12266                     scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
12267                 }
12268 
12269                 final ControllerActivityCounterImpl counter =
12270                         u.getOrCreateBluetoothControllerActivityLocked();
12271                 counter.getRxTimeCounter().addCountLocked(scanTimeRxSinceMarkMs);
12272                 counter.getTxTimeCounters()[0].addCountLocked(scanTimeTxSinceMarkMs);
12273 
12274                 if (uidEstimatedConsumptionMah != null) {
12275                     uidEstimatedConsumptionMah.add(u.getUid(),
12276                             mBluetoothPowerCalculator.calculatePowerMah(
12277                                     scanTimeRxSinceMarkMs, scanTimeTxSinceMarkMs, 0));
12278                 }
12279 
12280                 leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
12281                 leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
12282             }
12283         }
12284 
12285         if (DEBUG_ENERGY) {
12286             Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX="
12287                     + leftOverTxTimeMs);
12288         }
12289 
12290         //
12291         // Now distribute blame to apps that did bluetooth traffic.
12292         //
12293 
12294         long totalTxBytes = 0;
12295         long totalRxBytes = 0;
12296 
12297         final UidTraffic[] uidTraffic = info.getUidTraffic();
12298         final int numUids = uidTraffic != null ? uidTraffic.length : 0;
12299         for (int i = 0; i < numUids; i++) {
12300             final UidTraffic traffic = uidTraffic[i];
12301             final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(
12302                     traffic.getUid());
12303             final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(
12304                     traffic.getUid());
12305 
12306             // Add to the global counters.
12307             mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(rxBytes);
12308             mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes);
12309 
12310             // Add to the UID counters.
12311             final Uid u = getUidStatsLocked(mapUid(traffic.getUid()), elapsedRealtimeMs, uptimeMs);
12312             u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0);
12313             u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0);
12314 
12315             // Calculate the total traffic.
12316             totalRxBytes += rxBytes;
12317             totalTxBytes += txBytes;
12318         }
12319 
12320         if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0
12321                 || leftOverTxTimeMs != 0)) {
12322             for (int i = 0; i < numUids; i++) {
12323                 final UidTraffic traffic = uidTraffic[i];
12324                 final int uid = traffic.getUid();
12325                 final long rxBytes =
12326                         traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid);
12327                 final long txBytes =
12328                         traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid);
12329 
12330                 final Uid u = getUidStatsLocked(mapUid(uid), elapsedRealtimeMs, uptimeMs);
12331                 final ControllerActivityCounterImpl counter =
12332                         u.getOrCreateBluetoothControllerActivityLocked();
12333 
12334                 if (totalRxBytes > 0 && rxBytes > 0) {
12335                     final long timeRxMs = (leftOverRxTimeMs * rxBytes) / totalRxBytes;
12336                     if (DEBUG_ENERGY) {
12337                         Slog.d(TAG, "UID=" + uid + " rx_bytes=" + rxBytes + " rx_time=" + timeRxMs);
12338                     }
12339                     counter.getRxTimeCounter().addCountLocked(timeRxMs);
12340 
12341                     if (uidEstimatedConsumptionMah != null) {
12342                         uidEstimatedConsumptionMah.add(u.getUid(),
12343                                 mBluetoothPowerCalculator.calculatePowerMah(timeRxMs, 0, 0));
12344                     }
12345                 }
12346 
12347                 if (totalTxBytes > 0 && txBytes > 0) {
12348                     final long timeTxMs = (leftOverTxTimeMs * txBytes) / totalTxBytes;
12349                     if (DEBUG_ENERGY) {
12350                         Slog.d(TAG, "UID=" + uid + " tx_bytes=" + txBytes + " tx_time=" + timeTxMs);
12351                     }
12352                     counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
12353 
12354                     if (uidEstimatedConsumptionMah != null) {
12355                         uidEstimatedConsumptionMah.add(u.getUid(),
12356                                 mBluetoothPowerCalculator.calculatePowerMah(0, timeTxMs, 0));
12357                     }
12358                 }
12359             }
12360         }
12361 
12362         mBluetoothActivity.getRxTimeCounter().addCountLocked(rxTimeMs);
12363         mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(txTimeMs);
12364         mBluetoothActivity.getIdleTimeCounter().addCountLocked(idleTimeMs);
12365 
12366         // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
12367         final double opVolt = mPowerProfile.getAveragePower(
12368                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
12369         double controllerMaMs = 0;
12370         if (opVolt != 0) {
12371             controllerMaMs = (info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
12372                     / opVolt;
12373             // We store the power drain as mAms.
12374             mBluetoothActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
12375         }
12376 
12377         // Update the MeasuredEnergyStats information.
12378         if (uidEstimatedConsumptionMah != null) {
12379             mGlobalMeasuredEnergyStats.updateStandardBucket(
12380                     MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH, consumedChargeUC);
12381 
12382             double totalEstimatedMah
12383                     = mBluetoothPowerCalculator.calculatePowerMah(rxTimeMs, txTimeMs, idleTimeMs);
12384             totalEstimatedMah = Math.max(totalEstimatedMah, controllerMaMs / MILLISECONDS_IN_HOUR);
12385             distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH,
12386                     consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedMah);
12387         }
12388 
12389         mLastBluetoothActivityInfo.set(info);
12390     }
12391     /**
12392      * Read Resource Power Manager (RPM) state and voter times.
12393      * If RPM stats were fetched more recently than RPM_STATS_UPDATE_FREQ_MS ago, uses the old data
12394      * instead of fetching it anew.
12395      *
12396      * Note: This should be called without synchronizing this BatteryStatsImpl object
12397      */
fillLowPowerStats()12398     public void fillLowPowerStats() {
12399         if (mPlatformIdleStateCallback == null) return;
12400 
12401         RpmStats rpmStats = new RpmStats();
12402         long now = SystemClock.elapsedRealtime();
12403         if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
12404             mPlatformIdleStateCallback.fillLowPowerStats(rpmStats);
12405             synchronized (this) {
12406                 mTmpRpmStats = rpmStats;
12407                 mLastRpmStatsUpdateTimeMs = now;
12408             }
12409         }
12410     }
12411 
12412     /**
12413      * Record Resource Power Manager (RPM) state and voter times.
12414      * TODO(b/185252376): Remove this logging. PowerStatsService logs the same data more
12415      * efficiently.
12416      */
updateRpmStatsLocked(long elapsedRealtimeUs)12417     public void updateRpmStatsLocked(long elapsedRealtimeUs) {
12418         if (mTmpRpmStats == null) return;
12419 
12420         for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate
12421                 : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) {
12422 
12423             // Update values for this platform state.
12424             final String pName = pstate.getKey();
12425             final long pTimeUs = pstate.getValue().mTimeMs * 1000;
12426             final int pCount = pstate.getValue().mCount;
12427             getRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs);
12428             if (SCREEN_OFF_RPM_STATS_ENABLED) {
12429                 getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs);
12430             }
12431 
12432             // Update values for each voter of this platform state.
12433             for (Map.Entry<String, RpmStats.PowerStateElement> voter
12434                     : pstate.getValue().mVoters.entrySet()) {
12435                 final String vName = pName + "." + voter.getKey();
12436                 final long vTimeUs = voter.getValue().mTimeMs * 1000;
12437                 final int vCount = voter.getValue().mCount;
12438                 getRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs);
12439                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
12440                     getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs);
12441                 }
12442             }
12443         }
12444 
12445         for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys
12446                 : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) {
12447 
12448             final String subsysName = subsys.getKey();
12449             for (Map.Entry<String, RpmStats.PowerStateElement> sstate
12450                     : subsys.getValue().mStates.entrySet()) {
12451                 final String name = subsysName + "." + sstate.getKey();
12452                 final long timeUs = sstate.getValue().mTimeMs * 1000;
12453                 final int count = sstate.getValue().mCount;
12454                 getRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs);
12455                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
12456                     getScreenOffRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs);
12457                 }
12458             }
12459         }
12460     }
12461 
12462     /**
12463      * Accumulate Cpu charge consumption and distribute it to the correct state and the apps.
12464      * Only call if device is on battery.
12465      *
12466      * @param clusterChargeUC amount of charge (microcoulombs) consumed by each Cpu Cluster
12467      * @param accumulator collection of calculated uid cpu power consumption to smear
12468      *                    clusterChargeUC against.
12469      */
12470     @GuardedBy("this")
updateCpuMeasuredEnergyStatsLocked(@onNull long[] clusterChargeUC, @NonNull CpuDeltaPowerAccumulator accumulator)12471     private void updateCpuMeasuredEnergyStatsLocked(@NonNull long[] clusterChargeUC,
12472             @NonNull CpuDeltaPowerAccumulator accumulator) {
12473         if (DEBUG_ENERGY) {
12474             Slog.d(TAG,
12475                     "Updating cpu cluster stats: " + clusterChargeUC.toString());
12476         }
12477         if (mGlobalMeasuredEnergyStats == null) {
12478             return;
12479         }
12480 
12481         final int numClusters = clusterChargeUC.length;
12482         long totalCpuChargeUC = 0;
12483         for (int i = 0; i < numClusters; i++) {
12484             totalCpuChargeUC += clusterChargeUC[i];
12485         }
12486         if (totalCpuChargeUC <= 0) return;
12487 
12488         mGlobalMeasuredEnergyStats.updateStandardBucket(MeasuredEnergyStats.POWER_BUCKET_CPU,
12489                 totalCpuChargeUC);
12490 
12491         // Calculate the measured microcoulombs/calculated milliamp-hour charge ratio for each
12492         // cluster to normalize  each uid's estimated power usage against actual power usage for
12493         // a given cluster.
12494         final double[] clusterChargeRatio = new double[numClusters];
12495         for (int cluster = 0; cluster < numClusters; cluster++) {
12496 
12497             final double totalClusterChargeMah = accumulator.totalClusterChargesMah[cluster];
12498             if (totalClusterChargeMah <= 0.0) {
12499                 // This cluster did not have any work on it, since last update.
12500                 // Avoid dividing by zero.
12501                 clusterChargeRatio[cluster] = 0.0;
12502             } else {
12503                 clusterChargeRatio[cluster] =
12504                         clusterChargeUC[cluster] / accumulator.totalClusterChargesMah[cluster];
12505             }
12506         }
12507 
12508         // Assign and distribute power usage to apps based on their calculated cpu cluster charge.
12509         final long uidChargeArraySize = accumulator.perUidCpuClusterChargesMah.size();
12510         for (int i = 0; i < uidChargeArraySize; i++) {
12511             final Uid uid = accumulator.perUidCpuClusterChargesMah.keyAt(i);
12512             final double[] uidClusterChargesMah = accumulator.perUidCpuClusterChargesMah.valueAt(i);
12513 
12514             // Iterate each cpu cluster and sum the proportional measured cpu cluster charge to
12515             // get the total cpu charge consumed by a uid.
12516             long uidCpuChargeUC = 0;
12517             for (int cluster = 0; cluster < numClusters; cluster++) {
12518                 final double uidClusterChargeMah = uidClusterChargesMah[cluster];
12519 
12520                 // Proportionally allocate the measured cpu cluster charge to a uid using the
12521                 // measured charge/calculated charge ratio. Add 0.5 to round the proportional
12522                 // charge double to the nearest long value.
12523                 final long uidClusterChargeUC =
12524                         (long) (uidClusterChargeMah * clusterChargeRatio[cluster]
12525                                 + 0.5);
12526 
12527                 uidCpuChargeUC += uidClusterChargeUC;
12528             }
12529 
12530             if (uidCpuChargeUC < 0) {
12531                 Slog.wtf(TAG,
12532                         "Unexpected proportional measured charge (" + uidCpuChargeUC + ") for uid "
12533                                 + uid.mUid);
12534                 continue;
12535             }
12536 
12537             uid.addChargeToStandardBucketLocked(uidCpuChargeUC,
12538                     MeasuredEnergyStats.POWER_BUCKET_CPU);
12539         }
12540     }
12541 
12542     /**
12543      * Accumulate Display charge consumption and distribute it to the correct state and the apps.
12544      *
12545      * NOTE: The algorithm used makes the strong assumption that app foreground activity time
12546      * is always 0 when the screen is not "ON" and whenever the rail energy is 0 (if supported).
12547      * To the extent that those assumptions are violated, the algorithm will err.
12548      *
12549      * @param chargeUC amount of charge (microcoulombs) used by Display since this was last called.
12550      * @param screenState screen state at the time this data collection was scheduled
12551      */
12552     @GuardedBy("this")
updateDisplayMeasuredEnergyStatsLocked(long chargeUC, int screenState, long elapsedRealtimeMs)12553     public void updateDisplayMeasuredEnergyStatsLocked(long chargeUC, int screenState,
12554             long elapsedRealtimeMs) {
12555         if (DEBUG_ENERGY) Slog.d(TAG, "Updating display stats: " + chargeUC);
12556         if (mGlobalMeasuredEnergyStats == null) {
12557             return;
12558         }
12559 
12560         final @StandardPowerBucket int powerBucket =
12561                 MeasuredEnergyStats.getDisplayPowerBucket(mScreenStateAtLastEnergyMeasurement);
12562         mScreenStateAtLastEnergyMeasurement = screenState;
12563 
12564         if (!mOnBatteryInternal || chargeUC <= 0) {
12565             // There's nothing further to update.
12566             return;
12567         }
12568         if (mIgnoreNextExternalStats) {
12569             // Although under ordinary resets we won't get here, and typically a new sync will
12570             // happen right after the reset, strictly speaking we need to set all mark times to now.
12571             final int uidStatsSize = mUidStats.size();
12572             for (int i = 0; i < uidStatsSize; i++) {
12573                 final Uid uid = mUidStats.valueAt(i);
12574                 uid.markProcessForegroundTimeUs(elapsedRealtimeMs, false);
12575             }
12576             return;
12577         }
12578 
12579         mGlobalMeasuredEnergyStats.updateStandardBucket(powerBucket, chargeUC);
12580 
12581         // Now we blame individual apps, but only if the display was ON.
12582         if (powerBucket != MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON) {
12583             return;
12584         }
12585         // TODO(b/175726779): Consider unifying the code with the non-rail display power blaming.
12586 
12587         // NOTE: fg time is NOT pooled. If two uids are both somehow in fg, then that time is
12588         // 'double counted' and will simply exceed the realtime that elapsed.
12589         // If multidisplay becomes a reality, this is probably more reasonable than pooling.
12590 
12591         // Collect total time since mark so that we can normalize power.
12592         final SparseDoubleArray fgTimeUsArray = new SparseDoubleArray();
12593         final long elapsedRealtimeUs = elapsedRealtimeMs * 1000;
12594         // TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
12595         final int uidStatsSize = mUidStats.size();
12596         for (int i = 0; i < uidStatsSize; i++) {
12597             final Uid uid = mUidStats.valueAt(i);
12598             final long fgTimeUs = uid.markProcessForegroundTimeUs(elapsedRealtimeMs, true);
12599             if (fgTimeUs == 0) continue;
12600             fgTimeUsArray.put(uid.getUid(), (double) fgTimeUs);
12601         }
12602         distributeEnergyToUidsLocked(powerBucket, chargeUC, fgTimeUsArray, 0);
12603     }
12604 
12605     /**
12606      * Accumulate GNSS charge consumption and distribute it to the correct state and the apps.
12607      *
12608      * @param chargeUC amount of charge (microcoulombs) used by GNSS since this was last called.
12609      */
12610     @GuardedBy("this")
updateGnssMeasuredEnergyStatsLocked(long chargeUC, long elapsedRealtimeMs)12611     public void updateGnssMeasuredEnergyStatsLocked(long chargeUC, long elapsedRealtimeMs) {
12612         if (DEBUG_ENERGY) Slog.d(TAG, "Updating gnss stats: " + chargeUC);
12613         if (mGlobalMeasuredEnergyStats == null) {
12614             return;
12615         }
12616 
12617         if (!mOnBatteryInternal || chargeUC <= 0) {
12618             // There's nothing further to update.
12619             return;
12620         }
12621         if (mIgnoreNextExternalStats) {
12622             // Although under ordinary resets we won't get here, and typically a new sync will
12623             // happen right after the reset, strictly speaking we need to set all mark times to now.
12624             final int uidStatsSize = mUidStats.size();
12625             for (int i = 0; i < uidStatsSize; i++) {
12626                 final Uid uid = mUidStats.valueAt(i);
12627                 uid.markGnssTimeUs(elapsedRealtimeMs);
12628             }
12629             return;
12630         }
12631 
12632         mGlobalMeasuredEnergyStats.updateStandardBucket(MeasuredEnergyStats.POWER_BUCKET_GNSS,
12633                 chargeUC);
12634 
12635         // Collect the per uid time since mark so that we can normalize power.
12636         final SparseDoubleArray gnssTimeUsArray = new SparseDoubleArray();
12637         // TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
12638         final int uidStatsSize = mUidStats.size();
12639         for (int i = 0; i < uidStatsSize; i++) {
12640             final Uid uid = mUidStats.valueAt(i);
12641             final long gnssTimeUs = uid.markGnssTimeUs(elapsedRealtimeMs);
12642             if (gnssTimeUs == 0) continue;
12643             gnssTimeUsArray.put(uid.getUid(), (double) gnssTimeUs);
12644         }
12645         distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_GNSS, chargeUC,
12646                 gnssTimeUsArray, 0);
12647     }
12648 
12649     /**
12650      * Accumulate Custom power bucket charge, globally and for each app.
12651      *
12652      * @param totalChargeUC charge (microcoulombs) used for this bucket since this was last called.
12653      * @param uidCharges map of uid->charge (microcoulombs) for this bucket since last called.
12654      *                    Data inside uidCharges will not be modified (treated immutable).
12655      *                    Uids not already known to BatteryStats will be ignored.
12656      */
updateCustomMeasuredEnergyStatsLocked(int customPowerBucket, long totalChargeUC, @Nullable SparseLongArray uidCharges)12657     public void updateCustomMeasuredEnergyStatsLocked(int customPowerBucket,
12658             long totalChargeUC, @Nullable SparseLongArray uidCharges) {
12659         if (DEBUG_ENERGY) {
12660             Slog.d(TAG, "Updating attributed measured charge stats for custom bucket "
12661                     + customPowerBucket
12662                     + " with total charge " + totalChargeUC
12663                     + " and uid charges " + String.valueOf(uidCharges));
12664         }
12665         if (mGlobalMeasuredEnergyStats == null) return;
12666         if (!mOnBatteryInternal || mIgnoreNextExternalStats || totalChargeUC <= 0) return;
12667 
12668         mGlobalMeasuredEnergyStats.updateCustomBucket(customPowerBucket, totalChargeUC);
12669 
12670         if (uidCharges == null) return;
12671         final int numUids = uidCharges.size();
12672         for (int i = 0; i < numUids; i++) {
12673             final int uidInt = mapUid(uidCharges.keyAt(i));
12674             final long uidChargeUC = uidCharges.valueAt(i);
12675             if (uidChargeUC == 0) continue;
12676             final Uid uidObj = getAvailableUidStatsLocked(uidInt);
12677             if (uidObj != null) {
12678                 uidObj.addChargeToCustomBucketLocked(uidChargeUC, customPowerBucket);
12679             } else {
12680                 // Ignore any uid not already known to BatteryStats, rather than creating a new Uid.
12681                 // Otherwise we could end up reviving dead Uids. Note that the CPU data is updated
12682                 // first, so any uid that has used any CPU should already be known to BatteryStats.
12683                 // Recently removed uids (especially common for isolated uids) can reach this path
12684                 // and are ignored.
12685                 if (!Process.isIsolated(uidInt)) {
12686                     Slog.w(TAG, "Received measured charge " + totalChargeUC + " for custom bucket "
12687                             + customPowerBucket + " for non-existent uid " + uidInt);
12688                 }
12689             }
12690         }
12691     }
12692 
12693     /**
12694      * Attributes energy (for the given bucket) to each uid according to the following formula:
12695      *     blamedEnergy[uid] = totalEnergy * ratioNumerators[uid] / ratioDenominator;
12696      * <p>Does nothing if ratioDenominator is 0.
12697      *
12698      * <p>Here, ratioDenominator = max(sumOfAllRatioNumerators, minRatioDenominator),
12699      * so if given minRatioDenominator <= 0, then sumOfAllRatioNumerators will be used implicitly.
12700      *
12701      * <p>Note that ratioNumerators and minRatioDenominator must use the same units, but need not
12702      * use the same units as totalConsumedChargeUC (which must be in microcoulombs).
12703      *
12704      * <p>A consequence of minRatioDenominator is that the sum over all uids might be less than
12705      * totalConsumedChargeUC. This is intentional; the remainder is purposefully unnaccounted rather
12706      * than incorrectly blamed on uids, and implies unknown (non-uid) sources of drain.
12707      *
12708      * <p>All uids in ratioNumerators must exist in mUidStats already.
12709      */
distributeEnergyToUidsLocked(@tandardPowerBucket int bucket, long totalConsumedChargeUC, SparseDoubleArray ratioNumerators, double minRatioDenominator)12710     private void distributeEnergyToUidsLocked(@StandardPowerBucket int bucket,
12711             long totalConsumedChargeUC, SparseDoubleArray ratioNumerators,
12712             double minRatioDenominator) {
12713 
12714         // If the sum of all app usage was greater than the total, use that instead:
12715         double sumRatioNumerators = 0;
12716         for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
12717             sumRatioNumerators += ratioNumerators.valueAt(i);
12718         }
12719         final double ratioDenominator = Math.max(sumRatioNumerators, minRatioDenominator);
12720         if (ratioDenominator <= 0) return;
12721 
12722         for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
12723             final Uid uid = getAvailableUidStatsLocked(ratioNumerators.keyAt(i));
12724             final double ratioNumerator = ratioNumerators.valueAt(i);
12725             final long uidActualUC
12726                     = (long) (totalConsumedChargeUC * ratioNumerator / ratioDenominator + 0.5);
12727             uid.addChargeToStandardBucketLocked(uidActualUC, bucket);
12728         }
12729     }
12730 
12731     /**
12732      * Read and record Rail Energy data.
12733      */
updateRailStatsLocked()12734     public void updateRailStatsLocked() {
12735         if (mMeasuredEnergyRetriever == null || !mTmpRailStats.isRailStatsAvailable()) {
12736             return;
12737         }
12738         mMeasuredEnergyRetriever.fillRailDataStats(mTmpRailStats);
12739     }
12740 
12741     /** Informs that external stats data has been completely flushed. */
informThatAllExternalStatsAreFlushed()12742     public void informThatAllExternalStatsAreFlushed() {
12743         synchronized (this) {
12744             // Any data from the pre-reset era is flushed, so we can henceforth process future data.
12745             mIgnoreNextExternalStats = false;
12746         }
12747     }
12748 
12749     /**
12750      * Read and distribute kernel wake lock use across apps.
12751      */
updateKernelWakelocksLocked()12752     public void updateKernelWakelocksLocked() {
12753         updateKernelWakelocksLocked(mClocks.elapsedRealtime() * 1000);
12754     }
12755 
12756     /**
12757      * @see #updateKernelWakelocksLocked()
12758      */
updateKernelWakelocksLocked(long elapsedRealtimeUs)12759     public void updateKernelWakelocksLocked(long elapsedRealtimeUs) {
12760         final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
12761                 mTmpWakelockStats);
12762         if (wakelockStats == null) {
12763             // Not crashing might make board bringup easier.
12764             Slog.w(TAG, "Couldn't get kernel wake lock stats");
12765             return;
12766         }
12767 
12768         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
12769             String name = ent.getKey();
12770             KernelWakelockStats.Entry kws = ent.getValue();
12771 
12772             SamplingTimer kwlt = mKernelWakelockStats.get(name);
12773             if (kwlt == null) {
12774                 kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
12775                 mKernelWakelockStats.put(name, kwlt);
12776             }
12777 
12778             kwlt.update(kws.mTotalTime, kws.mCount, elapsedRealtimeUs);
12779             kwlt.setUpdateVersion(kws.mVersion);
12780         }
12781 
12782         int numWakelocksSetStale = 0;
12783         // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
12784         // this time.
12785         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
12786             SamplingTimer st = ent.getValue();
12787             if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
12788                 st.endSample(elapsedRealtimeUs);
12789                 numWakelocksSetStale++;
12790             }
12791         }
12792 
12793         // Record whether we've seen a non-zero time (for debugging b/22716723).
12794         if (wakelockStats.isEmpty()) {
12795             Slog.wtf(TAG, "All kernel wakelocks had time of zero");
12796         }
12797 
12798         if (numWakelocksSetStale == mKernelWakelockStats.size()) {
12799             Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
12800                     wakelockStats.kernelWakelockVersion);
12801         }
12802     }
12803 
12804     // We use an anonymous class to access these variables,
12805     // so they can't live on the stack or they'd have to be
12806     // final MutableLong objects (more allocations).
12807     // Used in updateCpuTimeLocked().
12808     long mTempTotalCpuUserTimeUs;
12809     long mTempTotalCpuSystemTimeUs;
12810     long[][] mWakeLockAllocationsUs;
12811 
12812     /**
12813      * Reads the newest memory stats from the kernel.
12814      */
updateKernelMemoryBandwidthLocked()12815     public void updateKernelMemoryBandwidthLocked() {
12816         updateKernelMemoryBandwidthLocked(mClocks.elapsedRealtime() * 1000);
12817     }
12818 
updateKernelMemoryBandwidthLocked(long elapsedRealtimeUs)12819     public void updateKernelMemoryBandwidthLocked(long elapsedRealtimeUs) {
12820         mKernelMemoryBandwidthStats.updateStats();
12821         LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
12822         final int bandwidthEntryCount = bandwidthEntries.size();
12823         int index;
12824         for (int i = 0; i < bandwidthEntryCount; i++) {
12825             SamplingTimer timer;
12826             if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) {
12827                 timer = mKernelMemoryStats.valueAt(index);
12828             } else {
12829                 timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
12830                 mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
12831             }
12832             timer.update(bandwidthEntries.valueAt(i), 1, elapsedRealtimeUs);
12833             if (DEBUG_MEMORY) {
12834                 Slog.d(TAG, String.format("Added entry %d and updated timer to: "
12835                         + "mUnpluggedReportedTotalTimeUs %d size %d", bandwidthEntries.keyAt(i),
12836                         mKernelMemoryStats.get(
12837                                 bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTimeUs,
12838                         mKernelMemoryStats.size()));
12839             }
12840         }
12841     }
12842 
isOnBatteryLocked()12843     public boolean isOnBatteryLocked() {
12844         return mOnBatteryTimeBase.isRunning();
12845     }
12846 
isOnBatteryScreenOffLocked()12847     public boolean isOnBatteryScreenOffLocked() {
12848         return mOnBatteryScreenOffTimeBase.isRunning();
12849     }
12850 
12851     /**
12852      * Object for calculating and accumulating the estimated cpu power used while reading the
12853      * various cpu kernel files.
12854      */
12855     @VisibleForTesting
12856     public static class CpuDeltaPowerAccumulator {
12857         // Keeps track of total charge used per cluster.
12858         public final double[] totalClusterChargesMah;
12859         // Keeps track of charge used per cluster per uid.
12860         public final ArrayMap<Uid, double[]> perUidCpuClusterChargesMah;
12861 
12862         private final CpuPowerCalculator mCalculator;
12863         private Uid mCachedUid = null;
12864         private double[] mUidClusterCache = null;
12865 
CpuDeltaPowerAccumulator(CpuPowerCalculator calculator, int nClusters)12866         CpuDeltaPowerAccumulator(CpuPowerCalculator calculator, int nClusters) {
12867             mCalculator = calculator;
12868             totalClusterChargesMah = new double[nClusters];
12869             perUidCpuClusterChargesMah = new ArrayMap<>();
12870         }
12871 
12872         /** Add per cpu cluster durations to the currently cached uid. */
addCpuClusterDurationsMs(Uid uid, long[] durationsMs)12873         public void addCpuClusterDurationsMs(Uid uid, long[] durationsMs) {
12874             final double[] uidChargesMah = getOrCreateUidCpuClusterCharges(uid);
12875             for (int cluster = 0; cluster < durationsMs.length; cluster++) {
12876                 final double estimatedDeltaMah = mCalculator.calculatePerCpuClusterPowerMah(cluster,
12877                         durationsMs[cluster]);
12878                 uidChargesMah[cluster] += estimatedDeltaMah;
12879                 totalClusterChargesMah[cluster] += estimatedDeltaMah;
12880             }
12881         }
12882 
12883         /** Add per speed per cpu cluster durations to the currently cached uid. */
addCpuClusterSpeedDurationsMs(Uid uid, int cluster, int speed, long durationsMs)12884         public void addCpuClusterSpeedDurationsMs(Uid uid, int cluster, int speed,
12885                 long durationsMs) {
12886             final double[] uidChargesMah = getOrCreateUidCpuClusterCharges(uid);
12887             final double estimatedDeltaMah = mCalculator.calculatePerCpuFreqPowerMah(cluster, speed,
12888                     durationsMs);
12889             uidChargesMah[cluster] += estimatedDeltaMah;
12890             totalClusterChargesMah[cluster] += estimatedDeltaMah;
12891         }
12892 
getOrCreateUidCpuClusterCharges(Uid uid)12893         private double[] getOrCreateUidCpuClusterCharges(Uid uid) {
12894             // Repeated additions on the same uid is very likely.
12895             // Skip a lookup if getting the same uid as the last get.
12896             if (uid == mCachedUid) return mUidClusterCache;
12897 
12898             double[] uidChargesMah = perUidCpuClusterChargesMah.get(uid);
12899             if (uidChargesMah == null) {
12900                 uidChargesMah = new double[totalClusterChargesMah.length];
12901                 perUidCpuClusterChargesMah.put(uid, uidChargesMah);
12902             }
12903             mCachedUid = uid;
12904             mUidClusterCache = uidChargesMah;
12905             return uidChargesMah;
12906         }
12907     }
12908 
12909     /**
12910      * Read and distribute CPU usage across apps. If their are partial wakelocks being held
12911      * and we are on battery with screen off, we give more of the cpu time to those apps holding
12912      * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
12913      * It's possible this will be invoked after the internal battery/screen states are updated, so
12914      * passing the appropriate battery/screen states to try attribute the cpu times to correct
12915      * buckets.
12916      */
12917     @GuardedBy("this")
updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff, long[] measuredCpuClusterChargeUC)12918     public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff,
12919             long[] measuredCpuClusterChargeUC) {
12920         if (mPowerProfile == null) {
12921             return;
12922         }
12923 
12924         if (DEBUG_ENERGY_CPU) {
12925             Slog.d(TAG, "!Cpu updating!");
12926         }
12927 
12928         if (mCpuFreqs == null) {
12929             mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
12930         }
12931 
12932         // Calculate the wakelocks we have to distribute amongst. The system is excluded as it is
12933         // usually holding the wakelock on behalf of an app.
12934         // And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
12935         ArrayList<StopwatchTimer> partialTimersToConsider = null;
12936         if (onBatteryScreenOff) {
12937             partialTimersToConsider = new ArrayList<>();
12938             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
12939                 final StopwatchTimer timer = mPartialTimers.get(i);
12940                 // Since the collection and blaming of wakelocks can be scheduled to run after
12941                 // some delay, the mPartialTimers list may have new entries. We can't blame
12942                 // the newly added timer for past cpu time, so we only consider timers that
12943                 // were present for one round of collection. Once a timer has gone through
12944                 // a round of collection, its mInList field is set to true.
12945                 if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
12946                     partialTimersToConsider.add(timer);
12947                 }
12948             }
12949         }
12950         markPartialTimersAsEligible();
12951 
12952         // When the battery is not on, we don't attribute the cpu times to any timers but we still
12953         // need to take the snapshots.
12954         if (!onBattery) {
12955             mCpuUidUserSysTimeReader.readDelta(false, null);
12956             mCpuUidFreqTimeReader.readDelta(false, null);
12957             mNumAllUidCpuTimeReads += 2;
12958             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
12959                 mCpuUidActiveTimeReader.readDelta(false, null);
12960                 mCpuUidClusterTimeReader.readDelta(false, null);
12961                 mNumAllUidCpuTimeReads += 2;
12962             }
12963             for (int cluster = mKernelCpuSpeedReaders.length - 1; cluster >= 0; --cluster) {
12964                 mKernelCpuSpeedReaders[cluster].readDelta();
12965             }
12966             mSystemServerCpuThreadReader.readDelta();
12967             return;
12968         }
12969 
12970         mUserInfoProvider.refreshUserIds();
12971         final SparseLongArray updatedUids = mCpuUidFreqTimeReader.perClusterTimesAvailable()
12972                 ? null : new SparseLongArray();
12973 
12974         final CpuDeltaPowerAccumulator powerAccumulator;
12975         if (mGlobalMeasuredEnergyStats != null
12976                 && mGlobalMeasuredEnergyStats.isStandardBucketSupported(
12977                 MeasuredEnergyStats.POWER_BUCKET_CPU) && mCpuPowerCalculator != null) {
12978             if (measuredCpuClusterChargeUC == null) {
12979                 Slog.wtf(TAG,
12980                         "POWER_BUCKET_CPU supported but no measured Cpu Cluster charge reported "
12981                                 + "on updateCpuTimeLocked!");
12982                 powerAccumulator = null;
12983             } else {
12984                 // Cpu Measured Energy is supported, create an object to accumulate the estimated
12985                 // charge consumption since the last cpu update
12986                 final int numClusters = mPowerProfile.getNumCpuClusters();
12987                 powerAccumulator = new CpuDeltaPowerAccumulator(mCpuPowerCalculator, numClusters);
12988             }
12989         } else {
12990             powerAccumulator = null;
12991         }
12992 
12993         readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
12994         // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
12995         // freqs, so no need to approximate these values.
12996         if (updatedUids != null) {
12997             updateClusterSpeedTimes(updatedUids, onBattery, powerAccumulator);
12998         }
12999         readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff,
13000                 powerAccumulator);
13001         mNumAllUidCpuTimeReads += 2;
13002         if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
13003             // Cpu Active times do not get any info ony how to attribute measured Cpu Cluster
13004             // charge, so not need to provide the powerAccumulator
13005             readKernelUidCpuActiveTimesLocked(onBattery);
13006             readKernelUidCpuClusterTimesLocked(onBattery, powerAccumulator);
13007             mNumAllUidCpuTimeReads += 2;
13008         }
13009 
13010         updateSystemServerThreadStats();
13011 
13012         if (powerAccumulator != null) {
13013             updateCpuMeasuredEnergyStatsLocked(measuredCpuClusterChargeUC, powerAccumulator);
13014         }
13015     }
13016 
13017     /**
13018      * Estimates the proportion of the System Server CPU activity (per cluster per speed)
13019      * spent on handling incoming binder calls.
13020      */
13021     @VisibleForTesting
updateSystemServerThreadStats()13022     public void updateSystemServerThreadStats() {
13023         // There are some simplifying assumptions made in this algorithm
13024         // 1) We assume that if a thread handles incoming binder calls, all of its activity
13025         //    is spent doing that.  Most incoming calls are handled by threads allocated
13026         //    by the native layer in the binder thread pool, so this assumption is reasonable.
13027         // 2) We use the aggregate CPU time spent in different threads as a proxy for the CPU
13028         //    cost. In reality, in multi-core CPUs, the CPU cost may not be linearly
13029         //    affected by additional threads.
13030 
13031         SystemServerCpuThreadReader.SystemServiceCpuThreadTimes systemServiceCpuThreadTimes =
13032                     mSystemServerCpuThreadReader.readDelta();
13033         if (systemServiceCpuThreadTimes == null) {
13034             return;
13035         }
13036 
13037         if (mBinderThreadCpuTimesUs == null) {
13038             mBinderThreadCpuTimesUs = new LongSamplingCounterArray(mOnBatteryTimeBase);
13039         }
13040         mBinderThreadCpuTimesUs.addCountLocked(systemServiceCpuThreadTimes.binderThreadCpuTimesUs);
13041 
13042         if (DEBUG_BINDER_STATS) {
13043             Slog.d(TAG, "System server threads per CPU cluster (incoming binder threads)");
13044             long binderThreadTimeMs = 0;
13045             int cpuIndex = 0;
13046             final long[] binderThreadCpuTimesUs = mBinderThreadCpuTimesUs.getCountsLocked(
13047                     BatteryStats.STATS_SINCE_CHARGED);
13048             int index = 0;
13049             int numCpuClusters = mPowerProfile.getNumCpuClusters();
13050             for (int cluster = 0; cluster < numCpuClusters; cluster++) {
13051                 StringBuilder sb = new StringBuilder();
13052                 sb.append("cpu").append(cpuIndex).append(": [");
13053                 int numSpeeds = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
13054                 for (int speed = 0; speed < numSpeeds; speed++) {
13055                     if (speed != 0) {
13056                         sb.append(", ");
13057                     }
13058                     long binderCountMs = binderThreadCpuTimesUs[index] / 1000;
13059                     sb.append(TextUtils.formatSimple("%10d", binderCountMs));
13060 
13061                     binderThreadTimeMs += binderCountMs;
13062                     index++;
13063                 }
13064                 cpuIndex += mPowerProfile.getNumCoresInCpuCluster(cluster);
13065                 Slog.d(TAG, sb.toString());
13066             }
13067         }
13068     }
13069 
13070     /**
13071      * Mark the current partial timers as gone through a collection so that they will be
13072      * considered in the next cpu times distribution to wakelock holders.
13073      */
13074     @VisibleForTesting
markPartialTimersAsEligible()13075     public void markPartialTimersAsEligible() {
13076         if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
13077             // No difference, so each timer is now considered for the next collection.
13078             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
13079                 mPartialTimers.get(i).mInList = true;
13080             }
13081         } else {
13082             // The lists are different, meaning we added (or removed a timer) since the last
13083             // collection.
13084             for (int i = mLastPartialTimers.size() - 1; i >= 0; --i) {
13085                 mLastPartialTimers.get(i).mInList = false;
13086             }
13087             mLastPartialTimers.clear();
13088 
13089             // Mark the current timers as gone through a collection.
13090             final int numPartialTimers = mPartialTimers.size();
13091             for (int i = 0; i < numPartialTimers; ++i) {
13092                 final StopwatchTimer timer = mPartialTimers.get(i);
13093                 timer.mInList = true;
13094                 mLastPartialTimers.add(timer);
13095             }
13096         }
13097     }
13098 
13099     /**
13100      * Take snapshot of cpu times (aggregated over all uids) at different frequencies and
13101      * calculate cpu times spent by each uid at different frequencies. Will also add estimated
13102      * power consumptions, if powerAccumulator data structure is provided.
13103      *
13104      * @param updatedUids  The uids for which times spent at different frequencies are calculated.
13105      * @param onBattery whether or not this is onBattery
13106      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
13107      */
13108     @VisibleForTesting
updateClusterSpeedTimes(@onNull SparseLongArray updatedUids, boolean onBattery, @Nullable CpuDeltaPowerAccumulator powerAccumulator)13109     public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery,
13110             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
13111         long totalCpuClustersTimeMs = 0;
13112         // Read the time spent for each cluster at various cpu frequencies.
13113         final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
13114         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
13115             clusterSpeedTimesMs[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
13116             if (clusterSpeedTimesMs[cluster] != null) {
13117                 for (int speed = clusterSpeedTimesMs[cluster].length - 1; speed >= 0; --speed) {
13118                     totalCpuClustersTimeMs += clusterSpeedTimesMs[cluster][speed];
13119                 }
13120             }
13121         }
13122         if (totalCpuClustersTimeMs != 0) {
13123             // We have cpu times per freq aggregated over all uids but we need the times per uid.
13124             // So, we distribute total time spent by an uid to different cpu freqs based on the
13125             // amount of time cpu was running at that freq.
13126             final int updatedUidsCount = updatedUids.size();
13127             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
13128             final long uptimeMs = mClocks.uptimeMillis();
13129             for (int i = 0; i < updatedUidsCount; ++i) {
13130                 final Uid u = getUidStatsLocked(updatedUids.keyAt(i), elapsedRealtimeMs, uptimeMs);
13131                 final long appCpuTimeUs = updatedUids.valueAt(i);
13132                 // Add the cpu speeds to this UID.
13133                 final int numClusters = mPowerProfile.getNumCpuClusters();
13134                 if (u.mCpuClusterSpeedTimesUs == null ||
13135                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
13136                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
13137                 }
13138 
13139                 for (int cluster = 0; cluster < clusterSpeedTimesMs.length; cluster++) {
13140                     final int speedsInCluster = clusterSpeedTimesMs[cluster].length;
13141                     if (u.mCpuClusterSpeedTimesUs[cluster] == null || speedsInCluster !=
13142                             u.mCpuClusterSpeedTimesUs[cluster].length) {
13143                         u.mCpuClusterSpeedTimesUs[cluster]
13144                                 = new LongSamplingCounter[speedsInCluster];
13145                     }
13146 
13147                     final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeedTimesUs[cluster];
13148                     for (int speed = 0; speed < speedsInCluster; speed++) {
13149                         if (cpuSpeeds[speed] == null) {
13150                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
13151                         }
13152                         final long deltaSpeedCount = appCpuTimeUs
13153                                 * clusterSpeedTimesMs[cluster][speed]
13154                                 / totalCpuClustersTimeMs;
13155                         cpuSpeeds[speed].addCountLocked(deltaSpeedCount, onBattery);
13156 
13157                         if (powerAccumulator != null) {
13158                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
13159                                     speed, deltaSpeedCount);
13160                         }
13161                     }
13162                 }
13163             }
13164         }
13165     }
13166 
13167     /**
13168      * Take a snapshot of the cpu times spent by each uid and update the corresponding counters.
13169      * If {@param partialTimers} is not null and empty, then we assign a portion of cpu times to
13170      * wakelock holders.
13171      *
13172      * @param partialTimers The wakelock holders among which the cpu times will be distributed.
13173      * @param updatedUids If not null, then the uids found in the snapshot will be added to this.
13174      */
13175     @VisibleForTesting
readKernelUidCpuTimesLocked(@ullable ArrayList<StopwatchTimer> partialTimers, @Nullable SparseLongArray updatedUids, boolean onBattery)13176     public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
13177             @Nullable SparseLongArray updatedUids, boolean onBattery) {
13178         mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
13179         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
13180         final long startTimeMs = mClocks.uptimeMillis();
13181         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
13182 
13183         mCpuUidUserSysTimeReader.readDelta(false, (uid, timesUs) -> {
13184             long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
13185 
13186             uid = mapUid(uid);
13187             if (Process.isIsolated(uid)) {
13188                 // This could happen if the isolated uid mapping was removed before that process
13189                 // was actually killed.
13190                 if (DEBUG) Slog.d(TAG, "Got readings for an isolated uid: " + uid);
13191                 return;
13192             }
13193             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
13194                 if (DEBUG) Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
13195                 return;
13196             }
13197             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
13198 
13199             // Accumulate the total system and user time.
13200             mTempTotalCpuUserTimeUs += userTimeUs;
13201             mTempTotalCpuSystemTimeUs += systemTimeUs;
13202 
13203             StringBuilder sb = null;
13204             if (DEBUG_ENERGY_CPU) {
13205                 sb = new StringBuilder();
13206                 sb.append("  got time for uid=").append(u.mUid).append(": u=");
13207                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
13208                 sb.append(" s=");
13209                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
13210                 sb.append("\n");
13211             }
13212 
13213             if (numWakelocks > 0) {
13214                 // We have wakelocks being held, so only give a portion of the
13215                 // time to the process. The rest will be distributed among wakelock
13216                 // holders.
13217                 userTimeUs = (userTimeUs * WAKE_LOCK_WEIGHT) / 100;
13218                 systemTimeUs = (systemTimeUs * WAKE_LOCK_WEIGHT) / 100;
13219             }
13220 
13221             if (sb != null) {
13222                 sb.append("  adding to uid=").append(u.mUid).append(": u=");
13223                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
13224                 sb.append(" s=");
13225                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
13226                 Slog.d(TAG, sb.toString());
13227             }
13228 
13229             u.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
13230             u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
13231             if (updatedUids != null) {
13232                 updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
13233             }
13234         });
13235 
13236         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
13237         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
13238             Slog.d(TAG, "Reading cpu stats took " + elapsedTimeMs + "ms");
13239         }
13240 
13241         if (numWakelocks > 0) {
13242             // Distribute a portion of the total cpu time to wakelock holders.
13243             mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
13244             mTempTotalCpuSystemTimeUs =
13245                     (mTempTotalCpuSystemTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
13246 
13247             for (int i = 0; i < numWakelocks; ++i) {
13248                 final StopwatchTimer timer = partialTimers.get(i);
13249                 final int userTimeUs = (int) (mTempTotalCpuUserTimeUs / (numWakelocks - i));
13250                 final int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / (numWakelocks - i));
13251 
13252                 if (DEBUG_ENERGY_CPU) {
13253                     final StringBuilder sb = new StringBuilder();
13254                     sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
13255                             .append(": u=");
13256                     TimeUtils.formatDuration(userTimeUs / 1000, sb);
13257                     sb.append(" s=");
13258                     TimeUtils.formatDuration(systemTimeUs / 1000, sb);
13259                     Slog.d(TAG, sb.toString());
13260                 }
13261 
13262                 timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
13263                 timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
13264                 if (updatedUids != null) {
13265                     final int uid = timer.mUid.getUid();
13266                     updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
13267                 }
13268 
13269                 final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
13270                 proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery);
13271 
13272                 mTempTotalCpuUserTimeUs -= userTimeUs;
13273                 mTempTotalCpuSystemTimeUs -= systemTimeUs;
13274             }
13275         }
13276     }
13277 
13278     /**
13279      * Take a snapshot of the cpu times spent by each uid in each freq and update the
13280      * corresponding counters.  Will also add estimated power consumptions, if powerAccumulator
13281      * data structure is provided.
13282      *
13283      * @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
13284      * @param onBattery whether or not this is onBattery
13285      * @param onBatteryScreenOff whether or not this is onBattery with the screen off.
13286      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
13287      */
13288     @VisibleForTesting
readKernelUidCpuFreqTimesLocked(@ullable ArrayList<StopwatchTimer> partialTimers, boolean onBattery, boolean onBatteryScreenOff, @Nullable CpuDeltaPowerAccumulator powerAccumulator)13289     public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
13290             boolean onBattery, boolean onBatteryScreenOff,
13291             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
13292         final boolean perClusterTimesAvailable =
13293                 mCpuUidFreqTimeReader.perClusterTimesAvailable();
13294         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
13295         final int numClusters = mPowerProfile.getNumCpuClusters();
13296         mWakeLockAllocationsUs = null;
13297         final long startTimeMs = mClocks.uptimeMillis();
13298         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
13299         // If power is being accumulated for attribution, data needs to be read immediately.
13300         final boolean forceRead = powerAccumulator != null;
13301         mCpuUidFreqTimeReader.readDelta(forceRead, (uid, cpuFreqTimeMs) -> {
13302             uid = mapUid(uid);
13303             if (Process.isIsolated(uid)) {
13304                 if (DEBUG) Slog.d(TAG, "Got freq readings for an isolated uid: " + uid);
13305                 return;
13306             }
13307             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
13308                 if (DEBUG) Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
13309                 return;
13310             }
13311             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
13312             if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
13313                 detachIfNotNull(u.mCpuFreqTimeMs);
13314                 u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
13315             }
13316             u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
13317             if (u.mScreenOffCpuFreqTimeMs == null ||
13318                     u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
13319                 detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
13320                 u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
13321                         mOnBatteryScreenOffTimeBase);
13322             }
13323             u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff);
13324 
13325             if (perClusterTimesAvailable) {
13326                 if (u.mCpuClusterSpeedTimesUs == null ||
13327                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
13328                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
13329                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
13330                 }
13331                 if (numWakelocks > 0 && mWakeLockAllocationsUs == null) {
13332                     mWakeLockAllocationsUs = new long[numClusters][];
13333                 }
13334 
13335                 int freqIndex = 0;
13336                 for (int cluster = 0; cluster < numClusters; ++cluster) {
13337                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
13338                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
13339                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
13340                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
13341                         u.mCpuClusterSpeedTimesUs[cluster]
13342                                 = new LongSamplingCounter[speedsInCluster];
13343                     }
13344                     if (numWakelocks > 0 && mWakeLockAllocationsUs[cluster] == null) {
13345                         mWakeLockAllocationsUs[cluster] = new long[speedsInCluster];
13346                     }
13347                     final LongSamplingCounter[] cpuTimesUs = u.mCpuClusterSpeedTimesUs[cluster];
13348                     for (int speed = 0; speed < speedsInCluster; ++speed) {
13349                         if (cpuTimesUs[speed] == null) {
13350                             cpuTimesUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
13351                         }
13352                         final long appAllocationUs;
13353                         if (mWakeLockAllocationsUs != null) {
13354                             appAllocationUs =
13355                                     (cpuFreqTimeMs[freqIndex] * 1000 * WAKE_LOCK_WEIGHT) / 100;
13356                             mWakeLockAllocationsUs[cluster][speed] +=
13357                                     (cpuFreqTimeMs[freqIndex] * 1000 - appAllocationUs);
13358                         } else {
13359                             appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
13360                         }
13361                         cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
13362 
13363                         if (powerAccumulator != null) {
13364                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
13365                                     speed, appAllocationUs / 1000);
13366                         }
13367                         freqIndex++;
13368                     }
13369                 }
13370             }
13371         });
13372 
13373         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
13374         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
13375             Slog.d(TAG, "Reading cpu freq times took " + elapsedTimeMs + "ms");
13376         }
13377 
13378         if (mWakeLockAllocationsUs != null) {
13379             for (int i = 0; i < numWakelocks; ++i) {
13380                 final Uid u = partialTimers.get(i).mUid;
13381                 if (u.mCpuClusterSpeedTimesUs == null ||
13382                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
13383                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
13384                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
13385                 }
13386 
13387                 for (int cluster = 0; cluster < numClusters; ++cluster) {
13388                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
13389                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
13390                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
13391                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
13392                         u.mCpuClusterSpeedTimesUs[cluster]
13393                                 = new LongSamplingCounter[speedsInCluster];
13394                     }
13395                     final LongSamplingCounter[] cpuTimeUs = u.mCpuClusterSpeedTimesUs[cluster];
13396                     for (int speed = 0; speed < speedsInCluster; ++speed) {
13397                         if (cpuTimeUs[speed] == null) {
13398                             cpuTimeUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
13399                         }
13400                         final long allocationUs =
13401                                 mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
13402                         cpuTimeUs[speed].addCountLocked(allocationUs, onBattery);
13403                         mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
13404 
13405                         if (powerAccumulator != null) {
13406                             powerAccumulator.addCpuClusterSpeedDurationsMs(u, cluster,
13407                                     speed, allocationUs / 1000);
13408                         }
13409                     }
13410                 }
13411             }
13412         }
13413     }
13414 
13415     /**
13416      * Take a snapshot of the cpu active times spent by each uid and update the corresponding
13417      * counters.
13418      */
13419     @VisibleForTesting
readKernelUidCpuActiveTimesLocked(boolean onBattery)13420     public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
13421         final long startTimeMs = mClocks.uptimeMillis();
13422         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
13423         mCpuUidActiveTimeReader.readDelta(false, (uid, cpuActiveTimesMs) -> {
13424             uid = mapUid(uid);
13425             if (Process.isIsolated(uid)) {
13426                 if (DEBUG) Slog.w(TAG, "Got active times for an isolated uid: " + uid);
13427                 return;
13428             }
13429             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
13430                 if (DEBUG) Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
13431                 return;
13432             }
13433             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
13434             u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesMs, onBattery);
13435         });
13436 
13437         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
13438         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
13439             Slog.d(TAG, "Reading cpu active times took " + elapsedTimeMs + "ms");
13440         }
13441     }
13442 
13443     /**
13444      * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding
13445      * counters. Will also add estimated power consumptions, if powerAccumulator data structure
13446      * is provided.
13447      *
13448      * @param onBattery whether or not this is onBattery
13449      * @param powerAccumulator object to accumulate the estimated cluster charge consumption.
13450      */
13451     @VisibleForTesting
readKernelUidCpuClusterTimesLocked(boolean onBattery, @Nullable CpuDeltaPowerAccumulator powerAccumulator)13452     public void readKernelUidCpuClusterTimesLocked(boolean onBattery,
13453             @Nullable CpuDeltaPowerAccumulator powerAccumulator) {
13454         final long startTimeMs = mClocks.uptimeMillis();
13455         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
13456         // If power is being accumulated for attribution, data needs to be read immediately.
13457         final boolean forceRead = powerAccumulator != null;
13458         mCpuUidClusterTimeReader.readDelta(forceRead, (uid, cpuClusterTimesMs) -> {
13459             uid = mapUid(uid);
13460             if (Process.isIsolated(uid)) {
13461                 if (DEBUG) Slog.w(TAG, "Got cluster times for an isolated uid: " + uid);
13462                 return;
13463             }
13464             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
13465                 if (DEBUG) Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
13466                 return;
13467             }
13468             final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs);
13469             u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesMs, onBattery);
13470 
13471             if (powerAccumulator != null) {
13472                 powerAccumulator.addCpuClusterDurationsMs(u, cpuClusterTimesMs);
13473             }
13474         });
13475 
13476         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
13477         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
13478             Slog.d(TAG, "Reading cpu cluster times took " + elapsedTimeMs + "ms");
13479         }
13480     }
13481 
setChargingLocked(boolean charging)13482     boolean setChargingLocked(boolean charging) {
13483         // if the device is no longer charging, remove the callback
13484         // if the device is now charging, it means that this is either called
13485         // 1. directly when level >= 90
13486         // 2. or from within the runnable that we deferred
13487         // For 1. if we have an existing callback, remove it, since we will immediately send a
13488         // ACTION_CHARGING
13489         // For 2. we remove existing callback so we don't send multiple ACTION_CHARGING
13490         mHandler.removeCallbacks(mDeferSetCharging);
13491         if (mCharging != charging) {
13492             mCharging = charging;
13493             if (charging) {
13494                 mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
13495             } else {
13496                 mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
13497             }
13498             mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
13499             return true;
13500         }
13501         return false;
13502     }
13503 
13504     /**
13505      * Notifies BatteryStatsImpl that the system server is ready.
13506      */
onSystemReady()13507     public void onSystemReady() {
13508         mSystemReady = true;
13509     }
13510 
13511     @GuardedBy("this")
setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery, final int oldStatus, final int level, final int chargeUah)13512     protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
13513             final boolean onBattery, final int oldStatus, final int level, final int chargeUah) {
13514         boolean doWrite = false;
13515         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
13516         m.arg1 = onBattery ? 1 : 0;
13517         mHandler.sendMessage(m);
13518 
13519         final long uptimeUs = mSecUptime * 1000;
13520         final long realtimeUs = mSecRealtime * 1000;
13521         final int screenState = mScreenState;
13522         if (onBattery) {
13523             // We will reset our status if we are unplugging after the
13524             // battery was last full, or the level is at 100, or
13525             // we have gone through a significant charge (from a very low
13526             // level to a now very high level).
13527             // Also, we will reset the stats if battery got partially charged
13528             // and discharged repeatedly without ever reaching the full charge.
13529             // This reset is done in order to prevent stats sessions from going on forever.
13530             // Exceedingly long battery sessions would lead to an overflow of
13531             // data structures such as mWakeupReasonStats.
13532             boolean reset = false;
13533             if (!mNoAutoReset && mSystemReady
13534                     && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
13535                     || level >= 90
13536                     || (mDischargeCurrentLevel < 20 && level >= 80)
13537                     || getHighDischargeAmountSinceCharge() >= 200)) {
13538                 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
13539                         + " dischargeLevel=" + mDischargeCurrentLevel
13540                         + " lowAmount=" + getLowDischargeAmountSinceCharge()
13541                         + " highAmount=" + getHighDischargeAmountSinceCharge());
13542                 // Before we write, collect a snapshot of the final aggregated
13543                 // stats to be reported in the next checkin.  Only do this if we have
13544                 // a sufficient amount of data to make it interesting.
13545                 if (getLowDischargeAmountSinceCharge() >= 20) {
13546                     final long startTimeMs = SystemClock.uptimeMillis();
13547                     final Parcel parcel = Parcel.obtain();
13548                     writeSummaryToParcel(parcel, true);
13549                     final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs;
13550                     BackgroundThread.getHandler().post(new Runnable() {
13551                         @Override public void run() {
13552                             synchronized (mCheckinFile) {
13553                                 final long startTimeMs2 = SystemClock.uptimeMillis();
13554                                 FileOutputStream stream = null;
13555                                 try {
13556                                     stream = mCheckinFile.startWrite();
13557                                     stream.write(parcel.marshall());
13558                                     stream.flush();
13559                                     mCheckinFile.finishWrite(stream);
13560                                     com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
13561                                             "batterystats-checkin", initialTimeMs
13562                                             + SystemClock.uptimeMillis() - startTimeMs2);
13563                                 } catch (IOException e) {
13564                                     Slog.w("BatteryStats",
13565                                             "Error writing checkin battery statistics", e);
13566                                     mCheckinFile.failWrite(stream);
13567                                 } finally {
13568                                     parcel.recycle();
13569                                 }
13570                             }
13571                         }
13572                     });
13573                 }
13574                 doWrite = true;
13575                 resetAllStatsLocked(mSecUptime, mSecRealtime, RESET_REASON_FULL_CHARGE);
13576                 if (chargeUah > 0 && level > 0) {
13577                     // Only use the reported coulomb charge value if it is supported and reported.
13578                     mEstimatedBatteryCapacityMah = (int) ((chargeUah / 1000) / (level / 100.0));
13579                 }
13580                 mDischargeStartLevel = level;
13581                 reset = true;
13582                 mDischargeStepTracker.init();
13583             }
13584             if (mCharging) {
13585                 setChargingLocked(false);
13586             }
13587             mLastChargingStateLevel = level;
13588             mOnBattery = mOnBatteryInternal = true;
13589             mLastDischargeStepLevel = level;
13590             mMinDischargeStepLevel = level;
13591             mDischargeStepTracker.clearTime();
13592             mDailyDischargeStepTracker.clearTime();
13593             mInitStepMode = mCurStepMode;
13594             mModStepMode = 0;
13595             pullPendingStateUpdatesLocked();
13596             mHistoryCur.batteryLevel = (byte)level;
13597             mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
13598             if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
13599                     + Integer.toHexString(mHistoryCur.states));
13600             if (reset) {
13601                 mRecordingHistory = true;
13602                 startRecordingHistory(mSecRealtime, mSecUptime, reset);
13603             }
13604             addHistoryRecordLocked(mSecRealtime, mSecUptime);
13605             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
13606             if (Display.isOnState(screenState)) {
13607                 mDischargeScreenOnUnplugLevel = level;
13608                 mDischargeScreenDozeUnplugLevel = 0;
13609                 mDischargeScreenOffUnplugLevel = 0;
13610             } else if (Display.isDozeState(screenState)) {
13611                 mDischargeScreenOnUnplugLevel = 0;
13612                 mDischargeScreenDozeUnplugLevel = level;
13613                 mDischargeScreenOffUnplugLevel = 0;
13614             } else {
13615                 mDischargeScreenOnUnplugLevel = 0;
13616                 mDischargeScreenDozeUnplugLevel = 0;
13617                 mDischargeScreenOffUnplugLevel = level;
13618             }
13619             mDischargeAmountScreenOn = 0;
13620             mDischargeAmountScreenDoze = 0;
13621             mDischargeAmountScreenOff = 0;
13622             updateTimeBasesLocked(true, screenState, uptimeUs, realtimeUs);
13623         } else {
13624             mLastChargingStateLevel = level;
13625             mOnBattery = mOnBatteryInternal = false;
13626             pullPendingStateUpdatesLocked();
13627             mHistoryCur.batteryLevel = (byte)level;
13628             mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
13629             if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
13630                     + Integer.toHexString(mHistoryCur.states));
13631             addHistoryRecordLocked(mSecRealtime, mSecUptime);
13632             mDischargeCurrentLevel = mDischargePlugLevel = level;
13633             if (level < mDischargeUnplugLevel) {
13634                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
13635                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
13636             }
13637             updateDischargeScreenLevelsLocked(screenState, screenState);
13638             updateTimeBasesLocked(false, screenState, uptimeUs, realtimeUs);
13639             mChargeStepTracker.init();
13640             mLastChargeStepLevel = level;
13641             mMaxChargeStepLevel = level;
13642             mInitStepMode = mCurStepMode;
13643             mModStepMode = 0;
13644         }
13645         if (doWrite || (mLastWriteTimeMs + (60 * 1000)) < mSecRealtime) {
13646             if (mStatsFile != null && mBatteryStatsHistory.getActiveFile() != null) {
13647                 writeAsyncLocked();
13648             }
13649         }
13650     }
13651 
startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs, boolean reset)13652     private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
13653             boolean reset) {
13654         mRecordingHistory = true;
13655         mHistoryCur.currentTime = mClocks.currentTimeMillis();
13656         addHistoryBufferLocked(elapsedRealtimeMs,
13657                 reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
13658                 mHistoryCur);
13659         mHistoryCur.currentTime = 0;
13660         if (reset) {
13661             initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
13662         }
13663     }
13664 
recordCurrentTimeChangeLocked(final long currentTimeMs, final long elapsedRealtimeMs, final long uptimeMs)13665     private void recordCurrentTimeChangeLocked(final long currentTimeMs,
13666             final long elapsedRealtimeMs, final long uptimeMs) {
13667         if (mRecordingHistory) {
13668             mHistoryCur.currentTime = currentTimeMs;
13669             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_CURRENT_TIME, mHistoryCur);
13670             mHistoryCur.currentTime = 0;
13671         }
13672     }
13673 
recordShutdownLocked(final long currentTimeMs, final long elapsedRealtimeMs)13674     private void recordShutdownLocked(final long currentTimeMs, final long elapsedRealtimeMs) {
13675         if (mRecordingHistory) {
13676             mHistoryCur.currentTime = currentTimeMs;
13677             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_SHUTDOWN, mHistoryCur);
13678             mHistoryCur.currentTime = 0;
13679         }
13680     }
13681 
scheduleSyncExternalStatsLocked(String reason, int updateFlags)13682     private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
13683         if (mExternalSync != null) {
13684             mExternalSync.scheduleSync(reason, updateFlags);
13685         }
13686     }
13687 
13688     // This should probably be exposed in the API, though it's not critical
13689     public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
13690 
13691     @GuardedBy("this")
setBatteryStateLocked(final int status, final int health, final int plugType, final int level, int temp, final int voltageMv, final int chargeUah, final int chargeFullUah, final long chargeTimeToFullSeconds)13692     public void setBatteryStateLocked(final int status, final int health, final int plugType,
13693             final int level, /* not final */ int temp, final int voltageMv, final int chargeUah,
13694             final int chargeFullUah, final long chargeTimeToFullSeconds) {
13695         setBatteryStateLocked(status, health, plugType, level, temp, voltageMv, chargeUah,
13696                 chargeFullUah, chargeTimeToFullSeconds,
13697                 mClocks.elapsedRealtime(), mClocks.uptimeMillis(), mClocks.currentTimeMillis());
13698     }
13699 
setBatteryStateLocked(final int status, final int health, final int plugType, final int level, int temp, final int voltageMv, final int chargeUah, final int chargeFullUah, final long chargeTimeToFullSeconds, final long elapsedRealtimeMs, final long uptimeMs, final long currentTimeMs)13700     public void setBatteryStateLocked(final int status, final int health, final int plugType,
13701             final int level, /* not final */ int temp, final int voltageMv, final int chargeUah,
13702             final int chargeFullUah, final long chargeTimeToFullSeconds,
13703             final long elapsedRealtimeMs, final long uptimeMs, final long currentTimeMs) {
13704         // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
13705         temp = Math.max(0, temp);
13706 
13707         reportChangesToStatsLog(mHaveBatteryLevel ? mHistoryCur : null,
13708                 status, plugType, level);
13709 
13710         final boolean onBattery = isOnBattery(plugType, status);
13711         if (!mHaveBatteryLevel) {
13712             mHaveBatteryLevel = true;
13713             // We start out assuming that the device is plugged in (not
13714             // on battery).  If our first report is now that we are indeed
13715             // plugged in, then twiddle our state to correctly reflect that
13716             // since we won't be going through the full setOnBattery().
13717             if (onBattery == mOnBattery) {
13718                 if (onBattery) {
13719                     mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
13720                 } else {
13721                     mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
13722                 }
13723             }
13724             // Always start out assuming charging, that will be updated later.
13725             mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
13726             mHistoryCur.batteryStatus = (byte)status;
13727             mHistoryCur.batteryLevel = (byte)level;
13728             mHistoryCur.batteryChargeUah = chargeUah;
13729             mMaxChargeStepLevel = mMinDischargeStepLevel =
13730                     mLastChargeStepLevel = mLastDischargeStepLevel = level;
13731             mLastChargingStateLevel = level;
13732         } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
13733             recordDailyStatsIfNeededLocked(level >= 100 && onBattery, currentTimeMs);
13734         }
13735         int oldStatus = mHistoryCur.batteryStatus;
13736         if (onBattery) {
13737             mDischargeCurrentLevel = level;
13738             if (!mRecordingHistory) {
13739                 mRecordingHistory = true;
13740                 startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
13741             }
13742         } else if (level < 96 &&
13743                 status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
13744             if (!mRecordingHistory) {
13745                 mRecordingHistory = true;
13746                 startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
13747             }
13748         }
13749         mBatteryVoltageMv = voltageMv;
13750         mCurrentBatteryLevel = level;
13751         if (mDischargePlugLevel < 0) {
13752             mDischargePlugLevel = level;
13753         }
13754 
13755         if (onBattery != mOnBattery) {
13756             mHistoryCur.batteryLevel = (byte)level;
13757             mHistoryCur.batteryStatus = (byte)status;
13758             mHistoryCur.batteryHealth = (byte)health;
13759             mHistoryCur.batteryPlugType = (byte)plugType;
13760             mHistoryCur.batteryTemperature = (short)temp;
13761             mHistoryCur.batteryVoltage = (char) voltageMv;
13762             if (chargeUah < mHistoryCur.batteryChargeUah) {
13763                 // Only record discharges
13764                 final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah;
13765                 mDischargeCounter.addCountLocked(chargeDiff);
13766                 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
13767                 if (Display.isDozeState(mScreenState)) {
13768                     mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
13769                 }
13770                 if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
13771                     mDischargeLightDozeCounter.addCountLocked(chargeDiff);
13772                 } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
13773                     mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
13774                 }
13775             }
13776             mHistoryCur.batteryChargeUah = chargeUah;
13777             setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUah);
13778         } else {
13779             boolean changed = false;
13780             if (mHistoryCur.batteryLevel != level) {
13781                 mHistoryCur.batteryLevel = (byte)level;
13782                 changed = true;
13783 
13784                 // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
13785                 // which will pull external stats.
13786                 mExternalSync.scheduleSyncDueToBatteryLevelChange(
13787                         mConstants.BATTERY_LEVEL_COLLECTION_DELAY_MS);
13788             }
13789             if (mHistoryCur.batteryStatus != status) {
13790                 mHistoryCur.batteryStatus = (byte)status;
13791                 changed = true;
13792             }
13793             if (mHistoryCur.batteryHealth != health) {
13794                 mHistoryCur.batteryHealth = (byte)health;
13795                 changed = true;
13796             }
13797             if (mHistoryCur.batteryPlugType != plugType) {
13798                 mHistoryCur.batteryPlugType = (byte)plugType;
13799                 changed = true;
13800             }
13801             if (temp >= (mHistoryCur.batteryTemperature+10)
13802                     || temp <= (mHistoryCur.batteryTemperature-10)) {
13803                 mHistoryCur.batteryTemperature = (short)temp;
13804                 changed = true;
13805             }
13806             if (voltageMv > (mHistoryCur.batteryVoltage + 20)
13807                     || voltageMv < (mHistoryCur.batteryVoltage - 20)) {
13808                 mHistoryCur.batteryVoltage = (char) voltageMv;
13809                 changed = true;
13810             }
13811             if (chargeUah >= (mHistoryCur.batteryChargeUah + 10)
13812                     || chargeUah <= (mHistoryCur.batteryChargeUah - 10)) {
13813                 if (chargeUah < mHistoryCur.batteryChargeUah) {
13814                     // Only record discharges
13815                     final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah;
13816                     mDischargeCounter.addCountLocked(chargeDiff);
13817                     mDischargeScreenOffCounter.addCountLocked(chargeDiff);
13818                     if (Display.isDozeState(mScreenState)) {
13819                         mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
13820                     }
13821                     if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
13822                         mDischargeLightDozeCounter.addCountLocked(chargeDiff);
13823                     } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
13824                         mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
13825                     }
13826                 }
13827                 mHistoryCur.batteryChargeUah = chargeUah;
13828                 changed = true;
13829             }
13830             long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
13831                     | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
13832                     | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
13833             if (onBattery) {
13834                 changed |= setChargingLocked(false);
13835                 if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
13836                     mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
13837                             modeBits, elapsedRealtimeMs);
13838                     mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
13839                             modeBits, elapsedRealtimeMs);
13840                     mLastDischargeStepLevel = level;
13841                     mMinDischargeStepLevel = level;
13842                     mInitStepMode = mCurStepMode;
13843                     mModStepMode = 0;
13844                 }
13845             } else {
13846                 if (level >= 90) {
13847                     // If the battery level is at least 90%, always consider the device to be
13848                     // charging even if it happens to go down a level.
13849                     changed |= setChargingLocked(true);
13850                 } else if (!mCharging) {
13851                     if (mLastChargeStepLevel < level) {
13852                         // We have not reported that we are charging, but the level has gone up,
13853                         // but we would like to not have tons of activity from charging-constraint
13854                         // jobs, so instead of reporting ACTION_CHARGING immediately, we defer it.
13855                         if (!mHandler.hasCallbacks(mDeferSetCharging)) {
13856                             mHandler.postDelayed(
13857                                     mDeferSetCharging,
13858                                     mConstants.BATTERY_CHARGED_DELAY_MS);
13859                         }
13860                     } else if (mLastChargeStepLevel > level) {
13861                         // if we had deferred a runnable due to charge level increasing, but then
13862                         // later the charge level drops (could be due to thermal issues), we don't
13863                         // want to trigger the deferred runnable, so remove it here
13864                         mHandler.removeCallbacks(mDeferSetCharging);
13865                     }
13866                 } else {
13867                     if (mLastChargeStepLevel > level) {
13868                         // We had reported that the device was charging, but here we are with
13869                         // power connected and the level going down.  Looks like the current
13870                         // power supplied isn't enough, so consider the device to now be
13871                         // discharging.
13872                         changed |= setChargingLocked(false);
13873                     }
13874                 }
13875                 if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
13876                     mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
13877                             modeBits, elapsedRealtimeMs);
13878                     mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
13879                             modeBits, elapsedRealtimeMs);
13880                     mMaxChargeStepLevel = level;
13881                     mInitStepMode = mCurStepMode;
13882                     mModStepMode = 0;
13883                 }
13884                 mLastChargeStepLevel = level;
13885             }
13886             if (changed) {
13887                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
13888             }
13889         }
13890         if (!onBattery &&
13891                 (status == BatteryManager.BATTERY_STATUS_FULL ||
13892                         status == BatteryManager.BATTERY_STATUS_UNKNOWN)) {
13893             // We don't record history while we are plugged in and fully charged
13894             // (or when battery is not present).  The next time we are
13895             // unplugged, history will be cleared.
13896             mRecordingHistory = DEBUG;
13897         }
13898 
13899         mLastLearnedBatteryCapacityUah = chargeFullUah;
13900         if (mMinLearnedBatteryCapacityUah == -1) {
13901             mMinLearnedBatteryCapacityUah = chargeFullUah;
13902         } else {
13903             mMinLearnedBatteryCapacityUah = Math.min(mMinLearnedBatteryCapacityUah, chargeFullUah);
13904         }
13905         mMaxLearnedBatteryCapacityUah = Math.max(mMaxLearnedBatteryCapacityUah, chargeFullUah);
13906 
13907         mBatteryTimeToFullSeconds = chargeTimeToFullSeconds;
13908     }
13909 
isOnBattery(int plugType, int status)13910     public static boolean isOnBattery(int plugType, int status) {
13911         return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN;
13912     }
13913 
13914     // Inform StatsLog of setBatteryState changes.
13915     // If this is the first reporting, pass in recentPast == null.
reportChangesToStatsLog(HistoryItem recentPast, final int status, final int plugType, final int level)13916     private void reportChangesToStatsLog(HistoryItem recentPast,
13917             final int status, final int plugType, final int level) {
13918 
13919         if (recentPast == null || recentPast.batteryStatus != status) {
13920             FrameworkStatsLog.write(FrameworkStatsLog.CHARGING_STATE_CHANGED, status);
13921         }
13922         if (recentPast == null || recentPast.batteryPlugType != plugType) {
13923             FrameworkStatsLog.write(FrameworkStatsLog.PLUGGED_STATE_CHANGED, plugType);
13924         }
13925         if (recentPast == null || recentPast.batteryLevel != level) {
13926             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_LEVEL_CHANGED, level);
13927         }
13928     }
13929 
13930     @UnsupportedAppUsage
getAwakeTimeBattery()13931     public long getAwakeTimeBattery() {
13932         // This previously evaluated to mOnBatteryTimeBase.getUptime(getBatteryUptimeLocked());
13933         // for over a decade, but surely that was a mistake.
13934         return getBatteryUptimeLocked(mClocks.uptimeMillis());
13935     }
13936 
13937     @UnsupportedAppUsage
getAwakeTimePlugged()13938     public long getAwakeTimePlugged() {
13939         return (mClocks.uptimeMillis() * 1000) - getAwakeTimeBattery();
13940     }
13941 
13942     @Override
computeUptime(long curTimeUs, int which)13943     public long computeUptime(long curTimeUs, int which) {
13944         return mUptimeUs + (curTimeUs - mUptimeStartUs);
13945     }
13946 
13947     @Override
computeRealtime(long curTimeUs, int which)13948     public long computeRealtime(long curTimeUs, int which) {
13949         return mRealtimeUs + (curTimeUs - mRealtimeStartUs);
13950     }
13951 
13952     @Override
13953     @UnsupportedAppUsage
computeBatteryUptime(long curTimeUs, int which)13954     public long computeBatteryUptime(long curTimeUs, int which) {
13955         return mOnBatteryTimeBase.computeUptime(curTimeUs, which);
13956     }
13957 
13958     @Override
13959     @UnsupportedAppUsage
computeBatteryRealtime(long curTimeUs, int which)13960     public long computeBatteryRealtime(long curTimeUs, int which) {
13961         return mOnBatteryTimeBase.computeRealtime(curTimeUs, which);
13962     }
13963 
13964     @Override
computeBatteryScreenOffUptime(long curTimeUs, int which)13965     public long computeBatteryScreenOffUptime(long curTimeUs, int which) {
13966         return mOnBatteryScreenOffTimeBase.computeUptime(curTimeUs, which);
13967     }
13968 
13969     @Override
computeBatteryScreenOffRealtime(long curTimeUs, int which)13970     public long computeBatteryScreenOffRealtime(long curTimeUs, int which) {
13971         return mOnBatteryScreenOffTimeBase.computeRealtime(curTimeUs, which);
13972     }
13973 
computeTimePerLevel(long[] steps, int numSteps)13974     private long computeTimePerLevel(long[] steps, int numSteps) {
13975         // For now we'll do a simple average across all steps.
13976         if (numSteps <= 0) {
13977             return -1;
13978         }
13979         long total = 0;
13980         for (int i=0; i<numSteps; i++) {
13981             total += steps[i] & STEP_LEVEL_TIME_MASK;
13982         }
13983         return total / numSteps;
13984         /*
13985         long[] buckets = new long[numSteps];
13986         int numBuckets = 0;
13987         int numToAverage = 4;
13988         int i = 0;
13989         while (i < numSteps) {
13990             long totalTime = 0;
13991             int num = 0;
13992             for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
13993                 totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
13994                 num++;
13995             }
13996             buckets[numBuckets] = totalTime / num;
13997             numBuckets++;
13998             numToAverage *= 2;
13999             i += num;
14000         }
14001         if (numBuckets < 1) {
14002             return -1;
14003         }
14004         long averageTime = buckets[numBuckets-1];
14005         for (i=numBuckets-2; i>=0; i--) {
14006             averageTime = (averageTime + buckets[i]) / 2;
14007         }
14008         return averageTime;
14009         */
14010     }
14011 
14012     @Override
14013     @UnsupportedAppUsage
computeBatteryTimeRemaining(long curTime)14014     public long computeBatteryTimeRemaining(long curTime) {
14015         if (!mOnBattery) {
14016             return -1;
14017         }
14018         /* Simple implementation just looks at the average discharge per level across the
14019            entire sample period.
14020         int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
14021         if (discharge < 2) {
14022             return -1;
14023         }
14024         long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
14025         if (duration < 1000*1000) {
14026             return -1;
14027         }
14028         long usPerLevel = duration/discharge;
14029         return usPerLevel * mCurrentBatteryLevel;
14030         */
14031         if (mDischargeStepTracker.mNumStepDurations < 1) {
14032             return -1;
14033         }
14034         long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
14035         if (msPerLevel <= 0) {
14036             return -1;
14037         }
14038         return (msPerLevel * mCurrentBatteryLevel) * 1000;
14039     }
14040 
14041     @Override
getDischargeLevelStepTracker()14042     public LevelStepTracker getDischargeLevelStepTracker() {
14043         return mDischargeStepTracker;
14044     }
14045 
14046     @Override
getDailyDischargeLevelStepTracker()14047     public LevelStepTracker getDailyDischargeLevelStepTracker() {
14048         return mDailyDischargeStepTracker;
14049     }
14050 
14051     @Override
computeChargeTimeRemaining(long curTime)14052     public long computeChargeTimeRemaining(long curTime) {
14053         if (mOnBattery) {
14054             // Not yet working.
14055             return -1;
14056         }
14057         if (mBatteryTimeToFullSeconds >= 0) {
14058             return mBatteryTimeToFullSeconds * (1000 * 1000); // s to us
14059         }
14060         // Else use algorithmic approach
14061         if (mChargeStepTracker.mNumStepDurations < 1) {
14062             return -1;
14063         }
14064         long msPerLevel = mChargeStepTracker.computeTimePerLevel();
14065         if (msPerLevel <= 0) {
14066             return -1;
14067         }
14068         return (msPerLevel * (100 - mCurrentBatteryLevel)) * 1000;
14069     }
14070 
14071     /*@hide */
getCellularBatteryStats()14072     public CellularBatteryStats getCellularBatteryStats() {
14073         final int which = STATS_SINCE_CHARGED;
14074         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
14075         final ControllerActivityCounter counter = getModemControllerActivity();
14076         final long sleepTimeMs = counter.getSleepTimeCounter().getCountLocked(which);
14077         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
14078         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
14079         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
14080         final long monitoredRailChargeConsumedMaMs =
14081                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
14082         long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
14083         for (int i = 0; i < timeInRatMs.length; i++) {
14084             timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTimeUs, which) / 1000;
14085         }
14086         long[] timeInRxSignalStrengthLevelMs =
14087                 new long[CellSignalStrength.getNumSignalStrengthLevels()];
14088         for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
14089             timeInRxSignalStrengthLevelMs[i] =
14090                 getPhoneSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
14091         }
14092         long[] txTimeMs = new long[Math.min(ModemActivityInfo.getNumTxPowerLevels(),
14093             counter.getTxTimeCounters().length)];
14094         long totalTxTimeMs = 0;
14095         for (int i = 0; i < txTimeMs.length; i++) {
14096             txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
14097             totalTxTimeMs += txTimeMs[i];
14098         }
14099 
14100         return new CellularBatteryStats(computeBatteryRealtime(rawRealTimeUs, which) / 1000,
14101                 getMobileRadioActiveTime(rawRealTimeUs, which) / 1000,
14102                 getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which),
14103                 getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which),
14104                 getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which),
14105                 getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which),
14106                 sleepTimeMs, idleTimeMs, rxTimeMs, energyConsumedMaMs, timeInRatMs,
14107                 timeInRxSignalStrengthLevelMs, txTimeMs,
14108                 monitoredRailChargeConsumedMaMs);
14109     }
14110 
14111     /*@hide */
getWifiBatteryStats()14112     public WifiBatteryStats getWifiBatteryStats() {
14113         final int which = STATS_SINCE_CHARGED;
14114         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
14115         final ControllerActivityCounter counter = getWifiControllerActivity();
14116         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
14117         final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which);
14118         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
14119         final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which);
14120         final long totalControllerActivityTimeMs
14121                 = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000;
14122         final long sleepTimeMs
14123                 = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs);
14124         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
14125         final long monitoredRailChargeConsumedMaMs =
14126                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
14127         long numAppScanRequest = 0;
14128         for (int i = 0; i < mUidStats.size(); i++) {
14129             numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which);
14130         }
14131         long[] timeInStateMs = new long[NUM_WIFI_STATES];
14132         for (int i=0; i<NUM_WIFI_STATES; i++) {
14133             timeInStateMs[i] = getWifiStateTime(i, rawRealTimeUs, which) / 1000;
14134         }
14135         long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES];
14136         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14137             timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTimeUs, which) / 1000;
14138         }
14139         long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS];
14140         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14141             timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
14142         }
14143         return new WifiBatteryStats(
14144                 computeBatteryRealtime(rawRealTimeUs, which) / 1000,
14145                 getWifiActiveTime(rawRealTimeUs, which) / 1000,
14146                 getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which),
14147                 getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which),
14148                 getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which),
14149                 getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which),
14150                 sleepTimeMs, scanTimeMs, idleTimeMs, rxTimeMs, txTimeMs, energyConsumedMaMs,
14151                 numAppScanRequest, timeInStateMs, timeSignalStrengthTimeMs, timeInSupplStateMs,
14152                 monitoredRailChargeConsumedMaMs);
14153     }
14154 
14155     /*@hide */
getGpsBatteryStats()14156     public GpsBatteryStats getGpsBatteryStats() {
14157         GpsBatteryStats s = new GpsBatteryStats();
14158         final int which = STATS_SINCE_CHARGED;
14159         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
14160         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTimeUs, which) / 1000);
14161         s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
14162         long[] time = new long[mGpsSignalQualityTimer.length];
14163         for (int i=0; i<time.length; i++) {
14164             time[i] = getGpsSignalQualityTime(i, rawRealTimeUs, which) / 1000;
14165         }
14166         s.setTimeInGpsSignalQualityLevel(time);
14167         return s;
14168     }
14169 
14170     @Override
getChargeLevelStepTracker()14171     public LevelStepTracker getChargeLevelStepTracker() {
14172         return mChargeStepTracker;
14173     }
14174 
14175     @Override
getDailyChargeLevelStepTracker()14176     public LevelStepTracker getDailyChargeLevelStepTracker() {
14177         return mDailyChargeStepTracker;
14178     }
14179 
14180     @Override
getDailyPackageChanges()14181     public ArrayList<PackageChange> getDailyPackageChanges() {
14182         return mDailyPackageChanges;
14183     }
14184 
14185     /**
14186      * @return battery uptime in microseconds
14187      */
getBatteryUptimeLocked()14188     protected long getBatteryUptimeLocked() {
14189         return getBatteryUptimeLocked(mClocks.uptimeMillis());
14190     }
14191 
14192     /**
14193      * @return battery uptime in microseconds
14194      */
getBatteryUptimeLocked(long uptimeMs)14195     protected long getBatteryUptimeLocked(long uptimeMs) {
14196         return mOnBatteryTimeBase.getUptime(uptimeMs * 1000);
14197     }
14198 
14199     @Override
getBatteryUptime(long curTimeUs)14200     public long getBatteryUptime(long curTimeUs) {
14201         return mOnBatteryTimeBase.getUptime(curTimeUs);
14202     }
14203 
14204     @Override
14205     @UnsupportedAppUsage
getBatteryRealtime(long curTimeUs)14206     public long getBatteryRealtime(long curTimeUs) {
14207         return mOnBatteryTimeBase.getRealtime(curTimeUs);
14208     }
14209 
14210     @Override
14211     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getDischargeStartLevel()14212     public int getDischargeStartLevel() {
14213         synchronized(this) {
14214             return getDischargeStartLevelLocked();
14215         }
14216     }
14217 
getDischargeStartLevelLocked()14218     public int getDischargeStartLevelLocked() {
14219             return mDischargeUnplugLevel;
14220     }
14221 
14222     @Override
14223     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getDischargeCurrentLevel()14224     public int getDischargeCurrentLevel() {
14225         synchronized(this) {
14226             return getDischargeCurrentLevelLocked();
14227         }
14228     }
14229 
getDischargeCurrentLevelLocked()14230     public int getDischargeCurrentLevelLocked() {
14231         return mDischargeCurrentLevel;
14232     }
14233 
14234     @Override
getLowDischargeAmountSinceCharge()14235     public int getLowDischargeAmountSinceCharge() {
14236         synchronized(this) {
14237             int val = mLowDischargeAmountSinceCharge;
14238             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
14239                 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
14240             }
14241             return val;
14242         }
14243     }
14244 
14245     @Override
getHighDischargeAmountSinceCharge()14246     public int getHighDischargeAmountSinceCharge() {
14247         synchronized(this) {
14248             int val = mHighDischargeAmountSinceCharge;
14249             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
14250                 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
14251             }
14252             return val;
14253         }
14254     }
14255 
14256     @Override
14257     @UnsupportedAppUsage
getDischargeAmount(int which)14258     public int getDischargeAmount(int which) {
14259         int dischargeAmount = which == STATS_SINCE_CHARGED
14260                 ? getHighDischargeAmountSinceCharge()
14261                 : (getDischargeStartLevel() - getDischargeCurrentLevel());
14262         if (dischargeAmount < 0) {
14263             dischargeAmount = 0;
14264         }
14265         return dischargeAmount;
14266     }
14267 
14268     @Override
14269     @UnsupportedAppUsage
getDischargeAmountScreenOn()14270     public int getDischargeAmountScreenOn() {
14271         synchronized(this) {
14272             int val = mDischargeAmountScreenOn;
14273             if (mOnBattery && Display.isOnState(mScreenState)
14274                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
14275                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
14276             }
14277             return val;
14278         }
14279     }
14280 
14281     @Override
getDischargeAmountScreenOnSinceCharge()14282     public int getDischargeAmountScreenOnSinceCharge() {
14283         synchronized(this) {
14284             int val = mDischargeAmountScreenOnSinceCharge;
14285             if (mOnBattery && Display.isOnState(mScreenState)
14286                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
14287                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
14288             }
14289             return val;
14290         }
14291     }
14292 
14293     @Override
14294     @UnsupportedAppUsage
getDischargeAmountScreenOff()14295     public int getDischargeAmountScreenOff() {
14296         synchronized(this) {
14297             int val = mDischargeAmountScreenOff;
14298             if (mOnBattery && Display.isOffState(mScreenState)
14299                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
14300                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
14301             }
14302             // For backward compatibility, doze discharge is counted into screen off.
14303             return val + getDischargeAmountScreenDoze();
14304         }
14305     }
14306 
14307     @Override
getDischargeAmountScreenOffSinceCharge()14308     public int getDischargeAmountScreenOffSinceCharge() {
14309         synchronized(this) {
14310             int val = mDischargeAmountScreenOffSinceCharge;
14311             if (mOnBattery && Display.isOffState(mScreenState)
14312                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
14313                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
14314             }
14315             // For backward compatibility, doze discharge is counted into screen off.
14316             return val + getDischargeAmountScreenDozeSinceCharge();
14317         }
14318     }
14319 
14320     @Override
getDischargeAmountScreenDoze()14321     public int getDischargeAmountScreenDoze() {
14322         synchronized(this) {
14323             int val = mDischargeAmountScreenDoze;
14324             if (mOnBattery && Display.isDozeState(mScreenState)
14325                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
14326                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
14327             }
14328             return val;
14329         }
14330     }
14331 
14332     @Override
getDischargeAmountScreenDozeSinceCharge()14333     public int getDischargeAmountScreenDozeSinceCharge() {
14334         synchronized(this) {
14335             int val = mDischargeAmountScreenDozeSinceCharge;
14336             if (mOnBattery && Display.isDozeState(mScreenState)
14337                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
14338                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
14339             }
14340             return val;
14341         }
14342     }
14343 
14344 
14345     /**
14346      * Estimates the time spent by the system server handling incoming binder requests.
14347      */
14348     @Override
getSystemServiceTimeAtCpuSpeeds()14349     public long[] getSystemServiceTimeAtCpuSpeeds() {
14350         if (mBinderThreadCpuTimesUs == null) {
14351             return null;
14352         }
14353 
14354         return mBinderThreadCpuTimesUs.getCountsLocked(BatteryStats.STATS_SINCE_CHARGED);
14355     }
14356 
14357     /**
14358      * Retrieve the statistics object for a particular uid, creating if needed.
14359      */
14360     @UnsupportedAppUsage
getUidStatsLocked(int uid)14361     public Uid getUidStatsLocked(int uid) {
14362         return getUidStatsLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
14363     }
14364 
getUidStatsLocked(int uid, long elapsedRealtimeMs, long uptimeMs)14365     public Uid getUidStatsLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
14366         Uid u = mUidStats.get(uid);
14367         if (u == null) {
14368             u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
14369             mUidStats.put(uid, u);
14370         }
14371         return u;
14372     }
14373 
14374     /**
14375      * Retrieve the statistics object for a particular uid. Returns null if the object is not
14376      * available.
14377      */
getAvailableUidStatsLocked(int uid)14378     public Uid getAvailableUidStatsLocked(int uid) {
14379         Uid u = mUidStats.get(uid);
14380         return u;
14381     }
14382 
onCleanupUserLocked(int userId, long elapsedRealtimeMs)14383     public void onCleanupUserLocked(int userId, long elapsedRealtimeMs) {
14384         final int firstUidForUser = UserHandle.getUid(userId, 0);
14385         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
14386         mPendingRemovedUids.add(
14387                 new UidToRemove(firstUidForUser, lastUidForUser, elapsedRealtimeMs));
14388     }
14389 
onUserRemovedLocked(int userId)14390     public void onUserRemovedLocked(int userId) {
14391         final int firstUidForUser = UserHandle.getUid(userId, 0);
14392         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
14393         mUidStats.put(firstUidForUser, null);
14394         mUidStats.put(lastUidForUser, null);
14395         final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
14396         final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
14397         for (int i = firstIndex; i <= lastIndex; i++) {
14398             final Uid uid = mUidStats.valueAt(i);
14399             if (uid != null) {
14400                 uid.detachFromTimeBase();
14401             }
14402         }
14403         mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
14404     }
14405 
14406     /**
14407      * Remove the statistics object for a particular uid.
14408      */
14409     @UnsupportedAppUsage
removeUidStatsLocked(int uid)14410     public void removeUidStatsLocked(int uid) {
14411         removeUidStatsLocked(uid, mClocks.elapsedRealtime());
14412     }
14413 
14414     /**
14415      * @see #removeUidStatsLocked(int)
14416      */
removeUidStatsLocked(int uid, long elapsedRealtimeMs)14417     public void removeUidStatsLocked(int uid, long elapsedRealtimeMs) {
14418         final Uid u = mUidStats.get(uid);
14419         if (u != null) {
14420             u.detachFromTimeBase();
14421         }
14422         mUidStats.remove(uid);
14423         mPendingRemovedUids.add(new UidToRemove(uid, elapsedRealtimeMs));
14424     }
14425 
14426     /**
14427      * Retrieve the statistics object for a particular process, creating
14428      * if needed.
14429      */
14430     @UnsupportedAppUsage
getProcessStatsLocked(int uid, String name)14431     public Uid.Proc getProcessStatsLocked(int uid, String name) {
14432         return getProcessStatsLocked(uid, name, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
14433     }
14434 
14435     /**
14436      * @see #getProcessStatsLocked(int, String)
14437      */
getProcessStatsLocked(int uid, String name, long elapsedRealtimeMs, long uptimeMs)14438     public Uid.Proc getProcessStatsLocked(int uid, String name,
14439             long elapsedRealtimeMs, long uptimeMs) {
14440         uid = mapUid(uid);
14441         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
14442         return u.getProcessStatsLocked(name);
14443     }
14444 
14445     /**
14446      * Retrieve the statistics object for a particular process, creating
14447      * if needed.
14448      */
14449     @UnsupportedAppUsage
getPackageStatsLocked(int uid, String pkg)14450     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
14451         return getPackageStatsLocked(uid, pkg, mClocks.elapsedRealtime(), mClocks.uptimeMillis());
14452     }
14453 
14454     /**
14455      * @see getPackageStatsLocked(int, String)
14456      */
getPackageStatsLocked(int uid, String pkg, long elapsedRealtimeMs, long uptimeMs)14457     public Uid.Pkg getPackageStatsLocked(int uid, String pkg,
14458             long elapsedRealtimeMs, long uptimeMs) {
14459         uid = mapUid(uid);
14460         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
14461         return u.getPackageStatsLocked(pkg);
14462     }
14463 
14464     /**
14465      * Retrieve the statistics object for a particular service, creating
14466      * if needed.
14467      */
14468     @UnsupportedAppUsage
getServiceStatsLocked(int uid, String pkg, String name)14469     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
14470         return getServiceStatsLocked(uid, pkg, name,
14471                 mClocks.elapsedRealtime(), mClocks.uptimeMillis());
14472     }
14473 
getServiceStatsLocked(int uid, String pkg, String name, long elapsedRealtimeMs, long uptimeMs)14474     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name,
14475             long elapsedRealtimeMs, long uptimeMs) {
14476         uid = mapUid(uid);
14477         Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs);
14478         return u.getServiceStatsLocked(pkg, name);
14479     }
14480 
shutdownLocked()14481     public void shutdownLocked() {
14482         recordShutdownLocked(mClocks.currentTimeMillis(), mClocks.elapsedRealtime());
14483         writeSyncLocked();
14484         mShuttingDown = true;
14485     }
14486 
trackPerProcStateCpuTimes()14487     public boolean trackPerProcStateCpuTimes() {
14488         return mConstants.TRACK_CPU_TIMES_BY_PROC_STATE && mPerProcStateCpuTimesAvailable;
14489     }
14490 
systemServicesReady(Context context)14491     public void systemServicesReady(Context context) {
14492         mConstants.startObserving(context.getContentResolver());
14493         registerUsbStateReceiver(context);
14494     }
14495 
14496     /**
14497      * Initialize the measured charge stats data structures.
14498      *
14499      * @param supportedStandardBuckets boolean array indicating which {@link StandardPowerBucket}s
14500      *                                 are currently supported. If null, none are supported
14501      *                                 (regardless of customBucketNames).
14502      * @param customBucketNames        names of custom (OTHER) EnergyConsumers on this device
14503      */
14504     @GuardedBy("this")
initMeasuredEnergyStatsLocked(@ullable boolean[] supportedStandardBuckets, String[] customBucketNames)14505     public void initMeasuredEnergyStatsLocked(@Nullable boolean[] supportedStandardBuckets,
14506             String[] customBucketNames) {
14507         boolean supportedBucketMismatch = false;
14508         mScreenStateAtLastEnergyMeasurement = mScreenState;
14509 
14510         if (supportedStandardBuckets == null) {
14511             if (mGlobalMeasuredEnergyStats != null) {
14512                 // Measured energy no longer supported, wipe out the existing data.
14513                 supportedBucketMismatch = true;
14514             }
14515         } else {
14516             if (mGlobalMeasuredEnergyStats == null) {
14517                 mGlobalMeasuredEnergyStats =
14518                         new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
14519             } else {
14520                 supportedBucketMismatch = !mGlobalMeasuredEnergyStats.isSupportEqualTo(
14521                         supportedStandardBuckets, customBucketNames);
14522             }
14523 
14524             if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH]) {
14525                 mBluetoothPowerCalculator = new BluetoothPowerCalculator(mPowerProfile);
14526             }
14527             if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_CPU]) {
14528                 mCpuPowerCalculator = new CpuPowerCalculator(mPowerProfile);
14529             }
14530             if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO]) {
14531                 mMobileRadioPowerCalculator = new MobileRadioPowerCalculator(mPowerProfile);
14532             }
14533             if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_WIFI]) {
14534                 mWifiPowerCalculator = new WifiPowerCalculator(mPowerProfile);
14535             }
14536         }
14537 
14538         if (supportedBucketMismatch) {
14539             mGlobalMeasuredEnergyStats = supportedStandardBuckets == null
14540                     ? null : new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
14541             // Supported power buckets changed since last boot.
14542             // Existing data is no longer reliable.
14543             resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
14544                     RESET_REASON_MEASURED_ENERGY_BUCKETS_CHANGE);
14545         }
14546     }
14547 
14548     /** Get the last known Battery voltage (in millivolts), returns -1 if unknown */
14549     @GuardedBy("this")
getBatteryVoltageMvLocked()14550     public int getBatteryVoltageMvLocked() {
14551         return mBatteryVoltageMv;
14552     }
14553 
14554     @VisibleForTesting
14555     public final class Constants extends ContentObserver {
14556         public static final String KEY_TRACK_CPU_TIMES_BY_PROC_STATE
14557                 = "track_cpu_times_by_proc_state";
14558         public static final String KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME
14559                 = "track_cpu_active_cluster_time";
14560         public static final String KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS
14561                 = "proc_state_cpu_times_read_delay_ms";
14562         public static final String KEY_KERNEL_UID_READERS_THROTTLE_TIME
14563                 = "kernel_uid_readers_throttle_time";
14564         public static final String KEY_UID_REMOVE_DELAY_MS
14565                 = "uid_remove_delay_ms";
14566         public static final String KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
14567                 = "external_stats_collection_rate_limit_ms";
14568         public static final String KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS
14569                 = "battery_level_collection_delay_ms";
14570         public static final String KEY_MAX_HISTORY_FILES = "max_history_files";
14571         public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
14572         public static final String KEY_BATTERY_CHARGED_DELAY_MS =
14573                 "battery_charged_delay_ms";
14574 
14575         private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = false;
14576         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
14577         private static final long DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS = 5_000;
14578         private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000;
14579         private static final long DEFAULT_UID_REMOVE_DELAY_MS = 5L * 60L * 1000L;
14580         private static final long DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = 600_000;
14581         private static final long DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS = 300_000;
14582         private static final int DEFAULT_MAX_HISTORY_FILES = 32;
14583         private static final int DEFAULT_MAX_HISTORY_BUFFER_KB = 128; /*Kilo Bytes*/
14584         private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64;
14585         private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
14586         private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
14587 
14588         public boolean TRACK_CPU_TIMES_BY_PROC_STATE = DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE;
14589         public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
14590         public long PROC_STATE_CPU_TIMES_READ_DELAY_MS = DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS;
14591         /* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
14592          * update when startObserving. */
14593         public long KERNEL_UID_READERS_THROTTLE_TIME;
14594         public long UID_REMOVE_DELAY_MS = DEFAULT_UID_REMOVE_DELAY_MS;
14595         public long EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
14596                 = DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
14597         public long BATTERY_LEVEL_COLLECTION_DELAY_MS
14598                 = DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS;
14599         public int MAX_HISTORY_FILES;
14600         public int MAX_HISTORY_BUFFER; /*Bytes*/
14601         public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
14602 
14603         private ContentResolver mResolver;
14604         private final KeyValueListParser mParser = new KeyValueListParser(',');
14605 
Constants(Handler handler)14606         public Constants(Handler handler) {
14607             super(handler);
14608             if (ActivityManager.isLowRamDeviceStatic()) {
14609                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE;
14610                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB * 1024;
14611             } else {
14612                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES;
14613                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_KB * 1024;
14614             }
14615         }
14616 
startObserving(ContentResolver resolver)14617         public void startObserving(ContentResolver resolver) {
14618             mResolver = resolver;
14619             mResolver.registerContentObserver(
14620                     Settings.Global.getUriFor(Settings.Global.BATTERY_STATS_CONSTANTS),
14621                     false /* notifyForDescendants */, this);
14622             mResolver.registerContentObserver(
14623                     Settings.Global.getUriFor(Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY),
14624                     false /* notifyForDescendants */, this);
14625             updateConstants();
14626         }
14627 
14628         @Override
onChange(boolean selfChange, Uri uri)14629         public void onChange(boolean selfChange, Uri uri) {
14630             if (uri.equals(
14631                     Settings.Global.getUriFor(
14632                             Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY))) {
14633                 synchronized (BatteryStatsImpl.this) {
14634                     updateBatteryChargedDelayMsLocked();
14635                 }
14636                 return;
14637             }
14638             updateConstants();
14639         }
14640 
updateConstants()14641         private void updateConstants() {
14642             synchronized (BatteryStatsImpl.this) {
14643                 try {
14644                     mParser.setString(Settings.Global.getString(mResolver,
14645                             Settings.Global.BATTERY_STATS_CONSTANTS));
14646                 } catch (IllegalArgumentException e) {
14647                     // Failed to parse the settings string, log this and move on
14648                     // with defaults.
14649                     Slog.e(TAG, "Bad batterystats settings", e);
14650                 }
14651 
14652                 updateTrackCpuTimesByProcStateLocked(TRACK_CPU_TIMES_BY_PROC_STATE,
14653                         mParser.getBoolean(KEY_TRACK_CPU_TIMES_BY_PROC_STATE,
14654                                 DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE));
14655                 TRACK_CPU_ACTIVE_CLUSTER_TIME = mParser.getBoolean(
14656                         KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME, DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME);
14657                 updateProcStateCpuTimesReadDelayMs(PROC_STATE_CPU_TIMES_READ_DELAY_MS,
14658                         mParser.getLong(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS,
14659                                 DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS));
14660                 updateKernelUidReadersThrottleTime(KERNEL_UID_READERS_THROTTLE_TIME,
14661                         mParser.getLong(KEY_KERNEL_UID_READERS_THROTTLE_TIME,
14662                                 DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME));
14663                 updateUidRemoveDelay(
14664                         mParser.getLong(KEY_UID_REMOVE_DELAY_MS, DEFAULT_UID_REMOVE_DELAY_MS));
14665                 EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = mParser.getLong(
14666                         KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS,
14667                         DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
14668                 BATTERY_LEVEL_COLLECTION_DELAY_MS = mParser.getLong(
14669                         KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS,
14670                         DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS);
14671 
14672                 MAX_HISTORY_FILES = mParser.getInt(KEY_MAX_HISTORY_FILES,
14673                         ActivityManager.isLowRamDeviceStatic() ?
14674                                 DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE
14675                         : DEFAULT_MAX_HISTORY_FILES);
14676                 MAX_HISTORY_BUFFER = mParser.getInt(KEY_MAX_HISTORY_BUFFER_KB,
14677                         ActivityManager.isLowRamDeviceStatic() ?
14678                                 DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB
14679                                 : DEFAULT_MAX_HISTORY_BUFFER_KB)
14680                         * 1024;
14681                 updateBatteryChargedDelayMsLocked();
14682             }
14683         }
14684 
updateBatteryChargedDelayMsLocked()14685         private void updateBatteryChargedDelayMsLocked() {
14686             // a negative value indicates that we should ignore this override
14687             final int delay = Settings.Global.getInt(mResolver,
14688                     Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
14689                     -1);
14690 
14691             BATTERY_CHARGED_DELAY_MS = delay >= 0 ? delay : mParser.getInt(
14692                     KEY_BATTERY_CHARGED_DELAY_MS,
14693                     DEFAULT_BATTERY_CHARGED_DELAY_MS);
14694         }
14695 
updateTrackCpuTimesByProcStateLocked(boolean wasEnabled, boolean isEnabled)14696         private void updateTrackCpuTimesByProcStateLocked(boolean wasEnabled, boolean isEnabled) {
14697             TRACK_CPU_TIMES_BY_PROC_STATE = isEnabled;
14698             if (isEnabled && !wasEnabled) {
14699                 mIsPerProcessStateCpuDataStale = true;
14700                 mExternalSync.scheduleCpuSyncDueToSettingChange();
14701 
14702                 mNumSingleUidCpuTimeReads = 0;
14703                 mNumBatchedSingleUidCpuTimeReads = 0;
14704                 mCpuTimeReadsTrackingStartTimeMs = mClocks.uptimeMillis();
14705             }
14706         }
14707 
updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis)14708         private void updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis) {
14709             PROC_STATE_CPU_TIMES_READ_DELAY_MS = newDelayMillis;
14710             if (oldDelayMillis != newDelayMillis) {
14711                 mNumSingleUidCpuTimeReads = 0;
14712                 mNumBatchedSingleUidCpuTimeReads = 0;
14713                 mCpuTimeReadsTrackingStartTimeMs = mClocks.uptimeMillis();
14714             }
14715         }
14716 
updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs)14717         private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
14718             KERNEL_UID_READERS_THROTTLE_TIME = newTimeMs;
14719             if (oldTimeMs != newTimeMs) {
14720                 mCpuUidUserSysTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
14721                 mCpuUidFreqTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
14722                 mCpuUidActiveTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
14723                 mCpuUidClusterTimeReader
14724                         .setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
14725             }
14726         }
14727 
updateUidRemoveDelay(long newTimeMs)14728         private void updateUidRemoveDelay(long newTimeMs) {
14729             UID_REMOVE_DELAY_MS = newTimeMs;
14730             clearPendingRemovedUids();
14731         }
14732 
dumpLocked(PrintWriter pw)14733         public void dumpLocked(PrintWriter pw) {
14734             pw.print(KEY_TRACK_CPU_TIMES_BY_PROC_STATE); pw.print("=");
14735             pw.println(TRACK_CPU_TIMES_BY_PROC_STATE);
14736             pw.print(KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME); pw.print("=");
14737             pw.println(TRACK_CPU_ACTIVE_CLUSTER_TIME);
14738             pw.print(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS); pw.print("=");
14739             pw.println(PROC_STATE_CPU_TIMES_READ_DELAY_MS);
14740             pw.print(KEY_KERNEL_UID_READERS_THROTTLE_TIME); pw.print("=");
14741             pw.println(KERNEL_UID_READERS_THROTTLE_TIME);
14742             pw.print(KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS); pw.print("=");
14743             pw.println(EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
14744             pw.print(KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS); pw.print("=");
14745             pw.println(BATTERY_LEVEL_COLLECTION_DELAY_MS);
14746             pw.print(KEY_MAX_HISTORY_FILES); pw.print("=");
14747             pw.println(MAX_HISTORY_FILES);
14748             pw.print(KEY_MAX_HISTORY_BUFFER_KB); pw.print("=");
14749             pw.println(MAX_HISTORY_BUFFER/1024);
14750             pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("=");
14751             pw.println(BATTERY_CHARGED_DELAY_MS);
14752         }
14753     }
14754 
getExternalStatsCollectionRateLimitMs()14755     public long getExternalStatsCollectionRateLimitMs() {
14756         synchronized (this) {
14757             return mConstants.EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
14758         }
14759     }
14760 
14761     @GuardedBy("this")
dumpConstantsLocked(PrintWriter pw)14762     public void dumpConstantsLocked(PrintWriter pw) {
14763         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
14764         iPw.println("BatteryStats constants:");
14765         iPw.increaseIndent();
14766         mConstants.dumpLocked(iPw);
14767         iPw.decreaseIndent();
14768     }
14769 
14770     @GuardedBy("this")
dumpCpuStatsLocked(PrintWriter pw)14771     public void dumpCpuStatsLocked(PrintWriter pw) {
14772         int size = mUidStats.size();
14773         pw.println("Per UID CPU user & system time in ms:");
14774         for (int i = 0; i < size; i++) {
14775             int u = mUidStats.keyAt(i);
14776             Uid uid = mUidStats.get(u);
14777             pw.print("  "); pw.print(u); pw.print(": ");
14778             pw.print(uid.getUserCpuTimeUs(STATS_SINCE_CHARGED) / 1000); pw.print(" ");
14779             pw.println(uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED) / 1000);
14780         }
14781 
14782         pw.println("Per UID CPU active time in ms:");
14783         for (int i = 0; i < size; i++) {
14784             int u = mUidStats.keyAt(i);
14785             Uid uid = mUidStats.get(u);
14786             if (uid.getCpuActiveTime() > 0) {
14787                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(uid.getCpuActiveTime());
14788             }
14789         }
14790         pw.println("Per UID CPU cluster time in ms:");
14791         for (int i = 0; i < size; i++) {
14792             int u = mUidStats.keyAt(i);
14793             long[] times = mUidStats.get(u).getCpuClusterTimes();
14794             if (times != null) {
14795                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
14796             }
14797         }
14798         pw.println("Per UID CPU frequency time in ms:");
14799         for (int i = 0; i < size; i++) {
14800             int u = mUidStats.keyAt(i);
14801             long[] times = mUidStats.get(u).getCpuFreqTimes(STATS_SINCE_CHARGED);
14802             if (times != null) {
14803                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
14804             }
14805         }
14806 
14807         updateSystemServiceCallStats();
14808         if (mBinderThreadCpuTimesUs != null) {
14809             pw.println("Per UID System server binder time in ms:");
14810             long[] systemServiceTimeAtCpuSpeeds = getSystemServiceTimeAtCpuSpeeds();
14811             for (int i = 0; i < size; i++) {
14812                 int u = mUidStats.keyAt(i);
14813                 Uid uid = mUidStats.get(u);
14814                 double proportionalSystemServiceUsage = uid.getProportionalSystemServiceUsage();
14815                 long timeUs = 0;
14816                 for (int j = systemServiceTimeAtCpuSpeeds.length - 1; j >= 0; j--) {
14817                     timeUs += systemServiceTimeAtCpuSpeeds[j] * proportionalSystemServiceUsage;
14818                 }
14819 
14820                 pw.print("  ");
14821                 pw.print(u);
14822                 pw.print(": ");
14823                 pw.println(timeUs / 1000);
14824             }
14825         }
14826     }
14827 
14828     /**
14829      * Dump measured charge stats
14830      */
14831     @GuardedBy("this")
dumpMeasuredEnergyStatsLocked(PrintWriter pw)14832     public void dumpMeasuredEnergyStatsLocked(PrintWriter pw) {
14833         pw.printf("On battery measured charge stats (microcoulombs) \n");
14834         if (mGlobalMeasuredEnergyStats == null) {
14835             pw.printf("    Not supported on this device.\n");
14836             return;
14837         }
14838 
14839         dumpMeasuredEnergyStatsLocked(pw, "global usage", mGlobalMeasuredEnergyStats);
14840 
14841         int size = mUidStats.size();
14842         for (int i = 0; i < size; i++) {
14843             final int u = mUidStats.keyAt(i);
14844             final Uid uid = mUidStats.get(u);
14845             final String name = "uid " + uid.mUid;
14846             dumpMeasuredEnergyStatsLocked(pw, name, uid.mUidMeasuredEnergyStats);
14847         }
14848     }
14849 
14850     /** Dump measured charge stats for the given uid */
14851     @GuardedBy("this")
dumpMeasuredEnergyStatsLocked(PrintWriter pw, String name, MeasuredEnergyStats stats)14852     private void dumpMeasuredEnergyStatsLocked(PrintWriter pw, String name,
14853             MeasuredEnergyStats stats) {
14854         if (stats == null) return;
14855         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
14856         iPw.increaseIndent();
14857         iPw.printf("%s:\n", name);
14858         iPw.increaseIndent();
14859         stats.dump(iPw);
14860         iPw.decreaseIndent();
14861     }
14862 
14863     final ReentrantLock mWriteLock = new ReentrantLock();
14864 
writeAsyncLocked()14865     public void writeAsyncLocked() {
14866         writeStatsLocked(false);
14867         writeHistoryLocked(false);
14868     }
14869 
writeSyncLocked()14870     public void writeSyncLocked() {
14871         writeStatsLocked(true);
14872         writeHistoryLocked(true);
14873     }
14874 
writeStatsLocked(boolean sync)14875     void writeStatsLocked(boolean sync) {
14876         if (mStatsFile == null) {
14877             Slog.w(TAG,
14878                     "writeStatsLocked: no file associated with this instance");
14879             return;
14880         }
14881 
14882         if (mShuttingDown) {
14883             return;
14884         }
14885 
14886         final Parcel p = Parcel.obtain();
14887         final long start = SystemClock.uptimeMillis();
14888         writeSummaryToParcel(p, false/*history is in separate file*/);
14889         if (DEBUG) {
14890             Slog.d(TAG, "writeSummaryToParcel duration ms:"
14891                     + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
14892         }
14893         mLastWriteTimeMs = mClocks.elapsedRealtime();
14894         writeParcelToFileLocked(p, mStatsFile, sync);
14895     }
14896 
writeHistoryLocked(boolean sync)14897     void writeHistoryLocked(boolean sync) {
14898         if (mBatteryStatsHistory.getActiveFile() == null) {
14899             Slog.w(TAG,
14900                     "writeHistoryLocked: no history file associated with this instance");
14901             return;
14902         }
14903 
14904         if (mShuttingDown) {
14905             return;
14906         }
14907 
14908         Parcel p = Parcel.obtain();
14909         final long start = SystemClock.uptimeMillis();
14910         writeHistoryBuffer(p, true);
14911         if (DEBUG) {
14912             Slog.d(TAG, "writeHistoryBuffer duration ms:"
14913                     + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
14914         }
14915         writeParcelToFileLocked(p, mBatteryStatsHistory.getActiveFile(), sync);
14916     }
14917 
writeParcelToFileLocked(Parcel p, AtomicFile file, boolean sync)14918     void writeParcelToFileLocked(Parcel p, AtomicFile file, boolean sync) {
14919         if (sync) {
14920             commitPendingDataToDisk(p, file);
14921         } else {
14922             BackgroundThread.getHandler().post(new Runnable() {
14923                 @Override public void run() {
14924                     commitPendingDataToDisk(p, file);
14925                 }
14926             });
14927         }
14928     }
14929 
commitPendingDataToDisk(Parcel p, AtomicFile file)14930     private void commitPendingDataToDisk(Parcel p, AtomicFile file) {
14931         mWriteLock.lock();
14932         FileOutputStream fos = null;
14933         try {
14934             final long startTimeMs = SystemClock.uptimeMillis();
14935             fos = file.startWrite();
14936             fos.write(p.marshall());
14937             fos.flush();
14938             file.finishWrite(fos);
14939             if (DEBUG) {
14940                 Slog.d(TAG, "commitPendingDataToDisk file:" + file.getBaseFile().getPath()
14941                         + " duration ms:" + (SystemClock.uptimeMillis() - startTimeMs)
14942                         + " bytes:" + p.dataSize());
14943             }
14944             com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
14945                     "batterystats", SystemClock.uptimeMillis() - startTimeMs);
14946         } catch (IOException e) {
14947             Slog.w(TAG, "Error writing battery statistics", e);
14948             file.failWrite(fos);
14949         } finally {
14950             p.recycle();
14951             mWriteLock.unlock();
14952         }
14953     }
14954 
14955     @UnsupportedAppUsage
readLocked()14956     public void readLocked() {
14957         if (mDailyFile != null) {
14958             readDailyStatsLocked();
14959         }
14960 
14961         if (mStatsFile == null) {
14962             Slog.w(TAG, "readLocked: no file associated with this instance");
14963             return;
14964         }
14965 
14966         final AtomicFile activeHistoryFile = mBatteryStatsHistory.getActiveFile();
14967         if (activeHistoryFile == null) {
14968             Slog.w(TAG,
14969                     "readLocked: no history file associated with this instance");
14970             return;
14971         }
14972 
14973         mUidStats.clear();
14974 
14975         Parcel stats = Parcel.obtain();
14976         try {
14977             final long start = SystemClock.uptimeMillis();
14978             if (mStatsFile.exists()) {
14979                 byte[] raw = mStatsFile.readFully();
14980                 stats.unmarshall(raw, 0, raw.length);
14981                 stats.setDataPosition(0);
14982                 readSummaryFromParcel(stats);
14983                 if (DEBUG) {
14984                     Slog.d(TAG, "readLocked stats file:" + mStatsFile.getBaseFile().getPath()
14985                             + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
14986                             - start));
14987                 }
14988             }
14989         } catch (Exception e) {
14990             Slog.e(TAG, "Error reading battery statistics", e);
14991             resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
14992                     RESET_REASON_CORRUPT_FILE);
14993         } finally {
14994             stats.recycle();
14995         }
14996 
14997         Parcel history = Parcel.obtain();
14998         try {
14999             final long start = SystemClock.uptimeMillis();
15000             if (activeHistoryFile.exists()) {
15001                 byte[] raw = activeHistoryFile.readFully();
15002                 if (raw.length > 0) {
15003                     history.unmarshall(raw, 0, raw.length);
15004                     history.setDataPosition(0);
15005                     readHistoryBuffer(history);
15006                 }
15007                 if (DEBUG) {
15008                     Slog.d(TAG, "readLocked history file::"
15009                             + activeHistoryFile.getBaseFile().getPath()
15010                             + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
15011                             - start));
15012                 }
15013             }
15014         } catch (Exception e) {
15015             Slog.e(TAG, "Error reading battery history", e);
15016             clearHistoryLocked();
15017             mBatteryStatsHistory.resetAllFiles();
15018         } finally {
15019             history.recycle();
15020         }
15021 
15022         mEndPlatformVersion = Build.ID;
15023 
15024         if (mHistoryBuffer.dataPosition() > 0
15025                 || mBatteryStatsHistory.getFilesNumbers().size() > 1) {
15026             mRecordingHistory = true;
15027             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
15028             final long uptimeMs = mClocks.uptimeMillis();
15029             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_START, mHistoryCur);
15030             startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
15031         }
15032 
15033         recordDailyStatsIfNeededLocked(false, mClocks.currentTimeMillis());
15034     }
15035 
describeContents()15036     public int describeContents() {
15037         return 0;
15038     }
15039 
readHistoryBuffer(Parcel in)15040     void  readHistoryBuffer(Parcel in) throws ParcelFormatException {
15041         final int version = in.readInt();
15042         if (version != VERSION) {
15043             Slog.w("BatteryStats", "readHistoryBuffer: version got " + version
15044                     + ", expected " + VERSION + "; erasing old stats");
15045             return;
15046         }
15047 
15048         final long historyBaseTime = in.readLong();
15049 
15050         mHistoryBuffer.setDataSize(0);
15051         mHistoryBuffer.setDataPosition(0);
15052 
15053         int bufSize = in.readInt();
15054         int curPos = in.dataPosition();
15055         if (bufSize >= (mConstants.MAX_HISTORY_BUFFER*100)) {
15056             throw new ParcelFormatException("File corrupt: history data buffer too large " +
15057                     bufSize);
15058         } else if ((bufSize&~3) != bufSize) {
15059             throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
15060                     bufSize);
15061         } else {
15062             if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
15063                     + " bytes at " + curPos);
15064             mHistoryBuffer.appendFrom(in, curPos, bufSize);
15065             in.setDataPosition(curPos + bufSize);
15066         }
15067 
15068         if (DEBUG_HISTORY) {
15069             StringBuilder sb = new StringBuilder(128);
15070             sb.append("****************** OLD mHistoryBaseTimeMs: ");
15071             TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
15072             Slog.i(TAG, sb.toString());
15073         }
15074         mHistoryBaseTimeMs = historyBaseTime;
15075         if (DEBUG_HISTORY) {
15076             StringBuilder sb = new StringBuilder(128);
15077             sb.append("****************** NEW mHistoryBaseTimeMs: ");
15078             TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
15079             Slog.i(TAG, sb.toString());
15080         }
15081 
15082         // We are just arbitrarily going to insert 1 minute from the sample of
15083         // the last run until samples in this run.
15084         if (mHistoryBaseTimeMs > 0) {
15085             long oldnow = mClocks.elapsedRealtime();
15086             mHistoryBaseTimeMs = mHistoryBaseTimeMs - oldnow + 1;
15087             if (DEBUG_HISTORY) {
15088                 StringBuilder sb = new StringBuilder(128);
15089                 sb.append("****************** ADJUSTED mHistoryBaseTimeMs: ");
15090                 TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
15091                 Slog.i(TAG, sb.toString());
15092             }
15093         }
15094     }
15095 
writeHistoryBuffer(Parcel out, boolean inclData)15096     void writeHistoryBuffer(Parcel out, boolean inclData) {
15097         if (DEBUG_HISTORY) {
15098             StringBuilder sb = new StringBuilder(128);
15099             sb.append("****************** WRITING mHistoryBaseTimeMs: ");
15100             TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
15101             sb.append(" mLastHistoryElapsedRealtimeMs: ");
15102             TimeUtils.formatDuration(mLastHistoryElapsedRealtimeMs, sb);
15103             Slog.i(TAG, sb.toString());
15104         }
15105         out.writeInt(VERSION);
15106         out.writeLong(mHistoryBaseTimeMs + mLastHistoryElapsedRealtimeMs);
15107         if (!inclData) {
15108             out.writeInt(0);
15109             out.writeInt(0);
15110             return;
15111         }
15112 
15113         out.writeInt(mHistoryBuffer.dataSize());
15114         if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
15115                 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
15116         out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
15117     }
15118 
readSummaryFromParcel(Parcel in)15119     public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
15120         final int version = in.readInt();
15121         if (version != VERSION) {
15122             Slog.w("BatteryStats", "readFromParcel: version got " + version
15123                 + ", expected " + VERSION + "; erasing old stats");
15124             return;
15125         }
15126 
15127         boolean inclHistory = in.readBoolean();
15128         if (inclHistory) {
15129             readHistoryBuffer(in);
15130             mBatteryStatsHistory.readFromParcel(in);
15131         }
15132 
15133         mHistoryTagPool.clear();
15134         mNextHistoryTagIdx = 0;
15135         mNumHistoryTagChars = 0;
15136 
15137         int numTags = in.readInt();
15138         for (int i=0; i<numTags; i++) {
15139             int idx = in.readInt();
15140             String str = in.readString();
15141             if (str == null) {
15142                 throw new ParcelFormatException("null history tag string");
15143             }
15144             int uid = in.readInt();
15145             HistoryTag tag = new HistoryTag();
15146             tag.string = str;
15147             tag.uid = uid;
15148             tag.poolIdx = idx;
15149             mHistoryTagPool.put(tag, idx);
15150             if (idx >= mNextHistoryTagIdx) {
15151                 mNextHistoryTagIdx = idx+1;
15152             }
15153             mNumHistoryTagChars += tag.string.length() + 1;
15154         }
15155 
15156         mStartCount = in.readInt();
15157         mUptimeUs = in.readLong();
15158         mRealtimeUs = in.readLong();
15159         mStartClockTimeMs = in.readLong();
15160         mStartPlatformVersion = in.readString();
15161         mEndPlatformVersion = in.readString();
15162         mOnBatteryTimeBase.readSummaryFromParcel(in);
15163         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
15164         mDischargeUnplugLevel = in.readInt();
15165         mDischargePlugLevel = in.readInt();
15166         mDischargeCurrentLevel = in.readInt();
15167         mCurrentBatteryLevel = in.readInt();
15168         mEstimatedBatteryCapacityMah = in.readInt();
15169         mLastLearnedBatteryCapacityUah = in.readInt();
15170         mMinLearnedBatteryCapacityUah = in.readInt();
15171         mMaxLearnedBatteryCapacityUah = in.readInt();
15172         mLowDischargeAmountSinceCharge = in.readInt();
15173         mHighDischargeAmountSinceCharge = in.readInt();
15174         mDischargeAmountScreenOnSinceCharge = in.readInt();
15175         mDischargeAmountScreenOffSinceCharge = in.readInt();
15176         mDischargeAmountScreenDozeSinceCharge = in.readInt();
15177         mDischargeStepTracker.readFromParcel(in);
15178         mChargeStepTracker.readFromParcel(in);
15179         mDailyDischargeStepTracker.readFromParcel(in);
15180         mDailyChargeStepTracker.readFromParcel(in);
15181         mDischargeCounter.readSummaryFromParcelLocked(in);
15182         mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
15183         mDischargeScreenDozeCounter.readSummaryFromParcelLocked(in);
15184         mDischargeLightDozeCounter.readSummaryFromParcelLocked(in);
15185         mDischargeDeepDozeCounter.readSummaryFromParcelLocked(in);
15186         int NPKG = in.readInt();
15187         if (NPKG > 0) {
15188             mDailyPackageChanges = new ArrayList<>(NPKG);
15189             while (NPKG > 0) {
15190                 NPKG--;
15191                 PackageChange pc = new PackageChange();
15192                 pc.mPackageName = in.readString();
15193                 pc.mUpdate = in.readInt() != 0;
15194                 pc.mVersionCode = in.readLong();
15195                 mDailyPackageChanges.add(pc);
15196             }
15197         } else {
15198             mDailyPackageChanges = null;
15199         }
15200         mDailyStartTimeMs = in.readLong();
15201         mNextMinDailyDeadlineMs = in.readLong();
15202         mNextMaxDailyDeadlineMs = in.readLong();
15203         mBatteryTimeToFullSeconds = in.readLong();
15204 
15205         /**
15206          * WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled
15207          *          later when {@link #initMeasuredEnergyStatsLocked} is called.
15208          */
15209         mGlobalMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(in);
15210 
15211         mStartCount++;
15212 
15213         mScreenState = Display.STATE_UNKNOWN;
15214         mScreenOnTimer.readSummaryFromParcelLocked(in);
15215         mScreenDozeTimer.readSummaryFromParcelLocked(in);
15216         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
15217             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
15218         }
15219         mInteractive = false;
15220         mInteractiveTimer.readSummaryFromParcelLocked(in);
15221         mPhoneOn = false;
15222         mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
15223         mLongestLightIdleTimeMs = in.readLong();
15224         mLongestFullIdleTimeMs = in.readLong();
15225         mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
15226         mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
15227         mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
15228         mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
15229         mPhoneOnTimer.readSummaryFromParcelLocked(in);
15230         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
15231             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
15232         }
15233         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
15234         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
15235             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
15236         }
15237         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
15238             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
15239             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
15240         }
15241         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
15242         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
15243         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
15244         mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
15245         mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
15246         mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
15247         mWifiMulticastWakelockTimer.readSummaryFromParcelLocked(in);
15248         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
15249         mWifiOn = false;
15250         mWifiOnTimer.readSummaryFromParcelLocked(in);
15251         mGlobalWifiRunning = false;
15252         mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
15253         for (int i=0; i<NUM_WIFI_STATES; i++) {
15254             mWifiStateTimer[i].readSummaryFromParcelLocked(in);
15255         }
15256         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
15257             mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
15258         }
15259         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
15260             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
15261         }
15262         mWifiActiveTimer.readSummaryFromParcelLocked(in);
15263         mWifiActivity.readSummaryFromParcel(in);
15264         for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
15265             mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
15266         }
15267         mBluetoothActivity.readSummaryFromParcel(in);
15268         mModemActivity.readSummaryFromParcel(in);
15269         mHasWifiReporting = in.readInt() != 0;
15270         mHasBluetoothReporting = in.readInt() != 0;
15271         mHasModemReporting = in.readInt() != 0;
15272 
15273         mNumConnectivityChange = in.readInt();
15274         mFlashlightOnNesting = 0;
15275         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
15276         mCameraOnNesting = 0;
15277         mCameraOnTimer.readSummaryFromParcelLocked(in);
15278         mBluetoothScanNesting = 0;
15279         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
15280 
15281         int NRPMS = in.readInt();
15282         if (NRPMS > 10000) {
15283             throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS);
15284         }
15285         for (int irpm = 0; irpm < NRPMS; irpm++) {
15286             if (in.readInt() != 0) {
15287                 String rpmName = in.readString();
15288                 getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
15289             }
15290         }
15291         int NSORPMS = in.readInt();
15292         if (NSORPMS > 10000) {
15293             throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS);
15294         }
15295         for (int irpm = 0; irpm < NSORPMS; irpm++) {
15296             if (in.readInt() != 0) {
15297                 String rpmName = in.readString();
15298                 getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
15299             }
15300         }
15301 
15302         int NKW = in.readInt();
15303         if (NKW > 10000) {
15304             throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
15305         }
15306         for (int ikw = 0; ikw < NKW; ikw++) {
15307             if (in.readInt() != 0) {
15308                 String kwltName = in.readString();
15309                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
15310             }
15311         }
15312 
15313         int NWR = in.readInt();
15314         if (NWR > 10000) {
15315             throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
15316         }
15317         for (int iwr = 0; iwr < NWR; iwr++) {
15318             if (in.readInt() != 0) {
15319                 String reasonName = in.readString();
15320                 getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
15321             }
15322         }
15323 
15324         int NMS = in.readInt();
15325         for (int ims = 0; ims < NMS; ims++) {
15326             if (in.readInt() != 0) {
15327                 long kmstName = in.readLong();
15328                 getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
15329             }
15330         }
15331 
15332         final int NU = in.readInt();
15333         if (NU > 10000) {
15334             throw new ParcelFormatException("File corrupt: too many uids " + NU);
15335         }
15336         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
15337         final long uptimeMs = mClocks.uptimeMillis();
15338         for (int iu = 0; iu < NU; iu++) {
15339             int uid = in.readInt();
15340             Uid u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
15341             mUidStats.put(uid, u);
15342 
15343             u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
15344             u.mOnBatteryScreenOffBackgroundTimeBase.readSummaryFromParcel(in);
15345 
15346             u.mWifiRunning = false;
15347             if (in.readInt() != 0) {
15348                 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
15349             }
15350             u.mFullWifiLockOut = false;
15351             if (in.readInt() != 0) {
15352                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
15353             }
15354             u.mWifiScanStarted = false;
15355             if (in.readInt() != 0) {
15356                 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
15357             }
15358             u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
15359             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
15360                 if (in.readInt() != 0) {
15361                     u.makeWifiBatchedScanBin(i, null);
15362                     u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
15363                 }
15364             }
15365             u.mWifiMulticastWakelockCount = 0;
15366             if (in.readInt() != 0) {
15367                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
15368             }
15369             if (in.readInt() != 0) {
15370                 u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
15371             }
15372             if (in.readInt() != 0) {
15373                 u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
15374             }
15375             if (in.readInt() != 0) {
15376                 u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
15377             }
15378             if (in.readInt() != 0) {
15379                 u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
15380             }
15381             if (in.readInt() != 0) {
15382                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
15383             }
15384             if (in.readInt() != 0) {
15385                 u.createForegroundServiceTimerLocked().readSummaryFromParcelLocked(in);
15386             }
15387             if (in.readInt() != 0) {
15388                 u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
15389             }
15390             if (in.readInt() != 0) {
15391                 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
15392             }
15393             if (in.readInt() != 0) {
15394                 u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in);
15395             }
15396             if (in.readInt() != 0) {
15397                 u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
15398             }
15399             if (in.readInt() != 0) {
15400                 u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in);
15401             }
15402             u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
15403             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
15404                 if (in.readInt() != 0) {
15405                     u.makeProcessState(i, null);
15406                     u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
15407                 }
15408             }
15409             if (in.readInt() != 0) {
15410                 u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
15411             }
15412 
15413             if (in.readInt() != 0) {
15414                 if (u.mUserActivityCounters == null) {
15415                     u.initUserActivityLocked();
15416                 }
15417                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
15418                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
15419                 }
15420             }
15421 
15422             if (in.readInt() != 0) {
15423                 if (u.mNetworkByteActivityCounters == null) {
15424                     u.initNetworkActivityLocked();
15425                 }
15426                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
15427                     u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
15428                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
15429                 }
15430                 u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
15431                 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
15432             }
15433 
15434             u.mUserCpuTime.readSummaryFromParcelLocked(in);
15435             u.mSystemCpuTime.readSummaryFromParcelLocked(in);
15436 
15437             if (in.readInt() != 0) {
15438                 final int numClusters = in.readInt();
15439                 if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
15440                     throw new ParcelFormatException("Incompatible cpu cluster arrangement");
15441                 }
15442                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
15443                 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
15444                 for (int cluster = 0; cluster < numClusters; cluster++) {
15445                     if (in.readInt() != 0) {
15446                         final int NSB = in.readInt();
15447                         if (mPowerProfile != null &&
15448                                 mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
15449                             throw new ParcelFormatException("File corrupt: too many speed bins " +
15450                                     NSB);
15451                         }
15452 
15453                         u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[NSB];
15454                         for (int speed = 0; speed < NSB; speed++) {
15455                             if (in.readInt() != 0) {
15456                                 u.mCpuClusterSpeedTimesUs[cluster][speed] = new LongSamplingCounter(
15457                                         mOnBatteryTimeBase);
15458                                 u.mCpuClusterSpeedTimesUs[cluster][speed].readSummaryFromParcelLocked(in);
15459                             }
15460                         }
15461                     } else {
15462                         u.mCpuClusterSpeedTimesUs[cluster] = null;
15463                     }
15464                 }
15465             } else {
15466                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
15467                 u.mCpuClusterSpeedTimesUs = null;
15468             }
15469 
15470             detachIfNotNull(u.mCpuFreqTimeMs);
15471             u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
15472                     in, mOnBatteryTimeBase);
15473             detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
15474             u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
15475                     in, mOnBatteryScreenOffTimeBase);
15476 
15477             u.mCpuActiveTimeMs.readSummaryFromParcelLocked(in);
15478             u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
15479 
15480             int length = in.readInt();
15481             if (length == Uid.NUM_PROCESS_STATE) {
15482                 detachIfNotNull(u.mProcStateTimeMs);
15483                 u.mProcStateTimeMs = new LongSamplingCounterArray[length];
15484                 for (int procState = 0; procState < length; ++procState) {
15485                     u.mProcStateTimeMs[procState]
15486                             = LongSamplingCounterArray.readSummaryFromParcelLocked(
15487                                     in, mOnBatteryTimeBase);
15488                 }
15489             } else {
15490                 detachIfNotNull(u.mProcStateTimeMs);
15491                 u.mProcStateTimeMs = null;
15492             }
15493             length = in.readInt();
15494             if (length == Uid.NUM_PROCESS_STATE) {
15495                 detachIfNotNull(u.mProcStateScreenOffTimeMs);
15496                 u.mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
15497                 for (int procState = 0; procState < length; ++procState) {
15498                     u.mProcStateScreenOffTimeMs[procState]
15499                             = LongSamplingCounterArray.readSummaryFromParcelLocked(
15500                                     in, mOnBatteryScreenOffTimeBase);
15501                 }
15502             } else {
15503                 detachIfNotNull(u.mProcStateScreenOffTimeMs);
15504                 u.mProcStateScreenOffTimeMs = null;
15505             }
15506 
15507             if (in.readInt() != 0) {
15508                 detachIfNotNull(u.mMobileRadioApWakeupCount);
15509                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
15510                 u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
15511             } else {
15512                 detachIfNotNull(u.mMobileRadioApWakeupCount);
15513                 u.mMobileRadioApWakeupCount = null;
15514             }
15515 
15516             if (in.readInt() != 0) {
15517                 detachIfNotNull(u.mWifiRadioApWakeupCount);
15518                 u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
15519                 u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
15520             } else {
15521                 detachIfNotNull(u.mWifiRadioApWakeupCount);
15522                 u.mWifiRadioApWakeupCount = null;
15523             }
15524 
15525             u.mUidMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(in,
15526                     /* template */ mGlobalMeasuredEnergyStats);
15527 
15528             int NW = in.readInt();
15529             if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
15530                 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
15531             }
15532             for (int iw = 0; iw < NW; iw++) {
15533                 String wlName = in.readString();
15534                 u.readWakeSummaryFromParcelLocked(wlName, in);
15535             }
15536 
15537             int NS = in.readInt();
15538             if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
15539                 throw new ParcelFormatException("File corrupt: too many syncs " + NS);
15540             }
15541             for (int is = 0; is < NS; is++) {
15542                 String name = in.readString();
15543                 u.readSyncSummaryFromParcelLocked(name, in);
15544             }
15545 
15546             int NJ = in.readInt();
15547             if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
15548                 throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
15549             }
15550             for (int ij = 0; ij < NJ; ij++) {
15551                 String name = in.readString();
15552                 u.readJobSummaryFromParcelLocked(name, in);
15553             }
15554 
15555             u.readJobCompletionsFromParcelLocked(in);
15556 
15557             u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in);
15558             u.mJobsDeferredCount.readSummaryFromParcelLocked(in);
15559             u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in);
15560             detachIfNotNull(u.mJobsFreshnessBuckets);
15561             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
15562                 if (in.readInt() != 0) {
15563                     u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase);
15564                     u.mJobsFreshnessBuckets[i].readSummaryFromParcelLocked(in);
15565                 }
15566             }
15567 
15568             int NP = in.readInt();
15569             if (NP > 1000) {
15570                 throw new ParcelFormatException("File corrupt: too many sensors " + NP);
15571             }
15572             for (int is = 0; is < NP; is++) {
15573                 int seNumber = in.readInt();
15574                 if (in.readInt() != 0) {
15575                     u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
15576                 }
15577             }
15578 
15579             NP = in.readInt();
15580             if (NP > 1000) {
15581                 throw new ParcelFormatException("File corrupt: too many processes " + NP);
15582             }
15583             for (int ip = 0; ip < NP; ip++) {
15584                 String procName = in.readString();
15585                 Uid.Proc p = u.getProcessStatsLocked(procName);
15586                 p.mUserTimeMs = in.readLong();
15587                 p.mSystemTimeMs = in.readLong();
15588                 p.mForegroundTimeMs = in.readLong();
15589                 p.mStarts = in.readInt();
15590                 p.mNumCrashes = in.readInt();
15591                 p.mNumAnrs = in.readInt();
15592                 p.readExcessivePowerFromParcelLocked(in);
15593             }
15594 
15595             NP = in.readInt();
15596             if (NP > 10000) {
15597                 throw new ParcelFormatException("File corrupt: too many packages " + NP);
15598             }
15599             for (int ip = 0; ip < NP; ip++) {
15600                 String pkgName = in.readString();
15601                 detachIfNotNull(u.mPackageStats.get(pkgName));
15602                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
15603                 final int NWA = in.readInt();
15604                 if (NWA > 10000) {
15605                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
15606                 }
15607                 p.mWakeupAlarms.clear();
15608                 for (int iwa = 0; iwa < NWA; iwa++) {
15609                     String tag = in.readString();
15610                     Counter c = new Counter(mOnBatteryScreenOffTimeBase);
15611                     c.readSummaryFromParcelLocked(in);
15612                     p.mWakeupAlarms.put(tag, c);
15613                 }
15614                 NS = in.readInt();
15615                 if (NS > 10000) {
15616                     throw new ParcelFormatException("File corrupt: too many services " + NS);
15617                 }
15618                 for (int is = 0; is < NS; is++) {
15619                     String servName = in.readString();
15620                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
15621                     s.mStartTimeMs = in.readLong();
15622                     s.mStarts = in.readInt();
15623                     s.mLaunches = in.readInt();
15624                 }
15625             }
15626         }
15627 
15628         mBinderThreadCpuTimesUs =
15629                 LongSamplingCounterArray.readSummaryFromParcelLocked(in, mOnBatteryTimeBase);
15630     }
15631 
15632     /**
15633      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
15634      * disk.  This format does not allow a lossless round-trip.
15635      *
15636      * @param out the Parcel to be written to.
15637      */
writeSummaryToParcel(Parcel out, boolean inclHistory)15638     public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
15639         pullPendingStateUpdatesLocked();
15640 
15641         // Pull the clock time.  This may update the time and make a new history entry
15642         // if we had originally pulled a time before the RTC was set.
15643         getStartClockTime();
15644 
15645         final long NOW_SYS = mClocks.uptimeMillis() * 1000;
15646         final long NOWREAL_SYS = mClocks.elapsedRealtime() * 1000;
15647 
15648         out.writeInt(VERSION);
15649 
15650         out.writeBoolean(inclHistory);
15651         if (inclHistory) {
15652             writeHistoryBuffer(out, true);
15653             mBatteryStatsHistory.writeToParcel(out);
15654         }
15655 
15656         out.writeInt(mHistoryTagPool.size());
15657         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
15658             HistoryTag tag = ent.getKey();
15659             out.writeInt(ent.getValue());
15660             out.writeString(tag.string);
15661             out.writeInt(tag.uid);
15662         }
15663 
15664         out.writeInt(mStartCount);
15665         out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
15666         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
15667         out.writeLong(mStartClockTimeMs);
15668         out.writeString(mStartPlatformVersion);
15669         out.writeString(mEndPlatformVersion);
15670         mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
15671         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
15672         out.writeInt(mDischargeUnplugLevel);
15673         out.writeInt(mDischargePlugLevel);
15674         out.writeInt(mDischargeCurrentLevel);
15675         out.writeInt(mCurrentBatteryLevel);
15676         out.writeInt(mEstimatedBatteryCapacityMah);
15677         out.writeInt(mLastLearnedBatteryCapacityUah);
15678         out.writeInt(mMinLearnedBatteryCapacityUah);
15679         out.writeInt(mMaxLearnedBatteryCapacityUah);
15680         out.writeInt(getLowDischargeAmountSinceCharge());
15681         out.writeInt(getHighDischargeAmountSinceCharge());
15682         out.writeInt(getDischargeAmountScreenOnSinceCharge());
15683         out.writeInt(getDischargeAmountScreenOffSinceCharge());
15684         out.writeInt(getDischargeAmountScreenDozeSinceCharge());
15685         mDischargeStepTracker.writeToParcel(out);
15686         mChargeStepTracker.writeToParcel(out);
15687         mDailyDischargeStepTracker.writeToParcel(out);
15688         mDailyChargeStepTracker.writeToParcel(out);
15689         mDischargeCounter.writeSummaryFromParcelLocked(out);
15690         mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
15691         mDischargeScreenDozeCounter.writeSummaryFromParcelLocked(out);
15692         mDischargeLightDozeCounter.writeSummaryFromParcelLocked(out);
15693         mDischargeDeepDozeCounter.writeSummaryFromParcelLocked(out);
15694         if (mDailyPackageChanges != null) {
15695             final int NPKG = mDailyPackageChanges.size();
15696             out.writeInt(NPKG);
15697             for (int i=0; i<NPKG; i++) {
15698                 PackageChange pc = mDailyPackageChanges.get(i);
15699                 out.writeString(pc.mPackageName);
15700                 out.writeInt(pc.mUpdate ? 1 : 0);
15701                 out.writeLong(pc.mVersionCode);
15702             }
15703         } else {
15704             out.writeInt(0);
15705         }
15706         out.writeLong(mDailyStartTimeMs);
15707         out.writeLong(mNextMinDailyDeadlineMs);
15708         out.writeLong(mNextMaxDailyDeadlineMs);
15709         out.writeLong(mBatteryTimeToFullSeconds);
15710 
15711         MeasuredEnergyStats.writeSummaryToParcel(mGlobalMeasuredEnergyStats, out, false, false);
15712 
15713         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15714         mScreenDozeTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15715         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
15716             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15717         }
15718         mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15719         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15720         out.writeLong(mLongestLightIdleTimeMs);
15721         out.writeLong(mLongestFullIdleTimeMs);
15722         mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15723         mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15724         mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15725         mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15726         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15727         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
15728             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15729         }
15730         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15731         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
15732             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15733         }
15734         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
15735             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
15736             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
15737         }
15738         mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15739         mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15740         mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
15741         mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
15742         mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
15743         mWifiMulticastWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15744         mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15745         mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15746         for (int i=0; i<NUM_WIFI_STATES; i++) {
15747             mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15748         }
15749         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
15750             mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15751         }
15752         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
15753             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15754         }
15755         mWifiActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15756         mWifiActivity.writeSummaryToParcel(out);
15757         for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
15758             mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15759         }
15760         mBluetoothActivity.writeSummaryToParcel(out);
15761         mModemActivity.writeSummaryToParcel(out);
15762         out.writeInt(mHasWifiReporting ? 1 : 0);
15763         out.writeInt(mHasBluetoothReporting ? 1 : 0);
15764         out.writeInt(mHasModemReporting ? 1 : 0);
15765 
15766         out.writeInt(mNumConnectivityChange);
15767         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15768         mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15769         mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15770 
15771         out.writeInt(mRpmStats.size());
15772         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
15773             Timer rpmt = ent.getValue();
15774             if (rpmt != null) {
15775                 out.writeInt(1);
15776                 out.writeString(ent.getKey());
15777                 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15778             } else {
15779                 out.writeInt(0);
15780             }
15781         }
15782         out.writeInt(mScreenOffRpmStats.size());
15783         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
15784             Timer rpmt = ent.getValue();
15785             if (rpmt != null) {
15786                 out.writeInt(1);
15787                 out.writeString(ent.getKey());
15788                 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15789             } else {
15790                 out.writeInt(0);
15791             }
15792         }
15793 
15794         out.writeInt(mKernelWakelockStats.size());
15795         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
15796             Timer kwlt = ent.getValue();
15797             if (kwlt != null) {
15798                 out.writeInt(1);
15799                 out.writeString(ent.getKey());
15800                 kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15801             } else {
15802                 out.writeInt(0);
15803             }
15804         }
15805 
15806         out.writeInt(mWakeupReasonStats.size());
15807         for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
15808             SamplingTimer timer = ent.getValue();
15809             if (timer != null) {
15810                 out.writeInt(1);
15811                 out.writeString(ent.getKey());
15812                 timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15813             } else {
15814                 out.writeInt(0);
15815             }
15816         }
15817 
15818         out.writeInt(mKernelMemoryStats.size());
15819         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
15820             Timer kmt = mKernelMemoryStats.valueAt(i);
15821             if (kmt != null) {
15822                 out.writeInt(1);
15823                 out.writeLong(mKernelMemoryStats.keyAt(i));
15824                 kmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15825             } else {
15826                 out.writeInt(0);
15827             }
15828         }
15829 
15830         final int NU = mUidStats.size();
15831         out.writeInt(NU);
15832         for (int iu = 0; iu < NU; iu++) {
15833             out.writeInt(mUidStats.keyAt(iu));
15834             Uid u = mUidStats.valueAt(iu);
15835 
15836             u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
15837             u.mOnBatteryScreenOffBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
15838 
15839             if (u.mWifiRunningTimer != null) {
15840                 out.writeInt(1);
15841                 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15842             } else {
15843                 out.writeInt(0);
15844             }
15845             if (u.mFullWifiLockTimer != null) {
15846                 out.writeInt(1);
15847                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15848             } else {
15849                 out.writeInt(0);
15850             }
15851             if (u.mWifiScanTimer != null) {
15852                 out.writeInt(1);
15853                 u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15854             } else {
15855                 out.writeInt(0);
15856             }
15857             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
15858                 if (u.mWifiBatchedScanTimer[i] != null) {
15859                     out.writeInt(1);
15860                     u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15861                 } else {
15862                     out.writeInt(0);
15863                 }
15864             }
15865             if (u.mWifiMulticastTimer != null) {
15866                 out.writeInt(1);
15867                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15868             } else {
15869                 out.writeInt(0);
15870             }
15871             if (u.mAudioTurnedOnTimer != null) {
15872                 out.writeInt(1);
15873                 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15874             } else {
15875                 out.writeInt(0);
15876             }
15877             if (u.mVideoTurnedOnTimer != null) {
15878                 out.writeInt(1);
15879                 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15880             } else {
15881                 out.writeInt(0);
15882             }
15883             if (u.mFlashlightTurnedOnTimer != null) {
15884                 out.writeInt(1);
15885                 u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15886             } else {
15887                 out.writeInt(0);
15888             }
15889             if (u.mCameraTurnedOnTimer != null) {
15890                 out.writeInt(1);
15891                 u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15892             } else {
15893                 out.writeInt(0);
15894             }
15895             if (u.mForegroundActivityTimer != null) {
15896                 out.writeInt(1);
15897                 u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15898             } else {
15899                 out.writeInt(0);
15900             }
15901             if (u.mForegroundServiceTimer != null) {
15902                 out.writeInt(1);
15903                 u.mForegroundServiceTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15904             } else {
15905                 out.writeInt(0);
15906             }
15907             if (u.mAggregatedPartialWakelockTimer != null) {
15908                 out.writeInt(1);
15909                 u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15910             } else {
15911                 out.writeInt(0);
15912             }
15913             if (u.mBluetoothScanTimer != null) {
15914                 out.writeInt(1);
15915                 u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15916             } else {
15917                 out.writeInt(0);
15918             }
15919             if (u.mBluetoothUnoptimizedScanTimer != null) {
15920                 out.writeInt(1);
15921                 u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15922             } else {
15923                 out.writeInt(0);
15924             }
15925             if (u.mBluetoothScanResultCounter != null) {
15926                 out.writeInt(1);
15927                 u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
15928             } else {
15929                 out.writeInt(0);
15930             }
15931             if (u.mBluetoothScanResultBgCounter != null) {
15932                 out.writeInt(1);
15933                 u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out);
15934             } else {
15935                 out.writeInt(0);
15936             }
15937             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
15938                 if (u.mProcessStateTimer[i] != null) {
15939                     out.writeInt(1);
15940                     u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15941                 } else {
15942                     out.writeInt(0);
15943                 }
15944             }
15945             if (u.mVibratorOnTimer != null) {
15946                 out.writeInt(1);
15947                 u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
15948             } else {
15949                 out.writeInt(0);
15950             }
15951 
15952             if (u.mUserActivityCounters == null) {
15953                 out.writeInt(0);
15954             } else {
15955                 out.writeInt(1);
15956                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
15957                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
15958                 }
15959             }
15960 
15961             if (u.mNetworkByteActivityCounters == null) {
15962                 out.writeInt(0);
15963             } else {
15964                 out.writeInt(1);
15965                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
15966                     u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
15967                     u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
15968                 }
15969                 u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
15970                 u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
15971             }
15972 
15973             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
15974             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
15975 
15976             if (u.mCpuClusterSpeedTimesUs != null) {
15977                 out.writeInt(1);
15978                 out.writeInt(u.mCpuClusterSpeedTimesUs.length);
15979                 for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeedTimesUs) {
15980                     if (cpuSpeeds != null) {
15981                         out.writeInt(1);
15982                         out.writeInt(cpuSpeeds.length);
15983                         for (LongSamplingCounter c : cpuSpeeds) {
15984                             if (c != null) {
15985                                 out.writeInt(1);
15986                                 c.writeSummaryFromParcelLocked(out);
15987                             } else {
15988                                 out.writeInt(0);
15989                             }
15990                         }
15991                     } else {
15992                         out.writeInt(0);
15993                     }
15994                 }
15995             } else {
15996                 out.writeInt(0);
15997             }
15998 
15999             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
16000             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
16001 
16002             u.mCpuActiveTimeMs.writeSummaryFromParcelLocked(out);
16003             u.mCpuClusterTimesMs.writeSummaryToParcelLocked(out);
16004 
16005             if (u.mProcStateTimeMs != null) {
16006                 out.writeInt(u.mProcStateTimeMs.length);
16007                 for (LongSamplingCounterArray counters : u.mProcStateTimeMs) {
16008                     LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
16009                 }
16010             } else {
16011                 out.writeInt(0);
16012             }
16013             if (u.mProcStateScreenOffTimeMs != null) {
16014                 out.writeInt(u.mProcStateScreenOffTimeMs.length);
16015                 for (LongSamplingCounterArray counters : u.mProcStateScreenOffTimeMs) {
16016                     LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
16017                 }
16018             } else {
16019                 out.writeInt(0);
16020             }
16021 
16022             if (u.mMobileRadioApWakeupCount != null) {
16023                 out.writeInt(1);
16024                 u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
16025             } else {
16026                 out.writeInt(0);
16027             }
16028 
16029             if (u.mWifiRadioApWakeupCount != null) {
16030                 out.writeInt(1);
16031                 u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
16032             } else {
16033                 out.writeInt(0);
16034             }
16035 
16036             MeasuredEnergyStats.writeSummaryToParcel(u.mUidMeasuredEnergyStats, out, true, true);
16037 
16038             final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
16039             int NW = wakeStats.size();
16040             out.writeInt(NW);
16041             for (int iw=0; iw<NW; iw++) {
16042                 out.writeString(wakeStats.keyAt(iw));
16043                 Uid.Wakelock wl = wakeStats.valueAt(iw);
16044                 if (wl.mTimerFull != null) {
16045                     out.writeInt(1);
16046                     wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16047                 } else {
16048                     out.writeInt(0);
16049                 }
16050                 if (wl.mTimerPartial != null) {
16051                     out.writeInt(1);
16052                     wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16053                 } else {
16054                     out.writeInt(0);
16055                 }
16056                 if (wl.mTimerWindow != null) {
16057                     out.writeInt(1);
16058                     wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16059                 } else {
16060                     out.writeInt(0);
16061                 }
16062                 if (wl.mTimerDraw != null) {
16063                     out.writeInt(1);
16064                     wl.mTimerDraw.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16065                 } else {
16066                     out.writeInt(0);
16067                 }
16068             }
16069 
16070             final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
16071             int NS = syncStats.size();
16072             out.writeInt(NS);
16073             for (int is=0; is<NS; is++) {
16074                 out.writeString(syncStats.keyAt(is));
16075                 syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16076             }
16077 
16078             final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
16079             int NJ = jobStats.size();
16080             out.writeInt(NJ);
16081             for (int ij=0; ij<NJ; ij++) {
16082                 out.writeString(jobStats.keyAt(ij));
16083                 jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16084             }
16085 
16086             u.writeJobCompletionsToParcelLocked(out);
16087 
16088             u.mJobsDeferredEventCount.writeSummaryFromParcelLocked(out);
16089             u.mJobsDeferredCount.writeSummaryFromParcelLocked(out);
16090             u.mJobsFreshnessTimeMs.writeSummaryFromParcelLocked(out);
16091             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
16092                 if (u.mJobsFreshnessBuckets[i] != null) {
16093                     out.writeInt(1);
16094                     u.mJobsFreshnessBuckets[i].writeSummaryFromParcelLocked(out);
16095                 } else {
16096                     out.writeInt(0);
16097                 }
16098             }
16099 
16100             int NSE = u.mSensorStats.size();
16101             out.writeInt(NSE);
16102             for (int ise=0; ise<NSE; ise++) {
16103                 out.writeInt(u.mSensorStats.keyAt(ise));
16104                 Uid.Sensor se = u.mSensorStats.valueAt(ise);
16105                 if (se.mTimer != null) {
16106                     out.writeInt(1);
16107                     se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
16108                 } else {
16109                     out.writeInt(0);
16110                 }
16111             }
16112 
16113             int NP = u.mProcessStats.size();
16114             out.writeInt(NP);
16115             for (int ip=0; ip<NP; ip++) {
16116                 out.writeString(u.mProcessStats.keyAt(ip));
16117                 Uid.Proc ps = u.mProcessStats.valueAt(ip);
16118                 out.writeLong(ps.mUserTimeMs);
16119                 out.writeLong(ps.mSystemTimeMs);
16120                 out.writeLong(ps.mForegroundTimeMs);
16121                 out.writeInt(ps.mStarts);
16122                 out.writeInt(ps.mNumCrashes);
16123                 out.writeInt(ps.mNumAnrs);
16124                 ps.writeExcessivePowerToParcelLocked(out);
16125             }
16126 
16127             NP = u.mPackageStats.size();
16128             out.writeInt(NP);
16129             if (NP > 0) {
16130                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
16131                     : u.mPackageStats.entrySet()) {
16132                     out.writeString(ent.getKey());
16133                     Uid.Pkg ps = ent.getValue();
16134                     final int NWA = ps.mWakeupAlarms.size();
16135                     out.writeInt(NWA);
16136                     for (int iwa=0; iwa<NWA; iwa++) {
16137                         out.writeString(ps.mWakeupAlarms.keyAt(iwa));
16138                         ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
16139                     }
16140                     NS = ps.mServiceStats.size();
16141                     out.writeInt(NS);
16142                     for (int is=0; is<NS; is++) {
16143                         out.writeString(ps.mServiceStats.keyAt(is));
16144                         BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
16145                         long time = ss.getStartTimeToNowLocked(
16146                                 mOnBatteryTimeBase.getUptime(NOW_SYS) / 1000);
16147                         out.writeLong(time);
16148                         out.writeInt(ss.mStarts);
16149                         out.writeInt(ss.mLaunches);
16150                     }
16151                 }
16152             }
16153         }
16154 
16155         LongSamplingCounterArray.writeSummaryToParcelLocked(out, mBinderThreadCpuTimesUs);
16156     }
16157 
readFromParcel(Parcel in)16158     public void readFromParcel(Parcel in) {
16159         readFromParcelLocked(in);
16160     }
16161 
readFromParcelLocked(Parcel in)16162     void readFromParcelLocked(Parcel in) {
16163         int magic = in.readInt();
16164         if (magic != MAGIC) {
16165             throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
16166         }
16167 
16168         readHistoryBuffer(in);
16169         mBatteryStatsHistory.readFromParcel(in);
16170 
16171         mStartCount = in.readInt();
16172         mStartClockTimeMs = in.readLong();
16173         mStartPlatformVersion = in.readString();
16174         mEndPlatformVersion = in.readString();
16175         mUptimeUs = in.readLong();
16176         mUptimeStartUs = in.readLong();
16177         mRealtimeUs = in.readLong();
16178         mRealtimeStartUs = in.readLong();
16179         mOnBattery = in.readInt() != 0;
16180         mEstimatedBatteryCapacityMah = in.readInt();
16181         mLastLearnedBatteryCapacityUah = in.readInt();
16182         mMinLearnedBatteryCapacityUah = in.readInt();
16183         mMaxLearnedBatteryCapacityUah = in.readInt();
16184         mOnBatteryInternal = false; // we are no longer really running.
16185         mOnBatteryTimeBase.readFromParcel(in);
16186         mOnBatteryScreenOffTimeBase.readFromParcel(in);
16187 
16188         mScreenState = Display.STATE_UNKNOWN;
16189         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
16190         mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
16191         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
16192             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
16193                     mOnBatteryTimeBase, in);
16194         }
16195         mInteractive = false;
16196         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase, in);
16197         mPhoneOn = false;
16198         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
16199                 mOnBatteryTimeBase, in);
16200         mLongestLightIdleTimeMs = in.readLong();
16201         mLongestFullIdleTimeMs = in.readLong();
16202         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null,
16203                 mOnBatteryTimeBase, in);
16204         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null,
16205                 mOnBatteryTimeBase, in);
16206         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null,
16207                 mOnBatteryTimeBase, in);
16208         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase, in);
16209         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase, in);
16210         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
16211             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i,
16212                     null, mOnBatteryTimeBase, in);
16213         }
16214         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
16215                 mOnBatteryTimeBase, in);
16216         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
16217             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i,
16218                     null, mOnBatteryTimeBase, in);
16219         }
16220         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
16221             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
16222             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
16223         }
16224         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
16225         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
16226                 mOnBatteryTimeBase, in);
16227         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
16228                 mOnBatteryTimeBase, in);
16229         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
16230         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
16231         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
16232         mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null, -4, null,
16233                 mOnBatteryTimeBase, in);
16234         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
16235         mWifiOn = false;
16236         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase, in);
16237         mGlobalWifiRunning = false;
16238         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null,
16239                 mOnBatteryTimeBase, in);
16240         for (int i=0; i<NUM_WIFI_STATES; i++) {
16241             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i,
16242                     null, mOnBatteryTimeBase, in);
16243         }
16244         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
16245             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i,
16246                     null, mOnBatteryTimeBase, in);
16247         }
16248         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
16249             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
16250                     null, mOnBatteryTimeBase, in);
16251         }
16252         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null,
16253             mOnBatteryTimeBase, in);
16254         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
16255                 NUM_WIFI_TX_LEVELS, in);
16256         for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
16257             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i,
16258                 null, mOnBatteryTimeBase, in);
16259         }
16260         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
16261                 NUM_BT_TX_LEVELS, in);
16262         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
16263                 ModemActivityInfo.getNumTxPowerLevels(), in);
16264         mHasWifiReporting = in.readInt() != 0;
16265         mHasBluetoothReporting = in.readInt() != 0;
16266         mHasModemReporting = in.readInt() != 0;
16267 
16268         mNumConnectivityChange = in.readInt();
16269         mAudioOnNesting = 0;
16270         // TODO: It's likely a mistake that mAudioOnTimer/mVideoOnTimer don't write/read to parcel!
16271         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
16272         mVideoOnNesting = 0;
16273         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
16274         mFlashlightOnNesting = 0;
16275         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase, in);
16276         mCameraOnNesting = 0;
16277         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
16278         mBluetoothScanNesting = 0;
16279         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
16280         mDischargeUnplugLevel = in.readInt();
16281         mDischargePlugLevel = in.readInt();
16282         mDischargeCurrentLevel = in.readInt();
16283         mCurrentBatteryLevel = in.readInt();
16284         mLowDischargeAmountSinceCharge = in.readInt();
16285         mHighDischargeAmountSinceCharge = in.readInt();
16286         mDischargeAmountScreenOn = in.readInt();
16287         mDischargeAmountScreenOnSinceCharge = in.readInt();
16288         mDischargeAmountScreenOff = in.readInt();
16289         mDischargeAmountScreenOffSinceCharge = in.readInt();
16290         mDischargeAmountScreenDoze = in.readInt();
16291         mDischargeAmountScreenDozeSinceCharge = in.readInt();
16292         mDischargeStepTracker.readFromParcel(in);
16293         mChargeStepTracker.readFromParcel(in);
16294         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
16295         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase, in);
16296         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
16297         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
16298         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
16299         mLastWriteTimeMs = in.readLong();
16300         mBatteryTimeToFullSeconds = in.readLong();
16301 
16302         if (in.readInt() != 0) {
16303             mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(in);
16304         }
16305 
16306         mRpmStats.clear();
16307         int NRPMS = in.readInt();
16308         for (int irpm = 0; irpm < NRPMS; irpm++) {
16309             if (in.readInt() != 0) {
16310                 String rpmName = in.readString();
16311                 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
16312                 mRpmStats.put(rpmName, rpmt);
16313             }
16314         }
16315         mScreenOffRpmStats.clear();
16316         int NSORPMS = in.readInt();
16317         for (int irpm = 0; irpm < NSORPMS; irpm++) {
16318             if (in.readInt() != 0) {
16319                 String rpmName = in.readString();
16320                 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
16321                 mScreenOffRpmStats.put(rpmName, rpmt);
16322             }
16323         }
16324 
16325         mKernelWakelockStats.clear();
16326         int NKW = in.readInt();
16327         for (int ikw = 0; ikw < NKW; ikw++) {
16328             if (in.readInt() != 0) {
16329                 String wakelockName = in.readString();
16330                 SamplingTimer kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
16331                 mKernelWakelockStats.put(wakelockName, kwlt);
16332             }
16333         }
16334 
16335         mWakeupReasonStats.clear();
16336         int NWR = in.readInt();
16337         for (int iwr = 0; iwr < NWR; iwr++) {
16338             if (in.readInt() != 0) {
16339                 String reasonName = in.readString();
16340                 SamplingTimer timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
16341                 mWakeupReasonStats.put(reasonName, timer);
16342             }
16343         }
16344 
16345         mKernelMemoryStats.clear();
16346         int nmt = in.readInt();
16347         for (int imt = 0; imt < nmt; imt++) {
16348             if (in.readInt() != 0) {
16349                 Long bucket = in.readLong();
16350                 SamplingTimer kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
16351                 mKernelMemoryStats.put(bucket, kmt);
16352             }
16353         }
16354 
16355         mPartialTimers.clear();
16356         mFullTimers.clear();
16357         mWindowTimers.clear();
16358         mWifiRunningTimers.clear();
16359         mFullWifiLockTimers.clear();
16360         mWifiScanTimers.clear();
16361         mWifiBatchedScanTimers.clear();
16362         mWifiMulticastTimers.clear();
16363         mAudioTurnedOnTimers.clear();
16364         mVideoTurnedOnTimers.clear();
16365         mFlashlightTurnedOnTimers.clear();
16366         mCameraTurnedOnTimers.clear();
16367 
16368         int numUids = in.readInt();
16369         mUidStats.clear();
16370         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
16371         final long uptimeMs = mClocks.uptimeMillis();
16372         for (int i = 0; i < numUids; i++) {
16373             int uid = in.readInt();
16374             Uid u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
16375             u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
16376             mUidStats.append(uid, u);
16377         }
16378 
16379         mBinderThreadCpuTimesUs = LongSamplingCounterArray.readFromParcel(in, mOnBatteryTimeBase);
16380     }
16381 
writeToParcel(Parcel out, int flags)16382     public void writeToParcel(Parcel out, int flags) {
16383         writeToParcelLocked(out, true, flags);
16384     }
16385 
writeToParcelWithoutUids(Parcel out, int flags)16386     public void writeToParcelWithoutUids(Parcel out, int flags) {
16387         writeToParcelLocked(out, false, flags);
16388     }
16389 
16390     @SuppressWarnings("unused")
writeToParcelLocked(Parcel out, boolean inclUids, int flags)16391     void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
16392         // Need to update with current kernel wake lock counts.
16393         pullPendingStateUpdatesLocked();
16394 
16395         updateSystemServiceCallStats();
16396 
16397         // Pull the clock time.  This may update the time and make a new history entry
16398         // if we had originally pulled a time before the RTC was set.
16399         getStartClockTime();
16400 
16401         final long uSecUptime = mClocks.uptimeMillis() * 1000;
16402         final long uSecRealtime = mClocks.elapsedRealtime() * 1000;
16403         final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
16404         final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
16405 
16406         out.writeInt(MAGIC);
16407 
16408         writeHistoryBuffer(out, true);
16409         mBatteryStatsHistory.writeToParcel(out);
16410 
16411         out.writeInt(mStartCount);
16412         out.writeLong(mStartClockTimeMs);
16413         out.writeString(mStartPlatformVersion);
16414         out.writeString(mEndPlatformVersion);
16415         out.writeLong(mUptimeUs);
16416         out.writeLong(mUptimeStartUs);
16417         out.writeLong(mRealtimeUs);
16418         out.writeLong(mRealtimeStartUs);
16419         out.writeInt(mOnBattery ? 1 : 0);
16420         out.writeInt(mEstimatedBatteryCapacityMah);
16421         out.writeInt(mLastLearnedBatteryCapacityUah);
16422         out.writeInt(mMinLearnedBatteryCapacityUah);
16423         out.writeInt(mMaxLearnedBatteryCapacityUah);
16424         mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
16425         mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
16426 
16427         mScreenOnTimer.writeToParcel(out, uSecRealtime);
16428         mScreenDozeTimer.writeToParcel(out, uSecRealtime);
16429         for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; i++) {
16430             mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
16431         }
16432         mInteractiveTimer.writeToParcel(out, uSecRealtime);
16433         mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
16434         out.writeLong(mLongestLightIdleTimeMs);
16435         out.writeLong(mLongestFullIdleTimeMs);
16436         mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
16437         mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
16438         mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
16439         mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
16440         mPhoneOnTimer.writeToParcel(out, uSecRealtime);
16441         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
16442             mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
16443         }
16444         mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
16445         for (int i = 0; i < NUM_DATA_CONNECTION_TYPES; i++) {
16446             mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
16447         }
16448         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
16449             mNetworkByteActivityCounters[i].writeToParcel(out);
16450             mNetworkPacketActivityCounters[i].writeToParcel(out);
16451         }
16452         mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
16453         mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
16454         mMobileRadioActiveAdjustedTime.writeToParcel(out);
16455         mMobileRadioActiveUnknownTime.writeToParcel(out);
16456         mMobileRadioActiveUnknownCount.writeToParcel(out);
16457         mWifiMulticastWakelockTimer.writeToParcel(out, uSecRealtime);
16458         mWifiOnTimer.writeToParcel(out, uSecRealtime);
16459         mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
16460         for (int i = 0; i < NUM_WIFI_STATES; i++) {
16461             mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
16462         }
16463         for (int i = 0; i < NUM_WIFI_SUPPL_STATES; i++) {
16464             mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
16465         }
16466         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
16467             mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
16468         }
16469         mWifiActiveTimer.writeToParcel(out, uSecRealtime);
16470         mWifiActivity.writeToParcel(out, 0);
16471         for (int i = 0; i < mGpsSignalQualityTimer.length; i++) {
16472             mGpsSignalQualityTimer[i].writeToParcel(out, uSecRealtime);
16473         }
16474         mBluetoothActivity.writeToParcel(out, 0);
16475         mModemActivity.writeToParcel(out, 0);
16476         out.writeInt(mHasWifiReporting ? 1 : 0);
16477         out.writeInt(mHasBluetoothReporting ? 1 : 0);
16478         out.writeInt(mHasModemReporting ? 1 : 0);
16479 
16480         out.writeInt(mNumConnectivityChange);
16481         mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
16482         mCameraOnTimer.writeToParcel(out, uSecRealtime);
16483         mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
16484         out.writeInt(mDischargeUnplugLevel);
16485         out.writeInt(mDischargePlugLevel);
16486         out.writeInt(mDischargeCurrentLevel);
16487         out.writeInt(mCurrentBatteryLevel);
16488         out.writeInt(mLowDischargeAmountSinceCharge);
16489         out.writeInt(mHighDischargeAmountSinceCharge);
16490         out.writeInt(mDischargeAmountScreenOn);
16491         out.writeInt(mDischargeAmountScreenOnSinceCharge);
16492         out.writeInt(mDischargeAmountScreenOff);
16493         out.writeInt(mDischargeAmountScreenOffSinceCharge);
16494         out.writeInt(mDischargeAmountScreenDoze);
16495         out.writeInt(mDischargeAmountScreenDozeSinceCharge);
16496         mDischargeStepTracker.writeToParcel(out);
16497         mChargeStepTracker.writeToParcel(out);
16498         mDischargeCounter.writeToParcel(out);
16499         mDischargeScreenOffCounter.writeToParcel(out);
16500         mDischargeScreenDozeCounter.writeToParcel(out);
16501         mDischargeLightDozeCounter.writeToParcel(out);
16502         mDischargeDeepDozeCounter.writeToParcel(out);
16503         out.writeLong(mLastWriteTimeMs);
16504         out.writeLong(mBatteryTimeToFullSeconds);
16505 
16506         if (mGlobalMeasuredEnergyStats != null) {
16507             out.writeInt(1);
16508             mGlobalMeasuredEnergyStats.writeToParcel(out);
16509         } else {
16510             out.writeInt(0);
16511         }
16512 
16513         out.writeInt(mRpmStats.size());
16514         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
16515             SamplingTimer rpmt = ent.getValue();
16516             if (rpmt != null) {
16517                 out.writeInt(1);
16518                 out.writeString(ent.getKey());
16519                 rpmt.writeToParcel(out, uSecRealtime);
16520             } else {
16521                 out.writeInt(0);
16522             }
16523         }
16524         out.writeInt(mScreenOffRpmStats.size());
16525         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
16526             SamplingTimer rpmt = ent.getValue();
16527             if (rpmt != null) {
16528                 out.writeInt(1);
16529                 out.writeString(ent.getKey());
16530                 rpmt.writeToParcel(out, uSecRealtime);
16531             } else {
16532                 out.writeInt(0);
16533             }
16534         }
16535 
16536         if (inclUids) {
16537             out.writeInt(mKernelWakelockStats.size());
16538             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
16539                 SamplingTimer kwlt = ent.getValue();
16540                 if (kwlt != null) {
16541                     out.writeInt(1);
16542                     out.writeString(ent.getKey());
16543                     kwlt.writeToParcel(out, uSecRealtime);
16544                 } else {
16545                     out.writeInt(0);
16546                 }
16547             }
16548             out.writeInt(mWakeupReasonStats.size());
16549             for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
16550                 SamplingTimer timer = ent.getValue();
16551                 if (timer != null) {
16552                     out.writeInt(1);
16553                     out.writeString(ent.getKey());
16554                     timer.writeToParcel(out, uSecRealtime);
16555                 } else {
16556                     out.writeInt(0);
16557                 }
16558             }
16559         } else {
16560             out.writeInt(0);
16561             out.writeInt(0);
16562         }
16563 
16564         out.writeInt(mKernelMemoryStats.size());
16565         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
16566             SamplingTimer kmt = mKernelMemoryStats.valueAt(i);
16567             if (kmt != null) {
16568                 out.writeInt(1);
16569                 out.writeLong(mKernelMemoryStats.keyAt(i));
16570                 kmt.writeToParcel(out, uSecRealtime);
16571             } else {
16572                 out.writeInt(0);
16573             }
16574         }
16575 
16576         if (inclUids) {
16577             int size = mUidStats.size();
16578             out.writeInt(size);
16579             for (int i = 0; i < size; i++) {
16580                 out.writeInt(mUidStats.keyAt(i));
16581                 Uid uid = mUidStats.valueAt(i);
16582 
16583                 uid.writeToParcelLocked(out, uSecUptime, uSecRealtime);
16584             }
16585         } else {
16586             out.writeInt(0);
16587         }
16588         LongSamplingCounterArray.writeToParcel(out, mBinderThreadCpuTimesUs);
16589     }
16590 
writeCpuSpeedCountersToParcel(Parcel out, LongSamplingCounter[][] counters)16591     private void writeCpuSpeedCountersToParcel(Parcel out, LongSamplingCounter[][] counters) {
16592         if (counters == null) {
16593             out.writeInt(0);
16594             return;
16595         }
16596 
16597         out.writeInt(1);
16598         out.writeInt(counters.length);
16599         for (int i = 0; i < counters.length; i++) {
16600             LongSamplingCounter[] counterArray = counters[i];
16601             if (counterArray == null) {
16602                 out.writeInt(0);
16603                 continue;
16604             }
16605 
16606             out.writeInt(1);
16607             out.writeInt(counterArray.length);
16608             for (int j = 0; j < counterArray.length; j++) {
16609                 LongSamplingCounter c = counterArray[j];
16610                 if (c != null) {
16611                     out.writeInt(1);
16612                     c.writeToParcel(out);
16613                 } else {
16614                     out.writeInt(0);
16615                 }
16616             }
16617         }
16618     }
16619 
readCpuSpeedCountersFromParcel(Parcel in)16620     private LongSamplingCounter[][] readCpuSpeedCountersFromParcel(Parcel in) {
16621         LongSamplingCounter[][] counters;
16622         if (in.readInt() != 0) {
16623             int numCpuClusters = in.readInt();
16624             if (mPowerProfile != null
16625                     && mPowerProfile.getNumCpuClusters() != numCpuClusters) {
16626                 throw new ParcelFormatException("Incompatible number of cpu clusters");
16627             }
16628 
16629             counters = new LongSamplingCounter[numCpuClusters][];
16630             for (int cluster = 0; cluster < numCpuClusters; cluster++) {
16631                 if (in.readInt() != 0) {
16632                     int numSpeeds = in.readInt();
16633                     if (mPowerProfile != null
16634                             && mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
16635                         throw new ParcelFormatException("Incompatible number of cpu speeds");
16636                     }
16637 
16638                     final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
16639                     counters[cluster] = cpuSpeeds;
16640                     for (int speed = 0; speed < numSpeeds; speed++) {
16641                         if (in.readInt() != 0) {
16642                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase, in);
16643                         }
16644                     }
16645                 } else {
16646                     counters[cluster] = null;
16647                 }
16648             }
16649         } else {
16650             counters = null;
16651         }
16652 
16653         return counters;
16654     }
16655 
16656     @UnsupportedAppUsage
16657     public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
16658         new Parcelable.Creator<BatteryStatsImpl>() {
16659         public BatteryStatsImpl createFromParcel(Parcel in) {
16660             return new BatteryStatsImpl(in);
16661         }
16662 
16663         public BatteryStatsImpl[] newArray(int size) {
16664             return new BatteryStatsImpl[size];
16665         }
16666     };
16667 
prepareForDumpLocked()16668     public void prepareForDumpLocked() {
16669         // Need to retrieve current kernel wake lock stats before printing.
16670         pullPendingStateUpdatesLocked();
16671 
16672         // Pull the clock time.  This may update the time and make a new history entry
16673         // if we had originally pulled a time before the RTC was set.
16674         getStartClockTime();
16675 
16676         updateSystemServiceCallStats();
16677     }
16678 
dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart)16679     public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
16680         if (DEBUG) {
16681             pw.println("mOnBatteryTimeBase:");
16682             mOnBatteryTimeBase.dump(pw, "  ");
16683             pw.println("mOnBatteryScreenOffTimeBase:");
16684             mOnBatteryScreenOffTimeBase.dump(pw, "  ");
16685             Printer pr = new PrintWriterPrinter(pw);
16686             pr.println("*** Screen on timer:");
16687             mScreenOnTimer.logState(pr, "  ");
16688             pr.println("*** Screen doze timer:");
16689             mScreenDozeTimer.logState(pr, "  ");
16690             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
16691                 pr.println("*** Screen brightness #" + i + ":");
16692                 mScreenBrightnessTimer[i].logState(pr, "  ");
16693             }
16694             pr.println("*** Interactive timer:");
16695             mInteractiveTimer.logState(pr, "  ");
16696             pr.println("*** Power save mode timer:");
16697             mPowerSaveModeEnabledTimer.logState(pr, "  ");
16698             pr.println("*** Device idle mode light timer:");
16699             mDeviceIdleModeLightTimer.logState(pr, "  ");
16700             pr.println("*** Device idle mode full timer:");
16701             mDeviceIdleModeFullTimer.logState(pr, "  ");
16702             pr.println("*** Device light idling timer:");
16703             mDeviceLightIdlingTimer.logState(pr, "  ");
16704             pr.println("*** Device idling timer:");
16705             mDeviceIdlingTimer.logState(pr, "  ");
16706             pr.println("*** Phone timer:");
16707             mPhoneOnTimer.logState(pr, "  ");
16708             for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
16709                 pr.println("*** Phone signal strength #" + i + ":");
16710                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
16711             }
16712             pr.println("*** Signal scanning :");
16713             mPhoneSignalScanningTimer.logState(pr, "  ");
16714             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
16715                 pr.println("*** Data connection type #" + i + ":");
16716                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
16717             }
16718             pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
16719             pr.println("*** Mobile network active timer:");
16720             mMobileRadioActiveTimer.logState(pr, "  ");
16721             pr.println("*** Mobile network active adjusted timer:");
16722             mMobileRadioActiveAdjustedTime.logState(pr, "  ");
16723             pr.println("*** Wifi Multicast WakeLock Timer:");
16724             mWifiMulticastWakelockTimer.logState(pr, "  ");
16725             pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
16726             pr.println("*** Wifi timer:");
16727             mWifiOnTimer.logState(pr, "  ");
16728             pr.println("*** WifiRunning timer:");
16729             mGlobalWifiRunningTimer.logState(pr, "  ");
16730             for (int i=0; i<NUM_WIFI_STATES; i++) {
16731                 pr.println("*** Wifi state #" + i + ":");
16732                 mWifiStateTimer[i].logState(pr, "  ");
16733             }
16734             for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
16735                 pr.println("*** Wifi suppl state #" + i + ":");
16736                 mWifiSupplStateTimer[i].logState(pr, "  ");
16737             }
16738             for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
16739                 pr.println("*** Wifi signal strength #" + i + ":");
16740                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
16741             }
16742             for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
16743                 pr.println("*** GPS signal quality #" + i + ":");
16744                 mGpsSignalQualityTimer[i].logState(pr, "  ");
16745             }
16746             pr.println("*** Flashlight timer:");
16747             mFlashlightOnTimer.logState(pr, "  ");
16748             pr.println("*** Camera timer:");
16749             mCameraOnTimer.logState(pr, "  ");
16750         }
16751         super.dumpLocked(context, pw, flags, reqUid, histStart);
16752 
16753         pw.print("Total cpu time reads: ");
16754         pw.println(mNumSingleUidCpuTimeReads);
16755         pw.print("Batched cpu time reads: ");
16756         pw.println(mNumBatchedSingleUidCpuTimeReads);
16757         pw.print("Batching Duration (min): ");
16758         pw.println((mClocks.uptimeMillis() - mCpuTimeReadsTrackingStartTimeMs) / (60 * 1000));
16759         pw.print("All UID cpu time reads since the later of device start or stats reset: ");
16760         pw.println(mNumAllUidCpuTimeReads);
16761         pw.print("UIDs removed since the later of device start or stats reset: ");
16762         pw.println(mNumUidsRemoved);
16763 
16764         pw.println();
16765         dumpConstantsLocked(pw);
16766 
16767         pw.println();
16768         dumpMeasuredEnergyStatsLocked(pw);
16769     }
16770 }
16771