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 android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.app.ActivityManager;
22 import android.bluetooth.BluetoothActivityEnergyInfo;
23 import android.bluetooth.UidTraffic;
24 import android.compat.annotation.UnsupportedAppUsage;
25 import android.content.BroadcastReceiver;
26 import android.content.ContentResolver;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.IntentFilter;
30 import android.database.ContentObserver;
31 import android.hardware.usb.UsbManager;
32 import android.net.ConnectivityManager;
33 import android.net.INetworkStatsService;
34 import android.net.NetworkStats;
35 import android.net.Uri;
36 import android.net.wifi.WifiActivityEnergyInfo;
37 import android.net.wifi.WifiManager;
38 import android.os.BatteryManager;
39 import android.os.BatteryStats;
40 import android.os.Build;
41 import android.os.Handler;
42 import android.os.IBatteryPropertiesRegistrar;
43 import android.os.Looper;
44 import android.os.Message;
45 import android.os.OsProtoEnums;
46 import android.os.Parcel;
47 import android.os.ParcelFormatException;
48 import android.os.Parcelable;
49 import android.os.PowerManager;
50 import android.os.Process;
51 import android.os.RemoteException;
52 import android.os.ServiceManager;
53 import android.os.SystemClock;
54 import android.os.UserHandle;
55 import android.os.WorkSource;
56 import android.os.WorkSource.WorkChain;
57 import android.os.connectivity.CellularBatteryStats;
58 import android.os.connectivity.GpsBatteryStats;
59 import android.os.connectivity.WifiBatteryStats;
60 import android.provider.Settings;
61 import android.telephony.CellSignalStrength;
62 import android.telephony.DataConnectionRealTimeInfo;
63 import android.telephony.ModemActivityInfo;
64 import android.telephony.ModemActivityInfo.TransmitPower;
65 import android.telephony.ServiceState;
66 import android.telephony.SignalStrength;
67 import android.telephony.TelephonyManager;
68 import android.text.TextUtils;
69 import android.util.ArrayMap;
70 import android.util.IntArray;
71 import android.util.KeyValueListParser;
72 import android.util.Log;
73 import android.util.LogWriter;
74 import android.util.LongSparseArray;
75 import android.util.LongSparseLongArray;
76 import android.util.MutableInt;
77 import android.util.Pools;
78 import android.util.PrintWriterPrinter;
79 import android.util.Printer;
80 import android.util.Slog;
81 import android.util.SparseArray;
82 import android.util.SparseIntArray;
83 import android.util.SparseLongArray;
84 import android.util.StatsLog;
85 import android.util.TimeUtils;
86 import android.util.Xml;
87 import android.view.Display;
88 
89 import com.android.internal.annotations.GuardedBy;
90 import com.android.internal.annotations.VisibleForTesting;
91 import com.android.internal.location.gnssmetrics.GnssMetrics;
92 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
93 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
94 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
95 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
96 import com.android.internal.util.ArrayUtils;
97 import com.android.internal.util.FastPrintWriter;
98 import com.android.internal.util.FastXmlSerializer;
99 import com.android.internal.util.XmlUtils;
100 
101 import libcore.util.EmptyArray;
102 
103 import org.xmlpull.v1.XmlPullParser;
104 import org.xmlpull.v1.XmlPullParserException;
105 import org.xmlpull.v1.XmlSerializer;
106 
107 import java.io.ByteArrayOutputStream;
108 import java.io.File;
109 import java.io.FileInputStream;
110 import java.io.FileNotFoundException;
111 import java.io.FileOutputStream;
112 import java.io.IOException;
113 import java.io.PrintWriter;
114 import java.nio.charset.StandardCharsets;
115 import java.util.ArrayList;
116 import java.util.Arrays;
117 import java.util.Calendar;
118 import java.util.Collection;
119 import java.util.HashMap;
120 import java.util.HashSet;
121 import java.util.Iterator;
122 import java.util.LinkedList;
123 import java.util.List;
124 import java.util.Map;
125 import java.util.Queue;
126 import java.util.concurrent.Future;
127 import java.util.concurrent.atomic.AtomicInteger;
128 import java.util.concurrent.locks.ReentrantLock;
129 
130 /**
131  * All information we are collecting about things that can happen that impact
132  * battery life.  All times are represented in microseconds except where indicated
133  * otherwise.
134  */
135 public class BatteryStatsImpl extends BatteryStats {
136     private static final String TAG = "BatteryStatsImpl";
137     private static final boolean DEBUG = false;
138     public static final boolean DEBUG_ENERGY = false;
139     private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
140     private static final boolean DEBUG_MEMORY = false;
141     private static final boolean DEBUG_HISTORY = false;
142     private static final boolean USE_OLD_HISTORY = false;   // for debugging.
143 
144     // TODO: remove "tcp" from network methods, since we measure total stats.
145 
146     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
147     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
148 
149     // Current on-disk Parcel version
150     static final int VERSION = 186 + (USE_OLD_HISTORY ? 1000 : 0);
151 
152     // The maximum number of names wakelocks we will keep track of
153     // per uid; once the limit is reached, we batch the remaining wakelocks
154     // in to one common name.
155     private static final int MAX_WAKELOCKS_PER_UID;
156 
157     static {
158         if (ActivityManager.isLowRamDeviceStatic()) {
159             MAX_WAKELOCKS_PER_UID = 40;
160         } else {
161             MAX_WAKELOCKS_PER_UID = 200;
162         }
163     }
164 
165     // Number of transmit power states the Wifi controller can be in.
166     private static final int NUM_WIFI_TX_LEVELS = 1;
167 
168     // Number of transmit power states the Bluetooth controller can be in.
169     private static final int NUM_BT_TX_LEVELS = 1;
170 
171     /**
172      * Holding a wakelock costs more than just using the cpu.
173      * Currently, we assign only half the cpu time to an app that is running but
174      * not holding a wakelock. The apps holding wakelocks get the rest of the blame.
175      * If no app is holding a wakelock, then the distribution is normal.
176      */
177     @VisibleForTesting
178     public static final int WAKE_LOCK_WEIGHT = 50;
179 
180     protected Clocks mClocks;
181 
182     private final AtomicFile mStatsFile;
183     public final AtomicFile mCheckinFile;
184     public final AtomicFile mDailyFile;
185 
186     static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1;
187     static final int MSG_REPORT_POWER_CHANGE = 2;
188     static final int MSG_REPORT_CHARGING = 3;
189     static final int MSG_REPORT_RESET_STATS = 4;
190     static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
191 
192     private static final double MILLISECONDS_IN_HOUR = 3600 * 1000;
193     private static final long MILLISECONDS_IN_YEAR = 365 * 24 * 3600 * 1000L;
194 
195     private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
196     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
197 
198     @VisibleForTesting
199     protected KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader =
200             new KernelCpuUidUserSysTimeReader(true);
201     @VisibleForTesting
202     protected KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
203     @VisibleForTesting
204     protected KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader =
205             new KernelCpuUidFreqTimeReader(true);
206     @VisibleForTesting
207     protected KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader =
208             new KernelCpuUidActiveTimeReader(true);
209     @VisibleForTesting
210     protected KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader =
211             new KernelCpuUidClusterTimeReader(true);
212     @VisibleForTesting
213     protected KernelSingleUidTimeReader mKernelSingleUidTimeReader;
214 
215     private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats
216             = new KernelMemoryBandwidthStats();
217     private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>();
getKernelMemoryStats()218     public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
219         return mKernelMemoryStats;
220     }
221 
222     @GuardedBy("this")
223     public boolean mPerProcStateCpuTimesAvailable = true;
224 
225     /**
226      * When per process state cpu times tracking is off, cpu times in KernelSingleUidTimeReader are
227      * not updated. So, when the setting is turned on later, we would end up with huge cpu time
228      * deltas. This flag tracks the case where tracking is turned on from off so that we won't
229      * end up attributing the huge deltas to wrong buckets.
230      */
231     @GuardedBy("this")
232     private boolean mIsPerProcessStateCpuDataStale;
233 
234     /**
235      * Uids for which per-procstate cpu times need to be updated.
236      *
237      * Contains uid -> procState mappings.
238      */
239     @GuardedBy("this")
240     @VisibleForTesting
241     protected final SparseIntArray mPendingUids = new SparseIntArray();
242 
243     @GuardedBy("this")
244     private long mNumSingleUidCpuTimeReads;
245     @GuardedBy("this")
246     private long mNumBatchedSingleUidCpuTimeReads;
247     @GuardedBy("this")
248     private long mCpuTimeReadsTrackingStartTime = SystemClock.uptimeMillis();
249     @GuardedBy("this")
250     private int mNumUidsRemoved;
251     @GuardedBy("this")
252     private int mNumAllUidCpuTimeReads;
253 
254     /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
255     private final RpmStats mTmpRpmStats = new RpmStats();
256     /** The soonest the RPM stats can be updated after it was last updated. */
257     private static final long RPM_STATS_UPDATE_FREQ_MS = 1000;
258     /** Last time that RPM stats were updated by updateRpmStatsLocked. */
259     private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
260 
261     /** Container for Rail Energy Data stats. */
262     private final RailStats mTmpRailStats = new RailStats();
263     /**
264      * Use a queue to delay removing UIDs from {@link KernelCpuUidUserSysTimeReader},
265      * {@link KernelCpuUidActiveTimeReader}, {@link KernelCpuUidClusterTimeReader},
266      * {@link KernelCpuUidFreqTimeReader} and from the Kernel.
267      *
268      * Isolated and invalid UID info must be removed to conserve memory. However, STATSD and
269      * Batterystats both need to access UID cpu time. To resolve this race condition, only
270      * Batterystats shall remove UIDs, and a delay {@link Constants#UID_REMOVE_DELAY_MS} is
271      * implemented so that STATSD can capture those UID times before they are deleted.
272      */
273     @GuardedBy("this")
274     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
275     protected Queue<UidToRemove> mPendingRemovedUids = new LinkedList<>();
276 
277     @VisibleForTesting
278     public final class UidToRemove {
279         int startUid;
280         int endUid;
281         long timeAddedInQueue;
282 
283         /** Remove just one UID */
UidToRemove(int uid, long timestamp)284         public UidToRemove(int uid, long timestamp) {
285             this(uid, uid, timestamp);
286         }
287 
288         /** Remove a range of UIDs, startUid must be smaller than endUid. */
UidToRemove(int startUid, int endUid, long timestamp)289         public UidToRemove(int startUid, int endUid, long timestamp) {
290             this.startUid = startUid;
291             this.endUid = endUid;
292             timeAddedInQueue = timestamp;
293         }
294 
remove()295         void remove() {
296             if (startUid == endUid) {
297                 mCpuUidUserSysTimeReader.removeUid(startUid);
298                 mCpuUidFreqTimeReader.removeUid(startUid);
299                 if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
300                     mCpuUidActiveTimeReader.removeUid(startUid);
301                     mCpuUidClusterTimeReader.removeUid(startUid);
302                 }
303                 if (mKernelSingleUidTimeReader != null) {
304                     mKernelSingleUidTimeReader.removeUid(startUid);
305                 }
306                 mNumUidsRemoved++;
307             } else if (startUid < endUid) {
308                 mCpuUidFreqTimeReader.removeUidsInRange(startUid, endUid);
309                 mCpuUidUserSysTimeReader.removeUidsInRange(startUid, endUid);
310                 if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
311                     mCpuUidActiveTimeReader.removeUidsInRange(startUid, endUid);
312                     mCpuUidClusterTimeReader.removeUidsInRange(startUid, endUid);
313                 }
314                 if (mKernelSingleUidTimeReader != null) {
315                     mKernelSingleUidTimeReader.removeUidsInRange(startUid, endUid);
316                 }
317                 // Treat as one. We don't know how many uids there are in between.
318                 mNumUidsRemoved++;
319             } else {
320                 Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
321             }
322         }
323     }
324 
325     public interface BatteryCallback {
batteryNeedsCpuUpdate()326         public void batteryNeedsCpuUpdate();
batteryPowerChanged(boolean onBattery)327         public void batteryPowerChanged(boolean onBattery);
batterySendBroadcast(Intent intent)328         public void batterySendBroadcast(Intent intent);
batteryStatsReset()329         public void batteryStatsReset();
330     }
331 
332     public interface PlatformIdleStateCallback {
fillLowPowerStats(RpmStats rpmStats)333         public void fillLowPowerStats(RpmStats rpmStats);
getPlatformLowPowerStats()334         public String getPlatformLowPowerStats();
getSubsystemLowPowerStats()335         public String getSubsystemLowPowerStats();
336     }
337 
338     /** interface to update rail information for power monitor */
339     public interface RailEnergyDataCallback {
340         /** Function to fill the map for the rail data stats
341          * Used for power monitoring feature
342          * @param railStats
343          */
fillRailDataStats(RailStats railStats)344         void fillRailDataStats(RailStats railStats);
345     }
346 
347     public static abstract class UserInfoProvider {
348         private int[] userIds;
getUserIds()349         protected abstract @Nullable int[] getUserIds();
350         @VisibleForTesting
refreshUserIds()351         public final void refreshUserIds() {
352             userIds = getUserIds();
353         }
354         @VisibleForTesting
exists(int userId)355         public boolean exists(int userId) {
356             return userIds != null ? ArrayUtils.contains(userIds, userId) : true;
357         }
358     }
359 
360     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
361 
362     private final Runnable mDeferSetCharging = new Runnable() {
363         @Override
364         public void run() {
365             synchronized (BatteryStatsImpl.this) {
366                 if (mOnBattery) {
367                     // if the device gets unplugged in the time between this runnable being
368                     // executed and the lock being taken, we don't want to set charging state
369                     return;
370                 }
371                 boolean changed = setChargingLocked(true);
372                 if (changed) {
373                     final long uptime = mClocks.uptimeMillis();
374                     final long elapsedRealtime = mClocks.elapsedRealtime();
375                     addHistoryRecordLocked(elapsedRealtime, uptime);
376                 }
377             }
378         }
379     };
380 
381     public final RailEnergyDataCallback mRailEnergyDataCallback;
382 
383     /**
384      * This handler is running on {@link BackgroundThread}.
385      */
386     final class MyHandler extends Handler {
MyHandler(Looper looper)387         public MyHandler(Looper looper) {
388             super(looper, null, true);
389         }
390 
391         @Override
handleMessage(Message msg)392         public void handleMessage(Message msg) {
393             BatteryCallback cb = mCallback;
394             switch (msg.what) {
395                 case MSG_REPORT_CPU_UPDATE_NEEDED:
396                     if (cb != null) {
397                         cb.batteryNeedsCpuUpdate();
398                     }
399                     break;
400                 case MSG_REPORT_POWER_CHANGE:
401                     if (cb != null) {
402                         cb.batteryPowerChanged(msg.arg1 != 0);
403                     }
404                     break;
405                 case MSG_REPORT_CHARGING:
406                     if (cb != null) {
407                         final String action;
408                         synchronized (BatteryStatsImpl.this) {
409                             action = mCharging ? BatteryManager.ACTION_CHARGING
410                                     : BatteryManager.ACTION_DISCHARGING;
411                         }
412                         Intent intent = new Intent(action);
413                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
414                         cb.batterySendBroadcast(intent);
415                     }
416                     break;
417                 case MSG_REPORT_RESET_STATS:
418                     if (cb != null) {
419                         cb.batteryStatsReset();
420                     }
421                 }
422         }
423     }
424 
postBatteryNeedsCpuUpdateMsg()425     public void postBatteryNeedsCpuUpdateMsg() {
426         mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED);
427     }
428 
429     /**
430      * Update per-freq cpu times for all the uids in {@link #mPendingUids}.
431      */
updateProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff)432     public void updateProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
433         final SparseIntArray uidStates;
434         synchronized (BatteryStatsImpl.this) {
435             if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
436                 return;
437             }
438             if(!initKernelSingleUidTimeReaderLocked()) {
439                 return;
440             }
441             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
442             // compute deltas since it might result in mis-attributing cpu times to wrong states.
443             if (mIsPerProcessStateCpuDataStale) {
444                 mPendingUids.clear();
445                 return;
446             }
447 
448             if (mPendingUids.size() == 0) {
449                 return;
450             }
451             uidStates = mPendingUids.clone();
452             mPendingUids.clear();
453         }
454         for (int i = uidStates.size() - 1; i >= 0; --i) {
455             final int uid = uidStates.keyAt(i);
456             final int procState = uidStates.valueAt(i);
457             final int[] isolatedUids;
458             final Uid u;
459             synchronized (BatteryStatsImpl.this) {
460                 // It's possible that uid no longer exists and any internal references have
461                 // already been deleted, so using {@link #getAvailableUidStatsLocked} to avoid
462                 // creating an UidStats object if it doesn't already exist.
463                 u = getAvailableUidStatsLocked(uid);
464                 if (u == null) {
465                     continue;
466                 }
467                 if (u.mChildUids == null) {
468                     isolatedUids = null;
469                 } else {
470                     isolatedUids = u.mChildUids.toArray();
471                     for (int j = isolatedUids.length - 1; j >= 0; --j) {
472                         isolatedUids[j] = u.mChildUids.get(j);
473                     }
474                 }
475             }
476             long[] cpuTimesMs = mKernelSingleUidTimeReader.readDeltaMs(uid);
477             if (isolatedUids != null) {
478                 for (int j = isolatedUids.length - 1; j >= 0; --j) {
479                     cpuTimesMs = addCpuTimes(cpuTimesMs,
480                             mKernelSingleUidTimeReader.readDeltaMs(isolatedUids[j]));
481                 }
482             }
483             if (onBattery && cpuTimesMs != null) {
484                 synchronized (BatteryStatsImpl.this) {
485                     u.addProcStateTimesMs(procState, cpuTimesMs, onBattery);
486                     u.addProcStateScreenOffTimesMs(procState, cpuTimesMs, onBatteryScreenOff);
487                 }
488             }
489         }
490     }
491 
clearPendingRemovedUids()492     public void clearPendingRemovedUids() {
493         long cutOffTime = mClocks.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS;
494         while (!mPendingRemovedUids.isEmpty()
495                 && mPendingRemovedUids.peek().timeAddedInQueue < cutOffTime) {
496             mPendingRemovedUids.poll().remove();
497         }
498     }
499 
copyFromAllUidsCpuTimes()500     public void copyFromAllUidsCpuTimes() {
501         synchronized (BatteryStatsImpl.this) {
502             copyFromAllUidsCpuTimes(
503                     mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
504         }
505     }
506 
507     /**
508      * When the battery/screen state changes, we don't attribute the cpu times to any process
509      * but we still need to snapshots of all uids to get correct deltas later on. Since we
510      * already read this data for updating per-freq cpu times, we can use the same data for
511      * per-procstate cpu times.
512      */
copyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff)513     public void copyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
514         synchronized (BatteryStatsImpl.this) {
515             if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
516                 return;
517             }
518             if(!initKernelSingleUidTimeReaderLocked()) {
519                 return;
520             }
521 
522             final SparseArray<long[]> allUidCpuFreqTimesMs =
523                     mCpuUidFreqTimeReader.getAllUidCpuFreqTimeMs();
524             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
525             // compute deltas since it might result in mis-attributing cpu times to wrong states.
526             if (mIsPerProcessStateCpuDataStale) {
527                 mKernelSingleUidTimeReader.setAllUidsCpuTimesMs(allUidCpuFreqTimesMs);
528                 mIsPerProcessStateCpuDataStale = false;
529                 mPendingUids.clear();
530                 return;
531             }
532             for (int i = allUidCpuFreqTimesMs.size() - 1; i >= 0; --i) {
533                 final int uid = allUidCpuFreqTimesMs.keyAt(i);
534                 final Uid u = getAvailableUidStatsLocked(mapUid(uid));
535                 if (u == null) {
536                     continue;
537                 }
538                 final long[] cpuTimesMs = allUidCpuFreqTimesMs.valueAt(i);
539                 if (cpuTimesMs == null) {
540                     continue;
541                 }
542                 final long[] deltaTimesMs = mKernelSingleUidTimeReader.computeDelta(
543                         uid, cpuTimesMs.clone());
544                 if (onBattery && deltaTimesMs != null) {
545                     final int procState;
546                     final int idx = mPendingUids.indexOfKey(uid);
547                     if (idx >= 0) {
548                         procState = mPendingUids.valueAt(idx);
549                         mPendingUids.removeAt(idx);
550                     } else {
551                         procState = u.mProcessState;
552                     }
553                     if (procState >= 0 && procState < Uid.NUM_PROCESS_STATE) {
554                         u.addProcStateTimesMs(procState, deltaTimesMs, onBattery);
555                         u.addProcStateScreenOffTimesMs(procState, deltaTimesMs, onBatteryScreenOff);
556                     }
557                 }
558             }
559         }
560     }
561 
562     @VisibleForTesting
addCpuTimes(long[] timesA, long[] timesB)563     public long[] addCpuTimes(long[] timesA, long[] timesB) {
564         if (timesA != null && timesB != null) {
565             for (int i = timesA.length - 1; i >= 0; --i) {
566                 timesA[i] += timesB[i];
567             }
568             return timesA;
569         }
570         return timesA == null ? (timesB == null ? null : timesB) : timesA;
571     }
572 
573     @GuardedBy("this")
initKernelSingleUidTimeReaderLocked()574     private boolean initKernelSingleUidTimeReaderLocked() {
575         if (mKernelSingleUidTimeReader == null) {
576             if (mPowerProfile == null) {
577                 return false;
578             }
579             if (mCpuFreqs == null) {
580                 mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
581             }
582             if (mCpuFreqs != null) {
583                 mKernelSingleUidTimeReader = new KernelSingleUidTimeReader(mCpuFreqs.length);
584             } else {
585                 mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.allUidTimesAvailable();
586                 return false;
587             }
588         }
589         mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.allUidTimesAvailable()
590                 && mKernelSingleUidTimeReader.singleUidCpuTimesAvailable();
591         return true;
592     }
593 
594     public interface Clocks {
elapsedRealtime()595         public long elapsedRealtime();
uptimeMillis()596         public long uptimeMillis();
597     }
598 
599     public static class SystemClocks implements Clocks {
elapsedRealtime()600         public long elapsedRealtime() {
601             return SystemClock.elapsedRealtime();
602         }
603 
uptimeMillis()604         public long uptimeMillis() {
605             return SystemClock.uptimeMillis();
606         }
607     }
608 
609     public interface ExternalStatsSync {
610         int UPDATE_CPU = 0x01;
611         int UPDATE_WIFI = 0x02;
612         int UPDATE_RADIO = 0x04;
613         int UPDATE_BT = 0x08;
614         int UPDATE_RPM = 0x10; // 16
615         int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM;
616 
scheduleSync(String reason, int flags)617         Future<?> scheduleSync(String reason, int flags);
scheduleCpuSyncDueToRemovedUid(int uid)618         Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff, long delayMillis)619         Future<?> scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff,
620                 long delayMillis);
scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff)621         Future<?> scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff);
scheduleCpuSyncDueToSettingChange()622         Future<?> scheduleCpuSyncDueToSettingChange();
scheduleCpuSyncDueToScreenStateChange(boolean onBattery, boolean onBatteryScreenOff)623         Future<?> scheduleCpuSyncDueToScreenStateChange(boolean onBattery,
624                 boolean onBatteryScreenOff);
scheduleCpuSyncDueToWakelockChange(long delayMillis)625         Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis);
cancelCpuSyncDueToWakelockChange()626         void cancelCpuSyncDueToWakelockChange();
scheduleSyncDueToBatteryLevelChange(long delayMillis)627         Future<?> scheduleSyncDueToBatteryLevelChange(long delayMillis);
628     }
629 
630     public Handler mHandler;
631     private ExternalStatsSync mExternalSync = null;
632     @VisibleForTesting
633     protected UserInfoProvider mUserInfoProvider = null;
634 
635     private BatteryCallback mCallback;
636 
637     /**
638      * Mapping isolated uids to the actual owning app uid.
639      */
640     final SparseIntArray mIsolatedUids = new SparseIntArray();
641 
642     /**
643      * The statistics we have collected organized by uids.
644      */
645     final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
646 
647     // A set of pools of currently active timers.  When a timer is queried, we will divide the
648     // elapsed time by the number of active timers to arrive at that timer's share of the time.
649     // In order to do this, we must refresh each timer whenever the number of active timers
650     // changes.
651     @VisibleForTesting
652     @UnsupportedAppUsage
653     protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
654     @UnsupportedAppUsage
655     final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
656     @UnsupportedAppUsage
657     final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
658     final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
659     final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
660     final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
661     final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
662     final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
663     final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
664     final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers = new SparseArray<>();
665     final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
666     final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
667     final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
668     final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
669     final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
670 
671     // Last partial timers we use for distributing CPU usage.
672     @VisibleForTesting
673     protected ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
674 
675     // These are the objects that will want to do something when the device
676     // is unplugged from power.
677     protected final TimeBase mOnBatteryTimeBase = new TimeBase(true);
678 
679     // These are the objects that will want to do something when the device
680     // is unplugged from power *and* the screen is off or doze.
681     protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(true);
682 
683     // Set to true when we want to distribute CPU across wakelocks for the next
684     // CPU update, even if we aren't currently running wake locks.
685     boolean mDistributeWakelockCpu;
686 
687     boolean mShuttingDown;
688 
689     final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
690 
691     long mHistoryBaseTime;
692     protected boolean mHaveBatteryLevel = false;
693     protected boolean mRecordingHistory = false;
694     int mNumHistoryItems;
695 
696     final Parcel mHistoryBuffer = Parcel.obtain();
697     final HistoryItem mHistoryLastWritten = new HistoryItem();
698     final HistoryItem mHistoryLastLastWritten = new HistoryItem();
699     final HistoryItem mHistoryReadTmp = new HistoryItem();
700     final HistoryItem mHistoryAddTmp = new HistoryItem();
701     final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
702     String[] mReadHistoryStrings;
703     int[] mReadHistoryUids;
704     int mReadHistoryChars;
705     int mNextHistoryTagIdx = 0;
706     int mNumHistoryTagChars = 0;
707     int mHistoryBufferLastPos = -1;
708     int mActiveHistoryStates = 0xffffffff;
709     int mActiveHistoryStates2 = 0xffffffff;
710     long mLastHistoryElapsedRealtime = 0;
711     long mTrackRunningHistoryElapsedRealtime = 0;
712     long mTrackRunningHistoryUptime = 0;
713 
714     final BatteryStatsHistory mBatteryStatsHistory;
715 
716     final HistoryItem mHistoryCur = new HistoryItem();
717 
718     HistoryItem mHistory;
719     HistoryItem mHistoryEnd;
720     HistoryItem mHistoryLastEnd;
721     HistoryItem mHistoryCache;
722 
723     // Used by computeHistoryStepDetails
724     HistoryStepDetails mLastHistoryStepDetails = null;
725     byte mLastHistoryStepLevel = 0;
726     final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
727     final HistoryStepDetails mReadHistoryStepDetails = new HistoryStepDetails();
728     final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
729 
730     /**
731      * Total time (in milliseconds) spent executing in user code.
732      */
733     long mLastStepCpuUserTime;
734     long mCurStepCpuUserTime;
735     /**
736      * Total time (in milliseconds) spent executing in kernel code.
737      */
738     long mLastStepCpuSystemTime;
739     long mCurStepCpuSystemTime;
740     /**
741      * Times from /proc/stat (but measured in milliseconds).
742      */
743     long mLastStepStatUserTime;
744     long mLastStepStatSystemTime;
745     long mLastStepStatIOWaitTime;
746     long mLastStepStatIrqTime;
747     long mLastStepStatSoftIrqTime;
748     long mLastStepStatIdleTime;
749     long mCurStepStatUserTime;
750     long mCurStepStatSystemTime;
751     long mCurStepStatIOWaitTime;
752     long mCurStepStatIrqTime;
753     long mCurStepStatSoftIrqTime;
754     long mCurStepStatIdleTime;
755 
756     private HistoryItem mHistoryIterator;
757     private boolean mReadOverflow;
758     private boolean mIteratingHistory;
759 
760     int mStartCount;
761 
762     long mStartClockTime;
763     String mStartPlatformVersion;
764     String mEndPlatformVersion;
765 
766     long mUptime;
767     long mUptimeStart;
768     long mRealtime;
769     long mRealtimeStart;
770 
771     int mWakeLockNesting;
772     boolean mWakeLockImportant;
773     public boolean mRecordAllHistory;
774     boolean mNoAutoReset;
775 
776     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
777     protected int mScreenState = Display.STATE_UNKNOWN;
778     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
779     protected StopwatchTimer mScreenOnTimer;
780     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
781     protected StopwatchTimer mScreenDozeTimer;
782 
783     int mScreenBrightnessBin = -1;
784     final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
785 
786     boolean mPretendScreenOff;
787 
788     boolean mInteractive;
789     StopwatchTimer mInteractiveTimer;
790 
791     boolean mPowerSaveModeEnabled;
792     StopwatchTimer mPowerSaveModeEnabledTimer;
793 
794     boolean mDeviceIdling;
795     StopwatchTimer mDeviceIdlingTimer;
796 
797     boolean mDeviceLightIdling;
798     StopwatchTimer mDeviceLightIdlingTimer;
799 
800     int mDeviceIdleMode;
801     long mLastIdleTimeStart;
802     long mLongestLightIdleTime;
803     long mLongestFullIdleTime;
804     StopwatchTimer mDeviceIdleModeLightTimer;
805     StopwatchTimer mDeviceIdleModeFullTimer;
806 
807     boolean mPhoneOn;
808     StopwatchTimer mPhoneOnTimer;
809 
810     int mAudioOnNesting;
811     StopwatchTimer mAudioOnTimer;
812 
813     int mVideoOnNesting;
814     StopwatchTimer mVideoOnTimer;
815 
816     int mFlashlightOnNesting;
817     StopwatchTimer mFlashlightOnTimer;
818 
819     int mCameraOnNesting;
820     StopwatchTimer mCameraOnTimer;
821 
822     private static final int USB_DATA_UNKNOWN = 0;
823     private static final int USB_DATA_DISCONNECTED = 1;
824     private static final int USB_DATA_CONNECTED = 2;
825     int mUsbDataState = USB_DATA_UNKNOWN;
826 
827     int mGpsSignalQualityBin = -1;
828     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
829     protected final StopwatchTimer[] mGpsSignalQualityTimer =
830         new StopwatchTimer[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
831 
832     int mPhoneSignalStrengthBin = -1;
833     int mPhoneSignalStrengthBinRaw = -1;
834     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
835             new StopwatchTimer[CellSignalStrength.getNumSignalStrengthLevels()];
836 
837     StopwatchTimer mPhoneSignalScanningTimer;
838 
839     int mPhoneDataConnectionType = -1;
840     final StopwatchTimer[] mPhoneDataConnectionsTimer =
841             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
842 
843     final LongSamplingCounter[] mNetworkByteActivityCounters =
844             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
845     final LongSamplingCounter[] mNetworkPacketActivityCounters =
846             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
847 
848     /**
849      * The WiFi Overall wakelock timer
850      * This timer tracks the actual aggregate time for which MC wakelocks are enabled
851      * since addition of per UID timers would not result in an accurate value due to overlapp of
852      * per uid wakelock timers
853      */
854     StopwatchTimer mWifiMulticastWakelockTimer;
855 
856     /**
857      * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
858      */
859     ControllerActivityCounterImpl mWifiActivity;
860 
861     /**
862      * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
863      */
864     ControllerActivityCounterImpl mBluetoothActivity;
865 
866     /**
867      * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
868      */
869     ControllerActivityCounterImpl mModemActivity;
870 
871     /**
872      * Whether the device supports WiFi controller energy reporting. This is set to true on
873      * the first WiFi energy report. See {@link #mWifiActivity}.
874      */
875     boolean mHasWifiReporting = false;
876 
877     /**
878      * Whether the device supports Bluetooth controller energy reporting. This is set to true on
879      * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
880      */
881     boolean mHasBluetoothReporting = false;
882 
883     /**
884      * Whether the device supports Modem controller energy reporting. This is set to true on
885      * the first Modem energy report. See {@link #mModemActivity}.
886      */
887     boolean mHasModemReporting = false;
888 
889     boolean mWifiOn;
890     StopwatchTimer mWifiOnTimer;
891 
892     boolean mGlobalWifiRunning;
893     StopwatchTimer mGlobalWifiRunningTimer;
894 
895     int mWifiState = -1;
896     final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
897 
898     int mWifiSupplState = -1;
899     final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
900 
901     int mWifiSignalStrengthBin = -1;
902     final StopwatchTimer[] mWifiSignalStrengthsTimer =
903             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
904 
905     StopwatchTimer mWifiActiveTimer;
906 
907     int mBluetoothScanNesting;
908     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
909     protected StopwatchTimer mBluetoothScanTimer;
910 
911     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
912     long mMobileRadioActiveStartTime;
913     StopwatchTimer mMobileRadioActiveTimer;
914     StopwatchTimer mMobileRadioActivePerAppTimer;
915     LongSamplingCounter mMobileRadioActiveAdjustedTime;
916     LongSamplingCounter mMobileRadioActiveUnknownTime;
917     LongSamplingCounter mMobileRadioActiveUnknownCount;
918 
919     int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
920 
921     /**
922      * These provide time bases that discount the time the device is plugged
923      * in to power.
924      */
925     boolean mOnBattery;
926     @VisibleForTesting
927     protected boolean mOnBatteryInternal;
928 
929     /**
930      * External reporting of whether the device is actually charging.
931      */
932     boolean mCharging = true;
933     int mLastChargingStateLevel;
934 
935     /*
936      * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
937      */
938     int mDischargeStartLevel;
939     int mDischargeUnplugLevel;
940     int mDischargePlugLevel;
941     int mDischargeCurrentLevel;
942     int mCurrentBatteryLevel;
943     int mLowDischargeAmountSinceCharge;
944     int mHighDischargeAmountSinceCharge;
945     int mDischargeScreenOnUnplugLevel;
946     int mDischargeScreenOffUnplugLevel;
947     int mDischargeScreenDozeUnplugLevel;
948     int mDischargeAmountScreenOn;
949     int mDischargeAmountScreenOnSinceCharge;
950     int mDischargeAmountScreenOff;
951     int mDischargeAmountScreenOffSinceCharge;
952     int mDischargeAmountScreenDoze;
953     int mDischargeAmountScreenDozeSinceCharge;
954 
955     private LongSamplingCounter mDischargeScreenOffCounter;
956     private LongSamplingCounter mDischargeScreenDozeCounter;
957     private LongSamplingCounter mDischargeCounter;
958     private LongSamplingCounter mDischargeLightDozeCounter;
959     private LongSamplingCounter mDischargeDeepDozeCounter;
960 
961     static final int MAX_LEVEL_STEPS = 200;
962 
963     int mInitStepMode = 0;
964     int mCurStepMode = 0;
965     int mModStepMode = 0;
966 
967     int mLastDischargeStepLevel;
968     int mMinDischargeStepLevel;
969     final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
970     final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
971     ArrayList<PackageChange> mDailyPackageChanges;
972 
973     int mLastChargeStepLevel;
974     int mMaxChargeStepLevel;
975     final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
976     final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
977 
978     static final int MAX_DAILY_ITEMS = 10;
979 
980     long mDailyStartTime = 0;
981     long mNextMinDailyDeadline = 0;
982     long mNextMaxDailyDeadline = 0;
983 
984     final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
985 
986     long mLastWriteTime = 0; // Milliseconds
987 
988     private int mPhoneServiceState = -1;
989     private int mPhoneServiceStateRaw = -1;
990     private int mPhoneSimStateRaw = -1;
991 
992     private int mNumConnectivityChange;
993 
994     private int mEstimatedBatteryCapacity = -1;
995 
996     private int mMinLearnedBatteryCapacity = -1;
997     private int mMaxLearnedBatteryCapacity = -1;
998 
999     private long mBatteryTimeToFullSeconds = -1;
1000 
1001     private long[] mCpuFreqs;
1002 
1003     @VisibleForTesting
1004     protected PowerProfile mPowerProfile;
1005 
1006     @GuardedBy("this")
1007     final Constants mConstants;
1008 
1009     /*
1010      * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
1011      * recording their times when on-battery (regardless of screen state).
1012      */
1013     private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>();
1014     /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */
1015     private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>();
1016 
1017     @Override
getRpmStats()1018     public Map<String, ? extends Timer> getRpmStats() {
1019         return mRpmStats;
1020     }
1021 
1022     // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED.
1023     @Override
getScreenOffRpmStats()1024     public Map<String, ? extends Timer> getScreenOffRpmStats() {
1025         return mScreenOffRpmStats;
1026     }
1027 
1028     /*
1029      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
1030      */
1031     private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
1032 
1033     @UnsupportedAppUsage
getKernelWakelockStats()1034     public Map<String, ? extends Timer> getKernelWakelockStats() {
1035         return mKernelWakelockStats;
1036     }
1037 
1038     String mLastWakeupReason = null;
1039     long mLastWakeupUptimeMs = 0;
1040     private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
1041 
getWakeupReasonStats()1042     public Map<String, ? extends Timer> getWakeupReasonStats() {
1043         return mWakeupReasonStats;
1044     }
1045 
1046     @Override
getUahDischarge(int which)1047     public long getUahDischarge(int which) {
1048         return mDischargeCounter.getCountLocked(which);
1049     }
1050 
1051     @Override
getUahDischargeScreenOff(int which)1052     public long getUahDischargeScreenOff(int which) {
1053         return mDischargeScreenOffCounter.getCountLocked(which);
1054     }
1055 
1056     @Override
getUahDischargeScreenDoze(int which)1057     public long getUahDischargeScreenDoze(int which) {
1058         return mDischargeScreenDozeCounter.getCountLocked(which);
1059     }
1060 
1061     @Override
getUahDischargeLightDoze(int which)1062     public long getUahDischargeLightDoze(int which) {
1063         return mDischargeLightDozeCounter.getCountLocked(which);
1064     }
1065 
1066     @Override
getUahDischargeDeepDoze(int which)1067     public long getUahDischargeDeepDoze(int which) {
1068         return mDischargeDeepDozeCounter.getCountLocked(which);
1069     }
1070 
1071     @Override
getEstimatedBatteryCapacity()1072     public int getEstimatedBatteryCapacity() {
1073         return mEstimatedBatteryCapacity;
1074     }
1075 
1076     @Override
getMinLearnedBatteryCapacity()1077     public int getMinLearnedBatteryCapacity() {
1078         return mMinLearnedBatteryCapacity;
1079     }
1080 
1081     @Override
getMaxLearnedBatteryCapacity()1082     public int getMaxLearnedBatteryCapacity() {
1083         return mMaxLearnedBatteryCapacity;
1084     }
1085 
BatteryStatsImpl()1086     public BatteryStatsImpl() {
1087         this(new SystemClocks());
1088     }
1089 
BatteryStatsImpl(Clocks clocks)1090     public BatteryStatsImpl(Clocks clocks) {
1091         init(clocks);
1092         mStatsFile = null;
1093         mCheckinFile = null;
1094         mDailyFile = null;
1095         mBatteryStatsHistory = null;
1096         mHandler = null;
1097         mPlatformIdleStateCallback = null;
1098         mRailEnergyDataCallback = null;
1099         mUserInfoProvider = null;
1100         mConstants = new Constants(mHandler);
1101         clearHistoryLocked();
1102     }
1103 
init(Clocks clocks)1104     private void init(Clocks clocks) {
1105         mClocks = clocks;
1106     }
1107 
1108     /**
1109      * TimeBase observer.
1110      */
1111     public interface TimeBaseObs {
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)1112         void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1113         void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
1114 
1115         /**
1116          * Reset the observer's state, returns true if the timer/counter is inactive
1117          * so it can be destroyed.
1118          * @param detachIfReset detach if true, no-op if false.
1119          * @return Returns true if the timer/counter is inactive and can be destroyed.
1120          */
reset(boolean detachIfReset)1121         boolean reset(boolean detachIfReset);
1122         /**
1123          * Detach the observer from TimeBase.
1124          */
detach()1125         void detach();
1126     }
1127 
1128     // methods are protected not private to be VisibleForTesting
1129     public static class TimeBase {
1130         protected final Collection<TimeBaseObs> mObservers;
1131         protected long mUptime;
1132         protected long mRealtime;
1133 
1134         protected boolean mRunning;
1135 
1136         protected long mPastUptime;
1137         protected long mUptimeStart;
1138         protected long mPastRealtime;
1139         protected long mRealtimeStart;
1140         protected long mUnpluggedUptime;
1141         protected long mUnpluggedRealtime;
1142 
dump(PrintWriter pw, String prefix)1143         public void dump(PrintWriter pw, String prefix) {
1144             StringBuilder sb = new StringBuilder(128);
1145             pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
1146             sb.setLength(0);
1147             sb.append(prefix);
1148                     sb.append("mUptime=");
1149                     formatTimeMs(sb, mUptime / 1000);
1150             pw.println(sb.toString());
1151             sb.setLength(0);
1152             sb.append(prefix);
1153                     sb.append("mRealtime=");
1154                     formatTimeMs(sb, mRealtime / 1000);
1155             pw.println(sb.toString());
1156             sb.setLength(0);
1157             sb.append(prefix);
1158                     sb.append("mPastUptime=");
1159                     formatTimeMs(sb, mPastUptime / 1000); sb.append("mUptimeStart=");
1160                     formatTimeMs(sb, mUptimeStart / 1000);
1161                     sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptime / 1000);
1162             pw.println(sb.toString());
1163             sb.setLength(0);
1164             sb.append(prefix);
1165                     sb.append("mPastRealtime=");
1166                     formatTimeMs(sb, mPastRealtime / 1000); sb.append("mRealtimeStart=");
1167                     formatTimeMs(sb, mRealtimeStart / 1000);
1168                     sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000);
1169             pw.println(sb.toString());
1170         }
1171         /**
1172          * The mObservers of TimeBase in BatteryStatsImpl object can contain up to 20k entries.
1173          * The mObservers of TimeBase in BatteryStatsImpl.Uid object only contains a few or tens of
1174          * entries.
1175          * mObservers must have good performance on add(), remove(), also be memory efficient.
1176          * This is why we provide isLongList parameter for long and short list user cases.
1177          * @param isLongList If true, use HashSet for mObservers list.
1178          *                   If false, use ArrayList for mObservers list.
1179         */
TimeBase(boolean isLongList)1180         public TimeBase(boolean isLongList) {
1181             mObservers = isLongList ? new HashSet<>() : new ArrayList<>();
1182         }
1183 
TimeBase()1184         public TimeBase() {
1185             this(false);
1186         }
1187 
add(TimeBaseObs observer)1188         public void add(TimeBaseObs observer) {
1189             mObservers.add(observer);
1190         }
1191 
remove(TimeBaseObs observer)1192         public void remove(TimeBaseObs observer) {
1193             mObservers.remove(observer);
1194         }
1195 
hasObserver(TimeBaseObs observer)1196         public boolean hasObserver(TimeBaseObs observer) {
1197             return mObservers.contains(observer);
1198         }
1199 
init(long uptime, long realtime)1200         public void init(long uptime, long realtime) {
1201             mRealtime = 0;
1202             mUptime = 0;
1203             mPastUptime = 0;
1204             mPastRealtime = 0;
1205             mUptimeStart = uptime;
1206             mRealtimeStart = realtime;
1207             mUnpluggedUptime = getUptime(mUptimeStart);
1208             mUnpluggedRealtime = getRealtime(mRealtimeStart);
1209         }
1210 
reset(long uptime, long realtime)1211         public void reset(long uptime, long realtime) {
1212             if (!mRunning) {
1213                 mPastUptime = 0;
1214                 mPastRealtime = 0;
1215             } else {
1216                 mUptimeStart = uptime;
1217                 mRealtimeStart = realtime;
1218                 // TODO: Since mUptimeStart was just reset and we are running, getUptime will
1219                 // just return mPastUptime. Also, are we sure we don't want to reset that?
1220                 mUnpluggedUptime = getUptime(uptime);
1221                 // TODO: likewise.
1222                 mUnpluggedRealtime = getRealtime(realtime);
1223             }
1224         }
1225 
computeUptime(long curTime, int which)1226         public long computeUptime(long curTime, int which) {
1227             return mUptime + getUptime(curTime);
1228         }
1229 
computeRealtime(long curTime, int which)1230         public long computeRealtime(long curTime, int which) {
1231             return mRealtime + getRealtime(curTime);
1232         }
1233 
getUptime(long curTime)1234         public long getUptime(long curTime) {
1235             long time = mPastUptime;
1236             if (mRunning) {
1237                 time += curTime - mUptimeStart;
1238             }
1239             return time;
1240         }
1241 
getRealtime(long curTime)1242         public long getRealtime(long curTime) {
1243             long time = mPastRealtime;
1244             if (mRunning) {
1245                 time += curTime - mRealtimeStart;
1246             }
1247             return time;
1248         }
1249 
getUptimeStart()1250         public long getUptimeStart() {
1251             return mUptimeStart;
1252         }
1253 
getRealtimeStart()1254         public long getRealtimeStart() {
1255             return mRealtimeStart;
1256         }
1257 
isRunning()1258         public boolean isRunning() {
1259             return mRunning;
1260         }
1261 
setRunning(boolean running, long uptime, long realtime)1262         public boolean setRunning(boolean running, long uptime, long realtime) {
1263             if (mRunning != running) {
1264                 mRunning = running;
1265                 if (running) {
1266                     mUptimeStart = uptime;
1267                     mRealtimeStart = realtime;
1268                     long batteryUptime = mUnpluggedUptime = getUptime(uptime);
1269                     long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime);
1270                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
1271                     // Iterator object, here is an exception because mObservers' type is Collection
1272                     // instead of list.
1273                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
1274                     while (iter.hasNext()) {
1275                         iter.next().onTimeStarted(realtime, batteryUptime, batteryRealtime);
1276                     }
1277                 } else {
1278                     mPastUptime += uptime - mUptimeStart;
1279                     mPastRealtime += realtime - mRealtimeStart;
1280                     long batteryUptime = getUptime(uptime);
1281                     long batteryRealtime = getRealtime(realtime);
1282                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
1283                     // Iterator object, here is an exception because mObservers' type is Collection
1284                     // instead of list.
1285                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
1286                     while (iter.hasNext()) {
1287                         iter.next().onTimeStopped(realtime, batteryUptime, batteryRealtime);
1288                     }
1289                 }
1290                 return true;
1291             }
1292             return false;
1293         }
1294 
readSummaryFromParcel(Parcel in)1295         public void readSummaryFromParcel(Parcel in) {
1296             mUptime = in.readLong();
1297             mRealtime = in.readLong();
1298         }
1299 
writeSummaryToParcel(Parcel out, long uptime, long realtime)1300         public void writeSummaryToParcel(Parcel out, long uptime, long realtime) {
1301             out.writeLong(computeUptime(uptime, STATS_SINCE_CHARGED));
1302             out.writeLong(computeRealtime(realtime, STATS_SINCE_CHARGED));
1303         }
1304 
readFromParcel(Parcel in)1305         public void readFromParcel(Parcel in) {
1306             mRunning = false;
1307             mUptime = in.readLong();
1308             mPastUptime = in.readLong();
1309             mUptimeStart = in.readLong();
1310             mRealtime = in.readLong();
1311             mPastRealtime = in.readLong();
1312             mRealtimeStart = in.readLong();
1313             mUnpluggedUptime = in.readLong();
1314             mUnpluggedRealtime = in.readLong();
1315         }
1316 
writeToParcel(Parcel out, long uptime, long realtime)1317         public void writeToParcel(Parcel out, long uptime, long realtime) {
1318             final long runningUptime = getUptime(uptime);
1319             final long runningRealtime = getRealtime(realtime);
1320             out.writeLong(mUptime);
1321             out.writeLong(runningUptime);
1322             out.writeLong(mUptimeStart);
1323             out.writeLong(mRealtime);
1324             out.writeLong(runningRealtime);
1325             out.writeLong(mRealtimeStart);
1326             out.writeLong(mUnpluggedUptime);
1327             out.writeLong(mUnpluggedRealtime);
1328         }
1329     }
1330 
1331     /**
1332      * State for keeping track of counting information.
1333      */
1334     public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
1335         @UnsupportedAppUsage
1336         final AtomicInteger mCount = new AtomicInteger();
1337         final TimeBase mTimeBase;
1338 
Counter(TimeBase timeBase, Parcel in)1339         public Counter(TimeBase timeBase, Parcel in) {
1340             mTimeBase = timeBase;
1341             mCount.set(in.readInt());
1342             timeBase.add(this);
1343         }
1344 
Counter(TimeBase timeBase)1345         public Counter(TimeBase timeBase) {
1346             mTimeBase = timeBase;
1347             timeBase.add(this);
1348         }
1349 
writeToParcel(Parcel out)1350         public void writeToParcel(Parcel out) {
1351             out.writeInt(mCount.get());
1352         }
1353 
1354         @Override
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)1355         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1356         }
1357 
1358         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1359         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1360         }
1361 
1362         /**
1363          * Writes a possibly null Counter to a Parcel.
1364          *
1365          * @param out the Parcel to be written to.
1366          * @param counter a Counter, or null.
1367          */
writeCounterToParcel(Parcel out, @Nullable Counter counter)1368         public static void writeCounterToParcel(Parcel out, @Nullable Counter counter) {
1369             if (counter == null) {
1370                 out.writeInt(0); // indicates null
1371                 return;
1372             }
1373             out.writeInt(1); // indicates non-null
1374 
1375             counter.writeToParcel(out);
1376         }
1377 
1378         /**
1379          * Reads a Counter that was written using {@link #writeCounterToParcel(Parcel, Counter)}.
1380          * @param timeBase the timebase to assign to the Counter
1381          * @param in the parcel to read from
1382          * @return the Counter or null.
1383          */
readCounterFromParcel(TimeBase timeBase, Parcel in)1384         public static @Nullable Counter readCounterFromParcel(TimeBase timeBase, Parcel in) {
1385             if (in.readInt() == 0) {
1386                 return null;
1387             }
1388             return new Counter(timeBase, in);
1389         }
1390 
1391         @Override
getCountLocked(int which)1392         public int getCountLocked(int which) {
1393             return mCount.get();
1394         }
1395 
logState(Printer pw, String prefix)1396         public void logState(Printer pw, String prefix) {
1397             pw.println(prefix + "mCount=" + mCount.get());
1398         }
1399 
1400         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
stepAtomic()1401         public void stepAtomic() {
1402             if (mTimeBase.isRunning()) {
1403                 mCount.incrementAndGet();
1404             }
1405         }
1406 
addAtomic(int delta)1407         void addAtomic(int delta) {
1408             if (mTimeBase.isRunning()) {
1409                 mCount.addAndGet(delta);
1410             }
1411         }
1412 
1413         /**
1414          * Clear state of this counter.
1415          */
1416         @Override
reset(boolean detachIfReset)1417         public boolean reset(boolean detachIfReset) {
1418             mCount.set(0);
1419             if (detachIfReset) {
1420                 detach();
1421             }
1422             return true;
1423         }
1424 
1425         @Override
detach()1426         public void detach() {
1427             mTimeBase.remove(this);
1428         }
1429 
1430         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
writeSummaryFromParcelLocked(Parcel out)1431         public void writeSummaryFromParcelLocked(Parcel out) {
1432             out.writeInt(mCount.get());
1433         }
1434 
1435         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
readSummaryFromParcelLocked(Parcel in)1436         public void readSummaryFromParcelLocked(Parcel in) {
1437             mCount.set(in.readInt());
1438         }
1439     }
1440 
1441     @VisibleForTesting
1442     public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
1443         final TimeBase mTimeBase;
1444         public long[] mCounts;
1445 
LongSamplingCounterArray(TimeBase timeBase, Parcel in)1446         private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
1447             mTimeBase = timeBase;
1448             mCounts = in.createLongArray();
1449             timeBase.add(this);
1450         }
1451 
LongSamplingCounterArray(TimeBase timeBase)1452         public LongSamplingCounterArray(TimeBase timeBase) {
1453             mTimeBase = timeBase;
1454             timeBase.add(this);
1455         }
1456 
writeToParcel(Parcel out)1457         private void writeToParcel(Parcel out) {
1458             out.writeLongArray(mCounts);
1459         }
1460 
1461         @Override
onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime)1462         public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) {
1463         }
1464 
1465         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1466         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1467         }
1468 
1469         @Override
getCountsLocked(int which)1470         public long[] getCountsLocked(int which) {
1471             return mCounts == null ? null : Arrays.copyOf(mCounts, mCounts.length);
1472         }
1473 
1474         @Override
logState(Printer pw, String prefix)1475         public void logState(Printer pw, String prefix) {
1476             pw.println(prefix + "mCounts=" + Arrays.toString(mCounts));
1477         }
1478 
addCountLocked(long[] counts)1479         public void addCountLocked(long[] counts) {
1480             addCountLocked(counts, mTimeBase.isRunning());
1481         }
1482 
addCountLocked(long[] counts, boolean isRunning)1483         public void addCountLocked(long[] counts, boolean isRunning) {
1484             if (counts == null) {
1485                 return;
1486             }
1487             if (isRunning) {
1488                 if (mCounts == null) {
1489                     mCounts = new long[counts.length];
1490                 }
1491                 for (int i = 0; i < counts.length; ++i) {
1492                     mCounts[i] += counts[i];
1493                 }
1494             }
1495         }
1496 
getSize()1497         public int getSize() {
1498             return mCounts == null ? 0 : mCounts.length;
1499         }
1500 
1501         /**
1502          * Clear state of this counter.
1503          */
1504         @Override
reset(boolean detachIfReset)1505         public boolean reset(boolean detachIfReset) {
1506             if (mCounts != null) {
1507                 Arrays.fill(mCounts, 0);
1508             }
1509             if (detachIfReset) {
1510                 detach();
1511             }
1512             return true;
1513         }
1514 
1515         @Override
detach()1516         public void detach() {
1517             mTimeBase.remove(this);
1518         }
1519 
writeSummaryToParcelLocked(Parcel out)1520         private void writeSummaryToParcelLocked(Parcel out) {
1521             out.writeLongArray(mCounts);
1522         }
1523 
readSummaryFromParcelLocked(Parcel in)1524         private void readSummaryFromParcelLocked(Parcel in) {
1525             mCounts = in.createLongArray();
1526         }
1527 
writeToParcel(Parcel out, LongSamplingCounterArray counterArray)1528         public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
1529             if (counterArray != null) {
1530                 out.writeInt(1);
1531                 counterArray.writeToParcel(out);
1532             } else {
1533                 out.writeInt(0);
1534             }
1535         }
1536 
readFromParcel(Parcel in, TimeBase timeBase)1537         public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
1538             if (in.readInt() != 0) {
1539                 return new LongSamplingCounterArray(timeBase, in);
1540             } else {
1541                 return null;
1542             }
1543         }
1544 
writeSummaryToParcelLocked(Parcel out, LongSamplingCounterArray counterArray)1545         public static void writeSummaryToParcelLocked(Parcel out,
1546                 LongSamplingCounterArray counterArray) {
1547             if (counterArray != null) {
1548                 out.writeInt(1);
1549                 counterArray.writeSummaryToParcelLocked(out);
1550             } else {
1551                 out.writeInt(0);
1552             }
1553         }
1554 
readSummaryFromParcelLocked(Parcel in, TimeBase timeBase)1555         public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
1556                 TimeBase timeBase) {
1557             if (in.readInt() != 0) {
1558                 final LongSamplingCounterArray counterArray
1559                         = new LongSamplingCounterArray(timeBase);
1560                 counterArray.readSummaryFromParcelLocked(in);
1561                 return counterArray;
1562             } else {
1563                 return null;
1564             }
1565         }
1566     }
1567 
1568     @VisibleForTesting
1569     public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
1570         final TimeBase mTimeBase;
1571         private long mCount;
1572 
LongSamplingCounter(TimeBase timeBase, Parcel in)1573         public LongSamplingCounter(TimeBase timeBase, Parcel in) {
1574             mTimeBase = timeBase;
1575             mCount = in.readLong();
1576             timeBase.add(this);
1577         }
1578 
LongSamplingCounter(TimeBase timeBase)1579         public LongSamplingCounter(TimeBase timeBase) {
1580             mTimeBase = timeBase;
1581             timeBase.add(this);
1582         }
1583 
writeToParcel(Parcel out)1584         public void writeToParcel(Parcel out) {
1585             out.writeLong(mCount);
1586         }
1587 
1588         @Override
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)1589         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1590         }
1591 
1592         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1593         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1594         }
1595 
getCountLocked(int which)1596         public long getCountLocked(int which) {
1597             return mCount;
1598         }
1599 
1600         @Override
logState(Printer pw, String prefix)1601         public void logState(Printer pw, String prefix) {
1602             pw.println(prefix + "mCount=" + mCount);
1603         }
1604 
addCountLocked(long count)1605         public void addCountLocked(long count) {
1606             addCountLocked(count, mTimeBase.isRunning());
1607         }
1608 
addCountLocked(long count, boolean isRunning)1609         public void addCountLocked(long count, boolean isRunning) {
1610             if (isRunning) {
1611                 mCount += count;
1612             }
1613         }
1614 
1615         /**
1616          * Clear state of this counter.
1617          */
1618         @Override
reset(boolean detachIfReset)1619         public boolean reset(boolean detachIfReset) {
1620             mCount = 0;
1621             if (detachIfReset) {
1622                 detach();
1623             }
1624             return true;
1625         }
1626 
1627         @Override
detach()1628         public void detach() {
1629             mTimeBase.remove(this);
1630         }
1631 
writeSummaryFromParcelLocked(Parcel out)1632         public void writeSummaryFromParcelLocked(Parcel out) {
1633             out.writeLong(mCount);
1634         }
1635 
readSummaryFromParcelLocked(Parcel in)1636         public void readSummaryFromParcelLocked(Parcel in) {
1637             mCount = in.readLong();
1638         }
1639     }
1640 
1641     /**
1642      * State for keeping track of timing information.
1643      */
1644     public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
1645         protected final Clocks mClocks;
1646         protected final int mType;
1647         protected final TimeBase mTimeBase;
1648 
1649         protected int mCount;
1650 
1651         // Times are in microseconds for better accuracy when dividing by the
1652         // lock count, and are in "battery realtime" units.
1653 
1654         /**
1655          * The total time we have accumulated since the start of the original
1656          * boot, to the last time something interesting happened in the
1657          * current run.
1658          */
1659         protected long mTotalTime;
1660 
1661         /**
1662          * The total time this timer has been running until the latest mark has been set.
1663          * Subtract this from mTotalTime to get the time spent running since the mark was set.
1664          */
1665         protected long mTimeBeforeMark;
1666 
1667         /**
1668          * Constructs from a parcel.
1669          * @param type
1670          * @param timeBase
1671          * @param in
1672          */
Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in)1673         public Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in) {
1674             mClocks = clocks;
1675             mType = type;
1676             mTimeBase = timeBase;
1677 
1678             mCount = in.readInt();
1679             mTotalTime = in.readLong();
1680             mTimeBeforeMark = in.readLong();
1681             timeBase.add(this);
1682             if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTime);
1683         }
1684 
Timer(Clocks clocks, int type, TimeBase timeBase)1685         public Timer(Clocks clocks, int type, TimeBase timeBase) {
1686             mClocks = clocks;
1687             mType = type;
1688             mTimeBase = timeBase;
1689             timeBase.add(this);
1690         }
1691 
writeToParcel(Parcel out, long elapsedRealtimeUs)1692         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1693             if (DEBUG) {
1694                 Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
1695                         + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
1696             }
1697             out.writeInt(computeCurrentCountLocked());
1698             out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
1699             out.writeLong(mTimeBeforeMark);
1700         }
1701 
computeRunTimeLocked(long curBatteryRealtime)1702         protected abstract long computeRunTimeLocked(long curBatteryRealtime);
1703 
computeCurrentCountLocked()1704         protected abstract int computeCurrentCountLocked();
1705 
1706         /**
1707          * Clear state of this timer.  Returns true if the timer is inactive
1708          * so can be completely dropped.
1709          */
1710         @Override
reset(boolean detachIfReset)1711         public boolean reset(boolean detachIfReset) {
1712             mTotalTime = mTimeBeforeMark = 0;
1713             mCount = 0;
1714             if (detachIfReset) {
1715                 detach();
1716             }
1717             return true;
1718         }
1719 
1720         @Override
detach()1721         public void detach() {
1722             mTimeBase.remove(this);
1723         }
1724 
1725         @Override
onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime)1726         public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) {
1727         }
1728 
1729         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1730         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1731             if (DEBUG && mType < 0) {
1732                 Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtime
1733                         + " old mTotalTime=" + mTotalTime);
1734             }
1735             mTotalTime = computeRunTimeLocked(baseRealtime);
1736             mCount = computeCurrentCountLocked();
1737             if (DEBUG && mType < 0) {
1738                 Log.v(TAG, "plug #" + mType + ": new mTotalTime=" + mTotalTime);
1739             }
1740         }
1741 
1742         /**
1743          * Writes a possibly null Timer to a Parcel.
1744          *
1745          * @param out the Parcel to be written to.
1746          * @param timer a Timer, or null.
1747          */
1748         @UnsupportedAppUsage
writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs)1749         public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
1750             if (timer == null) {
1751                 out.writeInt(0); // indicates null
1752                 return;
1753             }
1754             out.writeInt(1); // indicates non-null
1755             timer.writeToParcel(out, elapsedRealtimeUs);
1756         }
1757 
1758         @Override
1759         @UnsupportedAppUsage
getTotalTimeLocked(long elapsedRealtimeUs, int which)1760         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
1761             return computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1762         }
1763 
1764         @Override
1765         @UnsupportedAppUsage
getCountLocked(int which)1766         public int getCountLocked(int which) {
1767             return computeCurrentCountLocked();
1768         }
1769 
1770         @Override
getTimeSinceMarkLocked(long elapsedRealtimeUs)1771         public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
1772             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1773             return val - mTimeBeforeMark;
1774         }
1775 
1776         @Override
logState(Printer pw, String prefix)1777         public void logState(Printer pw, String prefix) {
1778             pw.println(prefix + "mCount=" + mCount);
1779             pw.println(prefix + "mTotalTime=" + mTotalTime);
1780         }
1781 
1782 
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)1783         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
1784             long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1785             out.writeLong(runTime);
1786             out.writeInt(computeCurrentCountLocked());
1787         }
1788 
readSummaryFromParcelLocked(Parcel in)1789         public void readSummaryFromParcelLocked(Parcel in) {
1790             // Multiply by 1000 for backwards compatibility
1791             mTotalTime = in.readLong();
1792             mCount = in.readInt();
1793             // When reading the summary, we set the mark to be the latest information.
1794             mTimeBeforeMark = mTotalTime;
1795         }
1796     }
1797 
1798     /**
1799      * A counter meant to accept monotonically increasing values to its {@link #update(long, int)}
1800      * method. The state of the timer according to its {@link TimeBase} will determine how much
1801      * of the value is recorded.
1802      *
1803      * If the value being recorded resets, {@link #endSample()} can be called in order to
1804      * account for the change. If the value passed in to {@link #update(long, int)} decreased
1805      * between calls, the {@link #endSample()} is automatically called and the new value is
1806      * expected to increase monotonically from that point on.
1807      */
1808     public static class SamplingTimer extends Timer {
1809 
1810         /**
1811          * The most recent reported count from /proc/wakelocks.
1812          */
1813         int mCurrentReportedCount;
1814 
1815         /**
1816          * The reported count from /proc/wakelocks when unplug() was last
1817          * called.
1818          */
1819         int mUnpluggedReportedCount;
1820 
1821         /**
1822          * The most recent reported total_time from /proc/wakelocks.
1823          */
1824         long mCurrentReportedTotalTime;
1825 
1826 
1827         /**
1828          * The reported total_time from /proc/wakelocks when unplug() was last
1829          * called.
1830          */
1831         long mUnpluggedReportedTotalTime;
1832 
1833         /**
1834          * Whether we are currently in a discharge cycle.
1835          */
1836         boolean mTimeBaseRunning;
1837 
1838         /**
1839          * Whether we are currently recording reported values.
1840          */
1841         boolean mTrackingReportedValues;
1842 
1843         /*
1844          * A sequence counter, incremented once for each update of the stats.
1845          */
1846         int mUpdateVersion;
1847 
1848         @VisibleForTesting
SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in)1849         public SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in) {
1850             super(clocks, 0, timeBase, in);
1851             mCurrentReportedCount = in.readInt();
1852             mUnpluggedReportedCount = in.readInt();
1853             mCurrentReportedTotalTime = in.readLong();
1854             mUnpluggedReportedTotalTime = in.readLong();
1855             mTrackingReportedValues = in.readInt() == 1;
1856             mTimeBaseRunning = timeBase.isRunning();
1857         }
1858 
1859         @VisibleForTesting
SamplingTimer(Clocks clocks, TimeBase timeBase)1860         public SamplingTimer(Clocks clocks, TimeBase timeBase) {
1861             super(clocks, 0, timeBase);
1862             mTrackingReportedValues = false;
1863             mTimeBaseRunning = timeBase.isRunning();
1864         }
1865 
1866         /**
1867          * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to
1868          * be less than the values used for a previous invocation.
1869          */
endSample()1870         public void endSample() {
1871             mTotalTime = computeRunTimeLocked(0 /* unused by us */);
1872             mCount = computeCurrentCountLocked();
1873             mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = 0;
1874             mUnpluggedReportedCount = mCurrentReportedCount = 0;
1875             mTrackingReportedValues = false;
1876         }
1877 
setUpdateVersion(int version)1878         public void setUpdateVersion(int version) {
1879             mUpdateVersion = version;
1880         }
1881 
getUpdateVersion()1882         public int getUpdateVersion() {
1883             return mUpdateVersion;
1884         }
1885 
1886         /**
1887          * Updates the current recorded values. These are meant to be monotonically increasing
1888          * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}.
1889          *
1890          * If the values being recorded have been reset, the monotonically increasing requirement
1891          * will be broken. In this case, {@link #endSample()} is automatically called and
1892          * the total value of totalTime and count are recorded, starting a new monotonically
1893          * increasing sample.
1894          *
1895          * @param totalTime total time of sample in microseconds.
1896          * @param count total number of times the event being sampled occurred.
1897          */
update(long totalTime, int count)1898         public void update(long totalTime, int count) {
1899             if (mTimeBaseRunning && !mTrackingReportedValues) {
1900                 // Updating the reported value for the first time.
1901                 mUnpluggedReportedTotalTime = totalTime;
1902                 mUnpluggedReportedCount = count;
1903             }
1904 
1905             mTrackingReportedValues = true;
1906 
1907             if (totalTime < mCurrentReportedTotalTime || count < mCurrentReportedCount) {
1908                 endSample();
1909             }
1910 
1911             mCurrentReportedTotalTime = totalTime;
1912             mCurrentReportedCount = count;
1913         }
1914 
1915         /**
1916          * Adds deltaTime and deltaCount to the current sample.
1917          *
1918          * @param deltaTime additional time recorded since the last sampled event, in microseconds.
1919          * @param deltaCount additional number of times the event being sampled occurred.
1920          */
add(long deltaTime, int deltaCount)1921         public void add(long deltaTime, int deltaCount) {
1922             update(mCurrentReportedTotalTime + deltaTime, mCurrentReportedCount + deltaCount);
1923         }
1924 
1925         @Override
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)1926         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1927             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
1928             if (mTrackingReportedValues) {
1929                 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
1930                 mUnpluggedReportedCount = mCurrentReportedCount;
1931             }
1932             mTimeBaseRunning = true;
1933         }
1934 
1935         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1936         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1937             super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
1938             mTimeBaseRunning = false;
1939         }
1940 
1941         @Override
logState(Printer pw, String prefix)1942         public void logState(Printer pw, String prefix) {
1943             super.logState(pw, prefix);
1944             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
1945                     + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
1946                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
1947                     + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
1948         }
1949 
1950         @Override
computeRunTimeLocked(long curBatteryRealtime)1951         protected long computeRunTimeLocked(long curBatteryRealtime) {
1952             return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues
1953                     ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
1954         }
1955 
1956         @Override
computeCurrentCountLocked()1957         protected int computeCurrentCountLocked() {
1958             return mCount + (mTimeBaseRunning && mTrackingReportedValues
1959                     ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
1960         }
1961 
1962         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)1963         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1964             super.writeToParcel(out, elapsedRealtimeUs);
1965             out.writeInt(mCurrentReportedCount);
1966             out.writeInt(mUnpluggedReportedCount);
1967             out.writeLong(mCurrentReportedTotalTime);
1968             out.writeLong(mUnpluggedReportedTotalTime);
1969             out.writeInt(mTrackingReportedValues ? 1 : 0);
1970         }
1971 
1972         @Override
reset(boolean detachIfReset)1973         public boolean reset(boolean detachIfReset) {
1974             super.reset(detachIfReset);
1975             mTrackingReportedValues = false;
1976             mUnpluggedReportedTotalTime = 0;
1977             mUnpluggedReportedCount = 0;
1978             return true;
1979         }
1980     }
1981 
1982     /**
1983      * A timer that increments in batches.  It does not run for durations, but just jumps
1984      * for a pre-determined amount.
1985      */
1986     public static class BatchTimer extends Timer {
1987         final Uid mUid;
1988 
1989         /**
1990          * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
1991          */
1992         long mLastAddedTime;
1993 
1994         /**
1995          * The last duration that we added to the timer.  This is in microseconds.
1996          */
1997         long mLastAddedDuration;
1998 
1999         /**
2000          * Whether we are currently in a discharge cycle.
2001          */
2002         boolean mInDischarge;
2003 
BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in)2004         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in) {
2005             super(clocks, type, timeBase, in);
2006             mUid = uid;
2007             mLastAddedTime = in.readLong();
2008             mLastAddedDuration = in.readLong();
2009             mInDischarge = timeBase.isRunning();
2010         }
2011 
BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase)2012         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase) {
2013             super(clocks, type, timeBase);
2014             mUid = uid;
2015             mInDischarge = timeBase.isRunning();
2016         }
2017 
2018         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2019         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2020             super.writeToParcel(out, elapsedRealtimeUs);
2021             out.writeLong(mLastAddedTime);
2022             out.writeLong(mLastAddedDuration);
2023         }
2024 
2025         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)2026         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
2027             recomputeLastDuration(mClocks.elapsedRealtime() * 1000, false);
2028             mInDischarge = false;
2029             super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
2030         }
2031 
2032         @Override
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)2033         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
2034             recomputeLastDuration(elapsedRealtime, false);
2035             mInDischarge = true;
2036             // If we are still within the last added duration, then re-added whatever remains.
2037             if (mLastAddedTime == elapsedRealtime) {
2038                 mTotalTime += mLastAddedDuration;
2039             }
2040             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
2041         }
2042 
2043         @Override
logState(Printer pw, String prefix)2044         public void logState(Printer pw, String prefix) {
2045             super.logState(pw, prefix);
2046             pw.println(prefix + "mLastAddedTime=" + mLastAddedTime
2047                     + " mLastAddedDuration=" + mLastAddedDuration);
2048         }
2049 
computeOverage(long curTime)2050         private long computeOverage(long curTime) {
2051             if (mLastAddedTime > 0) {
2052                 return mLastAddedDuration - curTime;
2053             }
2054             return 0;
2055         }
2056 
recomputeLastDuration(long curTime, boolean abort)2057         private void recomputeLastDuration(long curTime, boolean abort) {
2058             final long overage = computeOverage(curTime);
2059             if (overage > 0) {
2060                 // Aborting before the duration ran out -- roll back the remaining
2061                 // duration.  Only do this if currently discharging; otherwise we didn't
2062                 // actually add the time.
2063                 if (mInDischarge) {
2064                     mTotalTime -= overage;
2065                 }
2066                 if (abort) {
2067                     mLastAddedTime = 0;
2068                 } else {
2069                     mLastAddedTime = curTime;
2070                     mLastAddedDuration -= overage;
2071                 }
2072             }
2073         }
2074 
addDuration(BatteryStatsImpl stats, long durationMillis)2075         public void addDuration(BatteryStatsImpl stats, long durationMillis) {
2076             final long now = mClocks.elapsedRealtime() * 1000;
2077             recomputeLastDuration(now, true);
2078             mLastAddedTime = now;
2079             mLastAddedDuration = durationMillis * 1000;
2080             if (mInDischarge) {
2081                 mTotalTime += mLastAddedDuration;
2082                 mCount++;
2083             }
2084         }
2085 
abortLastDuration(BatteryStatsImpl stats)2086         public void abortLastDuration(BatteryStatsImpl stats) {
2087             final long now = mClocks.elapsedRealtime() * 1000;
2088             recomputeLastDuration(now, true);
2089         }
2090 
2091         @Override
computeCurrentCountLocked()2092         protected int computeCurrentCountLocked() {
2093             return mCount;
2094         }
2095 
2096         @Override
computeRunTimeLocked(long curBatteryRealtime)2097         protected long computeRunTimeLocked(long curBatteryRealtime) {
2098             final long overage = computeOverage(mClocks.elapsedRealtime() * 1000);
2099             if (overage > 0) {
2100                 return mTotalTime = overage;
2101             }
2102             return mTotalTime;
2103         }
2104 
2105         @Override
reset(boolean detachIfReset)2106         public boolean reset(boolean detachIfReset) {
2107             final long now = mClocks.elapsedRealtime() * 1000;
2108             recomputeLastDuration(now, true);
2109             boolean stillActive = mLastAddedTime == now;
2110             super.reset(!stillActive && detachIfReset);
2111             return !stillActive;
2112         }
2113     }
2114 
2115 
2116     /**
2117      * A StopwatchTimer that also tracks the total and max individual
2118      * time spent active according to the given timebase.  Whereas
2119      * StopwatchTimer apportions the time amongst all in the pool,
2120      * the total and max durations are not apportioned.
2121      */
2122     public static class DurationTimer extends StopwatchTimer {
2123         /**
2124          * The time (in ms) that the timer was last acquired or the time base
2125          * last (re-)started. Increasing the nesting depth does not reset this time.
2126          *
2127          * -1 if the timer is currently not running or the time base is not running.
2128          *
2129          * If written to a parcel, the start time is reset, as is mNesting in the base class
2130          * StopwatchTimer.
2131          */
2132         long mStartTimeMs = -1;
2133 
2134         /**
2135          * The longest time period (in ms) that the timer has been active. Not pooled.
2136          */
2137         long mMaxDurationMs;
2138 
2139         /**
2140          * The time (in ms) that that the timer has been active since most recent
2141          * stopRunningLocked() or reset(). Not pooled.
2142          */
2143         long mCurrentDurationMs;
2144 
2145         /**
2146          * The total time (in ms) that that the timer has been active since most recent reset()
2147          * prior to the current startRunningLocked. This is the sum of all past currentDurations
2148          * (but not including the present currentDuration) since reset. Not pooled.
2149          */
2150         long mTotalDurationMs;
2151 
DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)2152         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2153                 TimeBase timeBase, Parcel in) {
2154             super(clocks, uid, type, timerPool, timeBase, in);
2155             mMaxDurationMs = in.readLong();
2156             mTotalDurationMs = in.readLong();
2157             mCurrentDurationMs = in.readLong();
2158         }
2159 
DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)2160         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2161                 TimeBase timeBase) {
2162             super(clocks, uid, type, timerPool, timeBase);
2163         }
2164 
2165         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2166         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2167             super.writeToParcel(out, elapsedRealtimeUs);
2168             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2169             out.writeLong(mTotalDurationMs);
2170             out.writeLong(getCurrentDurationMsLocked(elapsedRealtimeUs / 1000));
2171         }
2172 
2173         /**
2174          * Write the summary to the parcel.
2175          *
2176          * Since the time base is probably meaningless after we come back, reading
2177          * from this will have the effect of stopping the timer. So here all we write
2178          * is the max and total durations.
2179          */
2180         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2181         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2182             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2183             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2184             out.writeLong(getTotalDurationMsLocked(elapsedRealtimeUs / 1000));
2185         }
2186 
2187         /**
2188          * Read the summary parcel.
2189          *
2190          * Has the side effect of stopping the timer.
2191          */
2192         @Override
readSummaryFromParcelLocked(Parcel in)2193         public void readSummaryFromParcelLocked(Parcel in) {
2194             super.readSummaryFromParcelLocked(in);
2195             mMaxDurationMs = in.readLong();
2196             mTotalDurationMs = in.readLong();
2197             mStartTimeMs = -1;
2198             mCurrentDurationMs = 0;
2199         }
2200 
2201         /**
2202          * The TimeBase time started (again).
2203          *
2204          * If the timer is also running, store the start time.
2205          */
onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime)2206         public void onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime) {
2207             super.onTimeStarted(elapsedRealtimeUs, baseUptime, baseRealtime);
2208             if (mNesting > 0) {
2209                 mStartTimeMs = baseRealtime / 1000;
2210             }
2211         }
2212 
2213         /**
2214          * The TimeBase stopped running.
2215          *
2216          * If the timer is running, add the duration into mCurrentDurationMs.
2217          */
2218         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtimeUs)2219         public void onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtimeUs) {
2220             super.onTimeStopped(elapsedRealtimeUs, baseUptime, baseRealtimeUs);
2221             if (mNesting > 0) {
2222                 // baseRealtimeUs has already been converted to the timebase's realtime.
2223                 mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
2224             }
2225             mStartTimeMs = -1;
2226         }
2227 
2228         @Override
logState(Printer pw, String prefix)2229         public void logState(Printer pw, String prefix) {
2230             super.logState(pw, prefix);
2231         }
2232 
2233         @Override
startRunningLocked(long elapsedRealtimeMs)2234         public void startRunningLocked(long elapsedRealtimeMs) {
2235             super.startRunningLocked(elapsedRealtimeMs);
2236             if (mNesting == 1 && mTimeBase.isRunning()) {
2237                 // Just started
2238                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000;
2239             }
2240         }
2241 
2242         /**
2243          * Decrements the mNesting ref-count on this timer.
2244          *
2245          * If it actually stopped (mNesting went to 0), then possibly update
2246          * mMaxDuration if the current duration was the longest ever.
2247          */
2248         @Override
stopRunningLocked(long elapsedRealtimeMs)2249         public void stopRunningLocked(long elapsedRealtimeMs) {
2250             if (mNesting == 1) {
2251                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2252                 mTotalDurationMs += durationMs;
2253                 if (durationMs > mMaxDurationMs) {
2254                     mMaxDurationMs = durationMs;
2255                 }
2256                 mStartTimeMs = -1;
2257                 mCurrentDurationMs = 0;
2258             }
2259             // super method decrements mNesting, which getCurrentDurationMsLocked relies on,
2260             // so call super.stopRunningLocked after calling getCurrentDurationMsLocked.
2261             super.stopRunningLocked(elapsedRealtimeMs);
2262         }
2263 
2264         @Override
reset(boolean detachIfReset)2265         public boolean reset(boolean detachIfReset) {
2266             boolean result = super.reset(detachIfReset);
2267             mMaxDurationMs = 0;
2268             mTotalDurationMs = 0;
2269             mCurrentDurationMs = 0;
2270             if (mNesting > 0) {
2271                 mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000) / 1000;
2272             } else {
2273                 mStartTimeMs = -1;
2274             }
2275             return result;
2276         }
2277 
2278         /**
2279          * Returns the max duration that this timer has ever seen.
2280          *
2281          * Note that this time is NOT split between the timers in the timer group that
2282          * this timer is attached to.  It is the TOTAL time.
2283          */
2284         @Override
getMaxDurationMsLocked(long elapsedRealtimeMs)2285         public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
2286             if (mNesting > 0) {
2287                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2288                 if (durationMs > mMaxDurationMs) {
2289                     return durationMs;
2290                 }
2291             }
2292             return mMaxDurationMs;
2293         }
2294 
2295         /**
2296          * Returns the time since the timer was started.
2297          * Returns 0 if the timer is not currently running.
2298          *
2299          * Note that this time is NOT split between the timers in the timer group that
2300          * this timer is attached to.  It is the TOTAL time.
2301          *
2302          * Note that if running timer is parceled and unparceled, this method will return
2303          * current duration value at the time of parceling even though timer may not be
2304          * currently running.
2305          */
2306         @Override
getCurrentDurationMsLocked(long elapsedRealtimeMs)2307         public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
2308             long durationMs = mCurrentDurationMs;
2309             if (mNesting > 0 && mTimeBase.isRunning()) {
2310                 durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000)
2311                         - mStartTimeMs;
2312             }
2313             return durationMs;
2314         }
2315 
2316         /**
2317          * Returns the total cumulative duration that this timer has been on since reset().
2318          * If mTimerPool == null, this should be the same
2319          * as getTotalTimeLocked(elapsedRealtimeMs*1000, STATS_SINCE_CHARGED)/1000.
2320          *
2321          * Note that this time is NOT split between the timers in the timer group that
2322          * this timer is attached to.  It is the TOTAL time. For this reason, if mTimerPool != null,
2323          * the result will not be equivalent to getTotalTimeLocked.
2324          */
2325         @Override
getTotalDurationMsLocked(long elapsedRealtimeMs)2326         public long getTotalDurationMsLocked(long elapsedRealtimeMs) {
2327             return mTotalDurationMs + getCurrentDurationMsLocked(elapsedRealtimeMs);
2328         }
2329     }
2330 
2331     /**
2332      * State for keeping track of timing information.
2333      */
2334     public static class StopwatchTimer extends Timer {
2335         final Uid mUid;
2336         final ArrayList<StopwatchTimer> mTimerPool;
2337 
2338         int mNesting;
2339 
2340         /**
2341          * The last time at which we updated the timer.  If mNesting is > 0,
2342          * subtract this from the current battery time to find the amount of
2343          * time we have been running since we last computed an update.
2344          */
2345         long mUpdateTime;
2346 
2347         /**
2348          * The total time at which the timer was acquired, to determine if it
2349          * was actually held for an interesting duration. If time base was not running when timer
2350          * was acquired, will be -1.
2351          */
2352         long mAcquireTime = -1;
2353 
2354         long mTimeout;
2355 
2356         /**
2357          * For partial wake locks, keep track of whether we are in the list
2358          * to consume CPU cycles.
2359          */
2360         @VisibleForTesting
2361         public boolean mInList;
2362 
StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)2363         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2364                 TimeBase timeBase, Parcel in) {
2365             super(clocks, type, timeBase, in);
2366             mUid = uid;
2367             mTimerPool = timerPool;
2368             mUpdateTime = in.readLong();
2369         }
2370 
StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)2371         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2372                 TimeBase timeBase) {
2373             super(clocks, type, timeBase);
2374             mUid = uid;
2375             mTimerPool = timerPool;
2376         }
2377 
setTimeout(long timeout)2378         public void setTimeout(long timeout) {
2379             mTimeout = timeout;
2380         }
2381 
writeToParcel(Parcel out, long elapsedRealtimeUs)2382         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2383             super.writeToParcel(out, elapsedRealtimeUs);
2384             out.writeLong(mUpdateTime);
2385         }
2386 
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)2387         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
2388             if (mNesting > 0) {
2389                 if (DEBUG && mType < 0) {
2390                     Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
2391                 }
2392                 super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
2393                 mUpdateTime = baseRealtime;
2394                 if (DEBUG && mType < 0) {
2395                     Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
2396                 }
2397             }
2398         }
2399 
logState(Printer pw, String prefix)2400         public void logState(Printer pw, String prefix) {
2401             super.logState(pw, prefix);
2402             pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTime
2403                     + " mAcquireTime=" + mAcquireTime);
2404         }
2405 
startRunningLocked(long elapsedRealtimeMs)2406         public void startRunningLocked(long elapsedRealtimeMs) {
2407             if (mNesting++ == 0) {
2408                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2409                 mUpdateTime = batteryRealtime;
2410                 if (mTimerPool != null) {
2411                     // Accumulate time to all currently active timers before adding
2412                     // this new one to the pool.
2413                     refreshTimersLocked(batteryRealtime, mTimerPool, null);
2414                     // Add this timer to the active pool
2415                     mTimerPool.add(this);
2416                 }
2417                 if (mTimeBase.isRunning()) {
2418                     // Increment the count
2419                     mCount++;
2420                     mAcquireTime = mTotalTime;
2421                 } else {
2422                     mAcquireTime = -1;
2423                 }
2424                 if (DEBUG && mType < 0) {
2425                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
2426                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
2427                             + " mAcquireTime=" + mAcquireTime);
2428                 }
2429             }
2430         }
2431 
isRunningLocked()2432         public boolean isRunningLocked() {
2433             return mNesting > 0;
2434         }
2435 
stopRunningLocked(long elapsedRealtimeMs)2436         public void stopRunningLocked(long elapsedRealtimeMs) {
2437             // Ignore attempt to stop a timer that isn't running
2438             if (mNesting == 0) {
2439                 return;
2440             }
2441             if (--mNesting == 0) {
2442                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2443                 if (mTimerPool != null) {
2444                     // Accumulate time to all active counters, scaled by the total
2445                     // active in the pool, before taking this one out of the pool.
2446                     refreshTimersLocked(batteryRealtime, mTimerPool, null);
2447                     // Remove this timer from the active pool
2448                     mTimerPool.remove(this);
2449                 } else {
2450                     mNesting = 1;
2451                     mTotalTime = computeRunTimeLocked(batteryRealtime);
2452                     mNesting = 0;
2453                 }
2454 
2455                 if (DEBUG && mType < 0) {
2456                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
2457                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
2458                             + " mAcquireTime=" + mAcquireTime);
2459                 }
2460 
2461                 if (mAcquireTime >= 0 && mTotalTime == mAcquireTime) {
2462                     // If there was no change in the time, then discard this
2463                     // count.  A somewhat cheezy strategy, but hey.
2464                     mCount--;
2465                 }
2466             }
2467         }
2468 
stopAllRunningLocked(long elapsedRealtimeMs)2469         public void stopAllRunningLocked(long elapsedRealtimeMs) {
2470             if (mNesting > 0) {
2471                 mNesting = 1;
2472                 stopRunningLocked(elapsedRealtimeMs);
2473             }
2474         }
2475 
2476         // Update the total time for all other running Timers with the same type as this Timer
2477         // due to a change in timer count
refreshTimersLocked(long batteryRealtime, final ArrayList<StopwatchTimer> pool, StopwatchTimer self)2478         private static long refreshTimersLocked(long batteryRealtime,
2479                 final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
2480             long selfTime = 0;
2481             final int N = pool.size();
2482             for (int i=N-1; i>= 0; i--) {
2483                 final StopwatchTimer t = pool.get(i);
2484                 long heldTime = batteryRealtime - t.mUpdateTime;
2485                 if (heldTime > 0) {
2486                     final long myTime = heldTime / N;
2487                     if (t == self) {
2488                         selfTime = myTime;
2489                     }
2490                     t.mTotalTime += myTime;
2491                 }
2492                 t.mUpdateTime = batteryRealtime;
2493             }
2494             return selfTime;
2495         }
2496 
2497         @Override
computeRunTimeLocked(long curBatteryRealtime)2498         protected long computeRunTimeLocked(long curBatteryRealtime) {
2499             if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) {
2500                 curBatteryRealtime = mUpdateTime + mTimeout;
2501             }
2502             return mTotalTime + (mNesting > 0
2503                     ? (curBatteryRealtime - mUpdateTime)
2504                             / (mTimerPool != null ? mTimerPool.size() : 1)
2505                     : 0);
2506         }
2507 
2508         @Override
computeCurrentCountLocked()2509         protected int computeCurrentCountLocked() {
2510             return mCount;
2511         }
2512 
2513         @Override
reset(boolean detachIfReset)2514         public boolean reset(boolean detachIfReset) {
2515             boolean canDetach = mNesting <= 0;
2516             super.reset(canDetach && detachIfReset);
2517             if (mNesting > 0) {
2518                 mUpdateTime = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000);
2519             }
2520             mAcquireTime = -1; // to ensure mCount isn't decreased to -1 if timer is stopped later.
2521             return canDetach;
2522         }
2523 
2524         @Override
2525         @UnsupportedAppUsage
detach()2526         public void detach() {
2527             super.detach();
2528             if (mTimerPool != null) {
2529                 mTimerPool.remove(this);
2530             }
2531         }
2532 
2533         @Override
readSummaryFromParcelLocked(Parcel in)2534         public void readSummaryFromParcelLocked(Parcel in) {
2535             super.readSummaryFromParcelLocked(in);
2536             mNesting = 0;
2537         }
2538 
2539         /**
2540          * Set the mark so that we can query later for the total time the timer has
2541          * accumulated since this point. The timer can be running or not.
2542          *
2543          * @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
2544          */
setMark(long elapsedRealtimeMs)2545         public void setMark(long elapsedRealtimeMs) {
2546             final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2547             if (mNesting > 0) {
2548                 // We are running.
2549                 if (mTimerPool != null) {
2550                     refreshTimersLocked(batteryRealtime, mTimerPool, this);
2551                 } else {
2552                     mTotalTime += batteryRealtime - mUpdateTime;
2553                     mUpdateTime = batteryRealtime;
2554                 }
2555             }
2556             mTimeBeforeMark = mTotalTime;
2557         }
2558     }
2559 
2560     /**
2561      * State for keeping track of two DurationTimers with different TimeBases, presumably where one
2562      * TimeBase is effectively a subset of the other.
2563      */
2564     public static class DualTimer extends DurationTimer {
2565         // This class both is a DurationTimer and also holds a second DurationTimer.
2566         // The main timer (this) typically tracks the total time. It may be pooled (but since it's a
2567         // durationTimer, it also has the unpooled getTotalDurationMsLocked() for
2568         // STATS_SINCE_CHARGED).
2569         // mSubTimer typically tracks only part of the total time, such as background time, as
2570         // determined by a subTimeBase. It is NOT pooled.
2571         private final DurationTimer mSubTimer;
2572 
2573         /**
2574          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2575          * The main timer (this) is based on the given timeBase and timerPool.
2576          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2577          * the main timer is.
2578          */
DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase, Parcel in)2579         public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2580                 TimeBase timeBase, TimeBase subTimeBase, Parcel in) {
2581             super(clocks, uid, type, timerPool, timeBase, in);
2582             mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase, in);
2583         }
2584 
2585         /**
2586          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2587          * The main timer (this) is based on the given timeBase and timerPool.
2588          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2589          * the main timer is.
2590          */
DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase)2591         public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2592                 TimeBase timeBase, TimeBase subTimeBase) {
2593             super(clocks, uid, type, timerPool, timeBase);
2594             mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase);
2595         }
2596 
2597         /** Get the secondary timer. */
2598         @Override
getSubTimer()2599         public DurationTimer getSubTimer() {
2600             return mSubTimer;
2601         }
2602 
2603         @Override
startRunningLocked(long elapsedRealtimeMs)2604         public void startRunningLocked(long elapsedRealtimeMs) {
2605             super.startRunningLocked(elapsedRealtimeMs);
2606             mSubTimer.startRunningLocked(elapsedRealtimeMs);
2607         }
2608 
2609         @Override
stopRunningLocked(long elapsedRealtimeMs)2610         public void stopRunningLocked(long elapsedRealtimeMs) {
2611             super.stopRunningLocked(elapsedRealtimeMs);
2612             mSubTimer.stopRunningLocked(elapsedRealtimeMs);
2613         }
2614 
2615         @Override
stopAllRunningLocked(long elapsedRealtimeMs)2616         public void stopAllRunningLocked(long elapsedRealtimeMs) {
2617             super.stopAllRunningLocked(elapsedRealtimeMs);
2618             mSubTimer.stopAllRunningLocked(elapsedRealtimeMs);
2619         }
2620 
2621         @Override
reset(boolean detachIfReset)2622         public boolean reset(boolean detachIfReset) {
2623             boolean active = false;
2624             // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
2625             active |= !mSubTimer.reset(false);
2626             active |= !super.reset(detachIfReset);
2627             return !active;
2628         }
2629 
2630         @Override
detach()2631         public void detach() {
2632             mSubTimer.detach();
2633             super.detach();
2634         }
2635 
2636         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2637         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2638             super.writeToParcel(out, elapsedRealtimeUs);
2639             mSubTimer.writeToParcel(out, elapsedRealtimeUs);
2640         }
2641 
2642         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2643         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2644             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2645             mSubTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2646         }
2647 
2648         @Override
readSummaryFromParcelLocked(Parcel in)2649         public void readSummaryFromParcelLocked(Parcel in) {
2650             super.readSummaryFromParcelLocked(in);
2651             mSubTimer.readSummaryFromParcelLocked(in);
2652         }
2653     }
2654 
2655 
2656     public abstract class OverflowArrayMap<T> {
2657         private static final String OVERFLOW_NAME = "*overflow*";
2658 
2659         final int mUid;
2660         final ArrayMap<String, T> mMap = new ArrayMap<>();
2661         T mCurOverflow;
2662         ArrayMap<String, MutableInt> mActiveOverflow;
2663         long mLastOverflowTime;
2664         long mLastOverflowFinishTime;
2665         long mLastClearTime;
2666         long mLastCleanupTime;
2667 
OverflowArrayMap(int uid)2668         public OverflowArrayMap(int uid) {
2669             mUid = uid;
2670         }
2671 
getMap()2672         public ArrayMap<String, T> getMap() {
2673             return mMap;
2674         }
2675 
clear()2676         public void clear() {
2677             mLastClearTime = SystemClock.elapsedRealtime();
2678             mMap.clear();
2679             mCurOverflow = null;
2680             mActiveOverflow = null;
2681         }
2682 
add(String name, T obj)2683         public void add(String name, T obj) {
2684             if (name == null) {
2685                 name = "";
2686             }
2687             mMap.put(name, obj);
2688             if (OVERFLOW_NAME.equals(name)) {
2689                 mCurOverflow = obj;
2690             }
2691         }
2692 
cleanup()2693         public void cleanup() {
2694             mLastCleanupTime = SystemClock.elapsedRealtime();
2695             if (mActiveOverflow != null) {
2696                 if (mActiveOverflow.size() == 0) {
2697                     mActiveOverflow = null;
2698                 }
2699             }
2700             if (mActiveOverflow == null) {
2701                 // There is no currently active overflow, so we should no longer have
2702                 // an overflow entry.
2703                 if (mMap.containsKey(OVERFLOW_NAME)) {
2704                     Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
2705                             + mMap.get(OVERFLOW_NAME));
2706                     mMap.remove(OVERFLOW_NAME);
2707                 }
2708                 mCurOverflow = null;
2709             } else {
2710                 // There is currently active overflow, so we should still have an overflow entry.
2711                 if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
2712                     Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
2713                             + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
2714                 }
2715             }
2716         }
2717 
startObject(String name)2718         public T startObject(String name) {
2719             if (name == null) {
2720                 name = "";
2721             }
2722             T obj = mMap.get(name);
2723             if (obj != null) {
2724                 return obj;
2725             }
2726 
2727             // No object exists for the given name, but do we currently have it
2728             // running as part of the overflow?
2729             if (mActiveOverflow != null) {
2730                 MutableInt over = mActiveOverflow.get(name);
2731                 if (over != null) {
2732                     // We are already actively counting this name in the overflow object.
2733                     obj = mCurOverflow;
2734                     if (obj == null) {
2735                         // Shouldn't be here, but we'll try to recover.
2736                         Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
2737                         obj = mCurOverflow = instantiateObject();
2738                         mMap.put(OVERFLOW_NAME, obj);
2739                     }
2740                     over.value++;
2741                     return obj;
2742                 }
2743             }
2744 
2745             // No object exists for given name nor in the overflow; we need to make
2746             // a new one.
2747             final int N = mMap.size();
2748             if (N >= MAX_WAKELOCKS_PER_UID) {
2749                 // Went over the limit on number of objects to track; this one goes
2750                 // in to the overflow.
2751                 obj = mCurOverflow;
2752                 if (obj == null) {
2753                     // Need to start overflow now...
2754                     obj = mCurOverflow = instantiateObject();
2755                     mMap.put(OVERFLOW_NAME, obj);
2756                 }
2757                 if (mActiveOverflow == null) {
2758                     mActiveOverflow = new ArrayMap<>();
2759                 }
2760                 mActiveOverflow.put(name, new MutableInt(1));
2761                 mLastOverflowTime = SystemClock.elapsedRealtime();
2762                 return obj;
2763             }
2764 
2765             // Normal case where we just need to make a new object.
2766             obj = instantiateObject();
2767             mMap.put(name, obj);
2768             return obj;
2769         }
2770 
stopObject(String name)2771         public T stopObject(String name) {
2772             if (name == null) {
2773                 name = "";
2774             }
2775             T obj = mMap.get(name);
2776             if (obj != null) {
2777                 return obj;
2778             }
2779 
2780             // No object exists for the given name, but do we currently have it
2781             // running as part of the overflow?
2782             if (mActiveOverflow != null) {
2783                 MutableInt over = mActiveOverflow.get(name);
2784                 if (over != null) {
2785                     // We are already actively counting this name in the overflow object.
2786                     obj = mCurOverflow;
2787                     if (obj != null) {
2788                         over.value--;
2789                         if (over.value <= 0) {
2790                             mActiveOverflow.remove(name);
2791                             mLastOverflowFinishTime = SystemClock.elapsedRealtime();
2792                         }
2793                         return obj;
2794                     }
2795                 }
2796             }
2797 
2798             // Huh, they are stopping an active operation but we can't find one!
2799             // That's not good.
2800             StringBuilder sb = new StringBuilder();
2801             sb.append("Unable to find object for ");
2802             sb.append(name);
2803             sb.append(" in uid ");
2804             sb.append(mUid);
2805             sb.append(" mapsize=");
2806             sb.append(mMap.size());
2807             sb.append(" activeoverflow=");
2808             sb.append(mActiveOverflow);
2809             sb.append(" curoverflow=");
2810             sb.append(mCurOverflow);
2811             long now = SystemClock.elapsedRealtime();
2812             if (mLastOverflowTime != 0) {
2813                 sb.append(" lastOverflowTime=");
2814                 TimeUtils.formatDuration(mLastOverflowTime-now, sb);
2815             }
2816             if (mLastOverflowFinishTime != 0) {
2817                 sb.append(" lastOverflowFinishTime=");
2818                 TimeUtils.formatDuration(mLastOverflowFinishTime-now, sb);
2819             }
2820             if (mLastClearTime != 0) {
2821                 sb.append(" lastClearTime=");
2822                 TimeUtils.formatDuration(mLastClearTime-now, sb);
2823             }
2824             if (mLastCleanupTime != 0) {
2825                 sb.append(" lastCleanupTime=");
2826                 TimeUtils.formatDuration(mLastCleanupTime-now, sb);
2827             }
2828             Slog.wtf(TAG, sb.toString());
2829             return null;
2830         }
2831 
instantiateObject()2832         public abstract T instantiateObject();
2833     }
2834 
2835     public static class ControllerActivityCounterImpl extends ControllerActivityCounter
2836             implements Parcelable {
2837         private final LongSamplingCounter mIdleTimeMillis;
2838         private final LongSamplingCounter mScanTimeMillis;
2839         private final LongSamplingCounter mSleepTimeMillis;
2840         private final LongSamplingCounter mRxTimeMillis;
2841         private final LongSamplingCounter[] mTxTimeMillis;
2842         private final LongSamplingCounter mPowerDrainMaMs;
2843         private final LongSamplingCounter mMonitoredRailChargeConsumedMaMs;
2844 
ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates)2845         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates) {
2846             mIdleTimeMillis = new LongSamplingCounter(timeBase);
2847             mScanTimeMillis = new LongSamplingCounter(timeBase);
2848             mSleepTimeMillis = new LongSamplingCounter(timeBase);
2849             mRxTimeMillis = new LongSamplingCounter(timeBase);
2850             mTxTimeMillis = new LongSamplingCounter[numTxStates];
2851             for (int i = 0; i < numTxStates; i++) {
2852                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase);
2853             }
2854             mPowerDrainMaMs = new LongSamplingCounter(timeBase);
2855             mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase);
2856         }
2857 
ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in)2858         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in) {
2859             mIdleTimeMillis = new LongSamplingCounter(timeBase, in);
2860             mScanTimeMillis = new LongSamplingCounter(timeBase, in);
2861             mSleepTimeMillis = new LongSamplingCounter(timeBase, in);
2862             mRxTimeMillis = new LongSamplingCounter(timeBase, in);
2863             final int recordedTxStates = in.readInt();
2864             if (recordedTxStates != numTxStates) {
2865                 throw new ParcelFormatException("inconsistent tx state lengths");
2866             }
2867 
2868             mTxTimeMillis = new LongSamplingCounter[numTxStates];
2869             for (int i = 0; i < numTxStates; i++) {
2870                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase, in);
2871             }
2872             mPowerDrainMaMs = new LongSamplingCounter(timeBase, in);
2873             mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase, in);
2874         }
2875 
readSummaryFromParcel(Parcel in)2876         public void readSummaryFromParcel(Parcel in) {
2877             mIdleTimeMillis.readSummaryFromParcelLocked(in);
2878             mScanTimeMillis.readSummaryFromParcelLocked(in);
2879             mSleepTimeMillis.readSummaryFromParcelLocked(in);
2880             mRxTimeMillis.readSummaryFromParcelLocked(in);
2881             final int recordedTxStates = in.readInt();
2882             if (recordedTxStates != mTxTimeMillis.length) {
2883                 throw new ParcelFormatException("inconsistent tx state lengths");
2884             }
2885             for (LongSamplingCounter counter : mTxTimeMillis) {
2886                 counter.readSummaryFromParcelLocked(in);
2887             }
2888             mPowerDrainMaMs.readSummaryFromParcelLocked(in);
2889             mMonitoredRailChargeConsumedMaMs.readSummaryFromParcelLocked(in);
2890         }
2891 
2892         @Override
describeContents()2893         public int describeContents() {
2894             return 0;
2895         }
2896 
writeSummaryToParcel(Parcel dest)2897         public void writeSummaryToParcel(Parcel dest) {
2898             mIdleTimeMillis.writeSummaryFromParcelLocked(dest);
2899             mScanTimeMillis.writeSummaryFromParcelLocked(dest);
2900             mSleepTimeMillis.writeSummaryFromParcelLocked(dest);
2901             mRxTimeMillis.writeSummaryFromParcelLocked(dest);
2902             dest.writeInt(mTxTimeMillis.length);
2903             for (LongSamplingCounter counter : mTxTimeMillis) {
2904                 counter.writeSummaryFromParcelLocked(dest);
2905             }
2906             mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
2907             mMonitoredRailChargeConsumedMaMs.writeSummaryFromParcelLocked(dest);
2908         }
2909 
2910         @Override
writeToParcel(Parcel dest, int flags)2911         public void writeToParcel(Parcel dest, int flags) {
2912             mIdleTimeMillis.writeToParcel(dest);
2913             mScanTimeMillis.writeToParcel(dest);
2914             mSleepTimeMillis.writeToParcel(dest);
2915             mRxTimeMillis.writeToParcel(dest);
2916             dest.writeInt(mTxTimeMillis.length);
2917             for (LongSamplingCounter counter : mTxTimeMillis) {
2918                 counter.writeToParcel(dest);
2919             }
2920             mPowerDrainMaMs.writeToParcel(dest);
2921             mMonitoredRailChargeConsumedMaMs.writeToParcel(dest);
2922         }
2923 
reset(boolean detachIfReset)2924         public void reset(boolean detachIfReset) {
2925             mIdleTimeMillis.reset(detachIfReset);
2926             mScanTimeMillis.reset(detachIfReset);
2927             mSleepTimeMillis.reset(detachIfReset);
2928             mRxTimeMillis.reset(detachIfReset);
2929             for (LongSamplingCounter counter : mTxTimeMillis) {
2930                 counter.reset(detachIfReset);
2931             }
2932             mPowerDrainMaMs.reset(detachIfReset);
2933             mMonitoredRailChargeConsumedMaMs.reset(detachIfReset);
2934         }
2935 
detach()2936         public void detach() {
2937             mIdleTimeMillis.detach();
2938             mScanTimeMillis.detach();
2939             mSleepTimeMillis.detach();
2940             mRxTimeMillis.detach();
2941             for (LongSamplingCounter counter : mTxTimeMillis) {
2942                 counter.detach();
2943             }
2944             mPowerDrainMaMs.detach();
2945             mMonitoredRailChargeConsumedMaMs.detach();
2946         }
2947 
2948         /**
2949          * @return a LongSamplingCounter, measuring time spent in the idle state in
2950          * milliseconds.
2951          */
2952         @Override
getIdleTimeCounter()2953         public LongSamplingCounter getIdleTimeCounter() {
2954             return mIdleTimeMillis;
2955         }
2956 
2957         /**
2958          * @return a LongSamplingCounter, measuring time spent in the scan state in
2959          * milliseconds.
2960          */
2961         @Override
getScanTimeCounter()2962         public LongSamplingCounter getScanTimeCounter() {
2963             return mScanTimeMillis;
2964         }
2965 
2966         /**
2967          * @return a LongSamplingCounter, measuring time spent in the sleep state in
2968          * milliseconds.
2969          */
2970         @Override
getSleepTimeCounter()2971         public LongSamplingCounter getSleepTimeCounter() {
2972             return mSleepTimeMillis;
2973         }
2974 
2975         /**
2976          * @return a LongSamplingCounter, measuring time spent in the receive state in
2977          * milliseconds.
2978          */
2979         @Override
getRxTimeCounter()2980         public LongSamplingCounter getRxTimeCounter() {
2981             return mRxTimeMillis;
2982         }
2983 
2984         /**
2985          * @return a LongSamplingCounter[], measuring time spent in various transmit states in
2986          * milliseconds.
2987          */
2988         @Override
getTxTimeCounters()2989         public LongSamplingCounter[] getTxTimeCounters() {
2990             return mTxTimeMillis;
2991         }
2992 
2993         /**
2994          * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
2995          */
2996         @Override
getPowerCounter()2997         public LongSamplingCounter getPowerCounter() {
2998             return mPowerDrainMaMs;
2999         }
3000 
3001         /**
3002          * @return a LongSamplingCounter, measuring actual monitored rail energy consumed
3003          * milli-ampere milli-seconds (mAmS).
3004          */
3005         @Override
getMonitoredRailChargeConsumedMaMs()3006         public LongSamplingCounter getMonitoredRailChargeConsumedMaMs() {
3007             return mMonitoredRailChargeConsumedMaMs;
3008         }
3009     }
3010 
3011     /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */
getRpmTimerLocked(String name)3012     public SamplingTimer getRpmTimerLocked(String name) {
3013         SamplingTimer rpmt = mRpmStats.get(name);
3014         if (rpmt == null) {
3015             rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3016             mRpmStats.put(name, rpmt);
3017         }
3018         return rpmt;
3019     }
3020 
3021     /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */
getScreenOffRpmTimerLocked(String name)3022     public SamplingTimer getScreenOffRpmTimerLocked(String name) {
3023         SamplingTimer rpmt = mScreenOffRpmStats.get(name);
3024         if (rpmt == null) {
3025             rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
3026             mScreenOffRpmStats.put(name, rpmt);
3027         }
3028         return rpmt;
3029     }
3030 
3031     /*
3032      * Get the wakeup reason counter, and create a new one if one
3033      * doesn't already exist.
3034      */
getWakeupReasonTimerLocked(String name)3035     public SamplingTimer getWakeupReasonTimerLocked(String name) {
3036         SamplingTimer timer = mWakeupReasonStats.get(name);
3037         if (timer == null) {
3038             timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3039             mWakeupReasonStats.put(name, timer);
3040         }
3041         return timer;
3042     }
3043 
3044     /*
3045      * Get the KernelWakelockTimer associated with name, and create a new one if one
3046      * doesn't already exist.
3047      */
getKernelWakelockTimerLocked(String name)3048     public SamplingTimer getKernelWakelockTimerLocked(String name) {
3049         SamplingTimer kwlt = mKernelWakelockStats.get(name);
3050         if (kwlt == null) {
3051             kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
3052             mKernelWakelockStats.put(name, kwlt);
3053         }
3054         return kwlt;
3055     }
3056 
getKernelMemoryTimerLocked(long bucket)3057     public SamplingTimer getKernelMemoryTimerLocked(long bucket) {
3058         SamplingTimer kmt = mKernelMemoryStats.get(bucket);
3059         if (kmt == null) {
3060             kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3061             mKernelMemoryStats.put(bucket, kmt);
3062         }
3063         return kmt;
3064     }
3065 
writeHistoryTag(HistoryTag tag)3066     private int writeHistoryTag(HistoryTag tag) {
3067         Integer idxObj = mHistoryTagPool.get(tag);
3068         int idx;
3069         if (idxObj != null) {
3070             idx = idxObj;
3071         } else {
3072             idx = mNextHistoryTagIdx;
3073             HistoryTag key = new HistoryTag();
3074             key.setTo(tag);
3075             tag.poolIdx = idx;
3076             mHistoryTagPool.put(key, idx);
3077             mNextHistoryTagIdx++;
3078             mNumHistoryTagChars += key.string.length() + 1;
3079         }
3080         return idx;
3081     }
3082 
readHistoryTag(int index, HistoryTag tag)3083     private void readHistoryTag(int index, HistoryTag tag) {
3084         if (index < mReadHistoryStrings.length) {
3085             tag.string = mReadHistoryStrings[index];
3086             tag.uid = mReadHistoryUids[index];
3087         } else {
3088             tag.string = null;
3089             tag.uid = 0;
3090         }
3091         tag.poolIdx = index;
3092     }
3093 
3094     /*
3095         The history delta format uses flags to denote further data in subsequent ints in the parcel.
3096 
3097         There is always the first token, which may contain the delta time, or an indicator of
3098         the length of the time (int or long) following this token.
3099 
3100         First token: always present,
3101         31              23              15               7             0
3102         █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█
3103 
3104         T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
3105            follows containing the time, and 0x7ffff indicates a long immediately follows with the
3106            delta time.
3107         A: battery level changed and an int follows with battery data.
3108         B: state changed and an int follows with state change data.
3109         C: state2 has changed and an int follows with state2 change data.
3110         D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
3111         E: event data has changed and an event struct follows.
3112         F: battery charge in coulombs has changed and an int with the charge follows.
3113         G: state flag denoting that the mobile radio was active.
3114         H: state flag denoting that the wifi radio was active.
3115         I: state flag denoting that a wifi scan occurred.
3116         J: state flag denoting that a wifi full lock was held.
3117         K: state flag denoting that the gps was on.
3118         L: state flag denoting that a wakelock was held.
3119         M: state flag denoting that the cpu was running.
3120 
3121         Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
3122         with the time delta.
3123 
3124         Battery level int: if A in the first token is set,
3125         31              23              15               7             0
3126         █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█
3127 
3128         D: indicates that extra history details follow.
3129         V: the battery voltage.
3130         T: the battery temperature.
3131         L: the battery level (out of 100).
3132 
3133         State change int: if B in the first token is set,
3134         31              23              15               7             0
3135         █S|S|S|H|H|H|P|P█F|E|D|C|B| | |A█ | | | | | | | █ | | | | | | | █
3136 
3137         A: wifi multicast was on.
3138         B: battery was plugged in.
3139         C: screen was on.
3140         D: phone was scanning for signal.
3141         E: audio was on.
3142         F: a sensor was active.
3143 
3144         State2 change int: if C in the first token is set,
3145         31              23              15               7             0
3146         █M|L|K|J|I|H|H|G█F|E|D|C| | | | █ | | | | | | | █ |B|B|B|A|A|A|A█
3147 
3148         A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
3149         B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
3150         C: a bluetooth scan was active.
3151         D: the camera was active.
3152         E: bluetooth was on.
3153         F: a phone call was active.
3154         G: the device was charging.
3155         H: 2 bits indicating the device-idle (doze) state: off, light, full
3156         I: the flashlight was on.
3157         J: wifi was on.
3158         K: wifi was running.
3159         L: video was playing.
3160         M: power save mode was on.
3161 
3162         Wakelock/wakereason struct: if D in the first token is set,
3163         TODO(adamlesinski): describe wakelock/wakereason struct.
3164 
3165         Event struct: if E in the first token is set,
3166         TODO(adamlesinski): describe the event struct.
3167 
3168         History step details struct: if D in the battery level int is set,
3169         TODO(adamlesinski): describe the history step details struct.
3170 
3171         Battery charge int: if F in the first token is set, an int representing the battery charge
3172         in coulombs follows.
3173      */
3174 
3175     // Part of initial delta int that specifies the time delta.
3176     static final int DELTA_TIME_MASK = 0x7ffff;
3177     static final int DELTA_TIME_LONG = 0x7ffff;   // The delta is a following long
3178     static final int DELTA_TIME_INT = 0x7fffe;    // The delta is a following int
3179     static final int DELTA_TIME_ABS = 0x7fffd;    // Following is an entire abs update.
3180     // Flag in delta int: a new battery level int follows.
3181     static final int DELTA_BATTERY_LEVEL_FLAG               = 0x00080000;
3182     // Flag in delta int: a new full state and battery status int follows.
3183     static final int DELTA_STATE_FLAG                       = 0x00100000;
3184     // Flag in delta int: a new full state2 int follows.
3185     static final int DELTA_STATE2_FLAG                      = 0x00200000;
3186     // Flag in delta int: contains a wakelock or wakeReason tag.
3187     static final int DELTA_WAKELOCK_FLAG                    = 0x00400000;
3188     // Flag in delta int: contains an event description.
3189     static final int DELTA_EVENT_FLAG                       = 0x00800000;
3190     // Flag in delta int: contains the battery charge count in uAh.
3191     static final int DELTA_BATTERY_CHARGE_FLAG              = 0x01000000;
3192     // These upper bits are the frequently changing state bits.
3193     static final int DELTA_STATE_MASK                       = 0xfe000000;
3194 
3195     // These are the pieces of battery state that are packed in to the upper bits of
3196     // the state int that have been packed in to the first delta int.  They must fit
3197     // in STATE_BATTERY_MASK.
3198     static final int STATE_BATTERY_MASK         = 0xff000000;
3199     static final int STATE_BATTERY_STATUS_MASK  = 0x00000007;
3200     static final int STATE_BATTERY_STATUS_SHIFT = 29;
3201     static final int STATE_BATTERY_HEALTH_MASK  = 0x00000007;
3202     static final int STATE_BATTERY_HEALTH_SHIFT = 26;
3203     static final int STATE_BATTERY_PLUG_MASK    = 0x00000003;
3204     static final int STATE_BATTERY_PLUG_SHIFT   = 24;
3205 
3206     // We use the low bit of the battery state int to indicate that we have full details
3207     // from a battery level change.
3208     static final int BATTERY_DELTA_LEVEL_FLAG   = 0x00000001;
3209 
writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last)3210     public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
3211         if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
3212             dest.writeInt(DELTA_TIME_ABS);
3213             cur.writeToParcel(dest, 0);
3214             return;
3215         }
3216 
3217         final long deltaTime = cur.time - last.time;
3218         final int lastBatteryLevelInt = buildBatteryLevelInt(last);
3219         final int lastStateInt = buildStateInt(last);
3220 
3221         int deltaTimeToken;
3222         if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
3223             deltaTimeToken = DELTA_TIME_LONG;
3224         } else if (deltaTime >= DELTA_TIME_ABS) {
3225             deltaTimeToken = DELTA_TIME_INT;
3226         } else {
3227             deltaTimeToken = (int)deltaTime;
3228         }
3229         int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
3230         final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
3231                 ? BATTERY_DELTA_LEVEL_FLAG : 0;
3232         final boolean computeStepDetails = includeStepDetails != 0
3233                 || mLastHistoryStepDetails == null;
3234         final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
3235         final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
3236         if (batteryLevelIntChanged) {
3237             firstToken |= DELTA_BATTERY_LEVEL_FLAG;
3238         }
3239         final int stateInt = buildStateInt(cur);
3240         final boolean stateIntChanged = stateInt != lastStateInt;
3241         if (stateIntChanged) {
3242             firstToken |= DELTA_STATE_FLAG;
3243         }
3244         final boolean state2IntChanged = cur.states2 != last.states2;
3245         if (state2IntChanged) {
3246             firstToken |= DELTA_STATE2_FLAG;
3247         }
3248         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
3249             firstToken |= DELTA_WAKELOCK_FLAG;
3250         }
3251         if (cur.eventCode != HistoryItem.EVENT_NONE) {
3252             firstToken |= DELTA_EVENT_FLAG;
3253         }
3254 
3255         final boolean batteryChargeChanged = cur.batteryChargeUAh != last.batteryChargeUAh;
3256         if (batteryChargeChanged) {
3257             firstToken |= DELTA_BATTERY_CHARGE_FLAG;
3258         }
3259         dest.writeInt(firstToken);
3260         if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
3261                 + " deltaTime=" + deltaTime);
3262 
3263         if (deltaTimeToken >= DELTA_TIME_INT) {
3264             if (deltaTimeToken == DELTA_TIME_INT) {
3265                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
3266                 dest.writeInt((int)deltaTime);
3267             } else {
3268                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
3269                 dest.writeLong(deltaTime);
3270             }
3271         }
3272         if (batteryLevelIntChanged) {
3273             dest.writeInt(batteryLevelInt);
3274             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
3275                     + Integer.toHexString(batteryLevelInt)
3276                     + " batteryLevel=" + cur.batteryLevel
3277                     + " batteryTemp=" + cur.batteryTemperature
3278                     + " batteryVolt=" + (int)cur.batteryVoltage);
3279         }
3280         if (stateIntChanged) {
3281             dest.writeInt(stateInt);
3282             if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
3283                     + Integer.toHexString(stateInt)
3284                     + " batteryStatus=" + cur.batteryStatus
3285                     + " batteryHealth=" + cur.batteryHealth
3286                     + " batteryPlugType=" + cur.batteryPlugType
3287                     + " states=0x" + Integer.toHexString(cur.states));
3288         }
3289         if (state2IntChanged) {
3290             dest.writeInt(cur.states2);
3291             if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x"
3292                     + Integer.toHexString(cur.states2));
3293         }
3294         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
3295             int wakeLockIndex;
3296             int wakeReasonIndex;
3297             if (cur.wakelockTag != null) {
3298                 wakeLockIndex = writeHistoryTag(cur.wakelockTag);
3299                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
3300                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
3301             } else {
3302                 wakeLockIndex = 0xffff;
3303             }
3304             if (cur.wakeReasonTag != null) {
3305                 wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
3306                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
3307                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
3308             } else {
3309                 wakeReasonIndex = 0xffff;
3310             }
3311             dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
3312         }
3313         if (cur.eventCode != HistoryItem.EVENT_NONE) {
3314             int index = writeHistoryTag(cur.eventTag);
3315             int codeAndIndex = (cur.eventCode&0xffff) | (index<<16);
3316             dest.writeInt(codeAndIndex);
3317             if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
3318                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
3319                     + cur.eventTag.string);
3320         }
3321         if (computeStepDetails) {
3322             if (mPlatformIdleStateCallback != null) {
3323                 mCurHistoryStepDetails.statPlatformIdleState =
3324                         mPlatformIdleStateCallback.getPlatformLowPowerStats();
3325                 if (DEBUG) Slog.i(TAG, "WRITE PlatformIdleState:" +
3326                         mCurHistoryStepDetails.statPlatformIdleState);
3327 
3328                 mCurHistoryStepDetails.statSubsystemPowerState =
3329                         mPlatformIdleStateCallback.getSubsystemLowPowerStats();
3330                 if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
3331                         mCurHistoryStepDetails.statSubsystemPowerState);
3332 
3333             }
3334             computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
3335             if (includeStepDetails != 0) {
3336                 mCurHistoryStepDetails.writeToParcel(dest);
3337             }
3338             cur.stepDetails = mCurHistoryStepDetails;
3339             mLastHistoryStepDetails = mCurHistoryStepDetails;
3340         } else {
3341             cur.stepDetails = null;
3342         }
3343         if (mLastHistoryStepLevel < cur.batteryLevel) {
3344             mLastHistoryStepDetails = null;
3345         }
3346         mLastHistoryStepLevel = cur.batteryLevel;
3347 
3348         if (batteryChargeChanged) {
3349             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUAh=" + cur.batteryChargeUAh);
3350             dest.writeInt(cur.batteryChargeUAh);
3351         }
3352         dest.writeDouble(cur.modemRailChargeMah);
3353         dest.writeDouble(cur.wifiRailChargeMah);
3354     }
3355 
buildBatteryLevelInt(HistoryItem h)3356     private int buildBatteryLevelInt(HistoryItem h) {
3357         return ((((int)h.batteryLevel)<<25)&0xfe000000)
3358                 | ((((int)h.batteryTemperature)<<15)&0x01ff8000)
3359                 | ((((int)h.batteryVoltage)<<1)&0x00007ffe);
3360     }
3361 
readBatteryLevelInt(int batteryLevelInt, HistoryItem out)3362     private void readBatteryLevelInt(int batteryLevelInt, HistoryItem out) {
3363         out.batteryLevel = (byte)((batteryLevelInt & 0xfe000000) >>> 25);
3364         out.batteryTemperature = (short)((batteryLevelInt & 0x01ff8000) >>> 15);
3365         out.batteryVoltage = (char)((batteryLevelInt & 0x00007ffe) >>> 1);
3366     }
3367 
buildStateInt(HistoryItem h)3368     private int buildStateInt(HistoryItem h) {
3369         int plugType = 0;
3370         if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
3371             plugType = 1;
3372         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
3373             plugType = 2;
3374         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
3375             plugType = 3;
3376         }
3377         return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT)
3378                 | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT)
3379                 | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT)
3380                 | (h.states&(~STATE_BATTERY_MASK));
3381     }
3382 
computeHistoryStepDetails(final HistoryStepDetails out, final HistoryStepDetails last)3383     private void computeHistoryStepDetails(final HistoryStepDetails out,
3384             final HistoryStepDetails last) {
3385         final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
3386 
3387         // Perform a CPU update right after we do this collection, so we have started
3388         // collecting good data for the next step.
3389         requestImmediateCpuUpdate();
3390 
3391         if (last == null) {
3392             // We are not generating a delta, so all we need to do is reset the stats
3393             // we will later be doing a delta from.
3394             final int NU = mUidStats.size();
3395             for (int i=0; i<NU; i++) {
3396                 final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3397                 uid.mLastStepUserTime = uid.mCurStepUserTime;
3398                 uid.mLastStepSystemTime = uid.mCurStepSystemTime;
3399             }
3400             mLastStepCpuUserTime = mCurStepCpuUserTime;
3401             mLastStepCpuSystemTime = mCurStepCpuSystemTime;
3402             mLastStepStatUserTime = mCurStepStatUserTime;
3403             mLastStepStatSystemTime = mCurStepStatSystemTime;
3404             mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
3405             mLastStepStatIrqTime = mCurStepStatIrqTime;
3406             mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
3407             mLastStepStatIdleTime = mCurStepStatIdleTime;
3408             tmp.clear();
3409             return;
3410         }
3411         if (DEBUG) {
3412             Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTime + " sys="
3413                     + mLastStepStatSystemTime + " io=" + mLastStepStatIOWaitTime
3414                     + " irq=" + mLastStepStatIrqTime + " sirq="
3415                     + mLastStepStatSoftIrqTime + " idle=" + mLastStepStatIdleTime);
3416             Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTime + " sys="
3417                     + mCurStepStatSystemTime + " io=" + mCurStepStatIOWaitTime
3418                     + " irq=" + mCurStepStatIrqTime + " sirq="
3419                     + mCurStepStatSoftIrqTime + " idle=" + mCurStepStatIdleTime);
3420         }
3421         out.userTime = (int)(mCurStepCpuUserTime - mLastStepCpuUserTime);
3422         out.systemTime = (int)(mCurStepCpuSystemTime - mLastStepCpuSystemTime);
3423         out.statUserTime = (int)(mCurStepStatUserTime - mLastStepStatUserTime);
3424         out.statSystemTime = (int)(mCurStepStatSystemTime - mLastStepStatSystemTime);
3425         out.statIOWaitTime = (int)(mCurStepStatIOWaitTime - mLastStepStatIOWaitTime);
3426         out.statIrqTime = (int)(mCurStepStatIrqTime - mLastStepStatIrqTime);
3427         out.statSoftIrqTime = (int)(mCurStepStatSoftIrqTime - mLastStepStatSoftIrqTime);
3428         out.statIdlTime = (int)(mCurStepStatIdleTime - mLastStepStatIdleTime);
3429         out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
3430         out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
3431         out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
3432         final int NU = mUidStats.size();
3433         for (int i=0; i<NU; i++) {
3434             final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3435             final int totalUTime = (int)(uid.mCurStepUserTime - uid.mLastStepUserTime);
3436             final int totalSTime = (int)(uid.mCurStepSystemTime - uid.mLastStepSystemTime);
3437             final int totalTime = totalUTime + totalSTime;
3438             uid.mLastStepUserTime = uid.mCurStepUserTime;
3439             uid.mLastStepSystemTime = uid.mCurStepSystemTime;
3440             if (totalTime <= (out.appCpuUTime3+out.appCpuSTime3)) {
3441                 continue;
3442             }
3443             if (totalTime <= (out.appCpuUTime2+out.appCpuSTime2)) {
3444                 out.appCpuUid3 = uid.mUid;
3445                 out.appCpuUTime3 = totalUTime;
3446                 out.appCpuSTime3 = totalSTime;
3447             } else {
3448                 out.appCpuUid3 = out.appCpuUid2;
3449                 out.appCpuUTime3 = out.appCpuUTime2;
3450                 out.appCpuSTime3 = out.appCpuSTime2;
3451                 if (totalTime <= (out.appCpuUTime1+out.appCpuSTime1)) {
3452                     out.appCpuUid2 = uid.mUid;
3453                     out.appCpuUTime2 = totalUTime;
3454                     out.appCpuSTime2 = totalSTime;
3455                 } else {
3456                     out.appCpuUid2 = out.appCpuUid1;
3457                     out.appCpuUTime2 = out.appCpuUTime1;
3458                     out.appCpuSTime2 = out.appCpuSTime1;
3459                     out.appCpuUid1 = uid.mUid;
3460                     out.appCpuUTime1 = totalUTime;
3461                     out.appCpuSTime1 = totalSTime;
3462                 }
3463             }
3464         }
3465         mLastStepCpuUserTime = mCurStepCpuUserTime;
3466         mLastStepCpuSystemTime = mCurStepCpuSystemTime;
3467         mLastStepStatUserTime = mCurStepStatUserTime;
3468         mLastStepStatSystemTime = mCurStepStatSystemTime;
3469         mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
3470         mLastStepStatIrqTime = mCurStepStatIrqTime;
3471         mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
3472         mLastStepStatIdleTime = mCurStepStatIdleTime;
3473     }
3474 
readHistoryDelta(Parcel src, HistoryItem cur)3475     public void readHistoryDelta(Parcel src, HistoryItem cur) {
3476         int firstToken = src.readInt();
3477         int deltaTimeToken = firstToken&DELTA_TIME_MASK;
3478         cur.cmd = HistoryItem.CMD_UPDATE;
3479         cur.numReadInts = 1;
3480         if (DEBUG) Slog.i(TAG, "READ DELTA: firstToken=0x" + Integer.toHexString(firstToken)
3481                 + " deltaTimeToken=" + deltaTimeToken);
3482 
3483         if (deltaTimeToken < DELTA_TIME_ABS) {
3484             cur.time += deltaTimeToken;
3485         } else if (deltaTimeToken == DELTA_TIME_ABS) {
3486             cur.time = src.readLong();
3487             cur.numReadInts += 2;
3488             if (DEBUG) Slog.i(TAG, "READ DELTA: ABS time=" + cur.time);
3489             cur.readFromParcel(src);
3490             return;
3491         } else if (deltaTimeToken == DELTA_TIME_INT) {
3492             int delta = src.readInt();
3493             cur.time += delta;
3494             cur.numReadInts += 1;
3495             if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
3496         } else {
3497             long delta = src.readLong();
3498             if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
3499             cur.time += delta;
3500             cur.numReadInts += 2;
3501         }
3502 
3503         final int batteryLevelInt;
3504         if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
3505             batteryLevelInt = src.readInt();
3506             readBatteryLevelInt(batteryLevelInt, cur);
3507             cur.numReadInts += 1;
3508             if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x"
3509                     + Integer.toHexString(batteryLevelInt)
3510                     + " batteryLevel=" + cur.batteryLevel
3511                     + " batteryTemp=" + cur.batteryTemperature
3512                     + " batteryVolt=" + (int)cur.batteryVoltage);
3513         } else {
3514             batteryLevelInt = 0;
3515         }
3516 
3517         if ((firstToken&DELTA_STATE_FLAG) != 0) {
3518             int stateInt = src.readInt();
3519             cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~STATE_BATTERY_MASK));
3520             cur.batteryStatus = (byte)((stateInt>>STATE_BATTERY_STATUS_SHIFT)
3521                     & STATE_BATTERY_STATUS_MASK);
3522             cur.batteryHealth = (byte)((stateInt>>STATE_BATTERY_HEALTH_SHIFT)
3523                     & STATE_BATTERY_HEALTH_MASK);
3524             cur.batteryPlugType = (byte)((stateInt>>STATE_BATTERY_PLUG_SHIFT)
3525                     & STATE_BATTERY_PLUG_MASK);
3526             switch (cur.batteryPlugType) {
3527                 case 1:
3528                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_AC;
3529                     break;
3530                 case 2:
3531                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_USB;
3532                     break;
3533                 case 3:
3534                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
3535                     break;
3536             }
3537             cur.numReadInts += 1;
3538             if (DEBUG) Slog.i(TAG, "READ DELTA: stateToken=0x"
3539                     + Integer.toHexString(stateInt)
3540                     + " batteryStatus=" + cur.batteryStatus
3541                     + " batteryHealth=" + cur.batteryHealth
3542                     + " batteryPlugType=" + cur.batteryPlugType
3543                     + " states=0x" + Integer.toHexString(cur.states));
3544         } else {
3545             cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~STATE_BATTERY_MASK));
3546         }
3547 
3548         if ((firstToken&DELTA_STATE2_FLAG) != 0) {
3549             cur.states2 = src.readInt();
3550             if (DEBUG) Slog.i(TAG, "READ DELTA: states2=0x"
3551                     + Integer.toHexString(cur.states2));
3552         }
3553 
3554         if ((firstToken&DELTA_WAKELOCK_FLAG) != 0) {
3555             int indexes = src.readInt();
3556             int wakeLockIndex = indexes&0xffff;
3557             int wakeReasonIndex = (indexes>>16)&0xffff;
3558             if (wakeLockIndex != 0xffff) {
3559                 cur.wakelockTag = cur.localWakelockTag;
3560                 readHistoryTag(wakeLockIndex, cur.wakelockTag);
3561                 if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
3562                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
3563             } else {
3564                 cur.wakelockTag = null;
3565             }
3566             if (wakeReasonIndex != 0xffff) {
3567                 cur.wakeReasonTag = cur.localWakeReasonTag;
3568                 readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
3569                 if (DEBUG) Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
3570                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
3571             } else {
3572                 cur.wakeReasonTag = null;
3573             }
3574             cur.numReadInts += 1;
3575         } else {
3576             cur.wakelockTag = null;
3577             cur.wakeReasonTag = null;
3578         }
3579 
3580         if ((firstToken&DELTA_EVENT_FLAG) != 0) {
3581             cur.eventTag = cur.localEventTag;
3582             final int codeAndIndex = src.readInt();
3583             cur.eventCode = (codeAndIndex&0xffff);
3584             final int index = ((codeAndIndex>>16)&0xffff);
3585             readHistoryTag(index, cur.eventTag);
3586             cur.numReadInts += 1;
3587             if (DEBUG) Slog.i(TAG, "READ DELTA: event=" + cur.eventCode + " tag=#"
3588                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
3589                     + cur.eventTag.string);
3590         } else {
3591             cur.eventCode = HistoryItem.EVENT_NONE;
3592         }
3593 
3594         if ((batteryLevelInt&BATTERY_DELTA_LEVEL_FLAG) != 0) {
3595             cur.stepDetails = mReadHistoryStepDetails;
3596             cur.stepDetails.readFromParcel(src);
3597         } else {
3598             cur.stepDetails = null;
3599         }
3600 
3601         if ((firstToken&DELTA_BATTERY_CHARGE_FLAG) != 0) {
3602             cur.batteryChargeUAh = src.readInt();
3603         }
3604         cur.modemRailChargeMah = src.readDouble();
3605         cur.wifiRailChargeMah = src.readDouble();
3606     }
3607 
3608     @Override
commitCurrentHistoryBatchLocked()3609     public void commitCurrentHistoryBatchLocked() {
3610         mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
3611     }
3612 
createFakeHistoryEvents(long numEvents)3613     public void createFakeHistoryEvents(long numEvents) {
3614         for(long i = 0; i < numEvents; i++) {
3615             noteLongPartialWakelockStart("name1", "historyName1", 1000);
3616             noteLongPartialWakelockFinish("name1", "historyName1", 1000);
3617         }
3618     }
3619 
addHistoryBufferLocked(long elapsedRealtimeMs, HistoryItem cur)3620     void addHistoryBufferLocked(long elapsedRealtimeMs, HistoryItem cur) {
3621         if (!mHaveBatteryLevel || !mRecordingHistory) {
3622             return;
3623         }
3624 
3625         final long timeDiff = (mHistoryBaseTime+elapsedRealtimeMs) - mHistoryLastWritten.time;
3626         final int diffStates = mHistoryLastWritten.states^(cur.states&mActiveHistoryStates);
3627         final int diffStates2 = mHistoryLastWritten.states2^(cur.states2&mActiveHistoryStates2);
3628         final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
3629         final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
3630         if (DEBUG) Slog.i(TAG, "ADD: tdelta=" + timeDiff + " diff="
3631                 + Integer.toHexString(diffStates) + " lastDiff="
3632                 + Integer.toHexString(lastDiffStates) + " diff2="
3633                 + Integer.toHexString(diffStates2) + " lastDiff2="
3634                 + Integer.toHexString(lastDiffStates2));
3635         if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
3636                 && timeDiff < 1000 && (diffStates&lastDiffStates) == 0
3637                 && (diffStates2&lastDiffStates2) == 0
3638                 && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
3639                 && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
3640                 && mHistoryLastWritten.stepDetails == null
3641                 && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
3642                         || cur.eventCode == HistoryItem.EVENT_NONE)
3643                 && mHistoryLastWritten.batteryLevel == cur.batteryLevel
3644                 && mHistoryLastWritten.batteryStatus == cur.batteryStatus
3645                 && mHistoryLastWritten.batteryHealth == cur.batteryHealth
3646                 && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
3647                 && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
3648                 && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
3649             // We can merge this new change in with the last one.  Merging is
3650             // allowed as long as only the states have changed, and within those states
3651             // as long as no bit has changed both between now and the last entry, as
3652             // well as the last entry and the one before it (so we capture any toggles).
3653             if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
3654             mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
3655             mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
3656             mHistoryBufferLastPos = -1;
3657             elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTime;
3658             // If the last written history had a wakelock tag, we need to retain it.
3659             // Note that the condition above made sure that we aren't in a case where
3660             // both it and the current history item have a wakelock tag.
3661             if (mHistoryLastWritten.wakelockTag != null) {
3662                 cur.wakelockTag = cur.localWakelockTag;
3663                 cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
3664             }
3665             // If the last written history had a wake reason tag, we need to retain it.
3666             // Note that the condition above made sure that we aren't in a case where
3667             // both it and the current history item have a wakelock tag.
3668             if (mHistoryLastWritten.wakeReasonTag != null) {
3669                 cur.wakeReasonTag = cur.localWakeReasonTag;
3670                 cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
3671             }
3672             // If the last written history had an event, we need to retain it.
3673             // Note that the condition above made sure that we aren't in a case where
3674             // both it and the current history item have an event.
3675             if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
3676                 cur.eventCode = mHistoryLastWritten.eventCode;
3677                 cur.eventTag = cur.localEventTag;
3678                 cur.eventTag.setTo(mHistoryLastWritten.eventTag);
3679             }
3680             mHistoryLastWritten.setTo(mHistoryLastLastWritten);
3681         }
3682         final int dataSize = mHistoryBuffer.dataSize();
3683 
3684         if (dataSize >= mConstants.MAX_HISTORY_BUFFER) {
3685             //open a new history file.
3686             final long start = SystemClock.uptimeMillis();
3687             writeHistoryLocked(true);
3688             if (DEBUG) {
3689                 Slog.d(TAG, "addHistoryBufferLocked writeHistoryLocked takes ms:"
3690                         + (SystemClock.uptimeMillis() - start));
3691             }
3692             mBatteryStatsHistory.startNextFile();
3693             mHistoryBuffer.setDataSize(0);
3694             mHistoryBuffer.setDataPosition(0);
3695             mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
3696             mHistoryBufferLastPos = -1;
3697             final long elapsedRealtime = mClocks.elapsedRealtime();
3698             final long uptime = mClocks.uptimeMillis();
3699             HistoryItem newItem = new HistoryItem();
3700             newItem.setTo(cur);
3701             startRecordingHistory(elapsedRealtime, uptime, false);
3702             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, newItem);
3703             return;
3704         }
3705 
3706         if (dataSize == 0) {
3707             // The history is currently empty; we need it to start with a time stamp.
3708             cur.currentTime = System.currentTimeMillis();
3709             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
3710         }
3711         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3712     }
3713 
addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur)3714     private void addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur) {
3715         if (mIteratingHistory) {
3716             throw new IllegalStateException("Can't do this while iterating history!");
3717         }
3718         mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
3719         mHistoryLastLastWritten.setTo(mHistoryLastWritten);
3720         mHistoryLastWritten.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
3721         mHistoryLastWritten.states &= mActiveHistoryStates;
3722         mHistoryLastWritten.states2 &= mActiveHistoryStates2;
3723         writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
3724         mLastHistoryElapsedRealtime = elapsedRealtimeMs;
3725         cur.wakelockTag = null;
3726         cur.wakeReasonTag = null;
3727         cur.eventCode = HistoryItem.EVENT_NONE;
3728         cur.eventTag = null;
3729         if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
3730                 + " now " + mHistoryBuffer.dataPosition()
3731                 + " size is now " + mHistoryBuffer.dataSize());
3732     }
3733 
3734     int mChangedStates = 0;
3735     int mChangedStates2 = 0;
3736 
addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs)3737     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
3738         if (mTrackRunningHistoryElapsedRealtime != 0) {
3739             final long diffElapsed = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtime;
3740             final long diffUptime = uptimeMs - mTrackRunningHistoryUptime;
3741             if (diffUptime < (diffElapsed-20)) {
3742                 final long wakeElapsedTime = elapsedRealtimeMs - (diffElapsed - diffUptime);
3743                 mHistoryAddTmp.setTo(mHistoryLastWritten);
3744                 mHistoryAddTmp.wakelockTag = null;
3745                 mHistoryAddTmp.wakeReasonTag = null;
3746                 mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
3747                 mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
3748                 addHistoryRecordInnerLocked(wakeElapsedTime, mHistoryAddTmp);
3749             }
3750         }
3751         mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
3752         mTrackRunningHistoryElapsedRealtime = elapsedRealtimeMs;
3753         mTrackRunningHistoryUptime = uptimeMs;
3754         addHistoryRecordInnerLocked(elapsedRealtimeMs, mHistoryCur);
3755     }
3756 
addHistoryRecordInnerLocked(long elapsedRealtimeMs, HistoryItem cur)3757     void addHistoryRecordInnerLocked(long elapsedRealtimeMs, HistoryItem cur) {
3758         addHistoryBufferLocked(elapsedRealtimeMs, cur);
3759 
3760         if (!USE_OLD_HISTORY) {
3761             return;
3762         }
3763 
3764         if (!mHaveBatteryLevel || !mRecordingHistory) {
3765             return;
3766         }
3767 
3768         // If the current time is basically the same as the last time,
3769         // and no states have since the last recorded entry changed and
3770         // are now resetting back to their original value, then just collapse
3771         // into one record.
3772         if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE
3773                 && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+1000)
3774                 && ((mHistoryEnd.states^cur.states)&mChangedStates&mActiveHistoryStates) == 0
3775                 && ((mHistoryEnd.states2^cur.states2)&mChangedStates2&mActiveHistoryStates2) == 0) {
3776             // If the current is the same as the one before, then we no
3777             // longer need the entry.
3778             if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE
3779                     && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+500)
3780                     && mHistoryLastEnd.sameNonEvent(cur)) {
3781                 mHistoryLastEnd.next = null;
3782                 mHistoryEnd.next = mHistoryCache;
3783                 mHistoryCache = mHistoryEnd;
3784                 mHistoryEnd = mHistoryLastEnd;
3785                 mHistoryLastEnd = null;
3786             } else {
3787                 mChangedStates |= mHistoryEnd.states^(cur.states&mActiveHistoryStates);
3788                 mChangedStates2 |= mHistoryEnd.states^(cur.states2&mActiveHistoryStates2);
3789                 mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, cur);
3790             }
3791             return;
3792         }
3793 
3794         mChangedStates = 0;
3795         mChangedStates2 = 0;
3796         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3797     }
3798 
addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code, String name, int uid)3799     public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
3800             String name, int uid) {
3801         mHistoryCur.eventCode = code;
3802         mHistoryCur.eventTag = mHistoryCur.localEventTag;
3803         mHistoryCur.eventTag.string = name;
3804         mHistoryCur.eventTag.uid = uid;
3805         addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
3806     }
3807 
addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur)3808     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) {
3809         HistoryItem rec = mHistoryCache;
3810         if (rec != null) {
3811             mHistoryCache = rec.next;
3812         } else {
3813             rec = new HistoryItem();
3814         }
3815         rec.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
3816 
3817         addHistoryRecordLocked(rec);
3818     }
3819 
addHistoryRecordLocked(HistoryItem rec)3820     void addHistoryRecordLocked(HistoryItem rec) {
3821         mNumHistoryItems++;
3822         rec.next = null;
3823         mHistoryLastEnd = mHistoryEnd;
3824         if (mHistoryEnd != null) {
3825             mHistoryEnd.next = rec;
3826             mHistoryEnd = rec;
3827         } else {
3828             mHistory = mHistoryEnd = rec;
3829         }
3830     }
3831 
clearHistoryLocked()3832     void clearHistoryLocked() {
3833         if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
3834         if (USE_OLD_HISTORY) {
3835             if (mHistory != null) {
3836                 mHistoryEnd.next = mHistoryCache;
3837                 mHistoryCache = mHistory;
3838                 mHistory = mHistoryLastEnd = mHistoryEnd = null;
3839             }
3840             mNumHistoryItems = 0;
3841         }
3842 
3843         mHistoryBaseTime = 0;
3844         mLastHistoryElapsedRealtime = 0;
3845         mTrackRunningHistoryElapsedRealtime = 0;
3846         mTrackRunningHistoryUptime = 0;
3847 
3848         mHistoryBuffer.setDataSize(0);
3849         mHistoryBuffer.setDataPosition(0);
3850         mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
3851         mHistoryLastLastWritten.clear();
3852         mHistoryLastWritten.clear();
3853         mHistoryTagPool.clear();
3854         mNextHistoryTagIdx = 0;
3855         mNumHistoryTagChars = 0;
3856         mHistoryBufferLastPos = -1;
3857         mActiveHistoryStates = 0xffffffff;
3858         mActiveHistoryStates2 = 0xffffffff;
3859     }
3860 
3861     @GuardedBy("this")
updateTimeBasesLocked(boolean unplugged, int screenState, long uptime, long realtime)3862     public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptime,
3863             long realtime) {
3864         final boolean screenOff = !isScreenOn(screenState);
3865         final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
3866         final boolean updateOnBatteryScreenOffTimeBase =
3867                 (unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
3868 
3869         if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) {
3870             if (updateOnBatteryScreenOffTimeBase) {
3871                 updateKernelWakelocksLocked();
3872                 updateBatteryPropertiesLocked();
3873             }
3874             // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
3875             // updateRpmStatsLocked is too slow to run each screen change. When the speed is
3876             // improved, remove the surrounding if{}.
3877             if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
3878                 updateRpmStatsLocked(); // if either OnBattery or OnBatteryScreenOff timebase changes.
3879             }
3880             if (DEBUG_ENERGY_CPU) {
3881                 Slog.d(TAG, "Updating cpu time because screen is now "
3882                         + Display.stateToString(screenState)
3883                         + " and battery is " + (unplugged ? "on" : "off"));
3884             }
3885 
3886             mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime);
3887             if (updateOnBatteryTimeBase) {
3888                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
3889                     mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptime, realtime);
3890                 }
3891             }
3892             if (updateOnBatteryScreenOffTimeBase) {
3893                 mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff, uptime, realtime);
3894                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
3895                     mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptime, realtime);
3896                 }
3897             }
3898         }
3899     }
3900 
updateBatteryPropertiesLocked()3901     private void updateBatteryPropertiesLocked() {
3902         try {
3903             IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
3904                     ServiceManager.getService("batteryproperties"));
3905             if (registrar != null) {
3906                 registrar.scheduleUpdate();
3907             }
3908         } catch (RemoteException e) {
3909             // Ignore.
3910         }
3911     }
3912 
addIsolatedUidLocked(int isolatedUid, int appUid)3913     public void addIsolatedUidLocked(int isolatedUid, int appUid) {
3914         mIsolatedUids.put(isolatedUid, appUid);
3915         final Uid u = getUidStatsLocked(appUid);
3916         u.addIsolatedUid(isolatedUid);
3917     }
3918 
3919     /**
3920      * Schedules a read of the latest cpu times before removing the isolated UID.
3921      * @see #removeIsolatedUidLocked(int)
3922      */
scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid)3923     public void scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid) {
3924         int curUid = mIsolatedUids.get(isolatedUid, -1);
3925         if (curUid == appUid) {
3926             if (mExternalSync != null) {
3927                 mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
3928             }
3929         }
3930     }
3931 
3932     /**
3933      * This should only be called after the cpu times have been read.
3934      * @see #scheduleRemoveIsolatedUidLocked(int, int)
3935      */
3936     @GuardedBy("this")
removeIsolatedUidLocked(int isolatedUid)3937     public void removeIsolatedUidLocked(int isolatedUid) {
3938         final int idx = mIsolatedUids.indexOfKey(isolatedUid);
3939         if (idx >= 0) {
3940             final int ownerUid = mIsolatedUids.valueAt(idx);
3941             final Uid u = getUidStatsLocked(ownerUid);
3942             u.removeIsolatedUid(isolatedUid);
3943             mIsolatedUids.removeAt(idx);
3944         }
3945         mPendingRemovedUids.add(new UidToRemove(isolatedUid, mClocks.elapsedRealtime()));
3946     }
3947 
mapUid(int uid)3948     public int mapUid(int uid) {
3949         int isolated = mIsolatedUids.get(uid, -1);
3950         return isolated > 0 ? isolated : uid;
3951     }
3952 
noteEventLocked(int code, String name, int uid)3953     public void noteEventLocked(int code, String name, int uid) {
3954         uid = mapUid(uid);
3955         if (!mActiveEvents.updateState(code, name, uid, 0)) {
3956             return;
3957         }
3958         final long elapsedRealtime = mClocks.elapsedRealtime();
3959         final long uptime = mClocks.uptimeMillis();
3960         addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
3961     }
3962 
noteCurrentTimeChangedLocked()3963     public void noteCurrentTimeChangedLocked() {
3964         final long currentTime = System.currentTimeMillis();
3965         final long elapsedRealtime = mClocks.elapsedRealtime();
3966         final long uptime = mClocks.uptimeMillis();
3967         recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
3968     }
3969 
noteProcessStartLocked(String name, int uid)3970     public void noteProcessStartLocked(String name, int uid) {
3971         uid = mapUid(uid);
3972         if (isOnBattery()) {
3973             Uid u = getUidStatsLocked(uid);
3974             u.getProcessStatsLocked(name).incStartsLocked();
3975         }
3976         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
3977             return;
3978         }
3979         if (!mRecordAllHistory) {
3980             return;
3981         }
3982         final long elapsedRealtime = mClocks.elapsedRealtime();
3983         final long uptime = mClocks.uptimeMillis();
3984         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid);
3985     }
3986 
noteProcessCrashLocked(String name, int uid)3987     public void noteProcessCrashLocked(String name, int uid) {
3988         uid = mapUid(uid);
3989         if (isOnBattery()) {
3990             Uid u = getUidStatsLocked(uid);
3991             u.getProcessStatsLocked(name).incNumCrashesLocked();
3992         }
3993     }
3994 
noteProcessAnrLocked(String name, int uid)3995     public void noteProcessAnrLocked(String name, int uid) {
3996         uid = mapUid(uid);
3997         if (isOnBattery()) {
3998             Uid u = getUidStatsLocked(uid);
3999             u.getProcessStatsLocked(name).incNumAnrsLocked();
4000         }
4001     }
4002 
noteUidProcessStateLocked(int uid, int state)4003     public void noteUidProcessStateLocked(int uid, int state) {
4004         int parentUid = mapUid(uid);
4005         if (uid != parentUid) {
4006             // Isolated UIDs process state is already rolled up into parent, so no need to track
4007             // Otherwise the parent's process state will get downgraded incorrectly
4008             return;
4009         }
4010         getUidStatsLocked(uid).updateUidProcessStateLocked(state);
4011     }
4012 
noteProcessFinishLocked(String name, int uid)4013     public void noteProcessFinishLocked(String name, int uid) {
4014         uid = mapUid(uid);
4015         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
4016             return;
4017         }
4018         if (!mRecordAllHistory) {
4019             return;
4020         }
4021         final long elapsedRealtime = mClocks.elapsedRealtime();
4022         final long uptime = mClocks.uptimeMillis();
4023         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
4024     }
4025 
noteSyncStartLocked(String name, int uid)4026     public void noteSyncStartLocked(String name, int uid) {
4027         uid = mapUid(uid);
4028         final long elapsedRealtime = mClocks.elapsedRealtime();
4029         final long uptime = mClocks.uptimeMillis();
4030         getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime);
4031         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
4032             return;
4033         }
4034         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_START, name, uid);
4035     }
4036 
noteSyncFinishLocked(String name, int uid)4037     public void noteSyncFinishLocked(String name, int uid) {
4038         uid = mapUid(uid);
4039         final long elapsedRealtime = mClocks.elapsedRealtime();
4040         final long uptime = mClocks.uptimeMillis();
4041         getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime);
4042         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
4043             return;
4044         }
4045         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_FINISH, name, uid);
4046     }
4047 
noteJobStartLocked(String name, int uid)4048     public void noteJobStartLocked(String name, int uid) {
4049         uid = mapUid(uid);
4050         final long elapsedRealtime = mClocks.elapsedRealtime();
4051         final long uptime = mClocks.uptimeMillis();
4052         getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime);
4053         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
4054             return;
4055         }
4056         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid);
4057     }
4058 
noteJobFinishLocked(String name, int uid, int stopReason)4059     public void noteJobFinishLocked(String name, int uid, int stopReason) {
4060         uid = mapUid(uid);
4061         final long elapsedRealtime = mClocks.elapsedRealtime();
4062         final long uptime = mClocks.uptimeMillis();
4063         getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime, stopReason);
4064         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
4065             return;
4066         }
4067         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
4068     }
4069 
noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast)4070     public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast) {
4071         uid = mapUid(uid);
4072         getUidStatsLocked(uid).noteJobsDeferredLocked(numDeferred, sinceLast);
4073     }
4074 
noteAlarmStartLocked(String name, WorkSource workSource, int uid)4075     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
4076         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid);
4077     }
4078 
noteAlarmFinishLocked(String name, WorkSource workSource, int uid)4079     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
4080         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid);
4081     }
4082 
noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, int uid)4083     private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
4084             int uid) {
4085         if (!mRecordAllHistory) {
4086             return;
4087         }
4088 
4089         final long elapsedRealtime = mClocks.elapsedRealtime();
4090         final long uptime = mClocks.uptimeMillis();
4091 
4092         if (workSource != null) {
4093             for (int i = 0; i < workSource.size(); ++i) {
4094                 uid = mapUid(workSource.get(i));
4095                 if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4096                     addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4097                 }
4098             }
4099 
4100             List<WorkChain> workChains = workSource.getWorkChains();
4101             if (workChains != null) {
4102                 for (int i = 0; i < workChains.size(); ++i) {
4103                     uid = mapUid(workChains.get(i).getAttributionUid());
4104                     if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4105                         addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4106                     }
4107                 }
4108             }
4109         } else {
4110             uid = mapUid(uid);
4111 
4112             if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4113                 addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4114             }
4115         }
4116     }
4117 
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag)4118     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4119             String tag) {
4120         if (workSource != null) {
4121             for (int i = 0; i < workSource.size(); ++i) {
4122                 uid = workSource.get(i);
4123                 final String workSourceName = workSource.getName(i);
4124 
4125                 if (isOnBattery()) {
4126                     BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
4127                             workSourceName != null ? workSourceName : packageName);
4128                     pkg.noteWakeupAlarmLocked(tag);
4129                 }
4130             }
4131 
4132             ArrayList<WorkChain> workChains = workSource.getWorkChains();
4133             if (workChains != null) {
4134                 for (int i = 0; i < workChains.size(); ++i) {
4135                     final WorkChain wc = workChains.get(i);
4136                     uid = wc.getAttributionUid();
4137 
4138                     if (isOnBattery()) {
4139                         BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
4140                         pkg.noteWakeupAlarmLocked(tag);
4141                     }
4142                 }
4143             }
4144         } else {
4145             if (isOnBattery()) {
4146                 BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
4147                 pkg.noteWakeupAlarmLocked(tag);
4148             }
4149         }
4150     }
4151 
requestWakelockCpuUpdate()4152     private void requestWakelockCpuUpdate() {
4153         mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS);
4154     }
4155 
requestImmediateCpuUpdate()4156     private void requestImmediateCpuUpdate() {
4157         mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
4158     }
4159 
setRecordAllHistoryLocked(boolean enabled)4160     public void setRecordAllHistoryLocked(boolean enabled) {
4161         mRecordAllHistory = enabled;
4162         if (!enabled) {
4163             // Clear out any existing state.
4164             mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
4165             mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
4166             // Record the currently running processes as stopping, now that we are no
4167             // longer tracking them.
4168             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4169                     HistoryItem.EVENT_PROC);
4170             if (active != null) {
4171                 long mSecRealtime = mClocks.elapsedRealtime();
4172                 final long mSecUptime = mClocks.uptimeMillis();
4173                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4174                     SparseIntArray uids = ent.getValue();
4175                     for (int j=0; j<uids.size(); j++) {
4176                         addHistoryEventLocked(mSecRealtime, mSecUptime,
4177                                 HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
4178                     }
4179                 }
4180             }
4181         } else {
4182             // Record the currently running processes as starting, now that we are tracking them.
4183             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4184                     HistoryItem.EVENT_PROC);
4185             if (active != null) {
4186                 long mSecRealtime = mClocks.elapsedRealtime();
4187                 final long mSecUptime = mClocks.uptimeMillis();
4188                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4189                     SparseIntArray uids = ent.getValue();
4190                     for (int j=0; j<uids.size(); j++) {
4191                         addHistoryEventLocked(mSecRealtime, mSecUptime,
4192                                 HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
4193                     }
4194                 }
4195             }
4196         }
4197     }
4198 
setNoAutoReset(boolean enabled)4199     public void setNoAutoReset(boolean enabled) {
4200         mNoAutoReset = enabled;
4201     }
4202 
setPretendScreenOff(boolean pretendScreenOff)4203     public void setPretendScreenOff(boolean pretendScreenOff) {
4204         if (mPretendScreenOff != pretendScreenOff) {
4205             mPretendScreenOff = pretendScreenOff;
4206             noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON);
4207         }
4208     }
4209 
4210     private String mInitialAcquireWakeName;
4211     private int mInitialAcquireWakeUid = -1;
4212 
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtime, long uptime)4213     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4214         int type, boolean unimportantForLogging, long elapsedRealtime, long uptime) {
4215         uid = mapUid(uid);
4216         if (type == WAKE_TYPE_PARTIAL) {
4217             // Only care about partial wake locks, since full wake locks
4218             // will be canceled when the user puts the screen to sleep.
4219             aggregateLastWakeupUptimeLocked(uptime);
4220             if (historyName == null) {
4221                 historyName = name;
4222             }
4223             if (mRecordAllHistory) {
4224                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
4225                         uid, 0)) {
4226                     addHistoryEventLocked(elapsedRealtime, uptime,
4227                             HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
4228                 }
4229             }
4230             if (mWakeLockNesting == 0) {
4231                 mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
4232                 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
4233                         + Integer.toHexString(mHistoryCur.states));
4234                 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
4235                 mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
4236                 mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
4237                 mWakeLockImportant = !unimportantForLogging;
4238                 addHistoryRecordLocked(elapsedRealtime, uptime);
4239             } else if (!mWakeLockImportant && !unimportantForLogging
4240                     && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
4241                 if (mHistoryLastWritten.wakelockTag != null) {
4242                     // We'll try to update the last tag.
4243                     mHistoryLastWritten.wakelockTag = null;
4244                     mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
4245                     mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
4246                     mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
4247                     addHistoryRecordLocked(elapsedRealtime, uptime);
4248                 }
4249                 mWakeLockImportant = true;
4250             }
4251             mWakeLockNesting++;
4252         }
4253         if (uid >= 0) {
4254             if (mOnBatteryScreenOffTimeBase.isRunning()) {
4255                 // We only update the cpu time when a wake lock is acquired if the screen is off.
4256                 // If the screen is on, we don't distribute the power amongst partial wakelocks.
4257                 if (DEBUG_ENERGY_CPU) {
4258                     Slog.d(TAG, "Updating cpu time because of +wake_lock");
4259                 }
4260                 requestWakelockCpuUpdate();
4261             }
4262 
4263             getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
4264 
4265             if (wc != null) {
4266                 StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(),
4267                         getPowerManagerWakeLockLevel(type), name,
4268                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
4269             } else {
4270                 StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null,
4271                         getPowerManagerWakeLockLevel(type), name,
4272                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
4273             }
4274         }
4275     }
4276 
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, long elapsedRealtime, long uptime)4277     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4278             int type, long elapsedRealtime, long uptime) {
4279         uid = mapUid(uid);
4280         if (type == WAKE_TYPE_PARTIAL) {
4281             mWakeLockNesting--;
4282             if (mRecordAllHistory) {
4283                 if (historyName == null) {
4284                     historyName = name;
4285                 }
4286                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
4287                         uid, 0)) {
4288                     addHistoryEventLocked(elapsedRealtime, uptime,
4289                             HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
4290                 }
4291             }
4292             if (mWakeLockNesting == 0) {
4293                 mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
4294                 if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
4295                         + Integer.toHexString(mHistoryCur.states));
4296                 mInitialAcquireWakeName = null;
4297                 mInitialAcquireWakeUid = -1;
4298                 addHistoryRecordLocked(elapsedRealtime, uptime);
4299             }
4300         }
4301         if (uid >= 0) {
4302             if (mOnBatteryScreenOffTimeBase.isRunning()) {
4303                 if (DEBUG_ENERGY_CPU) {
4304                     Slog.d(TAG, "Updating cpu time because of -wake_lock");
4305                 }
4306                 requestWakelockCpuUpdate();
4307             }
4308 
4309             getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
4310             if (wc != null) {
4311                 StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(),
4312                         getPowerManagerWakeLockLevel(type), name,
4313                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
4314             } else {
4315                 StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null,
4316                         getPowerManagerWakeLockLevel(type), name,
4317                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
4318             }
4319         }
4320     }
4321 
4322     /**
4323      * Converts BatteryStats wakelock types back into PowerManager wakelock levels.
4324      * This is the inverse map of Notifier.getBatteryStatsWakeLockMonitorType().
4325      * These are estimations, since batterystats loses some of the original data.
4326      * TODO: Delete this. Instead, StatsLog.write should be called from PowerManager's Notifier.
4327      */
getPowerManagerWakeLockLevel(int battertStatsWakelockType)4328     private int getPowerManagerWakeLockLevel(int battertStatsWakelockType) {
4329         switch (battertStatsWakelockType) {
4330             // PowerManager.PARTIAL_WAKE_LOCK or PROXIMITY_SCREEN_OFF_WAKE_LOCK
4331             case BatteryStats.WAKE_TYPE_PARTIAL:
4332                 return PowerManager.PARTIAL_WAKE_LOCK;
4333 
4334             // PowerManager.SCREEN_DIM_WAKE_LOCK or SCREEN_BRIGHT_WAKE_LOCK
4335             case BatteryStats.WAKE_TYPE_FULL:
4336                 return PowerManager.FULL_WAKE_LOCK;
4337 
4338             case BatteryStats.WAKE_TYPE_DRAW:
4339                 return PowerManager.DRAW_WAKE_LOCK;
4340 
4341             // It appears that nothing can ever make a Window and PowerManager lacks an equivalent.
4342             case BatteryStats.WAKE_TYPE_WINDOW:
4343                 Slog.e(TAG, "Illegal window wakelock type observed in batterystats.");
4344                 return -1;
4345 
4346             default:
4347                 Slog.e(TAG, "Illegal wakelock type in batterystats: " + battertStatsWakelockType);
4348                 return -1;
4349         }
4350     }
4351 
noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging)4352     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
4353             String historyName, int type, boolean unimportantForLogging) {
4354         final long elapsedRealtime = mClocks.elapsedRealtime();
4355         final long uptime = mClocks.uptimeMillis();
4356         final int N = ws.size();
4357         for (int i=0; i<N; i++) {
4358             noteStartWakeLocked(ws.get(i), pid, null, name, historyName, type,
4359                     unimportantForLogging, elapsedRealtime, uptime);
4360         }
4361 
4362         List<WorkChain> wcs = ws.getWorkChains();
4363         if (wcs != null) {
4364             for (int i = 0; i < wcs.size(); ++i) {
4365                 final WorkChain wc = wcs.get(i);
4366                 noteStartWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4367                         unimportantForLogging, elapsedRealtime, uptime);
4368             }
4369         }
4370     }
4371 
noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, WorkSource newWs, int newPid, String newName, String newHistoryName, int newType, boolean newUnimportantForLogging)4372     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
4373             String historyName, int type, WorkSource newWs, int newPid, String newName,
4374             String newHistoryName, int newType, boolean newUnimportantForLogging) {
4375         final long elapsedRealtime = mClocks.elapsedRealtime();
4376         final long uptime = mClocks.uptimeMillis();
4377 
4378         List<WorkChain>[] wcs = WorkSource.diffChains(ws, newWs);
4379 
4380         // For correct semantics, we start the need worksources first, so that we won't
4381         // make inappropriate history items as if all wake locks went away and new ones
4382         // appeared.  This is okay because tracking of wake locks allows nesting.
4383         //
4384         // First the starts :
4385         final int NN = newWs.size();
4386         for (int i=0; i<NN; i++) {
4387             noteStartWakeLocked(newWs.get(i), newPid, null, newName, newHistoryName, newType,
4388                     newUnimportantForLogging, elapsedRealtime, uptime);
4389         }
4390         if (wcs != null) {
4391             List<WorkChain> newChains = wcs[0];
4392             if (newChains != null) {
4393                 for (int i = 0; i < newChains.size(); ++i) {
4394                     final WorkChain newChain = newChains.get(i);
4395                     noteStartWakeLocked(newChain.getAttributionUid(), newPid, newChain, newName,
4396                         newHistoryName, newType, newUnimportantForLogging, elapsedRealtime,
4397                         uptime);
4398                 }
4399             }
4400         }
4401 
4402         // Then the stops :
4403         final int NO = ws.size();
4404         for (int i=0; i<NO; i++) {
4405             noteStopWakeLocked(ws.get(i), pid, null, name, historyName, type, elapsedRealtime,
4406                     uptime);
4407         }
4408         if (wcs != null) {
4409             List<WorkChain> goneChains = wcs[1];
4410             if (goneChains != null) {
4411                 for (int i = 0; i < goneChains.size(); ++i) {
4412                     final WorkChain goneChain = goneChains.get(i);
4413                     noteStopWakeLocked(goneChain.getAttributionUid(), pid, goneChain, name,
4414                             historyName, type, elapsedRealtime, uptime);
4415                 }
4416             }
4417         }
4418     }
4419 
noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type)4420     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
4421             String historyName, int type) {
4422         final long elapsedRealtime = mClocks.elapsedRealtime();
4423         final long uptime = mClocks.uptimeMillis();
4424         final int N = ws.size();
4425         for (int i=0; i<N; i++) {
4426             noteStopWakeLocked(ws.get(i), pid, null, name, historyName, type, elapsedRealtime,
4427                     uptime);
4428         }
4429 
4430         List<WorkChain> wcs = ws.getWorkChains();
4431         if (wcs != null) {
4432             for (int i = 0; i < wcs.size(); ++i) {
4433                 final WorkChain wc = wcs.get(i);
4434                 noteStopWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4435                         elapsedRealtime, uptime);
4436             }
4437         }
4438     }
4439 
noteLongPartialWakelockStart(String name, String historyName, int uid)4440     public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
4441         uid = mapUid(uid);
4442         noteLongPartialWakeLockStartInternal(name, historyName, uid);
4443     }
4444 
noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource)4445     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
4446             WorkSource workSource) {
4447         final int N = workSource.size();
4448         for (int i = 0; i < N; ++i) {
4449             final int uid = mapUid(workSource.get(i));
4450             noteLongPartialWakeLockStartInternal(name, historyName, uid);
4451         }
4452 
4453         final ArrayList<WorkChain> workChains = workSource.getWorkChains();
4454         if (workChains != null) {
4455             for (int i = 0; i < workChains.size(); ++i) {
4456                 final WorkChain workChain = workChains.get(i);
4457                 final int uid = workChain.getAttributionUid();
4458                 noteLongPartialWakeLockStartInternal(name, historyName, uid);
4459             }
4460         }
4461     }
4462 
noteLongPartialWakeLockStartInternal(String name, String historyName, int uid)4463     private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid) {
4464         final long elapsedRealtime = mClocks.elapsedRealtime();
4465         final long uptime = mClocks.uptimeMillis();
4466         if (historyName == null) {
4467             historyName = name;
4468         }
4469         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid,
4470                 0)) {
4471             return;
4472         }
4473         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
4474                 historyName, uid);
4475     }
4476 
noteLongPartialWakelockFinish(String name, String historyName, int uid)4477     public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
4478         uid = mapUid(uid);
4479         noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4480     }
4481 
noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource)4482     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
4483             WorkSource workSource) {
4484         final int N = workSource.size();
4485         for (int i = 0; i < N; ++i) {
4486             final int uid = mapUid(workSource.get(i));
4487             noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4488         }
4489 
4490         final ArrayList<WorkChain> workChains = workSource.getWorkChains();
4491         if (workChains != null) {
4492             for (int i = 0; i < workChains.size(); ++i) {
4493                 final WorkChain workChain = workChains.get(i);
4494                 final int uid = workChain.getAttributionUid();
4495                 noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4496             }
4497         }
4498     }
4499 
noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid)4500     private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid) {
4501         final long elapsedRealtime = mClocks.elapsedRealtime();
4502         final long uptime = mClocks.uptimeMillis();
4503         if (historyName == null) {
4504             historyName = name;
4505         }
4506         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid,
4507                 0)) {
4508             return;
4509         }
4510         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
4511                 historyName, uid);
4512     }
4513 
aggregateLastWakeupUptimeLocked(long uptimeMs)4514     void aggregateLastWakeupUptimeLocked(long uptimeMs) {
4515         if (mLastWakeupReason != null) {
4516             long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
4517             SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
4518             timer.add(deltaUptime * 1000, 1); // time in in microseconds
4519             StatsLog.write(StatsLog.KERNEL_WAKEUP_REPORTED, mLastWakeupReason,
4520                     /* duration_usec */ deltaUptime * 1000);
4521             mLastWakeupReason = null;
4522         }
4523     }
4524 
noteWakeupReasonLocked(String reason)4525     public void noteWakeupReasonLocked(String reason) {
4526         final long elapsedRealtime = mClocks.elapsedRealtime();
4527         final long uptime = mClocks.uptimeMillis();
4528         if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
4529                 + Integer.toHexString(mHistoryCur.states));
4530         aggregateLastWakeupUptimeLocked(uptime);
4531         mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
4532         mHistoryCur.wakeReasonTag.string = reason;
4533         mHistoryCur.wakeReasonTag.uid = 0;
4534         mLastWakeupReason = reason;
4535         mLastWakeupUptimeMs = uptime;
4536         addHistoryRecordLocked(elapsedRealtime, uptime);
4537     }
4538 
startAddingCpuLocked()4539     public boolean startAddingCpuLocked() {
4540         mExternalSync.cancelCpuSyncDueToWakelockChange();
4541         return mOnBatteryInternal;
4542     }
4543 
finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime, int statSystemTime, int statIOWaitTime, int statIrqTime, int statSoftIrqTime, int statIdleTime)4544     public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime,
4545                                       int statSystemTime, int statIOWaitTime, int statIrqTime,
4546                                       int statSoftIrqTime, int statIdleTime) {
4547         if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
4548                 + " user=" + statUserTime + " sys=" + statSystemTime
4549                 + " io=" + statIOWaitTime + " irq=" + statIrqTime
4550                 + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime);
4551         mCurStepCpuUserTime += totalUTime;
4552         mCurStepCpuSystemTime += totalSTime;
4553         mCurStepStatUserTime += statUserTime;
4554         mCurStepStatSystemTime += statSystemTime;
4555         mCurStepStatIOWaitTime += statIOWaitTime;
4556         mCurStepStatIrqTime += statIrqTime;
4557         mCurStepStatSoftIrqTime += statSoftIrqTime;
4558         mCurStepStatIdleTime += statIdleTime;
4559     }
4560 
noteProcessDiedLocked(int uid, int pid)4561     public void noteProcessDiedLocked(int uid, int pid) {
4562         uid = mapUid(uid);
4563         Uid u = mUidStats.get(uid);
4564         if (u != null) {
4565             u.mPids.remove(pid);
4566         }
4567     }
4568 
getProcessWakeTime(int uid, int pid, long realtime)4569     public long getProcessWakeTime(int uid, int pid, long realtime) {
4570         uid = mapUid(uid);
4571         Uid u = mUidStats.get(uid);
4572         if (u != null) {
4573             Uid.Pid p = u.mPids.get(pid);
4574             if (p != null) {
4575                 return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0);
4576             }
4577         }
4578         return 0;
4579     }
4580 
reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime)4581     public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
4582         uid = mapUid(uid);
4583         Uid u = mUidStats.get(uid);
4584         if (u != null) {
4585             u.reportExcessiveCpuLocked(proc, overTime, usedTime);
4586         }
4587     }
4588 
4589     int mSensorNesting;
4590 
noteStartSensorLocked(int uid, int sensor)4591     public void noteStartSensorLocked(int uid, int sensor) {
4592         uid = mapUid(uid);
4593         final long elapsedRealtime = mClocks.elapsedRealtime();
4594         final long uptime = mClocks.uptimeMillis();
4595         if (mSensorNesting == 0) {
4596             mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
4597             if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
4598                     + Integer.toHexString(mHistoryCur.states));
4599             addHistoryRecordLocked(elapsedRealtime, uptime);
4600         }
4601         mSensorNesting++;
4602         getUidStatsLocked(uid).noteStartSensor(sensor, elapsedRealtime);
4603     }
4604 
noteStopSensorLocked(int uid, int sensor)4605     public void noteStopSensorLocked(int uid, int sensor) {
4606         uid = mapUid(uid);
4607         final long elapsedRealtime = mClocks.elapsedRealtime();
4608         final long uptime = mClocks.uptimeMillis();
4609         mSensorNesting--;
4610         if (mSensorNesting == 0) {
4611             mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
4612             if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
4613                     + Integer.toHexString(mHistoryCur.states));
4614             addHistoryRecordLocked(elapsedRealtime, uptime);
4615         }
4616         getUidStatsLocked(uid).noteStopSensor(sensor, elapsedRealtime);
4617     }
4618 
4619     int mGpsNesting;
4620 
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs)4621     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
4622         for (int i = 0; i < newWs.size(); ++i) {
4623             noteStartGpsLocked(newWs.get(i), null);
4624         }
4625 
4626         for (int i = 0; i < oldWs.size(); ++i) {
4627             noteStopGpsLocked((oldWs.get(i)), null);
4628         }
4629 
4630         List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
4631         if (wcs != null) {
4632             if (wcs[0] != null) {
4633                 final List<WorkChain> newChains = wcs[0];
4634                 for (int i = 0; i < newChains.size(); ++i) {
4635                     noteStartGpsLocked(-1, newChains.get(i));
4636                 }
4637             }
4638 
4639             if (wcs[1] != null) {
4640                 final List<WorkChain> goneChains = wcs[1];
4641                 for (int i = 0; i < goneChains.size(); ++i) {
4642                     noteStopGpsLocked(-1, goneChains.get(i));
4643                 }
4644             }
4645         }
4646     }
4647 
noteStartGpsLocked(int uid, WorkChain workChain)4648     private void noteStartGpsLocked(int uid, WorkChain workChain) {
4649         uid = getAttributionUid(uid, workChain);
4650         final long elapsedRealtime = mClocks.elapsedRealtime();
4651         final long uptime = mClocks.uptimeMillis();
4652         if (mGpsNesting == 0) {
4653             mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
4654             if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
4655                     + Integer.toHexString(mHistoryCur.states));
4656             addHistoryRecordLocked(elapsedRealtime, uptime);
4657         }
4658         mGpsNesting++;
4659 
4660         if (workChain == null) {
4661             StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
4662                     StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
4663         } else {
4664             StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED,
4665                     workChain.getUids(), workChain.getTags(),
4666                     StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
4667         }
4668 
4669         getUidStatsLocked(uid).noteStartGps(elapsedRealtime);
4670     }
4671 
noteStopGpsLocked(int uid, WorkChain workChain)4672     private void noteStopGpsLocked(int uid, WorkChain workChain) {
4673         uid = getAttributionUid(uid, workChain);
4674         final long elapsedRealtime = mClocks.elapsedRealtime();
4675         final long uptime = mClocks.uptimeMillis();
4676         mGpsNesting--;
4677         if (mGpsNesting == 0) {
4678             mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
4679             if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
4680                     + Integer.toHexString(mHistoryCur.states));
4681             addHistoryRecordLocked(elapsedRealtime, uptime);
4682             stopAllGpsSignalQualityTimersLocked(-1);
4683             mGpsSignalQualityBin = -1;
4684         }
4685 
4686         if (workChain == null) {
4687             StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
4688                     StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
4689         } else {
4690             StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(),
4691                     workChain.getTags(), StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
4692         }
4693 
4694         getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
4695     }
4696 
noteGpsSignalQualityLocked(int signalLevel)4697     public void noteGpsSignalQualityLocked(int signalLevel) {
4698         if (mGpsNesting == 0) {
4699             return;
4700         }
4701         if (signalLevel < 0 || signalLevel >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
4702             stopAllGpsSignalQualityTimersLocked(-1);
4703             return;
4704         }
4705         final long elapsedRealtime = mClocks.elapsedRealtime();
4706         final long uptime = mClocks.uptimeMillis();
4707         if (mGpsSignalQualityBin != signalLevel) {
4708             if (mGpsSignalQualityBin >= 0) {
4709                 mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtime);
4710             }
4711             if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
4712                 mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtime);
4713             }
4714             mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
4715                     | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
4716             addHistoryRecordLocked(elapsedRealtime, uptime);
4717             mGpsSignalQualityBin = signalLevel;
4718         }
4719         return;
4720     }
4721 
4722     @GuardedBy("this")
noteScreenStateLocked(int state)4723     public void noteScreenStateLocked(int state) {
4724         state = mPretendScreenOff ? Display.STATE_OFF : state;
4725 
4726         // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
4727         // original 4 are mapped to one of the originals.
4728         if (state > MAX_TRACKED_SCREEN_STATE) {
4729             switch (state) {
4730                 case Display.STATE_VR:
4731                     state = Display.STATE_ON;
4732                     break;
4733                 default:
4734                     Slog.wtf(TAG, "Unknown screen state (not mapped): " + state);
4735                     break;
4736             }
4737         }
4738 
4739         if (mScreenState != state) {
4740             recordDailyStatsIfNeededLocked(true);
4741             final int oldState = mScreenState;
4742             mScreenState = state;
4743             if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
4744                     + ", newState=" + Display.stateToString(state));
4745 
4746             if (state != Display.STATE_UNKNOWN) {
4747                 int stepState = state-1;
4748                 if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
4749                     mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
4750                     mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
4751                 } else {
4752                     Slog.wtf(TAG, "Unexpected screen state: " + state);
4753                 }
4754             }
4755 
4756             final long elapsedRealtime = mClocks.elapsedRealtime();
4757             final long uptime = mClocks.uptimeMillis();
4758 
4759             boolean updateHistory = false;
4760             if (isScreenDoze(state) && !isScreenDoze(oldState)) {
4761                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
4762                 mScreenDozeTimer.startRunningLocked(elapsedRealtime);
4763                 updateHistory = true;
4764             } else if (isScreenDoze(oldState) && !isScreenDoze(state)) {
4765                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG;
4766                 mScreenDozeTimer.stopRunningLocked(elapsedRealtime);
4767                 updateHistory = true;
4768             }
4769             if (isScreenOn(state)) {
4770                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
4771                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
4772                         + Integer.toHexString(mHistoryCur.states));
4773                 mScreenOnTimer.startRunningLocked(elapsedRealtime);
4774                 if (mScreenBrightnessBin >= 0) {
4775                     mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
4776                 }
4777                 updateHistory = true;
4778             } else if (isScreenOn(oldState)) {
4779                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
4780                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
4781                         + Integer.toHexString(mHistoryCur.states));
4782                 mScreenOnTimer.stopRunningLocked(elapsedRealtime);
4783                 if (mScreenBrightnessBin >= 0) {
4784                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
4785                 }
4786                 updateHistory = true;
4787             }
4788             if (updateHistory) {
4789                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: "
4790                         + Display.stateToString(state));
4791                 addHistoryRecordLocked(elapsedRealtime, uptime);
4792             }
4793             mExternalSync.scheduleCpuSyncDueToScreenStateChange(
4794                     mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
4795             if (isScreenOn(state)) {
4796                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
4797                         mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
4798                 // Fake a wake lock, so we consider the device waked as long as the screen is on.
4799                 noteStartWakeLocked(-1, -1, null, "screen", null, WAKE_TYPE_PARTIAL, false,
4800                         elapsedRealtime, uptime);
4801             } else if (isScreenOn(oldState)) {
4802                 noteStopWakeLocked(-1, -1, null, "screen", "screen", WAKE_TYPE_PARTIAL,
4803                         elapsedRealtime, uptime);
4804                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
4805                         mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
4806             }
4807             // Update discharge amounts.
4808             if (mOnBatteryInternal) {
4809                 updateDischargeScreenLevelsLocked(oldState, state);
4810             }
4811         }
4812     }
4813 
4814     @UnsupportedAppUsage
noteScreenBrightnessLocked(int brightness)4815     public void noteScreenBrightnessLocked(int brightness) {
4816         // Bin the brightness.
4817         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
4818         if (bin < 0) bin = 0;
4819         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
4820         if (mScreenBrightnessBin != bin) {
4821             final long elapsedRealtime = mClocks.elapsedRealtime();
4822             final long uptime = mClocks.uptimeMillis();
4823             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
4824                     | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
4825             if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
4826                     + Integer.toHexString(mHistoryCur.states));
4827             addHistoryRecordLocked(elapsedRealtime, uptime);
4828             if (mScreenState == Display.STATE_ON) {
4829                 if (mScreenBrightnessBin >= 0) {
4830                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
4831                 }
4832                 mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime);
4833             }
4834             mScreenBrightnessBin = bin;
4835         }
4836     }
4837 
4838     @UnsupportedAppUsage
noteUserActivityLocked(int uid, int event)4839     public void noteUserActivityLocked(int uid, int event) {
4840         if (mOnBatteryInternal) {
4841             uid = mapUid(uid);
4842             getUidStatsLocked(uid).noteUserActivityLocked(event);
4843         }
4844     }
4845 
noteWakeUpLocked(String reason, int reasonUid)4846     public void noteWakeUpLocked(String reason, int reasonUid) {
4847         final long elapsedRealtime = mClocks.elapsedRealtime();
4848         final long uptime = mClocks.uptimeMillis();
4849         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SCREEN_WAKE_UP,
4850                 reason, reasonUid);
4851     }
4852 
noteInteractiveLocked(boolean interactive)4853     public void noteInteractiveLocked(boolean interactive) {
4854         if (mInteractive != interactive) {
4855             final long elapsedRealtime = mClocks.elapsedRealtime();
4856             mInteractive = interactive;
4857             if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
4858             if (interactive) {
4859                 mInteractiveTimer.startRunningLocked(elapsedRealtime);
4860             } else {
4861                 mInteractiveTimer.stopRunningLocked(elapsedRealtime);
4862             }
4863         }
4864     }
4865 
noteConnectivityChangedLocked(int type, String extra)4866     public void noteConnectivityChangedLocked(int type, String extra) {
4867         final long elapsedRealtime = mClocks.elapsedRealtime();
4868         final long uptime = mClocks.uptimeMillis();
4869         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
4870                 extra, type);
4871         mNumConnectivityChange++;
4872     }
4873 
noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)4874     private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
4875             final long uptimeMillis, int uid) {
4876         uid = mapUid(uid);
4877         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
4878                 uid);
4879         getUidStatsLocked(uid).noteMobileRadioApWakeupLocked();
4880     }
4881 
4882     /**
4883      * Updates the radio power state and returns true if an external stats collection should occur.
4884      */
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid)4885     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
4886         final long elapsedRealtime = mClocks.elapsedRealtime();
4887         final long uptime = mClocks.uptimeMillis();
4888         if (mMobileRadioPowerState != powerState) {
4889             long realElapsedRealtimeMs;
4890             final boolean active =
4891                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
4892                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
4893             if (active) {
4894                 if (uid > 0) {
4895                     noteMobileRadioApWakeupLocked(elapsedRealtime, uptime, uid);
4896                 }
4897 
4898                 mMobileRadioActiveStartTime = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
4899                 mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
4900             } else {
4901                 realElapsedRealtimeMs = timestampNs / (1000*1000);
4902                 long lastUpdateTimeMs = mMobileRadioActiveStartTime;
4903                 if (realElapsedRealtimeMs < lastUpdateTimeMs) {
4904                     Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
4905                             + " is before start time " + lastUpdateTimeMs);
4906                     realElapsedRealtimeMs = elapsedRealtime;
4907                 } else if (realElapsedRealtimeMs < elapsedRealtime) {
4908                     mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
4909                             - realElapsedRealtimeMs);
4910                 }
4911                 mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
4912             }
4913             if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
4914                     + Integer.toHexString(mHistoryCur.states));
4915             addHistoryRecordLocked(elapsedRealtime, uptime);
4916             mMobileRadioPowerState = powerState;
4917             if (active) {
4918                 mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
4919                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
4920             } else {
4921                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
4922                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
4923                 // Tell the caller to collect radio network/power stats.
4924                 return true;
4925             }
4926         }
4927         return false;
4928     }
4929 
notePowerSaveModeLocked(boolean enabled)4930     public void notePowerSaveModeLocked(boolean enabled) {
4931         if (mPowerSaveModeEnabled != enabled) {
4932             int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
4933             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
4934             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
4935             final long elapsedRealtime = mClocks.elapsedRealtime();
4936             final long uptime = mClocks.uptimeMillis();
4937             mPowerSaveModeEnabled = enabled;
4938             if (enabled) {
4939                 mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
4940                 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
4941                         + Integer.toHexString(mHistoryCur.states2));
4942                 mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtime);
4943             } else {
4944                 mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
4945                 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
4946                         + Integer.toHexString(mHistoryCur.states2));
4947                 mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtime);
4948             }
4949             addHistoryRecordLocked(elapsedRealtime, uptime);
4950             StatsLog.write(StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED, enabled ?
4951                     StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON :
4952                     StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
4953         }
4954     }
4955 
noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid)4956     public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid) {
4957         final long elapsedRealtime = mClocks.elapsedRealtime();
4958         final long uptime = mClocks.uptimeMillis();
4959         boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
4960         if (mDeviceIdling && !nowIdling && activeReason == null) {
4961             // We don't go out of general idling mode until explicitly taken out of
4962             // device idle through going active or significant motion.
4963             nowIdling = true;
4964         }
4965         boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
4966         if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
4967             // We don't go out of general light idling mode until explicitly taken out of
4968             // device idle through going active or significant motion.
4969             nowLightIdling = true;
4970         }
4971         if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
4972             addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
4973                     activeReason, activeUid);
4974         }
4975         if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
4976             int statsmode;
4977             if (nowIdling)           statsmode = DEVICE_IDLE_MODE_DEEP;
4978             else if (nowLightIdling) statsmode = DEVICE_IDLE_MODE_LIGHT;
4979             else                     statsmode = DEVICE_IDLE_MODE_OFF;
4980             StatsLog.write(StatsLog.DEVICE_IDLING_MODE_STATE_CHANGED, statsmode);
4981         }
4982         if (mDeviceIdling != nowIdling) {
4983             mDeviceIdling = nowIdling;
4984             int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
4985             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
4986             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
4987             if (nowIdling) {
4988                 mDeviceIdlingTimer.startRunningLocked(elapsedRealtime);
4989             } else {
4990                 mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime);
4991             }
4992         }
4993         if (mDeviceLightIdling != nowLightIdling) {
4994             mDeviceLightIdling = nowLightIdling;
4995             if (nowLightIdling) {
4996                 mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtime);
4997             } else {
4998                 mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtime);
4999             }
5000         }
5001         if (mDeviceIdleMode != mode) {
5002             mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
5003                     | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
5004             if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
5005                     + Integer.toHexString(mHistoryCur.states2));
5006             addHistoryRecordLocked(elapsedRealtime, uptime);
5007             long lastDuration = elapsedRealtime - mLastIdleTimeStart;
5008             mLastIdleTimeStart = elapsedRealtime;
5009             if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
5010                 if (lastDuration > mLongestLightIdleTime) {
5011                     mLongestLightIdleTime = lastDuration;
5012                 }
5013                 mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtime);
5014             } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
5015                 if (lastDuration > mLongestFullIdleTime) {
5016                     mLongestFullIdleTime = lastDuration;
5017                 }
5018                 mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtime);
5019             }
5020             if (mode == DEVICE_IDLE_MODE_LIGHT) {
5021                 mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtime);
5022             } else if (mode == DEVICE_IDLE_MODE_DEEP) {
5023                 mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtime);
5024             }
5025             mDeviceIdleMode = mode;
5026             StatsLog.write(StatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mode);
5027         }
5028     }
5029 
notePackageInstalledLocked(String pkgName, long versionCode)5030     public void notePackageInstalledLocked(String pkgName, long versionCode) {
5031         final long elapsedRealtime = mClocks.elapsedRealtime();
5032         final long uptime = mClocks.uptimeMillis();
5033         // XXX need to figure out what to do with long version codes.
5034         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED,
5035                 pkgName, (int)versionCode);
5036         PackageChange pc = new PackageChange();
5037         pc.mPackageName = pkgName;
5038         pc.mUpdate = true;
5039         pc.mVersionCode = versionCode;
5040         addPackageChange(pc);
5041     }
5042 
notePackageUninstalledLocked(String pkgName)5043     public void notePackageUninstalledLocked(String pkgName) {
5044         final long elapsedRealtime = mClocks.elapsedRealtime();
5045         final long uptime = mClocks.uptimeMillis();
5046         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
5047                 pkgName, 0);
5048         PackageChange pc = new PackageChange();
5049         pc.mPackageName = pkgName;
5050         pc.mUpdate = true;
5051         addPackageChange(pc);
5052     }
5053 
addPackageChange(PackageChange pc)5054     private void addPackageChange(PackageChange pc) {
5055         if (mDailyPackageChanges == null) {
5056             mDailyPackageChanges = new ArrayList<>();
5057         }
5058         mDailyPackageChanges.add(pc);
5059     }
5060 
stopAllGpsSignalQualityTimersLocked(int except)5061     void stopAllGpsSignalQualityTimersLocked(int except) {
5062         final long elapsedRealtime = mClocks.elapsedRealtime();
5063         for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
5064             if (i == except) {
5065                 continue;
5066             }
5067             while (mGpsSignalQualityTimer[i].isRunningLocked()) {
5068                 mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtime);
5069             }
5070         }
5071     }
5072 
5073     @UnsupportedAppUsage
notePhoneOnLocked()5074     public void notePhoneOnLocked() {
5075         if (!mPhoneOn) {
5076             final long elapsedRealtime = mClocks.elapsedRealtime();
5077             final long uptime = mClocks.uptimeMillis();
5078             mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
5079             if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
5080                     + Integer.toHexString(mHistoryCur.states));
5081             addHistoryRecordLocked(elapsedRealtime, uptime);
5082             mPhoneOn = true;
5083             mPhoneOnTimer.startRunningLocked(elapsedRealtime);
5084         }
5085     }
5086 
5087     @UnsupportedAppUsage
notePhoneOffLocked()5088     public void notePhoneOffLocked() {
5089         if (mPhoneOn) {
5090             final long elapsedRealtime = mClocks.elapsedRealtime();
5091             final long uptime = mClocks.uptimeMillis();
5092             mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
5093             if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
5094                     + Integer.toHexString(mHistoryCur.states));
5095             addHistoryRecordLocked(elapsedRealtime, uptime);
5096             mPhoneOn = false;
5097             mPhoneOnTimer.stopRunningLocked(elapsedRealtime);
5098         }
5099     }
5100 
registerUsbStateReceiver(Context context)5101     private void registerUsbStateReceiver(Context context) {
5102         final IntentFilter usbStateFilter = new IntentFilter();
5103         usbStateFilter.addAction(UsbManager.ACTION_USB_STATE);
5104         context.registerReceiver(new BroadcastReceiver() {
5105             @Override
5106             public void onReceive(Context context, Intent intent) {
5107                 final boolean state = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
5108                 synchronized (BatteryStatsImpl.this) {
5109                     noteUsbConnectionStateLocked(state);
5110                 }
5111             }
5112         }, usbStateFilter);
5113         synchronized (this) {
5114             if (mUsbDataState == USB_DATA_UNKNOWN) {
5115                 final Intent usbState = context.registerReceiver(null, usbStateFilter);
5116                 final boolean initState = usbState != null && usbState.getBooleanExtra(
5117                         UsbManager.USB_CONNECTED, false);
5118                 noteUsbConnectionStateLocked(initState);
5119             }
5120         }
5121     }
5122 
noteUsbConnectionStateLocked(boolean connected)5123     private void noteUsbConnectionStateLocked(boolean connected) {
5124         int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED;
5125         if (mUsbDataState != newState) {
5126             mUsbDataState = newState;
5127             if (connected) {
5128                 mHistoryCur.states2 |= HistoryItem.STATE2_USB_DATA_LINK_FLAG;
5129             } else {
5130                 mHistoryCur.states2 &= ~HistoryItem.STATE2_USB_DATA_LINK_FLAG;
5131             }
5132             addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5133         }
5134     }
5135 
stopAllPhoneSignalStrengthTimersLocked(int except)5136     void stopAllPhoneSignalStrengthTimersLocked(int except) {
5137         final long elapsedRealtime = mClocks.elapsedRealtime();
5138         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
5139             if (i == except) {
5140                 continue;
5141             }
5142             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
5143                 mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
5144             }
5145         }
5146     }
5147 
fixPhoneServiceState(int state, int signalBin)5148     private int fixPhoneServiceState(int state, int signalBin) {
5149         if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
5150             // In this case we will always be STATE_OUT_OF_SERVICE, so need
5151             // to infer that we are scanning from other data.
5152             if (state == ServiceState.STATE_OUT_OF_SERVICE
5153                     && signalBin > CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5154                 state = ServiceState.STATE_IN_SERVICE;
5155             }
5156         }
5157 
5158         return state;
5159     }
5160 
updateAllPhoneStateLocked(int state, int simState, int strengthBin)5161     private void updateAllPhoneStateLocked(int state, int simState, int strengthBin) {
5162         boolean scanning = false;
5163         boolean newHistory = false;
5164 
5165         mPhoneServiceStateRaw = state;
5166         mPhoneSimStateRaw = simState;
5167         mPhoneSignalStrengthBinRaw = strengthBin;
5168 
5169         final long elapsedRealtime = mClocks.elapsedRealtime();
5170         final long uptime = mClocks.uptimeMillis();
5171 
5172         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
5173             // In this case we will always be STATE_OUT_OF_SERVICE, so need
5174             // to infer that we are scanning from other data.
5175             if (state == ServiceState.STATE_OUT_OF_SERVICE
5176                     && strengthBin > CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5177                 state = ServiceState.STATE_IN_SERVICE;
5178             }
5179         }
5180 
5181         // If the phone is powered off, stop all timers.
5182         if (state == ServiceState.STATE_POWER_OFF) {
5183             strengthBin = -1;
5184 
5185         // If we are in service, make sure the correct signal string timer is running.
5186         } else if (state == ServiceState.STATE_IN_SERVICE) {
5187             // Bin will be changed below.
5188 
5189         // If we're out of service, we are in the lowest signal strength
5190         // bin and have the scanning bit set.
5191         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
5192             scanning = true;
5193             strengthBin = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
5194             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
5195                 mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
5196                 newHistory = true;
5197                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
5198                         + Integer.toHexString(mHistoryCur.states));
5199                 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
5200                 StatsLog.write(StatsLog.PHONE_SERVICE_STATE_CHANGED, state, simState, strengthBin);
5201             }
5202         }
5203 
5204         if (!scanning) {
5205             // If we are no longer scanning, then stop the scanning timer.
5206             if (mPhoneSignalScanningTimer.isRunningLocked()) {
5207                 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
5208                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
5209                         + Integer.toHexString(mHistoryCur.states));
5210                 newHistory = true;
5211                 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
5212                 StatsLog.write(StatsLog.PHONE_SERVICE_STATE_CHANGED, state, simState, strengthBin);
5213             }
5214         }
5215 
5216         if (mPhoneServiceState != state) {
5217             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
5218                     | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
5219             if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
5220                     + Integer.toHexString(mHistoryCur.states));
5221             newHistory = true;
5222             mPhoneServiceState = state;
5223         }
5224 
5225         if (mPhoneSignalStrengthBin != strengthBin) {
5226             if (mPhoneSignalStrengthBin >= 0) {
5227                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
5228                         elapsedRealtime);
5229             }
5230             if (strengthBin >= 0) {
5231                 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
5232                     mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
5233                 }
5234                 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
5235                         | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
5236                 if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
5237                         + Integer.toHexString(mHistoryCur.states));
5238                 newHistory = true;
5239                 StatsLog.write(StatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
5240             } else {
5241                 stopAllPhoneSignalStrengthTimersLocked(-1);
5242             }
5243             mPhoneSignalStrengthBin = strengthBin;
5244         }
5245 
5246         if (newHistory) {
5247             addHistoryRecordLocked(elapsedRealtime, uptime);
5248         }
5249     }
5250 
5251     /**
5252      * Telephony stack updates the phone state.
5253      * @param state phone state from ServiceState.getState()
5254      */
notePhoneStateLocked(int state, int simState)5255     public void notePhoneStateLocked(int state, int simState) {
5256         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
5257     }
5258 
5259     @UnsupportedAppUsage
notePhoneSignalStrengthLocked(SignalStrength signalStrength)5260     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
5261         // Bin the strength.
5262         int bin = signalStrength.getLevel();
5263         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
5264     }
5265 
5266     @UnsupportedAppUsage
notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType)5267     public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType) {
5268         // BatteryStats uses 0 to represent no network type.
5269         // Telephony does not have a concept of no network type, and uses 0 to represent unknown.
5270         // Unknown is included in DATA_CONNECTION_OTHER.
5271         int bin = DATA_CONNECTION_OUT_OF_SERVICE;
5272         if (hasData) {
5273             if (dataType > 0 && dataType <= TelephonyManager.getAllNetworkTypes().length) {
5274                 bin = dataType;
5275             } else {
5276                 switch (serviceType) {
5277                     case ServiceState.STATE_OUT_OF_SERVICE:
5278                         bin = DATA_CONNECTION_OUT_OF_SERVICE;
5279                         break;
5280                     case ServiceState.STATE_EMERGENCY_ONLY:
5281                         bin = DATA_CONNECTION_EMERGENCY_SERVICE;
5282                         break;
5283                     default:
5284                         bin = DATA_CONNECTION_OTHER;
5285                         break;
5286                 }
5287             }
5288         }
5289         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
5290         if (mPhoneDataConnectionType != bin) {
5291             final long elapsedRealtime = mClocks.elapsedRealtime();
5292             final long uptime = mClocks.uptimeMillis();
5293             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
5294                     | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
5295             if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
5296                     + Integer.toHexString(mHistoryCur.states));
5297             addHistoryRecordLocked(elapsedRealtime, uptime);
5298             if (mPhoneDataConnectionType >= 0) {
5299                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
5300                         elapsedRealtime);
5301             }
5302             mPhoneDataConnectionType = bin;
5303             mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime);
5304         }
5305     }
5306 
noteWifiOnLocked()5307     public void noteWifiOnLocked() {
5308         if (!mWifiOn) {
5309             final long elapsedRealtime = mClocks.elapsedRealtime();
5310             final long uptime = mClocks.uptimeMillis();
5311             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
5312             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
5313                     + Integer.toHexString(mHistoryCur.states));
5314             addHistoryRecordLocked(elapsedRealtime, uptime);
5315             mWifiOn = true;
5316             mWifiOnTimer.startRunningLocked(elapsedRealtime);
5317             scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
5318         }
5319     }
5320 
noteWifiOffLocked()5321     public void noteWifiOffLocked() {
5322         final long elapsedRealtime = mClocks.elapsedRealtime();
5323         final long uptime = mClocks.uptimeMillis();
5324         if (mWifiOn) {
5325             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
5326             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
5327                     + Integer.toHexString(mHistoryCur.states));
5328             addHistoryRecordLocked(elapsedRealtime, uptime);
5329             mWifiOn = false;
5330             mWifiOnTimer.stopRunningLocked(elapsedRealtime);
5331             scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
5332         }
5333     }
5334 
5335     @UnsupportedAppUsage
noteAudioOnLocked(int uid)5336     public void noteAudioOnLocked(int uid) {
5337         uid = mapUid(uid);
5338         final long elapsedRealtime = mClocks.elapsedRealtime();
5339         final long uptime = mClocks.uptimeMillis();
5340         if (mAudioOnNesting == 0) {
5341             mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
5342             if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
5343                     + Integer.toHexString(mHistoryCur.states));
5344             addHistoryRecordLocked(elapsedRealtime, uptime);
5345             mAudioOnTimer.startRunningLocked(elapsedRealtime);
5346         }
5347         mAudioOnNesting++;
5348         getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
5349     }
5350 
5351     @UnsupportedAppUsage
noteAudioOffLocked(int uid)5352     public void noteAudioOffLocked(int uid) {
5353         if (mAudioOnNesting == 0) {
5354             return;
5355         }
5356         uid = mapUid(uid);
5357         final long elapsedRealtime = mClocks.elapsedRealtime();
5358         final long uptime = mClocks.uptimeMillis();
5359         if (--mAudioOnNesting == 0) {
5360             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
5361             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
5362                     + Integer.toHexString(mHistoryCur.states));
5363             addHistoryRecordLocked(elapsedRealtime, uptime);
5364             mAudioOnTimer.stopRunningLocked(elapsedRealtime);
5365         }
5366         getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
5367     }
5368 
5369     @UnsupportedAppUsage
noteVideoOnLocked(int uid)5370     public void noteVideoOnLocked(int uid) {
5371         uid = mapUid(uid);
5372         final long elapsedRealtime = mClocks.elapsedRealtime();
5373         final long uptime = mClocks.uptimeMillis();
5374         if (mVideoOnNesting == 0) {
5375             mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
5376             if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
5377                     + Integer.toHexString(mHistoryCur.states));
5378             addHistoryRecordLocked(elapsedRealtime, uptime);
5379             mVideoOnTimer.startRunningLocked(elapsedRealtime);
5380         }
5381         mVideoOnNesting++;
5382         getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
5383     }
5384 
5385     @UnsupportedAppUsage
noteVideoOffLocked(int uid)5386     public void noteVideoOffLocked(int uid) {
5387         if (mVideoOnNesting == 0) {
5388             return;
5389         }
5390         uid = mapUid(uid);
5391         final long elapsedRealtime = mClocks.elapsedRealtime();
5392         final long uptime = mClocks.uptimeMillis();
5393         if (--mVideoOnNesting == 0) {
5394             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
5395             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
5396                     + Integer.toHexString(mHistoryCur.states));
5397             addHistoryRecordLocked(elapsedRealtime, uptime);
5398             mVideoOnTimer.stopRunningLocked(elapsedRealtime);
5399         }
5400         getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime);
5401     }
5402 
noteResetAudioLocked()5403     public void noteResetAudioLocked() {
5404         if (mAudioOnNesting > 0) {
5405             final long elapsedRealtime = mClocks.elapsedRealtime();
5406             final long uptime = mClocks.uptimeMillis();
5407             mAudioOnNesting = 0;
5408             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
5409             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
5410                     + Integer.toHexString(mHistoryCur.states));
5411             addHistoryRecordLocked(elapsedRealtime, uptime);
5412             mAudioOnTimer.stopAllRunningLocked(elapsedRealtime);
5413             for (int i=0; i<mUidStats.size(); i++) {
5414                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5415                 uid.noteResetAudioLocked(elapsedRealtime);
5416             }
5417         }
5418     }
5419 
noteResetVideoLocked()5420     public void noteResetVideoLocked() {
5421         if (mVideoOnNesting > 0) {
5422             final long elapsedRealtime = mClocks.elapsedRealtime();
5423             final long uptime = mClocks.uptimeMillis();
5424             mVideoOnNesting = 0;
5425             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
5426             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
5427                     + Integer.toHexString(mHistoryCur.states));
5428             addHistoryRecordLocked(elapsedRealtime, uptime);
5429             mVideoOnTimer.stopAllRunningLocked(elapsedRealtime);
5430             for (int i=0; i<mUidStats.size(); i++) {
5431                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5432                 uid.noteResetVideoLocked(elapsedRealtime);
5433             }
5434         }
5435     }
5436 
noteActivityResumedLocked(int uid)5437     public void noteActivityResumedLocked(int uid) {
5438         uid = mapUid(uid);
5439         getUidStatsLocked(uid).noteActivityResumedLocked(mClocks.elapsedRealtime());
5440     }
5441 
noteActivityPausedLocked(int uid)5442     public void noteActivityPausedLocked(int uid) {
5443         uid = mapUid(uid);
5444         getUidStatsLocked(uid).noteActivityPausedLocked(mClocks.elapsedRealtime());
5445     }
5446 
noteVibratorOnLocked(int uid, long durationMillis)5447     public void noteVibratorOnLocked(int uid, long durationMillis) {
5448         uid = mapUid(uid);
5449         getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis);
5450     }
5451 
noteVibratorOffLocked(int uid)5452     public void noteVibratorOffLocked(int uid) {
5453         uid = mapUid(uid);
5454         getUidStatsLocked(uid).noteVibratorOffLocked();
5455     }
5456 
noteFlashlightOnLocked(int uid)5457     public void noteFlashlightOnLocked(int uid) {
5458         uid = mapUid(uid);
5459         final long elapsedRealtime = mClocks.elapsedRealtime();
5460         final long uptime = mClocks.uptimeMillis();
5461         if (mFlashlightOnNesting++ == 0) {
5462             mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
5463             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
5464                     + Integer.toHexString(mHistoryCur.states2));
5465             addHistoryRecordLocked(elapsedRealtime, uptime);
5466             mFlashlightOnTimer.startRunningLocked(elapsedRealtime);
5467         }
5468         getUidStatsLocked(uid).noteFlashlightTurnedOnLocked(elapsedRealtime);
5469     }
5470 
noteFlashlightOffLocked(int uid)5471     public void noteFlashlightOffLocked(int uid) {
5472         if (mFlashlightOnNesting == 0) {
5473             return;
5474         }
5475         uid = mapUid(uid);
5476         final long elapsedRealtime = mClocks.elapsedRealtime();
5477         final long uptime = mClocks.uptimeMillis();
5478         if (--mFlashlightOnNesting == 0) {
5479             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
5480             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
5481                     + Integer.toHexString(mHistoryCur.states2));
5482             addHistoryRecordLocked(elapsedRealtime, uptime);
5483             mFlashlightOnTimer.stopRunningLocked(elapsedRealtime);
5484         }
5485         getUidStatsLocked(uid).noteFlashlightTurnedOffLocked(elapsedRealtime);
5486     }
5487 
noteCameraOnLocked(int uid)5488     public void noteCameraOnLocked(int uid) {
5489         uid = mapUid(uid);
5490         final long elapsedRealtime = mClocks.elapsedRealtime();
5491         final long uptime = mClocks.uptimeMillis();
5492         if (mCameraOnNesting++ == 0) {
5493             mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
5494             if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
5495                     + Integer.toHexString(mHistoryCur.states2));
5496             addHistoryRecordLocked(elapsedRealtime, uptime);
5497             mCameraOnTimer.startRunningLocked(elapsedRealtime);
5498         }
5499         getUidStatsLocked(uid).noteCameraTurnedOnLocked(elapsedRealtime);
5500     }
5501 
noteCameraOffLocked(int uid)5502     public void noteCameraOffLocked(int uid) {
5503         if (mCameraOnNesting == 0) {
5504             return;
5505         }
5506         uid = mapUid(uid);
5507         final long elapsedRealtime = mClocks.elapsedRealtime();
5508         final long uptime = mClocks.uptimeMillis();
5509         if (--mCameraOnNesting == 0) {
5510             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
5511             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
5512                     + Integer.toHexString(mHistoryCur.states2));
5513             addHistoryRecordLocked(elapsedRealtime, uptime);
5514             mCameraOnTimer.stopRunningLocked(elapsedRealtime);
5515         }
5516         getUidStatsLocked(uid).noteCameraTurnedOffLocked(elapsedRealtime);
5517     }
5518 
noteResetCameraLocked()5519     public void noteResetCameraLocked() {
5520         if (mCameraOnNesting > 0) {
5521             final long elapsedRealtime = mClocks.elapsedRealtime();
5522             final long uptime = mClocks.uptimeMillis();
5523             mCameraOnNesting = 0;
5524             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
5525             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
5526                     + Integer.toHexString(mHistoryCur.states2));
5527             addHistoryRecordLocked(elapsedRealtime, uptime);
5528             mCameraOnTimer.stopAllRunningLocked(elapsedRealtime);
5529             for (int i=0; i<mUidStats.size(); i++) {
5530                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5531                 uid.noteResetCameraLocked(elapsedRealtime);
5532             }
5533         }
5534     }
5535 
noteResetFlashlightLocked()5536     public void noteResetFlashlightLocked() {
5537         if (mFlashlightOnNesting > 0) {
5538             final long elapsedRealtime = mClocks.elapsedRealtime();
5539             final long uptime = mClocks.uptimeMillis();
5540             mFlashlightOnNesting = 0;
5541             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
5542             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
5543                     + Integer.toHexString(mHistoryCur.states2));
5544             addHistoryRecordLocked(elapsedRealtime, uptime);
5545             mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtime);
5546             for (int i=0; i<mUidStats.size(); i++) {
5547                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5548                 uid.noteResetFlashlightLocked(elapsedRealtime);
5549             }
5550         }
5551     }
5552 
noteBluetoothScanStartedLocked(WorkChain workChain, int uid, boolean isUnoptimized)5553     private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
5554             boolean isUnoptimized) {
5555         uid = getAttributionUid(uid, workChain);
5556         final long elapsedRealtime = mClocks.elapsedRealtime();
5557         final long uptime = mClocks.uptimeMillis();
5558         if (mBluetoothScanNesting == 0) {
5559             mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5560             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
5561                     + Integer.toHexString(mHistoryCur.states2));
5562             addHistoryRecordLocked(elapsedRealtime, uptime);
5563             mBluetoothScanTimer.startRunningLocked(elapsedRealtime);
5564         }
5565         mBluetoothScanNesting++;
5566         getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime, isUnoptimized);
5567     }
5568 
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized)5569     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
5570         final int N = ws.size();
5571         for (int i = 0; i < N; i++) {
5572             noteBluetoothScanStartedLocked(null, ws.get(i), isUnoptimized);
5573         }
5574 
5575         final List<WorkChain> workChains = ws.getWorkChains();
5576         if (workChains != null) {
5577             for (int i = 0; i < workChains.size(); ++i) {
5578                 noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized);
5579             }
5580         }
5581     }
5582 
noteBluetoothScanStoppedLocked(WorkChain workChain, int uid, boolean isUnoptimized)5583     private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
5584             boolean isUnoptimized) {
5585         uid = getAttributionUid(uid, workChain);
5586         final long elapsedRealtime = mClocks.elapsedRealtime();
5587         final long uptime = mClocks.uptimeMillis();
5588         mBluetoothScanNesting--;
5589         if (mBluetoothScanNesting == 0) {
5590             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5591             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
5592                     + Integer.toHexString(mHistoryCur.states2));
5593             addHistoryRecordLocked(elapsedRealtime, uptime);
5594             mBluetoothScanTimer.stopRunningLocked(elapsedRealtime);
5595         }
5596         getUidStatsLocked(uid).noteBluetoothScanStoppedLocked(elapsedRealtime, isUnoptimized);
5597     }
5598 
getAttributionUid(int uid, WorkChain workChain)5599     private int getAttributionUid(int uid, WorkChain workChain) {
5600         if (workChain != null) {
5601             return mapUid(workChain.getAttributionUid());
5602         }
5603 
5604         return mapUid(uid);
5605     }
5606 
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized)5607     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
5608         final int N = ws.size();
5609         for (int i = 0; i < N; i++) {
5610             noteBluetoothScanStoppedLocked(null, ws.get(i), isUnoptimized);
5611         }
5612 
5613         final List<WorkChain> workChains = ws.getWorkChains();
5614         if (workChains != null) {
5615             for (int i = 0; i < workChains.size(); ++i) {
5616                 noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized);
5617             }
5618         }
5619     }
5620 
noteResetBluetoothScanLocked()5621     public void noteResetBluetoothScanLocked() {
5622         if (mBluetoothScanNesting > 0) {
5623             final long elapsedRealtime = mClocks.elapsedRealtime();
5624             final long uptime = mClocks.uptimeMillis();
5625             mBluetoothScanNesting = 0;
5626             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5627             if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
5628                     + Integer.toHexString(mHistoryCur.states2));
5629             addHistoryRecordLocked(elapsedRealtime, uptime);
5630             mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtime);
5631             for (int i=0; i<mUidStats.size(); i++) {
5632                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5633                 uid.noteResetBluetoothScanLocked(elapsedRealtime);
5634             }
5635         }
5636     }
5637 
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults)5638     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
5639         final int N = ws.size();
5640         for (int i = 0; i < N; i++) {
5641             int uid = mapUid(ws.get(i));
5642             getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
5643         }
5644 
5645         final List<WorkChain> workChains = ws.getWorkChains();
5646         if (workChains != null) {
5647             for (int i = 0; i < workChains.size(); ++i) {
5648                 final WorkChain wc = workChains.get(i);
5649                 int uid = mapUid(wc.getAttributionUid());
5650                 getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
5651             }
5652         }
5653     }
5654 
noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)5655     private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
5656             final long uptimeMillis, int uid) {
5657         uid = mapUid(uid);
5658         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
5659                 uid);
5660         getUidStatsLocked(uid).noteWifiRadioApWakeupLocked();
5661     }
5662 
noteWifiRadioPowerState(int powerState, long timestampNs, int uid)5663     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) {
5664         final long elapsedRealtime = mClocks.elapsedRealtime();
5665         final long uptime = mClocks.uptimeMillis();
5666         if (mWifiRadioPowerState != powerState) {
5667             final boolean active =
5668                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
5669                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
5670             if (active) {
5671                 if (uid > 0) {
5672                     noteWifiRadioApWakeupLocked(elapsedRealtime, uptime, uid);
5673                 }
5674                 mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
5675                 mWifiActiveTimer.startRunningLocked(elapsedRealtime);
5676             } else {
5677                 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
5678                 mWifiActiveTimer.stopRunningLocked(
5679                     timestampNs / (1000 * 1000));
5680             }
5681             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
5682                     + Integer.toHexString(mHistoryCur.states));
5683             addHistoryRecordLocked(elapsedRealtime, uptime);
5684             mWifiRadioPowerState = powerState;
5685         }
5686     }
5687 
noteWifiRunningLocked(WorkSource ws)5688     public void noteWifiRunningLocked(WorkSource ws) {
5689         if (!mGlobalWifiRunning) {
5690             final long elapsedRealtime = mClocks.elapsedRealtime();
5691             final long uptime = mClocks.uptimeMillis();
5692             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
5693             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
5694                     + Integer.toHexString(mHistoryCur.states));
5695             addHistoryRecordLocked(elapsedRealtime, uptime);
5696             mGlobalWifiRunning = true;
5697             mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
5698             int N = ws.size();
5699             for (int i=0; i<N; i++) {
5700                 int uid = mapUid(ws.get(i));
5701                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5702             }
5703 
5704             List<WorkChain> workChains = ws.getWorkChains();
5705             if (workChains != null) {
5706                 for (int i = 0; i < workChains.size(); ++i) {
5707                     int uid = mapUid(workChains.get(i).getAttributionUid());
5708                     getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5709                 }
5710             }
5711 
5712             scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
5713         } else {
5714             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
5715         }
5716     }
5717 
noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs)5718     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
5719         if (mGlobalWifiRunning) {
5720             final long elapsedRealtime = mClocks.elapsedRealtime();
5721             int N = oldWs.size();
5722             for (int i=0; i<N; i++) {
5723                 int uid = mapUid(oldWs.get(i));
5724                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5725             }
5726 
5727             List<WorkChain> workChains = oldWs.getWorkChains();
5728             if (workChains != null) {
5729                 for (int i = 0; i < workChains.size(); ++i) {
5730                     int uid = mapUid(workChains.get(i).getAttributionUid());
5731                     getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5732                 }
5733             }
5734 
5735             N = newWs.size();
5736             for (int i=0; i<N; i++) {
5737                 int uid = mapUid(newWs.get(i));
5738                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5739             }
5740 
5741             workChains = newWs.getWorkChains();
5742             if (workChains != null) {
5743                 for (int i = 0; i < workChains.size(); ++i) {
5744                     int uid = mapUid(workChains.get(i).getAttributionUid());
5745                     getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5746                 }
5747             }
5748         } else {
5749             Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
5750         }
5751     }
5752 
noteWifiStoppedLocked(WorkSource ws)5753     public void noteWifiStoppedLocked(WorkSource ws) {
5754         if (mGlobalWifiRunning) {
5755             final long elapsedRealtime = mClocks.elapsedRealtime();
5756             final long uptime = mClocks.uptimeMillis();
5757             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
5758             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
5759                     + Integer.toHexString(mHistoryCur.states));
5760             addHistoryRecordLocked(elapsedRealtime, uptime);
5761             mGlobalWifiRunning = false;
5762             mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
5763             int N = ws.size();
5764             for (int i=0; i<N; i++) {
5765                 int uid = mapUid(ws.get(i));
5766                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5767             }
5768 
5769             List<WorkChain> workChains = ws.getWorkChains();
5770             if (workChains != null) {
5771                 for (int i = 0; i < workChains.size(); ++i) {
5772                     int uid = mapUid(workChains.get(i).getAttributionUid());
5773                     getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5774                 }
5775             }
5776 
5777             scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
5778         } else {
5779             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
5780         }
5781     }
5782 
noteWifiStateLocked(int wifiState, String accessPoint)5783     public void noteWifiStateLocked(int wifiState, String accessPoint) {
5784         if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
5785         if (mWifiState != wifiState) {
5786             final long elapsedRealtime = mClocks.elapsedRealtime();
5787             if (mWifiState >= 0) {
5788                 mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
5789             }
5790             mWifiState = wifiState;
5791             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
5792             scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
5793         }
5794     }
5795 
noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth)5796     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
5797         if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
5798         if (mWifiSupplState != supplState) {
5799             final long elapsedRealtime = mClocks.elapsedRealtime();
5800             final long uptime = mClocks.uptimeMillis();
5801             if (mWifiSupplState >= 0) {
5802                 mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime);
5803             }
5804             mWifiSupplState = supplState;
5805             mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtime);
5806             mHistoryCur.states2 =
5807                     (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
5808                     | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
5809             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
5810                     + Integer.toHexString(mHistoryCur.states2));
5811             addHistoryRecordLocked(elapsedRealtime, uptime);
5812         }
5813     }
5814 
stopAllWifiSignalStrengthTimersLocked(int except)5815     void stopAllWifiSignalStrengthTimersLocked(int except) {
5816         final long elapsedRealtime = mClocks.elapsedRealtime();
5817         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
5818             if (i == except) {
5819                 continue;
5820             }
5821             while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
5822                 mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
5823             }
5824         }
5825     }
5826 
noteWifiRssiChangedLocked(int newRssi)5827     public void noteWifiRssiChangedLocked(int newRssi) {
5828         int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
5829         if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
5830         if (mWifiSignalStrengthBin != strengthBin) {
5831             final long elapsedRealtime = mClocks.elapsedRealtime();
5832             final long uptime = mClocks.uptimeMillis();
5833             if (mWifiSignalStrengthBin >= 0) {
5834                 mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
5835                         elapsedRealtime);
5836             }
5837             if (strengthBin >= 0) {
5838                 if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
5839                     mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
5840                 }
5841                 mHistoryCur.states2 =
5842                         (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
5843                         | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
5844                 if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
5845                         + Integer.toHexString(mHistoryCur.states2));
5846                 addHistoryRecordLocked(elapsedRealtime, uptime);
5847             } else {
5848                 stopAllWifiSignalStrengthTimersLocked(-1);
5849             }
5850             mWifiSignalStrengthBin = strengthBin;
5851         }
5852     }
5853 
5854     int mWifiFullLockNesting = 0;
5855 
5856     @UnsupportedAppUsage
noteFullWifiLockAcquiredLocked(int uid)5857     public void noteFullWifiLockAcquiredLocked(int uid) {
5858         final long elapsedRealtime = mClocks.elapsedRealtime();
5859         final long uptime = mClocks.uptimeMillis();
5860         if (mWifiFullLockNesting == 0) {
5861             mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
5862             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
5863                     + Integer.toHexString(mHistoryCur.states));
5864             addHistoryRecordLocked(elapsedRealtime, uptime);
5865         }
5866         mWifiFullLockNesting++;
5867         getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
5868     }
5869 
5870     @UnsupportedAppUsage
noteFullWifiLockReleasedLocked(int uid)5871     public void noteFullWifiLockReleasedLocked(int uid) {
5872         final long elapsedRealtime = mClocks.elapsedRealtime();
5873         final long uptime = mClocks.uptimeMillis();
5874         mWifiFullLockNesting--;
5875         if (mWifiFullLockNesting == 0) {
5876             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
5877             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
5878                     + Integer.toHexString(mHistoryCur.states));
5879             addHistoryRecordLocked(elapsedRealtime, uptime);
5880         }
5881         getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime);
5882     }
5883 
5884     int mWifiScanNesting = 0;
5885 
noteWifiScanStartedLocked(int uid)5886     public void noteWifiScanStartedLocked(int uid) {
5887         final long elapsedRealtime = mClocks.elapsedRealtime();
5888         final long uptime = mClocks.uptimeMillis();
5889         if (mWifiScanNesting == 0) {
5890             mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
5891             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
5892                     + Integer.toHexString(mHistoryCur.states));
5893             addHistoryRecordLocked(elapsedRealtime, uptime);
5894         }
5895         mWifiScanNesting++;
5896         getUidStatsLocked(uid).noteWifiScanStartedLocked(elapsedRealtime);
5897     }
5898 
noteWifiScanStoppedLocked(int uid)5899     public void noteWifiScanStoppedLocked(int uid) {
5900         final long elapsedRealtime = mClocks.elapsedRealtime();
5901         final long uptime = mClocks.uptimeMillis();
5902         mWifiScanNesting--;
5903         if (mWifiScanNesting == 0) {
5904             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
5905             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
5906                     + Integer.toHexString(mHistoryCur.states));
5907             addHistoryRecordLocked(elapsedRealtime, uptime);
5908         }
5909         getUidStatsLocked(uid).noteWifiScanStoppedLocked(elapsedRealtime);
5910     }
5911 
noteWifiBatchedScanStartedLocked(int uid, int csph)5912     public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
5913         uid = mapUid(uid);
5914         final long elapsedRealtime = mClocks.elapsedRealtime();
5915         getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime);
5916     }
5917 
noteWifiBatchedScanStoppedLocked(int uid)5918     public void noteWifiBatchedScanStoppedLocked(int uid) {
5919         uid = mapUid(uid);
5920         final long elapsedRealtime = mClocks.elapsedRealtime();
5921         getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime);
5922     }
5923 
5924     int mWifiMulticastNesting = 0;
5925 
5926     @UnsupportedAppUsage
noteWifiMulticastEnabledLocked(int uid)5927     public void noteWifiMulticastEnabledLocked(int uid) {
5928         uid = mapUid(uid);
5929         final long elapsedRealtime = mClocks.elapsedRealtime();
5930         final long uptime = mClocks.uptimeMillis();
5931         if (mWifiMulticastNesting == 0) {
5932             mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
5933             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
5934                     + Integer.toHexString(mHistoryCur.states));
5935             addHistoryRecordLocked(elapsedRealtime, uptime);
5936 
5937             // Start Wifi Multicast overall timer
5938             if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
5939                 if (DEBUG_HISTORY) Slog.v(TAG, "WiFi Multicast Overall Timer Started");
5940                 mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtime);
5941             }
5942         }
5943         mWifiMulticastNesting++;
5944         getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
5945     }
5946 
5947     @UnsupportedAppUsage
noteWifiMulticastDisabledLocked(int uid)5948     public void noteWifiMulticastDisabledLocked(int uid) {
5949         uid = mapUid(uid);
5950         final long elapsedRealtime = mClocks.elapsedRealtime();
5951         final long uptime = mClocks.uptimeMillis();
5952         mWifiMulticastNesting--;
5953         if (mWifiMulticastNesting == 0) {
5954             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
5955             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
5956                     + Integer.toHexString(mHistoryCur.states));
5957             addHistoryRecordLocked(elapsedRealtime, uptime);
5958 
5959             // Stop Wifi Multicast overall timer
5960             if (mWifiMulticastWakelockTimer.isRunningLocked()) {
5961                 if (DEBUG_HISTORY) Slog.v(TAG, "Multicast Overall Timer Stopped");
5962                 mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtime);
5963             }
5964         }
5965         getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime);
5966     }
5967 
noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws)5968     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
5969         int N = ws.size();
5970         for (int i=0; i<N; i++) {
5971             final int uid = mapUid(ws.get(i));
5972             noteFullWifiLockAcquiredLocked(uid);
5973         }
5974 
5975         final List<WorkChain> workChains = ws.getWorkChains();
5976         if (workChains != null) {
5977             for (int i = 0; i < workChains.size(); ++i) {
5978                 final WorkChain workChain = workChains.get(i);
5979                 final int uid = mapUid(workChain.getAttributionUid());
5980                 noteFullWifiLockAcquiredLocked(uid);
5981             }
5982         }
5983     }
5984 
noteFullWifiLockReleasedFromSourceLocked(WorkSource ws)5985     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
5986         int N = ws.size();
5987         for (int i=0; i<N; i++) {
5988             final int uid = mapUid(ws.get(i));
5989             noteFullWifiLockReleasedLocked(uid);
5990         }
5991 
5992         final List<WorkChain> workChains = ws.getWorkChains();
5993         if (workChains != null) {
5994             for (int i = 0; i < workChains.size(); ++i) {
5995                 final WorkChain workChain = workChains.get(i);
5996                 final int uid = mapUid(workChain.getAttributionUid());
5997                 noteFullWifiLockReleasedLocked(uid);
5998             }
5999         }
6000     }
6001 
noteWifiScanStartedFromSourceLocked(WorkSource ws)6002     public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
6003         int N = ws.size();
6004         for (int i=0; i<N; i++) {
6005             final int uid = mapUid(ws.get(i));
6006             noteWifiScanStartedLocked(uid);
6007         }
6008 
6009         final List<WorkChain> workChains = ws.getWorkChains();
6010         if (workChains != null) {
6011             for (int i = 0; i < workChains.size(); ++i) {
6012                 final WorkChain workChain = workChains.get(i);
6013                 final int uid = mapUid(workChain.getAttributionUid());
6014                 noteWifiScanStartedLocked(uid);
6015             }
6016         }
6017     }
6018 
noteWifiScanStoppedFromSourceLocked(WorkSource ws)6019     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
6020         int N = ws.size();
6021         for (int i=0; i<N; i++) {
6022             final int uid = mapUid(ws.get(i));
6023             noteWifiScanStoppedLocked(uid);
6024         }
6025 
6026         final List<WorkChain> workChains = ws.getWorkChains();
6027         if (workChains != null) {
6028             for (int i = 0; i < workChains.size(); ++i) {
6029                 final WorkChain workChain = workChains.get(i);
6030                 final int uid = mapUid(workChain.getAttributionUid());
6031                 noteWifiScanStoppedLocked(uid);
6032             }
6033         }
6034     }
6035 
noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph)6036     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
6037         int N = ws.size();
6038         for (int i=0; i<N; i++) {
6039             noteWifiBatchedScanStartedLocked(ws.get(i), csph);
6040         }
6041 
6042         final List<WorkChain> workChains = ws.getWorkChains();
6043         if (workChains != null) {
6044             for (int i = 0; i < workChains.size(); ++i) {
6045                 noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph);
6046             }
6047         }
6048     }
6049 
noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws)6050     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
6051         int N = ws.size();
6052         for (int i=0; i<N; i++) {
6053             noteWifiBatchedScanStoppedLocked(ws.get(i));
6054         }
6055 
6056         final List<WorkChain> workChains = ws.getWorkChains();
6057         if (workChains != null) {
6058             for (int i = 0; i < workChains.size(); ++i) {
6059                 noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid());
6060             }
6061         }
6062     }
6063 
includeInStringArray(String[] array, String str)6064     private static String[] includeInStringArray(String[] array, String str) {
6065         if (ArrayUtils.indexOf(array, str) >= 0) {
6066             return array;
6067         }
6068         String[] newArray = new String[array.length+1];
6069         System.arraycopy(array, 0, newArray, 0, array.length);
6070         newArray[array.length] = str;
6071         return newArray;
6072     }
6073 
excludeFromStringArray(String[] array, String str)6074     private static String[] excludeFromStringArray(String[] array, String str) {
6075         int index = ArrayUtils.indexOf(array, str);
6076         if (index >= 0) {
6077             String[] newArray = new String[array.length-1];
6078             if (index > 0) {
6079                 System.arraycopy(array, 0, newArray, 0, index);
6080             }
6081             if (index < array.length-1) {
6082                 System.arraycopy(array, index+1, newArray, index, array.length-index-1);
6083             }
6084             return newArray;
6085         }
6086         return array;
6087     }
6088 
noteNetworkInterfaceTypeLocked(String iface, int networkType)6089     public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
6090         if (TextUtils.isEmpty(iface)) return;
6091 
6092         synchronized (mModemNetworkLock) {
6093             if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
6094                 mModemIfaces = includeInStringArray(mModemIfaces, iface);
6095                 if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mModemIfaces);
6096             } else {
6097                 mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
6098                 if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mModemIfaces);
6099             }
6100         }
6101 
6102         synchronized (mWifiNetworkLock) {
6103             if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
6104                 mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
6105                 if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
6106             } else {
6107                 mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
6108                 if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
6109             }
6110         }
6111     }
6112 
getWifiIfaces()6113     public String[] getWifiIfaces() {
6114         synchronized (mWifiNetworkLock) {
6115             return mWifiIfaces;
6116         }
6117     }
6118 
getMobileIfaces()6119     public String[] getMobileIfaces() {
6120         synchronized (mModemNetworkLock) {
6121             return mModemIfaces;
6122         }
6123     }
6124 
6125     @UnsupportedAppUsage
getScreenOnTime(long elapsedRealtimeUs, int which)6126     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
6127         return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6128     }
6129 
getScreenOnCount(int which)6130     @Override public int getScreenOnCount(int which) {
6131         return mScreenOnTimer.getCountLocked(which);
6132     }
6133 
getScreenDozeTime(long elapsedRealtimeUs, int which)6134     @Override public long getScreenDozeTime(long elapsedRealtimeUs, int which) {
6135         return mScreenDozeTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6136     }
6137 
getScreenDozeCount(int which)6138     @Override public int getScreenDozeCount(int which) {
6139         return mScreenDozeTimer.getCountLocked(which);
6140     }
6141 
6142     @UnsupportedAppUsage
getScreenBrightnessTime(int brightnessBin, long elapsedRealtimeUs, int which)6143     @Override public long getScreenBrightnessTime(int brightnessBin,
6144             long elapsedRealtimeUs, int which) {
6145         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
6146                 elapsedRealtimeUs, which);
6147     }
6148 
getScreenBrightnessTimer(int brightnessBin)6149     @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
6150         return mScreenBrightnessTimer[brightnessBin];
6151     }
6152 
getInteractiveTime(long elapsedRealtimeUs, int which)6153     @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
6154         return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6155     }
6156 
getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which)6157     @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
6158         return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6159     }
6160 
getPowerSaveModeEnabledCount(int which)6161     @Override public int getPowerSaveModeEnabledCount(int which) {
6162         return mPowerSaveModeEnabledTimer.getCountLocked(which);
6163     }
6164 
getDeviceIdleModeTime(int mode, long elapsedRealtimeUs, int which)6165     @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
6166             int which) {
6167         switch (mode) {
6168             case DEVICE_IDLE_MODE_LIGHT:
6169                 return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6170             case DEVICE_IDLE_MODE_DEEP:
6171                 return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6172         }
6173         return 0;
6174     }
6175 
getDeviceIdleModeCount(int mode, int which)6176     @Override public int getDeviceIdleModeCount(int mode, int which) {
6177         switch (mode) {
6178             case DEVICE_IDLE_MODE_LIGHT:
6179                 return mDeviceIdleModeLightTimer.getCountLocked(which);
6180             case DEVICE_IDLE_MODE_DEEP:
6181                 return mDeviceIdleModeFullTimer.getCountLocked(which);
6182         }
6183         return 0;
6184     }
6185 
getLongestDeviceIdleModeTime(int mode)6186     @Override public long getLongestDeviceIdleModeTime(int mode) {
6187         switch (mode) {
6188             case DEVICE_IDLE_MODE_LIGHT:
6189                 return mLongestLightIdleTime;
6190             case DEVICE_IDLE_MODE_DEEP:
6191                 return mLongestFullIdleTime;
6192         }
6193         return 0;
6194     }
6195 
getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which)6196     @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
6197         switch (mode) {
6198             case DEVICE_IDLE_MODE_LIGHT:
6199                 return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6200             case DEVICE_IDLE_MODE_DEEP:
6201                 return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6202         }
6203         return 0;
6204     }
6205 
getDeviceIdlingCount(int mode, int which)6206     @Override public int getDeviceIdlingCount(int mode, int which) {
6207         switch (mode) {
6208             case DEVICE_IDLE_MODE_LIGHT:
6209                 return mDeviceLightIdlingTimer.getCountLocked(which);
6210             case DEVICE_IDLE_MODE_DEEP:
6211                 return mDeviceIdlingTimer.getCountLocked(which);
6212         }
6213         return 0;
6214     }
6215 
getNumConnectivityChange(int which)6216     @Override public int getNumConnectivityChange(int which) {
6217         return mNumConnectivityChange;
6218     }
6219 
getGpsSignalQualityTime(int strengthBin, long elapsedRealtimeUs, int which)6220     @Override public long getGpsSignalQualityTime(int strengthBin,
6221         long elapsedRealtimeUs, int which) {
6222         if (strengthBin < 0 || strengthBin >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
6223             return 0;
6224         }
6225         return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
6226             elapsedRealtimeUs, which);
6227     }
6228 
getGpsBatteryDrainMaMs()6229     @Override public long getGpsBatteryDrainMaMs() {
6230         final double opVolt = mPowerProfile.getAveragePower(
6231             PowerProfile.POWER_GPS_OPERATING_VOLTAGE) / 1000.0;
6232         if (opVolt == 0) {
6233             return 0;
6234         }
6235         double energyUsedMaMs = 0.0;
6236         final int which = STATS_SINCE_CHARGED;
6237         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
6238         for(int i=0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
6239             energyUsedMaMs
6240                 += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
6241                 * (getGpsSignalQualityTime(i, rawRealtime, which) / 1000);
6242         }
6243         return (long) energyUsedMaMs;
6244     }
6245 
6246     @UnsupportedAppUsage
getPhoneOnTime(long elapsedRealtimeUs, int which)6247     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
6248         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6249     }
6250 
getPhoneOnCount(int which)6251     @Override public int getPhoneOnCount(int which) {
6252         return mPhoneOnTimer.getCountLocked(which);
6253     }
6254 
6255     @UnsupportedAppUsage
getPhoneSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)6256     @Override public long getPhoneSignalStrengthTime(int strengthBin,
6257             long elapsedRealtimeUs, int which) {
6258         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
6259                 elapsedRealtimeUs, which);
6260     }
6261 
6262     @UnsupportedAppUsage
getPhoneSignalScanningTime( long elapsedRealtimeUs, int which)6263     @Override public long getPhoneSignalScanningTime(
6264             long elapsedRealtimeUs, int which) {
6265         return mPhoneSignalScanningTimer.getTotalTimeLocked(
6266                 elapsedRealtimeUs, which);
6267     }
6268 
getPhoneSignalScanningTimer()6269     @Override public Timer getPhoneSignalScanningTimer() {
6270         return mPhoneSignalScanningTimer;
6271     }
6272 
6273     @UnsupportedAppUsage
getPhoneSignalStrengthCount(int strengthBin, int which)6274     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
6275         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
6276     }
6277 
getPhoneSignalStrengthTimer(int strengthBin)6278     @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
6279         return mPhoneSignalStrengthsTimer[strengthBin];
6280     }
6281 
6282     @UnsupportedAppUsage
getPhoneDataConnectionTime(int dataType, long elapsedRealtimeUs, int which)6283     @Override public long getPhoneDataConnectionTime(int dataType,
6284             long elapsedRealtimeUs, int which) {
6285         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
6286                 elapsedRealtimeUs, which);
6287     }
6288 
6289     @UnsupportedAppUsage
getPhoneDataConnectionCount(int dataType, int which)6290     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
6291         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
6292     }
6293 
getPhoneDataConnectionTimer(int dataType)6294     @Override public Timer getPhoneDataConnectionTimer(int dataType) {
6295         return mPhoneDataConnectionsTimer[dataType];
6296     }
6297 
6298     @UnsupportedAppUsage
getMobileRadioActiveTime(long elapsedRealtimeUs, int which)6299     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
6300         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6301     }
6302 
getMobileRadioActiveCount(int which)6303     @Override public int getMobileRadioActiveCount(int which) {
6304         return mMobileRadioActiveTimer.getCountLocked(which);
6305     }
6306 
getMobileRadioActiveAdjustedTime(int which)6307     @Override public long getMobileRadioActiveAdjustedTime(int which) {
6308         return mMobileRadioActiveAdjustedTime.getCountLocked(which);
6309     }
6310 
getMobileRadioActiveUnknownTime(int which)6311     @Override public long getMobileRadioActiveUnknownTime(int which) {
6312         return mMobileRadioActiveUnknownTime.getCountLocked(which);
6313     }
6314 
getMobileRadioActiveUnknownCount(int which)6315     @Override public int getMobileRadioActiveUnknownCount(int which) {
6316         return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
6317     }
6318 
getWifiMulticastWakelockTime( long elapsedRealtimeUs, int which)6319     @Override public long getWifiMulticastWakelockTime(
6320             long elapsedRealtimeUs, int which) {
6321         return mWifiMulticastWakelockTimer.getTotalTimeLocked(
6322                 elapsedRealtimeUs, which);
6323     }
6324 
getWifiMulticastWakelockCount(int which)6325     @Override public int getWifiMulticastWakelockCount(int which) {
6326         return mWifiMulticastWakelockTimer.getCountLocked(which);
6327     }
6328 
6329     @UnsupportedAppUsage
getWifiOnTime(long elapsedRealtimeUs, int which)6330     @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
6331         return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6332     }
6333 
getWifiActiveTime(long elapsedRealtimeUs, int which)6334     @Override public long getWifiActiveTime(long elapsedRealtimeUs, int which) {
6335         return mWifiActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6336     }
6337 
6338     @UnsupportedAppUsage
getGlobalWifiRunningTime(long elapsedRealtimeUs, int which)6339     @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
6340         return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6341     }
6342 
getWifiStateTime(int wifiState, long elapsedRealtimeUs, int which)6343     @Override public long getWifiStateTime(int wifiState,
6344             long elapsedRealtimeUs, int which) {
6345         return mWifiStateTimer[wifiState].getTotalTimeLocked(
6346                 elapsedRealtimeUs, which);
6347     }
6348 
getWifiStateCount(int wifiState, int which)6349     @Override public int getWifiStateCount(int wifiState, int which) {
6350         return mWifiStateTimer[wifiState].getCountLocked(which);
6351     }
6352 
getWifiStateTimer(int wifiState)6353     @Override public Timer getWifiStateTimer(int wifiState) {
6354         return mWifiStateTimer[wifiState];
6355     }
6356 
getWifiSupplStateTime(int state, long elapsedRealtimeUs, int which)6357     @Override public long getWifiSupplStateTime(int state,
6358             long elapsedRealtimeUs, int which) {
6359         return mWifiSupplStateTimer[state].getTotalTimeLocked(
6360                 elapsedRealtimeUs, which);
6361     }
6362 
getWifiSupplStateCount(int state, int which)6363     @Override public int getWifiSupplStateCount(int state, int which) {
6364         return mWifiSupplStateTimer[state].getCountLocked(which);
6365     }
6366 
getWifiSupplStateTimer(int state)6367     @Override public Timer getWifiSupplStateTimer(int state) {
6368         return mWifiSupplStateTimer[state];
6369     }
6370 
getWifiSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)6371     @Override public long getWifiSignalStrengthTime(int strengthBin,
6372             long elapsedRealtimeUs, int which) {
6373         return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
6374                 elapsedRealtimeUs, which);
6375     }
6376 
getWifiSignalStrengthCount(int strengthBin, int which)6377     @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
6378         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
6379     }
6380 
getWifiSignalStrengthTimer(int strengthBin)6381     @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
6382         return mWifiSignalStrengthsTimer[strengthBin];
6383     }
6384 
6385     @Override
getBluetoothControllerActivity()6386     public ControllerActivityCounter getBluetoothControllerActivity() {
6387         return mBluetoothActivity;
6388     }
6389 
6390     @Override
getWifiControllerActivity()6391     public ControllerActivityCounter getWifiControllerActivity() {
6392         return mWifiActivity;
6393     }
6394 
6395     @Override
getModemControllerActivity()6396     public ControllerActivityCounter getModemControllerActivity() {
6397         return mModemActivity;
6398     }
6399 
6400     @Override
hasBluetoothActivityReporting()6401     public boolean hasBluetoothActivityReporting() {
6402         return mHasBluetoothReporting;
6403     }
6404 
6405     @Override
hasWifiActivityReporting()6406     public boolean hasWifiActivityReporting() {
6407         return mHasWifiReporting;
6408     }
6409 
6410     @Override
hasModemActivityReporting()6411     public boolean hasModemActivityReporting() {
6412         return mHasModemReporting;
6413     }
6414 
6415     @Override
getFlashlightOnTime(long elapsedRealtimeUs, int which)6416     public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
6417         return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6418     }
6419 
6420     @Override
getFlashlightOnCount(int which)6421     public long getFlashlightOnCount(int which) {
6422         return mFlashlightOnTimer.getCountLocked(which);
6423     }
6424 
6425     @Override
getCameraOnTime(long elapsedRealtimeUs, int which)6426     public long getCameraOnTime(long elapsedRealtimeUs, int which) {
6427         return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6428     }
6429 
6430     @Override
getBluetoothScanTime(long elapsedRealtimeUs, int which)6431     public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
6432         return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6433     }
6434 
6435     @Override
6436     @UnsupportedAppUsage
getNetworkActivityBytes(int type, int which)6437     public long getNetworkActivityBytes(int type, int which) {
6438         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
6439             return mNetworkByteActivityCounters[type].getCountLocked(which);
6440         } else {
6441             return 0;
6442         }
6443     }
6444 
6445     @Override
getNetworkActivityPackets(int type, int which)6446     public long getNetworkActivityPackets(int type, int which) {
6447         if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
6448             return mNetworkPacketActivityCounters[type].getCountLocked(which);
6449         } else {
6450             return 0;
6451         }
6452     }
6453 
getStartClockTime()6454     @Override public long getStartClockTime() {
6455         final long currentTime = System.currentTimeMillis();
6456         if ((currentTime > MILLISECONDS_IN_YEAR
6457                 && mStartClockTime < (currentTime - MILLISECONDS_IN_YEAR))
6458                 || (mStartClockTime > currentTime)) {
6459             // If the start clock time has changed by more than a year, then presumably
6460             // the previous time was completely bogus.  So we are going to figure out a
6461             // new time based on how much time has elapsed since we started counting.
6462             recordCurrentTimeChangeLocked(currentTime, mClocks.elapsedRealtime(),
6463                     mClocks.uptimeMillis());
6464             return currentTime - (mClocks.elapsedRealtime() - (mRealtimeStart / 1000));
6465         }
6466         return mStartClockTime;
6467     }
6468 
getStartPlatformVersion()6469     @Override public String getStartPlatformVersion() {
6470         return mStartPlatformVersion;
6471     }
6472 
getEndPlatformVersion()6473     @Override public String getEndPlatformVersion() {
6474         return mEndPlatformVersion;
6475     }
6476 
getParcelVersion()6477     @Override public int getParcelVersion() {
6478         return VERSION;
6479     }
6480 
getIsOnBattery()6481     @Override public boolean getIsOnBattery() {
6482         return mOnBattery;
6483     }
6484 
6485     @UnsupportedAppUsage
getUidStats()6486     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
6487         return mUidStats;
6488     }
6489 
resetIfNotNull(T t, boolean detachIfReset)6490     private static <T extends TimeBaseObs> boolean resetIfNotNull(T t, boolean detachIfReset) {
6491         if (t != null) {
6492             return t.reset(detachIfReset);
6493         }
6494         return true;
6495     }
6496 
resetIfNotNull(T[] t, boolean detachIfReset)6497     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[] t, boolean detachIfReset) {
6498         if (t != null) {
6499             boolean ret = true;
6500             for (int i = 0; i < t.length; i++) {
6501                 ret &= resetIfNotNull(t[i], detachIfReset);
6502             }
6503             return ret;
6504         }
6505         return true;
6506     }
6507 
resetIfNotNull(T[][] t, boolean detachIfReset)6508     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[][] t, boolean detachIfReset) {
6509         if (t != null) {
6510             boolean ret = true;
6511             for (int i = 0; i < t.length; i++) {
6512                 ret &= resetIfNotNull(t[i], detachIfReset);
6513             }
6514             return ret;
6515         }
6516         return true;
6517     }
6518 
resetIfNotNull(ControllerActivityCounterImpl counter, boolean detachIfReset)6519     private static boolean resetIfNotNull(ControllerActivityCounterImpl counter,
6520             boolean detachIfReset) {
6521         if (counter != null) {
6522             counter.reset(detachIfReset);
6523         }
6524         return true;
6525     }
6526 
detachIfNotNull(T t)6527     private static <T extends TimeBaseObs> void detachIfNotNull(T t) {
6528         if (t != null) {
6529             t.detach();
6530         }
6531     }
6532 
detachIfNotNull(T[] t)6533     private static <T extends TimeBaseObs> void detachIfNotNull(T[] t) {
6534         if (t != null) {
6535             for (int i = 0; i < t.length; i++) {
6536                 detachIfNotNull(t[i]);
6537             }
6538         }
6539     }
6540 
detachIfNotNull(T[][] t)6541     private static <T extends TimeBaseObs> void detachIfNotNull(T[][] t) {
6542         if (t != null) {
6543             for (int i = 0; i < t.length; i++) {
6544                 detachIfNotNull(t[i]);
6545             }
6546         }
6547     }
6548 
detachIfNotNull(ControllerActivityCounterImpl counter)6549     private static void detachIfNotNull(ControllerActivityCounterImpl counter) {
6550         if (counter != null) {
6551             counter.detach();
6552         }
6553     }
6554 
6555     /**
6556      * The statistics associated with a particular uid.
6557      */
6558     public static class Uid extends BatteryStats.Uid {
6559         /**
6560          * BatteryStatsImpl that we are associated with.
6561          */
6562         protected BatteryStatsImpl mBsi;
6563 
6564         final int mUid;
6565 
6566         /** TimeBase for when uid is in background and device is on battery. */
6567         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
6568         public final TimeBase mOnBatteryBackgroundTimeBase;
6569         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
6570         public final TimeBase mOnBatteryScreenOffBackgroundTimeBase;
6571 
6572         boolean mWifiRunning;
6573         StopwatchTimer mWifiRunningTimer;
6574 
6575         boolean mFullWifiLockOut;
6576         StopwatchTimer mFullWifiLockTimer;
6577 
6578         boolean mWifiScanStarted;
6579         DualTimer mWifiScanTimer;
6580 
6581         static final int NO_BATCHED_SCAN_STARTED = -1;
6582         int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
6583         StopwatchTimer[] mWifiBatchedScanTimer;
6584 
6585         int mWifiMulticastWakelockCount;
6586         StopwatchTimer mWifiMulticastTimer;
6587 
6588         StopwatchTimer mAudioTurnedOnTimer;
6589         StopwatchTimer mVideoTurnedOnTimer;
6590         StopwatchTimer mFlashlightTurnedOnTimer;
6591         StopwatchTimer mCameraTurnedOnTimer;
6592         StopwatchTimer mForegroundActivityTimer;
6593         StopwatchTimer mForegroundServiceTimer;
6594         /** Total time spent by the uid holding any partial wakelocks. */
6595         DualTimer mAggregatedPartialWakelockTimer;
6596         DualTimer mBluetoothScanTimer;
6597         DualTimer mBluetoothUnoptimizedScanTimer;
6598         Counter mBluetoothScanResultCounter;
6599         Counter mBluetoothScanResultBgCounter;
6600 
6601         int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
6602         StopwatchTimer[] mProcessStateTimer;
6603 
6604         boolean mInForegroundService = false;
6605 
6606         BatchTimer mVibratorOnTimer;
6607 
6608         Counter[] mUserActivityCounters;
6609 
6610         LongSamplingCounter[] mNetworkByteActivityCounters;
6611         LongSamplingCounter[] mNetworkPacketActivityCounters;
6612         LongSamplingCounter mMobileRadioActiveTime;
6613         LongSamplingCounter mMobileRadioActiveCount;
6614 
6615         /**
6616          * How many times this UID woke up the Application Processor due to a Mobile radio packet.
6617          */
6618         private LongSamplingCounter mMobileRadioApWakeupCount;
6619 
6620         /**
6621          * How many times this UID woke up the Application Processor due to a Wifi packet.
6622          */
6623         private LongSamplingCounter mWifiRadioApWakeupCount;
6624 
6625         /**
6626          * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
6627          * Can be null if the UID has had no such activity.
6628          */
6629         private ControllerActivityCounterImpl mWifiControllerActivity;
6630 
6631         /**
6632          * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
6633          * Can be null if the UID has had no such activity.
6634          */
6635         private ControllerActivityCounterImpl mBluetoothControllerActivity;
6636 
6637         /**
6638          * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
6639          * Can be null if the UID has had no such activity.
6640          */
6641         private ControllerActivityCounterImpl mModemControllerActivity;
6642 
6643         /**
6644          * The CPU times we had at the last history details update.
6645          */
6646         long mLastStepUserTime;
6647         long mLastStepSystemTime;
6648         long mCurStepUserTime;
6649         long mCurStepSystemTime;
6650 
6651         LongSamplingCounter mUserCpuTime;
6652         LongSamplingCounter mSystemCpuTime;
6653         LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
6654         LongSamplingCounter mCpuActiveTimeMs;
6655 
6656         LongSamplingCounterArray mCpuFreqTimeMs;
6657         LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
6658         LongSamplingCounterArray mCpuClusterTimesMs;
6659 
6660         LongSamplingCounterArray[] mProcStateTimeMs;
6661         LongSamplingCounterArray[] mProcStateScreenOffTimeMs;
6662 
6663         IntArray mChildUids;
6664 
6665         /**
6666          * The statistics we have collected for this uid's wake locks.
6667          */
6668         final OverflowArrayMap<Wakelock> mWakelockStats;
6669 
6670         /**
6671          * The statistics we have collected for this uid's syncs.
6672          */
6673         final OverflowArrayMap<DualTimer> mSyncStats;
6674 
6675         /**
6676          * The statistics we have collected for this uid's jobs.
6677          */
6678         final OverflowArrayMap<DualTimer> mJobStats;
6679 
6680         /**
6681          * Count of the jobs that have completed and the reasons why they completed.
6682          */
6683         final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
6684 
6685         /**
6686          * Count of app launch events that had associated deferred job counts or info about
6687          * last time a job was run.
6688          */
6689         Counter mJobsDeferredEventCount;
6690 
6691         /**
6692          * Count of deferred jobs that were pending when the app was launched or brought to
6693          * the foreground through a user interaction.
6694          */
6695         Counter mJobsDeferredCount;
6696 
6697         /**
6698          * Sum of time since the last time a job was run for this app before it was launched.
6699          */
6700         LongSamplingCounter mJobsFreshnessTimeMs;
6701 
6702         /**
6703          * Array of counts of instances where the time since the last job was run for the app
6704          * fell within one of the thresholds in {@link #JOB_FRESHNESS_BUCKETS}.
6705          */
6706         final Counter[] mJobsFreshnessBuckets;
6707 
6708         /**
6709          * The statistics we have collected for this uid's sensor activations.
6710          */
6711         final SparseArray<Sensor> mSensorStats = new SparseArray<>();
6712 
6713         /**
6714          * The statistics we have collected for this uid's processes.
6715          */
6716         final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
6717 
6718         /**
6719          * The statistics we have collected for this uid's processes.
6720          */
6721         final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
6722 
6723         /**
6724          * The transient wake stats we have collected for this uid's pids.
6725          */
6726         final SparseArray<Pid> mPids = new SparseArray<>();
6727 
Uid(BatteryStatsImpl bsi, int uid)6728         public Uid(BatteryStatsImpl bsi, int uid) {
6729             mBsi = bsi;
6730             mUid = uid;
6731 
6732             /* Observer list of TimeBase object in Uid is short */
6733             mOnBatteryBackgroundTimeBase = new TimeBase(false);
6734             mOnBatteryBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
6735                     mBsi.mClocks.elapsedRealtime() * 1000);
6736             /* Observer list of TimeBase object in Uid is short */
6737             mOnBatteryScreenOffBackgroundTimeBase = new TimeBase(false);
6738             mOnBatteryScreenOffBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
6739                     mBsi.mClocks.elapsedRealtime() * 1000);
6740 
6741             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6742             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6743             mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6744             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase);
6745 
6746             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
6747                 @Override public Wakelock instantiateObject() {
6748                     return new Wakelock(mBsi, Uid.this);
6749                 }
6750             };
6751             mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
6752                 @Override public DualTimer instantiateObject() {
6753                     return new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
6754                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6755                 }
6756             };
6757             mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
6758                 @Override public DualTimer instantiateObject() {
6759                     return new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
6760                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6761                 }
6762             };
6763 
6764             mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_RUNNING,
6765                     mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
6766             mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, this, FULL_WIFI_LOCK,
6767                     mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
6768             mWifiScanTimer = new DualTimer(mBsi.mClocks, this, WIFI_SCAN,
6769                     mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6770             mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
6771             mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_MULTICAST_ENABLED,
6772                     mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
6773             mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
6774             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase);
6775             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase);
6776             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6777             mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length];
6778         }
6779 
6780         @VisibleForTesting
setProcessStateForTest(int procState)6781         public void setProcessStateForTest(int procState) {
6782             mProcessState = procState;
6783         }
6784 
6785         @Override
getCpuFreqTimes(int which)6786         public long[] getCpuFreqTimes(int which) {
6787             return nullIfAllZeros(mCpuFreqTimeMs, which);
6788         }
6789 
6790         @Override
getScreenOffCpuFreqTimes(int which)6791         public long[] getScreenOffCpuFreqTimes(int which) {
6792             return nullIfAllZeros(mScreenOffCpuFreqTimeMs, which);
6793         }
6794 
6795         @Override
getCpuActiveTime()6796         public long getCpuActiveTime() {
6797             return mCpuActiveTimeMs.getCountLocked(STATS_SINCE_CHARGED);
6798         }
6799 
6800         @Override
getCpuClusterTimes()6801         public long[] getCpuClusterTimes() {
6802             return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
6803         }
6804 
6805 
6806         @Override
getCpuFreqTimes(int which, int procState)6807         public long[] getCpuFreqTimes(int which, int procState) {
6808             if (which < 0 || which >= NUM_PROCESS_STATE) {
6809                 return null;
6810             }
6811             if (mProcStateTimeMs == null) {
6812                 return null;
6813             }
6814             if (!mBsi.mPerProcStateCpuTimesAvailable) {
6815                 mProcStateTimeMs = null;
6816                 return null;
6817             }
6818             return nullIfAllZeros(mProcStateTimeMs[procState], which);
6819         }
6820 
6821         @Override
getScreenOffCpuFreqTimes(int which, int procState)6822         public long[] getScreenOffCpuFreqTimes(int which, int procState) {
6823             if (which < 0 || which >= NUM_PROCESS_STATE) {
6824                 return null;
6825             }
6826             if (mProcStateScreenOffTimeMs == null) {
6827                 return null;
6828             }
6829             if (!mBsi.mPerProcStateCpuTimesAvailable) {
6830                 mProcStateScreenOffTimeMs = null;
6831                 return null;
6832             }
6833             return nullIfAllZeros(mProcStateScreenOffTimeMs[procState], which);
6834         }
6835 
addIsolatedUid(int isolatedUid)6836         public void addIsolatedUid(int isolatedUid) {
6837             if (mChildUids == null) {
6838                 mChildUids = new IntArray();
6839             } else if (mChildUids.indexOf(isolatedUid) >= 0) {
6840                 return;
6841             }
6842             mChildUids.add(isolatedUid);
6843         }
6844 
removeIsolatedUid(int isolatedUid)6845         public void removeIsolatedUid(int isolatedUid) {
6846             final int idx = mChildUids == null ? -1 : mChildUids.indexOf(isolatedUid);
6847             if (idx < 0) {
6848                 return;
6849             }
6850             mChildUids.remove(idx);
6851         }
6852 
nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which)6853         private long[] nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which) {
6854             if (cpuTimesMs == null) {
6855                 return null;
6856             }
6857             final long[] counts = cpuTimesMs.getCountsLocked(which);
6858             if (counts == null) {
6859                 return null;
6860             }
6861             // Return counts only if at least one of the elements is non-zero.
6862             for (int i = counts.length - 1; i >= 0; --i) {
6863                 if (counts[i] != 0) {
6864                     return counts;
6865                 }
6866             }
6867             return null;
6868         }
6869 
addProcStateTimesMs(int procState, long[] cpuTimesMs, boolean onBattery)6870         private void addProcStateTimesMs(int procState, long[] cpuTimesMs, boolean onBattery) {
6871             if (mProcStateTimeMs == null) {
6872                 mProcStateTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
6873             }
6874             if (mProcStateTimeMs[procState] == null
6875                     || mProcStateTimeMs[procState].getSize() != cpuTimesMs.length) {
6876                 detachIfNotNull(mProcStateTimeMs[procState]);
6877                 mProcStateTimeMs[procState] = new LongSamplingCounterArray(
6878                         mBsi.mOnBatteryTimeBase);
6879             }
6880             mProcStateTimeMs[procState].addCountLocked(cpuTimesMs, onBattery);
6881         }
6882 
addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs, boolean onBatteryScreenOff)6883         private void addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs,
6884                 boolean onBatteryScreenOff) {
6885             if (mProcStateScreenOffTimeMs == null) {
6886                 mProcStateScreenOffTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
6887             }
6888             if (mProcStateScreenOffTimeMs[procState] == null
6889                     || mProcStateScreenOffTimeMs[procState].getSize() != cpuTimesMs.length) {
6890                 detachIfNotNull(mProcStateScreenOffTimeMs[procState]);
6891                 mProcStateScreenOffTimeMs[procState] = new LongSamplingCounterArray(
6892                         mBsi.mOnBatteryScreenOffTimeBase);
6893             }
6894             mProcStateScreenOffTimeMs[procState].addCountLocked(cpuTimesMs, onBatteryScreenOff);
6895         }
6896 
6897         @Override
getAggregatedPartialWakelockTimer()6898         public Timer getAggregatedPartialWakelockTimer() {
6899             return mAggregatedPartialWakelockTimer;
6900         }
6901 
6902         @Override
6903         @UnsupportedAppUsage
getWakelockStats()6904         public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
6905             return mWakelockStats.getMap();
6906         }
6907 
6908         @Override
getMulticastWakelockStats()6909         public Timer getMulticastWakelockStats() {
6910             return mWifiMulticastTimer;
6911         }
6912 
6913         @Override
getSyncStats()6914         public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
6915             return mSyncStats.getMap();
6916         }
6917 
6918         @Override
getJobStats()6919         public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
6920             return mJobStats.getMap();
6921         }
6922 
6923         @Override
getJobCompletionStats()6924         public ArrayMap<String, SparseIntArray> getJobCompletionStats() {
6925             return mJobCompletions;
6926         }
6927 
6928         @Override
6929         @UnsupportedAppUsage
getSensorStats()6930         public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
6931             return mSensorStats;
6932         }
6933 
6934         @Override
6935         @UnsupportedAppUsage
getProcessStats()6936         public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
6937             return mProcessStats;
6938         }
6939 
6940         @Override
getPackageStats()6941         public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
6942             return mPackageStats;
6943         }
6944 
6945         @Override
6946         @UnsupportedAppUsage
getUid()6947         public int getUid() {
6948             return mUid;
6949         }
6950 
6951         @Override
noteWifiRunningLocked(long elapsedRealtimeMs)6952         public void noteWifiRunningLocked(long elapsedRealtimeMs) {
6953             if (!mWifiRunning) {
6954                 mWifiRunning = true;
6955                 if (mWifiRunningTimer == null) {
6956                     mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
6957                             mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
6958                 }
6959                 mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
6960             }
6961         }
6962 
6963         @Override
noteWifiStoppedLocked(long elapsedRealtimeMs)6964         public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
6965             if (mWifiRunning) {
6966                 mWifiRunning = false;
6967                 mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
6968             }
6969         }
6970 
6971         @Override
noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs)6972         public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
6973             if (!mFullWifiLockOut) {
6974                 mFullWifiLockOut = true;
6975                 if (mFullWifiLockTimer == null) {
6976                     mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
6977                             mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
6978                 }
6979                 mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
6980             }
6981         }
6982 
6983         @Override
noteFullWifiLockReleasedLocked(long elapsedRealtimeMs)6984         public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
6985             if (mFullWifiLockOut) {
6986                 mFullWifiLockOut = false;
6987                 mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
6988             }
6989         }
6990 
6991         @Override
noteWifiScanStartedLocked(long elapsedRealtimeMs)6992         public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
6993             if (!mWifiScanStarted) {
6994                 mWifiScanStarted = true;
6995                 if (mWifiScanTimer == null) {
6996                     mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
6997                             mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase,
6998                             mOnBatteryBackgroundTimeBase);
6999                 }
7000                 mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
7001             }
7002         }
7003 
7004         @Override
noteWifiScanStoppedLocked(long elapsedRealtimeMs)7005         public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
7006             if (mWifiScanStarted) {
7007                 mWifiScanStarted = false;
7008                 mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
7009             }
7010         }
7011 
7012         @Override
noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs)7013         public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
7014             int bin = 0;
7015             while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
7016                 csph = csph >> 3;
7017                 bin++;
7018             }
7019 
7020             if (mWifiBatchedScanBinStarted == bin) return;
7021 
7022             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
7023                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
7024                         stopRunningLocked(elapsedRealtimeMs);
7025             }
7026             mWifiBatchedScanBinStarted = bin;
7027             if (mWifiBatchedScanTimer[bin] == null) {
7028                 makeWifiBatchedScanBin(bin, null);
7029             }
7030             mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
7031         }
7032 
7033         @Override
noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs)7034         public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
7035             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
7036                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
7037                         stopRunningLocked(elapsedRealtimeMs);
7038                 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
7039             }
7040         }
7041 
7042         @Override
noteWifiMulticastEnabledLocked(long elapsedRealtimeMs)7043         public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
7044             if (mWifiMulticastWakelockCount == 0) {
7045                 if (mWifiMulticastTimer == null) {
7046                     mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7047                             WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
7048                 }
7049                 mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
7050             }
7051             mWifiMulticastWakelockCount++;
7052         }
7053 
7054         @Override
noteWifiMulticastDisabledLocked(long elapsedRealtimeMs)7055         public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
7056             if (mWifiMulticastWakelockCount == 0) {
7057                 return;
7058             }
7059 
7060             mWifiMulticastWakelockCount--;
7061             if (mWifiMulticastWakelockCount == 0) {
7062                 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
7063             }
7064         }
7065 
7066         @Override
getWifiControllerActivity()7067         public ControllerActivityCounter getWifiControllerActivity() {
7068             return mWifiControllerActivity;
7069         }
7070 
7071         @Override
getBluetoothControllerActivity()7072         public ControllerActivityCounter getBluetoothControllerActivity() {
7073             return mBluetoothControllerActivity;
7074         }
7075 
7076         @Override
getModemControllerActivity()7077         public ControllerActivityCounter getModemControllerActivity() {
7078             return mModemControllerActivity;
7079         }
7080 
getOrCreateWifiControllerActivityLocked()7081         public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
7082             if (mWifiControllerActivity == null) {
7083                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7084                         NUM_BT_TX_LEVELS);
7085             }
7086             return mWifiControllerActivity;
7087         }
7088 
getOrCreateBluetoothControllerActivityLocked()7089         public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
7090             if (mBluetoothControllerActivity == null) {
7091                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7092                         NUM_BT_TX_LEVELS);
7093             }
7094             return mBluetoothControllerActivity;
7095         }
7096 
getOrCreateModemControllerActivityLocked()7097         public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
7098             if (mModemControllerActivity == null) {
7099                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7100                         ModemActivityInfo.TX_POWER_LEVELS);
7101             }
7102             return mModemControllerActivity;
7103         }
7104 
createAudioTurnedOnTimerLocked()7105         public StopwatchTimer createAudioTurnedOnTimerLocked() {
7106             if (mAudioTurnedOnTimer == null) {
7107                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
7108                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7109             }
7110             return mAudioTurnedOnTimer;
7111         }
7112 
noteAudioTurnedOnLocked(long elapsedRealtimeMs)7113         public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
7114             createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7115         }
7116 
noteAudioTurnedOffLocked(long elapsedRealtimeMs)7117         public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
7118             if (mAudioTurnedOnTimer != null) {
7119                 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7120             }
7121         }
7122 
noteResetAudioLocked(long elapsedRealtimeMs)7123         public void noteResetAudioLocked(long elapsedRealtimeMs) {
7124             if (mAudioTurnedOnTimer != null) {
7125                 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7126             }
7127         }
7128 
createVideoTurnedOnTimerLocked()7129         public StopwatchTimer createVideoTurnedOnTimerLocked() {
7130             if (mVideoTurnedOnTimer == null) {
7131                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
7132                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7133             }
7134             return mVideoTurnedOnTimer;
7135         }
7136 
noteVideoTurnedOnLocked(long elapsedRealtimeMs)7137         public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
7138             createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7139         }
7140 
noteVideoTurnedOffLocked(long elapsedRealtimeMs)7141         public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
7142             if (mVideoTurnedOnTimer != null) {
7143                 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7144             }
7145         }
7146 
noteResetVideoLocked(long elapsedRealtimeMs)7147         public void noteResetVideoLocked(long elapsedRealtimeMs) {
7148             if (mVideoTurnedOnTimer != null) {
7149                 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7150             }
7151         }
7152 
createFlashlightTurnedOnTimerLocked()7153         public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
7154             if (mFlashlightTurnedOnTimer == null) {
7155                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7156                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7157             }
7158             return mFlashlightTurnedOnTimer;
7159         }
7160 
noteFlashlightTurnedOnLocked(long elapsedRealtimeMs)7161         public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
7162             createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7163         }
7164 
noteFlashlightTurnedOffLocked(long elapsedRealtimeMs)7165         public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
7166             if (mFlashlightTurnedOnTimer != null) {
7167                 mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7168             }
7169         }
7170 
noteResetFlashlightLocked(long elapsedRealtimeMs)7171         public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
7172             if (mFlashlightTurnedOnTimer != null) {
7173                 mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7174             }
7175         }
7176 
createCameraTurnedOnTimerLocked()7177         public StopwatchTimer createCameraTurnedOnTimerLocked() {
7178             if (mCameraTurnedOnTimer == null) {
7179                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
7180                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7181             }
7182             return mCameraTurnedOnTimer;
7183         }
7184 
noteCameraTurnedOnLocked(long elapsedRealtimeMs)7185         public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
7186             createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7187         }
7188 
noteCameraTurnedOffLocked(long elapsedRealtimeMs)7189         public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
7190             if (mCameraTurnedOnTimer != null) {
7191                 mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7192             }
7193         }
7194 
noteResetCameraLocked(long elapsedRealtimeMs)7195         public void noteResetCameraLocked(long elapsedRealtimeMs) {
7196             if (mCameraTurnedOnTimer != null) {
7197                 mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7198             }
7199         }
7200 
createForegroundActivityTimerLocked()7201         public StopwatchTimer createForegroundActivityTimerLocked() {
7202             if (mForegroundActivityTimer == null) {
7203                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7204                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
7205             }
7206             return mForegroundActivityTimer;
7207         }
7208 
createForegroundServiceTimerLocked()7209         public StopwatchTimer createForegroundServiceTimerLocked() {
7210             if (mForegroundServiceTimer == null) {
7211                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7212                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase);
7213             }
7214             return mForegroundServiceTimer;
7215         }
7216 
createAggregatedPartialWakelockTimerLocked()7217         public DualTimer createAggregatedPartialWakelockTimerLocked() {
7218             if (mAggregatedPartialWakelockTimer == null) {
7219                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
7220                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
7221                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase);
7222             }
7223             return mAggregatedPartialWakelockTimer;
7224         }
7225 
createBluetoothScanTimerLocked()7226         public DualTimer createBluetoothScanTimerLocked() {
7227             if (mBluetoothScanTimer == null) {
7228                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
7229                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
7230                         mOnBatteryBackgroundTimeBase);
7231             }
7232             return mBluetoothScanTimer;
7233         }
7234 
createBluetoothUnoptimizedScanTimerLocked()7235         public DualTimer createBluetoothUnoptimizedScanTimerLocked() {
7236             if (mBluetoothUnoptimizedScanTimer == null) {
7237                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
7238                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
7239                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
7240             }
7241             return mBluetoothUnoptimizedScanTimer;
7242         }
7243 
noteBluetoothScanStartedLocked(long elapsedRealtimeMs, boolean isUnoptimized)7244         public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs,
7245                 boolean isUnoptimized) {
7246             createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
7247             if (isUnoptimized) {
7248                 createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
7249             }
7250         }
7251 
noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized)7252         public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
7253             if (mBluetoothScanTimer != null) {
7254                 mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
7255             }
7256             if (isUnoptimized && mBluetoothUnoptimizedScanTimer != null) {
7257                 mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs);
7258             }
7259         }
7260 
noteResetBluetoothScanLocked(long elapsedRealtimeMs)7261         public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
7262             if (mBluetoothScanTimer != null) {
7263                 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
7264             }
7265             if (mBluetoothUnoptimizedScanTimer != null) {
7266                 mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
7267             }
7268         }
7269 
createBluetoothScanResultCounterLocked()7270         public Counter createBluetoothScanResultCounterLocked() {
7271             if (mBluetoothScanResultCounter == null) {
7272                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase);
7273             }
7274             return mBluetoothScanResultCounter;
7275         }
7276 
createBluetoothScanResultBgCounterLocked()7277         public Counter createBluetoothScanResultBgCounterLocked() {
7278             if (mBluetoothScanResultBgCounter == null) {
7279                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase);
7280             }
7281             return mBluetoothScanResultBgCounter;
7282         }
7283 
noteBluetoothScanResultsLocked(int numNewResults)7284         public void noteBluetoothScanResultsLocked(int numNewResults) {
7285             createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
7286             // Uses background timebase, so the count will only be incremented if uid in background.
7287             createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults);
7288         }
7289 
7290         @Override
noteActivityResumedLocked(long elapsedRealtimeMs)7291         public void noteActivityResumedLocked(long elapsedRealtimeMs) {
7292             // We always start, since we want multiple foreground PIDs to nest
7293             createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
7294         }
7295 
7296         @Override
noteActivityPausedLocked(long elapsedRealtimeMs)7297         public void noteActivityPausedLocked(long elapsedRealtimeMs) {
7298             if (mForegroundActivityTimer != null) {
7299                 mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
7300             }
7301         }
7302 
noteForegroundServiceResumedLocked(long elapsedRealtimeMs)7303         public void noteForegroundServiceResumedLocked(long elapsedRealtimeMs) {
7304             createForegroundServiceTimerLocked().startRunningLocked(elapsedRealtimeMs);
7305         }
7306 
noteForegroundServicePausedLocked(long elapsedRealtimeMs)7307         public void noteForegroundServicePausedLocked(long elapsedRealtimeMs) {
7308             if (mForegroundServiceTimer != null) {
7309                 mForegroundServiceTimer.stopRunningLocked(elapsedRealtimeMs);
7310             }
7311         }
7312 
createVibratorOnTimerLocked()7313         public BatchTimer createVibratorOnTimerLocked() {
7314             if (mVibratorOnTimer == null) {
7315                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
7316                         mBsi.mOnBatteryTimeBase);
7317             }
7318             return mVibratorOnTimer;
7319         }
7320 
noteVibratorOnLocked(long durationMillis)7321         public void noteVibratorOnLocked(long durationMillis) {
7322             createVibratorOnTimerLocked().addDuration(mBsi, durationMillis);
7323         }
7324 
noteVibratorOffLocked()7325         public void noteVibratorOffLocked() {
7326             if (mVibratorOnTimer != null) {
7327                 mVibratorOnTimer.abortLastDuration(mBsi);
7328             }
7329         }
7330 
7331         @Override
7332         @UnsupportedAppUsage
getWifiRunningTime(long elapsedRealtimeUs, int which)7333         public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
7334             if (mWifiRunningTimer == null) {
7335                 return 0;
7336             }
7337             return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7338         }
7339 
7340         @Override
getFullWifiLockTime(long elapsedRealtimeUs, int which)7341         public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
7342             if (mFullWifiLockTimer == null) {
7343                 return 0;
7344             }
7345             return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7346         }
7347 
7348         @Override
7349         @UnsupportedAppUsage
getWifiScanTime(long elapsedRealtimeUs, int which)7350         public long getWifiScanTime(long elapsedRealtimeUs, int which) {
7351             if (mWifiScanTimer == null) {
7352                 return 0;
7353             }
7354             return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7355         }
7356 
7357         @Override
getWifiScanCount(int which)7358         public int getWifiScanCount(int which) {
7359             if (mWifiScanTimer == null) {
7360                 return 0;
7361             }
7362             return mWifiScanTimer.getCountLocked(which);
7363         }
7364 
7365         @Override
getWifiScanTimer()7366         public Timer getWifiScanTimer() {
7367             return mWifiScanTimer;
7368         }
7369 
7370         @Override
getWifiScanBackgroundCount(int which)7371         public int getWifiScanBackgroundCount(int which) {
7372             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
7373                 return 0;
7374             }
7375             return mWifiScanTimer.getSubTimer().getCountLocked(which);
7376         }
7377 
7378         @Override
getWifiScanActualTime(final long elapsedRealtimeUs)7379         public long getWifiScanActualTime(final long elapsedRealtimeUs) {
7380             if (mWifiScanTimer == null) {
7381                 return 0;
7382             }
7383             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
7384             return mWifiScanTimer.getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
7385         }
7386 
7387         @Override
getWifiScanBackgroundTime(final long elapsedRealtimeUs)7388         public long getWifiScanBackgroundTime(final long elapsedRealtimeUs) {
7389             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
7390                 return 0;
7391             }
7392             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
7393             return mWifiScanTimer.getSubTimer().getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
7394         }
7395 
7396         @Override
getWifiScanBackgroundTimer()7397         public Timer getWifiScanBackgroundTimer() {
7398             if (mWifiScanTimer == null) {
7399                 return null;
7400             }
7401             return mWifiScanTimer.getSubTimer();
7402         }
7403 
7404         @Override
getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which)7405         public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
7406             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
7407             if (mWifiBatchedScanTimer[csphBin] == null) {
7408                 return 0;
7409             }
7410             return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
7411         }
7412 
7413         @Override
getWifiBatchedScanCount(int csphBin, int which)7414         public int getWifiBatchedScanCount(int csphBin, int which) {
7415             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
7416             if (mWifiBatchedScanTimer[csphBin] == null) {
7417                 return 0;
7418             }
7419             return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
7420         }
7421 
7422         @Override
getWifiMulticastTime(long elapsedRealtimeUs, int which)7423         public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
7424             if (mWifiMulticastTimer == null) {
7425                 return 0;
7426             }
7427             return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7428         }
7429 
7430         @Override
getAudioTurnedOnTimer()7431         public Timer getAudioTurnedOnTimer() {
7432             return mAudioTurnedOnTimer;
7433         }
7434 
7435         @Override
getVideoTurnedOnTimer()7436         public Timer getVideoTurnedOnTimer() {
7437             return mVideoTurnedOnTimer;
7438         }
7439 
7440         @Override
getFlashlightTurnedOnTimer()7441         public Timer getFlashlightTurnedOnTimer() {
7442             return mFlashlightTurnedOnTimer;
7443         }
7444 
7445         @Override
getCameraTurnedOnTimer()7446         public Timer getCameraTurnedOnTimer() {
7447             return mCameraTurnedOnTimer;
7448         }
7449 
7450         @Override
getForegroundActivityTimer()7451         public Timer getForegroundActivityTimer() {
7452             return mForegroundActivityTimer;
7453         }
7454 
7455         @Override
getForegroundServiceTimer()7456         public Timer getForegroundServiceTimer() {
7457             return mForegroundServiceTimer;
7458         }
7459 
7460         @Override
getBluetoothScanTimer()7461         public Timer getBluetoothScanTimer() {
7462             return mBluetoothScanTimer;
7463         }
7464 
7465         @Override
getBluetoothScanBackgroundTimer()7466         public Timer getBluetoothScanBackgroundTimer() {
7467             if (mBluetoothScanTimer == null) {
7468                 return null;
7469             }
7470             return mBluetoothScanTimer.getSubTimer();
7471         }
7472 
7473         @Override
getBluetoothUnoptimizedScanTimer()7474         public Timer getBluetoothUnoptimizedScanTimer() {
7475             return mBluetoothUnoptimizedScanTimer;
7476         }
7477 
7478         @Override
getBluetoothUnoptimizedScanBackgroundTimer()7479         public Timer getBluetoothUnoptimizedScanBackgroundTimer() {
7480             if (mBluetoothUnoptimizedScanTimer == null) {
7481                 return null;
7482             }
7483             return mBluetoothUnoptimizedScanTimer.getSubTimer();
7484         }
7485 
7486         @Override
getBluetoothScanResultCounter()7487         public Counter getBluetoothScanResultCounter() {
7488             return mBluetoothScanResultCounter;
7489         }
7490 
7491         @Override
getBluetoothScanResultBgCounter()7492         public Counter getBluetoothScanResultBgCounter() {
7493             return mBluetoothScanResultBgCounter;
7494         }
7495 
makeProcessState(int i, Parcel in)7496         void makeProcessState(int i, Parcel in) {
7497             if (i < 0 || i >= NUM_PROCESS_STATE) return;
7498 
7499             detachIfNotNull(mProcessStateTimer[i]);
7500             if (in == null) {
7501                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
7502                         mBsi.mOnBatteryTimeBase);
7503             } else {
7504                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
7505                         mBsi.mOnBatteryTimeBase, in);
7506             }
7507         }
7508 
7509         @Override
getProcessStateTime(int state, long elapsedRealtimeUs, int which)7510         public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
7511             if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
7512             if (mProcessStateTimer[state] == null) {
7513                 return 0;
7514             }
7515             return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
7516         }
7517 
7518         @Override
getProcessStateTimer(int state)7519         public Timer getProcessStateTimer(int state) {
7520             if (state < 0 || state >= NUM_PROCESS_STATE) return null;
7521             return mProcessStateTimer[state];
7522         }
7523 
7524         @Override
getVibratorOnTimer()7525         public Timer getVibratorOnTimer() {
7526             return mVibratorOnTimer;
7527         }
7528 
7529         @Override
noteUserActivityLocked(int type)7530         public void noteUserActivityLocked(int type) {
7531             if (mUserActivityCounters == null) {
7532                 initUserActivityLocked();
7533             }
7534             if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
7535                 mUserActivityCounters[type].stepAtomic();
7536             } else {
7537                 Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
7538                         new Throwable());
7539             }
7540         }
7541 
7542         @Override
hasUserActivity()7543         public boolean hasUserActivity() {
7544             return mUserActivityCounters != null;
7545         }
7546 
7547         @Override
getUserActivityCount(int type, int which)7548         public int getUserActivityCount(int type, int which) {
7549             if (mUserActivityCounters == null) {
7550                 return 0;
7551             }
7552             return mUserActivityCounters[type].getCountLocked(which);
7553         }
7554 
makeWifiBatchedScanBin(int i, Parcel in)7555         void makeWifiBatchedScanBin(int i, Parcel in) {
7556             if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
7557 
7558             ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
7559             if (collected == null) {
7560                 collected = new ArrayList<StopwatchTimer>();
7561                 mBsi.mWifiBatchedScanTimers.put(i, collected);
7562             }
7563             detachIfNotNull(mWifiBatchedScanTimer[i]);
7564             if (in == null) {
7565                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
7566                         collected, mBsi.mOnBatteryTimeBase);
7567             } else {
7568                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
7569                         collected, mBsi.mOnBatteryTimeBase, in);
7570             }
7571         }
7572 
7573 
initUserActivityLocked()7574         void initUserActivityLocked() {
7575             detachIfNotNull(mUserActivityCounters);
7576             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
7577             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
7578                 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
7579             }
7580         }
7581 
noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets)7582         void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
7583             if (mNetworkByteActivityCounters == null) {
7584                 initNetworkActivityLocked();
7585             }
7586             if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
7587                 mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
7588                 mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
7589             } else {
7590                 Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
7591                         new Throwable());
7592             }
7593         }
7594 
noteMobileRadioActiveTimeLocked(long batteryUptime)7595         void noteMobileRadioActiveTimeLocked(long batteryUptime) {
7596             if (mNetworkByteActivityCounters == null) {
7597                 initNetworkActivityLocked();
7598             }
7599             mMobileRadioActiveTime.addCountLocked(batteryUptime);
7600             mMobileRadioActiveCount.addCountLocked(1);
7601         }
7602 
7603         @Override
hasNetworkActivity()7604         public boolean hasNetworkActivity() {
7605             return mNetworkByteActivityCounters != null;
7606         }
7607 
7608         @Override
getNetworkActivityBytes(int type, int which)7609         public long getNetworkActivityBytes(int type, int which) {
7610             if (mNetworkByteActivityCounters != null && type >= 0
7611                     && type < mNetworkByteActivityCounters.length) {
7612                 return mNetworkByteActivityCounters[type].getCountLocked(which);
7613             } else {
7614                 return 0;
7615             }
7616         }
7617 
7618         @Override
getNetworkActivityPackets(int type, int which)7619         public long getNetworkActivityPackets(int type, int which) {
7620             if (mNetworkPacketActivityCounters != null && type >= 0
7621                     && type < mNetworkPacketActivityCounters.length) {
7622                 return mNetworkPacketActivityCounters[type].getCountLocked(which);
7623             } else {
7624                 return 0;
7625             }
7626         }
7627 
7628         @Override
getMobileRadioActiveTime(int which)7629         public long getMobileRadioActiveTime(int which) {
7630             return mMobileRadioActiveTime != null
7631                     ? mMobileRadioActiveTime.getCountLocked(which) : 0;
7632         }
7633 
7634         @Override
getMobileRadioActiveCount(int which)7635         public int getMobileRadioActiveCount(int which) {
7636             return mMobileRadioActiveCount != null
7637                     ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
7638         }
7639 
7640         @Override
getUserCpuTimeUs(int which)7641         public long getUserCpuTimeUs(int which) {
7642             return mUserCpuTime.getCountLocked(which);
7643         }
7644 
7645         @Override
getSystemCpuTimeUs(int which)7646         public long getSystemCpuTimeUs(int which) {
7647             return mSystemCpuTime.getCountLocked(which);
7648         }
7649 
7650         @Override
getTimeAtCpuSpeed(int cluster, int step, int which)7651         public long getTimeAtCpuSpeed(int cluster, int step, int which) {
7652             if (mCpuClusterSpeedTimesUs != null) {
7653                 if (cluster >= 0 && cluster < mCpuClusterSpeedTimesUs.length) {
7654                     final LongSamplingCounter[] cpuSpeedTimesUs = mCpuClusterSpeedTimesUs[cluster];
7655                     if (cpuSpeedTimesUs != null) {
7656                         if (step >= 0 && step < cpuSpeedTimesUs.length) {
7657                             final LongSamplingCounter c = cpuSpeedTimesUs[step];
7658                             if (c != null) {
7659                                 return c.getCountLocked(which);
7660                             }
7661                         }
7662                     }
7663                 }
7664             }
7665             return 0;
7666         }
7667 
noteMobileRadioApWakeupLocked()7668         public void noteMobileRadioApWakeupLocked() {
7669             if (mMobileRadioApWakeupCount == null) {
7670                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7671             }
7672             mMobileRadioApWakeupCount.addCountLocked(1);
7673         }
7674 
7675         @Override
getMobileRadioApWakeupCount(int which)7676         public long getMobileRadioApWakeupCount(int which) {
7677             if (mMobileRadioApWakeupCount != null) {
7678                 return mMobileRadioApWakeupCount.getCountLocked(which);
7679             }
7680             return 0;
7681         }
7682 
noteWifiRadioApWakeupLocked()7683         public void noteWifiRadioApWakeupLocked() {
7684             if (mWifiRadioApWakeupCount == null) {
7685                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7686             }
7687             mWifiRadioApWakeupCount.addCountLocked(1);
7688         }
7689 
7690         @Override
getWifiRadioApWakeupCount(int which)7691         public long getWifiRadioApWakeupCount(int which) {
7692             if (mWifiRadioApWakeupCount != null) {
7693                 return mWifiRadioApWakeupCount.getCountLocked(which);
7694             }
7695             return 0;
7696         }
7697 
7698         @Override
getDeferredJobsCheckinLineLocked(StringBuilder sb, int which)7699         public void getDeferredJobsCheckinLineLocked(StringBuilder sb, int which) {
7700             sb.setLength(0);
7701             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
7702             if (deferredEventCount == 0) {
7703                 return;
7704             }
7705             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
7706             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
7707             sb.append(deferredEventCount); sb.append(',');
7708             sb.append(deferredCount); sb.append(',');
7709             sb.append(totalLatency);
7710             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
7711                 if (mJobsFreshnessBuckets[i] == null) {
7712                     sb.append(",0");
7713                 } else {
7714                     sb.append(",");
7715                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
7716                 }
7717             }
7718         }
7719 
7720         @Override
getDeferredJobsLineLocked(StringBuilder sb, int which)7721         public void getDeferredJobsLineLocked(StringBuilder sb, int which) {
7722             sb.setLength(0);
7723             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
7724             if (deferredEventCount == 0) {
7725                 return;
7726             }
7727             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
7728             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
7729             sb.append("times="); sb.append(deferredEventCount); sb.append(", ");
7730             sb.append("count="); sb.append(deferredCount); sb.append(", ");
7731             sb.append("totalLatencyMs="); sb.append(totalLatency); sb.append(", ");
7732             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
7733                 sb.append("<"); sb.append(JOB_FRESHNESS_BUCKETS[i]); sb.append("ms=");
7734                 if (mJobsFreshnessBuckets[i] == null) {
7735                     sb.append("0");
7736                 } else {
7737                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
7738                 }
7739                 sb.append(" ");
7740             }
7741         }
7742 
initNetworkActivityLocked()7743         void initNetworkActivityLocked() {
7744             detachIfNotNull(mNetworkByteActivityCounters);
7745             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
7746             detachIfNotNull(mNetworkPacketActivityCounters);
7747             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
7748             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7749                 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7750                 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7751             }
7752             detachIfNotNull(mMobileRadioActiveTime);
7753             mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7754             detachIfNotNull(mMobileRadioActiveCount);
7755             mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7756         }
7757 
7758         /**
7759          * Clear all stats for this uid.  Returns true if the uid is completely
7760          * inactive so can be dropped.
7761          */
7762         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
reset(long uptime, long realtime)7763         public boolean reset(long uptime, long realtime) {
7764             boolean active = false;
7765 
7766             mOnBatteryBackgroundTimeBase.init(uptime, realtime);
7767             mOnBatteryScreenOffBackgroundTimeBase.init(uptime, realtime);
7768 
7769             if (mWifiRunningTimer != null) {
7770                 active |= !mWifiRunningTimer.reset(false);
7771                 active |= mWifiRunning;
7772             }
7773             if (mFullWifiLockTimer != null) {
7774                 active |= !mFullWifiLockTimer.reset(false);
7775                 active |= mFullWifiLockOut;
7776             }
7777             if (mWifiScanTimer != null) {
7778                 active |= !mWifiScanTimer.reset(false);
7779                 active |= mWifiScanStarted;
7780             }
7781             if (mWifiBatchedScanTimer != null) {
7782                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
7783                     if (mWifiBatchedScanTimer[i] != null) {
7784                         active |= !mWifiBatchedScanTimer[i].reset(false);
7785                     }
7786                 }
7787                 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
7788             }
7789             if (mWifiMulticastTimer != null) {
7790                 active |= !mWifiMulticastTimer.reset(false);
7791                 active |= (mWifiMulticastWakelockCount > 0);
7792             }
7793 
7794             active |= !resetIfNotNull(mAudioTurnedOnTimer, false);
7795             active |= !resetIfNotNull(mVideoTurnedOnTimer, false);
7796             active |= !resetIfNotNull(mFlashlightTurnedOnTimer, false);
7797             active |= !resetIfNotNull(mCameraTurnedOnTimer, false);
7798             active |= !resetIfNotNull(mForegroundActivityTimer, false);
7799             active |= !resetIfNotNull(mForegroundServiceTimer, false);
7800             active |= !resetIfNotNull(mAggregatedPartialWakelockTimer, false);
7801             active |= !resetIfNotNull(mBluetoothScanTimer, false);
7802             active |= !resetIfNotNull(mBluetoothUnoptimizedScanTimer, false);
7803 
7804             resetIfNotNull(mBluetoothScanResultCounter, false);
7805             resetIfNotNull(mBluetoothScanResultBgCounter, false);
7806 
7807             if (mProcessStateTimer != null) {
7808                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
7809                     active |= !resetIfNotNull(mProcessStateTimer[i], false);
7810                 }
7811                 active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
7812             }
7813             if (mVibratorOnTimer != null) {
7814                 if (mVibratorOnTimer.reset(false)) {
7815                     mVibratorOnTimer.detach();
7816                     mVibratorOnTimer = null;
7817                 } else {
7818                     active = true;
7819                 }
7820             }
7821 
7822             resetIfNotNull(mUserActivityCounters, false);
7823 
7824             resetIfNotNull(mNetworkByteActivityCounters, false);
7825             resetIfNotNull(mNetworkPacketActivityCounters, false);
7826             resetIfNotNull(mMobileRadioActiveTime, false);
7827             resetIfNotNull(mMobileRadioActiveCount, false);
7828 
7829             resetIfNotNull(mWifiControllerActivity, false);
7830             resetIfNotNull(mBluetoothControllerActivity, false);
7831             resetIfNotNull(mModemControllerActivity, false);
7832 
7833             resetIfNotNull(mUserCpuTime, false);
7834             resetIfNotNull(mSystemCpuTime, false);
7835 
7836             resetIfNotNull(mCpuClusterSpeedTimesUs, false);
7837 
7838             resetIfNotNull(mCpuFreqTimeMs, false);
7839             resetIfNotNull(mScreenOffCpuFreqTimeMs, false);
7840 
7841 
7842             resetIfNotNull(mCpuActiveTimeMs, false);
7843             resetIfNotNull(mCpuClusterTimesMs, false);
7844 
7845             resetIfNotNull(mProcStateTimeMs, false);
7846 
7847             resetIfNotNull(mProcStateScreenOffTimeMs, false);
7848 
7849             resetIfNotNull(mMobileRadioApWakeupCount, false);
7850 
7851             resetIfNotNull(mWifiRadioApWakeupCount, false);
7852 
7853 
7854             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
7855             for (int iw=wakeStats.size()-1; iw>=0; iw--) {
7856                 Wakelock wl = wakeStats.valueAt(iw);
7857                 if (wl.reset()) {
7858                     wakeStats.removeAt(iw);
7859                 } else {
7860                     active = true;
7861                 }
7862             }
7863             mWakelockStats.cleanup();
7864             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
7865             for (int is=syncStats.size()-1; is>=0; is--) {
7866                 DualTimer timer = syncStats.valueAt(is);
7867                 if (timer.reset(false)) {
7868                     syncStats.removeAt(is);
7869                     timer.detach();
7870                 } else {
7871                     active = true;
7872                 }
7873             }
7874             mSyncStats.cleanup();
7875             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
7876             for (int ij=jobStats.size()-1; ij>=0; ij--) {
7877                 DualTimer timer = jobStats.valueAt(ij);
7878                 if (timer.reset(false)) {
7879                     jobStats.removeAt(ij);
7880                     timer.detach();
7881                 } else {
7882                     active = true;
7883                 }
7884             }
7885             mJobStats.cleanup();
7886             mJobCompletions.clear();
7887 
7888             resetIfNotNull(mJobsDeferredEventCount, false);
7889             resetIfNotNull(mJobsDeferredCount, false);
7890             resetIfNotNull(mJobsFreshnessTimeMs, false);
7891             resetIfNotNull(mJobsFreshnessBuckets, false);
7892 
7893             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
7894                 Sensor s = mSensorStats.valueAt(ise);
7895                 if (s.reset()) {
7896                     mSensorStats.removeAt(ise);
7897                 } else {
7898                     active = true;
7899                 }
7900             }
7901 
7902             for (int ip = mProcessStats.size() - 1; ip >= 0; ip--) {
7903                 Proc proc = mProcessStats.valueAt(ip);
7904                 proc.detach();
7905             }
7906             mProcessStats.clear();
7907 
7908             for (int i = mPids.size() - 1; i >= 0; i--) {
7909                 Pid pid = mPids.valueAt(i);
7910                 if (pid.mWakeNesting > 0) {
7911                     active = true;
7912                 } else {
7913                     mPids.removeAt(i);
7914                 }
7915             }
7916 
7917 
7918             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
7919                 Pkg p = mPackageStats.valueAt(i);
7920                 p.detach();
7921             }
7922             mPackageStats.clear();
7923 
7924             mLastStepUserTime = mLastStepSystemTime = 0;
7925             mCurStepUserTime = mCurStepSystemTime = 0;
7926 
7927             return !active;
7928         }
7929 
7930         /**
7931          * This method MUST be called whenever the Uid object is destructed, otherwise it is a
7932          * memory leak in {@link TimeBase#mObservers} list.
7933          * Typically the Uid object is destructed when it is removed from
7934          * {@link BatteryStatsImpl#mUidStats}
7935          */
detachFromTimeBase()7936         void detachFromTimeBase() {
7937             detachIfNotNull(mWifiRunningTimer);
7938             detachIfNotNull(mFullWifiLockTimer);
7939             detachIfNotNull(mWifiScanTimer);
7940             detachIfNotNull(mWifiBatchedScanTimer);
7941             detachIfNotNull(mWifiMulticastTimer);
7942             detachIfNotNull(mAudioTurnedOnTimer);
7943             detachIfNotNull(mVideoTurnedOnTimer);
7944             detachIfNotNull(mFlashlightTurnedOnTimer);
7945 
7946             detachIfNotNull(mCameraTurnedOnTimer);
7947             detachIfNotNull(mForegroundActivityTimer);
7948             detachIfNotNull(mForegroundServiceTimer);
7949 
7950             detachIfNotNull(mAggregatedPartialWakelockTimer);
7951 
7952             detachIfNotNull(mBluetoothScanTimer);
7953             detachIfNotNull(mBluetoothUnoptimizedScanTimer);
7954             detachIfNotNull(mBluetoothScanResultCounter);
7955             detachIfNotNull(mBluetoothScanResultBgCounter);
7956 
7957             detachIfNotNull(mProcessStateTimer);
7958 
7959             detachIfNotNull(mVibratorOnTimer);
7960 
7961             detachIfNotNull(mUserActivityCounters);
7962 
7963             detachIfNotNull(mNetworkByteActivityCounters);
7964             detachIfNotNull(mNetworkPacketActivityCounters);
7965 
7966             detachIfNotNull(mMobileRadioActiveTime);
7967             detachIfNotNull(mMobileRadioActiveCount);
7968             detachIfNotNull(mMobileRadioApWakeupCount);
7969             detachIfNotNull(mWifiRadioApWakeupCount);
7970 
7971             detachIfNotNull(mWifiControllerActivity);
7972             detachIfNotNull(mBluetoothControllerActivity);
7973             detachIfNotNull(mModemControllerActivity);
7974 
7975             mPids.clear();
7976 
7977             detachIfNotNull(mUserCpuTime);
7978             detachIfNotNull(mSystemCpuTime);
7979 
7980             detachIfNotNull(mCpuClusterSpeedTimesUs);
7981 
7982             detachIfNotNull(mCpuActiveTimeMs);
7983             detachIfNotNull(mCpuFreqTimeMs);
7984 
7985             detachIfNotNull(mScreenOffCpuFreqTimeMs);
7986 
7987             detachIfNotNull(mCpuClusterTimesMs);
7988 
7989             detachIfNotNull(mProcStateTimeMs);
7990 
7991             detachIfNotNull(mProcStateScreenOffTimeMs);
7992 
7993             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
7994             for (int iw = wakeStats.size() - 1; iw >= 0; iw--) {
7995                 Wakelock wl = wakeStats.valueAt(iw);
7996                 wl.detachFromTimeBase();
7997             }
7998             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
7999             for (int is = syncStats.size() - 1; is >= 0; is--) {
8000                 DualTimer timer = syncStats.valueAt(is);
8001                 detachIfNotNull(timer);
8002             }
8003             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
8004             for (int ij = jobStats.size() - 1; ij >= 0; ij--) {
8005                 DualTimer timer = jobStats.valueAt(ij);
8006                 detachIfNotNull(timer);
8007             }
8008 
8009             detachIfNotNull(mJobsDeferredEventCount);
8010             detachIfNotNull(mJobsDeferredCount);
8011             detachIfNotNull(mJobsFreshnessTimeMs);
8012             detachIfNotNull(mJobsFreshnessBuckets);
8013 
8014 
8015             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
8016                 Sensor s = mSensorStats.valueAt(ise);
8017                 s.detachFromTimeBase();
8018             }
8019 
8020             for (int ip= mProcessStats.size() - 1; ip >= 0; ip--) {
8021                 Proc proc = mProcessStats.valueAt(ip);
8022                 proc.detach();
8023             }
8024             mProcessStats.clear();
8025 
8026             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
8027                 Pkg p = mPackageStats.valueAt(i);
8028                 p.detach();
8029             }
8030             mPackageStats.clear();
8031         }
8032 
writeJobCompletionsToParcelLocked(Parcel out)8033         void writeJobCompletionsToParcelLocked(Parcel out) {
8034             int NJC = mJobCompletions.size();
8035             out.writeInt(NJC);
8036             for (int ijc=0; ijc<NJC; ijc++) {
8037                 out.writeString(mJobCompletions.keyAt(ijc));
8038                 SparseIntArray types = mJobCompletions.valueAt(ijc);
8039                 int NT = types.size();
8040                 out.writeInt(NT);
8041                 for (int it=0; it<NT; it++) {
8042                     out.writeInt(types.keyAt(it));
8043                     out.writeInt(types.valueAt(it));
8044                 }
8045             }
8046         }
8047 
writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs)8048         void writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
8049             mOnBatteryBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
8050             mOnBatteryScreenOffBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
8051 
8052             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
8053             int NW = wakeStats.size();
8054             out.writeInt(NW);
8055             for (int iw=0; iw<NW; iw++) {
8056                 out.writeString(wakeStats.keyAt(iw));
8057                 Uid.Wakelock wakelock = wakeStats.valueAt(iw);
8058                 wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
8059             }
8060 
8061             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
8062             int NS = syncStats.size();
8063             out.writeInt(NS);
8064             for (int is=0; is<NS; is++) {
8065                 out.writeString(syncStats.keyAt(is));
8066                 DualTimer timer = syncStats.valueAt(is);
8067                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
8068             }
8069 
8070             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
8071             int NJ = jobStats.size();
8072             out.writeInt(NJ);
8073             for (int ij=0; ij<NJ; ij++) {
8074                 out.writeString(jobStats.keyAt(ij));
8075                 DualTimer timer = jobStats.valueAt(ij);
8076                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
8077             }
8078 
8079             writeJobCompletionsToParcelLocked(out);
8080 
8081             mJobsDeferredEventCount.writeToParcel(out);
8082             mJobsDeferredCount.writeToParcel(out);
8083             mJobsFreshnessTimeMs.writeToParcel(out);
8084             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8085                 Counter.writeCounterToParcel(out, mJobsFreshnessBuckets[i]);
8086             }
8087 
8088             int NSE = mSensorStats.size();
8089             out.writeInt(NSE);
8090             for (int ise=0; ise<NSE; ise++) {
8091                 out.writeInt(mSensorStats.keyAt(ise));
8092                 Uid.Sensor sensor = mSensorStats.valueAt(ise);
8093                 sensor.writeToParcelLocked(out, elapsedRealtimeUs);
8094             }
8095 
8096             int NP = mProcessStats.size();
8097             out.writeInt(NP);
8098             for (int ip=0; ip<NP; ip++) {
8099                 out.writeString(mProcessStats.keyAt(ip));
8100                 Uid.Proc proc = mProcessStats.valueAt(ip);
8101                 proc.writeToParcelLocked(out);
8102             }
8103 
8104             out.writeInt(mPackageStats.size());
8105             for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
8106                 out.writeString(pkgEntry.getKey());
8107                 Uid.Pkg pkg = pkgEntry.getValue();
8108                 pkg.writeToParcelLocked(out);
8109             }
8110 
8111             if (mWifiRunningTimer != null) {
8112                 out.writeInt(1);
8113                 mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
8114             } else {
8115                 out.writeInt(0);
8116             }
8117             if (mFullWifiLockTimer != null) {
8118                 out.writeInt(1);
8119                 mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
8120             } else {
8121                 out.writeInt(0);
8122             }
8123             if (mWifiScanTimer != null) {
8124                 out.writeInt(1);
8125                 mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
8126             } else {
8127                 out.writeInt(0);
8128             }
8129             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8130                 if (mWifiBatchedScanTimer[i] != null) {
8131                     out.writeInt(1);
8132                     mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
8133                 } else {
8134                     out.writeInt(0);
8135                 }
8136             }
8137             if (mWifiMulticastTimer != null) {
8138                 out.writeInt(1);
8139                 mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
8140             } else {
8141                 out.writeInt(0);
8142             }
8143 
8144             if (mAudioTurnedOnTimer != null) {
8145                 out.writeInt(1);
8146                 mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8147             } else {
8148                 out.writeInt(0);
8149             }
8150             if (mVideoTurnedOnTimer != null) {
8151                 out.writeInt(1);
8152                 mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8153             } else {
8154                 out.writeInt(0);
8155             }
8156             if (mFlashlightTurnedOnTimer != null) {
8157                 out.writeInt(1);
8158                 mFlashlightTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8159             } else {
8160                 out.writeInt(0);
8161             }
8162             if (mCameraTurnedOnTimer != null) {
8163                 out.writeInt(1);
8164                 mCameraTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8165             } else {
8166                 out.writeInt(0);
8167             }
8168             if (mForegroundActivityTimer != null) {
8169                 out.writeInt(1);
8170                 mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
8171             } else {
8172                 out.writeInt(0);
8173             }
8174             if (mForegroundServiceTimer != null) {
8175                 out.writeInt(1);
8176                 mForegroundServiceTimer.writeToParcel(out, elapsedRealtimeUs);
8177             } else {
8178                 out.writeInt(0);
8179             }
8180             if (mAggregatedPartialWakelockTimer != null) {
8181                 out.writeInt(1);
8182                 mAggregatedPartialWakelockTimer.writeToParcel(out, elapsedRealtimeUs);
8183             } else {
8184                 out.writeInt(0);
8185             }
8186             if (mBluetoothScanTimer != null) {
8187                 out.writeInt(1);
8188                 mBluetoothScanTimer.writeToParcel(out, elapsedRealtimeUs);
8189             } else {
8190                 out.writeInt(0);
8191             }
8192             if (mBluetoothUnoptimizedScanTimer != null) {
8193                 out.writeInt(1);
8194                 mBluetoothUnoptimizedScanTimer.writeToParcel(out, elapsedRealtimeUs);
8195             } else {
8196                 out.writeInt(0);
8197             }
8198             if (mBluetoothScanResultCounter != null) {
8199                 out.writeInt(1);
8200                 mBluetoothScanResultCounter.writeToParcel(out);
8201             } else {
8202                 out.writeInt(0);
8203             }
8204             if (mBluetoothScanResultBgCounter != null) {
8205                 out.writeInt(1);
8206                 mBluetoothScanResultBgCounter.writeToParcel(out);
8207             } else {
8208                 out.writeInt(0);
8209             }
8210             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
8211                 if (mProcessStateTimer[i] != null) {
8212                     out.writeInt(1);
8213                     mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
8214                 } else {
8215                     out.writeInt(0);
8216                 }
8217             }
8218             if (mVibratorOnTimer != null) {
8219                 out.writeInt(1);
8220                 mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
8221             } else {
8222                 out.writeInt(0);
8223             }
8224             if (mUserActivityCounters != null) {
8225                 out.writeInt(1);
8226                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8227                     mUserActivityCounters[i].writeToParcel(out);
8228                 }
8229             } else {
8230                 out.writeInt(0);
8231             }
8232             if (mNetworkByteActivityCounters != null) {
8233                 out.writeInt(1);
8234                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8235                     mNetworkByteActivityCounters[i].writeToParcel(out);
8236                     mNetworkPacketActivityCounters[i].writeToParcel(out);
8237                 }
8238                 mMobileRadioActiveTime.writeToParcel(out);
8239                 mMobileRadioActiveCount.writeToParcel(out);
8240             } else {
8241                 out.writeInt(0);
8242             }
8243 
8244             if (mWifiControllerActivity != null) {
8245                 out.writeInt(1);
8246                 mWifiControllerActivity.writeToParcel(out, 0);
8247             } else {
8248                 out.writeInt(0);
8249             }
8250 
8251             if (mBluetoothControllerActivity != null) {
8252                 out.writeInt(1);
8253                 mBluetoothControllerActivity.writeToParcel(out, 0);
8254             } else {
8255                 out.writeInt(0);
8256             }
8257 
8258             if (mModemControllerActivity != null) {
8259                 out.writeInt(1);
8260                 mModemControllerActivity.writeToParcel(out, 0);
8261             } else {
8262                 out.writeInt(0);
8263             }
8264 
8265             mUserCpuTime.writeToParcel(out);
8266             mSystemCpuTime.writeToParcel(out);
8267 
8268             if (mCpuClusterSpeedTimesUs != null) {
8269                 out.writeInt(1);
8270                 out.writeInt(mCpuClusterSpeedTimesUs.length);
8271                 for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) {
8272                     if (cpuSpeeds != null) {
8273                         out.writeInt(1);
8274                         out.writeInt(cpuSpeeds.length);
8275                         for (LongSamplingCounter c : cpuSpeeds) {
8276                             if (c != null) {
8277                                 out.writeInt(1);
8278                                 c.writeToParcel(out);
8279                             } else {
8280                                 out.writeInt(0);
8281                             }
8282                         }
8283                     } else {
8284                         out.writeInt(0);
8285                     }
8286                 }
8287             } else {
8288                 out.writeInt(0);
8289             }
8290 
8291             LongSamplingCounterArray.writeToParcel(out, mCpuFreqTimeMs);
8292             LongSamplingCounterArray.writeToParcel(out, mScreenOffCpuFreqTimeMs);
8293 
8294             mCpuActiveTimeMs.writeToParcel(out);
8295             mCpuClusterTimesMs.writeToParcel(out);
8296 
8297             if (mProcStateTimeMs != null) {
8298                 out.writeInt(mProcStateTimeMs.length);
8299                 for (LongSamplingCounterArray counters : mProcStateTimeMs) {
8300                     LongSamplingCounterArray.writeToParcel(out, counters);
8301                 }
8302             } else {
8303                 out.writeInt(0);
8304             }
8305             if (mProcStateScreenOffTimeMs != null) {
8306                 out.writeInt(mProcStateScreenOffTimeMs.length);
8307                 for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
8308                     LongSamplingCounterArray.writeToParcel(out, counters);
8309                 }
8310             } else {
8311                 out.writeInt(0);
8312             }
8313 
8314             if (mMobileRadioApWakeupCount != null) {
8315                 out.writeInt(1);
8316                 mMobileRadioApWakeupCount.writeToParcel(out);
8317             } else {
8318                 out.writeInt(0);
8319             }
8320 
8321             if (mWifiRadioApWakeupCount != null) {
8322                 out.writeInt(1);
8323                 mWifiRadioApWakeupCount.writeToParcel(out);
8324             } else {
8325                 out.writeInt(0);
8326             }
8327         }
8328 
readJobCompletionsFromParcelLocked(Parcel in)8329         void readJobCompletionsFromParcelLocked(Parcel in) {
8330             int numJobCompletions = in.readInt();
8331             mJobCompletions.clear();
8332             for (int j = 0; j < numJobCompletions; j++) {
8333                 String jobName = in.readString();
8334                 int numTypes = in.readInt();
8335                 if (numTypes > 0) {
8336                     SparseIntArray types = new SparseIntArray();
8337                     for (int k = 0; k < numTypes; k++) {
8338                         int type = in.readInt();
8339                         int count = in.readInt();
8340                         types.put(type, count);
8341                     }
8342                     mJobCompletions.put(jobName, types);
8343                 }
8344             }
8345         }
8346 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in)8347         void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
8348             mOnBatteryBackgroundTimeBase.readFromParcel(in);
8349             mOnBatteryScreenOffBackgroundTimeBase.readFromParcel(in);
8350 
8351             int numWakelocks = in.readInt();
8352             mWakelockStats.clear();
8353             for (int j = 0; j < numWakelocks; j++) {
8354                 String wakelockName = in.readString();
8355                 Uid.Wakelock wakelock = new Wakelock(mBsi, this);
8356                 wakelock.readFromParcelLocked(
8357                         timeBase, screenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase, in);
8358                 mWakelockStats.add(wakelockName, wakelock);
8359             }
8360 
8361             int numSyncs = in.readInt();
8362             mSyncStats.clear();
8363             for (int j = 0; j < numSyncs; j++) {
8364                 String syncName = in.readString();
8365                 if (in.readInt() != 0) {
8366                     mSyncStats.add(syncName, new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
8367                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
8368                 }
8369             }
8370 
8371             int numJobs = in.readInt();
8372             mJobStats.clear();
8373             for (int j = 0; j < numJobs; j++) {
8374                 String jobName = in.readString();
8375                 if (in.readInt() != 0) {
8376                     mJobStats.add(jobName, new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
8377                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
8378                 }
8379             }
8380 
8381             readJobCompletionsFromParcelLocked(in);
8382 
8383             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase, in);
8384             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase, in);
8385             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8386             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8387                 mJobsFreshnessBuckets[i] = Counter.readCounterFromParcel(mBsi.mOnBatteryTimeBase,
8388                         in);
8389             }
8390 
8391             int numSensors = in.readInt();
8392             mSensorStats.clear();
8393             for (int k = 0; k < numSensors; k++) {
8394                 int sensorNumber = in.readInt();
8395                 Uid.Sensor sensor = new Sensor(mBsi, this, sensorNumber);
8396                 sensor.readFromParcelLocked(mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
8397                         in);
8398                 mSensorStats.put(sensorNumber, sensor);
8399             }
8400 
8401             int numProcs = in.readInt();
8402             mProcessStats.clear();
8403             for (int k = 0; k < numProcs; k++) {
8404                 String processName = in.readString();
8405                 Uid.Proc proc = new Proc(mBsi, processName);
8406                 proc.readFromParcelLocked(in);
8407                 mProcessStats.put(processName, proc);
8408             }
8409 
8410             int numPkgs = in.readInt();
8411             mPackageStats.clear();
8412             for (int l = 0; l < numPkgs; l++) {
8413                 String packageName = in.readString();
8414                 Uid.Pkg pkg = new Pkg(mBsi);
8415                 pkg.readFromParcelLocked(in);
8416                 mPackageStats.put(packageName, pkg);
8417             }
8418 
8419             mWifiRunning = false;
8420             if (in.readInt() != 0) {
8421                 mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
8422                         mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase, in);
8423             } else {
8424                 mWifiRunningTimer = null;
8425             }
8426             mFullWifiLockOut = false;
8427             if (in.readInt() != 0) {
8428                 mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
8429                         mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase, in);
8430             } else {
8431                 mFullWifiLockTimer = null;
8432             }
8433             mWifiScanStarted = false;
8434             if (in.readInt() != 0) {
8435                 mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
8436                         mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
8437                         in);
8438             } else {
8439                 mWifiScanTimer = null;
8440             }
8441             mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
8442             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8443                 if (in.readInt() != 0) {
8444                     makeWifiBatchedScanBin(i, in);
8445                 } else {
8446                     mWifiBatchedScanTimer[i] = null;
8447                 }
8448             }
8449             mWifiMulticastWakelockCount = 0;
8450             if (in.readInt() != 0) {
8451                 mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_MULTICAST_ENABLED,
8452                         mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase, in);
8453             } else {
8454                 mWifiMulticastTimer = null;
8455             }
8456             if (in.readInt() != 0) {
8457                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
8458                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8459             } else {
8460                 mAudioTurnedOnTimer = null;
8461             }
8462             if (in.readInt() != 0) {
8463                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
8464                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8465             } else {
8466                 mVideoTurnedOnTimer = null;
8467             }
8468             if (in.readInt() != 0) {
8469                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8470                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8471             } else {
8472                 mFlashlightTurnedOnTimer = null;
8473             }
8474             if (in.readInt() != 0) {
8475                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
8476                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8477             } else {
8478                 mCameraTurnedOnTimer = null;
8479             }
8480             if (in.readInt() != 0) {
8481                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8482                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase, in);
8483             } else {
8484                 mForegroundActivityTimer = null;
8485             }
8486             if (in.readInt() != 0) {
8487                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8488                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase, in);
8489             } else {
8490                 mForegroundServiceTimer = null;
8491             }
8492             if (in.readInt() != 0) {
8493                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
8494                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
8495                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase,
8496                         in);
8497             } else {
8498                 mAggregatedPartialWakelockTimer = null;
8499             }
8500             if (in.readInt() != 0) {
8501                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
8502                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
8503                         mOnBatteryBackgroundTimeBase, in);
8504             } else {
8505                 mBluetoothScanTimer = null;
8506             }
8507             if (in.readInt() != 0) {
8508                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
8509                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
8510                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in);
8511             } else {
8512                 mBluetoothUnoptimizedScanTimer = null;
8513             }
8514             if (in.readInt() != 0) {
8515                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase, in);
8516             } else {
8517                 mBluetoothScanResultCounter = null;
8518             }
8519             if (in.readInt() != 0) {
8520                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase, in);
8521             } else {
8522                 mBluetoothScanResultBgCounter = null;
8523             }
8524             mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
8525             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
8526                 if (in.readInt() != 0) {
8527                     makeProcessState(i, in);
8528                 } else {
8529                     mProcessStateTimer[i] = null;
8530                 }
8531             }
8532             if (in.readInt() != 0) {
8533                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
8534                         mBsi.mOnBatteryTimeBase, in);
8535             } else {
8536                 mVibratorOnTimer = null;
8537             }
8538             if (in.readInt() != 0) {
8539                 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
8540                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8541                     mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase, in);
8542                 }
8543             } else {
8544                 mUserActivityCounters = null;
8545             }
8546             if (in.readInt() != 0) {
8547                 mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
8548                 mNetworkPacketActivityCounters
8549                         = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
8550                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8551                     mNetworkByteActivityCounters[i]
8552                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8553                     mNetworkPacketActivityCounters[i]
8554                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8555                 }
8556                 mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8557                 mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8558             } else {
8559                 mNetworkByteActivityCounters = null;
8560                 mNetworkPacketActivityCounters = null;
8561             }
8562 
8563             if (in.readInt() != 0) {
8564                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8565                         NUM_WIFI_TX_LEVELS, in);
8566             } else {
8567                 mWifiControllerActivity = null;
8568             }
8569 
8570             if (in.readInt() != 0) {
8571                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8572                         NUM_BT_TX_LEVELS, in);
8573             } else {
8574                 mBluetoothControllerActivity = null;
8575             }
8576 
8577             if (in.readInt() != 0) {
8578                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8579                         ModemActivityInfo.TX_POWER_LEVELS, in);
8580             } else {
8581                 mModemControllerActivity = null;
8582             }
8583 
8584             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8585             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8586 
8587             if (in.readInt() != 0) {
8588                 int numCpuClusters = in.readInt();
8589                 if (mBsi.mPowerProfile != null && mBsi.mPowerProfile.getNumCpuClusters() != numCpuClusters) {
8590                     throw new ParcelFormatException("Incompatible number of cpu clusters");
8591                 }
8592 
8593                 mCpuClusterSpeedTimesUs = new LongSamplingCounter[numCpuClusters][];
8594                 for (int cluster = 0; cluster < numCpuClusters; cluster++) {
8595                     if (in.readInt() != 0) {
8596                         int numSpeeds = in.readInt();
8597                         if (mBsi.mPowerProfile != null &&
8598                                 mBsi.mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
8599                             throw new ParcelFormatException("Incompatible number of cpu speeds");
8600                         }
8601 
8602                         final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
8603                         mCpuClusterSpeedTimesUs[cluster] = cpuSpeeds;
8604                         for (int speed = 0; speed < numSpeeds; speed++) {
8605                             if (in.readInt() != 0) {
8606                                 cpuSpeeds[speed] = new LongSamplingCounter(
8607                                         mBsi.mOnBatteryTimeBase, in);
8608                             }
8609                         }
8610                     } else {
8611                         mCpuClusterSpeedTimesUs[cluster] = null;
8612                     }
8613                 }
8614             } else {
8615                 mCpuClusterSpeedTimesUs = null;
8616             }
8617 
8618             mCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(in, mBsi.mOnBatteryTimeBase);
8619             mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(
8620                     in, mBsi.mOnBatteryScreenOffTimeBase);
8621 
8622             mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8623             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
8624 
8625             int length = in.readInt();
8626             if (length == NUM_PROCESS_STATE) {
8627                 mProcStateTimeMs = new LongSamplingCounterArray[length];
8628                 for (int procState = 0; procState < length; ++procState) {
8629                     mProcStateTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
8630                             in, mBsi.mOnBatteryTimeBase);
8631                 }
8632             } else {
8633                 mProcStateTimeMs = null;
8634             }
8635             length = in.readInt();
8636             if (length == NUM_PROCESS_STATE) {
8637                 mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
8638                 for (int procState = 0; procState < length; ++procState) {
8639                     mProcStateScreenOffTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
8640                             in, mBsi.mOnBatteryScreenOffTimeBase);
8641                 }
8642             } else {
8643                 mProcStateScreenOffTimeMs = null;
8644             }
8645 
8646             if (in.readInt() != 0) {
8647                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8648             } else {
8649                 mMobileRadioApWakeupCount = null;
8650             }
8651 
8652             if (in.readInt() != 0) {
8653                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8654             } else {
8655                 mWifiRadioApWakeupCount = null;
8656             }
8657         }
8658 
noteJobsDeferredLocked(int numDeferred, long sinceLast)8659         public void noteJobsDeferredLocked(int numDeferred, long sinceLast) {
8660             mJobsDeferredEventCount.addAtomic(1);
8661             mJobsDeferredCount.addAtomic(numDeferred);
8662             if (sinceLast != 0) {
8663                 // Add the total time, which can be divided by the event count to get an average
8664                 mJobsFreshnessTimeMs.addCountLocked(sinceLast);
8665                 // Also keep track of how many times there were in these different buckets.
8666                 for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8667                     if (sinceLast < JOB_FRESHNESS_BUCKETS[i]) {
8668                         if (mJobsFreshnessBuckets[i] == null) {
8669                             mJobsFreshnessBuckets[i] = new Counter(
8670                                     mBsi.mOnBatteryTimeBase);
8671                         }
8672                         mJobsFreshnessBuckets[i].addAtomic(1);
8673                         break;
8674                     }
8675                 }
8676             }
8677         }
8678 
8679         /**
8680          * The statistics associated with a particular wake lock.
8681          */
8682         public static class Wakelock extends BatteryStats.Uid.Wakelock {
8683             /**
8684              * BatteryStatsImpl that we are associated with.
8685              */
8686             protected BatteryStatsImpl mBsi;
8687 
8688             /**
8689              * BatteryStatsImpl that we are associated with.
8690              */
8691             protected Uid mUid;
8692 
8693             /**
8694              * How long (in ms) this uid has been keeping the device partially awake.
8695              * Tracks both the total time and the time while the app was in the background.
8696              */
8697             DualTimer mTimerPartial;
8698 
8699             /**
8700              * How long (in ms) this uid has been keeping the device fully awake.
8701              */
8702             StopwatchTimer mTimerFull;
8703 
8704             /**
8705              * How long (in ms) this uid has had a window keeping the device awake.
8706              */
8707             StopwatchTimer mTimerWindow;
8708 
8709             /**
8710              * How long (in ms) this uid has had a draw wake lock.
8711              */
8712             StopwatchTimer mTimerDraw;
8713 
Wakelock(BatteryStatsImpl bsi, Uid uid)8714             public Wakelock(BatteryStatsImpl bsi, Uid uid) {
8715                 mBsi = bsi;
8716                 mUid = uid;
8717             }
8718 
8719             /**
8720              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
8721              * proper timer pool from the given BatteryStatsImpl object.
8722              *
8723              * @param in the Parcel to be read from.
8724              * return a new Timer, or null.
8725              */
readStopwatchTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in)8726             private StopwatchTimer readStopwatchTimerFromParcel(int type,
8727                     ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
8728                 if (in.readInt() == 0) {
8729                     return null;
8730                 }
8731 
8732                 return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
8733             }
8734 
8735             /**
8736              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
8737              * proper timer pool from the given BatteryStatsImpl object.
8738              *
8739              * @param in the Parcel to be read from.
8740              * return a new Timer, or null.
8741              */
readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, TimeBase bgTimeBase, Parcel in)8742             private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
8743                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
8744                 if (in.readInt() == 0) {
8745                     return null;
8746                 }
8747 
8748                 return new DualTimer(mBsi.mClocks, mUid, type, pool, timeBase, bgTimeBase, in);
8749             }
8750 
reset()8751             boolean reset() {
8752                 boolean wlactive = false;
8753 
8754                 wlactive |= !resetIfNotNull(mTimerFull,false);
8755                 wlactive |= !resetIfNotNull(mTimerPartial,false);
8756                 wlactive |= !resetIfNotNull(mTimerWindow,false);
8757                 wlactive |= !resetIfNotNull(mTimerDraw,false);
8758 
8759                 if (!wlactive) {
8760                     detachIfNotNull(mTimerFull);
8761                     mTimerFull = null;
8762 
8763                     detachIfNotNull(mTimerPartial);
8764                     mTimerPartial = null;
8765 
8766                     detachIfNotNull(mTimerWindow);
8767                     mTimerWindow = null;
8768 
8769                     detachIfNotNull(mTimerDraw);
8770                     mTimerDraw = null;
8771                 }
8772                 return !wlactive;
8773             }
8774 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, TimeBase screenOffBgTimeBase, Parcel in)8775             void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase,
8776                     TimeBase screenOffBgTimeBase, Parcel in) {
8777                 mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL,
8778                         mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in);
8779                 mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
8780                         mBsi.mFullTimers, timeBase, in);
8781                 mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
8782                         mBsi.mWindowTimers, timeBase, in);
8783                 mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
8784                         mBsi.mDrawTimers, timeBase, in);
8785             }
8786 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)8787             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
8788                 Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
8789                 Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
8790                 Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
8791                 Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
8792             }
8793 
8794             @Override
8795             @UnsupportedAppUsage
getWakeTime(int type)8796             public Timer getWakeTime(int type) {
8797                 switch (type) {
8798                 case WAKE_TYPE_FULL: return mTimerFull;
8799                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
8800                 case WAKE_TYPE_WINDOW: return mTimerWindow;
8801                 case WAKE_TYPE_DRAW: return mTimerDraw;
8802                 default: throw new IllegalArgumentException("type = " + type);
8803                 }
8804             }
8805 
detachFromTimeBase()8806             public void detachFromTimeBase() {
8807                 detachIfNotNull(mTimerPartial);
8808                 detachIfNotNull(mTimerFull);
8809                 detachIfNotNull(mTimerWindow);
8810                 detachIfNotNull(mTimerDraw);
8811             }
8812         }
8813 
8814         public static class Sensor extends BatteryStats.Uid.Sensor {
8815             /**
8816              * BatteryStatsImpl that we are associated with.
8817              */
8818             protected BatteryStatsImpl mBsi;
8819 
8820             /**
8821              * Uid that we are associated with.
8822              */
8823             protected Uid mUid;
8824 
8825             final int mHandle;
8826             DualTimer mTimer;
8827 
Sensor(BatteryStatsImpl bsi, Uid uid, int handle)8828             public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
8829                 mBsi = bsi;
8830                 mUid = uid;
8831                 mHandle = handle;
8832             }
8833 
readTimersFromParcel( TimeBase timeBase, TimeBase bgTimeBase, Parcel in)8834             private DualTimer readTimersFromParcel(
8835                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
8836                 if (in.readInt() == 0) {
8837                     return null;
8838                 }
8839 
8840                 ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
8841                 if (pool == null) {
8842                     pool = new ArrayList<StopwatchTimer>();
8843                     mBsi.mSensorTimers.put(mHandle, pool);
8844                 }
8845                 return new DualTimer(mBsi.mClocks, mUid, 0, pool, timeBase, bgTimeBase, in);
8846             }
8847 
reset()8848             boolean reset() {
8849                 if (mTimer.reset(true)) {
8850                     mTimer = null;
8851                     return true;
8852                 }
8853                 return false;
8854             }
8855 
readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in)8856             void readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
8857                 mTimer = readTimersFromParcel(timeBase, bgTimeBase, in);
8858             }
8859 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)8860             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
8861                 Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
8862             }
8863 
8864             @Override
8865             @UnsupportedAppUsage
getSensorTime()8866             public Timer getSensorTime() {
8867                 return mTimer;
8868             }
8869 
8870             @Override
getSensorBackgroundTime()8871             public Timer getSensorBackgroundTime() {
8872                 if (mTimer == null) {
8873                     return null;
8874                 }
8875                 return mTimer.getSubTimer();
8876             }
8877 
8878             @Override
8879             @UnsupportedAppUsage
getHandle()8880             public int getHandle() {
8881                 return mHandle;
8882             }
8883 
detachFromTimeBase()8884             public void  detachFromTimeBase() {
8885                 detachIfNotNull(mTimer);
8886             }
8887         }
8888 
8889         /**
8890          * The statistics associated with a particular process.
8891          */
8892         public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
8893             /**
8894              * BatteryStatsImpl that we are associated with.
8895              */
8896             protected BatteryStatsImpl mBsi;
8897 
8898             /**
8899              * The name of this process.
8900              */
8901             final String mName;
8902 
8903             /**
8904              * Remains true until removed from the stats.
8905              */
8906             boolean mActive = true;
8907 
8908             /**
8909              * Total time (in ms) spent executing in user code.
8910              */
8911             long mUserTime;
8912 
8913             /**
8914              * Total time (in ms) spent executing in kernel code.
8915              */
8916             long mSystemTime;
8917 
8918             /**
8919              * Amount of time (in ms) the process was running in the foreground.
8920              */
8921             long mForegroundTime;
8922 
8923             /**
8924              * Number of times the process has been started.
8925              */
8926             int mStarts;
8927 
8928             /**
8929              * Number of times the process has crashed.
8930              */
8931             int mNumCrashes;
8932 
8933             /**
8934              * Number of times the process has had an ANR.
8935              */
8936             int mNumAnrs;
8937 
8938             ArrayList<ExcessivePower> mExcessivePower;
8939 
Proc(BatteryStatsImpl bsi, String name)8940             public Proc(BatteryStatsImpl bsi, String name) {
8941                 mBsi = bsi;
8942                 mName = name;
8943                 mBsi.mOnBatteryTimeBase.add(this);
8944             }
8945 
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)8946             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
8947             }
8948 
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)8949             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
8950             }
8951 
8952             @Override
reset(boolean detachIfReset)8953             public boolean reset(boolean detachIfReset) {
8954                 if (detachIfReset) {
8955                     this.detach();
8956                 }
8957                 return true;
8958             }
8959 
8960             @Override
detach()8961             public void detach() {
8962                 mActive = false;
8963                 mBsi.mOnBatteryTimeBase.remove(this);
8964             }
8965 
countExcessivePowers()8966             public int countExcessivePowers() {
8967                 return mExcessivePower != null ? mExcessivePower.size() : 0;
8968             }
8969 
getExcessivePower(int i)8970             public ExcessivePower getExcessivePower(int i) {
8971                 if (mExcessivePower != null) {
8972                     return mExcessivePower.get(i);
8973                 }
8974                 return null;
8975             }
8976 
addExcessiveCpu(long overTime, long usedTime)8977             public void addExcessiveCpu(long overTime, long usedTime) {
8978                 if (mExcessivePower == null) {
8979                     mExcessivePower = new ArrayList<ExcessivePower>();
8980                 }
8981                 ExcessivePower ew = new ExcessivePower();
8982                 ew.type = ExcessivePower.TYPE_CPU;
8983                 ew.overTime = overTime;
8984                 ew.usedTime = usedTime;
8985                 mExcessivePower.add(ew);
8986             }
8987 
writeExcessivePowerToParcelLocked(Parcel out)8988             void writeExcessivePowerToParcelLocked(Parcel out) {
8989                 if (mExcessivePower == null) {
8990                     out.writeInt(0);
8991                     return;
8992                 }
8993 
8994                 final int N = mExcessivePower.size();
8995                 out.writeInt(N);
8996                 for (int i=0; i<N; i++) {
8997                     ExcessivePower ew = mExcessivePower.get(i);
8998                     out.writeInt(ew.type);
8999                     out.writeLong(ew.overTime);
9000                     out.writeLong(ew.usedTime);
9001                 }
9002             }
9003 
readExcessivePowerFromParcelLocked(Parcel in)9004             void readExcessivePowerFromParcelLocked(Parcel in) {
9005                 final int N = in.readInt();
9006                 if (N == 0) {
9007                     mExcessivePower = null;
9008                     return;
9009                 }
9010 
9011                 if (N > 10000) {
9012                     throw new ParcelFormatException(
9013                             "File corrupt: too many excessive power entries " + N);
9014                 }
9015 
9016                 mExcessivePower = new ArrayList<>();
9017                 for (int i=0; i<N; i++) {
9018                     ExcessivePower ew = new ExcessivePower();
9019                     ew.type = in.readInt();
9020                     ew.overTime = in.readLong();
9021                     ew.usedTime = in.readLong();
9022                     mExcessivePower.add(ew);
9023                 }
9024             }
9025 
writeToParcelLocked(Parcel out)9026             void writeToParcelLocked(Parcel out) {
9027                 out.writeLong(mUserTime);
9028                 out.writeLong(mSystemTime);
9029                 out.writeLong(mForegroundTime);
9030                 out.writeInt(mStarts);
9031                 out.writeInt(mNumCrashes);
9032                 out.writeInt(mNumAnrs);
9033                 writeExcessivePowerToParcelLocked(out);
9034             }
9035 
readFromParcelLocked(Parcel in)9036             void readFromParcelLocked(Parcel in) {
9037                 mUserTime = in.readLong();
9038                 mSystemTime = in.readLong();
9039                 mForegroundTime = in.readLong();
9040                 mStarts = in.readInt();
9041                 mNumCrashes = in.readInt();
9042                 mNumAnrs = in.readInt();
9043                 readExcessivePowerFromParcelLocked(in);
9044             }
9045 
9046             @UnsupportedAppUsage
addCpuTimeLocked(int utime, int stime)9047             public void addCpuTimeLocked(int utime, int stime) {
9048                 addCpuTimeLocked(utime, stime, mBsi.mOnBatteryTimeBase.isRunning());
9049             }
9050 
addCpuTimeLocked(int utime, int stime, boolean isRunning)9051             public void addCpuTimeLocked(int utime, int stime, boolean isRunning) {
9052                 if (isRunning) {
9053                     mUserTime += utime;
9054                     mSystemTime += stime;
9055                 }
9056             }
9057 
9058             @UnsupportedAppUsage
addForegroundTimeLocked(long ttime)9059             public void addForegroundTimeLocked(long ttime) {
9060                 mForegroundTime += ttime;
9061             }
9062 
9063             @UnsupportedAppUsage
incStartsLocked()9064             public void incStartsLocked() {
9065                 mStarts++;
9066             }
9067 
incNumCrashesLocked()9068             public void incNumCrashesLocked() {
9069                 mNumCrashes++;
9070             }
9071 
incNumAnrsLocked()9072             public void incNumAnrsLocked() {
9073                 mNumAnrs++;
9074             }
9075 
9076             @Override
isActive()9077             public boolean isActive() {
9078                 return mActive;
9079             }
9080 
9081             @Override
9082             @UnsupportedAppUsage
getUserTime(int which)9083             public long getUserTime(int which) {
9084                 return mUserTime;
9085             }
9086 
9087             @Override
9088             @UnsupportedAppUsage
getSystemTime(int which)9089             public long getSystemTime(int which) {
9090                 return mSystemTime;
9091             }
9092 
9093             @Override
9094             @UnsupportedAppUsage
getForegroundTime(int which)9095             public long getForegroundTime(int which) {
9096                 return mForegroundTime;
9097             }
9098 
9099             @Override
9100             @UnsupportedAppUsage
getStarts(int which)9101             public int getStarts(int which) {
9102                 return mStarts;
9103             }
9104 
9105             @Override
getNumCrashes(int which)9106             public int getNumCrashes(int which) {
9107                 return mNumCrashes;
9108             }
9109 
9110             @Override
getNumAnrs(int which)9111             public int getNumAnrs(int which) {
9112                 return mNumAnrs;
9113             }
9114         }
9115 
9116         /**
9117          * The statistics associated with a particular package.
9118          */
9119         public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
9120             /**
9121              * BatteryStatsImpl that we are associated with.
9122              */
9123             protected BatteryStatsImpl mBsi;
9124 
9125             /**
9126              * Number of times wakeup alarms have occurred for this app.
9127              * On screen-off timebase starting in report v25.
9128              */
9129             ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
9130 
9131             /**
9132              * The statics we have collected for this package's services.
9133              */
9134             final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
9135 
Pkg(BatteryStatsImpl bsi)9136             public Pkg(BatteryStatsImpl bsi) {
9137                 mBsi = bsi;
9138                 mBsi.mOnBatteryScreenOffTimeBase.add(this);
9139             }
9140 
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)9141             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
9142             }
9143 
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)9144             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
9145             }
9146 
9147             @Override
reset(boolean detachIfReset)9148             public boolean reset(boolean detachIfReset) {
9149                 if (detachIfReset) {
9150                     this.detach();
9151                 }
9152                 return true;
9153             }
9154 
9155             @Override
detach()9156             public void detach() {
9157                 mBsi.mOnBatteryScreenOffTimeBase.remove(this);
9158                 for (int j = mWakeupAlarms.size() - 1; j >= 0; j--) {
9159                     detachIfNotNull(mWakeupAlarms.valueAt(j));
9160                 }
9161                 for (int j = mServiceStats.size() - 1; j >= 0; j--) {
9162                     detachIfNotNull(mServiceStats.valueAt(j));
9163                 }
9164             }
9165 
readFromParcelLocked(Parcel in)9166             void readFromParcelLocked(Parcel in) {
9167                 int numWA = in.readInt();
9168                 mWakeupAlarms.clear();
9169                 for (int i=0; i<numWA; i++) {
9170                     String tag = in.readString();
9171                     mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryScreenOffTimeBase, in));
9172                 }
9173 
9174                 int numServs = in.readInt();
9175                 mServiceStats.clear();
9176                 for (int m = 0; m < numServs; m++) {
9177                     String serviceName = in.readString();
9178                     Uid.Pkg.Serv serv = new Serv(mBsi);
9179                     mServiceStats.put(serviceName, serv);
9180 
9181                     serv.readFromParcelLocked(in);
9182                 }
9183             }
9184 
writeToParcelLocked(Parcel out)9185             void writeToParcelLocked(Parcel out) {
9186                 int numWA = mWakeupAlarms.size();
9187                 out.writeInt(numWA);
9188                 for (int i=0; i<numWA; i++) {
9189                     out.writeString(mWakeupAlarms.keyAt(i));
9190                     mWakeupAlarms.valueAt(i).writeToParcel(out);
9191                 }
9192 
9193                 final int NS = mServiceStats.size();
9194                 out.writeInt(NS);
9195                 for (int i=0; i<NS; i++) {
9196                     out.writeString(mServiceStats.keyAt(i));
9197                     Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
9198                     serv.writeToParcelLocked(out);
9199                 }
9200             }
9201 
9202             @Override
getWakeupAlarmStats()9203             public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
9204                 return mWakeupAlarms;
9205             }
9206 
noteWakeupAlarmLocked(String tag)9207             public void noteWakeupAlarmLocked(String tag) {
9208                 Counter c = mWakeupAlarms.get(tag);
9209                 if (c == null) {
9210                     c = new Counter(mBsi.mOnBatteryScreenOffTimeBase);
9211                     mWakeupAlarms.put(tag, c);
9212                 }
9213                 c.stepAtomic();
9214             }
9215 
9216             @Override
getServiceStats()9217             public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
9218                 return mServiceStats;
9219             }
9220 
9221             /**
9222              * The statistics associated with a particular service.
9223              */
9224             public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
9225                 /**
9226                  * BatteryStatsImpl that we are associated with.
9227                  */
9228                 protected BatteryStatsImpl mBsi;
9229 
9230                 /**
9231                  * The android package in which this service resides.
9232                  */
9233                 protected Pkg mPkg;
9234 
9235                 /**
9236                  * Total time (ms in battery uptime) the service has been left started.
9237                  */
9238                 protected long mStartTime;
9239 
9240                 /**
9241                  * If service has been started and not yet stopped, this is
9242                  * when it was started.
9243                  */
9244                 protected long mRunningSince;
9245 
9246                 /**
9247                  * True if we are currently running.
9248                  */
9249                 protected boolean mRunning;
9250 
9251                 /**
9252                  * Total number of times startService() has been called.
9253                  */
9254                 protected int mStarts;
9255 
9256                 /**
9257                  * Total time (ms in battery uptime) the service has been left launched.
9258                  */
9259                 protected long mLaunchedTime;
9260 
9261                 /**
9262                  * If service has been launched and not yet exited, this is
9263                  * when it was launched (ms in battery uptime).
9264                  */
9265                 protected long mLaunchedSince;
9266 
9267                 /**
9268                  * True if we are currently launched.
9269                  */
9270                 protected boolean mLaunched;
9271 
9272                 /**
9273                  * Total number times the service has been launched.
9274                  */
9275                 protected int mLaunches;
9276 
9277                 /**
9278                  * Construct a Serv. Also adds it to the on-battery time base as a listener.
9279                  */
Serv(BatteryStatsImpl bsi)9280                 public Serv(BatteryStatsImpl bsi) {
9281                     mBsi = bsi;
9282                     mBsi.mOnBatteryTimeBase.add(this);
9283                 }
9284 
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)9285                 public void onTimeStarted(long elapsedRealtime, long baseUptime,
9286                         long baseRealtime) {
9287                 }
9288 
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)9289                 public void onTimeStopped(long elapsedRealtime, long baseUptime,
9290                         long baseRealtime) {
9291                 }
9292 
9293                 @Override
reset(boolean detachIfReset)9294                 public boolean reset(boolean detachIfReset) {
9295                     if (detachIfReset) {
9296                         this.detach();
9297                     }
9298                     return true;
9299                 }
9300 
9301                 /**
9302                  * Remove this Serv as a listener from the time base.
9303                  */
9304                 @Override
detach()9305                 public void detach() {
9306                     mBsi.mOnBatteryTimeBase.remove(this);
9307                 }
9308 
readFromParcelLocked(Parcel in)9309                 public void readFromParcelLocked(Parcel in) {
9310                     mStartTime = in.readLong();
9311                     mRunningSince = in.readLong();
9312                     mRunning = in.readInt() != 0;
9313                     mStarts = in.readInt();
9314                     mLaunchedTime = in.readLong();
9315                     mLaunchedSince = in.readLong();
9316                     mLaunched = in.readInt() != 0;
9317                     mLaunches = in.readInt();
9318                 }
9319 
writeToParcelLocked(Parcel out)9320                 public void writeToParcelLocked(Parcel out) {
9321                     out.writeLong(mStartTime);
9322                     out.writeLong(mRunningSince);
9323                     out.writeInt(mRunning ? 1 : 0);
9324                     out.writeInt(mStarts);
9325                     out.writeLong(mLaunchedTime);
9326                     out.writeLong(mLaunchedSince);
9327                     out.writeInt(mLaunched ? 1 : 0);
9328                     out.writeInt(mLaunches);
9329                 }
9330 
getLaunchTimeToNowLocked(long batteryUptime)9331                 public long getLaunchTimeToNowLocked(long batteryUptime) {
9332                     if (!mLaunched) return mLaunchedTime;
9333                     return mLaunchedTime + batteryUptime - mLaunchedSince;
9334                 }
9335 
getStartTimeToNowLocked(long batteryUptime)9336                 public long getStartTimeToNowLocked(long batteryUptime) {
9337                     if (!mRunning) return mStartTime;
9338                     return mStartTime + batteryUptime - mRunningSince;
9339                 }
9340 
9341                 @UnsupportedAppUsage
startLaunchedLocked()9342                 public void startLaunchedLocked() {
9343                     if (!mLaunched) {
9344                         mLaunches++;
9345                         mLaunchedSince = mBsi.getBatteryUptimeLocked();
9346                         mLaunched = true;
9347                     }
9348                 }
9349 
9350                 @UnsupportedAppUsage
stopLaunchedLocked()9351                 public void stopLaunchedLocked() {
9352                     if (mLaunched) {
9353                         long time = mBsi.getBatteryUptimeLocked() - mLaunchedSince;
9354                         if (time > 0) {
9355                             mLaunchedTime += time;
9356                         } else {
9357                             mLaunches--;
9358                         }
9359                         mLaunched = false;
9360                     }
9361                 }
9362 
9363                 @UnsupportedAppUsage
startRunningLocked()9364                 public void startRunningLocked() {
9365                     if (!mRunning) {
9366                         mStarts++;
9367                         mRunningSince = mBsi.getBatteryUptimeLocked();
9368                         mRunning = true;
9369                     }
9370                 }
9371 
9372                 @UnsupportedAppUsage
stopRunningLocked()9373                 public void stopRunningLocked() {
9374                     if (mRunning) {
9375                         long time = mBsi.getBatteryUptimeLocked() - mRunningSince;
9376                         if (time > 0) {
9377                             mStartTime += time;
9378                         } else {
9379                             mStarts--;
9380                         }
9381                         mRunning = false;
9382                     }
9383                 }
9384 
9385                 @UnsupportedAppUsage
getBatteryStats()9386                 public BatteryStatsImpl getBatteryStats() {
9387                     return mBsi;
9388                 }
9389 
9390                 @Override
getLaunches(int which)9391                 public int getLaunches(int which) {
9392                     return mLaunches;
9393                 }
9394 
9395                 @Override
getStartTime(long now, int which)9396                 public long getStartTime(long now, int which) {
9397                     return getStartTimeToNowLocked(now);
9398                 }
9399 
9400                 @Override
getStarts(int which)9401                 public int getStarts(int which) {
9402                     return mStarts;
9403                 }
9404             }
9405 
newServiceStatsLocked()9406             final Serv newServiceStatsLocked() {
9407                 return new Serv(mBsi);
9408             }
9409         }
9410 
9411         /**
9412          * Retrieve the statistics object for a particular process, creating
9413          * if needed.
9414          */
getProcessStatsLocked(String name)9415         public Proc getProcessStatsLocked(String name) {
9416             Proc ps = mProcessStats.get(name);
9417             if (ps == null) {
9418                 ps = new Proc(mBsi, name);
9419                 mProcessStats.put(name, ps);
9420             }
9421 
9422             return ps;
9423         }
9424 
9425         @GuardedBy("mBsi")
updateUidProcessStateLocked(int procState)9426         public void updateUidProcessStateLocked(int procState) {
9427             int uidRunningState;
9428             // Make special note of Foreground Services
9429             final boolean userAwareService =
9430                     (ActivityManager.isForegroundService(procState));
9431             uidRunningState = BatteryStats.mapToInternalProcessState(procState);
9432 
9433             if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
9434                 return;
9435             }
9436 
9437             final long elapsedRealtimeMs = mBsi.mClocks.elapsedRealtime();
9438             if (mProcessState != uidRunningState) {
9439                 final long uptimeMs = mBsi.mClocks.uptimeMillis();
9440 
9441                 if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
9442                     mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
9443 
9444                     if (mBsi.trackPerProcStateCpuTimes()) {
9445                         if (mBsi.mPendingUids.size() == 0) {
9446                             mBsi.mExternalSync.scheduleReadProcStateCpuTimes(
9447                                     mBsi.mOnBatteryTimeBase.isRunning(),
9448                                     mBsi.mOnBatteryScreenOffTimeBase.isRunning(),
9449                                     mBsi.mConstants.PROC_STATE_CPU_TIMES_READ_DELAY_MS);
9450                             mBsi.mNumSingleUidCpuTimeReads++;
9451                         } else {
9452                             mBsi.mNumBatchedSingleUidCpuTimeReads++;
9453                         }
9454                         if (mBsi.mPendingUids.indexOfKey(mUid) < 0
9455                                 || ArrayUtils.contains(CRITICAL_PROC_STATES, mProcessState)) {
9456                             mBsi.mPendingUids.put(mUid, mProcessState);
9457                         }
9458                     } else {
9459                         mBsi.mPendingUids.clear();
9460                     }
9461                 }
9462                 mProcessState = uidRunningState;
9463                 if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
9464                     if (mProcessStateTimer[uidRunningState] == null) {
9465                         makeProcessState(uidRunningState, null);
9466                     }
9467                     mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
9468                 }
9469 
9470                 updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
9471                 updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
9472             }
9473 
9474             if (userAwareService != mInForegroundService) {
9475                 if (userAwareService) {
9476                     noteForegroundServiceResumedLocked(elapsedRealtimeMs);
9477                 } else {
9478                     noteForegroundServicePausedLocked(elapsedRealtimeMs);
9479                 }
9480                 mInForegroundService = userAwareService;
9481             }
9482         }
9483 
9484         /** Whether to consider Uid to be in the background for background timebase purposes. */
isInBackground()9485         public boolean isInBackground() {
9486             // Note that PROCESS_STATE_CACHED and ActivityManager.PROCESS_STATE_NONEXISTENT is
9487             // also considered to be 'background' for our purposes, because it's not foreground.
9488             return mProcessState >= PROCESS_STATE_BACKGROUND;
9489         }
9490 
updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs)9491         public boolean updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs) {
9492             boolean on = mBsi.mOnBatteryTimeBase.isRunning() && isInBackground();
9493             return mOnBatteryBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
9494         }
9495 
updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs)9496         public boolean updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs) {
9497             boolean on = mBsi.mOnBatteryScreenOffTimeBase.isRunning() && isInBackground();
9498             return mOnBatteryScreenOffBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
9499         }
9500 
getPidStats()9501         public SparseArray<? extends Pid> getPidStats() {
9502             return mPids;
9503         }
9504 
getPidStatsLocked(int pid)9505         public Pid getPidStatsLocked(int pid) {
9506             Pid p = mPids.get(pid);
9507             if (p == null) {
9508                 p = new Pid();
9509                 mPids.put(pid, p);
9510             }
9511             return p;
9512         }
9513 
9514         /**
9515          * Retrieve the statistics object for a particular service, creating
9516          * if needed.
9517          */
getPackageStatsLocked(String name)9518         public Pkg getPackageStatsLocked(String name) {
9519             Pkg ps = mPackageStats.get(name);
9520             if (ps == null) {
9521                 ps = new Pkg(mBsi);
9522                 mPackageStats.put(name, ps);
9523             }
9524 
9525             return ps;
9526         }
9527 
9528         /**
9529          * Retrieve the statistics object for a particular service, creating
9530          * if needed.
9531          */
getServiceStatsLocked(String pkg, String serv)9532         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
9533             Pkg ps = getPackageStatsLocked(pkg);
9534             Pkg.Serv ss = ps.mServiceStats.get(serv);
9535             if (ss == null) {
9536                 ss = ps.newServiceStatsLocked();
9537                 ps.mServiceStats.put(serv, ss);
9538             }
9539 
9540             return ss;
9541         }
9542 
readSyncSummaryFromParcelLocked(String name, Parcel in)9543         public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
9544             DualTimer timer = mSyncStats.instantiateObject();
9545             timer.readSummaryFromParcelLocked(in);
9546             mSyncStats.add(name, timer);
9547         }
9548 
readJobSummaryFromParcelLocked(String name, Parcel in)9549         public void readJobSummaryFromParcelLocked(String name, Parcel in) {
9550             DualTimer timer = mJobStats.instantiateObject();
9551             timer.readSummaryFromParcelLocked(in);
9552             mJobStats.add(name, timer);
9553         }
9554 
readWakeSummaryFromParcelLocked(String wlName, Parcel in)9555         public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
9556             Wakelock wl = new Wakelock(mBsi, this);
9557             mWakelockStats.add(wlName, wl);
9558             if (in.readInt() != 0) {
9559                 getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
9560             }
9561             if (in.readInt() != 0) {
9562                 getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
9563             }
9564             if (in.readInt() != 0) {
9565                 getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
9566             }
9567             if (in.readInt() != 0) {
9568                 getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
9569             }
9570         }
9571 
getSensorTimerLocked(int sensor, boolean create)9572         public DualTimer getSensorTimerLocked(int sensor, boolean create) {
9573             Sensor se = mSensorStats.get(sensor);
9574             if (se == null) {
9575                 if (!create) {
9576                     return null;
9577                 }
9578                 se = new Sensor(mBsi, this, sensor);
9579                 mSensorStats.put(sensor, se);
9580             }
9581             DualTimer t = se.mTimer;
9582             if (t != null) {
9583                 return t;
9584             }
9585             ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
9586             if (timers == null) {
9587                 timers = new ArrayList<StopwatchTimer>();
9588                 mBsi.mSensorTimers.put(sensor, timers);
9589             }
9590             t = new DualTimer(mBsi.mClocks, this, BatteryStats.SENSOR, timers,
9591                     mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
9592             se.mTimer = t;
9593             return t;
9594         }
9595 
noteStartSyncLocked(String name, long elapsedRealtimeMs)9596         public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
9597             DualTimer t = mSyncStats.startObject(name);
9598             if (t != null) {
9599                 t.startRunningLocked(elapsedRealtimeMs);
9600             }
9601         }
9602 
noteStopSyncLocked(String name, long elapsedRealtimeMs)9603         public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
9604             DualTimer t = mSyncStats.stopObject(name);
9605             if (t != null) {
9606                 t.stopRunningLocked(elapsedRealtimeMs);
9607             }
9608         }
9609 
noteStartJobLocked(String name, long elapsedRealtimeMs)9610         public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
9611             DualTimer t = mJobStats.startObject(name);
9612             if (t != null) {
9613                 t.startRunningLocked(elapsedRealtimeMs);
9614             }
9615         }
9616 
noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason)9617         public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
9618             DualTimer t = mJobStats.stopObject(name);
9619             if (t != null) {
9620                 t.stopRunningLocked(elapsedRealtimeMs);
9621             }
9622             if (mBsi.mOnBatteryTimeBase.isRunning()) {
9623                 SparseIntArray types = mJobCompletions.get(name);
9624                 if (types == null) {
9625                     types = new SparseIntArray();
9626                     mJobCompletions.put(name, types);
9627                 }
9628                 int last = types.get(stopReason, 0);
9629                 types.put(stopReason, last + 1);
9630             }
9631         }
9632 
getWakelockTimerLocked(Wakelock wl, int type)9633         public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
9634             if (wl == null) {
9635                 return null;
9636             }
9637             switch (type) {
9638                 case WAKE_TYPE_PARTIAL: {
9639                     DualTimer t = wl.mTimerPartial;
9640                     if (t == null) {
9641                         t = new DualTimer(mBsi.mClocks, this, WAKE_TYPE_PARTIAL,
9642                                 mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase,
9643                                 mOnBatteryScreenOffBackgroundTimeBase);
9644                         wl.mTimerPartial = t;
9645                     }
9646                     return t;
9647                 }
9648                 case WAKE_TYPE_FULL: {
9649                     StopwatchTimer t = wl.mTimerFull;
9650                     if (t == null) {
9651                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_FULL,
9652                                 mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
9653                         wl.mTimerFull = t;
9654                     }
9655                     return t;
9656                 }
9657                 case WAKE_TYPE_WINDOW: {
9658                     StopwatchTimer t = wl.mTimerWindow;
9659                     if (t == null) {
9660                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_WINDOW,
9661                                 mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
9662                         wl.mTimerWindow = t;
9663                     }
9664                     return t;
9665                 }
9666                 case WAKE_TYPE_DRAW: {
9667                     StopwatchTimer t = wl.mTimerDraw;
9668                     if (t == null) {
9669                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_DRAW,
9670                                 mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
9671                         wl.mTimerDraw = t;
9672                     }
9673                     return t;
9674                 }
9675                 default:
9676                     throw new IllegalArgumentException("type=" + type);
9677             }
9678         }
9679 
noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)9680         public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
9681             Wakelock wl = mWakelockStats.startObject(name);
9682             if (wl != null) {
9683                 getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
9684             }
9685             if (type == WAKE_TYPE_PARTIAL) {
9686                 createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
9687                 if (pid >= 0) {
9688                     Pid p = getPidStatsLocked(pid);
9689                     if (p.mWakeNesting++ == 0) {
9690                         p.mWakeStartMs = elapsedRealtimeMs;
9691                     }
9692                 }
9693             }
9694         }
9695 
noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)9696         public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
9697             Wakelock wl = mWakelockStats.stopObject(name);
9698             if (wl != null) {
9699                 StopwatchTimer wlt = getWakelockTimerLocked(wl, type);
9700                 wlt.stopRunningLocked(elapsedRealtimeMs);
9701             }
9702             if (type == WAKE_TYPE_PARTIAL) {
9703                 if (mAggregatedPartialWakelockTimer != null) {
9704                     mAggregatedPartialWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
9705                 }
9706                 if (pid >= 0) {
9707                     Pid p = mPids.get(pid);
9708                     if (p != null && p.mWakeNesting > 0) {
9709                         if (p.mWakeNesting-- == 1) {
9710                             p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
9711                             p.mWakeStartMs = 0;
9712                         }
9713                     }
9714                 }
9715             }
9716         }
9717 
reportExcessiveCpuLocked(String proc, long overTime, long usedTime)9718         public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
9719             Proc p = getProcessStatsLocked(proc);
9720             if (p != null) {
9721                 p.addExcessiveCpu(overTime, usedTime);
9722             }
9723         }
9724 
noteStartSensor(int sensor, long elapsedRealtimeMs)9725         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
9726             DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
9727             t.startRunningLocked(elapsedRealtimeMs);
9728         }
9729 
noteStopSensor(int sensor, long elapsedRealtimeMs)9730         public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
9731             // Don't create a timer if one doesn't already exist
9732             DualTimer t = getSensorTimerLocked(sensor, false);
9733             if (t != null) {
9734                 t.stopRunningLocked(elapsedRealtimeMs);
9735             }
9736         }
9737 
noteStartGps(long elapsedRealtimeMs)9738         public void noteStartGps(long elapsedRealtimeMs) {
9739             noteStartSensor(Sensor.GPS, elapsedRealtimeMs);
9740         }
9741 
noteStopGps(long elapsedRealtimeMs)9742         public void noteStopGps(long elapsedRealtimeMs) {
9743             noteStopSensor(Sensor.GPS, elapsedRealtimeMs);
9744         }
9745 
getBatteryStats()9746         public BatteryStatsImpl getBatteryStats() {
9747             return mBsi;
9748         }
9749     }
9750 
getCpuFreqs()9751     public long[] getCpuFreqs() {
9752         return mCpuFreqs;
9753     }
9754 
BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb, RailEnergyDataCallback railStatsCb, UserInfoProvider userInfoProvider)9755     public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
9756             RailEnergyDataCallback railStatsCb, UserInfoProvider userInfoProvider) {
9757         this(new SystemClocks(), systemDir, handler, cb, railStatsCb, userInfoProvider);
9758     }
9759 
BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler, PlatformIdleStateCallback cb, RailEnergyDataCallback railStatsCb, UserInfoProvider userInfoProvider)9760     private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
9761             PlatformIdleStateCallback cb, RailEnergyDataCallback railStatsCb,
9762             UserInfoProvider userInfoProvider) {
9763         init(clocks);
9764 
9765 
9766         if (systemDir == null) {
9767             mStatsFile = null;
9768             mBatteryStatsHistory = new BatteryStatsHistory(this, mHistoryBuffer);
9769         } else {
9770             mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
9771             mBatteryStatsHistory = new BatteryStatsHistory(this, systemDir, mHistoryBuffer);
9772         }
9773         mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
9774         mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
9775         mHandler = new MyHandler(handler.getLooper());
9776         mConstants = new Constants(mHandler);
9777         mStartCount++;
9778         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
9779         mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
9780         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
9781             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
9782                     mOnBatteryTimeBase);
9783         }
9784         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase);
9785         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
9786                 mOnBatteryTimeBase);
9787         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -11, null,
9788                 mOnBatteryTimeBase);
9789         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
9790         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null, mOnBatteryTimeBase);
9791         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase);
9792         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase);
9793         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
9794             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i, null,
9795                     mOnBatteryTimeBase);
9796         }
9797         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
9798                 mOnBatteryTimeBase);
9799         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
9800             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i, null,
9801                     mOnBatteryTimeBase);
9802         }
9803         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9804             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
9805             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
9806         }
9807         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
9808         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
9809                 NUM_BT_TX_LEVELS);
9810         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
9811                 ModemActivityInfo.TX_POWER_LEVELS);
9812         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase);
9813         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
9814                 mOnBatteryTimeBase);
9815         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
9816         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
9817         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
9818         mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null,
9819                 WIFI_AGGREGATE_MULTICAST_ENABLED, null, mOnBatteryTimeBase);
9820         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase);
9821         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null, mOnBatteryTimeBase);
9822         for (int i=0; i<NUM_WIFI_STATES; i++) {
9823             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i, null,
9824                     mOnBatteryTimeBase);
9825         }
9826         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
9827             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i, null,
9828                     mOnBatteryTimeBase);
9829         }
9830         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
9831             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
9832                     mOnBatteryTimeBase);
9833         }
9834         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null, mOnBatteryTimeBase);
9835         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
9836             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i, null,
9837                 mOnBatteryTimeBase);
9838         }
9839         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
9840         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
9841         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
9842         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase);
9843         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
9844         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
9845         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
9846         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
9847         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
9848         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
9849         mOnBattery = mOnBatteryInternal = false;
9850         long uptime = mClocks.uptimeMillis() * 1000;
9851         long realtime = mClocks.elapsedRealtime() * 1000;
9852         initTimes(uptime, realtime);
9853         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
9854         mDischargeStartLevel = 0;
9855         mDischargeUnplugLevel = 0;
9856         mDischargePlugLevel = -1;
9857         mDischargeCurrentLevel = 0;
9858         mCurrentBatteryLevel = 0;
9859         initDischarge();
9860         clearHistoryLocked();
9861         updateDailyDeadlineLocked();
9862         mPlatformIdleStateCallback = cb;
9863         mRailEnergyDataCallback = railStatsCb;
9864         mUserInfoProvider = userInfoProvider;
9865     }
9866 
9867     @UnsupportedAppUsage
BatteryStatsImpl(Parcel p)9868     public BatteryStatsImpl(Parcel p) {
9869         this(new SystemClocks(), p);
9870     }
9871 
BatteryStatsImpl(Clocks clocks, Parcel p)9872     public BatteryStatsImpl(Clocks clocks, Parcel p) {
9873         init(clocks);
9874         mStatsFile = null;
9875         mCheckinFile = null;
9876         mDailyFile = null;
9877         mHandler = null;
9878         mExternalSync = null;
9879         mConstants = new Constants(mHandler);
9880         clearHistoryLocked();
9881         mBatteryStatsHistory = new BatteryStatsHistory(this, mHistoryBuffer);
9882         readFromParcel(p);
9883         mPlatformIdleStateCallback = null;
9884         mRailEnergyDataCallback = null;
9885     }
9886 
setPowerProfileLocked(PowerProfile profile)9887     public void setPowerProfileLocked(PowerProfile profile) {
9888         mPowerProfile = profile;
9889 
9890         // We need to initialize the KernelCpuSpeedReaders to read from
9891         // the first cpu of each core. Once we have the PowerProfile, we have access to this
9892         // information.
9893         final int numClusters = mPowerProfile.getNumCpuClusters();
9894         mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
9895         int firstCpuOfCluster = 0;
9896         for (int i = 0; i < numClusters; i++) {
9897             final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
9898             mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
9899                     numSpeedSteps);
9900             firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
9901         }
9902 
9903         if (mEstimatedBatteryCapacity == -1) {
9904             // Initialize the estimated battery capacity to a known preset one.
9905             mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
9906         }
9907     }
9908 
setCallback(BatteryCallback cb)9909     public void setCallback(BatteryCallback cb) {
9910         mCallback = cb;
9911     }
9912 
setRadioScanningTimeoutLocked(long timeout)9913     public void setRadioScanningTimeoutLocked(long timeout) {
9914         if (mPhoneSignalScanningTimer != null) {
9915             mPhoneSignalScanningTimer.setTimeout(timeout);
9916         }
9917     }
9918 
setExternalStatsSyncLocked(ExternalStatsSync sync)9919     public void setExternalStatsSyncLocked(ExternalStatsSync sync) {
9920         mExternalSync = sync;
9921     }
9922 
updateDailyDeadlineLocked()9923     public void updateDailyDeadlineLocked() {
9924         // Get the current time.
9925         long currentTime = mDailyStartTime = System.currentTimeMillis();
9926         Calendar calDeadline = Calendar.getInstance();
9927         calDeadline.setTimeInMillis(currentTime);
9928 
9929         // Move time up to the next day, ranging from 1am to 3pm.
9930         calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
9931         calDeadline.set(Calendar.MILLISECOND, 0);
9932         calDeadline.set(Calendar.SECOND, 0);
9933         calDeadline.set(Calendar.MINUTE, 0);
9934         calDeadline.set(Calendar.HOUR_OF_DAY, 1);
9935         mNextMinDailyDeadline = calDeadline.getTimeInMillis();
9936         calDeadline.set(Calendar.HOUR_OF_DAY, 3);
9937         mNextMaxDailyDeadline = calDeadline.getTimeInMillis();
9938     }
9939 
recordDailyStatsIfNeededLocked(boolean settled)9940     public void recordDailyStatsIfNeededLocked(boolean settled) {
9941         long currentTime = System.currentTimeMillis();
9942         if (currentTime >= mNextMaxDailyDeadline) {
9943             recordDailyStatsLocked();
9944         } else if (settled && currentTime >= mNextMinDailyDeadline) {
9945             recordDailyStatsLocked();
9946         } else if (currentTime < (mDailyStartTime-(1000*60*60*24))) {
9947             recordDailyStatsLocked();
9948         }
9949     }
9950 
recordDailyStatsLocked()9951     public void recordDailyStatsLocked() {
9952         DailyItem item = new DailyItem();
9953         item.mStartTime = mDailyStartTime;
9954         item.mEndTime = System.currentTimeMillis();
9955         boolean hasData = false;
9956         if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
9957             hasData = true;
9958             item.mDischargeSteps = new LevelStepTracker(
9959                     mDailyDischargeStepTracker.mNumStepDurations,
9960                     mDailyDischargeStepTracker.mStepDurations);
9961         }
9962         if (mDailyChargeStepTracker.mNumStepDurations > 0) {
9963             hasData = true;
9964             item.mChargeSteps = new LevelStepTracker(
9965                     mDailyChargeStepTracker.mNumStepDurations,
9966                     mDailyChargeStepTracker.mStepDurations);
9967         }
9968         if (mDailyPackageChanges != null) {
9969             hasData = true;
9970             item.mPackageChanges = mDailyPackageChanges;
9971             mDailyPackageChanges = null;
9972         }
9973         mDailyDischargeStepTracker.init();
9974         mDailyChargeStepTracker.init();
9975         updateDailyDeadlineLocked();
9976 
9977         if (hasData) {
9978             final long startTime = SystemClock.uptimeMillis();
9979             mDailyItems.add(item);
9980             while (mDailyItems.size() > MAX_DAILY_ITEMS) {
9981                 mDailyItems.remove(0);
9982             }
9983             final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
9984             try {
9985                 XmlSerializer out = new FastXmlSerializer();
9986                 out.setOutput(memStream, StandardCharsets.UTF_8.name());
9987                 writeDailyItemsLocked(out);
9988                 final long initialTime = SystemClock.uptimeMillis() - startTime;
9989                 BackgroundThread.getHandler().post(new Runnable() {
9990                     @Override
9991                     public void run() {
9992                         synchronized (mCheckinFile) {
9993                             final long startTime2 = SystemClock.uptimeMillis();
9994                             FileOutputStream stream = null;
9995                             try {
9996                                 stream = mDailyFile.startWrite();
9997                                 memStream.writeTo(stream);
9998                                 stream.flush();
9999                                 mDailyFile.finishWrite(stream);
10000                                 com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
10001                                         "batterystats-daily",
10002                                         initialTime + SystemClock.uptimeMillis() - startTime2);
10003                             } catch (IOException e) {
10004                                 Slog.w("BatteryStats",
10005                                         "Error writing battery daily items", e);
10006                                 mDailyFile.failWrite(stream);
10007                             }
10008                         }
10009                     }
10010                 });
10011             } catch (IOException e) {
10012             }
10013         }
10014     }
10015 
writeDailyItemsLocked(XmlSerializer out)10016     private void writeDailyItemsLocked(XmlSerializer out) throws IOException {
10017         StringBuilder sb = new StringBuilder(64);
10018         out.startDocument(null, true);
10019         out.startTag(null, "daily-items");
10020         for (int i=0; i<mDailyItems.size(); i++) {
10021             final DailyItem dit = mDailyItems.get(i);
10022             out.startTag(null, "item");
10023             out.attribute(null, "start", Long.toString(dit.mStartTime));
10024             out.attribute(null, "end", Long.toString(dit.mEndTime));
10025             writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
10026             writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
10027             if (dit.mPackageChanges != null) {
10028                 for (int j=0; j<dit.mPackageChanges.size(); j++) {
10029                     PackageChange pc = dit.mPackageChanges.get(j);
10030                     if (pc.mUpdate) {
10031                         out.startTag(null, "upd");
10032                         out.attribute(null, "pkg", pc.mPackageName);
10033                         out.attribute(null, "ver", Long.toString(pc.mVersionCode));
10034                         out.endTag(null, "upd");
10035                     } else {
10036                         out.startTag(null, "rem");
10037                         out.attribute(null, "pkg", pc.mPackageName);
10038                         out.endTag(null, "rem");
10039                     }
10040                 }
10041             }
10042             out.endTag(null, "item");
10043         }
10044         out.endTag(null, "daily-items");
10045         out.endDocument();
10046     }
10047 
writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps, StringBuilder tmpBuilder)10048     private void writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps,
10049             StringBuilder tmpBuilder) throws IOException {
10050         if (steps != null) {
10051             out.startTag(null, tag);
10052             out.attribute(null, "n", Integer.toString(steps.mNumStepDurations));
10053             for (int i=0; i<steps.mNumStepDurations; i++) {
10054                 out.startTag(null, "s");
10055                 tmpBuilder.setLength(0);
10056                 steps.encodeEntryAt(i, tmpBuilder);
10057                 out.attribute(null, "v", tmpBuilder.toString());
10058                 out.endTag(null, "s");
10059             }
10060             out.endTag(null, tag);
10061         }
10062     }
10063 
readDailyStatsLocked()10064     public void readDailyStatsLocked() {
10065         Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
10066         mDailyItems.clear();
10067         FileInputStream stream;
10068         try {
10069             stream = mDailyFile.openRead();
10070         } catch (FileNotFoundException e) {
10071             return;
10072         }
10073         try {
10074             XmlPullParser parser = Xml.newPullParser();
10075             parser.setInput(stream, StandardCharsets.UTF_8.name());
10076             readDailyItemsLocked(parser);
10077         } catch (XmlPullParserException e) {
10078         } finally {
10079             try {
10080                 stream.close();
10081             } catch (IOException e) {
10082             }
10083         }
10084     }
10085 
readDailyItemsLocked(XmlPullParser parser)10086     private void readDailyItemsLocked(XmlPullParser parser) {
10087         try {
10088             int type;
10089             while ((type = parser.next()) != XmlPullParser.START_TAG
10090                     && type != XmlPullParser.END_DOCUMENT) {
10091                 ;
10092             }
10093 
10094             if (type != XmlPullParser.START_TAG) {
10095                 throw new IllegalStateException("no start tag found");
10096             }
10097 
10098             int outerDepth = parser.getDepth();
10099             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10100                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10101                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10102                     continue;
10103                 }
10104 
10105                 String tagName = parser.getName();
10106                 if (tagName.equals("item")) {
10107                     readDailyItemTagLocked(parser);
10108                 } else {
10109                     Slog.w(TAG, "Unknown element under <daily-items>: "
10110                             + parser.getName());
10111                     XmlUtils.skipCurrentTag(parser);
10112                 }
10113             }
10114 
10115         } catch (IllegalStateException e) {
10116             Slog.w(TAG, "Failed parsing daily " + e);
10117         } catch (NullPointerException e) {
10118             Slog.w(TAG, "Failed parsing daily " + e);
10119         } catch (NumberFormatException e) {
10120             Slog.w(TAG, "Failed parsing daily " + e);
10121         } catch (XmlPullParserException e) {
10122             Slog.w(TAG, "Failed parsing daily " + e);
10123         } catch (IOException e) {
10124             Slog.w(TAG, "Failed parsing daily " + e);
10125         } catch (IndexOutOfBoundsException e) {
10126             Slog.w(TAG, "Failed parsing daily " + e);
10127         }
10128     }
10129 
readDailyItemTagLocked(XmlPullParser parser)10130     void readDailyItemTagLocked(XmlPullParser parser) throws NumberFormatException,
10131             XmlPullParserException, IOException {
10132         DailyItem dit = new DailyItem();
10133         String attr = parser.getAttributeValue(null, "start");
10134         if (attr != null) {
10135             dit.mStartTime = Long.parseLong(attr);
10136         }
10137         attr = parser.getAttributeValue(null, "end");
10138         if (attr != null) {
10139             dit.mEndTime = Long.parseLong(attr);
10140         }
10141         int outerDepth = parser.getDepth();
10142         int type;
10143         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10144                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10145             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10146                 continue;
10147             }
10148 
10149             String tagName = parser.getName();
10150             if (tagName.equals("dis")) {
10151                 readDailyItemTagDetailsLocked(parser, dit, false, "dis");
10152             } else if (tagName.equals("chg")) {
10153                 readDailyItemTagDetailsLocked(parser, dit, true, "chg");
10154             } else if (tagName.equals("upd")) {
10155                 if (dit.mPackageChanges == null) {
10156                     dit.mPackageChanges = new ArrayList<>();
10157                 }
10158                 PackageChange pc = new PackageChange();
10159                 pc.mUpdate = true;
10160                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
10161                 String verStr = parser.getAttributeValue(null, "ver");
10162                 pc.mVersionCode = verStr != null ? Long.parseLong(verStr) : 0;
10163                 dit.mPackageChanges.add(pc);
10164                 XmlUtils.skipCurrentTag(parser);
10165             } else if (tagName.equals("rem")) {
10166                 if (dit.mPackageChanges == null) {
10167                     dit.mPackageChanges = new ArrayList<>();
10168                 }
10169                 PackageChange pc = new PackageChange();
10170                 pc.mUpdate = false;
10171                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
10172                 dit.mPackageChanges.add(pc);
10173                 XmlUtils.skipCurrentTag(parser);
10174             } else {
10175                 Slog.w(TAG, "Unknown element under <item>: "
10176                         + parser.getName());
10177                 XmlUtils.skipCurrentTag(parser);
10178             }
10179         }
10180         mDailyItems.add(dit);
10181     }
10182 
readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge, String tag)10183     void readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge,
10184             String tag)
10185             throws NumberFormatException, XmlPullParserException, IOException {
10186         final String numAttr = parser.getAttributeValue(null, "n");
10187         if (numAttr == null) {
10188             Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
10189             XmlUtils.skipCurrentTag(parser);
10190             return;
10191         }
10192         final int num = Integer.parseInt(numAttr);
10193         LevelStepTracker steps = new LevelStepTracker(num);
10194         if (isCharge) {
10195             dit.mChargeSteps = steps;
10196         } else {
10197             dit.mDischargeSteps = steps;
10198         }
10199         int i = 0;
10200         int outerDepth = parser.getDepth();
10201         int type;
10202         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10203                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10204             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10205                 continue;
10206             }
10207 
10208             String tagName = parser.getName();
10209             if ("s".equals(tagName)) {
10210                 if (i < num) {
10211                     String valueAttr = parser.getAttributeValue(null, "v");
10212                     if (valueAttr != null) {
10213                         steps.decodeEntryAt(i, valueAttr);
10214                         i++;
10215                     }
10216                 }
10217             } else {
10218                 Slog.w(TAG, "Unknown element under <" + tag + ">: "
10219                         + parser.getName());
10220                 XmlUtils.skipCurrentTag(parser);
10221             }
10222         }
10223         steps.mNumStepDurations = i;
10224     }
10225 
10226     @Override
getDailyItemLocked(int daysAgo)10227     public DailyItem getDailyItemLocked(int daysAgo) {
10228         int index = mDailyItems.size()-1-daysAgo;
10229         return index >= 0 ? mDailyItems.get(index) : null;
10230     }
10231 
10232     @Override
getCurrentDailyStartTime()10233     public long getCurrentDailyStartTime() {
10234         return mDailyStartTime;
10235     }
10236 
10237     @Override
getNextMinDailyDeadline()10238     public long getNextMinDailyDeadline() {
10239         return mNextMinDailyDeadline;
10240     }
10241 
10242     @Override
getNextMaxDailyDeadline()10243     public long getNextMaxDailyDeadline() {
10244         return mNextMaxDailyDeadline;
10245     }
10246 
10247     @Override
startIteratingOldHistoryLocked()10248     public boolean startIteratingOldHistoryLocked() {
10249         if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
10250                 + " pos=" + mHistoryBuffer.dataPosition());
10251         if ((mHistoryIterator = mHistory) == null) {
10252             return false;
10253         }
10254         mHistoryBuffer.setDataPosition(0);
10255         mHistoryReadTmp.clear();
10256         mReadOverflow = false;
10257         mIteratingHistory = true;
10258         return true;
10259     }
10260 
10261     @Override
getNextOldHistoryLocked(HistoryItem out)10262     public boolean getNextOldHistoryLocked(HistoryItem out) {
10263         boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
10264         if (!end) {
10265             readHistoryDelta(mHistoryBuffer, mHistoryReadTmp);
10266             mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
10267         }
10268         HistoryItem cur = mHistoryIterator;
10269         if (cur == null) {
10270             if (!mReadOverflow && !end) {
10271                 Slog.w(TAG, "Old history ends before new history!");
10272             }
10273             return false;
10274         }
10275         out.setTo(cur);
10276         mHistoryIterator = cur.next;
10277         if (!mReadOverflow) {
10278             if (end) {
10279                 Slog.w(TAG, "New history ends before old history!");
10280             } else if (!out.same(mHistoryReadTmp)) {
10281                 PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
10282                 pw.println("Histories differ!");
10283                 pw.println("Old history:");
10284                 (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
10285                 pw.println("New history:");
10286                 (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
10287                         true);
10288                 pw.flush();
10289             }
10290         }
10291         return true;
10292     }
10293 
10294     @Override
finishIteratingOldHistoryLocked()10295     public void finishIteratingOldHistoryLocked() {
10296         mIteratingHistory = false;
10297         mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
10298         mHistoryIterator = null;
10299     }
10300 
getHistoryTotalSize()10301     public int getHistoryTotalSize() {
10302         return mConstants.MAX_HISTORY_BUFFER * mConstants.MAX_HISTORY_FILES;
10303     }
10304 
getHistoryUsedSize()10305     public int getHistoryUsedSize() {
10306         return mBatteryStatsHistory.getHistoryUsedSize();
10307     }
10308 
10309     @Override
10310     @UnsupportedAppUsage
startIteratingHistoryLocked()10311     public boolean startIteratingHistoryLocked() {
10312         mBatteryStatsHistory.startIteratingHistory();
10313         mReadOverflow = false;
10314         mIteratingHistory = true;
10315         mReadHistoryStrings = new String[mHistoryTagPool.size()];
10316         mReadHistoryUids = new int[mHistoryTagPool.size()];
10317         mReadHistoryChars = 0;
10318         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
10319             final HistoryTag tag = ent.getKey();
10320             final int idx = ent.getValue();
10321             mReadHistoryStrings[idx] = tag.string;
10322             mReadHistoryUids[idx] = tag.uid;
10323             mReadHistoryChars += tag.string.length() + 1;
10324         }
10325         return true;
10326     }
10327 
10328     @Override
getHistoryStringPoolSize()10329     public int getHistoryStringPoolSize() {
10330         return mReadHistoryStrings.length;
10331     }
10332 
10333     @Override
getHistoryStringPoolBytes()10334     public int getHistoryStringPoolBytes() {
10335         // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
10336         // Each string character is 2 bytes.
10337         return (mReadHistoryStrings.length * 12) + (mReadHistoryChars * 2);
10338     }
10339 
10340     @Override
getHistoryTagPoolString(int index)10341     public String getHistoryTagPoolString(int index) {
10342         return mReadHistoryStrings[index];
10343     }
10344 
10345     @Override
getHistoryTagPoolUid(int index)10346     public int getHistoryTagPoolUid(int index) {
10347         return mReadHistoryUids[index];
10348     }
10349 
10350     @Override
10351     @UnsupportedAppUsage
getNextHistoryLocked(HistoryItem out)10352     public boolean getNextHistoryLocked(HistoryItem out) {
10353         Parcel p = mBatteryStatsHistory.getNextParcel(out);
10354         if (p == null) {
10355             return false;
10356         }
10357         final long lastRealtime = out.time;
10358         final long lastWalltime = out.currentTime;
10359         readHistoryDelta(p, out);
10360         if (out.cmd != HistoryItem.CMD_CURRENT_TIME
10361                 && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
10362             out.currentTime = lastWalltime + (out.time - lastRealtime);
10363         }
10364         return true;
10365     }
10366 
10367     @Override
finishIteratingHistoryLocked()10368     public void finishIteratingHistoryLocked() {
10369         mBatteryStatsHistory.finishIteratingHistory();
10370         mIteratingHistory = false;
10371         mReadHistoryStrings = null;
10372         mReadHistoryUids = null;
10373     }
10374 
10375     @Override
getHistoryBaseTime()10376     public long getHistoryBaseTime() {
10377         return mHistoryBaseTime;
10378     }
10379 
10380     @Override
getStartCount()10381     public int getStartCount() {
10382         return mStartCount;
10383     }
10384 
10385     @UnsupportedAppUsage
isOnBattery()10386     public boolean isOnBattery() {
10387         return mOnBattery;
10388     }
10389 
isCharging()10390     public boolean isCharging() {
10391         return mCharging;
10392     }
10393 
isScreenOn(int state)10394     public boolean isScreenOn(int state) {
10395         return state == Display.STATE_ON || state == Display.STATE_VR
10396             || state == Display.STATE_ON_SUSPEND;
10397     }
10398 
isScreenOff(int state)10399     public boolean isScreenOff(int state) {
10400         return state == Display.STATE_OFF;
10401     }
10402 
isScreenDoze(int state)10403     public boolean isScreenDoze(int state) {
10404         return state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND;
10405     }
10406 
initTimes(long uptime, long realtime)10407     void initTimes(long uptime, long realtime) {
10408         mStartClockTime = System.currentTimeMillis();
10409         mOnBatteryTimeBase.init(uptime, realtime);
10410         mOnBatteryScreenOffTimeBase.init(uptime, realtime);
10411         mRealtime = 0;
10412         mUptime = 0;
10413         mRealtimeStart = realtime;
10414         mUptimeStart = uptime;
10415     }
10416 
initDischarge()10417     void initDischarge() {
10418         mLowDischargeAmountSinceCharge = 0;
10419         mHighDischargeAmountSinceCharge = 0;
10420         mDischargeAmountScreenOn = 0;
10421         mDischargeAmountScreenOnSinceCharge = 0;
10422         mDischargeAmountScreenOff = 0;
10423         mDischargeAmountScreenOffSinceCharge = 0;
10424         mDischargeAmountScreenDoze = 0;
10425         mDischargeAmountScreenDozeSinceCharge = 0;
10426         mDischargeStepTracker.init();
10427         mChargeStepTracker.init();
10428         mDischargeScreenOffCounter.reset(false);
10429         mDischargeScreenDozeCounter.reset(false);
10430         mDischargeLightDozeCounter.reset(false);
10431         mDischargeDeepDozeCounter.reset(false);
10432         mDischargeCounter.reset(false);
10433     }
10434 
resetAllStatsCmdLocked()10435     public void resetAllStatsCmdLocked() {
10436         resetAllStatsLocked();
10437         final long mSecUptime = mClocks.uptimeMillis();
10438         long uptime = mSecUptime * 1000;
10439         long mSecRealtime = mClocks.elapsedRealtime();
10440         long realtime = mSecRealtime * 1000;
10441         mDischargeStartLevel = mHistoryCur.batteryLevel;
10442         pullPendingStateUpdatesLocked();
10443         addHistoryRecordLocked(mSecRealtime, mSecUptime);
10444         mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
10445                 = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
10446         mOnBatteryTimeBase.reset(uptime, realtime);
10447         mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
10448         if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
10449             if (isScreenOn(mScreenState)) {
10450                 mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
10451                 mDischargeScreenDozeUnplugLevel = 0;
10452                 mDischargeScreenOffUnplugLevel = 0;
10453             } else if (isScreenDoze(mScreenState)) {
10454                 mDischargeScreenOnUnplugLevel = 0;
10455                 mDischargeScreenDozeUnplugLevel = mHistoryCur.batteryLevel;
10456                 mDischargeScreenOffUnplugLevel = 0;
10457             } else {
10458                 mDischargeScreenOnUnplugLevel = 0;
10459                 mDischargeScreenDozeUnplugLevel = 0;
10460                 mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
10461             }
10462             mDischargeAmountScreenOn = 0;
10463             mDischargeAmountScreenOff = 0;
10464             mDischargeAmountScreenDoze = 0;
10465         }
10466         initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
10467     }
10468 
resetAllStatsLocked()10469     private void resetAllStatsLocked() {
10470         final long uptimeMillis = mClocks.uptimeMillis();
10471         final long elapsedRealtimeMillis = mClocks.elapsedRealtime();
10472         mStartCount = 0;
10473         initTimes(uptimeMillis * 1000, elapsedRealtimeMillis * 1000);
10474         mScreenOnTimer.reset(false);
10475         mScreenDozeTimer.reset(false);
10476         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10477             mScreenBrightnessTimer[i].reset(false);
10478         }
10479 
10480         if (mPowerProfile != null) {
10481             mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
10482         } else {
10483             mEstimatedBatteryCapacity = -1;
10484         }
10485         mMinLearnedBatteryCapacity = -1;
10486         mMaxLearnedBatteryCapacity = -1;
10487         mInteractiveTimer.reset(false);
10488         mPowerSaveModeEnabledTimer.reset(false);
10489         mLastIdleTimeStart = elapsedRealtimeMillis;
10490         mLongestLightIdleTime = 0;
10491         mLongestFullIdleTime = 0;
10492         mDeviceIdleModeLightTimer.reset(false);
10493         mDeviceIdleModeFullTimer.reset(false);
10494         mDeviceLightIdlingTimer.reset(false);
10495         mDeviceIdlingTimer.reset(false);
10496         mPhoneOnTimer.reset(false);
10497         mAudioOnTimer.reset(false);
10498         mVideoOnTimer.reset(false);
10499         mFlashlightOnTimer.reset(false);
10500         mCameraOnTimer.reset(false);
10501         mBluetoothScanTimer.reset(false);
10502         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
10503             mPhoneSignalStrengthsTimer[i].reset(false);
10504         }
10505         mPhoneSignalScanningTimer.reset(false);
10506         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10507             mPhoneDataConnectionsTimer[i].reset(false);
10508         }
10509         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10510             mNetworkByteActivityCounters[i].reset(false);
10511             mNetworkPacketActivityCounters[i].reset(false);
10512         }
10513         mMobileRadioActiveTimer.reset(false);
10514         mMobileRadioActivePerAppTimer.reset(false);
10515         mMobileRadioActiveAdjustedTime.reset(false);
10516         mMobileRadioActiveUnknownTime.reset(false);
10517         mMobileRadioActiveUnknownCount.reset(false);
10518         mWifiOnTimer.reset(false);
10519         mGlobalWifiRunningTimer.reset(false);
10520         for (int i=0; i<NUM_WIFI_STATES; i++) {
10521             mWifiStateTimer[i].reset(false);
10522         }
10523         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10524             mWifiSupplStateTimer[i].reset(false);
10525         }
10526         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10527             mWifiSignalStrengthsTimer[i].reset(false);
10528         }
10529         mWifiMulticastWakelockTimer.reset(false);
10530         mWifiActiveTimer.reset(false);
10531         mWifiActivity.reset(false);
10532         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
10533             mGpsSignalQualityTimer[i].reset(false);
10534         }
10535         mBluetoothActivity.reset(false);
10536         mModemActivity.reset(false);
10537         mNumConnectivityChange = 0;
10538 
10539         for (int i=0; i<mUidStats.size(); i++) {
10540             if (mUidStats.valueAt(i).reset(uptimeMillis * 1000, elapsedRealtimeMillis * 1000)) {
10541                 mUidStats.valueAt(i).detachFromTimeBase();
10542                 mUidStats.remove(mUidStats.keyAt(i));
10543                 i--;
10544             }
10545         }
10546 
10547         if (mRpmStats.size() > 0) {
10548             for (SamplingTimer timer : mRpmStats.values()) {
10549                 mOnBatteryTimeBase.remove(timer);
10550             }
10551             mRpmStats.clear();
10552         }
10553         if (mScreenOffRpmStats.size() > 0) {
10554             for (SamplingTimer timer : mScreenOffRpmStats.values()) {
10555                 mOnBatteryScreenOffTimeBase.remove(timer);
10556             }
10557             mScreenOffRpmStats.clear();
10558         }
10559 
10560         if (mKernelWakelockStats.size() > 0) {
10561             for (SamplingTimer timer : mKernelWakelockStats.values()) {
10562                 mOnBatteryScreenOffTimeBase.remove(timer);
10563             }
10564             mKernelWakelockStats.clear();
10565         }
10566 
10567         if (mKernelMemoryStats.size() > 0) {
10568             for (int i = 0; i < mKernelMemoryStats.size(); i++) {
10569                 mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i));
10570             }
10571             mKernelMemoryStats.clear();
10572         }
10573 
10574         if (mWakeupReasonStats.size() > 0) {
10575             for (SamplingTimer timer : mWakeupReasonStats.values()) {
10576                 mOnBatteryTimeBase.remove(timer);
10577             }
10578             mWakeupReasonStats.clear();
10579         }
10580 
10581         mTmpRailStats.reset();
10582 
10583         mLastHistoryStepDetails = null;
10584         mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
10585         mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
10586         mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
10587         mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
10588         mLastStepStatUserTime = mCurStepStatUserTime = 0;
10589         mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
10590         mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
10591         mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
10592         mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
10593         mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
10594 
10595         mNumAllUidCpuTimeReads = 0;
10596         mNumUidsRemoved = 0;
10597 
10598         initDischarge();
10599 
10600         clearHistoryLocked();
10601         mBatteryStatsHistory.resetAllFiles();
10602 
10603         mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
10604     }
10605 
initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs)10606     private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
10607         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
10608             if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
10609                 // Not recording process starts/stops.
10610                 continue;
10611             }
10612             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
10613             if (active == null) {
10614                 continue;
10615             }
10616             for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
10617                 SparseIntArray uids = ent.getValue();
10618                 for (int j=0; j<uids.size(); j++) {
10619                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
10620                             uids.keyAt(j));
10621                 }
10622             }
10623         }
10624     }
10625 
updateDischargeScreenLevelsLocked(int oldState, int newState)10626     void updateDischargeScreenLevelsLocked(int oldState, int newState) {
10627         updateOldDischargeScreenLevelLocked(oldState);
10628         updateNewDischargeScreenLevelLocked(newState);
10629     }
10630 
updateOldDischargeScreenLevelLocked(int state)10631     private void updateOldDischargeScreenLevelLocked(int state) {
10632         if (isScreenOn(state)) {
10633             int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
10634             if (diff > 0) {
10635                 mDischargeAmountScreenOn += diff;
10636                 mDischargeAmountScreenOnSinceCharge += diff;
10637             }
10638         } else if (isScreenDoze(state)) {
10639             int diff = mDischargeScreenDozeUnplugLevel - mDischargeCurrentLevel;
10640             if (diff > 0) {
10641                 mDischargeAmountScreenDoze += diff;
10642                 mDischargeAmountScreenDozeSinceCharge += diff;
10643             }
10644         } else if (isScreenOff(state)){
10645             int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
10646             if (diff > 0) {
10647                 mDischargeAmountScreenOff += diff;
10648                 mDischargeAmountScreenOffSinceCharge += diff;
10649             }
10650         }
10651     }
10652 
updateNewDischargeScreenLevelLocked(int state)10653     private void updateNewDischargeScreenLevelLocked(int state) {
10654         if (isScreenOn(state)) {
10655             mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
10656             mDischargeScreenOffUnplugLevel = 0;
10657             mDischargeScreenDozeUnplugLevel = 0;
10658         } else if (isScreenDoze(state)){
10659             mDischargeScreenOnUnplugLevel = 0;
10660             mDischargeScreenDozeUnplugLevel = mDischargeCurrentLevel;
10661             mDischargeScreenOffUnplugLevel = 0;
10662         } else if (isScreenOff(state)) {
10663             mDischargeScreenOnUnplugLevel = 0;
10664             mDischargeScreenDozeUnplugLevel = 0;
10665             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
10666         }
10667     }
10668 
pullPendingStateUpdatesLocked()10669     public void pullPendingStateUpdatesLocked() {
10670         if (mOnBatteryInternal) {
10671             updateDischargeScreenLevelsLocked(mScreenState, mScreenState);
10672         }
10673     }
10674 
10675     private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6);
10676 
10677     private final Object mWifiNetworkLock = new Object();
10678 
10679     @GuardedBy("mWifiNetworkLock")
10680     private String[] mWifiIfaces = EmptyArray.STRING;
10681 
10682     @GuardedBy("mWifiNetworkLock")
10683     private NetworkStats mLastWifiNetworkStats = new NetworkStats(0, -1);
10684 
10685     private final Object mModemNetworkLock = new Object();
10686 
10687     @GuardedBy("mModemNetworkLock")
10688     private String[] mModemIfaces = EmptyArray.STRING;
10689 
10690     @GuardedBy("mModemNetworkLock")
10691     private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
10692 
readNetworkStatsLocked(String[] ifaces)10693     private NetworkStats readNetworkStatsLocked(String[] ifaces) {
10694         try {
10695             if (!ArrayUtils.isEmpty(ifaces)) {
10696                 INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
10697                         ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
10698                 if (statsService != null) {
10699                     return statsService.getDetailedUidStats(ifaces);
10700                 } else {
10701                     Slog.e(TAG, "Failed to get networkStatsService ");
10702                 }
10703             }
10704         } catch (RemoteException e) {
10705             Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces) + e);
10706         }
10707         return null;
10708     }
10709 
10710    /**
10711      * Distribute WiFi energy info and network traffic to apps.
10712      * @param info The energy information from the WiFi controller.
10713      */
updateWifiState(@ullable final WifiActivityEnergyInfo info)10714     public void updateWifiState(@Nullable final WifiActivityEnergyInfo info) {
10715         if (DEBUG_ENERGY) {
10716             Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
10717         }
10718 
10719         // Grab a separate lock to acquire the network stats, which may do I/O.
10720         NetworkStats delta = null;
10721         synchronized (mWifiNetworkLock) {
10722             final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces);
10723             if (latestStats != null) {
10724                 delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null,
10725                         mNetworkStatsPool.acquire());
10726                 mNetworkStatsPool.release(mLastWifiNetworkStats);
10727                 mLastWifiNetworkStats = latestStats;
10728             }
10729         }
10730 
10731         synchronized (this) {
10732             if (!mOnBatteryInternal) {
10733                 if (delta != null) {
10734                     mNetworkStatsPool.release(delta);
10735                 }
10736                 return;
10737             }
10738 
10739             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
10740             SparseLongArray rxPackets = new SparseLongArray();
10741             SparseLongArray txPackets = new SparseLongArray();
10742             long totalTxPackets = 0;
10743             long totalRxPackets = 0;
10744             if (delta != null) {
10745                 NetworkStats.Entry entry = new NetworkStats.Entry();
10746                 final int size = delta.size();
10747                 for (int i = 0; i < size; i++) {
10748                     entry = delta.getValues(i, entry);
10749 
10750                     if (DEBUG_ENERGY) {
10751                         Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
10752                                 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
10753                                 + " txPackets=" + entry.txPackets);
10754                     }
10755 
10756                     if (entry.rxBytes == 0 && entry.txBytes == 0) {
10757                         // Skip the lookup below since there is no work to do.
10758                         continue;
10759                     }
10760 
10761                     final Uid u = getUidStatsLocked(mapUid(entry.uid));
10762                     if (entry.rxBytes != 0) {
10763                         u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
10764                                 entry.rxPackets);
10765                         if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
10766                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
10767                                     entry.rxPackets);
10768                         }
10769                         mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
10770                                 entry.rxBytes);
10771                         mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
10772                                 entry.rxPackets);
10773 
10774                         rxPackets.put(u.getUid(), entry.rxPackets);
10775 
10776                         // Sum the total number of packets so that the Rx Power can
10777                         // be evenly distributed amongst the apps.
10778                         totalRxPackets += entry.rxPackets;
10779                     }
10780 
10781                     if (entry.txBytes != 0) {
10782                         u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
10783                                 entry.txPackets);
10784                         if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
10785                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
10786                                     entry.txPackets);
10787                         }
10788                         mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
10789                                 entry.txBytes);
10790                         mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
10791                                 entry.txPackets);
10792 
10793                         txPackets.put(u.getUid(), entry.txPackets);
10794 
10795                         // Sum the total number of packets so that the Tx Power can
10796                         // be evenly distributed amongst the apps.
10797                         totalTxPackets += entry.txPackets;
10798                     }
10799                 }
10800                 mNetworkStatsPool.release(delta);
10801                 delta = null;
10802             }
10803 
10804             if (info != null) {
10805                 mHasWifiReporting = true;
10806 
10807                 // Measured in mAms
10808                 final long txTimeMs = info.getControllerTxTimeMillis();
10809                 final long rxTimeMs = info.getControllerRxTimeMillis();
10810                 final long scanTimeMs = info.getControllerScanTimeMillis();
10811                 final long idleTimeMs = info.getControllerIdleTimeMillis();
10812                 final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
10813 
10814                 long leftOverRxTimeMs = rxTimeMs;
10815                 long leftOverTxTimeMs = txTimeMs;
10816 
10817                 if (DEBUG_ENERGY) {
10818                     Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
10819                     Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
10820                     Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
10821                     Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
10822                     Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
10823                     Slog.d(TAG, "  Scan Time:  " + scanTimeMs + " ms");
10824                 }
10825 
10826                 long totalWifiLockTimeMs = 0;
10827                 long totalScanTimeMs = 0;
10828 
10829                 // On the first pass, collect some totals so that we can normalize power
10830                 // calculations if we need to.
10831                 final int uidStatsSize = mUidStats.size();
10832                 for (int i = 0; i < uidStatsSize; i++) {
10833                     final Uid uid = mUidStats.valueAt(i);
10834 
10835                     // Sum the total scan power for all apps.
10836                     totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
10837                             elapsedRealtimeMs * 1000) / 1000;
10838 
10839                     // Sum the total time holding wifi lock for all apps.
10840                     totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
10841                             elapsedRealtimeMs * 1000) / 1000;
10842                 }
10843 
10844                 if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
10845                     Slog.d(TAG,
10846                             "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
10847                                     + rxTimeMs + " ms). Normalizing scan time.");
10848                 }
10849                 if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
10850                     Slog.d(TAG,
10851                             "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
10852                                     + txTimeMs + " ms). Normalizing scan time.");
10853                 }
10854 
10855                 // Actually assign and distribute power usage to apps.
10856                 for (int i = 0; i < uidStatsSize; i++) {
10857                     final Uid uid = mUidStats.valueAt(i);
10858 
10859                     long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
10860                             elapsedRealtimeMs * 1000) / 1000;
10861                     if (scanTimeSinceMarkMs > 0) {
10862                         // Set the new mark so that next time we get new data since this point.
10863                         uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
10864 
10865                         long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
10866                         long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
10867 
10868                         // Our total scan time is more than the reported Tx/Rx time.
10869                         // This is possible because the cost of a scan is approximate.
10870                         // Let's normalize the result so that we evenly blame each app
10871                         // scanning.
10872                         //
10873                         // This means that we may have apps that transmitted/received packets not be
10874                         // blamed for this, but this is fine as scans are relatively more expensive.
10875                         if (totalScanTimeMs > rxTimeMs) {
10876                             scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
10877                                     totalScanTimeMs;
10878                         }
10879                         if (totalScanTimeMs > txTimeMs) {
10880                             scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
10881                                     totalScanTimeMs;
10882                         }
10883 
10884                         if (DEBUG_ENERGY) {
10885                             Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
10886                                     + scanRxTimeSinceMarkMs + " ms  Tx:"
10887                                     + scanTxTimeSinceMarkMs + " ms)");
10888                         }
10889 
10890                         ControllerActivityCounterImpl activityCounter =
10891                                 uid.getOrCreateWifiControllerActivityLocked();
10892                         activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
10893                         activityCounter.getTxTimeCounters()[0].addCountLocked(
10894                                 scanTxTimeSinceMarkMs);
10895                         leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
10896                         leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
10897                     }
10898 
10899                     // Distribute evenly the power consumed while Idle to each app holding a WiFi
10900                     // lock.
10901                     final long wifiLockTimeSinceMarkMs =
10902                             uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
10903                                     elapsedRealtimeMs * 1000) / 1000;
10904                     if (wifiLockTimeSinceMarkMs > 0) {
10905                         // Set the new mark so that next time we get new data since this point.
10906                         uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
10907 
10908                         final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
10909                                 / totalWifiLockTimeMs;
10910                         if (DEBUG_ENERGY) {
10911                             Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
10912                                     + myIdleTimeMs + " ms");
10913                         }
10914                         uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
10915                                 .addCountLocked(myIdleTimeMs);
10916                     }
10917                 }
10918 
10919                 if (DEBUG_ENERGY) {
10920                     Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
10921                     Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
10922                 }
10923 
10924                 // Distribute the remaining Tx power appropriately between all apps that transmitted
10925                 // packets.
10926                 for (int i = 0; i < txPackets.size(); i++) {
10927                     final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
10928                     final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
10929                             / totalTxPackets;
10930                     if (DEBUG_ENERGY) {
10931                         Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
10932                     }
10933                     uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
10934                             .addCountLocked(myTxTimeMs);
10935                 }
10936 
10937                 // Distribute the remaining Rx power appropriately between all apps that received
10938                 // packets.
10939                 for (int i = 0; i < rxPackets.size(); i++) {
10940                     final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
10941                     final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
10942                             / totalRxPackets;
10943                     if (DEBUG_ENERGY) {
10944                         Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
10945                     }
10946                     uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
10947                             .addCountLocked(myRxTimeMs);
10948                 }
10949 
10950                 // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
10951 
10952 
10953                 // Update WiFi controller stats.
10954                 mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
10955                 mWifiActivity.getTxTimeCounters()[0].addCountLocked(
10956                         info.getControllerTxTimeMillis());
10957                 mWifiActivity.getScanTimeCounter().addCountLocked(
10958                     info.getControllerScanTimeMillis());
10959                 mWifiActivity.getIdleTimeCounter().addCountLocked(
10960                         info.getControllerIdleTimeMillis());
10961 
10962                 // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
10963                 final double opVolt = mPowerProfile.getAveragePower(
10964                         PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
10965                 if (opVolt != 0) {
10966                     // We store the power drain as mAms.
10967                     mWifiActivity.getPowerCounter().addCountLocked(
10968                             (long) (info.getControllerEnergyUsed() / opVolt));
10969                 }
10970                 // Converting uWs to mAms.
10971                 // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
10972                 long monitoredRailChargeConsumedMaMs =
10973                         (long) (mTmpRailStats.getWifiTotalEnergyUseduWs() / opVolt);
10974                 mWifiActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
10975                         monitoredRailChargeConsumedMaMs);
10976                 mHistoryCur.wifiRailChargeMah +=
10977                         (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
10978                 addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
10979                 mTmpRailStats.resetWifiTotalEnergyUsed();
10980             }
10981         }
10982     }
10983 
10984     private ModemActivityInfo mLastModemActivityInfo =
10985             new ModemActivityInfo(0, 0, 0, new int[0], 0);
10986 
getDeltaModemActivityInfo(ModemActivityInfo activityInfo)10987     private ModemActivityInfo getDeltaModemActivityInfo(ModemActivityInfo activityInfo) {
10988         if (activityInfo == null) {
10989             return null;
10990         }
10991         int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
10992         for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) {
10993             txTimeMs[i] = activityInfo.getTransmitPowerInfo().get(i).getTimeInMillis()
10994                     - mLastModemActivityInfo.getTransmitPowerInfo().get(i).getTimeInMillis();
10995         }
10996         ModemActivityInfo deltaInfo = new ModemActivityInfo(activityInfo.getTimestamp(),
10997                 activityInfo.getSleepTimeMillis() - mLastModemActivityInfo.getSleepTimeMillis(),
10998                 activityInfo.getIdleTimeMillis() - mLastModemActivityInfo.getIdleTimeMillis(),
10999                 txTimeMs,
11000                 activityInfo.getReceiveTimeMillis() - mLastModemActivityInfo.getReceiveTimeMillis());
11001         mLastModemActivityInfo = activityInfo;
11002         return deltaInfo;
11003     }
11004 
11005     /**
11006      * Distribute Cell radio energy info and network traffic to apps.
11007      */
updateMobileRadioState(@ullable final ModemActivityInfo activityInfo)11008     public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo) {
11009         if (DEBUG_ENERGY) {
11010             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
11011         }
11012         ModemActivityInfo deltaInfo = getDeltaModemActivityInfo(activityInfo);
11013 
11014         // Add modem tx power to history.
11015         addModemTxPowerToHistory(deltaInfo);
11016 
11017         // Grab a separate lock to acquire the network stats, which may do I/O.
11018         NetworkStats delta = null;
11019         synchronized (mModemNetworkLock) {
11020             final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces);
11021             if (latestStats != null) {
11022                 delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null,
11023                         mNetworkStatsPool.acquire());
11024                 mNetworkStatsPool.release(mLastModemNetworkStats);
11025                 mLastModemNetworkStats = latestStats;
11026             }
11027         }
11028 
11029         synchronized (this) {
11030             if (!mOnBatteryInternal) {
11031                 if (delta != null) {
11032                     mNetworkStatsPool.release(delta);
11033                 }
11034                 return;
11035             }
11036 
11037             if (deltaInfo != null) {
11038                 mHasModemReporting = true;
11039                 mModemActivity.getIdleTimeCounter().addCountLocked(
11040                         deltaInfo.getIdleTimeMillis());
11041                 mModemActivity.getSleepTimeCounter().addCountLocked(
11042                         deltaInfo.getSleepTimeMillis());
11043                 mModemActivity.getRxTimeCounter().addCountLocked(deltaInfo.getReceiveTimeMillis());
11044                 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
11045                     mModemActivity.getTxTimeCounters()[lvl]
11046                         .addCountLocked(deltaInfo.getTransmitPowerInfo()
11047                             .get(lvl).getTimeInMillis());
11048                 }
11049 
11050                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11051                 final double opVolt = mPowerProfile.getAveragePower(
11052                     PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11053                 if (opVolt != 0) {
11054                     double energyUsed =
11055                             deltaInfo.getSleepTimeMillis() *
11056                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
11057                             + deltaInfo.getIdleTimeMillis() *
11058                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
11059                             + deltaInfo.getReceiveTimeMillis() *
11060                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
11061 
11062                     List<TransmitPower> txPowerInfo = deltaInfo.getTransmitPowerInfo();
11063                     for (int i = 0; i < Math.min(txPowerInfo.size(),
11064                             SignalStrength.NUM_SIGNAL_STRENGTH_BINS); i++) {
11065                         energyUsed += txPowerInfo.get(i).getTimeInMillis() * mPowerProfile
11066                             .getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
11067                     }
11068 
11069                     // We store the power drain as mAms.
11070                     mModemActivity.getPowerCounter().addCountLocked((long) energyUsed);
11071                     // Converting uWs to mAms.
11072                     // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
11073                     long monitoredRailChargeConsumedMaMs =
11074                             (long) (mTmpRailStats.getCellularTotalEnergyUseduWs() / opVolt);
11075                     mModemActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
11076                             monitoredRailChargeConsumedMaMs);
11077                     mHistoryCur.modemRailChargeMah +=
11078                             (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
11079                     addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
11080                     mTmpRailStats.resetCellularTotalEnergyUsed();
11081                 }
11082             }
11083             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
11084             long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
11085                     elapsedRealtimeMs * 1000);
11086             mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
11087 
11088             long totalRxPackets = 0;
11089             long totalTxPackets = 0;
11090             if (delta != null) {
11091                 NetworkStats.Entry entry = new NetworkStats.Entry();
11092                 final int size = delta.size();
11093                 for (int i = 0; i < size; i++) {
11094                     entry = delta.getValues(i, entry);
11095                     if (entry.rxPackets == 0 && entry.txPackets == 0) {
11096                         continue;
11097                     }
11098 
11099                     if (DEBUG_ENERGY) {
11100                         Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
11101                                 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
11102                                 + " txPackets=" + entry.txPackets);
11103                     }
11104 
11105                     totalRxPackets += entry.rxPackets;
11106                     totalTxPackets += entry.txPackets;
11107 
11108                     final Uid u = getUidStatsLocked(mapUid(entry.uid));
11109                     u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
11110                             entry.rxPackets);
11111                     u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
11112                             entry.txPackets);
11113                     if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11114                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
11115                                 entry.rxBytes, entry.rxPackets);
11116                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
11117                                 entry.txBytes, entry.txPackets);
11118                     }
11119 
11120                     mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
11121                             entry.rxBytes);
11122                     mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
11123                             entry.txBytes);
11124                     mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
11125                             entry.rxPackets);
11126                     mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
11127                             entry.txPackets);
11128                 }
11129 
11130                 // Now distribute proportional blame to the apps that did networking.
11131                 long totalPackets = totalRxPackets + totalTxPackets;
11132                 if (totalPackets > 0) {
11133                     for (int i = 0; i < size; i++) {
11134                         entry = delta.getValues(i, entry);
11135                         if (entry.rxPackets == 0 && entry.txPackets == 0) {
11136                             continue;
11137                         }
11138 
11139                         final Uid u = getUidStatsLocked(mapUid(entry.uid));
11140 
11141                         // Distribute total radio active time in to this app.
11142                         final long appPackets = entry.rxPackets + entry.txPackets;
11143                         final long appRadioTime = (radioTime * appPackets) / totalPackets;
11144                         u.noteMobileRadioActiveTimeLocked(appRadioTime);
11145 
11146                         // Remove this app from the totals, so that we don't lose any time
11147                         // due to rounding.
11148                         radioTime -= appRadioTime;
11149                         totalPackets -= appPackets;
11150 
11151                         if (deltaInfo != null) {
11152                             ControllerActivityCounterImpl activityCounter =
11153                                     u.getOrCreateModemControllerActivityLocked();
11154                             if (totalRxPackets > 0 && entry.rxPackets > 0) {
11155                                 final long rxMs = (entry.rxPackets
11156                                     * deltaInfo.getReceiveTimeMillis()) / totalRxPackets;
11157                                 activityCounter.getRxTimeCounter().addCountLocked(rxMs);
11158                             }
11159 
11160                             if (totalTxPackets > 0 && entry.txPackets > 0) {
11161                                 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
11162                                     long txMs =
11163                                             entry.txPackets * deltaInfo.getTransmitPowerInfo()
11164                                                 .get(lvl).getTimeInMillis();
11165                                     txMs /= totalTxPackets;
11166                                     activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
11167                                 }
11168                             }
11169                         }
11170                     }
11171                 }
11172 
11173                 if (radioTime > 0) {
11174                     // Whoops, there is some radio time we can't blame on an app!
11175                     mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
11176                     mMobileRadioActiveUnknownCount.addCountLocked(1);
11177                 }
11178 
11179                 mNetworkStatsPool.release(delta);
11180                 delta = null;
11181             }
11182         }
11183     }
11184 
11185     /**
11186      * Add modem tx power to history
11187      * Device is said to be in high cellular transmit power when it has spent most of the transmit
11188      * time at the highest power level.
11189      * @param activityInfo
11190      */
addModemTxPowerToHistory(final ModemActivityInfo activityInfo)11191     private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo) {
11192         if (activityInfo == null) {
11193             return;
11194         }
11195         List<TransmitPower> txPowerInfo = activityInfo.getTransmitPowerInfo();
11196         if (txPowerInfo == null || txPowerInfo.size() != ModemActivityInfo.TX_POWER_LEVELS) {
11197             return;
11198         }
11199         final long elapsedRealtime = mClocks.elapsedRealtime();
11200         final long uptime = mClocks.uptimeMillis();
11201         int levelMaxTimeSpent = 0;
11202         for (int i = 1; i < txPowerInfo.size(); i++) {
11203             if (txPowerInfo.get(i).getTimeInMillis() > txPowerInfo.get(levelMaxTimeSpent)
11204                 .getTimeInMillis()) {
11205                 levelMaxTimeSpent = i;
11206             }
11207         }
11208         if (levelMaxTimeSpent == ModemActivityInfo.TX_POWER_LEVELS - 1) {
11209             mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
11210             addHistoryRecordLocked(elapsedRealtime, uptime);
11211         }
11212     }
11213 
11214     private final class BluetoothActivityInfoCache {
11215         long idleTimeMs;
11216         long rxTimeMs;
11217         long txTimeMs;
11218         long energy;
11219 
11220         SparseLongArray uidRxBytes = new SparseLongArray();
11221         SparseLongArray uidTxBytes = new SparseLongArray();
11222 
set(BluetoothActivityEnergyInfo info)11223         void set(BluetoothActivityEnergyInfo info) {
11224             idleTimeMs = info.getControllerIdleTimeMillis();
11225             rxTimeMs = info.getControllerRxTimeMillis();
11226             txTimeMs = info.getControllerTxTimeMillis();
11227             energy = info.getControllerEnergyUsed();
11228             if (info.getUidTraffic() != null) {
11229                 for (UidTraffic traffic : info.getUidTraffic()) {
11230                     uidRxBytes.put(traffic.getUid(), traffic.getRxBytes());
11231                     uidTxBytes.put(traffic.getUid(), traffic.getTxBytes());
11232                 }
11233             }
11234         }
11235     }
11236 
11237     private final BluetoothActivityInfoCache mLastBluetoothActivityInfo
11238             = new BluetoothActivityInfoCache();
11239 
11240     /**
11241      * Distribute Bluetooth energy info and network traffic to apps.
11242      *
11243      * @param info The energy information from the bluetooth controller.
11244      */
updateBluetoothStateLocked(@ullable final BluetoothActivityEnergyInfo info)11245     public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
11246         if (DEBUG_ENERGY) {
11247             Slog.d(TAG, "Updating bluetooth stats: " + info);
11248         }
11249 
11250         if (info == null || !mOnBatteryInternal) {
11251             return;
11252         }
11253 
11254         mHasBluetoothReporting = true;
11255 
11256         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
11257         final long rxTimeMs =
11258                 info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs;
11259         final long txTimeMs =
11260                 info.getControllerTxTimeMillis() - mLastBluetoothActivityInfo.txTimeMs;
11261         final long idleTimeMs =
11262                 info.getControllerIdleTimeMillis() - mLastBluetoothActivityInfo.idleTimeMs;
11263 
11264         if (DEBUG_ENERGY) {
11265             Slog.d(TAG, "------ BEGIN BLE power blaming ------");
11266             Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
11267             Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
11268             Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
11269         }
11270 
11271         long totalScanTimeMs = 0;
11272 
11273         final int uidCount = mUidStats.size();
11274         for (int i = 0; i < uidCount; i++) {
11275             final Uid u = mUidStats.valueAt(i);
11276             if (u.mBluetoothScanTimer == null) {
11277                 continue;
11278             }
11279 
11280             totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
11281                     elapsedRealtimeMs * 1000) / 1000;
11282         }
11283 
11284         final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
11285         final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
11286 
11287         if (DEBUG_ENERGY) {
11288             Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
11289                     + " TX=" + normalizeScanTxTime);
11290         }
11291 
11292         long leftOverRxTimeMs = rxTimeMs;
11293         long leftOverTxTimeMs = txTimeMs;
11294 
11295         for (int i = 0; i < uidCount; i++) {
11296             final Uid u = mUidStats.valueAt(i);
11297             if (u.mBluetoothScanTimer == null) {
11298                 continue;
11299             }
11300 
11301             long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
11302                     elapsedRealtimeMs * 1000) / 1000;
11303             if (scanTimeSinceMarkMs > 0) {
11304                 // Set the new mark so that next time we get new data since this point.
11305                 u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
11306 
11307                 long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
11308                 long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
11309 
11310                 if (normalizeScanRxTime) {
11311                     // Scan time is longer than the total rx time in the controller,
11312                     // so distribute the scan time proportionately. This means regular traffic
11313                     // will not blamed, but scans are more expensive anyways.
11314                     scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
11315                 }
11316 
11317                 if (normalizeScanTxTime) {
11318                     // Scan time is longer than the total tx time in the controller,
11319                     // so distribute the scan time proportionately. This means regular traffic
11320                     // will not blamed, but scans are more expensive anyways.
11321                     scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
11322                 }
11323 
11324                 final ControllerActivityCounterImpl counter =
11325                         u.getOrCreateBluetoothControllerActivityLocked();
11326                 counter.getRxTimeCounter().addCountLocked(scanTimeRxSinceMarkMs);
11327                 counter.getTxTimeCounters()[0].addCountLocked(scanTimeTxSinceMarkMs);
11328 
11329                 leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
11330                 leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
11331             }
11332         }
11333 
11334         if (DEBUG_ENERGY) {
11335             Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX="
11336                     + leftOverTxTimeMs);
11337         }
11338 
11339         //
11340         // Now distribute blame to apps that did bluetooth traffic.
11341         //
11342 
11343         long totalTxBytes = 0;
11344         long totalRxBytes = 0;
11345 
11346         final UidTraffic[] uidTraffic = info.getUidTraffic();
11347         final int numUids = uidTraffic != null ? uidTraffic.length : 0;
11348         for (int i = 0; i < numUids; i++) {
11349             final UidTraffic traffic = uidTraffic[i];
11350             final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(
11351                     traffic.getUid());
11352             final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(
11353                     traffic.getUid());
11354 
11355             // Add to the global counters.
11356             mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(rxBytes);
11357             mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes);
11358 
11359             // Add to the UID counters.
11360             final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
11361             u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0);
11362             u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0);
11363 
11364             // Calculate the total traffic.
11365             totalRxBytes += rxBytes;
11366             totalTxBytes += txBytes;
11367         }
11368 
11369         if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0
11370                 || leftOverTxTimeMs != 0)) {
11371             for (int i = 0; i < numUids; i++) {
11372                 final UidTraffic traffic = uidTraffic[i];
11373                 final int uid = traffic.getUid();
11374                 final long rxBytes =
11375                         traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid);
11376                 final long txBytes =
11377                         traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid);
11378 
11379                 final Uid u = getUidStatsLocked(mapUid(uid));
11380                 final ControllerActivityCounterImpl counter =
11381                         u.getOrCreateBluetoothControllerActivityLocked();
11382 
11383                 if (totalRxBytes > 0 && rxBytes > 0) {
11384                     final long timeRxMs = (leftOverRxTimeMs * rxBytes) / totalRxBytes;
11385                     if (DEBUG_ENERGY) {
11386                         Slog.d(TAG, "UID=" + uid + " rx_bytes=" + rxBytes + " rx_time=" + timeRxMs);
11387                     }
11388                     counter.getRxTimeCounter().addCountLocked(timeRxMs);
11389                 }
11390 
11391                 if (totalTxBytes > 0 && txBytes > 0) {
11392                     final long timeTxMs = (leftOverTxTimeMs * txBytes) / totalTxBytes;
11393                     if (DEBUG_ENERGY) {
11394                         Slog.d(TAG, "UID=" + uid + " tx_bytes=" + txBytes + " tx_time=" + timeTxMs);
11395                     }
11396                     counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
11397                 }
11398             }
11399         }
11400 
11401         mBluetoothActivity.getRxTimeCounter().addCountLocked(rxTimeMs);
11402         mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(txTimeMs);
11403         mBluetoothActivity.getIdleTimeCounter().addCountLocked(idleTimeMs);
11404 
11405         // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11406         final double opVolt = mPowerProfile.getAveragePower(
11407                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11408         if (opVolt != 0) {
11409             // We store the power drain as mAms.
11410             mBluetoothActivity.getPowerCounter().addCountLocked(
11411                     (long) ((info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
11412                             / opVolt));
11413         }
11414         mLastBluetoothActivityInfo.set(info);
11415     }
11416 
11417     /**
11418      * Read and record Resource Power Manager (RPM) state and voter times.
11419      * If RPM stats were fetched more recently than RPM_STATS_UPDATE_FREQ_MS ago, uses the old data
11420      * instead of fetching it anew.
11421      */
updateRpmStatsLocked()11422     public void updateRpmStatsLocked() {
11423         if (mPlatformIdleStateCallback == null) return;
11424         long now = SystemClock.elapsedRealtime();
11425         if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
11426             mPlatformIdleStateCallback.fillLowPowerStats(mTmpRpmStats);
11427             mLastRpmStatsUpdateTimeMs = now;
11428         }
11429 
11430         for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate
11431                 : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) {
11432 
11433             // Update values for this platform state.
11434             final String pName = pstate.getKey();
11435             final long pTimeUs = pstate.getValue().mTimeMs * 1000;
11436             final int pCount = pstate.getValue().mCount;
11437             getRpmTimerLocked(pName).update(pTimeUs, pCount);
11438             if (SCREEN_OFF_RPM_STATS_ENABLED) {
11439                 getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount);
11440             }
11441 
11442             // Update values for each voter of this platform state.
11443             for (Map.Entry<String, RpmStats.PowerStateElement> voter
11444                     : pstate.getValue().mVoters.entrySet()) {
11445                 final String vName = pName + "." + voter.getKey();
11446                 final long vTimeUs = voter.getValue().mTimeMs * 1000;
11447                 final int vCount = voter.getValue().mCount;
11448                 getRpmTimerLocked(vName).update(vTimeUs, vCount);
11449                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
11450                     getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount);
11451                 }
11452             }
11453         }
11454 
11455         for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys
11456                 : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) {
11457 
11458             final String subsysName = subsys.getKey();
11459             for (Map.Entry<String, RpmStats.PowerStateElement> sstate
11460                     : subsys.getValue().mStates.entrySet()) {
11461                 final String name = subsysName + "." + sstate.getKey();
11462                 final long timeUs = sstate.getValue().mTimeMs * 1000;
11463                 final int count = sstate.getValue().mCount;
11464                 getRpmTimerLocked(name).update(timeUs, count);
11465                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
11466                     getScreenOffRpmTimerLocked(name).update(timeUs, count);
11467                 }
11468             }
11469         }
11470     }
11471 
11472     /**
11473      * Read and record Rail Energy data.
11474      */
updateRailStatsLocked()11475     public void updateRailStatsLocked() {
11476         if (mRailEnergyDataCallback == null || !mTmpRailStats.isRailStatsAvailable()) {
11477             return;
11478         }
11479         mRailEnergyDataCallback.fillRailDataStats(mTmpRailStats);
11480     }
11481 
11482     /**
11483      * Read and distribute kernel wake lock use across apps.
11484      */
updateKernelWakelocksLocked()11485     public void updateKernelWakelocksLocked() {
11486         final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
11487                 mTmpWakelockStats);
11488         if (wakelockStats == null) {
11489             // Not crashing might make board bringup easier.
11490             Slog.w(TAG, "Couldn't get kernel wake lock stats");
11491             return;
11492         }
11493 
11494         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
11495             String name = ent.getKey();
11496             KernelWakelockStats.Entry kws = ent.getValue();
11497 
11498             SamplingTimer kwlt = mKernelWakelockStats.get(name);
11499             if (kwlt == null) {
11500                 kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
11501                 mKernelWakelockStats.put(name, kwlt);
11502             }
11503 
11504             kwlt.update(kws.mTotalTime, kws.mCount);
11505             kwlt.setUpdateVersion(kws.mVersion);
11506         }
11507 
11508         int numWakelocksSetStale = 0;
11509         // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
11510         // this time.
11511         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
11512             SamplingTimer st = ent.getValue();
11513             if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
11514                 st.endSample();
11515                 numWakelocksSetStale++;
11516             }
11517         }
11518 
11519         // Record whether we've seen a non-zero time (for debugging b/22716723).
11520         if (wakelockStats.isEmpty()) {
11521             Slog.wtf(TAG, "All kernel wakelocks had time of zero");
11522         }
11523 
11524         if (numWakelocksSetStale == mKernelWakelockStats.size()) {
11525             Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
11526                     wakelockStats.kernelWakelockVersion);
11527         }
11528     }
11529 
11530     // We use an anonymous class to access these variables,
11531     // so they can't live on the stack or they'd have to be
11532     // final MutableLong objects (more allocations).
11533     // Used in updateCpuTimeLocked().
11534     long mTempTotalCpuUserTimeUs;
11535     long mTempTotalCpuSystemTimeUs;
11536     long[][] mWakeLockAllocationsUs;
11537 
11538     /**
11539      * Reads the newest memory stats from the kernel.
11540      */
updateKernelMemoryBandwidthLocked()11541     public void updateKernelMemoryBandwidthLocked() {
11542         mKernelMemoryBandwidthStats.updateStats();
11543         LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
11544         final int bandwidthEntryCount = bandwidthEntries.size();
11545         int index;
11546         for (int i = 0; i < bandwidthEntryCount; i++) {
11547             SamplingTimer timer;
11548             if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) {
11549                 timer = mKernelMemoryStats.valueAt(index);
11550             } else {
11551                 timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
11552                 mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
11553             }
11554             timer.update(bandwidthEntries.valueAt(i), 1);
11555             if (DEBUG_MEMORY) {
11556                 Slog.d(TAG, String.format("Added entry %d and updated timer to: "
11557                         + "mUnpluggedReportedTotalTime %d size %d", bandwidthEntries.keyAt(i),
11558                         mKernelMemoryStats.get(
11559                                 bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTime,
11560                         mKernelMemoryStats.size()));
11561             }
11562         }
11563     }
11564 
isOnBatteryLocked()11565     public boolean isOnBatteryLocked() {
11566         return mOnBatteryTimeBase.isRunning();
11567     }
11568 
isOnBatteryScreenOffLocked()11569     public boolean isOnBatteryScreenOffLocked() {
11570         return mOnBatteryScreenOffTimeBase.isRunning();
11571     }
11572 
11573     /**
11574      * Read and distribute CPU usage across apps. If their are partial wakelocks being held
11575      * and we are on battery with screen off, we give more of the cpu time to those apps holding
11576      * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
11577      * It's possible this will be invoked after the internal battery/screen states are updated, so
11578      * passing the appropriate battery/screen states to try attribute the cpu times to correct
11579      * buckets.
11580      */
11581     @GuardedBy("this")
updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff)11582     public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff) {
11583         if (mPowerProfile == null) {
11584             return;
11585         }
11586 
11587         if (DEBUG_ENERGY_CPU) {
11588             Slog.d(TAG, "!Cpu updating!");
11589         }
11590 
11591         if (mCpuFreqs == null) {
11592             mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
11593         }
11594 
11595         // Calculate the wakelocks we have to distribute amongst. The system is excluded as it is
11596         // usually holding the wakelock on behalf of an app.
11597         // And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
11598         ArrayList<StopwatchTimer> partialTimersToConsider = null;
11599         if (onBatteryScreenOff) {
11600             partialTimersToConsider = new ArrayList<>();
11601             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
11602                 final StopwatchTimer timer = mPartialTimers.get(i);
11603                 // Since the collection and blaming of wakelocks can be scheduled to run after
11604                 // some delay, the mPartialTimers list may have new entries. We can't blame
11605                 // the newly added timer for past cpu time, so we only consider timers that
11606                 // were present for one round of collection. Once a timer has gone through
11607                 // a round of collection, its mInList field is set to true.
11608                 if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
11609                     partialTimersToConsider.add(timer);
11610                 }
11611             }
11612         }
11613         markPartialTimersAsEligible();
11614 
11615         // When the battery is not on, we don't attribute the cpu times to any timers but we still
11616         // need to take the snapshots.
11617         if (!onBattery) {
11618             mCpuUidUserSysTimeReader.readDelta(null);
11619             mCpuUidFreqTimeReader.readDelta(null);
11620             mNumAllUidCpuTimeReads += 2;
11621             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
11622                 mCpuUidActiveTimeReader.readDelta(null);
11623                 mCpuUidClusterTimeReader.readDelta(null);
11624                 mNumAllUidCpuTimeReads += 2;
11625             }
11626             for (int cluster = mKernelCpuSpeedReaders.length - 1; cluster >= 0; --cluster) {
11627                 mKernelCpuSpeedReaders[cluster].readDelta();
11628             }
11629             return;
11630         }
11631 
11632         mUserInfoProvider.refreshUserIds();
11633         final SparseLongArray updatedUids = mCpuUidFreqTimeReader.perClusterTimesAvailable()
11634                 ? null : new SparseLongArray();
11635         readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
11636         // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
11637         // freqs, so no need to approximate these values.
11638         if (updatedUids != null) {
11639             updateClusterSpeedTimes(updatedUids, onBattery);
11640         }
11641         readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff);
11642         mNumAllUidCpuTimeReads += 2;
11643         if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
11644             readKernelUidCpuActiveTimesLocked(onBattery);
11645             readKernelUidCpuClusterTimesLocked(onBattery);
11646             mNumAllUidCpuTimeReads += 2;
11647         }
11648     }
11649 
11650     /**
11651      * Mark the current partial timers as gone through a collection so that they will be
11652      * considered in the next cpu times distribution to wakelock holders.
11653      */
11654     @VisibleForTesting
markPartialTimersAsEligible()11655     public void markPartialTimersAsEligible() {
11656         if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
11657             // No difference, so each timer is now considered for the next collection.
11658             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
11659                 mPartialTimers.get(i).mInList = true;
11660             }
11661         } else {
11662             // The lists are different, meaning we added (or removed a timer) since the last
11663             // collection.
11664             for (int i = mLastPartialTimers.size() - 1; i >= 0; --i) {
11665                 mLastPartialTimers.get(i).mInList = false;
11666             }
11667             mLastPartialTimers.clear();
11668 
11669             // Mark the current timers as gone through a collection.
11670             final int numPartialTimers = mPartialTimers.size();
11671             for (int i = 0; i < numPartialTimers; ++i) {
11672                 final StopwatchTimer timer = mPartialTimers.get(i);
11673                 timer.mInList = true;
11674                 mLastPartialTimers.add(timer);
11675             }
11676         }
11677     }
11678 
11679     /**
11680      * Take snapshot of cpu times (aggregated over all uids) at different frequencies and
11681      * calculate cpu times spent by each uid at different frequencies.
11682      *
11683      * @param updatedUids The uids for which times spent at different frequencies are calculated.
11684      */
11685     @VisibleForTesting
updateClusterSpeedTimes(@onNull SparseLongArray updatedUids, boolean onBattery)11686     public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery) {
11687         long totalCpuClustersTimeMs = 0;
11688         // Read the time spent for each cluster at various cpu frequencies.
11689         final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
11690         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
11691             clusterSpeedTimesMs[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
11692             if (clusterSpeedTimesMs[cluster] != null) {
11693                 for (int speed = clusterSpeedTimesMs[cluster].length - 1; speed >= 0; --speed) {
11694                     totalCpuClustersTimeMs += clusterSpeedTimesMs[cluster][speed];
11695                 }
11696             }
11697         }
11698         if (totalCpuClustersTimeMs != 0) {
11699             // We have cpu times per freq aggregated over all uids but we need the times per uid.
11700             // So, we distribute total time spent by an uid to different cpu freqs based on the
11701             // amount of time cpu was running at that freq.
11702             final int updatedUidsCount = updatedUids.size();
11703             for (int i = 0; i < updatedUidsCount; ++i) {
11704                 final Uid u = getUidStatsLocked(updatedUids.keyAt(i));
11705                 final long appCpuTimeUs = updatedUids.valueAt(i);
11706                 // Add the cpu speeds to this UID.
11707                 final int numClusters = mPowerProfile.getNumCpuClusters();
11708                 if (u.mCpuClusterSpeedTimesUs == null ||
11709                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
11710                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
11711                 }
11712 
11713                 for (int cluster = 0; cluster < clusterSpeedTimesMs.length; cluster++) {
11714                     final int speedsInCluster = clusterSpeedTimesMs[cluster].length;
11715                     if (u.mCpuClusterSpeedTimesUs[cluster] == null || speedsInCluster !=
11716                             u.mCpuClusterSpeedTimesUs[cluster].length) {
11717                         u.mCpuClusterSpeedTimesUs[cluster]
11718                                 = new LongSamplingCounter[speedsInCluster];
11719                     }
11720 
11721                     final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeedTimesUs[cluster];
11722                     for (int speed = 0; speed < speedsInCluster; speed++) {
11723                         if (cpuSpeeds[speed] == null) {
11724                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
11725                         }
11726                         cpuSpeeds[speed].addCountLocked(appCpuTimeUs
11727                                 * clusterSpeedTimesMs[cluster][speed]
11728                                 / totalCpuClustersTimeMs, onBattery);
11729                     }
11730                 }
11731             }
11732         }
11733     }
11734 
11735     /**
11736      * Take a snapshot of the cpu times spent by each uid and update the corresponding counters.
11737      * If {@param partialTimers} is not null and empty, then we assign a portion of cpu times to
11738      * wakelock holders.
11739      *
11740      * @param partialTimers The wakelock holders among which the cpu times will be distributed.
11741      * @param updatedUids If not null, then the uids found in the snapshot will be added to this.
11742      */
11743     @VisibleForTesting
readKernelUidCpuTimesLocked(@ullable ArrayList<StopwatchTimer> partialTimers, @Nullable SparseLongArray updatedUids, boolean onBattery)11744     public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
11745             @Nullable SparseLongArray updatedUids, boolean onBattery) {
11746         mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
11747         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
11748         final long startTimeMs = mClocks.uptimeMillis();
11749 
11750         mCpuUidUserSysTimeReader.readDelta((uid, timesUs) -> {
11751             long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
11752 
11753             uid = mapUid(uid);
11754             if (Process.isIsolated(uid)) {
11755                 // This could happen if the isolated uid mapping was removed before that process
11756                 // was actually killed.
11757                 mCpuUidUserSysTimeReader.removeUid(uid);
11758                 Slog.d(TAG, "Got readings for an isolated uid with no mapping: " + uid);
11759                 return;
11760             }
11761             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
11762                 Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
11763                 mCpuUidUserSysTimeReader.removeUid(uid);
11764                 return;
11765             }
11766             final Uid u = getUidStatsLocked(uid);
11767 
11768             // Accumulate the total system and user time.
11769             mTempTotalCpuUserTimeUs += userTimeUs;
11770             mTempTotalCpuSystemTimeUs += systemTimeUs;
11771 
11772             StringBuilder sb = null;
11773             if (DEBUG_ENERGY_CPU) {
11774                 sb = new StringBuilder();
11775                 sb.append("  got time for uid=").append(u.mUid).append(": u=");
11776                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
11777                 sb.append(" s=");
11778                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
11779                 sb.append("\n");
11780             }
11781 
11782             if (numWakelocks > 0) {
11783                 // We have wakelocks being held, so only give a portion of the
11784                 // time to the process. The rest will be distributed among wakelock
11785                 // holders.
11786                 userTimeUs = (userTimeUs * WAKE_LOCK_WEIGHT) / 100;
11787                 systemTimeUs = (systemTimeUs * WAKE_LOCK_WEIGHT) / 100;
11788             }
11789 
11790             if (sb != null) {
11791                 sb.append("  adding to uid=").append(u.mUid).append(": u=");
11792                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
11793                 sb.append(" s=");
11794                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
11795                 Slog.d(TAG, sb.toString());
11796             }
11797 
11798             u.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
11799             u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
11800             if (updatedUids != null) {
11801                 updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
11802             }
11803         });
11804 
11805         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
11806         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
11807             Slog.d(TAG, "Reading cpu stats took " + elapsedTimeMs + "ms");
11808         }
11809 
11810         if (numWakelocks > 0) {
11811             // Distribute a portion of the total cpu time to wakelock holders.
11812             mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
11813             mTempTotalCpuSystemTimeUs =
11814                     (mTempTotalCpuSystemTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
11815 
11816             for (int i = 0; i < numWakelocks; ++i) {
11817                 final StopwatchTimer timer = partialTimers.get(i);
11818                 final int userTimeUs = (int) (mTempTotalCpuUserTimeUs / (numWakelocks - i));
11819                 final int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / (numWakelocks - i));
11820 
11821                 if (DEBUG_ENERGY_CPU) {
11822                     final StringBuilder sb = new StringBuilder();
11823                     sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
11824                             .append(": u=");
11825                     TimeUtils.formatDuration(userTimeUs / 1000, sb);
11826                     sb.append(" s=");
11827                     TimeUtils.formatDuration(systemTimeUs / 1000, sb);
11828                     Slog.d(TAG, sb.toString());
11829                 }
11830 
11831                 timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
11832                 timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
11833                 if (updatedUids != null) {
11834                     final int uid = timer.mUid.getUid();
11835                     updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
11836                 }
11837 
11838                 final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
11839                 proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery);
11840 
11841                 mTempTotalCpuUserTimeUs -= userTimeUs;
11842                 mTempTotalCpuSystemTimeUs -= systemTimeUs;
11843             }
11844         }
11845     }
11846 
11847     /**
11848      * Take a snapshot of the cpu times spent by each uid in each freq and update the
11849      * corresponding counters.
11850      *
11851      * @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
11852      */
11853     @VisibleForTesting
readKernelUidCpuFreqTimesLocked(@ullable ArrayList<StopwatchTimer> partialTimers, boolean onBattery, boolean onBatteryScreenOff)11854     public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
11855             boolean onBattery, boolean onBatteryScreenOff) {
11856         final boolean perClusterTimesAvailable =
11857                 mCpuUidFreqTimeReader.perClusterTimesAvailable();
11858         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
11859         final int numClusters = mPowerProfile.getNumCpuClusters();
11860         mWakeLockAllocationsUs = null;
11861         final long startTimeMs = mClocks.uptimeMillis();
11862         mCpuUidFreqTimeReader.readDelta((uid, cpuFreqTimeMs) -> {
11863             uid = mapUid(uid);
11864             if (Process.isIsolated(uid)) {
11865                 mCpuUidFreqTimeReader.removeUid(uid);
11866                 Slog.d(TAG, "Got freq readings for an isolated uid with no mapping: " + uid);
11867                 return;
11868             }
11869             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
11870                 Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
11871                 mCpuUidFreqTimeReader.removeUid(uid);
11872                 return;
11873             }
11874             final Uid u = getUidStatsLocked(uid);
11875             if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
11876                 detachIfNotNull(u.mCpuFreqTimeMs);
11877                 u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
11878             }
11879             u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
11880             if (u.mScreenOffCpuFreqTimeMs == null ||
11881                     u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
11882                 detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
11883                 u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
11884                         mOnBatteryScreenOffTimeBase);
11885             }
11886             u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff);
11887 
11888             if (perClusterTimesAvailable) {
11889                 if (u.mCpuClusterSpeedTimesUs == null ||
11890                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
11891                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
11892                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
11893                 }
11894                 if (numWakelocks > 0 && mWakeLockAllocationsUs == null) {
11895                     mWakeLockAllocationsUs = new long[numClusters][];
11896                 }
11897 
11898                 int freqIndex = 0;
11899                 for (int cluster = 0; cluster < numClusters; ++cluster) {
11900                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
11901                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
11902                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
11903                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
11904                         u.mCpuClusterSpeedTimesUs[cluster]
11905                                 = new LongSamplingCounter[speedsInCluster];
11906                     }
11907                     if (numWakelocks > 0 && mWakeLockAllocationsUs[cluster] == null) {
11908                         mWakeLockAllocationsUs[cluster] = new long[speedsInCluster];
11909                     }
11910                     final LongSamplingCounter[] cpuTimesUs = u.mCpuClusterSpeedTimesUs[cluster];
11911                     for (int speed = 0; speed < speedsInCluster; ++speed) {
11912                         if (cpuTimesUs[speed] == null) {
11913                             cpuTimesUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
11914                         }
11915                         final long appAllocationUs;
11916                         if (mWakeLockAllocationsUs != null) {
11917                             appAllocationUs =
11918                                     (cpuFreqTimeMs[freqIndex] * 1000 * WAKE_LOCK_WEIGHT) / 100;
11919                             mWakeLockAllocationsUs[cluster][speed] +=
11920                                     (cpuFreqTimeMs[freqIndex] * 1000 - appAllocationUs);
11921                         } else {
11922                             appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
11923                         }
11924                         cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
11925                         freqIndex++;
11926                     }
11927                 }
11928             }
11929         });
11930 
11931         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
11932         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
11933             Slog.d(TAG, "Reading cpu freq times took " + elapsedTimeMs + "ms");
11934         }
11935 
11936         if (mWakeLockAllocationsUs != null) {
11937             for (int i = 0; i < numWakelocks; ++i) {
11938                 final Uid u = partialTimers.get(i).mUid;
11939                 if (u.mCpuClusterSpeedTimesUs == null ||
11940                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
11941                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
11942                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
11943                 }
11944 
11945                 for (int cluster = 0; cluster < numClusters; ++cluster) {
11946                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
11947                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
11948                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
11949                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
11950                         u.mCpuClusterSpeedTimesUs[cluster]
11951                                 = new LongSamplingCounter[speedsInCluster];
11952                     }
11953                     final LongSamplingCounter[] cpuTimeUs = u.mCpuClusterSpeedTimesUs[cluster];
11954                     for (int speed = 0; speed < speedsInCluster; ++speed) {
11955                         if (cpuTimeUs[speed] == null) {
11956                             cpuTimeUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
11957                         }
11958                         final long allocationUs =
11959                                 mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
11960                         cpuTimeUs[speed].addCountLocked(allocationUs, onBattery);
11961                         mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
11962                     }
11963                 }
11964             }
11965         }
11966     }
11967 
11968     /**
11969      * Take a snapshot of the cpu active times spent by each uid and update the corresponding
11970      * counters.
11971      */
11972     @VisibleForTesting
readKernelUidCpuActiveTimesLocked(boolean onBattery)11973     public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
11974         final long startTimeMs = mClocks.uptimeMillis();
11975         mCpuUidActiveTimeReader.readDelta((uid, cpuActiveTimesMs) -> {
11976             uid = mapUid(uid);
11977             if (Process.isIsolated(uid)) {
11978                 mCpuUidActiveTimeReader.removeUid(uid);
11979                 Slog.w(TAG, "Got active times for an isolated uid with no mapping: " + uid);
11980                 return;
11981             }
11982             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
11983                 Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
11984                 mCpuUidActiveTimeReader.removeUid(uid);
11985                 return;
11986             }
11987             final Uid u = getUidStatsLocked(uid);
11988             u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesMs, onBattery);
11989         });
11990 
11991         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
11992         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
11993             Slog.d(TAG, "Reading cpu active times took " + elapsedTimeMs + "ms");
11994         }
11995     }
11996 
11997     /**
11998      * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding
11999      * counters.
12000      */
12001     @VisibleForTesting
readKernelUidCpuClusterTimesLocked(boolean onBattery)12002     public void readKernelUidCpuClusterTimesLocked(boolean onBattery) {
12003         final long startTimeMs = mClocks.uptimeMillis();
12004         mCpuUidClusterTimeReader.readDelta((uid, cpuClusterTimesMs) -> {
12005             uid = mapUid(uid);
12006             if (Process.isIsolated(uid)) {
12007                 mCpuUidClusterTimeReader.removeUid(uid);
12008                 Slog.w(TAG, "Got cluster times for an isolated uid with no mapping: " + uid);
12009                 return;
12010             }
12011             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
12012                 Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
12013                 mCpuUidClusterTimeReader.removeUid(uid);
12014                 return;
12015             }
12016             final Uid u = getUidStatsLocked(uid);
12017             u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesMs, onBattery);
12018         });
12019 
12020         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
12021         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
12022             Slog.d(TAG, "Reading cpu cluster times took " + elapsedTimeMs + "ms");
12023         }
12024     }
12025 
setChargingLocked(boolean charging)12026     boolean setChargingLocked(boolean charging) {
12027         // if the device is no longer charging, remove the callback
12028         // if the device is now charging, it means that this is either called
12029         // 1. directly when level >= 90
12030         // 2. or from within the runnable that we deferred
12031         // For 1. if we have an existing callback, remove it, since we will immediately send a
12032         // ACTION_CHARGING
12033         // For 2. we remove existing callback so we don't send multiple ACTION_CHARGING
12034         mHandler.removeCallbacks(mDeferSetCharging);
12035         if (mCharging != charging) {
12036             mCharging = charging;
12037             if (charging) {
12038                 mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
12039             } else {
12040                 mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
12041             }
12042             mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
12043             return true;
12044         }
12045         return false;
12046     }
12047 
12048     @GuardedBy("this")
setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery, final int oldStatus, final int level, final int chargeUAh)12049     protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
12050             final boolean onBattery, final int oldStatus, final int level, final int chargeUAh) {
12051         boolean doWrite = false;
12052         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
12053         m.arg1 = onBattery ? 1 : 0;
12054         mHandler.sendMessage(m);
12055 
12056         final long uptime = mSecUptime * 1000;
12057         final long realtime = mSecRealtime * 1000;
12058         final int screenState = mScreenState;
12059         if (onBattery) {
12060             // We will reset our status if we are unplugging after the
12061             // battery was last full, or the level is at 100, or
12062             // we have gone through a significant charge (from a very low
12063             // level to a now very high level).
12064             boolean reset = false;
12065             if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
12066                     || level >= 90
12067                     || (mDischargeCurrentLevel < 20 && level >= 80))) {
12068                 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
12069                         + " dischargeLevel=" + mDischargeCurrentLevel
12070                         + " lowAmount=" + getLowDischargeAmountSinceCharge()
12071                         + " highAmount=" + getHighDischargeAmountSinceCharge());
12072                 // Before we write, collect a snapshot of the final aggregated
12073                 // stats to be reported in the next checkin.  Only do this if we have
12074                 // a sufficient amount of data to make it interesting.
12075                 if (getLowDischargeAmountSinceCharge() >= 20) {
12076                     final long startTime = SystemClock.uptimeMillis();
12077                     final Parcel parcel = Parcel.obtain();
12078                     writeSummaryToParcel(parcel, true);
12079                     final long initialTime = SystemClock.uptimeMillis() - startTime;
12080                     BackgroundThread.getHandler().post(new Runnable() {
12081                         @Override public void run() {
12082                             synchronized (mCheckinFile) {
12083                                 final long startTime2 = SystemClock.uptimeMillis();
12084                                 FileOutputStream stream = null;
12085                                 try {
12086                                     stream = mCheckinFile.startWrite();
12087                                     stream.write(parcel.marshall());
12088                                     stream.flush();
12089                                     mCheckinFile.finishWrite(stream);
12090                                     com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
12091                                             "batterystats-checkin",
12092                                             initialTime + SystemClock.uptimeMillis() - startTime2);
12093                                 } catch (IOException e) {
12094                                     Slog.w("BatteryStats",
12095                                             "Error writing checkin battery statistics", e);
12096                                     mCheckinFile.failWrite(stream);
12097                                 } finally {
12098                                     parcel.recycle();
12099                                 }
12100                             }
12101                         }
12102                     });
12103                 }
12104                 doWrite = true;
12105                 resetAllStatsLocked();
12106                 if (chargeUAh > 0 && level > 0) {
12107                     // Only use the reported coulomb charge value if it is supported and reported.
12108                     mEstimatedBatteryCapacity = (int) ((chargeUAh / 1000) / (level / 100.0));
12109                 }
12110                 mDischargeStartLevel = level;
12111                 reset = true;
12112                 mDischargeStepTracker.init();
12113             }
12114             if (mCharging) {
12115                 setChargingLocked(false);
12116             }
12117             mLastChargingStateLevel = level;
12118             mOnBattery = mOnBatteryInternal = true;
12119             mLastDischargeStepLevel = level;
12120             mMinDischargeStepLevel = level;
12121             mDischargeStepTracker.clearTime();
12122             mDailyDischargeStepTracker.clearTime();
12123             mInitStepMode = mCurStepMode;
12124             mModStepMode = 0;
12125             pullPendingStateUpdatesLocked();
12126             mHistoryCur.batteryLevel = (byte)level;
12127             mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12128             if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
12129                     + Integer.toHexString(mHistoryCur.states));
12130             if (reset) {
12131                 mRecordingHistory = true;
12132                 startRecordingHistory(mSecRealtime, mSecUptime, reset);
12133             }
12134             addHistoryRecordLocked(mSecRealtime, mSecUptime);
12135             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
12136             if (isScreenOn(screenState)) {
12137                 mDischargeScreenOnUnplugLevel = level;
12138                 mDischargeScreenDozeUnplugLevel = 0;
12139                 mDischargeScreenOffUnplugLevel = 0;
12140             } else if (isScreenDoze(screenState)) {
12141                 mDischargeScreenOnUnplugLevel = 0;
12142                 mDischargeScreenDozeUnplugLevel = level;
12143                 mDischargeScreenOffUnplugLevel = 0;
12144             } else {
12145                 mDischargeScreenOnUnplugLevel = 0;
12146                 mDischargeScreenDozeUnplugLevel = 0;
12147                 mDischargeScreenOffUnplugLevel = level;
12148             }
12149             mDischargeAmountScreenOn = 0;
12150             mDischargeAmountScreenDoze = 0;
12151             mDischargeAmountScreenOff = 0;
12152             updateTimeBasesLocked(true, screenState, uptime, realtime);
12153         } else {
12154             mLastChargingStateLevel = level;
12155             mOnBattery = mOnBatteryInternal = false;
12156             pullPendingStateUpdatesLocked();
12157             mHistoryCur.batteryLevel = (byte)level;
12158             mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12159             if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
12160                     + Integer.toHexString(mHistoryCur.states));
12161             addHistoryRecordLocked(mSecRealtime, mSecUptime);
12162             mDischargeCurrentLevel = mDischargePlugLevel = level;
12163             if (level < mDischargeUnplugLevel) {
12164                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
12165                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
12166             }
12167             updateDischargeScreenLevelsLocked(screenState, screenState);
12168             updateTimeBasesLocked(false, screenState, uptime, realtime);
12169             mChargeStepTracker.init();
12170             mLastChargeStepLevel = level;
12171             mMaxChargeStepLevel = level;
12172             mInitStepMode = mCurStepMode;
12173             mModStepMode = 0;
12174         }
12175         if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
12176             if (mStatsFile != null && mBatteryStatsHistory.getActiveFile() != null) {
12177                 writeAsyncLocked();
12178             }
12179         }
12180     }
12181 
startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs, boolean reset)12182     private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
12183             boolean reset) {
12184         mRecordingHistory = true;
12185         mHistoryCur.currentTime = System.currentTimeMillis();
12186         addHistoryBufferLocked(elapsedRealtimeMs,
12187                 reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
12188                 mHistoryCur);
12189         mHistoryCur.currentTime = 0;
12190         if (reset) {
12191             initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
12192         }
12193     }
12194 
recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs, final long uptimeMs)12195     private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
12196             final long uptimeMs) {
12197         if (mRecordingHistory) {
12198             mHistoryCur.currentTime = currentTime;
12199             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_CURRENT_TIME, mHistoryCur);
12200             mHistoryCur.currentTime = 0;
12201         }
12202     }
12203 
recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs)12204     private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
12205         if (mRecordingHistory) {
12206             mHistoryCur.currentTime = System.currentTimeMillis();
12207             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_SHUTDOWN, mHistoryCur);
12208             mHistoryCur.currentTime = 0;
12209         }
12210     }
12211 
scheduleSyncExternalStatsLocked(String reason, int updateFlags)12212     private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
12213         if (mExternalSync != null) {
12214             mExternalSync.scheduleSync(reason, updateFlags);
12215         }
12216     }
12217 
12218     // This should probably be exposed in the API, though it's not critical
12219     public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
12220 
12221     @GuardedBy("this")
setBatteryStateLocked(final int status, final int health, final int plugType, final int level, int temp, final int volt, final int chargeUAh, final int chargeFullUAh, final long chargeTimeToFullSeconds)12222     public void setBatteryStateLocked(final int status, final int health, final int plugType,
12223             final int level, /* not final */ int temp, final int volt, final int chargeUAh,
12224             final int chargeFullUAh, final long chargeTimeToFullSeconds) {
12225         // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
12226         temp = Math.max(0, temp);
12227 
12228         reportChangesToStatsLog(mHaveBatteryLevel ? mHistoryCur : null,
12229                 status, plugType, level);
12230 
12231         final boolean onBattery = isOnBattery(plugType, status);
12232         final long uptime = mClocks.uptimeMillis();
12233         final long elapsedRealtime = mClocks.elapsedRealtime();
12234         if (!mHaveBatteryLevel) {
12235             mHaveBatteryLevel = true;
12236             // We start out assuming that the device is plugged in (not
12237             // on battery).  If our first report is now that we are indeed
12238             // plugged in, then twiddle our state to correctly reflect that
12239             // since we won't be going through the full setOnBattery().
12240             if (onBattery == mOnBattery) {
12241                 if (onBattery) {
12242                     mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12243                 } else {
12244                     mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12245                 }
12246             }
12247             // Always start out assuming charging, that will be updated later.
12248             mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
12249             mHistoryCur.batteryStatus = (byte)status;
12250             mHistoryCur.batteryLevel = (byte)level;
12251             mHistoryCur.batteryChargeUAh = chargeUAh;
12252             mMaxChargeStepLevel = mMinDischargeStepLevel =
12253                     mLastChargeStepLevel = mLastDischargeStepLevel = level;
12254             mLastChargingStateLevel = level;
12255         } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
12256             recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
12257         }
12258         int oldStatus = mHistoryCur.batteryStatus;
12259         if (onBattery) {
12260             mDischargeCurrentLevel = level;
12261             if (!mRecordingHistory) {
12262                 mRecordingHistory = true;
12263                 startRecordingHistory(elapsedRealtime, uptime, true);
12264             }
12265         } else if (level < 96 &&
12266                 status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
12267             if (!mRecordingHistory) {
12268                 mRecordingHistory = true;
12269                 startRecordingHistory(elapsedRealtime, uptime, true);
12270             }
12271         }
12272         mCurrentBatteryLevel = level;
12273         if (mDischargePlugLevel < 0) {
12274             mDischargePlugLevel = level;
12275         }
12276 
12277         if (onBattery != mOnBattery) {
12278             mHistoryCur.batteryLevel = (byte)level;
12279             mHistoryCur.batteryStatus = (byte)status;
12280             mHistoryCur.batteryHealth = (byte)health;
12281             mHistoryCur.batteryPlugType = (byte)plugType;
12282             mHistoryCur.batteryTemperature = (short)temp;
12283             mHistoryCur.batteryVoltage = (char)volt;
12284             if (chargeUAh < mHistoryCur.batteryChargeUAh) {
12285                 // Only record discharges
12286                 final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
12287                 mDischargeCounter.addCountLocked(chargeDiff);
12288                 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
12289                 if (isScreenDoze(mScreenState)) {
12290                     mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
12291                 }
12292                 if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
12293                     mDischargeLightDozeCounter.addCountLocked(chargeDiff);
12294                 } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
12295                     mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
12296                 }
12297             }
12298             mHistoryCur.batteryChargeUAh = chargeUAh;
12299             setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level, chargeUAh);
12300         } else {
12301             boolean changed = false;
12302             if (mHistoryCur.batteryLevel != level) {
12303                 mHistoryCur.batteryLevel = (byte)level;
12304                 changed = true;
12305 
12306                 // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
12307                 // which will pull external stats.
12308                 mExternalSync.scheduleSyncDueToBatteryLevelChange(
12309                         mConstants.BATTERY_LEVEL_COLLECTION_DELAY_MS);
12310             }
12311             if (mHistoryCur.batteryStatus != status) {
12312                 mHistoryCur.batteryStatus = (byte)status;
12313                 changed = true;
12314             }
12315             if (mHistoryCur.batteryHealth != health) {
12316                 mHistoryCur.batteryHealth = (byte)health;
12317                 changed = true;
12318             }
12319             if (mHistoryCur.batteryPlugType != plugType) {
12320                 mHistoryCur.batteryPlugType = (byte)plugType;
12321                 changed = true;
12322             }
12323             if (temp >= (mHistoryCur.batteryTemperature+10)
12324                     || temp <= (mHistoryCur.batteryTemperature-10)) {
12325                 mHistoryCur.batteryTemperature = (short)temp;
12326                 changed = true;
12327             }
12328             if (volt > (mHistoryCur.batteryVoltage+20)
12329                     || volt < (mHistoryCur.batteryVoltage-20)) {
12330                 mHistoryCur.batteryVoltage = (char)volt;
12331                 changed = true;
12332             }
12333             if (chargeUAh >= (mHistoryCur.batteryChargeUAh+10)
12334                     || chargeUAh <= (mHistoryCur.batteryChargeUAh-10)) {
12335                 if (chargeUAh < mHistoryCur.batteryChargeUAh) {
12336                     // Only record discharges
12337                     final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
12338                     mDischargeCounter.addCountLocked(chargeDiff);
12339                     mDischargeScreenOffCounter.addCountLocked(chargeDiff);
12340                     if (isScreenDoze(mScreenState)) {
12341                         mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
12342                     }
12343                     if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
12344                         mDischargeLightDozeCounter.addCountLocked(chargeDiff);
12345                     } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
12346                         mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
12347                     }
12348                 }
12349                 mHistoryCur.batteryChargeUAh = chargeUAh;
12350                 changed = true;
12351             }
12352             long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
12353                     | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
12354                     | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
12355             if (onBattery) {
12356                 changed |= setChargingLocked(false);
12357                 if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
12358                     mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
12359                             modeBits, elapsedRealtime);
12360                     mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
12361                             modeBits, elapsedRealtime);
12362                     mLastDischargeStepLevel = level;
12363                     mMinDischargeStepLevel = level;
12364                     mInitStepMode = mCurStepMode;
12365                     mModStepMode = 0;
12366                 }
12367             } else {
12368                 if (level >= 90) {
12369                     // If the battery level is at least 90%, always consider the device to be
12370                     // charging even if it happens to go down a level.
12371                     changed |= setChargingLocked(true);
12372                 } else if (!mCharging) {
12373                     if (mLastChargeStepLevel < level) {
12374                         // We have not reported that we are charging, but the level has gone up,
12375                         // but we would like to not have tons of activity from charging-constraint
12376                         // jobs, so instead of reporting ACTION_CHARGING immediately, we defer it.
12377                         if (!mHandler.hasCallbacks(mDeferSetCharging)) {
12378                             mHandler.postDelayed(
12379                                     mDeferSetCharging,
12380                                     mConstants.BATTERY_CHARGED_DELAY_MS);
12381                         }
12382                     } else if (mLastChargeStepLevel > level) {
12383                         // if we had deferred a runnable due to charge level increasing, but then
12384                         // later the charge level drops (could be due to thermal issues), we don't
12385                         // want to trigger the deferred runnable, so remove it here
12386                         mHandler.removeCallbacks(mDeferSetCharging);
12387                     }
12388                 } else {
12389                     if (mLastChargeStepLevel > level) {
12390                         // We had reported that the device was charging, but here we are with
12391                         // power connected and the level going down.  Looks like the current
12392                         // power supplied isn't enough, so consider the device to now be
12393                         // discharging.
12394                         changed |= setChargingLocked(false);
12395                     }
12396                 }
12397                 if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
12398                     mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
12399                             modeBits, elapsedRealtime);
12400                     mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
12401                             modeBits, elapsedRealtime);
12402                     mMaxChargeStepLevel = level;
12403                     mInitStepMode = mCurStepMode;
12404                     mModStepMode = 0;
12405                 }
12406                 mLastChargeStepLevel = level;
12407             }
12408             if (changed) {
12409                 addHistoryRecordLocked(elapsedRealtime, uptime);
12410             }
12411         }
12412         if (!onBattery &&
12413                 (status == BatteryManager.BATTERY_STATUS_FULL ||
12414                         status == BatteryManager.BATTERY_STATUS_UNKNOWN)) {
12415             // We don't record history while we are plugged in and fully charged
12416             // (or when battery is not present).  The next time we are
12417             // unplugged, history will be cleared.
12418             mRecordingHistory = DEBUG;
12419         }
12420 
12421         if (mMinLearnedBatteryCapacity == -1) {
12422             mMinLearnedBatteryCapacity = chargeFullUAh;
12423         } else {
12424             mMinLearnedBatteryCapacity = Math.min(mMinLearnedBatteryCapacity, chargeFullUAh);
12425         }
12426         mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh);
12427 
12428         mBatteryTimeToFullSeconds = chargeTimeToFullSeconds;
12429     }
12430 
isOnBattery(int plugType, int status)12431     public static boolean isOnBattery(int plugType, int status) {
12432         return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN;
12433     }
12434 
12435     // Inform StatsLog of setBatteryState changes.
12436     // If this is the first reporting, pass in recentPast == null.
reportChangesToStatsLog(HistoryItem recentPast, final int status, final int plugType, final int level)12437     private void reportChangesToStatsLog(HistoryItem recentPast,
12438             final int status, final int plugType, final int level) {
12439 
12440         if (recentPast == null || recentPast.batteryStatus != status) {
12441             StatsLog.write(StatsLog.CHARGING_STATE_CHANGED, status);
12442         }
12443         if (recentPast == null || recentPast.batteryPlugType != plugType) {
12444             StatsLog.write(StatsLog.PLUGGED_STATE_CHANGED, plugType);
12445         }
12446         if (recentPast == null || recentPast.batteryLevel != level) {
12447             StatsLog.write(StatsLog.BATTERY_LEVEL_CHANGED, level);
12448         }
12449     }
12450 
12451     @UnsupportedAppUsage
getAwakeTimeBattery()12452     public long getAwakeTimeBattery() {
12453         // This previously evaluated to mOnBatteryTimeBase.getUptime(getBatteryUptimeLocked());
12454         // for over a decade, but surely that was a mistake.
12455         return getBatteryUptimeLocked();
12456     }
12457 
12458     @UnsupportedAppUsage
getAwakeTimePlugged()12459     public long getAwakeTimePlugged() {
12460         return (mClocks.uptimeMillis() * 1000) - getAwakeTimeBattery();
12461     }
12462 
12463     @Override
computeUptime(long curTime, int which)12464     public long computeUptime(long curTime, int which) {
12465         return mUptime + (curTime - mUptimeStart);
12466     }
12467 
12468     @Override
computeRealtime(long curTime, int which)12469     public long computeRealtime(long curTime, int which) {
12470         return mRealtime + (curTime - mRealtimeStart);
12471     }
12472 
12473     @Override
12474     @UnsupportedAppUsage
computeBatteryUptime(long curTime, int which)12475     public long computeBatteryUptime(long curTime, int which) {
12476         return mOnBatteryTimeBase.computeUptime(curTime, which);
12477     }
12478 
12479     @Override
12480     @UnsupportedAppUsage
computeBatteryRealtime(long curTime, int which)12481     public long computeBatteryRealtime(long curTime, int which) {
12482         return mOnBatteryTimeBase.computeRealtime(curTime, which);
12483     }
12484 
12485     @Override
computeBatteryScreenOffUptime(long curTime, int which)12486     public long computeBatteryScreenOffUptime(long curTime, int which) {
12487         return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
12488     }
12489 
12490     @Override
computeBatteryScreenOffRealtime(long curTime, int which)12491     public long computeBatteryScreenOffRealtime(long curTime, int which) {
12492         return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
12493     }
12494 
computeTimePerLevel(long[] steps, int numSteps)12495     private long computeTimePerLevel(long[] steps, int numSteps) {
12496         // For now we'll do a simple average across all steps.
12497         if (numSteps <= 0) {
12498             return -1;
12499         }
12500         long total = 0;
12501         for (int i=0; i<numSteps; i++) {
12502             total += steps[i] & STEP_LEVEL_TIME_MASK;
12503         }
12504         return total / numSteps;
12505         /*
12506         long[] buckets = new long[numSteps];
12507         int numBuckets = 0;
12508         int numToAverage = 4;
12509         int i = 0;
12510         while (i < numSteps) {
12511             long totalTime = 0;
12512             int num = 0;
12513             for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
12514                 totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
12515                 num++;
12516             }
12517             buckets[numBuckets] = totalTime / num;
12518             numBuckets++;
12519             numToAverage *= 2;
12520             i += num;
12521         }
12522         if (numBuckets < 1) {
12523             return -1;
12524         }
12525         long averageTime = buckets[numBuckets-1];
12526         for (i=numBuckets-2; i>=0; i--) {
12527             averageTime = (averageTime + buckets[i]) / 2;
12528         }
12529         return averageTime;
12530         */
12531     }
12532 
12533     @Override
12534     @UnsupportedAppUsage
computeBatteryTimeRemaining(long curTime)12535     public long computeBatteryTimeRemaining(long curTime) {
12536         if (!mOnBattery) {
12537             return -1;
12538         }
12539         /* Simple implementation just looks at the average discharge per level across the
12540            entire sample period.
12541         int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
12542         if (discharge < 2) {
12543             return -1;
12544         }
12545         long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
12546         if (duration < 1000*1000) {
12547             return -1;
12548         }
12549         long usPerLevel = duration/discharge;
12550         return usPerLevel * mCurrentBatteryLevel;
12551         */
12552         if (mDischargeStepTracker.mNumStepDurations < 1) {
12553             return -1;
12554         }
12555         long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
12556         if (msPerLevel <= 0) {
12557             return -1;
12558         }
12559         return (msPerLevel * mCurrentBatteryLevel) * 1000;
12560     }
12561 
12562     @Override
getDischargeLevelStepTracker()12563     public LevelStepTracker getDischargeLevelStepTracker() {
12564         return mDischargeStepTracker;
12565     }
12566 
12567     @Override
getDailyDischargeLevelStepTracker()12568     public LevelStepTracker getDailyDischargeLevelStepTracker() {
12569         return mDailyDischargeStepTracker;
12570     }
12571 
12572     @Override
computeChargeTimeRemaining(long curTime)12573     public long computeChargeTimeRemaining(long curTime) {
12574         if (mOnBattery) {
12575             // Not yet working.
12576             return -1;
12577         }
12578         if (mBatteryTimeToFullSeconds >= 0) {
12579             return mBatteryTimeToFullSeconds * (1000 * 1000); // s to us
12580         }
12581         // Else use algorithmic approach
12582         if (mChargeStepTracker.mNumStepDurations < 1) {
12583             return -1;
12584         }
12585         long msPerLevel = mChargeStepTracker.computeTimePerLevel();
12586         if (msPerLevel <= 0) {
12587             return -1;
12588         }
12589         return (msPerLevel * (100 - mCurrentBatteryLevel)) * 1000;
12590     }
12591 
12592     /*@hide */
getCellularBatteryStats()12593     public CellularBatteryStats getCellularBatteryStats() {
12594         CellularBatteryStats s = new CellularBatteryStats();
12595         final int which = STATS_SINCE_CHARGED;
12596         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
12597         final ControllerActivityCounter counter = getModemControllerActivity();
12598         final long sleepTimeMs = counter.getSleepTimeCounter().getCountLocked(which);
12599         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
12600         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
12601         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
12602         final long monitoredRailChargeConsumedMaMs =
12603                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
12604         long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
12605         for (int i = 0; i < timeInRatMs.length; i++) {
12606            timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTime, which) / 1000;
12607         }
12608         long[] timeInRxSignalStrengthLevelMs =
12609                 new long[CellSignalStrength.getNumSignalStrengthLevels()];
12610         for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
12611            timeInRxSignalStrengthLevelMs[i]
12612                = getPhoneSignalStrengthTime(i, rawRealTime, which) / 1000;
12613         }
12614         long[] txTimeMs = new long[Math.min(ModemActivityInfo.TX_POWER_LEVELS,
12615             counter.getTxTimeCounters().length)];
12616         long totalTxTimeMs = 0;
12617         for (int i = 0; i < txTimeMs.length; i++) {
12618             txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
12619             totalTxTimeMs += txTimeMs[i];
12620         }
12621         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
12622         s.setKernelActiveTimeMs(getMobileRadioActiveTime(rawRealTime, which) / 1000);
12623         s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which));
12624         s.setNumBytesTx(getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which));
12625         s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which));
12626         s.setNumBytesRx(getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which));
12627         s.setSleepTimeMs(sleepTimeMs);
12628         s.setIdleTimeMs(idleTimeMs);
12629         s.setRxTimeMs(rxTimeMs);
12630         s.setEnergyConsumedMaMs(energyConsumedMaMs);
12631         s.setTimeInRatMs(timeInRatMs);
12632         s.setTimeInRxSignalStrengthLevelMs(timeInRxSignalStrengthLevelMs);
12633         s.setTxTimeMs(txTimeMs);
12634         s.setMonitoredRailChargeConsumedMaMs(monitoredRailChargeConsumedMaMs);
12635         return s;
12636     }
12637 
12638     /*@hide */
getWifiBatteryStats()12639     public WifiBatteryStats getWifiBatteryStats() {
12640         WifiBatteryStats s = new WifiBatteryStats();
12641         final int which = STATS_SINCE_CHARGED;
12642         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
12643         final ControllerActivityCounter counter = getWifiControllerActivity();
12644         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
12645         final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which);
12646         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
12647         final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which);
12648         final long totalControllerActivityTimeMs
12649                 = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000;
12650         final long sleepTimeMs
12651                 = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs);
12652         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
12653         final long monitoredRailChargeConsumedMaMs =
12654                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
12655         long numAppScanRequest = 0;
12656         for (int i = 0; i < mUidStats.size(); i++) {
12657             numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which);
12658         }
12659         long[] timeInStateMs = new long[NUM_WIFI_STATES];
12660         for (int i=0; i<NUM_WIFI_STATES; i++) {
12661             timeInStateMs[i] = getWifiStateTime(i, rawRealTime, which) / 1000;
12662         }
12663         long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES];
12664         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
12665             timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTime, which) / 1000;
12666         }
12667         long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS];
12668         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
12669             timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTime, which) / 1000;
12670         }
12671         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
12672         s.setKernelActiveTimeMs(getWifiActiveTime(rawRealTime, which) / 1000);
12673         s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which));
12674         s.setNumBytesTx(getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which));
12675         s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which));
12676         s.setNumBytesRx(getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which));
12677         s.setSleepTimeMs(sleepTimeMs);
12678         s.setIdleTimeMs(idleTimeMs);
12679         s.setRxTimeMs(rxTimeMs);
12680         s.setTxTimeMs(txTimeMs);
12681         s.setScanTimeMs(scanTimeMs);
12682         s.setEnergyConsumedMaMs(energyConsumedMaMs);
12683         s.setNumAppScanRequest(numAppScanRequest);
12684         s.setTimeInStateMs(timeInStateMs);
12685         s.setTimeInSupplicantStateMs(timeInSupplStateMs);
12686         s.setTimeInRxSignalStrengthLevelMs(timeSignalStrengthTimeMs);
12687         s.setMonitoredRailChargeConsumedMaMs(monitoredRailChargeConsumedMaMs);
12688         return s;
12689     }
12690 
12691     /*@hide */
getGpsBatteryStats()12692     public GpsBatteryStats getGpsBatteryStats() {
12693         GpsBatteryStats s = new GpsBatteryStats();
12694         final int which = STATS_SINCE_CHARGED;
12695         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
12696         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
12697         s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
12698         long[] time = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
12699         for (int i=0; i<time.length; i++) {
12700             time[i] = getGpsSignalQualityTime(i, rawRealTime, which) / 1000;
12701         }
12702         s.setTimeInGpsSignalQualityLevel(time);
12703         return s;
12704     }
12705 
12706     @Override
getChargeLevelStepTracker()12707     public LevelStepTracker getChargeLevelStepTracker() {
12708         return mChargeStepTracker;
12709     }
12710 
12711     @Override
getDailyChargeLevelStepTracker()12712     public LevelStepTracker getDailyChargeLevelStepTracker() {
12713         return mDailyChargeStepTracker;
12714     }
12715 
12716     @Override
getDailyPackageChanges()12717     public ArrayList<PackageChange> getDailyPackageChanges() {
12718         return mDailyPackageChanges;
12719     }
12720 
getBatteryUptimeLocked()12721     protected long getBatteryUptimeLocked() {
12722         return mOnBatteryTimeBase.getUptime(mClocks.uptimeMillis() * 1000);
12723     }
12724 
12725     @Override
getBatteryUptime(long curTime)12726     public long getBatteryUptime(long curTime) {
12727         return mOnBatteryTimeBase.getUptime(curTime);
12728     }
12729 
12730     @Override
12731     @UnsupportedAppUsage
getBatteryRealtime(long curTime)12732     public long getBatteryRealtime(long curTime) {
12733         return mOnBatteryTimeBase.getRealtime(curTime);
12734     }
12735 
12736     @Override
12737     @UnsupportedAppUsage
getDischargeStartLevel()12738     public int getDischargeStartLevel() {
12739         synchronized(this) {
12740             return getDischargeStartLevelLocked();
12741         }
12742     }
12743 
getDischargeStartLevelLocked()12744     public int getDischargeStartLevelLocked() {
12745             return mDischargeUnplugLevel;
12746     }
12747 
12748     @Override
12749     @UnsupportedAppUsage
getDischargeCurrentLevel()12750     public int getDischargeCurrentLevel() {
12751         synchronized(this) {
12752             return getDischargeCurrentLevelLocked();
12753         }
12754     }
12755 
getDischargeCurrentLevelLocked()12756     public int getDischargeCurrentLevelLocked() {
12757         return mDischargeCurrentLevel;
12758     }
12759 
12760     @Override
getLowDischargeAmountSinceCharge()12761     public int getLowDischargeAmountSinceCharge() {
12762         synchronized(this) {
12763             int val = mLowDischargeAmountSinceCharge;
12764             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
12765                 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
12766             }
12767             return val;
12768         }
12769     }
12770 
12771     @Override
getHighDischargeAmountSinceCharge()12772     public int getHighDischargeAmountSinceCharge() {
12773         synchronized(this) {
12774             int val = mHighDischargeAmountSinceCharge;
12775             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
12776                 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
12777             }
12778             return val;
12779         }
12780     }
12781 
12782     @Override
12783     @UnsupportedAppUsage
getDischargeAmount(int which)12784     public int getDischargeAmount(int which) {
12785         int dischargeAmount = which == STATS_SINCE_CHARGED
12786                 ? getHighDischargeAmountSinceCharge()
12787                 : (getDischargeStartLevel() - getDischargeCurrentLevel());
12788         if (dischargeAmount < 0) {
12789             dischargeAmount = 0;
12790         }
12791         return dischargeAmount;
12792     }
12793 
12794     @Override
12795     @UnsupportedAppUsage
getDischargeAmountScreenOn()12796     public int getDischargeAmountScreenOn() {
12797         synchronized(this) {
12798             int val = mDischargeAmountScreenOn;
12799             if (mOnBattery && isScreenOn(mScreenState)
12800                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
12801                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
12802             }
12803             return val;
12804         }
12805     }
12806 
12807     @Override
getDischargeAmountScreenOnSinceCharge()12808     public int getDischargeAmountScreenOnSinceCharge() {
12809         synchronized(this) {
12810             int val = mDischargeAmountScreenOnSinceCharge;
12811             if (mOnBattery && isScreenOn(mScreenState)
12812                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
12813                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
12814             }
12815             return val;
12816         }
12817     }
12818 
12819     @Override
12820     @UnsupportedAppUsage
getDischargeAmountScreenOff()12821     public int getDischargeAmountScreenOff() {
12822         synchronized(this) {
12823             int val = mDischargeAmountScreenOff;
12824             if (mOnBattery && isScreenOff(mScreenState)
12825                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
12826                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
12827             }
12828             // For backward compatibility, doze discharge is counted into screen off.
12829             return val + getDischargeAmountScreenDoze();
12830         }
12831     }
12832 
12833     @Override
getDischargeAmountScreenOffSinceCharge()12834     public int getDischargeAmountScreenOffSinceCharge() {
12835         synchronized(this) {
12836             int val = mDischargeAmountScreenOffSinceCharge;
12837             if (mOnBattery && isScreenOff(mScreenState)
12838                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
12839                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
12840             }
12841             // For backward compatibility, doze discharge is counted into screen off.
12842             return val + getDischargeAmountScreenDozeSinceCharge();
12843         }
12844     }
12845 
12846     @Override
getDischargeAmountScreenDoze()12847     public int getDischargeAmountScreenDoze() {
12848         synchronized(this) {
12849             int val = mDischargeAmountScreenDoze;
12850             if (mOnBattery && isScreenDoze(mScreenState)
12851                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
12852                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
12853             }
12854             return val;
12855         }
12856     }
12857 
12858     @Override
getDischargeAmountScreenDozeSinceCharge()12859     public int getDischargeAmountScreenDozeSinceCharge() {
12860         synchronized(this) {
12861             int val = mDischargeAmountScreenDozeSinceCharge;
12862             if (mOnBattery && isScreenDoze(mScreenState)
12863                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
12864                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
12865             }
12866             return val;
12867         }
12868     }
12869 
12870     /**
12871      * Retrieve the statistics object for a particular uid, creating if needed.
12872      */
12873     @UnsupportedAppUsage
getUidStatsLocked(int uid)12874     public Uid getUidStatsLocked(int uid) {
12875         Uid u = mUidStats.get(uid);
12876         if (u == null) {
12877             u = new Uid(this, uid);
12878             mUidStats.put(uid, u);
12879         }
12880         return u;
12881     }
12882 
12883     /**
12884      * Retrieve the statistics object for a particular uid. Returns null if the object is not
12885      * available.
12886      */
getAvailableUidStatsLocked(int uid)12887     public Uid getAvailableUidStatsLocked(int uid) {
12888         Uid u = mUidStats.get(uid);
12889         return u;
12890     }
12891 
onCleanupUserLocked(int userId)12892     public void onCleanupUserLocked(int userId) {
12893         final int firstUidForUser = UserHandle.getUid(userId, 0);
12894         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
12895         mPendingRemovedUids.add(
12896                 new UidToRemove(firstUidForUser, lastUidForUser, mClocks.elapsedRealtime()));
12897     }
12898 
onUserRemovedLocked(int userId)12899     public void onUserRemovedLocked(int userId) {
12900         final int firstUidForUser = UserHandle.getUid(userId, 0);
12901         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
12902         mUidStats.put(firstUidForUser, null);
12903         mUidStats.put(lastUidForUser, null);
12904         final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
12905         final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
12906         for (int i = firstIndex; i <= lastIndex; i++) {
12907             final Uid uid = mUidStats.valueAt(i);
12908             if (uid != null) {
12909                 uid.detachFromTimeBase();
12910             }
12911         }
12912         mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
12913     }
12914 
12915     /**
12916      * Remove the statistics object for a particular uid.
12917      */
12918     @UnsupportedAppUsage
removeUidStatsLocked(int uid)12919     public void removeUidStatsLocked(int uid) {
12920         final Uid u = mUidStats.get(uid);
12921         if (u != null) {
12922             u.detachFromTimeBase();
12923         }
12924         mUidStats.remove(uid);
12925         mPendingRemovedUids.add(new UidToRemove(uid, mClocks.elapsedRealtime()));
12926     }
12927 
12928     /**
12929      * Retrieve the statistics object for a particular process, creating
12930      * if needed.
12931      */
12932     @UnsupportedAppUsage
getProcessStatsLocked(int uid, String name)12933     public Uid.Proc getProcessStatsLocked(int uid, String name) {
12934         uid = mapUid(uid);
12935         Uid u = getUidStatsLocked(uid);
12936         return u.getProcessStatsLocked(name);
12937     }
12938 
12939     /**
12940      * Retrieve the statistics object for a particular process, creating
12941      * if needed.
12942      */
12943     @UnsupportedAppUsage
getPackageStatsLocked(int uid, String pkg)12944     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
12945         uid = mapUid(uid);
12946         Uid u = getUidStatsLocked(uid);
12947         return u.getPackageStatsLocked(pkg);
12948     }
12949 
12950     /**
12951      * Retrieve the statistics object for a particular service, creating
12952      * if needed.
12953      */
12954     @UnsupportedAppUsage
getServiceStatsLocked(int uid, String pkg, String name)12955     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
12956         uid = mapUid(uid);
12957         Uid u = getUidStatsLocked(uid);
12958         return u.getServiceStatsLocked(pkg, name);
12959     }
12960 
shutdownLocked()12961     public void shutdownLocked() {
12962         recordShutdownLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
12963         writeSyncLocked();
12964         mShuttingDown = true;
12965     }
12966 
trackPerProcStateCpuTimes()12967     public boolean trackPerProcStateCpuTimes() {
12968         return mConstants.TRACK_CPU_TIMES_BY_PROC_STATE && mPerProcStateCpuTimesAvailable;
12969     }
12970 
systemServicesReady(Context context)12971     public void systemServicesReady(Context context) {
12972         mConstants.startObserving(context.getContentResolver());
12973         registerUsbStateReceiver(context);
12974     }
12975 
12976     @VisibleForTesting
12977     public final class Constants extends ContentObserver {
12978         public static final String KEY_TRACK_CPU_TIMES_BY_PROC_STATE
12979                 = "track_cpu_times_by_proc_state";
12980         public static final String KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME
12981                 = "track_cpu_active_cluster_time";
12982         public static final String KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS
12983                 = "proc_state_cpu_times_read_delay_ms";
12984         public static final String KEY_KERNEL_UID_READERS_THROTTLE_TIME
12985                 = "kernel_uid_readers_throttle_time";
12986         public static final String KEY_UID_REMOVE_DELAY_MS
12987                 = "uid_remove_delay_ms";
12988         public static final String KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
12989                 = "external_stats_collection_rate_limit_ms";
12990         public static final String KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS
12991                 = "battery_level_collection_delay_ms";
12992         public static final String KEY_MAX_HISTORY_FILES = "max_history_files";
12993         public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
12994         public static final String KEY_BATTERY_CHARGED_DELAY_MS =
12995                 "battery_charged_delay_ms";
12996 
12997         private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = false;
12998         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
12999         private static final long DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS = 5_000;
13000         private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000;
13001         private static final long DEFAULT_UID_REMOVE_DELAY_MS = 5L * 60L * 1000L;
13002         private static final long DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = 600_000;
13003         private static final long DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS = 300_000;
13004         private static final int DEFAULT_MAX_HISTORY_FILES = 32;
13005         private static final int DEFAULT_MAX_HISTORY_BUFFER_KB = 128; /*Kilo Bytes*/
13006         private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64;
13007         private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
13008         private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
13009 
13010         public boolean TRACK_CPU_TIMES_BY_PROC_STATE = DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE;
13011         public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
13012         public long PROC_STATE_CPU_TIMES_READ_DELAY_MS = DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS;
13013         /* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
13014          * update when startObserving. */
13015         public long KERNEL_UID_READERS_THROTTLE_TIME;
13016         public long UID_REMOVE_DELAY_MS = DEFAULT_UID_REMOVE_DELAY_MS;
13017         public long EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
13018                 = DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
13019         public long BATTERY_LEVEL_COLLECTION_DELAY_MS
13020                 = DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS;
13021         public int MAX_HISTORY_FILES;
13022         public int MAX_HISTORY_BUFFER; /*Bytes*/
13023         public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
13024 
13025         private ContentResolver mResolver;
13026         private final KeyValueListParser mParser = new KeyValueListParser(',');
13027 
Constants(Handler handler)13028         public Constants(Handler handler) {
13029             super(handler);
13030             if (ActivityManager.isLowRamDeviceStatic()) {
13031                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE;
13032                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB * 1024;
13033             } else {
13034                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES;
13035                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_KB * 1024;
13036             }
13037         }
13038 
startObserving(ContentResolver resolver)13039         public void startObserving(ContentResolver resolver) {
13040             mResolver = resolver;
13041             mResolver.registerContentObserver(
13042                     Settings.Global.getUriFor(Settings.Global.BATTERY_STATS_CONSTANTS),
13043                     false /* notifyForDescendants */, this);
13044             mResolver.registerContentObserver(
13045                     Settings.Global.getUriFor(Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY),
13046                     false /* notifyForDescendants */, this);
13047             updateConstants();
13048         }
13049 
13050         @Override
onChange(boolean selfChange, Uri uri)13051         public void onChange(boolean selfChange, Uri uri) {
13052             if (uri.equals(
13053                     Settings.Global.getUriFor(
13054                             Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY))) {
13055                 synchronized (BatteryStatsImpl.this) {
13056                     updateBatteryChargedDelayMsLocked();
13057                 }
13058                 return;
13059             }
13060             updateConstants();
13061         }
13062 
updateConstants()13063         private void updateConstants() {
13064             synchronized (BatteryStatsImpl.this) {
13065                 try {
13066                     mParser.setString(Settings.Global.getString(mResolver,
13067                             Settings.Global.BATTERY_STATS_CONSTANTS));
13068                 } catch (IllegalArgumentException e) {
13069                     // Failed to parse the settings string, log this and move on
13070                     // with defaults.
13071                     Slog.e(TAG, "Bad batterystats settings", e);
13072                 }
13073 
13074                 updateTrackCpuTimesByProcStateLocked(TRACK_CPU_TIMES_BY_PROC_STATE,
13075                         mParser.getBoolean(KEY_TRACK_CPU_TIMES_BY_PROC_STATE,
13076                                 DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE));
13077                 TRACK_CPU_ACTIVE_CLUSTER_TIME = mParser.getBoolean(
13078                         KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME, DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME);
13079                 updateProcStateCpuTimesReadDelayMs(PROC_STATE_CPU_TIMES_READ_DELAY_MS,
13080                         mParser.getLong(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS,
13081                                 DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS));
13082                 updateKernelUidReadersThrottleTime(KERNEL_UID_READERS_THROTTLE_TIME,
13083                         mParser.getLong(KEY_KERNEL_UID_READERS_THROTTLE_TIME,
13084                                 DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME));
13085                 updateUidRemoveDelay(
13086                         mParser.getLong(KEY_UID_REMOVE_DELAY_MS, DEFAULT_UID_REMOVE_DELAY_MS));
13087                 EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = mParser.getLong(
13088                         KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS,
13089                         DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
13090                 BATTERY_LEVEL_COLLECTION_DELAY_MS = mParser.getLong(
13091                         KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS,
13092                         DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS);
13093 
13094                 MAX_HISTORY_FILES = mParser.getInt(KEY_MAX_HISTORY_FILES,
13095                         ActivityManager.isLowRamDeviceStatic() ?
13096                                 DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE
13097                         : DEFAULT_MAX_HISTORY_FILES);
13098                 MAX_HISTORY_BUFFER = mParser.getInt(KEY_MAX_HISTORY_BUFFER_KB,
13099                         ActivityManager.isLowRamDeviceStatic() ?
13100                                 DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB
13101                                 : DEFAULT_MAX_HISTORY_BUFFER_KB)
13102                         * 1024;
13103                 updateBatteryChargedDelayMsLocked();
13104             }
13105         }
13106 
updateBatteryChargedDelayMsLocked()13107         private void updateBatteryChargedDelayMsLocked() {
13108             // a negative value indicates that we should ignore this override
13109             final int delay = Settings.Global.getInt(mResolver,
13110                     Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
13111                     -1);
13112 
13113             BATTERY_CHARGED_DELAY_MS = delay >= 0 ? delay : mParser.getInt(
13114                     KEY_BATTERY_CHARGED_DELAY_MS,
13115                     DEFAULT_BATTERY_CHARGED_DELAY_MS);
13116         }
13117 
updateTrackCpuTimesByProcStateLocked(boolean wasEnabled, boolean isEnabled)13118         private void updateTrackCpuTimesByProcStateLocked(boolean wasEnabled, boolean isEnabled) {
13119             TRACK_CPU_TIMES_BY_PROC_STATE = isEnabled;
13120             if (isEnabled && !wasEnabled) {
13121                 mIsPerProcessStateCpuDataStale = true;
13122                 mExternalSync.scheduleCpuSyncDueToSettingChange();
13123 
13124                 mNumSingleUidCpuTimeReads = 0;
13125                 mNumBatchedSingleUidCpuTimeReads = 0;
13126                 mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
13127             }
13128         }
13129 
updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis)13130         private void updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis) {
13131             PROC_STATE_CPU_TIMES_READ_DELAY_MS = newDelayMillis;
13132             if (oldDelayMillis != newDelayMillis) {
13133                 mNumSingleUidCpuTimeReads = 0;
13134                 mNumBatchedSingleUidCpuTimeReads = 0;
13135                 mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
13136             }
13137         }
13138 
updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs)13139         private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
13140             KERNEL_UID_READERS_THROTTLE_TIME = newTimeMs;
13141             if (oldTimeMs != newTimeMs) {
13142                 mCpuUidUserSysTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
13143                 mCpuUidFreqTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
13144                 mCpuUidActiveTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
13145                 mCpuUidClusterTimeReader
13146                         .setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
13147             }
13148         }
13149 
updateUidRemoveDelay(long newTimeMs)13150         private void updateUidRemoveDelay(long newTimeMs) {
13151             UID_REMOVE_DELAY_MS = newTimeMs;
13152             clearPendingRemovedUids();
13153         }
13154 
dumpLocked(PrintWriter pw)13155         public void dumpLocked(PrintWriter pw) {
13156             pw.print(KEY_TRACK_CPU_TIMES_BY_PROC_STATE); pw.print("=");
13157             pw.println(TRACK_CPU_TIMES_BY_PROC_STATE);
13158             pw.print(KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME); pw.print("=");
13159             pw.println(TRACK_CPU_ACTIVE_CLUSTER_TIME);
13160             pw.print(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS); pw.print("=");
13161             pw.println(PROC_STATE_CPU_TIMES_READ_DELAY_MS);
13162             pw.print(KEY_KERNEL_UID_READERS_THROTTLE_TIME); pw.print("=");
13163             pw.println(KERNEL_UID_READERS_THROTTLE_TIME);
13164             pw.print(KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS); pw.print("=");
13165             pw.println(EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
13166             pw.print(KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS); pw.print("=");
13167             pw.println(BATTERY_LEVEL_COLLECTION_DELAY_MS);
13168             pw.print(KEY_MAX_HISTORY_FILES); pw.print("=");
13169             pw.println(MAX_HISTORY_FILES);
13170             pw.print(KEY_MAX_HISTORY_BUFFER_KB); pw.print("=");
13171             pw.println(MAX_HISTORY_BUFFER/1024);
13172             pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("=");
13173             pw.println(BATTERY_CHARGED_DELAY_MS);
13174         }
13175     }
13176 
getExternalStatsCollectionRateLimitMs()13177     public long getExternalStatsCollectionRateLimitMs() {
13178         synchronized (this) {
13179             return mConstants.EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
13180         }
13181     }
13182 
13183     @GuardedBy("this")
dumpConstantsLocked(PrintWriter pw)13184     public void dumpConstantsLocked(PrintWriter pw) {
13185         mConstants.dumpLocked(pw);
13186     }
13187 
13188     @GuardedBy("this")
dumpCpuStatsLocked(PrintWriter pw)13189     public void dumpCpuStatsLocked(PrintWriter pw) {
13190         int size = mUidStats.size();
13191         pw.println("Per UID CPU user & system time in ms:");
13192         for (int i = 0; i < size; i++) {
13193             int u = mUidStats.keyAt(i);
13194             Uid uid = mUidStats.get(u);
13195             pw.print("  "); pw.print(u); pw.print(": ");
13196             pw.print(uid.getUserCpuTimeUs(STATS_SINCE_CHARGED) / 1000); pw.print(" ");
13197             pw.println(uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED) / 1000);
13198         }
13199         pw.println("Per UID CPU active time in ms:");
13200         for (int i = 0; i < size; i++) {
13201             int u = mUidStats.keyAt(i);
13202             Uid uid = mUidStats.get(u);
13203             if (uid.getCpuActiveTime() > 0) {
13204                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(uid.getCpuActiveTime());
13205             }
13206         }
13207         pw.println("Per UID CPU cluster time in ms:");
13208         for (int i = 0; i < size; i++) {
13209             int u = mUidStats.keyAt(i);
13210             long[] times = mUidStats.get(u).getCpuClusterTimes();
13211             if (times != null) {
13212                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
13213             }
13214         }
13215         pw.println("Per UID CPU frequency time in ms:");
13216         for (int i = 0; i < size; i++) {
13217             int u = mUidStats.keyAt(i);
13218             long[] times = mUidStats.get(u).getCpuFreqTimes(STATS_SINCE_CHARGED);
13219             if (times != null) {
13220                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
13221             }
13222         }
13223     }
13224 
13225     final ReentrantLock mWriteLock = new ReentrantLock();
13226 
writeAsyncLocked()13227     public void writeAsyncLocked() {
13228         writeStatsLocked(false);
13229         writeHistoryLocked(false);
13230     }
13231 
writeSyncLocked()13232     public void writeSyncLocked() {
13233         writeStatsLocked(true);
13234         writeHistoryLocked(true);
13235     }
13236 
writeStatsLocked(boolean sync)13237     void writeStatsLocked(boolean sync) {
13238         if (mStatsFile == null) {
13239             Slog.w(TAG,
13240                     "writeStatsLocked: no file associated with this instance");
13241             return;
13242         }
13243 
13244         if (mShuttingDown) {
13245             return;
13246         }
13247 
13248         final Parcel p = Parcel.obtain();
13249         final long start = SystemClock.uptimeMillis();
13250         writeSummaryToParcel(p, false/*history is in separate file*/);
13251         if (DEBUG) {
13252             Slog.d(TAG, "writeSummaryToParcel duration ms:"
13253                     + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
13254         }
13255         mLastWriteTime = mClocks.elapsedRealtime();
13256         writeParcelToFileLocked(p, mStatsFile, sync);
13257     }
13258 
writeHistoryLocked(boolean sync)13259     void writeHistoryLocked(boolean sync) {
13260         if (mBatteryStatsHistory.getActiveFile() == null) {
13261             Slog.w(TAG,
13262                     "writeHistoryLocked: no history file associated with this instance");
13263             return;
13264         }
13265 
13266         if (mShuttingDown) {
13267             return;
13268         }
13269 
13270         Parcel p = Parcel.obtain();
13271         final long start = SystemClock.uptimeMillis();
13272         writeHistoryBuffer(p, true, true);
13273         if (DEBUG) {
13274             Slog.d(TAG, "writeHistoryBuffer duration ms:"
13275                     + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
13276         }
13277         writeParcelToFileLocked(p, mBatteryStatsHistory.getActiveFile(), sync);
13278     }
13279 
writeParcelToFileLocked(Parcel p, AtomicFile file, boolean sync)13280     void writeParcelToFileLocked(Parcel p, AtomicFile file, boolean sync) {
13281         if (sync) {
13282             commitPendingDataToDisk(p, file);
13283         } else {
13284             BackgroundThread.getHandler().post(new Runnable() {
13285                 @Override public void run() {
13286                     commitPendingDataToDisk(p, file);
13287                 }
13288             });
13289         }
13290     }
13291 
commitPendingDataToDisk(Parcel p, AtomicFile file)13292     private void commitPendingDataToDisk(Parcel p, AtomicFile file) {
13293         mWriteLock.lock();
13294         FileOutputStream fos = null;
13295         try {
13296             final long startTime = SystemClock.uptimeMillis();
13297             fos = file.startWrite();
13298             fos.write(p.marshall());
13299             fos.flush();
13300             file.finishWrite(fos);
13301             if (DEBUG) {
13302                 Slog.d(TAG, "commitPendingDataToDisk file:" + file.getBaseFile().getPath()
13303                         + " duration ms:" + (SystemClock.uptimeMillis() - startTime)
13304                         + " bytes:" + p.dataSize());
13305             }
13306             com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
13307                     "batterystats", SystemClock.uptimeMillis() - startTime);
13308         } catch (IOException e) {
13309             Slog.w(TAG, "Error writing battery statistics", e);
13310             file.failWrite(fos);
13311         } finally {
13312             p.recycle();
13313             mWriteLock.unlock();
13314         }
13315     }
13316 
13317     @UnsupportedAppUsage
readLocked()13318     public void readLocked() {
13319         if (mDailyFile != null) {
13320             readDailyStatsLocked();
13321         }
13322 
13323         if (mStatsFile == null) {
13324             Slog.w(TAG, "readLocked: no file associated with this instance");
13325             return;
13326         }
13327 
13328         if (mBatteryStatsHistory.getActiveFile() == null) {
13329             Slog.w(TAG,
13330                     "readLocked: no history file associated with this instance");
13331             return;
13332         }
13333 
13334         mUidStats.clear();
13335 
13336         Parcel stats = Parcel.obtain();
13337         try {
13338             final long start = SystemClock.uptimeMillis();
13339             byte[] raw = mStatsFile.readFully();
13340             stats.unmarshall(raw, 0, raw.length);
13341             stats.setDataPosition(0);
13342             readSummaryFromParcel(stats);
13343             if (DEBUG) {
13344                 Slog.d(TAG, "readLocked stats file:" + mStatsFile.getBaseFile().getPath()
13345                         + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
13346                         - start));
13347             }
13348         } catch (Exception e) {
13349             Slog.e(TAG, "Error reading battery statistics", e);
13350             resetAllStatsLocked();
13351         } finally {
13352             stats.recycle();
13353         }
13354 
13355         Parcel history = Parcel.obtain();
13356         try {
13357             final long start = SystemClock.uptimeMillis();
13358             byte[] raw = mBatteryStatsHistory.getActiveFile().readFully();
13359             if (raw.length > 0) {
13360                 history.unmarshall(raw, 0, raw.length);
13361                 history.setDataPosition(0);
13362                 readHistoryBuffer(history, true);
13363             }
13364             if (DEBUG) {
13365                 Slog.d(TAG, "readLocked history file::"
13366                         + mBatteryStatsHistory.getActiveFile().getBaseFile().getPath()
13367                         + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
13368                         - start));
13369             }
13370         } catch (Exception e) {
13371             Slog.e(TAG, "Error reading battery history", e);
13372             clearHistoryLocked();
13373             mBatteryStatsHistory.resetAllFiles();
13374         } finally {
13375             history.recycle();
13376         }
13377 
13378         mEndPlatformVersion = Build.ID;
13379 
13380         if (mHistoryBuffer.dataPosition() > 0
13381                 || mBatteryStatsHistory.getFilesNumbers().size() > 1) {
13382             mRecordingHistory = true;
13383             final long elapsedRealtime = mClocks.elapsedRealtime();
13384             final long uptime = mClocks.uptimeMillis();
13385             if (USE_OLD_HISTORY) {
13386                 addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
13387             }
13388             addHistoryBufferLocked(elapsedRealtime, HistoryItem.CMD_START, mHistoryCur);
13389             startRecordingHistory(elapsedRealtime, uptime, false);
13390         }
13391 
13392         recordDailyStatsIfNeededLocked(false);
13393     }
13394 
describeContents()13395     public int describeContents() {
13396         return 0;
13397     }
13398 
readHistoryBuffer(Parcel in, boolean andOldHistory)13399     void  readHistoryBuffer(Parcel in, boolean andOldHistory) throws ParcelFormatException {
13400         final int version = in.readInt();
13401         if (version != VERSION) {
13402             Slog.w("BatteryStats", "readHistoryBuffer: version got " + version
13403                     + ", expected " + VERSION + "; erasing old stats");
13404             return;
13405         }
13406 
13407         final long historyBaseTime = in.readLong();
13408 
13409         mHistoryBuffer.setDataSize(0);
13410         mHistoryBuffer.setDataPosition(0);
13411 
13412         int bufSize = in.readInt();
13413         int curPos = in.dataPosition();
13414         if (bufSize >= (mConstants.MAX_HISTORY_BUFFER*100)) {
13415             throw new ParcelFormatException("File corrupt: history data buffer too large " +
13416                     bufSize);
13417         } else if ((bufSize&~3) != bufSize) {
13418             throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
13419                     bufSize);
13420         } else {
13421             if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
13422                     + " bytes at " + curPos);
13423             mHistoryBuffer.appendFrom(in, curPos, bufSize);
13424             in.setDataPosition(curPos + bufSize);
13425         }
13426 
13427         if (andOldHistory) {
13428             readOldHistory(in);
13429         }
13430 
13431         if (DEBUG_HISTORY) {
13432             StringBuilder sb = new StringBuilder(128);
13433             sb.append("****************** OLD mHistoryBaseTime: ");
13434             TimeUtils.formatDuration(mHistoryBaseTime, sb);
13435             Slog.i(TAG, sb.toString());
13436         }
13437         mHistoryBaseTime = historyBaseTime;
13438         if (DEBUG_HISTORY) {
13439             StringBuilder sb = new StringBuilder(128);
13440             sb.append("****************** NEW mHistoryBaseTime: ");
13441             TimeUtils.formatDuration(mHistoryBaseTime, sb);
13442             Slog.i(TAG, sb.toString());
13443         }
13444 
13445         // We are just arbitrarily going to insert 1 minute from the sample of
13446         // the last run until samples in this run.
13447         if (mHistoryBaseTime > 0) {
13448             long oldnow = mClocks.elapsedRealtime();
13449             mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
13450             if (DEBUG_HISTORY) {
13451                 StringBuilder sb = new StringBuilder(128);
13452                 sb.append("****************** ADJUSTED mHistoryBaseTime: ");
13453                 TimeUtils.formatDuration(mHistoryBaseTime, sb);
13454                 Slog.i(TAG, sb.toString());
13455             }
13456         }
13457     }
13458 
readOldHistory(Parcel in)13459     void readOldHistory(Parcel in) {
13460         if (!USE_OLD_HISTORY) {
13461             return;
13462         }
13463         mHistory = mHistoryEnd = mHistoryCache = null;
13464         long time;
13465         while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
13466             HistoryItem rec = new HistoryItem(time, in);
13467             addHistoryRecordLocked(rec);
13468         }
13469     }
13470 
writeHistoryBuffer(Parcel out, boolean inclData, boolean andOldHistory)13471     void writeHistoryBuffer(Parcel out, boolean inclData, boolean andOldHistory) {
13472         if (DEBUG_HISTORY) {
13473             StringBuilder sb = new StringBuilder(128);
13474             sb.append("****************** WRITING mHistoryBaseTime: ");
13475             TimeUtils.formatDuration(mHistoryBaseTime, sb);
13476             sb.append(" mLastHistoryElapsedRealtime: ");
13477             TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
13478             Slog.i(TAG, sb.toString());
13479         }
13480         out.writeInt(VERSION);
13481         out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
13482         if (!inclData) {
13483             out.writeInt(0);
13484             out.writeInt(0);
13485             return;
13486         }
13487 
13488         out.writeInt(mHistoryBuffer.dataSize());
13489         if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
13490                 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
13491         out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
13492 
13493         if (andOldHistory) {
13494             writeOldHistory(out);
13495         }
13496     }
13497 
writeOldHistory(Parcel out)13498     void writeOldHistory(Parcel out) {
13499         if (!USE_OLD_HISTORY) {
13500             return;
13501         }
13502         HistoryItem rec = mHistory;
13503         while (rec != null) {
13504             if (rec.time >= 0) rec.writeToParcel(out, 0);
13505             rec = rec.next;
13506         }
13507         out.writeLong(-1);
13508     }
13509 
readSummaryFromParcel(Parcel in)13510     public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
13511         final int version = in.readInt();
13512         if (version != VERSION) {
13513             Slog.w("BatteryStats", "readFromParcel: version got " + version
13514                 + ", expected " + VERSION + "; erasing old stats");
13515             return;
13516         }
13517 
13518         boolean inclHistory = in.readBoolean();
13519         if (inclHistory) {
13520             readHistoryBuffer(in, true);
13521             mBatteryStatsHistory.readFromParcel(in);
13522         }
13523 
13524         mHistoryTagPool.clear();
13525         mNextHistoryTagIdx = 0;
13526         mNumHistoryTagChars = 0;
13527 
13528         int numTags = in.readInt();
13529         for (int i=0; i<numTags; i++) {
13530             int idx = in.readInt();
13531             String str = in.readString();
13532             if (str == null) {
13533                 throw new ParcelFormatException("null history tag string");
13534             }
13535             int uid = in.readInt();
13536             HistoryTag tag = new HistoryTag();
13537             tag.string = str;
13538             tag.uid = uid;
13539             tag.poolIdx = idx;
13540             mHistoryTagPool.put(tag, idx);
13541             if (idx >= mNextHistoryTagIdx) {
13542                 mNextHistoryTagIdx = idx+1;
13543             }
13544             mNumHistoryTagChars += tag.string.length() + 1;
13545         }
13546 
13547         mStartCount = in.readInt();
13548         mUptime = in.readLong();
13549         mRealtime = in.readLong();
13550         mStartClockTime = in.readLong();
13551         mStartPlatformVersion = in.readString();
13552         mEndPlatformVersion = in.readString();
13553         mOnBatteryTimeBase.readSummaryFromParcel(in);
13554         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
13555         mDischargeUnplugLevel = in.readInt();
13556         mDischargePlugLevel = in.readInt();
13557         mDischargeCurrentLevel = in.readInt();
13558         mCurrentBatteryLevel = in.readInt();
13559         mEstimatedBatteryCapacity = in.readInt();
13560         mMinLearnedBatteryCapacity = in.readInt();
13561         mMaxLearnedBatteryCapacity = in.readInt();
13562         mLowDischargeAmountSinceCharge = in.readInt();
13563         mHighDischargeAmountSinceCharge = in.readInt();
13564         mDischargeAmountScreenOnSinceCharge = in.readInt();
13565         mDischargeAmountScreenOffSinceCharge = in.readInt();
13566         mDischargeAmountScreenDozeSinceCharge = in.readInt();
13567         mDischargeStepTracker.readFromParcel(in);
13568         mChargeStepTracker.readFromParcel(in);
13569         mDailyDischargeStepTracker.readFromParcel(in);
13570         mDailyChargeStepTracker.readFromParcel(in);
13571         mDischargeCounter.readSummaryFromParcelLocked(in);
13572         mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
13573         mDischargeScreenDozeCounter.readSummaryFromParcelLocked(in);
13574         mDischargeLightDozeCounter.readSummaryFromParcelLocked(in);
13575         mDischargeDeepDozeCounter.readSummaryFromParcelLocked(in);
13576         int NPKG = in.readInt();
13577         if (NPKG > 0) {
13578             mDailyPackageChanges = new ArrayList<>(NPKG);
13579             while (NPKG > 0) {
13580                 NPKG--;
13581                 PackageChange pc = new PackageChange();
13582                 pc.mPackageName = in.readString();
13583                 pc.mUpdate = in.readInt() != 0;
13584                 pc.mVersionCode = in.readLong();
13585                 mDailyPackageChanges.add(pc);
13586             }
13587         } else {
13588             mDailyPackageChanges = null;
13589         }
13590         mDailyStartTime = in.readLong();
13591         mNextMinDailyDeadline = in.readLong();
13592         mNextMaxDailyDeadline = in.readLong();
13593 
13594         mStartCount++;
13595 
13596         mScreenState = Display.STATE_UNKNOWN;
13597         mScreenOnTimer.readSummaryFromParcelLocked(in);
13598         mScreenDozeTimer.readSummaryFromParcelLocked(in);
13599         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
13600             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
13601         }
13602         mInteractive = false;
13603         mInteractiveTimer.readSummaryFromParcelLocked(in);
13604         mPhoneOn = false;
13605         mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
13606         mLongestLightIdleTime = in.readLong();
13607         mLongestFullIdleTime = in.readLong();
13608         mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
13609         mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
13610         mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
13611         mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
13612         mPhoneOnTimer.readSummaryFromParcelLocked(in);
13613         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
13614             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
13615         }
13616         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
13617         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
13618             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
13619         }
13620         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
13621             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
13622             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
13623         }
13624         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
13625         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
13626         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
13627         mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
13628         mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
13629         mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
13630         mWifiMulticastWakelockTimer.readSummaryFromParcelLocked(in);
13631         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
13632         mWifiOn = false;
13633         mWifiOnTimer.readSummaryFromParcelLocked(in);
13634         mGlobalWifiRunning = false;
13635         mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
13636         for (int i=0; i<NUM_WIFI_STATES; i++) {
13637             mWifiStateTimer[i].readSummaryFromParcelLocked(in);
13638         }
13639         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
13640             mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
13641         }
13642         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
13643             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
13644         }
13645         mWifiActiveTimer.readSummaryFromParcelLocked(in);
13646         mWifiActivity.readSummaryFromParcel(in);
13647         for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
13648             mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
13649         }
13650         mBluetoothActivity.readSummaryFromParcel(in);
13651         mModemActivity.readSummaryFromParcel(in);
13652         mHasWifiReporting = in.readInt() != 0;
13653         mHasBluetoothReporting = in.readInt() != 0;
13654         mHasModemReporting = in.readInt() != 0;
13655 
13656         mNumConnectivityChange = in.readInt();
13657         mFlashlightOnNesting = 0;
13658         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
13659         mCameraOnNesting = 0;
13660         mCameraOnTimer.readSummaryFromParcelLocked(in);
13661         mBluetoothScanNesting = 0;
13662         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
13663 
13664         int NRPMS = in.readInt();
13665         if (NRPMS > 10000) {
13666             throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS);
13667         }
13668         for (int irpm = 0; irpm < NRPMS; irpm++) {
13669             if (in.readInt() != 0) {
13670                 String rpmName = in.readString();
13671                 getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
13672             }
13673         }
13674         int NSORPMS = in.readInt();
13675         if (NSORPMS > 10000) {
13676             throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS);
13677         }
13678         for (int irpm = 0; irpm < NSORPMS; irpm++) {
13679             if (in.readInt() != 0) {
13680                 String rpmName = in.readString();
13681                 getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
13682             }
13683         }
13684 
13685         int NKW = in.readInt();
13686         if (NKW > 10000) {
13687             throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
13688         }
13689         for (int ikw = 0; ikw < NKW; ikw++) {
13690             if (in.readInt() != 0) {
13691                 String kwltName = in.readString();
13692                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
13693             }
13694         }
13695 
13696         int NWR = in.readInt();
13697         if (NWR > 10000) {
13698             throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
13699         }
13700         for (int iwr = 0; iwr < NWR; iwr++) {
13701             if (in.readInt() != 0) {
13702                 String reasonName = in.readString();
13703                 getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
13704             }
13705         }
13706 
13707         int NMS = in.readInt();
13708         for (int ims = 0; ims < NMS; ims++) {
13709             if (in.readInt() != 0) {
13710                 long kmstName = in.readLong();
13711                 getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
13712             }
13713         }
13714 
13715         final int NU = in.readInt();
13716         if (NU > 10000) {
13717             throw new ParcelFormatException("File corrupt: too many uids " + NU);
13718         }
13719         for (int iu = 0; iu < NU; iu++) {
13720             int uid = in.readInt();
13721             Uid u = new Uid(this, uid);
13722             mUidStats.put(uid, u);
13723 
13724             u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
13725             u.mOnBatteryScreenOffBackgroundTimeBase.readSummaryFromParcel(in);
13726 
13727             u.mWifiRunning = false;
13728             if (in.readInt() != 0) {
13729                 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
13730             }
13731             u.mFullWifiLockOut = false;
13732             if (in.readInt() != 0) {
13733                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
13734             }
13735             u.mWifiScanStarted = false;
13736             if (in.readInt() != 0) {
13737                 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
13738             }
13739             u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
13740             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
13741                 if (in.readInt() != 0) {
13742                     u.makeWifiBatchedScanBin(i, null);
13743                     u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
13744                 }
13745             }
13746             u.mWifiMulticastWakelockCount = 0;
13747             if (in.readInt() != 0) {
13748                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
13749             }
13750             if (in.readInt() != 0) {
13751                 u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13752             }
13753             if (in.readInt() != 0) {
13754                 u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13755             }
13756             if (in.readInt() != 0) {
13757                 u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13758             }
13759             if (in.readInt() != 0) {
13760                 u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13761             }
13762             if (in.readInt() != 0) {
13763                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
13764             }
13765             if (in.readInt() != 0) {
13766                 u.createForegroundServiceTimerLocked().readSummaryFromParcelLocked(in);
13767             }
13768             if (in.readInt() != 0) {
13769                 u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
13770             }
13771             if (in.readInt() != 0) {
13772                 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
13773             }
13774             if (in.readInt() != 0) {
13775                 u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in);
13776             }
13777             if (in.readInt() != 0) {
13778                 u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
13779             }
13780             if (in.readInt() != 0) {
13781                 u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in);
13782             }
13783             u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
13784             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
13785                 if (in.readInt() != 0) {
13786                     u.makeProcessState(i, null);
13787                     u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
13788                 }
13789             }
13790             if (in.readInt() != 0) {
13791                 u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
13792             }
13793 
13794             if (in.readInt() != 0) {
13795                 if (u.mUserActivityCounters == null) {
13796                     u.initUserActivityLocked();
13797                 }
13798                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
13799                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
13800                 }
13801             }
13802 
13803             if (in.readInt() != 0) {
13804                 if (u.mNetworkByteActivityCounters == null) {
13805                     u.initNetworkActivityLocked();
13806                 }
13807                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
13808                     u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
13809                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
13810                 }
13811                 u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
13812                 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
13813             }
13814 
13815             u.mUserCpuTime.readSummaryFromParcelLocked(in);
13816             u.mSystemCpuTime.readSummaryFromParcelLocked(in);
13817 
13818             if (in.readInt() != 0) {
13819                 final int numClusters = in.readInt();
13820                 if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
13821                     throw new ParcelFormatException("Incompatible cpu cluster arrangement");
13822                 }
13823                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
13824                 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
13825                 for (int cluster = 0; cluster < numClusters; cluster++) {
13826                     if (in.readInt() != 0) {
13827                         final int NSB = in.readInt();
13828                         if (mPowerProfile != null &&
13829                                 mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
13830                             throw new ParcelFormatException("File corrupt: too many speed bins " +
13831                                     NSB);
13832                         }
13833 
13834                         u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[NSB];
13835                         for (int speed = 0; speed < NSB; speed++) {
13836                             if (in.readInt() != 0) {
13837                                 u.mCpuClusterSpeedTimesUs[cluster][speed] = new LongSamplingCounter(
13838                                         mOnBatteryTimeBase);
13839                                 u.mCpuClusterSpeedTimesUs[cluster][speed].readSummaryFromParcelLocked(in);
13840                             }
13841                         }
13842                     } else {
13843                         u.mCpuClusterSpeedTimesUs[cluster] = null;
13844                     }
13845                 }
13846             } else {
13847                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
13848                 u.mCpuClusterSpeedTimesUs = null;
13849             }
13850 
13851             detachIfNotNull(u.mCpuFreqTimeMs);
13852             u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
13853                     in, mOnBatteryTimeBase);
13854             detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
13855             u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
13856                     in, mOnBatteryScreenOffTimeBase);
13857 
13858             u.mCpuActiveTimeMs.readSummaryFromParcelLocked(in);
13859             u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
13860 
13861             int length = in.readInt();
13862             if (length == Uid.NUM_PROCESS_STATE) {
13863                 detachIfNotNull(u.mProcStateTimeMs);
13864                 u.mProcStateTimeMs = new LongSamplingCounterArray[length];
13865                 for (int procState = 0; procState < length; ++procState) {
13866                     u.mProcStateTimeMs[procState]
13867                             = LongSamplingCounterArray.readSummaryFromParcelLocked(
13868                                     in, mOnBatteryTimeBase);
13869                 }
13870             } else {
13871                 detachIfNotNull(u.mProcStateTimeMs);
13872                 u.mProcStateTimeMs = null;
13873             }
13874             length = in.readInt();
13875             if (length == Uid.NUM_PROCESS_STATE) {
13876                 detachIfNotNull(u.mProcStateScreenOffTimeMs);
13877                 u.mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
13878                 for (int procState = 0; procState < length; ++procState) {
13879                     u.mProcStateScreenOffTimeMs[procState]
13880                             = LongSamplingCounterArray.readSummaryFromParcelLocked(
13881                                     in, mOnBatteryScreenOffTimeBase);
13882                 }
13883             } else {
13884                 detachIfNotNull(u.mProcStateScreenOffTimeMs);
13885                 u.mProcStateScreenOffTimeMs = null;
13886             }
13887 
13888             if (in.readInt() != 0) {
13889                 detachIfNotNull(u.mMobileRadioApWakeupCount);
13890                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
13891                 u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
13892             } else {
13893                 detachIfNotNull(u.mMobileRadioApWakeupCount);
13894                 u.mMobileRadioApWakeupCount = null;
13895             }
13896 
13897             if (in.readInt() != 0) {
13898                 detachIfNotNull(u.mWifiRadioApWakeupCount);
13899                 u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
13900                 u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
13901             } else {
13902                 detachIfNotNull(u.mWifiRadioApWakeupCount);
13903                 u.mWifiRadioApWakeupCount = null;
13904             }
13905 
13906             int NW = in.readInt();
13907             if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
13908                 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
13909             }
13910             for (int iw = 0; iw < NW; iw++) {
13911                 String wlName = in.readString();
13912                 u.readWakeSummaryFromParcelLocked(wlName, in);
13913             }
13914 
13915             int NS = in.readInt();
13916             if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
13917                 throw new ParcelFormatException("File corrupt: too many syncs " + NS);
13918             }
13919             for (int is = 0; is < NS; is++) {
13920                 String name = in.readString();
13921                 u.readSyncSummaryFromParcelLocked(name, in);
13922             }
13923 
13924             int NJ = in.readInt();
13925             if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
13926                 throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
13927             }
13928             for (int ij = 0; ij < NJ; ij++) {
13929                 String name = in.readString();
13930                 u.readJobSummaryFromParcelLocked(name, in);
13931             }
13932 
13933             u.readJobCompletionsFromParcelLocked(in);
13934 
13935             u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in);
13936             u.mJobsDeferredCount.readSummaryFromParcelLocked(in);
13937             u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in);
13938             detachIfNotNull(u.mJobsFreshnessBuckets);
13939             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
13940                 if (in.readInt() != 0) {
13941                     u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase);
13942                     u.mJobsFreshnessBuckets[i].readSummaryFromParcelLocked(in);
13943                 }
13944             }
13945 
13946             int NP = in.readInt();
13947             if (NP > 1000) {
13948                 throw new ParcelFormatException("File corrupt: too many sensors " + NP);
13949             }
13950             for (int is = 0; is < NP; is++) {
13951                 int seNumber = in.readInt();
13952                 if (in.readInt() != 0) {
13953                     u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
13954                 }
13955             }
13956 
13957             NP = in.readInt();
13958             if (NP > 1000) {
13959                 throw new ParcelFormatException("File corrupt: too many processes " + NP);
13960             }
13961             for (int ip = 0; ip < NP; ip++) {
13962                 String procName = in.readString();
13963                 Uid.Proc p = u.getProcessStatsLocked(procName);
13964                 p.mUserTime = in.readLong();
13965                 p.mSystemTime = in.readLong();
13966                 p.mForegroundTime = in.readLong();
13967                 p.mStarts = in.readInt();
13968                 p.mNumCrashes = in.readInt();
13969                 p.mNumAnrs = in.readInt();
13970                 p.readExcessivePowerFromParcelLocked(in);
13971             }
13972 
13973             NP = in.readInt();
13974             if (NP > 10000) {
13975                 throw new ParcelFormatException("File corrupt: too many packages " + NP);
13976             }
13977             for (int ip = 0; ip < NP; ip++) {
13978                 String pkgName = in.readString();
13979                 detachIfNotNull(u.mPackageStats.get(pkgName));
13980                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
13981                 final int NWA = in.readInt();
13982                 if (NWA > 10000) {
13983                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
13984                 }
13985                 p.mWakeupAlarms.clear();
13986                 for (int iwa = 0; iwa < NWA; iwa++) {
13987                     String tag = in.readString();
13988                     Counter c = new Counter(mOnBatteryScreenOffTimeBase);
13989                     c.readSummaryFromParcelLocked(in);
13990                     p.mWakeupAlarms.put(tag, c);
13991                 }
13992                 NS = in.readInt();
13993                 if (NS > 10000) {
13994                     throw new ParcelFormatException("File corrupt: too many services " + NS);
13995                 }
13996                 for (int is = 0; is < NS; is++) {
13997                     String servName = in.readString();
13998                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
13999                     s.mStartTime = in.readLong();
14000                     s.mStarts = in.readInt();
14001                     s.mLaunches = in.readInt();
14002                 }
14003             }
14004         }
14005     }
14006 
14007     /**
14008      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
14009      * disk.  This format does not allow a lossless round-trip.
14010      *
14011      * @param out the Parcel to be written to.
14012      */
writeSummaryToParcel(Parcel out, boolean inclHistory)14013     public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
14014         pullPendingStateUpdatesLocked();
14015 
14016         // Pull the clock time.  This may update the time and make a new history entry
14017         // if we had originally pulled a time before the RTC was set.
14018         getStartClockTime();
14019 
14020         final long NOW_SYS = mClocks.uptimeMillis() * 1000;
14021         final long NOWREAL_SYS = mClocks.elapsedRealtime() * 1000;
14022 
14023         out.writeInt(VERSION);
14024 
14025         out.writeBoolean(inclHistory);
14026         if (inclHistory) {
14027             writeHistoryBuffer(out, true, true);
14028             mBatteryStatsHistory.writeToParcel(out);
14029         }
14030 
14031         out.writeInt(mHistoryTagPool.size());
14032         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
14033             HistoryTag tag = ent.getKey();
14034             out.writeInt(ent.getValue());
14035             out.writeString(tag.string);
14036             out.writeInt(tag.uid);
14037         }
14038 
14039         out.writeInt(mStartCount);
14040         out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
14041         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
14042         out.writeLong(mStartClockTime);
14043         out.writeString(mStartPlatformVersion);
14044         out.writeString(mEndPlatformVersion);
14045         mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14046         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14047         out.writeInt(mDischargeUnplugLevel);
14048         out.writeInt(mDischargePlugLevel);
14049         out.writeInt(mDischargeCurrentLevel);
14050         out.writeInt(mCurrentBatteryLevel);
14051         out.writeInt(mEstimatedBatteryCapacity);
14052         out.writeInt(mMinLearnedBatteryCapacity);
14053         out.writeInt(mMaxLearnedBatteryCapacity);
14054         out.writeInt(getLowDischargeAmountSinceCharge());
14055         out.writeInt(getHighDischargeAmountSinceCharge());
14056         out.writeInt(getDischargeAmountScreenOnSinceCharge());
14057         out.writeInt(getDischargeAmountScreenOffSinceCharge());
14058         out.writeInt(getDischargeAmountScreenDozeSinceCharge());
14059         mDischargeStepTracker.writeToParcel(out);
14060         mChargeStepTracker.writeToParcel(out);
14061         mDailyDischargeStepTracker.writeToParcel(out);
14062         mDailyChargeStepTracker.writeToParcel(out);
14063         mDischargeCounter.writeSummaryFromParcelLocked(out);
14064         mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
14065         mDischargeScreenDozeCounter.writeSummaryFromParcelLocked(out);
14066         mDischargeLightDozeCounter.writeSummaryFromParcelLocked(out);
14067         mDischargeDeepDozeCounter.writeSummaryFromParcelLocked(out);
14068         if (mDailyPackageChanges != null) {
14069             final int NPKG = mDailyPackageChanges.size();
14070             out.writeInt(NPKG);
14071             for (int i=0; i<NPKG; i++) {
14072                 PackageChange pc = mDailyPackageChanges.get(i);
14073                 out.writeString(pc.mPackageName);
14074                 out.writeInt(pc.mUpdate ? 1 : 0);
14075                 out.writeLong(pc.mVersionCode);
14076             }
14077         } else {
14078             out.writeInt(0);
14079         }
14080         out.writeLong(mDailyStartTime);
14081         out.writeLong(mNextMinDailyDeadline);
14082         out.writeLong(mNextMaxDailyDeadline);
14083 
14084         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14085         mScreenDozeTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14086         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14087             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14088         }
14089         mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14090         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14091         out.writeLong(mLongestLightIdleTime);
14092         out.writeLong(mLongestFullIdleTime);
14093         mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14094         mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14095         mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14096         mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14097         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14098         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
14099             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14100         }
14101         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14102         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14103             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14104         }
14105         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14106             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
14107             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
14108         }
14109         mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14110         mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14111         mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
14112         mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
14113         mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
14114         mWifiMulticastWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14115         mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14116         mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14117         for (int i=0; i<NUM_WIFI_STATES; i++) {
14118             mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14119         }
14120         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14121             mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14122         }
14123         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14124             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14125         }
14126         mWifiActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14127         mWifiActivity.writeSummaryToParcel(out);
14128         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14129             mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14130         }
14131         mBluetoothActivity.writeSummaryToParcel(out);
14132         mModemActivity.writeSummaryToParcel(out);
14133         out.writeInt(mHasWifiReporting ? 1 : 0);
14134         out.writeInt(mHasBluetoothReporting ? 1 : 0);
14135         out.writeInt(mHasModemReporting ? 1 : 0);
14136 
14137         out.writeInt(mNumConnectivityChange);
14138         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14139         mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14140         mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14141 
14142         out.writeInt(mRpmStats.size());
14143         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
14144             Timer rpmt = ent.getValue();
14145             if (rpmt != null) {
14146                 out.writeInt(1);
14147                 out.writeString(ent.getKey());
14148                 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14149             } else {
14150                 out.writeInt(0);
14151             }
14152         }
14153         out.writeInt(mScreenOffRpmStats.size());
14154         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
14155             Timer rpmt = ent.getValue();
14156             if (rpmt != null) {
14157                 out.writeInt(1);
14158                 out.writeString(ent.getKey());
14159                 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14160             } else {
14161                 out.writeInt(0);
14162             }
14163         }
14164 
14165         out.writeInt(mKernelWakelockStats.size());
14166         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
14167             Timer kwlt = ent.getValue();
14168             if (kwlt != null) {
14169                 out.writeInt(1);
14170                 out.writeString(ent.getKey());
14171                 kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14172             } else {
14173                 out.writeInt(0);
14174             }
14175         }
14176 
14177         out.writeInt(mWakeupReasonStats.size());
14178         for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
14179             SamplingTimer timer = ent.getValue();
14180             if (timer != null) {
14181                 out.writeInt(1);
14182                 out.writeString(ent.getKey());
14183                 timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14184             } else {
14185                 out.writeInt(0);
14186             }
14187         }
14188 
14189         out.writeInt(mKernelMemoryStats.size());
14190         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
14191             Timer kmt = mKernelMemoryStats.valueAt(i);
14192             if (kmt != null) {
14193                 out.writeInt(1);
14194                 out.writeLong(mKernelMemoryStats.keyAt(i));
14195                 kmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14196             } else {
14197                 out.writeInt(0);
14198             }
14199         }
14200 
14201         final int NU = mUidStats.size();
14202         out.writeInt(NU);
14203         for (int iu = 0; iu < NU; iu++) {
14204             out.writeInt(mUidStats.keyAt(iu));
14205             Uid u = mUidStats.valueAt(iu);
14206 
14207             u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14208             u.mOnBatteryScreenOffBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14209 
14210             if (u.mWifiRunningTimer != null) {
14211                 out.writeInt(1);
14212                 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14213             } else {
14214                 out.writeInt(0);
14215             }
14216             if (u.mFullWifiLockTimer != null) {
14217                 out.writeInt(1);
14218                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14219             } else {
14220                 out.writeInt(0);
14221             }
14222             if (u.mWifiScanTimer != null) {
14223                 out.writeInt(1);
14224                 u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14225             } else {
14226                 out.writeInt(0);
14227             }
14228             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
14229                 if (u.mWifiBatchedScanTimer[i] != null) {
14230                     out.writeInt(1);
14231                     u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14232                 } else {
14233                     out.writeInt(0);
14234                 }
14235             }
14236             if (u.mWifiMulticastTimer != null) {
14237                 out.writeInt(1);
14238                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14239             } else {
14240                 out.writeInt(0);
14241             }
14242             if (u.mAudioTurnedOnTimer != null) {
14243                 out.writeInt(1);
14244                 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14245             } else {
14246                 out.writeInt(0);
14247             }
14248             if (u.mVideoTurnedOnTimer != null) {
14249                 out.writeInt(1);
14250                 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14251             } else {
14252                 out.writeInt(0);
14253             }
14254             if (u.mFlashlightTurnedOnTimer != null) {
14255                 out.writeInt(1);
14256                 u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14257             } else {
14258                 out.writeInt(0);
14259             }
14260             if (u.mCameraTurnedOnTimer != null) {
14261                 out.writeInt(1);
14262                 u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14263             } else {
14264                 out.writeInt(0);
14265             }
14266             if (u.mForegroundActivityTimer != null) {
14267                 out.writeInt(1);
14268                 u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14269             } else {
14270                 out.writeInt(0);
14271             }
14272             if (u.mForegroundServiceTimer != null) {
14273                 out.writeInt(1);
14274                 u.mForegroundServiceTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14275             } else {
14276                 out.writeInt(0);
14277             }
14278             if (u.mAggregatedPartialWakelockTimer != null) {
14279                 out.writeInt(1);
14280                 u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14281             } else {
14282                 out.writeInt(0);
14283             }
14284             if (u.mBluetoothScanTimer != null) {
14285                 out.writeInt(1);
14286                 u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14287             } else {
14288                 out.writeInt(0);
14289             }
14290             if (u.mBluetoothUnoptimizedScanTimer != null) {
14291                 out.writeInt(1);
14292                 u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14293             } else {
14294                 out.writeInt(0);
14295             }
14296             if (u.mBluetoothScanResultCounter != null) {
14297                 out.writeInt(1);
14298                 u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
14299             } else {
14300                 out.writeInt(0);
14301             }
14302             if (u.mBluetoothScanResultBgCounter != null) {
14303                 out.writeInt(1);
14304                 u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out);
14305             } else {
14306                 out.writeInt(0);
14307             }
14308             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
14309                 if (u.mProcessStateTimer[i] != null) {
14310                     out.writeInt(1);
14311                     u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14312                 } else {
14313                     out.writeInt(0);
14314                 }
14315             }
14316             if (u.mVibratorOnTimer != null) {
14317                 out.writeInt(1);
14318                 u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14319             } else {
14320                 out.writeInt(0);
14321             }
14322 
14323             if (u.mUserActivityCounters == null) {
14324                 out.writeInt(0);
14325             } else {
14326                 out.writeInt(1);
14327                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
14328                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
14329                 }
14330             }
14331 
14332             if (u.mNetworkByteActivityCounters == null) {
14333                 out.writeInt(0);
14334             } else {
14335                 out.writeInt(1);
14336                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14337                     u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
14338                     u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
14339                 }
14340                 u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
14341                 u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
14342             }
14343 
14344             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
14345             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
14346 
14347             if (u.mCpuClusterSpeedTimesUs != null) {
14348                 out.writeInt(1);
14349                 out.writeInt(u.mCpuClusterSpeedTimesUs.length);
14350                 for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeedTimesUs) {
14351                     if (cpuSpeeds != null) {
14352                         out.writeInt(1);
14353                         out.writeInt(cpuSpeeds.length);
14354                         for (LongSamplingCounter c : cpuSpeeds) {
14355                             if (c != null) {
14356                                 out.writeInt(1);
14357                                 c.writeSummaryFromParcelLocked(out);
14358                             } else {
14359                                 out.writeInt(0);
14360                             }
14361                         }
14362                     } else {
14363                         out.writeInt(0);
14364                     }
14365                 }
14366             } else {
14367                 out.writeInt(0);
14368             }
14369 
14370             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
14371             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
14372 
14373             u.mCpuActiveTimeMs.writeSummaryFromParcelLocked(out);
14374             u.mCpuClusterTimesMs.writeSummaryToParcelLocked(out);
14375 
14376             if (u.mProcStateTimeMs != null) {
14377                 out.writeInt(u.mProcStateTimeMs.length);
14378                 for (LongSamplingCounterArray counters : u.mProcStateTimeMs) {
14379                     LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
14380                 }
14381             } else {
14382                 out.writeInt(0);
14383             }
14384             if (u.mProcStateScreenOffTimeMs != null) {
14385                 out.writeInt(u.mProcStateScreenOffTimeMs.length);
14386                 for (LongSamplingCounterArray counters : u.mProcStateScreenOffTimeMs) {
14387                     LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
14388                 }
14389             } else {
14390                 out.writeInt(0);
14391             }
14392 
14393             if (u.mMobileRadioApWakeupCount != null) {
14394                 out.writeInt(1);
14395                 u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
14396             } else {
14397                 out.writeInt(0);
14398             }
14399 
14400             if (u.mWifiRadioApWakeupCount != null) {
14401                 out.writeInt(1);
14402                 u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
14403             } else {
14404                 out.writeInt(0);
14405             }
14406 
14407             final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
14408             int NW = wakeStats.size();
14409             out.writeInt(NW);
14410             for (int iw=0; iw<NW; iw++) {
14411                 out.writeString(wakeStats.keyAt(iw));
14412                 Uid.Wakelock wl = wakeStats.valueAt(iw);
14413                 if (wl.mTimerFull != null) {
14414                     out.writeInt(1);
14415                     wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14416                 } else {
14417                     out.writeInt(0);
14418                 }
14419                 if (wl.mTimerPartial != null) {
14420                     out.writeInt(1);
14421                     wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14422                 } else {
14423                     out.writeInt(0);
14424                 }
14425                 if (wl.mTimerWindow != null) {
14426                     out.writeInt(1);
14427                     wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14428                 } else {
14429                     out.writeInt(0);
14430                 }
14431                 if (wl.mTimerDraw != null) {
14432                     out.writeInt(1);
14433                     wl.mTimerDraw.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14434                 } else {
14435                     out.writeInt(0);
14436                 }
14437             }
14438 
14439             final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
14440             int NS = syncStats.size();
14441             out.writeInt(NS);
14442             for (int is=0; is<NS; is++) {
14443                 out.writeString(syncStats.keyAt(is));
14444                 syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14445             }
14446 
14447             final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
14448             int NJ = jobStats.size();
14449             out.writeInt(NJ);
14450             for (int ij=0; ij<NJ; ij++) {
14451                 out.writeString(jobStats.keyAt(ij));
14452                 jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14453             }
14454 
14455             u.writeJobCompletionsToParcelLocked(out);
14456 
14457             u.mJobsDeferredEventCount.writeSummaryFromParcelLocked(out);
14458             u.mJobsDeferredCount.writeSummaryFromParcelLocked(out);
14459             u.mJobsFreshnessTimeMs.writeSummaryFromParcelLocked(out);
14460             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
14461                 if (u.mJobsFreshnessBuckets[i] != null) {
14462                     out.writeInt(1);
14463                     u.mJobsFreshnessBuckets[i].writeSummaryFromParcelLocked(out);
14464                 } else {
14465                     out.writeInt(0);
14466                 }
14467             }
14468 
14469             int NSE = u.mSensorStats.size();
14470             out.writeInt(NSE);
14471             for (int ise=0; ise<NSE; ise++) {
14472                 out.writeInt(u.mSensorStats.keyAt(ise));
14473                 Uid.Sensor se = u.mSensorStats.valueAt(ise);
14474                 if (se.mTimer != null) {
14475                     out.writeInt(1);
14476                     se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14477                 } else {
14478                     out.writeInt(0);
14479                 }
14480             }
14481 
14482             int NP = u.mProcessStats.size();
14483             out.writeInt(NP);
14484             for (int ip=0; ip<NP; ip++) {
14485                 out.writeString(u.mProcessStats.keyAt(ip));
14486                 Uid.Proc ps = u.mProcessStats.valueAt(ip);
14487                 out.writeLong(ps.mUserTime);
14488                 out.writeLong(ps.mSystemTime);
14489                 out.writeLong(ps.mForegroundTime);
14490                 out.writeInt(ps.mStarts);
14491                 out.writeInt(ps.mNumCrashes);
14492                 out.writeInt(ps.mNumAnrs);
14493                 ps.writeExcessivePowerToParcelLocked(out);
14494             }
14495 
14496             NP = u.mPackageStats.size();
14497             out.writeInt(NP);
14498             if (NP > 0) {
14499                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
14500                     : u.mPackageStats.entrySet()) {
14501                     out.writeString(ent.getKey());
14502                     Uid.Pkg ps = ent.getValue();
14503                     final int NWA = ps.mWakeupAlarms.size();
14504                     out.writeInt(NWA);
14505                     for (int iwa=0; iwa<NWA; iwa++) {
14506                         out.writeString(ps.mWakeupAlarms.keyAt(iwa));
14507                         ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
14508                     }
14509                     NS = ps.mServiceStats.size();
14510                     out.writeInt(NS);
14511                     for (int is=0; is<NS; is++) {
14512                         out.writeString(ps.mServiceStats.keyAt(is));
14513                         BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
14514                         long time = ss.getStartTimeToNowLocked(
14515                                 mOnBatteryTimeBase.getUptime(NOW_SYS));
14516                         out.writeLong(time);
14517                         out.writeInt(ss.mStarts);
14518                         out.writeInt(ss.mLaunches);
14519                     }
14520                 }
14521             }
14522         }
14523     }
14524 
readFromParcel(Parcel in)14525     public void readFromParcel(Parcel in) {
14526         readFromParcelLocked(in);
14527     }
14528 
readFromParcelLocked(Parcel in)14529     void readFromParcelLocked(Parcel in) {
14530         int magic = in.readInt();
14531         if (magic != MAGIC) {
14532             throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
14533         }
14534 
14535         readHistoryBuffer(in, false);
14536         mBatteryStatsHistory.readFromParcel(in);
14537 
14538         mStartCount = in.readInt();
14539         mStartClockTime = in.readLong();
14540         mStartPlatformVersion = in.readString();
14541         mEndPlatformVersion = in.readString();
14542         mUptime = in.readLong();
14543         mUptimeStart = in.readLong();
14544         mRealtime = in.readLong();
14545         mRealtimeStart = in.readLong();
14546         mOnBattery = in.readInt() != 0;
14547         mEstimatedBatteryCapacity = in.readInt();
14548         mMinLearnedBatteryCapacity = in.readInt();
14549         mMaxLearnedBatteryCapacity = in.readInt();
14550         mOnBatteryInternal = false; // we are no longer really running.
14551         mOnBatteryTimeBase.readFromParcel(in);
14552         mOnBatteryScreenOffTimeBase.readFromParcel(in);
14553 
14554         mScreenState = Display.STATE_UNKNOWN;
14555         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
14556         mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
14557         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14558             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
14559                     mOnBatteryTimeBase, in);
14560         }
14561         mInteractive = false;
14562         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase, in);
14563         mPhoneOn = false;
14564         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
14565                 mOnBatteryTimeBase, in);
14566         mLongestLightIdleTime = in.readLong();
14567         mLongestFullIdleTime = in.readLong();
14568         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null,
14569                 mOnBatteryTimeBase, in);
14570         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null,
14571                 mOnBatteryTimeBase, in);
14572         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null,
14573                 mOnBatteryTimeBase, in);
14574         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase, in);
14575         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase, in);
14576         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
14577             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i,
14578                     null, mOnBatteryTimeBase, in);
14579         }
14580         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
14581                 mOnBatteryTimeBase, in);
14582         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14583             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i,
14584                     null, mOnBatteryTimeBase, in);
14585         }
14586         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14587             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
14588             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
14589         }
14590         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
14591         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
14592                 mOnBatteryTimeBase, in);
14593         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
14594                 mOnBatteryTimeBase, in);
14595         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
14596         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
14597         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
14598         mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null, -4, null,
14599                 mOnBatteryTimeBase, in);
14600         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
14601         mWifiOn = false;
14602         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase, in);
14603         mGlobalWifiRunning = false;
14604         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null,
14605                 mOnBatteryTimeBase, in);
14606         for (int i=0; i<NUM_WIFI_STATES; i++) {
14607             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i,
14608                     null, mOnBatteryTimeBase, in);
14609         }
14610         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14611             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i,
14612                     null, mOnBatteryTimeBase, in);
14613         }
14614         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14615             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
14616                     null, mOnBatteryTimeBase, in);
14617         }
14618         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null,
14619             mOnBatteryTimeBase, in);
14620         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14621                 NUM_WIFI_TX_LEVELS, in);
14622         for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14623             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i,
14624                 null, mOnBatteryTimeBase, in);
14625         }
14626         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14627                 NUM_BT_TX_LEVELS, in);
14628         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14629                 ModemActivityInfo.TX_POWER_LEVELS, in);
14630         mHasWifiReporting = in.readInt() != 0;
14631         mHasBluetoothReporting = in.readInt() != 0;
14632         mHasModemReporting = in.readInt() != 0;
14633 
14634         mNumConnectivityChange = in.readInt();
14635         mAudioOnNesting = 0;
14636         // TODO: It's likely a mistake that mAudioOnTimer/mVideoOnTimer don't write/read to parcel!
14637         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
14638         mVideoOnNesting = 0;
14639         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
14640         mFlashlightOnNesting = 0;
14641         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase, in);
14642         mCameraOnNesting = 0;
14643         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
14644         mBluetoothScanNesting = 0;
14645         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
14646         mDischargeUnplugLevel = in.readInt();
14647         mDischargePlugLevel = in.readInt();
14648         mDischargeCurrentLevel = in.readInt();
14649         mCurrentBatteryLevel = in.readInt();
14650         mLowDischargeAmountSinceCharge = in.readInt();
14651         mHighDischargeAmountSinceCharge = in.readInt();
14652         mDischargeAmountScreenOn = in.readInt();
14653         mDischargeAmountScreenOnSinceCharge = in.readInt();
14654         mDischargeAmountScreenOff = in.readInt();
14655         mDischargeAmountScreenOffSinceCharge = in.readInt();
14656         mDischargeAmountScreenDoze = in.readInt();
14657         mDischargeAmountScreenDozeSinceCharge = in.readInt();
14658         mDischargeStepTracker.readFromParcel(in);
14659         mChargeStepTracker.readFromParcel(in);
14660         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14661         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase, in);
14662         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14663         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14664         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14665         mLastWriteTime = in.readLong();
14666 
14667         mRpmStats.clear();
14668         int NRPMS = in.readInt();
14669         for (int irpm = 0; irpm < NRPMS; irpm++) {
14670             if (in.readInt() != 0) {
14671                 String rpmName = in.readString();
14672                 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14673                 mRpmStats.put(rpmName, rpmt);
14674             }
14675         }
14676         mScreenOffRpmStats.clear();
14677         int NSORPMS = in.readInt();
14678         for (int irpm = 0; irpm < NSORPMS; irpm++) {
14679             if (in.readInt() != 0) {
14680                 String rpmName = in.readString();
14681                 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
14682                 mScreenOffRpmStats.put(rpmName, rpmt);
14683             }
14684         }
14685 
14686         mKernelWakelockStats.clear();
14687         int NKW = in.readInt();
14688         for (int ikw = 0; ikw < NKW; ikw++) {
14689             if (in.readInt() != 0) {
14690                 String wakelockName = in.readString();
14691                 SamplingTimer kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
14692                 mKernelWakelockStats.put(wakelockName, kwlt);
14693             }
14694         }
14695 
14696         mWakeupReasonStats.clear();
14697         int NWR = in.readInt();
14698         for (int iwr = 0; iwr < NWR; iwr++) {
14699             if (in.readInt() != 0) {
14700                 String reasonName = in.readString();
14701                 SamplingTimer timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14702                 mWakeupReasonStats.put(reasonName, timer);
14703             }
14704         }
14705 
14706         mKernelMemoryStats.clear();
14707         int nmt = in.readInt();
14708         for (int imt = 0; imt < nmt; imt++) {
14709             if (in.readInt() != 0) {
14710                 Long bucket = in.readLong();
14711                 SamplingTimer kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14712                 mKernelMemoryStats.put(bucket, kmt);
14713             }
14714         }
14715 
14716         mPartialTimers.clear();
14717         mFullTimers.clear();
14718         mWindowTimers.clear();
14719         mWifiRunningTimers.clear();
14720         mFullWifiLockTimers.clear();
14721         mWifiScanTimers.clear();
14722         mWifiBatchedScanTimers.clear();
14723         mWifiMulticastTimers.clear();
14724         mAudioTurnedOnTimers.clear();
14725         mVideoTurnedOnTimers.clear();
14726         mFlashlightTurnedOnTimers.clear();
14727         mCameraTurnedOnTimers.clear();
14728 
14729         int numUids = in.readInt();
14730         mUidStats.clear();
14731         for (int i = 0; i < numUids; i++) {
14732             int uid = in.readInt();
14733             Uid u = new Uid(this, uid);
14734             u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
14735             mUidStats.append(uid, u);
14736         }
14737     }
14738 
writeToParcel(Parcel out, int flags)14739     public void writeToParcel(Parcel out, int flags) {
14740         writeToParcelLocked(out, true, flags);
14741     }
14742 
writeToParcelWithoutUids(Parcel out, int flags)14743     public void writeToParcelWithoutUids(Parcel out, int flags) {
14744         writeToParcelLocked(out, false, flags);
14745     }
14746 
14747     @SuppressWarnings("unused")
writeToParcelLocked(Parcel out, boolean inclUids, int flags)14748     void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
14749         // Need to update with current kernel wake lock counts.
14750         pullPendingStateUpdatesLocked();
14751 
14752         // Pull the clock time.  This may update the time and make a new history entry
14753         // if we had originally pulled a time before the RTC was set.
14754         getStartClockTime();
14755 
14756         final long uSecUptime = mClocks.uptimeMillis() * 1000;
14757         final long uSecRealtime = mClocks.elapsedRealtime() * 1000;
14758         final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
14759         final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
14760 
14761         out.writeInt(MAGIC);
14762 
14763         writeHistoryBuffer(out, true, false);
14764         mBatteryStatsHistory.writeToParcel(out);
14765 
14766         out.writeInt(mStartCount);
14767         out.writeLong(mStartClockTime);
14768         out.writeString(mStartPlatformVersion);
14769         out.writeString(mEndPlatformVersion);
14770         out.writeLong(mUptime);
14771         out.writeLong(mUptimeStart);
14772         out.writeLong(mRealtime);
14773         out.writeLong(mRealtimeStart);
14774         out.writeInt(mOnBattery ? 1 : 0);
14775         out.writeInt(mEstimatedBatteryCapacity);
14776         out.writeInt(mMinLearnedBatteryCapacity);
14777         out.writeInt(mMaxLearnedBatteryCapacity);
14778         mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
14779         mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
14780 
14781         mScreenOnTimer.writeToParcel(out, uSecRealtime);
14782         mScreenDozeTimer.writeToParcel(out, uSecRealtime);
14783         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14784             mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
14785         }
14786         mInteractiveTimer.writeToParcel(out, uSecRealtime);
14787         mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
14788         out.writeLong(mLongestLightIdleTime);
14789         out.writeLong(mLongestFullIdleTime);
14790         mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
14791         mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
14792         mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
14793         mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
14794         mPhoneOnTimer.writeToParcel(out, uSecRealtime);
14795         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
14796             mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
14797         }
14798         mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
14799         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14800             mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
14801         }
14802         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14803             mNetworkByteActivityCounters[i].writeToParcel(out);
14804             mNetworkPacketActivityCounters[i].writeToParcel(out);
14805         }
14806         mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
14807         mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
14808         mMobileRadioActiveAdjustedTime.writeToParcel(out);
14809         mMobileRadioActiveUnknownTime.writeToParcel(out);
14810         mMobileRadioActiveUnknownCount.writeToParcel(out);
14811         mWifiMulticastWakelockTimer.writeToParcel(out, uSecRealtime);
14812         mWifiOnTimer.writeToParcel(out, uSecRealtime);
14813         mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
14814         for (int i=0; i<NUM_WIFI_STATES; i++) {
14815             mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
14816         }
14817         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14818             mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
14819         }
14820         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14821             mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
14822         }
14823         mWifiActiveTimer.writeToParcel(out, uSecRealtime);
14824         mWifiActivity.writeToParcel(out, 0);
14825         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14826             mGpsSignalQualityTimer[i].writeToParcel(out, uSecRealtime);
14827         }
14828         mBluetoothActivity.writeToParcel(out, 0);
14829         mModemActivity.writeToParcel(out, 0);
14830         out.writeInt(mHasWifiReporting ? 1 : 0);
14831         out.writeInt(mHasBluetoothReporting ? 1 : 0);
14832         out.writeInt(mHasModemReporting ? 1 : 0);
14833 
14834         out.writeInt(mNumConnectivityChange);
14835         mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
14836         mCameraOnTimer.writeToParcel(out, uSecRealtime);
14837         mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
14838         out.writeInt(mDischargeUnplugLevel);
14839         out.writeInt(mDischargePlugLevel);
14840         out.writeInt(mDischargeCurrentLevel);
14841         out.writeInt(mCurrentBatteryLevel);
14842         out.writeInt(mLowDischargeAmountSinceCharge);
14843         out.writeInt(mHighDischargeAmountSinceCharge);
14844         out.writeInt(mDischargeAmountScreenOn);
14845         out.writeInt(mDischargeAmountScreenOnSinceCharge);
14846         out.writeInt(mDischargeAmountScreenOff);
14847         out.writeInt(mDischargeAmountScreenOffSinceCharge);
14848         out.writeInt(mDischargeAmountScreenDoze);
14849         out.writeInt(mDischargeAmountScreenDozeSinceCharge);
14850         mDischargeStepTracker.writeToParcel(out);
14851         mChargeStepTracker.writeToParcel(out);
14852         mDischargeCounter.writeToParcel(out);
14853         mDischargeScreenOffCounter.writeToParcel(out);
14854         mDischargeScreenDozeCounter.writeToParcel(out);
14855         mDischargeLightDozeCounter.writeToParcel(out);
14856         mDischargeDeepDozeCounter.writeToParcel(out);
14857         out.writeLong(mLastWriteTime);
14858 
14859         out.writeInt(mRpmStats.size());
14860         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
14861             SamplingTimer rpmt = ent.getValue();
14862             if (rpmt != null) {
14863                 out.writeInt(1);
14864                 out.writeString(ent.getKey());
14865                 rpmt.writeToParcel(out, uSecRealtime);
14866             } else {
14867                 out.writeInt(0);
14868             }
14869         }
14870         out.writeInt(mScreenOffRpmStats.size());
14871         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
14872             SamplingTimer rpmt = ent.getValue();
14873             if (rpmt != null) {
14874                 out.writeInt(1);
14875                 out.writeString(ent.getKey());
14876                 rpmt.writeToParcel(out, uSecRealtime);
14877             } else {
14878                 out.writeInt(0);
14879             }
14880         }
14881 
14882         if (inclUids) {
14883             out.writeInt(mKernelWakelockStats.size());
14884             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
14885                 SamplingTimer kwlt = ent.getValue();
14886                 if (kwlt != null) {
14887                     out.writeInt(1);
14888                     out.writeString(ent.getKey());
14889                     kwlt.writeToParcel(out, uSecRealtime);
14890                 } else {
14891                     out.writeInt(0);
14892                 }
14893             }
14894             out.writeInt(mWakeupReasonStats.size());
14895             for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
14896                 SamplingTimer timer = ent.getValue();
14897                 if (timer != null) {
14898                     out.writeInt(1);
14899                     out.writeString(ent.getKey());
14900                     timer.writeToParcel(out, uSecRealtime);
14901                 } else {
14902                     out.writeInt(0);
14903                 }
14904             }
14905         } else {
14906             out.writeInt(0);
14907             out.writeInt(0);
14908         }
14909 
14910         out.writeInt(mKernelMemoryStats.size());
14911         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
14912             SamplingTimer kmt = mKernelMemoryStats.valueAt(i);
14913             if (kmt != null) {
14914                 out.writeInt(1);
14915                 out.writeLong(mKernelMemoryStats.keyAt(i));
14916                 kmt.writeToParcel(out, uSecRealtime);
14917             } else {
14918                 out.writeInt(0);
14919             }
14920         }
14921 
14922         if (inclUids) {
14923             int size = mUidStats.size();
14924             out.writeInt(size);
14925             for (int i = 0; i < size; i++) {
14926                 out.writeInt(mUidStats.keyAt(i));
14927                 Uid uid = mUidStats.valueAt(i);
14928 
14929                 uid.writeToParcelLocked(out, uSecUptime, uSecRealtime);
14930             }
14931         } else {
14932             out.writeInt(0);
14933         }
14934     }
14935 
14936     @UnsupportedAppUsage
14937     public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
14938         new Parcelable.Creator<BatteryStatsImpl>() {
14939         public BatteryStatsImpl createFromParcel(Parcel in) {
14940             return new BatteryStatsImpl(in);
14941         }
14942 
14943         public BatteryStatsImpl[] newArray(int size) {
14944             return new BatteryStatsImpl[size];
14945         }
14946     };
14947 
prepareForDumpLocked()14948     public void prepareForDumpLocked() {
14949         // Need to retrieve current kernel wake lock stats before printing.
14950         pullPendingStateUpdatesLocked();
14951 
14952         // Pull the clock time.  This may update the time and make a new history entry
14953         // if we had originally pulled a time before the RTC was set.
14954         getStartClockTime();
14955     }
14956 
dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart)14957     public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
14958         if (DEBUG) {
14959             pw.println("mOnBatteryTimeBase:");
14960             mOnBatteryTimeBase.dump(pw, "  ");
14961             pw.println("mOnBatteryScreenOffTimeBase:");
14962             mOnBatteryScreenOffTimeBase.dump(pw, "  ");
14963             Printer pr = new PrintWriterPrinter(pw);
14964             pr.println("*** Screen on timer:");
14965             mScreenOnTimer.logState(pr, "  ");
14966             pr.println("*** Screen doze timer:");
14967             mScreenDozeTimer.logState(pr, "  ");
14968             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14969                 pr.println("*** Screen brightness #" + i + ":");
14970                 mScreenBrightnessTimer[i].logState(pr, "  ");
14971             }
14972             pr.println("*** Interactive timer:");
14973             mInteractiveTimer.logState(pr, "  ");
14974             pr.println("*** Power save mode timer:");
14975             mPowerSaveModeEnabledTimer.logState(pr, "  ");
14976             pr.println("*** Device idle mode light timer:");
14977             mDeviceIdleModeLightTimer.logState(pr, "  ");
14978             pr.println("*** Device idle mode full timer:");
14979             mDeviceIdleModeFullTimer.logState(pr, "  ");
14980             pr.println("*** Device light idling timer:");
14981             mDeviceLightIdlingTimer.logState(pr, "  ");
14982             pr.println("*** Device idling timer:");
14983             mDeviceIdlingTimer.logState(pr, "  ");
14984             pr.println("*** Phone timer:");
14985             mPhoneOnTimer.logState(pr, "  ");
14986             for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
14987                 pr.println("*** Phone signal strength #" + i + ":");
14988                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
14989             }
14990             pr.println("*** Signal scanning :");
14991             mPhoneSignalScanningTimer.logState(pr, "  ");
14992             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14993                 pr.println("*** Data connection type #" + i + ":");
14994                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
14995             }
14996             pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
14997             pr.println("*** Mobile network active timer:");
14998             mMobileRadioActiveTimer.logState(pr, "  ");
14999             pr.println("*** Mobile network active adjusted timer:");
15000             mMobileRadioActiveAdjustedTime.logState(pr, "  ");
15001             pr.println("*** Wifi Multicast WakeLock Timer:");
15002             mWifiMulticastWakelockTimer.logState(pr, "  ");
15003             pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
15004             pr.println("*** Wifi timer:");
15005             mWifiOnTimer.logState(pr, "  ");
15006             pr.println("*** WifiRunning timer:");
15007             mGlobalWifiRunningTimer.logState(pr, "  ");
15008             for (int i=0; i<NUM_WIFI_STATES; i++) {
15009                 pr.println("*** Wifi state #" + i + ":");
15010                 mWifiStateTimer[i].logState(pr, "  ");
15011             }
15012             for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
15013                 pr.println("*** Wifi suppl state #" + i + ":");
15014                 mWifiSupplStateTimer[i].logState(pr, "  ");
15015             }
15016             for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
15017                 pr.println("*** Wifi signal strength #" + i + ":");
15018                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
15019             }
15020             for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
15021                 pr.println("*** GPS signal quality #" + i + ":");
15022                 mGpsSignalQualityTimer[i].logState(pr, "  ");
15023             }
15024             pr.println("*** Flashlight timer:");
15025             mFlashlightOnTimer.logState(pr, "  ");
15026             pr.println("*** Camera timer:");
15027             mCameraOnTimer.logState(pr, "  ");
15028         }
15029         super.dumpLocked(context, pw, flags, reqUid, histStart);
15030         pw.print("Total cpu time reads: ");
15031         pw.println(mNumSingleUidCpuTimeReads);
15032         pw.print("Batched cpu time reads: ");
15033         pw.println(mNumBatchedSingleUidCpuTimeReads);
15034         pw.print("Batching Duration (min): ");
15035         pw.println((mClocks.uptimeMillis() - mCpuTimeReadsTrackingStartTime) / (60 * 1000));
15036         pw.print("All UID cpu time reads since the later of device start or stats reset: ");
15037         pw.println(mNumAllUidCpuTimeReads);
15038         pw.print("UIDs removed since the later of device start or stats reset: ");
15039         pw.println(mNumUidsRemoved);
15040     }
15041 }
15042