1 /*
2  * Copyright (C) 2006-2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.os;
18 
19 import static android.os.BatteryStatsManager.NUM_WIFI_STATES;
20 import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;
21 
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.app.ActivityManager;
25 import android.bluetooth.BluetoothActivityEnergyInfo;
26 import android.bluetooth.UidTraffic;
27 import android.compat.annotation.UnsupportedAppUsage;
28 import android.content.BroadcastReceiver;
29 import android.content.ContentResolver;
30 import android.content.Context;
31 import android.content.Intent;
32 import android.content.IntentFilter;
33 import android.database.ContentObserver;
34 import android.hardware.usb.UsbManager;
35 import android.net.ConnectivityManager;
36 import android.net.INetworkStatsService;
37 import android.net.NetworkStats;
38 import android.net.Uri;
39 import android.net.wifi.WifiManager;
40 import android.os.BatteryManager;
41 import android.os.BatteryStats;
42 import android.os.Build;
43 import android.os.Handler;
44 import android.os.IBatteryPropertiesRegistrar;
45 import android.os.Looper;
46 import android.os.Message;
47 import android.os.OsProtoEnums;
48 import android.os.Parcel;
49 import android.os.ParcelFormatException;
50 import android.os.Parcelable;
51 import android.os.PowerManager;
52 import android.os.Process;
53 import android.os.RemoteException;
54 import android.os.ServiceManager;
55 import android.os.SystemClock;
56 import android.os.UserHandle;
57 import android.os.WorkSource;
58 import android.os.WorkSource.WorkChain;
59 import android.os.connectivity.CellularBatteryStats;
60 import android.os.connectivity.GpsBatteryStats;
61 import android.os.connectivity.WifiActivityEnergyInfo;
62 import android.os.connectivity.WifiBatteryStats;
63 import android.provider.Settings;
64 import android.telephony.CellSignalStrength;
65 import android.telephony.DataConnectionRealTimeInfo;
66 import android.telephony.ModemActivityInfo;
67 import android.telephony.ModemActivityInfo.TransmitPower;
68 import android.telephony.ServiceState;
69 import android.telephony.SignalStrength;
70 import android.telephony.TelephonyManager;
71 import android.text.TextUtils;
72 import android.util.ArrayMap;
73 import android.util.AtomicFile;
74 import android.util.IntArray;
75 import android.util.KeyValueListParser;
76 import android.util.Log;
77 import android.util.LogWriter;
78 import android.util.LongSparseArray;
79 import android.util.LongSparseLongArray;
80 import android.util.MutableInt;
81 import android.util.Pools;
82 import android.util.PrintWriterPrinter;
83 import android.util.Printer;
84 import android.util.Slog;
85 import android.util.SparseArray;
86 import android.util.SparseIntArray;
87 import android.util.SparseLongArray;
88 import android.util.TimeUtils;
89 import android.util.Xml;
90 import android.view.Display;
91 
92 import com.android.internal.annotations.GuardedBy;
93 import com.android.internal.annotations.VisibleForTesting;
94 import com.android.internal.location.gnssmetrics.GnssMetrics;
95 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
96 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
97 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
98 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
99 import com.android.internal.util.ArrayUtils;
100 import com.android.internal.util.FastPrintWriter;
101 import com.android.internal.util.FastXmlSerializer;
102 import com.android.internal.util.FrameworkStatsLog;
103 import com.android.internal.util.XmlUtils;
104 
105 import libcore.util.EmptyArray;
106 
107 import org.xmlpull.v1.XmlPullParser;
108 import org.xmlpull.v1.XmlPullParserException;
109 import org.xmlpull.v1.XmlSerializer;
110 
111 import java.io.ByteArrayOutputStream;
112 import java.io.File;
113 import java.io.FileInputStream;
114 import java.io.FileNotFoundException;
115 import java.io.FileOutputStream;
116 import java.io.IOException;
117 import java.io.PrintWriter;
118 import java.nio.charset.StandardCharsets;
119 import java.util.ArrayList;
120 import java.util.Arrays;
121 import java.util.Calendar;
122 import java.util.Collection;
123 import java.util.HashMap;
124 import java.util.HashSet;
125 import java.util.Iterator;
126 import java.util.LinkedList;
127 import java.util.List;
128 import java.util.Map;
129 import java.util.Queue;
130 import java.util.concurrent.Future;
131 import java.util.concurrent.atomic.AtomicInteger;
132 import java.util.concurrent.locks.ReentrantLock;
133 
134 /**
135  * All information we are collecting about things that can happen that impact
136  * battery life.  All times are represented in microseconds except where indicated
137  * otherwise.
138  */
139 public class BatteryStatsImpl extends BatteryStats {
140     private static final String TAG = "BatteryStatsImpl";
141     private static final boolean DEBUG = false;
142     public static final boolean DEBUG_ENERGY = false;
143     private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
144     private static final boolean DEBUG_MEMORY = false;
145     private static final boolean DEBUG_HISTORY = false;
146     private static final boolean USE_OLD_HISTORY = false;   // for debugging.
147 
148     // TODO: remove "tcp" from network methods, since we measure total stats.
149 
150     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
151     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
152 
153     // Current on-disk Parcel version
154     static final int VERSION = 186 + (USE_OLD_HISTORY ? 1000 : 0);
155 
156     // The maximum number of names wakelocks we will keep track of
157     // per uid; once the limit is reached, we batch the remaining wakelocks
158     // in to one common name.
159     private static final int MAX_WAKELOCKS_PER_UID;
160 
161     static {
162         if (ActivityManager.isLowRamDeviceStatic()) {
163             MAX_WAKELOCKS_PER_UID = 40;
164         } else {
165             MAX_WAKELOCKS_PER_UID = 200;
166         }
167     }
168 
169     // Number of transmit power states the Wifi controller can be in.
170     private static final int NUM_WIFI_TX_LEVELS = 1;
171 
172     // Number of transmit power states the Bluetooth controller can be in.
173     private static final int NUM_BT_TX_LEVELS = 1;
174 
175     /**
176      * Holding a wakelock costs more than just using the cpu.
177      * Currently, we assign only half the cpu time to an app that is running but
178      * not holding a wakelock. The apps holding wakelocks get the rest of the blame.
179      * If no app is holding a wakelock, then the distribution is normal.
180      */
181     @VisibleForTesting
182     public static final int WAKE_LOCK_WEIGHT = 50;
183 
184     protected Clocks mClocks;
185 
186     private final AtomicFile mStatsFile;
187     public final AtomicFile mCheckinFile;
188     public final AtomicFile mDailyFile;
189 
190     static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1;
191     static final int MSG_REPORT_POWER_CHANGE = 2;
192     static final int MSG_REPORT_CHARGING = 3;
193     static final int MSG_REPORT_RESET_STATS = 4;
194     static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
195 
196     private static final double MILLISECONDS_IN_HOUR = 3600 * 1000;
197     private static final long MILLISECONDS_IN_YEAR = 365 * 24 * 3600 * 1000L;
198 
199     private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
200     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
201 
202     @VisibleForTesting
203     protected KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader =
204             new KernelCpuUidUserSysTimeReader(true);
205     @VisibleForTesting
206     protected KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
207     @VisibleForTesting
208     protected KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader =
209             new KernelCpuUidFreqTimeReader(true);
210     @VisibleForTesting
211     protected KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader =
212             new KernelCpuUidActiveTimeReader(true);
213     @VisibleForTesting
214     protected KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader =
215             new KernelCpuUidClusterTimeReader(true);
216     @VisibleForTesting
217     protected KernelSingleUidTimeReader mKernelSingleUidTimeReader;
218 
219     private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats
220             = new KernelMemoryBandwidthStats();
221     private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>();
getKernelMemoryStats()222     public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
223         return mKernelMemoryStats;
224     }
225 
226     @GuardedBy("this")
227     public boolean mPerProcStateCpuTimesAvailable = true;
228 
229     /**
230      * When per process state cpu times tracking is off, cpu times in KernelSingleUidTimeReader are
231      * not updated. So, when the setting is turned on later, we would end up with huge cpu time
232      * deltas. This flag tracks the case where tracking is turned on from off so that we won't
233      * end up attributing the huge deltas to wrong buckets.
234      */
235     @GuardedBy("this")
236     private boolean mIsPerProcessStateCpuDataStale;
237 
238     /**
239      * Uids for which per-procstate cpu times need to be updated.
240      *
241      * Contains uid -> procState mappings.
242      */
243     @GuardedBy("this")
244     @VisibleForTesting
245     protected final SparseIntArray mPendingUids = new SparseIntArray();
246 
247     @GuardedBy("this")
248     private long mNumSingleUidCpuTimeReads;
249     @GuardedBy("this")
250     private long mNumBatchedSingleUidCpuTimeReads;
251     @GuardedBy("this")
252     private long mCpuTimeReadsTrackingStartTime = SystemClock.uptimeMillis();
253     @GuardedBy("this")
254     private int mNumUidsRemoved;
255     @GuardedBy("this")
256     private int mNumAllUidCpuTimeReads;
257 
258     /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
259     private final RpmStats mTmpRpmStats = new RpmStats();
260     /** The soonest the RPM stats can be updated after it was last updated. */
261     private static final long RPM_STATS_UPDATE_FREQ_MS = 1000;
262     /** Last time that RPM stats were updated by updateRpmStatsLocked. */
263     private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
264 
265     /** Container for Rail Energy Data stats. */
266     private final RailStats mTmpRailStats = new RailStats();
267     /**
268      * Use a queue to delay removing UIDs from {@link KernelCpuUidUserSysTimeReader},
269      * {@link KernelCpuUidActiveTimeReader}, {@link KernelCpuUidClusterTimeReader},
270      * {@link KernelCpuUidFreqTimeReader} and from the Kernel.
271      *
272      * Isolated and invalid UID info must be removed to conserve memory. However, STATSD and
273      * Batterystats both need to access UID cpu time. To resolve this race condition, only
274      * Batterystats shall remove UIDs, and a delay {@link Constants#UID_REMOVE_DELAY_MS} is
275      * implemented so that STATSD can capture those UID times before they are deleted.
276      */
277     @GuardedBy("this")
278     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
279     protected Queue<UidToRemove> mPendingRemovedUids = new LinkedList<>();
280 
281     @VisibleForTesting
282     public final class UidToRemove {
283         int startUid;
284         int endUid;
285         long timeAddedInQueue;
286 
287         /** Remove just one UID */
UidToRemove(int uid, long timestamp)288         public UidToRemove(int uid, long timestamp) {
289             this(uid, uid, timestamp);
290         }
291 
292         /** Remove a range of UIDs, startUid must be smaller than endUid. */
UidToRemove(int startUid, int endUid, long timestamp)293         public UidToRemove(int startUid, int endUid, long timestamp) {
294             this.startUid = startUid;
295             this.endUid = endUid;
296             timeAddedInQueue = timestamp;
297         }
298 
remove()299         void remove() {
300             if (startUid == endUid) {
301                 mCpuUidUserSysTimeReader.removeUid(startUid);
302                 mCpuUidFreqTimeReader.removeUid(startUid);
303                 if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
304                     mCpuUidActiveTimeReader.removeUid(startUid);
305                     mCpuUidClusterTimeReader.removeUid(startUid);
306                 }
307                 if (mKernelSingleUidTimeReader != null) {
308                     mKernelSingleUidTimeReader.removeUid(startUid);
309                 }
310                 mNumUidsRemoved++;
311             } else if (startUid < endUid) {
312                 mCpuUidFreqTimeReader.removeUidsInRange(startUid, endUid);
313                 mCpuUidUserSysTimeReader.removeUidsInRange(startUid, endUid);
314                 if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
315                     mCpuUidActiveTimeReader.removeUidsInRange(startUid, endUid);
316                     mCpuUidClusterTimeReader.removeUidsInRange(startUid, endUid);
317                 }
318                 if (mKernelSingleUidTimeReader != null) {
319                     mKernelSingleUidTimeReader.removeUidsInRange(startUid, endUid);
320                 }
321                 // Treat as one. We don't know how many uids there are in between.
322                 mNumUidsRemoved++;
323             } else {
324                 Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
325             }
326         }
327     }
328 
329     public interface BatteryCallback {
batteryNeedsCpuUpdate()330         public void batteryNeedsCpuUpdate();
batteryPowerChanged(boolean onBattery)331         public void batteryPowerChanged(boolean onBattery);
batterySendBroadcast(Intent intent)332         public void batterySendBroadcast(Intent intent);
batteryStatsReset()333         public void batteryStatsReset();
334     }
335 
336     public interface PlatformIdleStateCallback {
fillLowPowerStats(RpmStats rpmStats)337         public void fillLowPowerStats(RpmStats rpmStats);
getPlatformLowPowerStats()338         public String getPlatformLowPowerStats();
getSubsystemLowPowerStats()339         public String getSubsystemLowPowerStats();
340     }
341 
342     /** interface to update rail information for power monitor */
343     public interface RailEnergyDataCallback {
344         /** Function to fill the map for the rail data stats
345          * Used for power monitoring feature
346          * @param railStats
347          */
fillRailDataStats(RailStats railStats)348         void fillRailDataStats(RailStats railStats);
349     }
350 
351     public static abstract class UserInfoProvider {
352         private int[] userIds;
getUserIds()353         protected abstract @Nullable int[] getUserIds();
354         @VisibleForTesting
refreshUserIds()355         public final void refreshUserIds() {
356             userIds = getUserIds();
357         }
358         @VisibleForTesting
exists(int userId)359         public boolean exists(int userId) {
360             return userIds != null ? ArrayUtils.contains(userIds, userId) : true;
361         }
362     }
363 
364     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
365 
366     private final Runnable mDeferSetCharging = new Runnable() {
367         @Override
368         public void run() {
369             synchronized (BatteryStatsImpl.this) {
370                 if (mOnBattery) {
371                     // if the device gets unplugged in the time between this runnable being
372                     // executed and the lock being taken, we don't want to set charging state
373                     return;
374                 }
375                 boolean changed = setChargingLocked(true);
376                 if (changed) {
377                     final long uptime = mClocks.uptimeMillis();
378                     final long elapsedRealtime = mClocks.elapsedRealtime();
379                     addHistoryRecordLocked(elapsedRealtime, uptime);
380                 }
381             }
382         }
383     };
384 
385     public final RailEnergyDataCallback mRailEnergyDataCallback;
386 
387     /**
388      * This handler is running on {@link BackgroundThread}.
389      */
390     final class MyHandler extends Handler {
MyHandler(Looper looper)391         public MyHandler(Looper looper) {
392             super(looper, null, true);
393         }
394 
395         @Override
handleMessage(Message msg)396         public void handleMessage(Message msg) {
397             BatteryCallback cb = mCallback;
398             switch (msg.what) {
399                 case MSG_REPORT_CPU_UPDATE_NEEDED:
400                     if (cb != null) {
401                         cb.batteryNeedsCpuUpdate();
402                     }
403                     break;
404                 case MSG_REPORT_POWER_CHANGE:
405                     if (cb != null) {
406                         cb.batteryPowerChanged(msg.arg1 != 0);
407                     }
408                     break;
409                 case MSG_REPORT_CHARGING:
410                     if (cb != null) {
411                         final String action;
412                         synchronized (BatteryStatsImpl.this) {
413                             action = mCharging ? BatteryManager.ACTION_CHARGING
414                                     : BatteryManager.ACTION_DISCHARGING;
415                         }
416                         Intent intent = new Intent(action);
417                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
418                         cb.batterySendBroadcast(intent);
419                     }
420                     break;
421                 case MSG_REPORT_RESET_STATS:
422                     if (cb != null) {
423                         cb.batteryStatsReset();
424                     }
425                 }
426         }
427     }
428 
postBatteryNeedsCpuUpdateMsg()429     public void postBatteryNeedsCpuUpdateMsg() {
430         mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED);
431     }
432 
433     /**
434      * Update per-freq cpu times for all the uids in {@link #mPendingUids}.
435      */
updateProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff)436     public void updateProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
437         final SparseIntArray uidStates;
438         synchronized (BatteryStatsImpl.this) {
439             if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
440                 return;
441             }
442             if(!initKernelSingleUidTimeReaderLocked()) {
443                 return;
444             }
445             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
446             // compute deltas since it might result in mis-attributing cpu times to wrong states.
447             if (mIsPerProcessStateCpuDataStale) {
448                 mPendingUids.clear();
449                 return;
450             }
451 
452             if (mPendingUids.size() == 0) {
453                 return;
454             }
455             uidStates = mPendingUids.clone();
456             mPendingUids.clear();
457         }
458         for (int i = uidStates.size() - 1; i >= 0; --i) {
459             final int uid = uidStates.keyAt(i);
460             final int procState = uidStates.valueAt(i);
461             final int[] isolatedUids;
462             final Uid u;
463             synchronized (BatteryStatsImpl.this) {
464                 // It's possible that uid no longer exists and any internal references have
465                 // already been deleted, so using {@link #getAvailableUidStatsLocked} to avoid
466                 // creating an UidStats object if it doesn't already exist.
467                 u = getAvailableUidStatsLocked(uid);
468                 if (u == null) {
469                     continue;
470                 }
471                 if (u.mChildUids == null) {
472                     isolatedUids = null;
473                 } else {
474                     isolatedUids = u.mChildUids.toArray();
475                     for (int j = isolatedUids.length - 1; j >= 0; --j) {
476                         isolatedUids[j] = u.mChildUids.get(j);
477                     }
478                 }
479             }
480             long[] cpuTimesMs = mKernelSingleUidTimeReader.readDeltaMs(uid);
481             if (isolatedUids != null) {
482                 for (int j = isolatedUids.length - 1; j >= 0; --j) {
483                     cpuTimesMs = addCpuTimes(cpuTimesMs,
484                             mKernelSingleUidTimeReader.readDeltaMs(isolatedUids[j]));
485                 }
486             }
487             if (onBattery && cpuTimesMs != null) {
488                 synchronized (BatteryStatsImpl.this) {
489                     u.addProcStateTimesMs(procState, cpuTimesMs, onBattery);
490                     u.addProcStateScreenOffTimesMs(procState, cpuTimesMs, onBatteryScreenOff);
491                 }
492             }
493         }
494     }
495 
clearPendingRemovedUids()496     public void clearPendingRemovedUids() {
497         long cutOffTime = mClocks.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS;
498         while (!mPendingRemovedUids.isEmpty()
499                 && mPendingRemovedUids.peek().timeAddedInQueue < cutOffTime) {
500             mPendingRemovedUids.poll().remove();
501         }
502     }
503 
copyFromAllUidsCpuTimes()504     public void copyFromAllUidsCpuTimes() {
505         synchronized (BatteryStatsImpl.this) {
506             copyFromAllUidsCpuTimes(
507                     mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
508         }
509     }
510 
511     /**
512      * When the battery/screen state changes, we don't attribute the cpu times to any process
513      * but we still need to snapshots of all uids to get correct deltas later on. Since we
514      * already read this data for updating per-freq cpu times, we can use the same data for
515      * per-procstate cpu times.
516      */
copyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff)517     public void copyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
518         synchronized (BatteryStatsImpl.this) {
519             if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
520                 return;
521             }
522             if(!initKernelSingleUidTimeReaderLocked()) {
523                 return;
524             }
525 
526             final SparseArray<long[]> allUidCpuFreqTimesMs =
527                     mCpuUidFreqTimeReader.getAllUidCpuFreqTimeMs();
528             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
529             // compute deltas since it might result in mis-attributing cpu times to wrong states.
530             if (mIsPerProcessStateCpuDataStale) {
531                 mKernelSingleUidTimeReader.setAllUidsCpuTimesMs(allUidCpuFreqTimesMs);
532                 mIsPerProcessStateCpuDataStale = false;
533                 mPendingUids.clear();
534                 return;
535             }
536             for (int i = allUidCpuFreqTimesMs.size() - 1; i >= 0; --i) {
537                 final int uid = allUidCpuFreqTimesMs.keyAt(i);
538                 final Uid u = getAvailableUidStatsLocked(mapUid(uid));
539                 if (u == null) {
540                     continue;
541                 }
542                 final long[] cpuTimesMs = allUidCpuFreqTimesMs.valueAt(i);
543                 if (cpuTimesMs == null) {
544                     continue;
545                 }
546                 final long[] deltaTimesMs = mKernelSingleUidTimeReader.computeDelta(
547                         uid, cpuTimesMs.clone());
548                 if (onBattery && deltaTimesMs != null) {
549                     final int procState;
550                     final int idx = mPendingUids.indexOfKey(uid);
551                     if (idx >= 0) {
552                         procState = mPendingUids.valueAt(idx);
553                         mPendingUids.removeAt(idx);
554                     } else {
555                         procState = u.mProcessState;
556                     }
557                     if (procState >= 0 && procState < Uid.NUM_PROCESS_STATE) {
558                         u.addProcStateTimesMs(procState, deltaTimesMs, onBattery);
559                         u.addProcStateScreenOffTimesMs(procState, deltaTimesMs, onBatteryScreenOff);
560                     }
561                 }
562             }
563         }
564     }
565 
566     @VisibleForTesting
addCpuTimes(long[] timesA, long[] timesB)567     public long[] addCpuTimes(long[] timesA, long[] timesB) {
568         if (timesA != null && timesB != null) {
569             for (int i = timesA.length - 1; i >= 0; --i) {
570                 timesA[i] += timesB[i];
571             }
572             return timesA;
573         }
574         return timesA == null ? (timesB == null ? null : timesB) : timesA;
575     }
576 
577     @GuardedBy("this")
initKernelSingleUidTimeReaderLocked()578     private boolean initKernelSingleUidTimeReaderLocked() {
579         if (mKernelSingleUidTimeReader == null) {
580             if (mPowerProfile == null) {
581                 return false;
582             }
583             if (mCpuFreqs == null) {
584                 mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
585             }
586             if (mCpuFreqs != null) {
587                 mKernelSingleUidTimeReader = new KernelSingleUidTimeReader(mCpuFreqs.length);
588             } else {
589                 mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.allUidTimesAvailable();
590                 return false;
591             }
592         }
593         mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.allUidTimesAvailable()
594                 && mKernelSingleUidTimeReader.singleUidCpuTimesAvailable();
595         return true;
596     }
597 
598     public interface Clocks {
elapsedRealtime()599         public long elapsedRealtime();
uptimeMillis()600         public long uptimeMillis();
601     }
602 
603     public static class SystemClocks implements Clocks {
elapsedRealtime()604         public long elapsedRealtime() {
605             return SystemClock.elapsedRealtime();
606         }
607 
uptimeMillis()608         public long uptimeMillis() {
609             return SystemClock.uptimeMillis();
610         }
611     }
612 
613     public interface ExternalStatsSync {
614         int UPDATE_CPU = 0x01;
615         int UPDATE_WIFI = 0x02;
616         int UPDATE_RADIO = 0x04;
617         int UPDATE_BT = 0x08;
618         int UPDATE_RPM = 0x10; // 16
619         int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM;
620 
scheduleSync(String reason, int flags)621         Future<?> scheduleSync(String reason, int flags);
scheduleCpuSyncDueToRemovedUid(int uid)622         Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff, long delayMillis)623         Future<?> scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff,
624                 long delayMillis);
scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff)625         Future<?> scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff);
scheduleCpuSyncDueToSettingChange()626         Future<?> scheduleCpuSyncDueToSettingChange();
scheduleCpuSyncDueToScreenStateChange(boolean onBattery, boolean onBatteryScreenOff)627         Future<?> scheduleCpuSyncDueToScreenStateChange(boolean onBattery,
628                 boolean onBatteryScreenOff);
scheduleCpuSyncDueToWakelockChange(long delayMillis)629         Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis);
cancelCpuSyncDueToWakelockChange()630         void cancelCpuSyncDueToWakelockChange();
scheduleSyncDueToBatteryLevelChange(long delayMillis)631         Future<?> scheduleSyncDueToBatteryLevelChange(long delayMillis);
632     }
633 
634     public Handler mHandler;
635     private ExternalStatsSync mExternalSync = null;
636     @VisibleForTesting
637     protected UserInfoProvider mUserInfoProvider = null;
638 
639     private BatteryCallback mCallback;
640 
641     /**
642      * Mapping isolated uids to the actual owning app uid.
643      */
644     final SparseIntArray mIsolatedUids = new SparseIntArray();
645 
646     /**
647      * The statistics we have collected organized by uids.
648      */
649     final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
650 
651     // A set of pools of currently active timers.  When a timer is queried, we will divide the
652     // elapsed time by the number of active timers to arrive at that timer's share of the time.
653     // In order to do this, we must refresh each timer whenever the number of active timers
654     // changes.
655     @VisibleForTesting
656     @UnsupportedAppUsage
657     protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
658     @UnsupportedAppUsage
659     final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
660     @UnsupportedAppUsage
661     final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
662     final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
663     final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
664     final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
665     final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
666     final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
667     final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
668     final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers = new SparseArray<>();
669     final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
670     final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
671     final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
672     final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
673     final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
674 
675     // Last partial timers we use for distributing CPU usage.
676     @VisibleForTesting
677     protected ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
678 
679     // These are the objects that will want to do something when the device
680     // is unplugged from power.
681     protected final TimeBase mOnBatteryTimeBase = new TimeBase(true);
682 
683     // These are the objects that will want to do something when the device
684     // is unplugged from power *and* the screen is off or doze.
685     protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(true);
686 
687     // Set to true when we want to distribute CPU across wakelocks for the next
688     // CPU update, even if we aren't currently running wake locks.
689     boolean mDistributeWakelockCpu;
690 
691     boolean mShuttingDown;
692 
693     final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
694 
695     long mHistoryBaseTime;
696     protected boolean mHaveBatteryLevel = false;
697     protected boolean mRecordingHistory = false;
698     int mNumHistoryItems;
699 
700     final Parcel mHistoryBuffer = Parcel.obtain();
701     final HistoryItem mHistoryLastWritten = new HistoryItem();
702     final HistoryItem mHistoryLastLastWritten = new HistoryItem();
703     final HistoryItem mHistoryReadTmp = new HistoryItem();
704     final HistoryItem mHistoryAddTmp = new HistoryItem();
705     final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
706     String[] mReadHistoryStrings;
707     int[] mReadHistoryUids;
708     int mReadHistoryChars;
709     int mNextHistoryTagIdx = 0;
710     int mNumHistoryTagChars = 0;
711     int mHistoryBufferLastPos = -1;
712     int mActiveHistoryStates = 0xffffffff;
713     int mActiveHistoryStates2 = 0xffffffff;
714     long mLastHistoryElapsedRealtime = 0;
715     long mTrackRunningHistoryElapsedRealtime = 0;
716     long mTrackRunningHistoryUptime = 0;
717 
718     final BatteryStatsHistory mBatteryStatsHistory;
719 
720     final HistoryItem mHistoryCur = new HistoryItem();
721 
722     HistoryItem mHistory;
723     HistoryItem mHistoryEnd;
724     HistoryItem mHistoryLastEnd;
725     HistoryItem mHistoryCache;
726 
727     // Used by computeHistoryStepDetails
728     HistoryStepDetails mLastHistoryStepDetails = null;
729     byte mLastHistoryStepLevel = 0;
730     final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
731     final HistoryStepDetails mReadHistoryStepDetails = new HistoryStepDetails();
732     final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
733 
734     /**
735      * Total time (in milliseconds) spent executing in user code.
736      */
737     long mLastStepCpuUserTime;
738     long mCurStepCpuUserTime;
739     /**
740      * Total time (in milliseconds) spent executing in kernel code.
741      */
742     long mLastStepCpuSystemTime;
743     long mCurStepCpuSystemTime;
744     /**
745      * Times from /proc/stat (but measured in milliseconds).
746      */
747     long mLastStepStatUserTime;
748     long mLastStepStatSystemTime;
749     long mLastStepStatIOWaitTime;
750     long mLastStepStatIrqTime;
751     long mLastStepStatSoftIrqTime;
752     long mLastStepStatIdleTime;
753     long mCurStepStatUserTime;
754     long mCurStepStatSystemTime;
755     long mCurStepStatIOWaitTime;
756     long mCurStepStatIrqTime;
757     long mCurStepStatSoftIrqTime;
758     long mCurStepStatIdleTime;
759 
760     private HistoryItem mHistoryIterator;
761     private boolean mReadOverflow;
762     private boolean mIteratingHistory;
763 
764     int mStartCount;
765 
766     long mStartClockTime;
767     String mStartPlatformVersion;
768     String mEndPlatformVersion;
769 
770     long mUptime;
771     long mUptimeStart;
772     long mRealtime;
773     long mRealtimeStart;
774 
775     int mWakeLockNesting;
776     boolean mWakeLockImportant;
777     public boolean mRecordAllHistory;
778     boolean mNoAutoReset;
779 
780     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
781     protected int mScreenState = Display.STATE_UNKNOWN;
782     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
783     protected StopwatchTimer mScreenOnTimer;
784     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
785     protected StopwatchTimer mScreenDozeTimer;
786 
787     int mScreenBrightnessBin = -1;
788     final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
789 
790     boolean mPretendScreenOff;
791 
792     boolean mInteractive;
793     StopwatchTimer mInteractiveTimer;
794 
795     boolean mPowerSaveModeEnabled;
796     StopwatchTimer mPowerSaveModeEnabledTimer;
797 
798     boolean mDeviceIdling;
799     StopwatchTimer mDeviceIdlingTimer;
800 
801     boolean mDeviceLightIdling;
802     StopwatchTimer mDeviceLightIdlingTimer;
803 
804     int mDeviceIdleMode;
805     long mLastIdleTimeStart;
806     long mLongestLightIdleTime;
807     long mLongestFullIdleTime;
808     StopwatchTimer mDeviceIdleModeLightTimer;
809     StopwatchTimer mDeviceIdleModeFullTimer;
810 
811     boolean mPhoneOn;
812     StopwatchTimer mPhoneOnTimer;
813 
814     int mAudioOnNesting;
815     StopwatchTimer mAudioOnTimer;
816 
817     int mVideoOnNesting;
818     StopwatchTimer mVideoOnTimer;
819 
820     int mFlashlightOnNesting;
821     StopwatchTimer mFlashlightOnTimer;
822 
823     int mCameraOnNesting;
824     StopwatchTimer mCameraOnTimer;
825 
826     private static final int USB_DATA_UNKNOWN = 0;
827     private static final int USB_DATA_DISCONNECTED = 1;
828     private static final int USB_DATA_CONNECTED = 2;
829     int mUsbDataState = USB_DATA_UNKNOWN;
830 
831     int mGpsSignalQualityBin = -1;
832     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
833     protected final StopwatchTimer[] mGpsSignalQualityTimer =
834         new StopwatchTimer[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
835 
836     int mPhoneSignalStrengthBin = -1;
837     int mPhoneSignalStrengthBinRaw = -1;
838     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
839             new StopwatchTimer[CellSignalStrength.getNumSignalStrengthLevels()];
840 
841     StopwatchTimer mPhoneSignalScanningTimer;
842 
843     int mPhoneDataConnectionType = -1;
844     final StopwatchTimer[] mPhoneDataConnectionsTimer =
845             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
846 
847     final LongSamplingCounter[] mNetworkByteActivityCounters =
848             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
849     final LongSamplingCounter[] mNetworkPacketActivityCounters =
850             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
851 
852     /**
853      * The WiFi Overall wakelock timer
854      * This timer tracks the actual aggregate time for which MC wakelocks are enabled
855      * since addition of per UID timers would not result in an accurate value due to overlapp of
856      * per uid wakelock timers
857      */
858     StopwatchTimer mWifiMulticastWakelockTimer;
859 
860     /**
861      * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
862      */
863     ControllerActivityCounterImpl mWifiActivity;
864 
865     /**
866      * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
867      */
868     ControllerActivityCounterImpl mBluetoothActivity;
869 
870     /**
871      * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
872      */
873     ControllerActivityCounterImpl mModemActivity;
874 
875     /**
876      * Whether the device supports WiFi controller energy reporting. This is set to true on
877      * the first WiFi energy report. See {@link #mWifiActivity}.
878      */
879     boolean mHasWifiReporting = false;
880 
881     /**
882      * Whether the device supports Bluetooth controller energy reporting. This is set to true on
883      * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
884      */
885     boolean mHasBluetoothReporting = false;
886 
887     /**
888      * Whether the device supports Modem controller energy reporting. This is set to true on
889      * the first Modem energy report. See {@link #mModemActivity}.
890      */
891     boolean mHasModemReporting = false;
892 
893     boolean mWifiOn;
894     StopwatchTimer mWifiOnTimer;
895 
896     boolean mGlobalWifiRunning;
897     StopwatchTimer mGlobalWifiRunningTimer;
898 
899     int mWifiState = -1;
900     final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
901 
902     int mWifiSupplState = -1;
903     final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
904 
905     int mWifiSignalStrengthBin = -1;
906     final StopwatchTimer[] mWifiSignalStrengthsTimer =
907             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
908 
909     StopwatchTimer mWifiActiveTimer;
910 
911     int mBluetoothScanNesting;
912     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
913     protected StopwatchTimer mBluetoothScanTimer;
914 
915     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
916     long mMobileRadioActiveStartTime;
917     StopwatchTimer mMobileRadioActiveTimer;
918     StopwatchTimer mMobileRadioActivePerAppTimer;
919     LongSamplingCounter mMobileRadioActiveAdjustedTime;
920     LongSamplingCounter mMobileRadioActiveUnknownTime;
921     LongSamplingCounter mMobileRadioActiveUnknownCount;
922 
923     int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
924 
925     /**
926      * These provide time bases that discount the time the device is plugged
927      * in to power.
928      */
929     boolean mOnBattery;
930     @VisibleForTesting
931     protected boolean mOnBatteryInternal;
932 
933     /**
934      * External reporting of whether the device is actually charging.
935      */
936     boolean mCharging = true;
937     int mLastChargingStateLevel;
938 
939     /*
940      * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
941      */
942     int mDischargeStartLevel;
943     int mDischargeUnplugLevel;
944     int mDischargePlugLevel;
945     int mDischargeCurrentLevel;
946     int mCurrentBatteryLevel;
947     int mLowDischargeAmountSinceCharge;
948     int mHighDischargeAmountSinceCharge;
949     int mDischargeScreenOnUnplugLevel;
950     int mDischargeScreenOffUnplugLevel;
951     int mDischargeScreenDozeUnplugLevel;
952     int mDischargeAmountScreenOn;
953     int mDischargeAmountScreenOnSinceCharge;
954     int mDischargeAmountScreenOff;
955     int mDischargeAmountScreenOffSinceCharge;
956     int mDischargeAmountScreenDoze;
957     int mDischargeAmountScreenDozeSinceCharge;
958 
959     private LongSamplingCounter mDischargeScreenOffCounter;
960     private LongSamplingCounter mDischargeScreenDozeCounter;
961     private LongSamplingCounter mDischargeCounter;
962     private LongSamplingCounter mDischargeLightDozeCounter;
963     private LongSamplingCounter mDischargeDeepDozeCounter;
964 
965     static final int MAX_LEVEL_STEPS = 200;
966 
967     int mInitStepMode = 0;
968     int mCurStepMode = 0;
969     int mModStepMode = 0;
970 
971     int mLastDischargeStepLevel;
972     int mMinDischargeStepLevel;
973     final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
974     final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
975     ArrayList<PackageChange> mDailyPackageChanges;
976 
977     int mLastChargeStepLevel;
978     int mMaxChargeStepLevel;
979     final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
980     final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
981 
982     static final int MAX_DAILY_ITEMS = 10;
983 
984     long mDailyStartTime = 0;
985     long mNextMinDailyDeadline = 0;
986     long mNextMaxDailyDeadline = 0;
987 
988     final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
989 
990     long mLastWriteTime = 0; // Milliseconds
991 
992     private int mPhoneServiceState = -1;
993     private int mPhoneServiceStateRaw = -1;
994     private int mPhoneSimStateRaw = -1;
995 
996     private int mNumConnectivityChange;
997 
998     private int mEstimatedBatteryCapacity = -1;
999 
1000     private int mMinLearnedBatteryCapacity = -1;
1001     private int mMaxLearnedBatteryCapacity = -1;
1002 
1003     private long mBatteryTimeToFullSeconds = -1;
1004 
1005     private long[] mCpuFreqs;
1006 
1007     @VisibleForTesting
1008     protected PowerProfile mPowerProfile;
1009 
1010     @GuardedBy("this")
1011     final Constants mConstants;
1012 
1013     /*
1014      * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
1015      * recording their times when on-battery (regardless of screen state).
1016      */
1017     private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>();
1018     /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */
1019     private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>();
1020 
1021     @Override
getRpmStats()1022     public Map<String, ? extends Timer> getRpmStats() {
1023         return mRpmStats;
1024     }
1025 
1026     // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED.
1027     @Override
getScreenOffRpmStats()1028     public Map<String, ? extends Timer> getScreenOffRpmStats() {
1029         return mScreenOffRpmStats;
1030     }
1031 
1032     /*
1033      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
1034      */
1035     private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
1036 
1037     @UnsupportedAppUsage
getKernelWakelockStats()1038     public Map<String, ? extends Timer> getKernelWakelockStats() {
1039         return mKernelWakelockStats;
1040     }
1041 
1042     String mLastWakeupReason = null;
1043     long mLastWakeupUptimeMs = 0;
1044     private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
1045 
getWakeupReasonStats()1046     public Map<String, ? extends Timer> getWakeupReasonStats() {
1047         return mWakeupReasonStats;
1048     }
1049 
1050     @Override
getUahDischarge(int which)1051     public long getUahDischarge(int which) {
1052         return mDischargeCounter.getCountLocked(which);
1053     }
1054 
1055     @Override
getUahDischargeScreenOff(int which)1056     public long getUahDischargeScreenOff(int which) {
1057         return mDischargeScreenOffCounter.getCountLocked(which);
1058     }
1059 
1060     @Override
getUahDischargeScreenDoze(int which)1061     public long getUahDischargeScreenDoze(int which) {
1062         return mDischargeScreenDozeCounter.getCountLocked(which);
1063     }
1064 
1065     @Override
getUahDischargeLightDoze(int which)1066     public long getUahDischargeLightDoze(int which) {
1067         return mDischargeLightDozeCounter.getCountLocked(which);
1068     }
1069 
1070     @Override
getUahDischargeDeepDoze(int which)1071     public long getUahDischargeDeepDoze(int which) {
1072         return mDischargeDeepDozeCounter.getCountLocked(which);
1073     }
1074 
1075     @Override
getEstimatedBatteryCapacity()1076     public int getEstimatedBatteryCapacity() {
1077         return mEstimatedBatteryCapacity;
1078     }
1079 
1080     @Override
getMinLearnedBatteryCapacity()1081     public int getMinLearnedBatteryCapacity() {
1082         return mMinLearnedBatteryCapacity;
1083     }
1084 
1085     @Override
getMaxLearnedBatteryCapacity()1086     public int getMaxLearnedBatteryCapacity() {
1087         return mMaxLearnedBatteryCapacity;
1088     }
1089 
BatteryStatsImpl()1090     public BatteryStatsImpl() {
1091         this(new SystemClocks());
1092     }
1093 
BatteryStatsImpl(Clocks clocks)1094     public BatteryStatsImpl(Clocks clocks) {
1095         init(clocks);
1096         mStatsFile = null;
1097         mCheckinFile = null;
1098         mDailyFile = null;
1099         mBatteryStatsHistory = null;
1100         mHandler = null;
1101         mPlatformIdleStateCallback = null;
1102         mRailEnergyDataCallback = null;
1103         mUserInfoProvider = null;
1104         mConstants = new Constants(mHandler);
1105         clearHistoryLocked();
1106     }
1107 
init(Clocks clocks)1108     private void init(Clocks clocks) {
1109         mClocks = clocks;
1110     }
1111 
1112     /**
1113      * TimeBase observer.
1114      */
1115     public interface TimeBaseObs {
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)1116         void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1117         void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
1118 
1119         /**
1120          * Reset the observer's state, returns true if the timer/counter is inactive
1121          * so it can be destroyed.
1122          * @param detachIfReset detach if true, no-op if false.
1123          * @return Returns true if the timer/counter is inactive and can be destroyed.
1124          */
reset(boolean detachIfReset)1125         boolean reset(boolean detachIfReset);
1126         /**
1127          * Detach the observer from TimeBase.
1128          */
detach()1129         void detach();
1130     }
1131 
1132     // methods are protected not private to be VisibleForTesting
1133     public static class TimeBase {
1134         protected final Collection<TimeBaseObs> mObservers;
1135         protected long mUptime;
1136         protected long mRealtime;
1137 
1138         protected boolean mRunning;
1139 
1140         protected long mPastUptime;
1141         protected long mUptimeStart;
1142         protected long mPastRealtime;
1143         protected long mRealtimeStart;
1144         protected long mUnpluggedUptime;
1145         protected long mUnpluggedRealtime;
1146 
dump(PrintWriter pw, String prefix)1147         public void dump(PrintWriter pw, String prefix) {
1148             StringBuilder sb = new StringBuilder(128);
1149             pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
1150             sb.setLength(0);
1151             sb.append(prefix);
1152                     sb.append("mUptime=");
1153                     formatTimeMs(sb, mUptime / 1000);
1154             pw.println(sb.toString());
1155             sb.setLength(0);
1156             sb.append(prefix);
1157                     sb.append("mRealtime=");
1158                     formatTimeMs(sb, mRealtime / 1000);
1159             pw.println(sb.toString());
1160             sb.setLength(0);
1161             sb.append(prefix);
1162                     sb.append("mPastUptime=");
1163                     formatTimeMs(sb, mPastUptime / 1000); sb.append("mUptimeStart=");
1164                     formatTimeMs(sb, mUptimeStart / 1000);
1165                     sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptime / 1000);
1166             pw.println(sb.toString());
1167             sb.setLength(0);
1168             sb.append(prefix);
1169                     sb.append("mPastRealtime=");
1170                     formatTimeMs(sb, mPastRealtime / 1000); sb.append("mRealtimeStart=");
1171                     formatTimeMs(sb, mRealtimeStart / 1000);
1172                     sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000);
1173             pw.println(sb.toString());
1174         }
1175         /**
1176          * The mObservers of TimeBase in BatteryStatsImpl object can contain up to 20k entries.
1177          * The mObservers of TimeBase in BatteryStatsImpl.Uid object only contains a few or tens of
1178          * entries.
1179          * mObservers must have good performance on add(), remove(), also be memory efficient.
1180          * This is why we provide isLongList parameter for long and short list user cases.
1181          * @param isLongList If true, use HashSet for mObservers list.
1182          *                   If false, use ArrayList for mObservers list.
1183         */
TimeBase(boolean isLongList)1184         public TimeBase(boolean isLongList) {
1185             mObservers = isLongList ? new HashSet<>() : new ArrayList<>();
1186         }
1187 
TimeBase()1188         public TimeBase() {
1189             this(false);
1190         }
1191 
add(TimeBaseObs observer)1192         public void add(TimeBaseObs observer) {
1193             mObservers.add(observer);
1194         }
1195 
remove(TimeBaseObs observer)1196         public void remove(TimeBaseObs observer) {
1197             mObservers.remove(observer);
1198         }
1199 
hasObserver(TimeBaseObs observer)1200         public boolean hasObserver(TimeBaseObs observer) {
1201             return mObservers.contains(observer);
1202         }
1203 
init(long uptime, long realtime)1204         public void init(long uptime, long realtime) {
1205             mRealtime = 0;
1206             mUptime = 0;
1207             mPastUptime = 0;
1208             mPastRealtime = 0;
1209             mUptimeStart = uptime;
1210             mRealtimeStart = realtime;
1211             mUnpluggedUptime = getUptime(mUptimeStart);
1212             mUnpluggedRealtime = getRealtime(mRealtimeStart);
1213         }
1214 
reset(long uptime, long realtime)1215         public void reset(long uptime, long realtime) {
1216             if (!mRunning) {
1217                 mPastUptime = 0;
1218                 mPastRealtime = 0;
1219             } else {
1220                 mUptimeStart = uptime;
1221                 mRealtimeStart = realtime;
1222                 // TODO: Since mUptimeStart was just reset and we are running, getUptime will
1223                 // just return mPastUptime. Also, are we sure we don't want to reset that?
1224                 mUnpluggedUptime = getUptime(uptime);
1225                 // TODO: likewise.
1226                 mUnpluggedRealtime = getRealtime(realtime);
1227             }
1228         }
1229 
computeUptime(long curTime, int which)1230         public long computeUptime(long curTime, int which) {
1231             return mUptime + getUptime(curTime);
1232         }
1233 
computeRealtime(long curTime, int which)1234         public long computeRealtime(long curTime, int which) {
1235             return mRealtime + getRealtime(curTime);
1236         }
1237 
getUptime(long curTime)1238         public long getUptime(long curTime) {
1239             long time = mPastUptime;
1240             if (mRunning) {
1241                 time += curTime - mUptimeStart;
1242             }
1243             return time;
1244         }
1245 
getRealtime(long curTime)1246         public long getRealtime(long curTime) {
1247             long time = mPastRealtime;
1248             if (mRunning) {
1249                 time += curTime - mRealtimeStart;
1250             }
1251             return time;
1252         }
1253 
getUptimeStart()1254         public long getUptimeStart() {
1255             return mUptimeStart;
1256         }
1257 
getRealtimeStart()1258         public long getRealtimeStart() {
1259             return mRealtimeStart;
1260         }
1261 
isRunning()1262         public boolean isRunning() {
1263             return mRunning;
1264         }
1265 
setRunning(boolean running, long uptime, long realtime)1266         public boolean setRunning(boolean running, long uptime, long realtime) {
1267             if (mRunning != running) {
1268                 mRunning = running;
1269                 if (running) {
1270                     mUptimeStart = uptime;
1271                     mRealtimeStart = realtime;
1272                     long batteryUptime = mUnpluggedUptime = getUptime(uptime);
1273                     long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime);
1274                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
1275                     // Iterator object, here is an exception because mObservers' type is Collection
1276                     // instead of list.
1277                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
1278                     while (iter.hasNext()) {
1279                         iter.next().onTimeStarted(realtime, batteryUptime, batteryRealtime);
1280                     }
1281                 } else {
1282                     mPastUptime += uptime - mUptimeStart;
1283                     mPastRealtime += realtime - mRealtimeStart;
1284                     long batteryUptime = getUptime(uptime);
1285                     long batteryRealtime = getRealtime(realtime);
1286                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
1287                     // Iterator object, here is an exception because mObservers' type is Collection
1288                     // instead of list.
1289                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
1290                     while (iter.hasNext()) {
1291                         iter.next().onTimeStopped(realtime, batteryUptime, batteryRealtime);
1292                     }
1293                 }
1294                 return true;
1295             }
1296             return false;
1297         }
1298 
readSummaryFromParcel(Parcel in)1299         public void readSummaryFromParcel(Parcel in) {
1300             mUptime = in.readLong();
1301             mRealtime = in.readLong();
1302         }
1303 
writeSummaryToParcel(Parcel out, long uptime, long realtime)1304         public void writeSummaryToParcel(Parcel out, long uptime, long realtime) {
1305             out.writeLong(computeUptime(uptime, STATS_SINCE_CHARGED));
1306             out.writeLong(computeRealtime(realtime, STATS_SINCE_CHARGED));
1307         }
1308 
readFromParcel(Parcel in)1309         public void readFromParcel(Parcel in) {
1310             mRunning = false;
1311             mUptime = in.readLong();
1312             mPastUptime = in.readLong();
1313             mUptimeStart = in.readLong();
1314             mRealtime = in.readLong();
1315             mPastRealtime = in.readLong();
1316             mRealtimeStart = in.readLong();
1317             mUnpluggedUptime = in.readLong();
1318             mUnpluggedRealtime = in.readLong();
1319         }
1320 
writeToParcel(Parcel out, long uptime, long realtime)1321         public void writeToParcel(Parcel out, long uptime, long realtime) {
1322             final long runningUptime = getUptime(uptime);
1323             final long runningRealtime = getRealtime(realtime);
1324             out.writeLong(mUptime);
1325             out.writeLong(runningUptime);
1326             out.writeLong(mUptimeStart);
1327             out.writeLong(mRealtime);
1328             out.writeLong(runningRealtime);
1329             out.writeLong(mRealtimeStart);
1330             out.writeLong(mUnpluggedUptime);
1331             out.writeLong(mUnpluggedRealtime);
1332         }
1333     }
1334 
1335     /**
1336      * State for keeping track of counting information.
1337      */
1338     public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
1339         @UnsupportedAppUsage
1340         final AtomicInteger mCount = new AtomicInteger();
1341         final TimeBase mTimeBase;
1342 
Counter(TimeBase timeBase, Parcel in)1343         public Counter(TimeBase timeBase, Parcel in) {
1344             mTimeBase = timeBase;
1345             mCount.set(in.readInt());
1346             timeBase.add(this);
1347         }
1348 
Counter(TimeBase timeBase)1349         public Counter(TimeBase timeBase) {
1350             mTimeBase = timeBase;
1351             timeBase.add(this);
1352         }
1353 
writeToParcel(Parcel out)1354         public void writeToParcel(Parcel out) {
1355             out.writeInt(mCount.get());
1356         }
1357 
1358         @Override
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)1359         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1360         }
1361 
1362         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1363         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1364         }
1365 
1366         /**
1367          * Writes a possibly null Counter to a Parcel.
1368          *
1369          * @param out the Parcel to be written to.
1370          * @param counter a Counter, or null.
1371          */
writeCounterToParcel(Parcel out, @Nullable Counter counter)1372         public static void writeCounterToParcel(Parcel out, @Nullable Counter counter) {
1373             if (counter == null) {
1374                 out.writeInt(0); // indicates null
1375                 return;
1376             }
1377             out.writeInt(1); // indicates non-null
1378 
1379             counter.writeToParcel(out);
1380         }
1381 
1382         /**
1383          * Reads a Counter that was written using {@link #writeCounterToParcel(Parcel, Counter)}.
1384          * @param timeBase the timebase to assign to the Counter
1385          * @param in the parcel to read from
1386          * @return the Counter or null.
1387          */
readCounterFromParcel(TimeBase timeBase, Parcel in)1388         public static @Nullable Counter readCounterFromParcel(TimeBase timeBase, Parcel in) {
1389             if (in.readInt() == 0) {
1390                 return null;
1391             }
1392             return new Counter(timeBase, in);
1393         }
1394 
1395         @Override
getCountLocked(int which)1396         public int getCountLocked(int which) {
1397             return mCount.get();
1398         }
1399 
logState(Printer pw, String prefix)1400         public void logState(Printer pw, String prefix) {
1401             pw.println(prefix + "mCount=" + mCount.get());
1402         }
1403 
1404         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
stepAtomic()1405         public void stepAtomic() {
1406             if (mTimeBase.isRunning()) {
1407                 mCount.incrementAndGet();
1408             }
1409         }
1410 
addAtomic(int delta)1411         void addAtomic(int delta) {
1412             if (mTimeBase.isRunning()) {
1413                 mCount.addAndGet(delta);
1414             }
1415         }
1416 
1417         /**
1418          * Clear state of this counter.
1419          */
1420         @Override
reset(boolean detachIfReset)1421         public boolean reset(boolean detachIfReset) {
1422             mCount.set(0);
1423             if (detachIfReset) {
1424                 detach();
1425             }
1426             return true;
1427         }
1428 
1429         @Override
detach()1430         public void detach() {
1431             mTimeBase.remove(this);
1432         }
1433 
1434         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
writeSummaryFromParcelLocked(Parcel out)1435         public void writeSummaryFromParcelLocked(Parcel out) {
1436             out.writeInt(mCount.get());
1437         }
1438 
1439         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
readSummaryFromParcelLocked(Parcel in)1440         public void readSummaryFromParcelLocked(Parcel in) {
1441             mCount.set(in.readInt());
1442         }
1443     }
1444 
1445     @VisibleForTesting
1446     public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
1447         final TimeBase mTimeBase;
1448         public long[] mCounts;
1449 
LongSamplingCounterArray(TimeBase timeBase, Parcel in)1450         private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
1451             mTimeBase = timeBase;
1452             mCounts = in.createLongArray();
1453             timeBase.add(this);
1454         }
1455 
LongSamplingCounterArray(TimeBase timeBase)1456         public LongSamplingCounterArray(TimeBase timeBase) {
1457             mTimeBase = timeBase;
1458             timeBase.add(this);
1459         }
1460 
writeToParcel(Parcel out)1461         private void writeToParcel(Parcel out) {
1462             out.writeLongArray(mCounts);
1463         }
1464 
1465         @Override
onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime)1466         public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) {
1467         }
1468 
1469         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1470         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1471         }
1472 
1473         @Override
getCountsLocked(int which)1474         public long[] getCountsLocked(int which) {
1475             return mCounts == null ? null : Arrays.copyOf(mCounts, mCounts.length);
1476         }
1477 
1478         @Override
logState(Printer pw, String prefix)1479         public void logState(Printer pw, String prefix) {
1480             pw.println(prefix + "mCounts=" + Arrays.toString(mCounts));
1481         }
1482 
addCountLocked(long[] counts)1483         public void addCountLocked(long[] counts) {
1484             addCountLocked(counts, mTimeBase.isRunning());
1485         }
1486 
addCountLocked(long[] counts, boolean isRunning)1487         public void addCountLocked(long[] counts, boolean isRunning) {
1488             if (counts == null) {
1489                 return;
1490             }
1491             if (isRunning) {
1492                 if (mCounts == null) {
1493                     mCounts = new long[counts.length];
1494                 }
1495                 for (int i = 0; i < counts.length; ++i) {
1496                     mCounts[i] += counts[i];
1497                 }
1498             }
1499         }
1500 
getSize()1501         public int getSize() {
1502             return mCounts == null ? 0 : mCounts.length;
1503         }
1504 
1505         /**
1506          * Clear state of this counter.
1507          */
1508         @Override
reset(boolean detachIfReset)1509         public boolean reset(boolean detachIfReset) {
1510             if (mCounts != null) {
1511                 Arrays.fill(mCounts, 0);
1512             }
1513             if (detachIfReset) {
1514                 detach();
1515             }
1516             return true;
1517         }
1518 
1519         @Override
detach()1520         public void detach() {
1521             mTimeBase.remove(this);
1522         }
1523 
writeSummaryToParcelLocked(Parcel out)1524         private void writeSummaryToParcelLocked(Parcel out) {
1525             out.writeLongArray(mCounts);
1526         }
1527 
readSummaryFromParcelLocked(Parcel in)1528         private void readSummaryFromParcelLocked(Parcel in) {
1529             mCounts = in.createLongArray();
1530         }
1531 
writeToParcel(Parcel out, LongSamplingCounterArray counterArray)1532         public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
1533             if (counterArray != null) {
1534                 out.writeInt(1);
1535                 counterArray.writeToParcel(out);
1536             } else {
1537                 out.writeInt(0);
1538             }
1539         }
1540 
readFromParcel(Parcel in, TimeBase timeBase)1541         public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
1542             if (in.readInt() != 0) {
1543                 return new LongSamplingCounterArray(timeBase, in);
1544             } else {
1545                 return null;
1546             }
1547         }
1548 
writeSummaryToParcelLocked(Parcel out, LongSamplingCounterArray counterArray)1549         public static void writeSummaryToParcelLocked(Parcel out,
1550                 LongSamplingCounterArray counterArray) {
1551             if (counterArray != null) {
1552                 out.writeInt(1);
1553                 counterArray.writeSummaryToParcelLocked(out);
1554             } else {
1555                 out.writeInt(0);
1556             }
1557         }
1558 
readSummaryFromParcelLocked(Parcel in, TimeBase timeBase)1559         public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
1560                 TimeBase timeBase) {
1561             if (in.readInt() != 0) {
1562                 final LongSamplingCounterArray counterArray
1563                         = new LongSamplingCounterArray(timeBase);
1564                 counterArray.readSummaryFromParcelLocked(in);
1565                 return counterArray;
1566             } else {
1567                 return null;
1568             }
1569         }
1570     }
1571 
1572     @VisibleForTesting
1573     public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
1574         final TimeBase mTimeBase;
1575         private long mCount;
1576 
LongSamplingCounter(TimeBase timeBase, Parcel in)1577         public LongSamplingCounter(TimeBase timeBase, Parcel in) {
1578             mTimeBase = timeBase;
1579             mCount = in.readLong();
1580             timeBase.add(this);
1581         }
1582 
LongSamplingCounter(TimeBase timeBase)1583         public LongSamplingCounter(TimeBase timeBase) {
1584             mTimeBase = timeBase;
1585             timeBase.add(this);
1586         }
1587 
writeToParcel(Parcel out)1588         public void writeToParcel(Parcel out) {
1589             out.writeLong(mCount);
1590         }
1591 
1592         @Override
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)1593         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1594         }
1595 
1596         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1597         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1598         }
1599 
getCountLocked(int which)1600         public long getCountLocked(int which) {
1601             return mCount;
1602         }
1603 
1604         @Override
logState(Printer pw, String prefix)1605         public void logState(Printer pw, String prefix) {
1606             pw.println(prefix + "mCount=" + mCount);
1607         }
1608 
addCountLocked(long count)1609         public void addCountLocked(long count) {
1610             addCountLocked(count, mTimeBase.isRunning());
1611         }
1612 
addCountLocked(long count, boolean isRunning)1613         public void addCountLocked(long count, boolean isRunning) {
1614             if (isRunning) {
1615                 mCount += count;
1616             }
1617         }
1618 
1619         /**
1620          * Clear state of this counter.
1621          */
1622         @Override
reset(boolean detachIfReset)1623         public boolean reset(boolean detachIfReset) {
1624             mCount = 0;
1625             if (detachIfReset) {
1626                 detach();
1627             }
1628             return true;
1629         }
1630 
1631         @Override
detach()1632         public void detach() {
1633             mTimeBase.remove(this);
1634         }
1635 
writeSummaryFromParcelLocked(Parcel out)1636         public void writeSummaryFromParcelLocked(Parcel out) {
1637             out.writeLong(mCount);
1638         }
1639 
readSummaryFromParcelLocked(Parcel in)1640         public void readSummaryFromParcelLocked(Parcel in) {
1641             mCount = in.readLong();
1642         }
1643     }
1644 
1645     /**
1646      * State for keeping track of timing information.
1647      */
1648     public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
1649         protected final Clocks mClocks;
1650         protected final int mType;
1651         protected final TimeBase mTimeBase;
1652 
1653         protected int mCount;
1654 
1655         // Times are in microseconds for better accuracy when dividing by the
1656         // lock count, and are in "battery realtime" units.
1657 
1658         /**
1659          * The total time we have accumulated since the start of the original
1660          * boot, to the last time something interesting happened in the
1661          * current run.
1662          */
1663         protected long mTotalTime;
1664 
1665         /**
1666          * The total time this timer has been running until the latest mark has been set.
1667          * Subtract this from mTotalTime to get the time spent running since the mark was set.
1668          */
1669         protected long mTimeBeforeMark;
1670 
1671         /**
1672          * Constructs from a parcel.
1673          * @param type
1674          * @param timeBase
1675          * @param in
1676          */
Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in)1677         public Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in) {
1678             mClocks = clocks;
1679             mType = type;
1680             mTimeBase = timeBase;
1681 
1682             mCount = in.readInt();
1683             mTotalTime = in.readLong();
1684             mTimeBeforeMark = in.readLong();
1685             timeBase.add(this);
1686             if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTime);
1687         }
1688 
Timer(Clocks clocks, int type, TimeBase timeBase)1689         public Timer(Clocks clocks, int type, TimeBase timeBase) {
1690             mClocks = clocks;
1691             mType = type;
1692             mTimeBase = timeBase;
1693             timeBase.add(this);
1694         }
1695 
writeToParcel(Parcel out, long elapsedRealtimeUs)1696         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1697             if (DEBUG) {
1698                 Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
1699                         + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
1700             }
1701             out.writeInt(computeCurrentCountLocked());
1702             out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
1703             out.writeLong(mTimeBeforeMark);
1704         }
1705 
computeRunTimeLocked(long curBatteryRealtime)1706         protected abstract long computeRunTimeLocked(long curBatteryRealtime);
1707 
computeCurrentCountLocked()1708         protected abstract int computeCurrentCountLocked();
1709 
1710         /**
1711          * Clear state of this timer.  Returns true if the timer is inactive
1712          * so can be completely dropped.
1713          */
1714         @Override
reset(boolean detachIfReset)1715         public boolean reset(boolean detachIfReset) {
1716             mTotalTime = mTimeBeforeMark = 0;
1717             mCount = 0;
1718             if (detachIfReset) {
1719                 detach();
1720             }
1721             return true;
1722         }
1723 
1724         @Override
detach()1725         public void detach() {
1726             mTimeBase.remove(this);
1727         }
1728 
1729         @Override
onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime)1730         public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) {
1731         }
1732 
1733         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1734         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1735             if (DEBUG && mType < 0) {
1736                 Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtime
1737                         + " old mTotalTime=" + mTotalTime);
1738             }
1739             mTotalTime = computeRunTimeLocked(baseRealtime);
1740             mCount = computeCurrentCountLocked();
1741             if (DEBUG && mType < 0) {
1742                 Log.v(TAG, "plug #" + mType + ": new mTotalTime=" + mTotalTime);
1743             }
1744         }
1745 
1746         /**
1747          * Writes a possibly null Timer to a Parcel.
1748          *
1749          * @param out the Parcel to be written to.
1750          * @param timer a Timer, or null.
1751          */
1752         @UnsupportedAppUsage
writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs)1753         public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
1754             if (timer == null) {
1755                 out.writeInt(0); // indicates null
1756                 return;
1757             }
1758             out.writeInt(1); // indicates non-null
1759             timer.writeToParcel(out, elapsedRealtimeUs);
1760         }
1761 
1762         @Override
1763         @UnsupportedAppUsage
getTotalTimeLocked(long elapsedRealtimeUs, int which)1764         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
1765             return computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1766         }
1767 
1768         @Override
1769         @UnsupportedAppUsage
getCountLocked(int which)1770         public int getCountLocked(int which) {
1771             return computeCurrentCountLocked();
1772         }
1773 
1774         @Override
getTimeSinceMarkLocked(long elapsedRealtimeUs)1775         public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
1776             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1777             return val - mTimeBeforeMark;
1778         }
1779 
1780         @Override
logState(Printer pw, String prefix)1781         public void logState(Printer pw, String prefix) {
1782             pw.println(prefix + "mCount=" + mCount);
1783             pw.println(prefix + "mTotalTime=" + mTotalTime);
1784         }
1785 
1786 
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)1787         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
1788             long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1789             out.writeLong(runTime);
1790             out.writeInt(computeCurrentCountLocked());
1791         }
1792 
readSummaryFromParcelLocked(Parcel in)1793         public void readSummaryFromParcelLocked(Parcel in) {
1794             // Multiply by 1000 for backwards compatibility
1795             mTotalTime = in.readLong();
1796             mCount = in.readInt();
1797             // When reading the summary, we set the mark to be the latest information.
1798             mTimeBeforeMark = mTotalTime;
1799         }
1800     }
1801 
1802     /**
1803      * A counter meant to accept monotonically increasing values to its {@link #update(long, int)}
1804      * method. The state of the timer according to its {@link TimeBase} will determine how much
1805      * of the value is recorded.
1806      *
1807      * If the value being recorded resets, {@link #endSample()} can be called in order to
1808      * account for the change. If the value passed in to {@link #update(long, int)} decreased
1809      * between calls, the {@link #endSample()} is automatically called and the new value is
1810      * expected to increase monotonically from that point on.
1811      */
1812     public static class SamplingTimer extends Timer {
1813 
1814         /**
1815          * The most recent reported count from /proc/wakelocks.
1816          */
1817         int mCurrentReportedCount;
1818 
1819         /**
1820          * The reported count from /proc/wakelocks when unplug() was last
1821          * called.
1822          */
1823         int mUnpluggedReportedCount;
1824 
1825         /**
1826          * The most recent reported total_time from /proc/wakelocks.
1827          */
1828         long mCurrentReportedTotalTime;
1829 
1830 
1831         /**
1832          * The reported total_time from /proc/wakelocks when unplug() was last
1833          * called.
1834          */
1835         long mUnpluggedReportedTotalTime;
1836 
1837         /**
1838          * Whether we are currently in a discharge cycle.
1839          */
1840         boolean mTimeBaseRunning;
1841 
1842         /**
1843          * Whether we are currently recording reported values.
1844          */
1845         boolean mTrackingReportedValues;
1846 
1847         /*
1848          * A sequence counter, incremented once for each update of the stats.
1849          */
1850         int mUpdateVersion;
1851 
1852         @VisibleForTesting
SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in)1853         public SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in) {
1854             super(clocks, 0, timeBase, in);
1855             mCurrentReportedCount = in.readInt();
1856             mUnpluggedReportedCount = in.readInt();
1857             mCurrentReportedTotalTime = in.readLong();
1858             mUnpluggedReportedTotalTime = in.readLong();
1859             mTrackingReportedValues = in.readInt() == 1;
1860             mTimeBaseRunning = timeBase.isRunning();
1861         }
1862 
1863         @VisibleForTesting
SamplingTimer(Clocks clocks, TimeBase timeBase)1864         public SamplingTimer(Clocks clocks, TimeBase timeBase) {
1865             super(clocks, 0, timeBase);
1866             mTrackingReportedValues = false;
1867             mTimeBaseRunning = timeBase.isRunning();
1868         }
1869 
1870         /**
1871          * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to
1872          * be less than the values used for a previous invocation.
1873          */
endSample()1874         public void endSample() {
1875             mTotalTime = computeRunTimeLocked(0 /* unused by us */);
1876             mCount = computeCurrentCountLocked();
1877             mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = 0;
1878             mUnpluggedReportedCount = mCurrentReportedCount = 0;
1879             mTrackingReportedValues = false;
1880         }
1881 
setUpdateVersion(int version)1882         public void setUpdateVersion(int version) {
1883             mUpdateVersion = version;
1884         }
1885 
getUpdateVersion()1886         public int getUpdateVersion() {
1887             return mUpdateVersion;
1888         }
1889 
1890         /**
1891          * Updates the current recorded values. These are meant to be monotonically increasing
1892          * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}.
1893          *
1894          * If the values being recorded have been reset, the monotonically increasing requirement
1895          * will be broken. In this case, {@link #endSample()} is automatically called and
1896          * the total value of totalTime and count are recorded, starting a new monotonically
1897          * increasing sample.
1898          *
1899          * @param totalTime total time of sample in microseconds.
1900          * @param count total number of times the event being sampled occurred.
1901          */
update(long totalTime, int count)1902         public void update(long totalTime, int count) {
1903             if (mTimeBaseRunning && !mTrackingReportedValues) {
1904                 // Updating the reported value for the first time.
1905                 mUnpluggedReportedTotalTime = totalTime;
1906                 mUnpluggedReportedCount = count;
1907             }
1908 
1909             mTrackingReportedValues = true;
1910 
1911             if (totalTime < mCurrentReportedTotalTime || count < mCurrentReportedCount) {
1912                 endSample();
1913             }
1914 
1915             mCurrentReportedTotalTime = totalTime;
1916             mCurrentReportedCount = count;
1917         }
1918 
1919         /**
1920          * Adds deltaTime and deltaCount to the current sample.
1921          *
1922          * @param deltaTime additional time recorded since the last sampled event, in microseconds.
1923          * @param deltaCount additional number of times the event being sampled occurred.
1924          */
add(long deltaTime, int deltaCount)1925         public void add(long deltaTime, int deltaCount) {
1926             update(mCurrentReportedTotalTime + deltaTime, mCurrentReportedCount + deltaCount);
1927         }
1928 
1929         @Override
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)1930         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1931             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
1932             if (mTrackingReportedValues) {
1933                 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
1934                 mUnpluggedReportedCount = mCurrentReportedCount;
1935             }
1936             mTimeBaseRunning = true;
1937         }
1938 
1939         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1940         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1941             super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
1942             mTimeBaseRunning = false;
1943         }
1944 
1945         @Override
logState(Printer pw, String prefix)1946         public void logState(Printer pw, String prefix) {
1947             super.logState(pw, prefix);
1948             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
1949                     + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
1950                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
1951                     + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
1952         }
1953 
1954         @Override
computeRunTimeLocked(long curBatteryRealtime)1955         protected long computeRunTimeLocked(long curBatteryRealtime) {
1956             return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues
1957                     ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
1958         }
1959 
1960         @Override
computeCurrentCountLocked()1961         protected int computeCurrentCountLocked() {
1962             return mCount + (mTimeBaseRunning && mTrackingReportedValues
1963                     ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
1964         }
1965 
1966         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)1967         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1968             super.writeToParcel(out, elapsedRealtimeUs);
1969             out.writeInt(mCurrentReportedCount);
1970             out.writeInt(mUnpluggedReportedCount);
1971             out.writeLong(mCurrentReportedTotalTime);
1972             out.writeLong(mUnpluggedReportedTotalTime);
1973             out.writeInt(mTrackingReportedValues ? 1 : 0);
1974         }
1975 
1976         @Override
reset(boolean detachIfReset)1977         public boolean reset(boolean detachIfReset) {
1978             super.reset(detachIfReset);
1979             mTrackingReportedValues = false;
1980             mUnpluggedReportedTotalTime = 0;
1981             mUnpluggedReportedCount = 0;
1982             return true;
1983         }
1984     }
1985 
1986     /**
1987      * A timer that increments in batches.  It does not run for durations, but just jumps
1988      * for a pre-determined amount.
1989      */
1990     public static class BatchTimer extends Timer {
1991         final Uid mUid;
1992 
1993         /**
1994          * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
1995          */
1996         long mLastAddedTime;
1997 
1998         /**
1999          * The last duration that we added to the timer.  This is in microseconds.
2000          */
2001         long mLastAddedDuration;
2002 
2003         /**
2004          * Whether we are currently in a discharge cycle.
2005          */
2006         boolean mInDischarge;
2007 
BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in)2008         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in) {
2009             super(clocks, type, timeBase, in);
2010             mUid = uid;
2011             mLastAddedTime = in.readLong();
2012             mLastAddedDuration = in.readLong();
2013             mInDischarge = timeBase.isRunning();
2014         }
2015 
BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase)2016         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase) {
2017             super(clocks, type, timeBase);
2018             mUid = uid;
2019             mInDischarge = timeBase.isRunning();
2020         }
2021 
2022         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2023         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2024             super.writeToParcel(out, elapsedRealtimeUs);
2025             out.writeLong(mLastAddedTime);
2026             out.writeLong(mLastAddedDuration);
2027         }
2028 
2029         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)2030         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
2031             recomputeLastDuration(mClocks.elapsedRealtime() * 1000, false);
2032             mInDischarge = false;
2033             super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
2034         }
2035 
2036         @Override
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)2037         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
2038             recomputeLastDuration(elapsedRealtime, false);
2039             mInDischarge = true;
2040             // If we are still within the last added duration, then re-added whatever remains.
2041             if (mLastAddedTime == elapsedRealtime) {
2042                 mTotalTime += mLastAddedDuration;
2043             }
2044             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
2045         }
2046 
2047         @Override
logState(Printer pw, String prefix)2048         public void logState(Printer pw, String prefix) {
2049             super.logState(pw, prefix);
2050             pw.println(prefix + "mLastAddedTime=" + mLastAddedTime
2051                     + " mLastAddedDuration=" + mLastAddedDuration);
2052         }
2053 
computeOverage(long curTime)2054         private long computeOverage(long curTime) {
2055             if (mLastAddedTime > 0) {
2056                 return mLastAddedDuration - curTime;
2057             }
2058             return 0;
2059         }
2060 
recomputeLastDuration(long curTime, boolean abort)2061         private void recomputeLastDuration(long curTime, boolean abort) {
2062             final long overage = computeOverage(curTime);
2063             if (overage > 0) {
2064                 // Aborting before the duration ran out -- roll back the remaining
2065                 // duration.  Only do this if currently discharging; otherwise we didn't
2066                 // actually add the time.
2067                 if (mInDischarge) {
2068                     mTotalTime -= overage;
2069                 }
2070                 if (abort) {
2071                     mLastAddedTime = 0;
2072                 } else {
2073                     mLastAddedTime = curTime;
2074                     mLastAddedDuration -= overage;
2075                 }
2076             }
2077         }
2078 
addDuration(BatteryStatsImpl stats, long durationMillis)2079         public void addDuration(BatteryStatsImpl stats, long durationMillis) {
2080             final long now = mClocks.elapsedRealtime() * 1000;
2081             recomputeLastDuration(now, true);
2082             mLastAddedTime = now;
2083             mLastAddedDuration = durationMillis * 1000;
2084             if (mInDischarge) {
2085                 mTotalTime += mLastAddedDuration;
2086                 mCount++;
2087             }
2088         }
2089 
abortLastDuration(BatteryStatsImpl stats)2090         public void abortLastDuration(BatteryStatsImpl stats) {
2091             final long now = mClocks.elapsedRealtime() * 1000;
2092             recomputeLastDuration(now, true);
2093         }
2094 
2095         @Override
computeCurrentCountLocked()2096         protected int computeCurrentCountLocked() {
2097             return mCount;
2098         }
2099 
2100         @Override
computeRunTimeLocked(long curBatteryRealtime)2101         protected long computeRunTimeLocked(long curBatteryRealtime) {
2102             final long overage = computeOverage(mClocks.elapsedRealtime() * 1000);
2103             if (overage > 0) {
2104                 return mTotalTime = overage;
2105             }
2106             return mTotalTime;
2107         }
2108 
2109         @Override
reset(boolean detachIfReset)2110         public boolean reset(boolean detachIfReset) {
2111             final long now = mClocks.elapsedRealtime() * 1000;
2112             recomputeLastDuration(now, true);
2113             boolean stillActive = mLastAddedTime == now;
2114             super.reset(!stillActive && detachIfReset);
2115             return !stillActive;
2116         }
2117     }
2118 
2119 
2120     /**
2121      * A StopwatchTimer that also tracks the total and max individual
2122      * time spent active according to the given timebase.  Whereas
2123      * StopwatchTimer apportions the time amongst all in the pool,
2124      * the total and max durations are not apportioned.
2125      */
2126     public static class DurationTimer extends StopwatchTimer {
2127         /**
2128          * The time (in ms) that the timer was last acquired or the time base
2129          * last (re-)started. Increasing the nesting depth does not reset this time.
2130          *
2131          * -1 if the timer is currently not running or the time base is not running.
2132          *
2133          * If written to a parcel, the start time is reset, as is mNesting in the base class
2134          * StopwatchTimer.
2135          */
2136         long mStartTimeMs = -1;
2137 
2138         /**
2139          * The longest time period (in ms) that the timer has been active. Not pooled.
2140          */
2141         long mMaxDurationMs;
2142 
2143         /**
2144          * The time (in ms) that that the timer has been active since most recent
2145          * stopRunningLocked() or reset(). Not pooled.
2146          */
2147         long mCurrentDurationMs;
2148 
2149         /**
2150          * The total time (in ms) that that the timer has been active since most recent reset()
2151          * prior to the current startRunningLocked. This is the sum of all past currentDurations
2152          * (but not including the present currentDuration) since reset. Not pooled.
2153          */
2154         long mTotalDurationMs;
2155 
DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)2156         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2157                 TimeBase timeBase, Parcel in) {
2158             super(clocks, uid, type, timerPool, timeBase, in);
2159             mMaxDurationMs = in.readLong();
2160             mTotalDurationMs = in.readLong();
2161             mCurrentDurationMs = in.readLong();
2162         }
2163 
DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)2164         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2165                 TimeBase timeBase) {
2166             super(clocks, uid, type, timerPool, timeBase);
2167         }
2168 
2169         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2170         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2171             super.writeToParcel(out, elapsedRealtimeUs);
2172             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2173             out.writeLong(mTotalDurationMs);
2174             out.writeLong(getCurrentDurationMsLocked(elapsedRealtimeUs / 1000));
2175         }
2176 
2177         /**
2178          * Write the summary to the parcel.
2179          *
2180          * Since the time base is probably meaningless after we come back, reading
2181          * from this will have the effect of stopping the timer. So here all we write
2182          * is the max and total durations.
2183          */
2184         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2185         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2186             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2187             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2188             out.writeLong(getTotalDurationMsLocked(elapsedRealtimeUs / 1000));
2189         }
2190 
2191         /**
2192          * Read the summary parcel.
2193          *
2194          * Has the side effect of stopping the timer.
2195          */
2196         @Override
readSummaryFromParcelLocked(Parcel in)2197         public void readSummaryFromParcelLocked(Parcel in) {
2198             super.readSummaryFromParcelLocked(in);
2199             mMaxDurationMs = in.readLong();
2200             mTotalDurationMs = in.readLong();
2201             mStartTimeMs = -1;
2202             mCurrentDurationMs = 0;
2203         }
2204 
2205         /**
2206          * The TimeBase time started (again).
2207          *
2208          * If the timer is also running, store the start time.
2209          */
onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime)2210         public void onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime) {
2211             super.onTimeStarted(elapsedRealtimeUs, baseUptime, baseRealtime);
2212             if (mNesting > 0) {
2213                 mStartTimeMs = baseRealtime / 1000;
2214             }
2215         }
2216 
2217         /**
2218          * The TimeBase stopped running.
2219          *
2220          * If the timer is running, add the duration into mCurrentDurationMs.
2221          */
2222         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtimeUs)2223         public void onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtimeUs) {
2224             super.onTimeStopped(elapsedRealtimeUs, baseUptime, baseRealtimeUs);
2225             if (mNesting > 0) {
2226                 // baseRealtimeUs has already been converted to the timebase's realtime.
2227                 mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
2228             }
2229             mStartTimeMs = -1;
2230         }
2231 
2232         @Override
logState(Printer pw, String prefix)2233         public void logState(Printer pw, String prefix) {
2234             super.logState(pw, prefix);
2235         }
2236 
2237         @Override
startRunningLocked(long elapsedRealtimeMs)2238         public void startRunningLocked(long elapsedRealtimeMs) {
2239             super.startRunningLocked(elapsedRealtimeMs);
2240             if (mNesting == 1 && mTimeBase.isRunning()) {
2241                 // Just started
2242                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000;
2243             }
2244         }
2245 
2246         /**
2247          * Decrements the mNesting ref-count on this timer.
2248          *
2249          * If it actually stopped (mNesting went to 0), then possibly update
2250          * mMaxDuration if the current duration was the longest ever.
2251          */
2252         @Override
stopRunningLocked(long elapsedRealtimeMs)2253         public void stopRunningLocked(long elapsedRealtimeMs) {
2254             if (mNesting == 1) {
2255                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2256                 mTotalDurationMs += durationMs;
2257                 if (durationMs > mMaxDurationMs) {
2258                     mMaxDurationMs = durationMs;
2259                 }
2260                 mStartTimeMs = -1;
2261                 mCurrentDurationMs = 0;
2262             }
2263             // super method decrements mNesting, which getCurrentDurationMsLocked relies on,
2264             // so call super.stopRunningLocked after calling getCurrentDurationMsLocked.
2265             super.stopRunningLocked(elapsedRealtimeMs);
2266         }
2267 
2268         @Override
reset(boolean detachIfReset)2269         public boolean reset(boolean detachIfReset) {
2270             boolean result = super.reset(detachIfReset);
2271             mMaxDurationMs = 0;
2272             mTotalDurationMs = 0;
2273             mCurrentDurationMs = 0;
2274             if (mNesting > 0) {
2275                 mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000) / 1000;
2276             } else {
2277                 mStartTimeMs = -1;
2278             }
2279             return result;
2280         }
2281 
2282         /**
2283          * Returns the max duration that this timer has ever seen.
2284          *
2285          * Note that this time is NOT split between the timers in the timer group that
2286          * this timer is attached to.  It is the TOTAL time.
2287          */
2288         @Override
getMaxDurationMsLocked(long elapsedRealtimeMs)2289         public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
2290             if (mNesting > 0) {
2291                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2292                 if (durationMs > mMaxDurationMs) {
2293                     return durationMs;
2294                 }
2295             }
2296             return mMaxDurationMs;
2297         }
2298 
2299         /**
2300          * Returns the time since the timer was started.
2301          * Returns 0 if the timer is not currently running.
2302          *
2303          * Note that this time is NOT split between the timers in the timer group that
2304          * this timer is attached to.  It is the TOTAL time.
2305          *
2306          * Note that if running timer is parceled and unparceled, this method will return
2307          * current duration value at the time of parceling even though timer may not be
2308          * currently running.
2309          */
2310         @Override
getCurrentDurationMsLocked(long elapsedRealtimeMs)2311         public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
2312             long durationMs = mCurrentDurationMs;
2313             if (mNesting > 0 && mTimeBase.isRunning()) {
2314                 durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000)
2315                         - mStartTimeMs;
2316             }
2317             return durationMs;
2318         }
2319 
2320         /**
2321          * Returns the total cumulative duration that this timer has been on since reset().
2322          * If mTimerPool == null, this should be the same
2323          * as getTotalTimeLocked(elapsedRealtimeMs*1000, STATS_SINCE_CHARGED)/1000.
2324          *
2325          * Note that this time is NOT split between the timers in the timer group that
2326          * this timer is attached to.  It is the TOTAL time. For this reason, if mTimerPool != null,
2327          * the result will not be equivalent to getTotalTimeLocked.
2328          */
2329         @Override
getTotalDurationMsLocked(long elapsedRealtimeMs)2330         public long getTotalDurationMsLocked(long elapsedRealtimeMs) {
2331             return mTotalDurationMs + getCurrentDurationMsLocked(elapsedRealtimeMs);
2332         }
2333     }
2334 
2335     /**
2336      * State for keeping track of timing information.
2337      */
2338     public static class StopwatchTimer extends Timer {
2339         final Uid mUid;
2340         final ArrayList<StopwatchTimer> mTimerPool;
2341 
2342         int mNesting;
2343 
2344         /**
2345          * The last time at which we updated the timer.  If mNesting is > 0,
2346          * subtract this from the current battery time to find the amount of
2347          * time we have been running since we last computed an update.
2348          */
2349         long mUpdateTime;
2350 
2351         /**
2352          * The total time at which the timer was acquired, to determine if it
2353          * was actually held for an interesting duration. If time base was not running when timer
2354          * was acquired, will be -1.
2355          */
2356         long mAcquireTime = -1;
2357 
2358         long mTimeout;
2359 
2360         /**
2361          * For partial wake locks, keep track of whether we are in the list
2362          * to consume CPU cycles.
2363          */
2364         @VisibleForTesting
2365         public boolean mInList;
2366 
StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)2367         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2368                 TimeBase timeBase, Parcel in) {
2369             super(clocks, type, timeBase, in);
2370             mUid = uid;
2371             mTimerPool = timerPool;
2372             mUpdateTime = in.readLong();
2373         }
2374 
StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)2375         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2376                 TimeBase timeBase) {
2377             super(clocks, type, timeBase);
2378             mUid = uid;
2379             mTimerPool = timerPool;
2380         }
2381 
setTimeout(long timeout)2382         public void setTimeout(long timeout) {
2383             mTimeout = timeout;
2384         }
2385 
writeToParcel(Parcel out, long elapsedRealtimeUs)2386         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2387             super.writeToParcel(out, elapsedRealtimeUs);
2388             out.writeLong(mUpdateTime);
2389         }
2390 
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)2391         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
2392             if (mNesting > 0) {
2393                 if (DEBUG && mType < 0) {
2394                     Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
2395                 }
2396                 super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
2397                 mUpdateTime = baseRealtime;
2398                 if (DEBUG && mType < 0) {
2399                     Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
2400                 }
2401             }
2402         }
2403 
logState(Printer pw, String prefix)2404         public void logState(Printer pw, String prefix) {
2405             super.logState(pw, prefix);
2406             pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTime
2407                     + " mAcquireTime=" + mAcquireTime);
2408         }
2409 
startRunningLocked(long elapsedRealtimeMs)2410         public void startRunningLocked(long elapsedRealtimeMs) {
2411             if (mNesting++ == 0) {
2412                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2413                 mUpdateTime = batteryRealtime;
2414                 if (mTimerPool != null) {
2415                     // Accumulate time to all currently active timers before adding
2416                     // this new one to the pool.
2417                     refreshTimersLocked(batteryRealtime, mTimerPool, null);
2418                     // Add this timer to the active pool
2419                     mTimerPool.add(this);
2420                 }
2421                 if (mTimeBase.isRunning()) {
2422                     // Increment the count
2423                     mCount++;
2424                     mAcquireTime = mTotalTime;
2425                 } else {
2426                     mAcquireTime = -1;
2427                 }
2428                 if (DEBUG && mType < 0) {
2429                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
2430                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
2431                             + " mAcquireTime=" + mAcquireTime);
2432                 }
2433             }
2434         }
2435 
isRunningLocked()2436         public boolean isRunningLocked() {
2437             return mNesting > 0;
2438         }
2439 
stopRunningLocked(long elapsedRealtimeMs)2440         public void stopRunningLocked(long elapsedRealtimeMs) {
2441             // Ignore attempt to stop a timer that isn't running
2442             if (mNesting == 0) {
2443                 return;
2444             }
2445             if (--mNesting == 0) {
2446                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2447                 if (mTimerPool != null) {
2448                     // Accumulate time to all active counters, scaled by the total
2449                     // active in the pool, before taking this one out of the pool.
2450                     refreshTimersLocked(batteryRealtime, mTimerPool, null);
2451                     // Remove this timer from the active pool
2452                     mTimerPool.remove(this);
2453                 } else {
2454                     mNesting = 1;
2455                     mTotalTime = computeRunTimeLocked(batteryRealtime);
2456                     mNesting = 0;
2457                 }
2458 
2459                 if (DEBUG && mType < 0) {
2460                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
2461                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
2462                             + " mAcquireTime=" + mAcquireTime);
2463                 }
2464 
2465                 if (mAcquireTime >= 0 && mTotalTime == mAcquireTime) {
2466                     // If there was no change in the time, then discard this
2467                     // count.  A somewhat cheezy strategy, but hey.
2468                     mCount--;
2469                 }
2470             }
2471         }
2472 
stopAllRunningLocked(long elapsedRealtimeMs)2473         public void stopAllRunningLocked(long elapsedRealtimeMs) {
2474             if (mNesting > 0) {
2475                 mNesting = 1;
2476                 stopRunningLocked(elapsedRealtimeMs);
2477             }
2478         }
2479 
2480         // Update the total time for all other running Timers with the same type as this Timer
2481         // due to a change in timer count
refreshTimersLocked(long batteryRealtime, final ArrayList<StopwatchTimer> pool, StopwatchTimer self)2482         private static long refreshTimersLocked(long batteryRealtime,
2483                 final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
2484             long selfTime = 0;
2485             final int N = pool.size();
2486             for (int i=N-1; i>= 0; i--) {
2487                 final StopwatchTimer t = pool.get(i);
2488                 long heldTime = batteryRealtime - t.mUpdateTime;
2489                 if (heldTime > 0) {
2490                     final long myTime = heldTime / N;
2491                     if (t == self) {
2492                         selfTime = myTime;
2493                     }
2494                     t.mTotalTime += myTime;
2495                 }
2496                 t.mUpdateTime = batteryRealtime;
2497             }
2498             return selfTime;
2499         }
2500 
2501         @Override
computeRunTimeLocked(long curBatteryRealtime)2502         protected long computeRunTimeLocked(long curBatteryRealtime) {
2503             if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) {
2504                 curBatteryRealtime = mUpdateTime + mTimeout;
2505             }
2506             return mTotalTime + (mNesting > 0
2507                     ? (curBatteryRealtime - mUpdateTime)
2508                             / (mTimerPool != null ? mTimerPool.size() : 1)
2509                     : 0);
2510         }
2511 
2512         @Override
computeCurrentCountLocked()2513         protected int computeCurrentCountLocked() {
2514             return mCount;
2515         }
2516 
2517         @Override
reset(boolean detachIfReset)2518         public boolean reset(boolean detachIfReset) {
2519             boolean canDetach = mNesting <= 0;
2520             super.reset(canDetach && detachIfReset);
2521             if (mNesting > 0) {
2522                 mUpdateTime = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000);
2523             }
2524             mAcquireTime = -1; // to ensure mCount isn't decreased to -1 if timer is stopped later.
2525             return canDetach;
2526         }
2527 
2528         @Override
2529         @UnsupportedAppUsage
detach()2530         public void detach() {
2531             super.detach();
2532             if (mTimerPool != null) {
2533                 mTimerPool.remove(this);
2534             }
2535         }
2536 
2537         @Override
readSummaryFromParcelLocked(Parcel in)2538         public void readSummaryFromParcelLocked(Parcel in) {
2539             super.readSummaryFromParcelLocked(in);
2540             mNesting = 0;
2541         }
2542 
2543         /**
2544          * Set the mark so that we can query later for the total time the timer has
2545          * accumulated since this point. The timer can be running or not.
2546          *
2547          * @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
2548          */
setMark(long elapsedRealtimeMs)2549         public void setMark(long elapsedRealtimeMs) {
2550             final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2551             if (mNesting > 0) {
2552                 // We are running.
2553                 if (mTimerPool != null) {
2554                     refreshTimersLocked(batteryRealtime, mTimerPool, this);
2555                 } else {
2556                     mTotalTime += batteryRealtime - mUpdateTime;
2557                     mUpdateTime = batteryRealtime;
2558                 }
2559             }
2560             mTimeBeforeMark = mTotalTime;
2561         }
2562     }
2563 
2564     /**
2565      * State for keeping track of two DurationTimers with different TimeBases, presumably where one
2566      * TimeBase is effectively a subset of the other.
2567      */
2568     public static class DualTimer extends DurationTimer {
2569         // This class both is a DurationTimer and also holds a second DurationTimer.
2570         // The main timer (this) typically tracks the total time. It may be pooled (but since it's a
2571         // durationTimer, it also has the unpooled getTotalDurationMsLocked() for
2572         // STATS_SINCE_CHARGED).
2573         // mSubTimer typically tracks only part of the total time, such as background time, as
2574         // determined by a subTimeBase. It is NOT pooled.
2575         private final DurationTimer mSubTimer;
2576 
2577         /**
2578          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2579          * The main timer (this) is based on the given timeBase and timerPool.
2580          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2581          * the main timer is.
2582          */
DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase, Parcel in)2583         public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2584                 TimeBase timeBase, TimeBase subTimeBase, Parcel in) {
2585             super(clocks, uid, type, timerPool, timeBase, in);
2586             mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase, in);
2587         }
2588 
2589         /**
2590          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2591          * The main timer (this) is based on the given timeBase and timerPool.
2592          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2593          * the main timer is.
2594          */
DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase)2595         public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2596                 TimeBase timeBase, TimeBase subTimeBase) {
2597             super(clocks, uid, type, timerPool, timeBase);
2598             mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase);
2599         }
2600 
2601         /** Get the secondary timer. */
2602         @Override
getSubTimer()2603         public DurationTimer getSubTimer() {
2604             return mSubTimer;
2605         }
2606 
2607         @Override
startRunningLocked(long elapsedRealtimeMs)2608         public void startRunningLocked(long elapsedRealtimeMs) {
2609             super.startRunningLocked(elapsedRealtimeMs);
2610             mSubTimer.startRunningLocked(elapsedRealtimeMs);
2611         }
2612 
2613         @Override
stopRunningLocked(long elapsedRealtimeMs)2614         public void stopRunningLocked(long elapsedRealtimeMs) {
2615             super.stopRunningLocked(elapsedRealtimeMs);
2616             mSubTimer.stopRunningLocked(elapsedRealtimeMs);
2617         }
2618 
2619         @Override
stopAllRunningLocked(long elapsedRealtimeMs)2620         public void stopAllRunningLocked(long elapsedRealtimeMs) {
2621             super.stopAllRunningLocked(elapsedRealtimeMs);
2622             mSubTimer.stopAllRunningLocked(elapsedRealtimeMs);
2623         }
2624 
2625         @Override
reset(boolean detachIfReset)2626         public boolean reset(boolean detachIfReset) {
2627             boolean active = false;
2628             // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
2629             active |= !mSubTimer.reset(false);
2630             active |= !super.reset(detachIfReset);
2631             return !active;
2632         }
2633 
2634         @Override
detach()2635         public void detach() {
2636             mSubTimer.detach();
2637             super.detach();
2638         }
2639 
2640         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2641         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2642             super.writeToParcel(out, elapsedRealtimeUs);
2643             mSubTimer.writeToParcel(out, elapsedRealtimeUs);
2644         }
2645 
2646         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2647         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2648             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2649             mSubTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2650         }
2651 
2652         @Override
readSummaryFromParcelLocked(Parcel in)2653         public void readSummaryFromParcelLocked(Parcel in) {
2654             super.readSummaryFromParcelLocked(in);
2655             mSubTimer.readSummaryFromParcelLocked(in);
2656         }
2657     }
2658 
2659 
2660     public abstract class OverflowArrayMap<T> {
2661         private static final String OVERFLOW_NAME = "*overflow*";
2662 
2663         final int mUid;
2664         final ArrayMap<String, T> mMap = new ArrayMap<>();
2665         T mCurOverflow;
2666         ArrayMap<String, MutableInt> mActiveOverflow;
2667         long mLastOverflowTime;
2668         long mLastOverflowFinishTime;
2669         long mLastClearTime;
2670         long mLastCleanupTime;
2671 
OverflowArrayMap(int uid)2672         public OverflowArrayMap(int uid) {
2673             mUid = uid;
2674         }
2675 
getMap()2676         public ArrayMap<String, T> getMap() {
2677             return mMap;
2678         }
2679 
clear()2680         public void clear() {
2681             mLastClearTime = SystemClock.elapsedRealtime();
2682             mMap.clear();
2683             mCurOverflow = null;
2684             mActiveOverflow = null;
2685         }
2686 
add(String name, T obj)2687         public void add(String name, T obj) {
2688             if (name == null) {
2689                 name = "";
2690             }
2691             mMap.put(name, obj);
2692             if (OVERFLOW_NAME.equals(name)) {
2693                 mCurOverflow = obj;
2694             }
2695         }
2696 
cleanup()2697         public void cleanup() {
2698             mLastCleanupTime = SystemClock.elapsedRealtime();
2699             if (mActiveOverflow != null) {
2700                 if (mActiveOverflow.size() == 0) {
2701                     mActiveOverflow = null;
2702                 }
2703             }
2704             if (mActiveOverflow == null) {
2705                 // There is no currently active overflow, so we should no longer have
2706                 // an overflow entry.
2707                 if (mMap.containsKey(OVERFLOW_NAME)) {
2708                     Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
2709                             + mMap.get(OVERFLOW_NAME));
2710                     mMap.remove(OVERFLOW_NAME);
2711                 }
2712                 mCurOverflow = null;
2713             } else {
2714                 // There is currently active overflow, so we should still have an overflow entry.
2715                 if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
2716                     Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
2717                             + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
2718                 }
2719             }
2720         }
2721 
startObject(String name)2722         public T startObject(String name) {
2723             if (name == null) {
2724                 name = "";
2725             }
2726             T obj = mMap.get(name);
2727             if (obj != null) {
2728                 return obj;
2729             }
2730 
2731             // No object exists for the given name, but do we currently have it
2732             // running as part of the overflow?
2733             if (mActiveOverflow != null) {
2734                 MutableInt over = mActiveOverflow.get(name);
2735                 if (over != null) {
2736                     // We are already actively counting this name in the overflow object.
2737                     obj = mCurOverflow;
2738                     if (obj == null) {
2739                         // Shouldn't be here, but we'll try to recover.
2740                         Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
2741                         obj = mCurOverflow = instantiateObject();
2742                         mMap.put(OVERFLOW_NAME, obj);
2743                     }
2744                     over.value++;
2745                     return obj;
2746                 }
2747             }
2748 
2749             // No object exists for given name nor in the overflow; we need to make
2750             // a new one.
2751             final int N = mMap.size();
2752             if (N >= MAX_WAKELOCKS_PER_UID) {
2753                 // Went over the limit on number of objects to track; this one goes
2754                 // in to the overflow.
2755                 obj = mCurOverflow;
2756                 if (obj == null) {
2757                     // Need to start overflow now...
2758                     obj = mCurOverflow = instantiateObject();
2759                     mMap.put(OVERFLOW_NAME, obj);
2760                 }
2761                 if (mActiveOverflow == null) {
2762                     mActiveOverflow = new ArrayMap<>();
2763                 }
2764                 mActiveOverflow.put(name, new MutableInt(1));
2765                 mLastOverflowTime = SystemClock.elapsedRealtime();
2766                 return obj;
2767             }
2768 
2769             // Normal case where we just need to make a new object.
2770             obj = instantiateObject();
2771             mMap.put(name, obj);
2772             return obj;
2773         }
2774 
stopObject(String name)2775         public T stopObject(String name) {
2776             if (name == null) {
2777                 name = "";
2778             }
2779             T obj = mMap.get(name);
2780             if (obj != null) {
2781                 return obj;
2782             }
2783 
2784             // No object exists for the given name, but do we currently have it
2785             // running as part of the overflow?
2786             if (mActiveOverflow != null) {
2787                 MutableInt over = mActiveOverflow.get(name);
2788                 if (over != null) {
2789                     // We are already actively counting this name in the overflow object.
2790                     obj = mCurOverflow;
2791                     if (obj != null) {
2792                         over.value--;
2793                         if (over.value <= 0) {
2794                             mActiveOverflow.remove(name);
2795                             mLastOverflowFinishTime = SystemClock.elapsedRealtime();
2796                         }
2797                         return obj;
2798                     }
2799                 }
2800             }
2801 
2802             // Huh, they are stopping an active operation but we can't find one!
2803             // That's not good.
2804             StringBuilder sb = new StringBuilder();
2805             sb.append("Unable to find object for ");
2806             sb.append(name);
2807             sb.append(" in uid ");
2808             sb.append(mUid);
2809             sb.append(" mapsize=");
2810             sb.append(mMap.size());
2811             sb.append(" activeoverflow=");
2812             sb.append(mActiveOverflow);
2813             sb.append(" curoverflow=");
2814             sb.append(mCurOverflow);
2815             long now = SystemClock.elapsedRealtime();
2816             if (mLastOverflowTime != 0) {
2817                 sb.append(" lastOverflowTime=");
2818                 TimeUtils.formatDuration(mLastOverflowTime-now, sb);
2819             }
2820             if (mLastOverflowFinishTime != 0) {
2821                 sb.append(" lastOverflowFinishTime=");
2822                 TimeUtils.formatDuration(mLastOverflowFinishTime-now, sb);
2823             }
2824             if (mLastClearTime != 0) {
2825                 sb.append(" lastClearTime=");
2826                 TimeUtils.formatDuration(mLastClearTime-now, sb);
2827             }
2828             if (mLastCleanupTime != 0) {
2829                 sb.append(" lastCleanupTime=");
2830                 TimeUtils.formatDuration(mLastCleanupTime-now, sb);
2831             }
2832             Slog.wtf(TAG, sb.toString());
2833             return null;
2834         }
2835 
instantiateObject()2836         public abstract T instantiateObject();
2837     }
2838 
2839     public static class ControllerActivityCounterImpl extends ControllerActivityCounter
2840             implements Parcelable {
2841         private final LongSamplingCounter mIdleTimeMillis;
2842         private final LongSamplingCounter mScanTimeMillis;
2843         private final LongSamplingCounter mSleepTimeMillis;
2844         private final LongSamplingCounter mRxTimeMillis;
2845         private final LongSamplingCounter[] mTxTimeMillis;
2846         private final LongSamplingCounter mPowerDrainMaMs;
2847         private final LongSamplingCounter mMonitoredRailChargeConsumedMaMs;
2848 
ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates)2849         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates) {
2850             mIdleTimeMillis = new LongSamplingCounter(timeBase);
2851             mScanTimeMillis = new LongSamplingCounter(timeBase);
2852             mSleepTimeMillis = new LongSamplingCounter(timeBase);
2853             mRxTimeMillis = new LongSamplingCounter(timeBase);
2854             mTxTimeMillis = new LongSamplingCounter[numTxStates];
2855             for (int i = 0; i < numTxStates; i++) {
2856                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase);
2857             }
2858             mPowerDrainMaMs = new LongSamplingCounter(timeBase);
2859             mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase);
2860         }
2861 
ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in)2862         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in) {
2863             mIdleTimeMillis = new LongSamplingCounter(timeBase, in);
2864             mScanTimeMillis = new LongSamplingCounter(timeBase, in);
2865             mSleepTimeMillis = new LongSamplingCounter(timeBase, in);
2866             mRxTimeMillis = new LongSamplingCounter(timeBase, in);
2867             final int recordedTxStates = in.readInt();
2868             if (recordedTxStates != numTxStates) {
2869                 throw new ParcelFormatException("inconsistent tx state lengths");
2870             }
2871 
2872             mTxTimeMillis = new LongSamplingCounter[numTxStates];
2873             for (int i = 0; i < numTxStates; i++) {
2874                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase, in);
2875             }
2876             mPowerDrainMaMs = new LongSamplingCounter(timeBase, in);
2877             mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase, in);
2878         }
2879 
readSummaryFromParcel(Parcel in)2880         public void readSummaryFromParcel(Parcel in) {
2881             mIdleTimeMillis.readSummaryFromParcelLocked(in);
2882             mScanTimeMillis.readSummaryFromParcelLocked(in);
2883             mSleepTimeMillis.readSummaryFromParcelLocked(in);
2884             mRxTimeMillis.readSummaryFromParcelLocked(in);
2885             final int recordedTxStates = in.readInt();
2886             if (recordedTxStates != mTxTimeMillis.length) {
2887                 throw new ParcelFormatException("inconsistent tx state lengths");
2888             }
2889             for (LongSamplingCounter counter : mTxTimeMillis) {
2890                 counter.readSummaryFromParcelLocked(in);
2891             }
2892             mPowerDrainMaMs.readSummaryFromParcelLocked(in);
2893             mMonitoredRailChargeConsumedMaMs.readSummaryFromParcelLocked(in);
2894         }
2895 
2896         @Override
describeContents()2897         public int describeContents() {
2898             return 0;
2899         }
2900 
writeSummaryToParcel(Parcel dest)2901         public void writeSummaryToParcel(Parcel dest) {
2902             mIdleTimeMillis.writeSummaryFromParcelLocked(dest);
2903             mScanTimeMillis.writeSummaryFromParcelLocked(dest);
2904             mSleepTimeMillis.writeSummaryFromParcelLocked(dest);
2905             mRxTimeMillis.writeSummaryFromParcelLocked(dest);
2906             dest.writeInt(mTxTimeMillis.length);
2907             for (LongSamplingCounter counter : mTxTimeMillis) {
2908                 counter.writeSummaryFromParcelLocked(dest);
2909             }
2910             mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
2911             mMonitoredRailChargeConsumedMaMs.writeSummaryFromParcelLocked(dest);
2912         }
2913 
2914         @Override
writeToParcel(Parcel dest, int flags)2915         public void writeToParcel(Parcel dest, int flags) {
2916             mIdleTimeMillis.writeToParcel(dest);
2917             mScanTimeMillis.writeToParcel(dest);
2918             mSleepTimeMillis.writeToParcel(dest);
2919             mRxTimeMillis.writeToParcel(dest);
2920             dest.writeInt(mTxTimeMillis.length);
2921             for (LongSamplingCounter counter : mTxTimeMillis) {
2922                 counter.writeToParcel(dest);
2923             }
2924             mPowerDrainMaMs.writeToParcel(dest);
2925             mMonitoredRailChargeConsumedMaMs.writeToParcel(dest);
2926         }
2927 
reset(boolean detachIfReset)2928         public void reset(boolean detachIfReset) {
2929             mIdleTimeMillis.reset(detachIfReset);
2930             mScanTimeMillis.reset(detachIfReset);
2931             mSleepTimeMillis.reset(detachIfReset);
2932             mRxTimeMillis.reset(detachIfReset);
2933             for (LongSamplingCounter counter : mTxTimeMillis) {
2934                 counter.reset(detachIfReset);
2935             }
2936             mPowerDrainMaMs.reset(detachIfReset);
2937             mMonitoredRailChargeConsumedMaMs.reset(detachIfReset);
2938         }
2939 
detach()2940         public void detach() {
2941             mIdleTimeMillis.detach();
2942             mScanTimeMillis.detach();
2943             mSleepTimeMillis.detach();
2944             mRxTimeMillis.detach();
2945             for (LongSamplingCounter counter : mTxTimeMillis) {
2946                 counter.detach();
2947             }
2948             mPowerDrainMaMs.detach();
2949             mMonitoredRailChargeConsumedMaMs.detach();
2950         }
2951 
2952         /**
2953          * @return a LongSamplingCounter, measuring time spent in the idle state in
2954          * milliseconds.
2955          */
2956         @Override
getIdleTimeCounter()2957         public LongSamplingCounter getIdleTimeCounter() {
2958             return mIdleTimeMillis;
2959         }
2960 
2961         /**
2962          * @return a LongSamplingCounter, measuring time spent in the scan state in
2963          * milliseconds.
2964          */
2965         @Override
getScanTimeCounter()2966         public LongSamplingCounter getScanTimeCounter() {
2967             return mScanTimeMillis;
2968         }
2969 
2970         /**
2971          * @return a LongSamplingCounter, measuring time spent in the sleep state in
2972          * milliseconds.
2973          */
2974         @Override
getSleepTimeCounter()2975         public LongSamplingCounter getSleepTimeCounter() {
2976             return mSleepTimeMillis;
2977         }
2978 
2979         /**
2980          * @return a LongSamplingCounter, measuring time spent in the receive state in
2981          * milliseconds.
2982          */
2983         @Override
getRxTimeCounter()2984         public LongSamplingCounter getRxTimeCounter() {
2985             return mRxTimeMillis;
2986         }
2987 
2988         /**
2989          * @return a LongSamplingCounter[], measuring time spent in various transmit states in
2990          * milliseconds.
2991          */
2992         @Override
getTxTimeCounters()2993         public LongSamplingCounter[] getTxTimeCounters() {
2994             return mTxTimeMillis;
2995         }
2996 
2997         /**
2998          * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
2999          */
3000         @Override
getPowerCounter()3001         public LongSamplingCounter getPowerCounter() {
3002             return mPowerDrainMaMs;
3003         }
3004 
3005         /**
3006          * @return a LongSamplingCounter, measuring actual monitored rail energy consumed
3007          * milli-ampere milli-seconds (mAmS).
3008          */
3009         @Override
getMonitoredRailChargeConsumedMaMs()3010         public LongSamplingCounter getMonitoredRailChargeConsumedMaMs() {
3011             return mMonitoredRailChargeConsumedMaMs;
3012         }
3013     }
3014 
3015     /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */
getRpmTimerLocked(String name)3016     public SamplingTimer getRpmTimerLocked(String name) {
3017         SamplingTimer rpmt = mRpmStats.get(name);
3018         if (rpmt == null) {
3019             rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3020             mRpmStats.put(name, rpmt);
3021         }
3022         return rpmt;
3023     }
3024 
3025     /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */
getScreenOffRpmTimerLocked(String name)3026     public SamplingTimer getScreenOffRpmTimerLocked(String name) {
3027         SamplingTimer rpmt = mScreenOffRpmStats.get(name);
3028         if (rpmt == null) {
3029             rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
3030             mScreenOffRpmStats.put(name, rpmt);
3031         }
3032         return rpmt;
3033     }
3034 
3035     /*
3036      * Get the wakeup reason counter, and create a new one if one
3037      * doesn't already exist.
3038      */
getWakeupReasonTimerLocked(String name)3039     public SamplingTimer getWakeupReasonTimerLocked(String name) {
3040         SamplingTimer timer = mWakeupReasonStats.get(name);
3041         if (timer == null) {
3042             timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3043             mWakeupReasonStats.put(name, timer);
3044         }
3045         return timer;
3046     }
3047 
3048     /*
3049      * Get the KernelWakelockTimer associated with name, and create a new one if one
3050      * doesn't already exist.
3051      */
getKernelWakelockTimerLocked(String name)3052     public SamplingTimer getKernelWakelockTimerLocked(String name) {
3053         SamplingTimer kwlt = mKernelWakelockStats.get(name);
3054         if (kwlt == null) {
3055             kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
3056             mKernelWakelockStats.put(name, kwlt);
3057         }
3058         return kwlt;
3059     }
3060 
getKernelMemoryTimerLocked(long bucket)3061     public SamplingTimer getKernelMemoryTimerLocked(long bucket) {
3062         SamplingTimer kmt = mKernelMemoryStats.get(bucket);
3063         if (kmt == null) {
3064             kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3065             mKernelMemoryStats.put(bucket, kmt);
3066         }
3067         return kmt;
3068     }
3069 
writeHistoryTag(HistoryTag tag)3070     private int writeHistoryTag(HistoryTag tag) {
3071         Integer idxObj = mHistoryTagPool.get(tag);
3072         int idx;
3073         if (idxObj != null) {
3074             idx = idxObj;
3075         } else {
3076             idx = mNextHistoryTagIdx;
3077             HistoryTag key = new HistoryTag();
3078             key.setTo(tag);
3079             tag.poolIdx = idx;
3080             mHistoryTagPool.put(key, idx);
3081             mNextHistoryTagIdx++;
3082             mNumHistoryTagChars += key.string.length() + 1;
3083         }
3084         return idx;
3085     }
3086 
readHistoryTag(int index, HistoryTag tag)3087     private void readHistoryTag(int index, HistoryTag tag) {
3088         if (index < mReadHistoryStrings.length) {
3089             tag.string = mReadHistoryStrings[index];
3090             tag.uid = mReadHistoryUids[index];
3091         } else {
3092             tag.string = null;
3093             tag.uid = 0;
3094         }
3095         tag.poolIdx = index;
3096     }
3097 
3098     /*
3099         The history delta format uses flags to denote further data in subsequent ints in the parcel.
3100 
3101         There is always the first token, which may contain the delta time, or an indicator of
3102         the length of the time (int or long) following this token.
3103 
3104         First token: always present,
3105         31              23              15               7             0
3106         █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█
3107 
3108         T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
3109            follows containing the time, and 0x7ffff indicates a long immediately follows with the
3110            delta time.
3111         A: battery level changed and an int follows with battery data.
3112         B: state changed and an int follows with state change data.
3113         C: state2 has changed and an int follows with state2 change data.
3114         D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
3115         E: event data has changed and an event struct follows.
3116         F: battery charge in coulombs has changed and an int with the charge follows.
3117         G: state flag denoting that the mobile radio was active.
3118         H: state flag denoting that the wifi radio was active.
3119         I: state flag denoting that a wifi scan occurred.
3120         J: state flag denoting that a wifi full lock was held.
3121         K: state flag denoting that the gps was on.
3122         L: state flag denoting that a wakelock was held.
3123         M: state flag denoting that the cpu was running.
3124 
3125         Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
3126         with the time delta.
3127 
3128         Battery level int: if A in the first token is set,
3129         31              23              15               7             0
3130         █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█
3131 
3132         D: indicates that extra history details follow.
3133         V: the battery voltage.
3134         T: the battery temperature.
3135         L: the battery level (out of 100).
3136 
3137         State change int: if B in the first token is set,
3138         31              23              15               7             0
3139         █S|S|S|H|H|H|P|P█F|E|D|C|B| | |A█ | | | | | | | █ | | | | | | | █
3140 
3141         A: wifi multicast was on.
3142         B: battery was plugged in.
3143         C: screen was on.
3144         D: phone was scanning for signal.
3145         E: audio was on.
3146         F: a sensor was active.
3147 
3148         State2 change int: if C in the first token is set,
3149         31              23              15               7             0
3150         █M|L|K|J|I|H|H|G█F|E|D|C| | | | █ | | | | | | | █ |B|B|B|A|A|A|A█
3151 
3152         A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
3153         B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
3154         C: a bluetooth scan was active.
3155         D: the camera was active.
3156         E: bluetooth was on.
3157         F: a phone call was active.
3158         G: the device was charging.
3159         H: 2 bits indicating the device-idle (doze) state: off, light, full
3160         I: the flashlight was on.
3161         J: wifi was on.
3162         K: wifi was running.
3163         L: video was playing.
3164         M: power save mode was on.
3165 
3166         Wakelock/wakereason struct: if D in the first token is set,
3167         TODO(adamlesinski): describe wakelock/wakereason struct.
3168 
3169         Event struct: if E in the first token is set,
3170         TODO(adamlesinski): describe the event struct.
3171 
3172         History step details struct: if D in the battery level int is set,
3173         TODO(adamlesinski): describe the history step details struct.
3174 
3175         Battery charge int: if F in the first token is set, an int representing the battery charge
3176         in coulombs follows.
3177      */
3178 
3179     // Part of initial delta int that specifies the time delta.
3180     static final int DELTA_TIME_MASK = 0x7ffff;
3181     static final int DELTA_TIME_LONG = 0x7ffff;   // The delta is a following long
3182     static final int DELTA_TIME_INT = 0x7fffe;    // The delta is a following int
3183     static final int DELTA_TIME_ABS = 0x7fffd;    // Following is an entire abs update.
3184     // Flag in delta int: a new battery level int follows.
3185     static final int DELTA_BATTERY_LEVEL_FLAG               = 0x00080000;
3186     // Flag in delta int: a new full state and battery status int follows.
3187     static final int DELTA_STATE_FLAG                       = 0x00100000;
3188     // Flag in delta int: a new full state2 int follows.
3189     static final int DELTA_STATE2_FLAG                      = 0x00200000;
3190     // Flag in delta int: contains a wakelock or wakeReason tag.
3191     static final int DELTA_WAKELOCK_FLAG                    = 0x00400000;
3192     // Flag in delta int: contains an event description.
3193     static final int DELTA_EVENT_FLAG                       = 0x00800000;
3194     // Flag in delta int: contains the battery charge count in uAh.
3195     static final int DELTA_BATTERY_CHARGE_FLAG              = 0x01000000;
3196     // These upper bits are the frequently changing state bits.
3197     static final int DELTA_STATE_MASK                       = 0xfe000000;
3198 
3199     // These are the pieces of battery state that are packed in to the upper bits of
3200     // the state int that have been packed in to the first delta int.  They must fit
3201     // in STATE_BATTERY_MASK.
3202     static final int STATE_BATTERY_MASK         = 0xff000000;
3203     static final int STATE_BATTERY_STATUS_MASK  = 0x00000007;
3204     static final int STATE_BATTERY_STATUS_SHIFT = 29;
3205     static final int STATE_BATTERY_HEALTH_MASK  = 0x00000007;
3206     static final int STATE_BATTERY_HEALTH_SHIFT = 26;
3207     static final int STATE_BATTERY_PLUG_MASK    = 0x00000003;
3208     static final int STATE_BATTERY_PLUG_SHIFT   = 24;
3209 
3210     // We use the low bit of the battery state int to indicate that we have full details
3211     // from a battery level change.
3212     static final int BATTERY_DELTA_LEVEL_FLAG   = 0x00000001;
3213 
writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last)3214     public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
3215         if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
3216             dest.writeInt(DELTA_TIME_ABS);
3217             cur.writeToParcel(dest, 0);
3218             return;
3219         }
3220 
3221         final long deltaTime = cur.time - last.time;
3222         final int lastBatteryLevelInt = buildBatteryLevelInt(last);
3223         final int lastStateInt = buildStateInt(last);
3224 
3225         int deltaTimeToken;
3226         if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
3227             deltaTimeToken = DELTA_TIME_LONG;
3228         } else if (deltaTime >= DELTA_TIME_ABS) {
3229             deltaTimeToken = DELTA_TIME_INT;
3230         } else {
3231             deltaTimeToken = (int)deltaTime;
3232         }
3233         int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
3234         final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
3235                 ? BATTERY_DELTA_LEVEL_FLAG : 0;
3236         final boolean computeStepDetails = includeStepDetails != 0
3237                 || mLastHistoryStepDetails == null;
3238         final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
3239         final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
3240         if (batteryLevelIntChanged) {
3241             firstToken |= DELTA_BATTERY_LEVEL_FLAG;
3242         }
3243         final int stateInt = buildStateInt(cur);
3244         final boolean stateIntChanged = stateInt != lastStateInt;
3245         if (stateIntChanged) {
3246             firstToken |= DELTA_STATE_FLAG;
3247         }
3248         final boolean state2IntChanged = cur.states2 != last.states2;
3249         if (state2IntChanged) {
3250             firstToken |= DELTA_STATE2_FLAG;
3251         }
3252         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
3253             firstToken |= DELTA_WAKELOCK_FLAG;
3254         }
3255         if (cur.eventCode != HistoryItem.EVENT_NONE) {
3256             firstToken |= DELTA_EVENT_FLAG;
3257         }
3258 
3259         final boolean batteryChargeChanged = cur.batteryChargeUAh != last.batteryChargeUAh;
3260         if (batteryChargeChanged) {
3261             firstToken |= DELTA_BATTERY_CHARGE_FLAG;
3262         }
3263         dest.writeInt(firstToken);
3264         if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
3265                 + " deltaTime=" + deltaTime);
3266 
3267         if (deltaTimeToken >= DELTA_TIME_INT) {
3268             if (deltaTimeToken == DELTA_TIME_INT) {
3269                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
3270                 dest.writeInt((int)deltaTime);
3271             } else {
3272                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
3273                 dest.writeLong(deltaTime);
3274             }
3275         }
3276         if (batteryLevelIntChanged) {
3277             dest.writeInt(batteryLevelInt);
3278             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
3279                     + Integer.toHexString(batteryLevelInt)
3280                     + " batteryLevel=" + cur.batteryLevel
3281                     + " batteryTemp=" + cur.batteryTemperature
3282                     + " batteryVolt=" + (int)cur.batteryVoltage);
3283         }
3284         if (stateIntChanged) {
3285             dest.writeInt(stateInt);
3286             if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
3287                     + Integer.toHexString(stateInt)
3288                     + " batteryStatus=" + cur.batteryStatus
3289                     + " batteryHealth=" + cur.batteryHealth
3290                     + " batteryPlugType=" + cur.batteryPlugType
3291                     + " states=0x" + Integer.toHexString(cur.states));
3292         }
3293         if (state2IntChanged) {
3294             dest.writeInt(cur.states2);
3295             if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x"
3296                     + Integer.toHexString(cur.states2));
3297         }
3298         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
3299             int wakeLockIndex;
3300             int wakeReasonIndex;
3301             if (cur.wakelockTag != null) {
3302                 wakeLockIndex = writeHistoryTag(cur.wakelockTag);
3303                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
3304                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
3305             } else {
3306                 wakeLockIndex = 0xffff;
3307             }
3308             if (cur.wakeReasonTag != null) {
3309                 wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
3310                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
3311                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
3312             } else {
3313                 wakeReasonIndex = 0xffff;
3314             }
3315             dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
3316         }
3317         if (cur.eventCode != HistoryItem.EVENT_NONE) {
3318             int index = writeHistoryTag(cur.eventTag);
3319             int codeAndIndex = (cur.eventCode&0xffff) | (index<<16);
3320             dest.writeInt(codeAndIndex);
3321             if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
3322                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
3323                     + cur.eventTag.string);
3324         }
3325         if (computeStepDetails) {
3326             if (mPlatformIdleStateCallback != null) {
3327                 mCurHistoryStepDetails.statPlatformIdleState =
3328                         mPlatformIdleStateCallback.getPlatformLowPowerStats();
3329                 if (DEBUG) Slog.i(TAG, "WRITE PlatformIdleState:" +
3330                         mCurHistoryStepDetails.statPlatformIdleState);
3331 
3332                 mCurHistoryStepDetails.statSubsystemPowerState =
3333                         mPlatformIdleStateCallback.getSubsystemLowPowerStats();
3334                 if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
3335                         mCurHistoryStepDetails.statSubsystemPowerState);
3336 
3337             }
3338             computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
3339             if (includeStepDetails != 0) {
3340                 mCurHistoryStepDetails.writeToParcel(dest);
3341             }
3342             cur.stepDetails = mCurHistoryStepDetails;
3343             mLastHistoryStepDetails = mCurHistoryStepDetails;
3344         } else {
3345             cur.stepDetails = null;
3346         }
3347         if (mLastHistoryStepLevel < cur.batteryLevel) {
3348             mLastHistoryStepDetails = null;
3349         }
3350         mLastHistoryStepLevel = cur.batteryLevel;
3351 
3352         if (batteryChargeChanged) {
3353             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUAh=" + cur.batteryChargeUAh);
3354             dest.writeInt(cur.batteryChargeUAh);
3355         }
3356         dest.writeDouble(cur.modemRailChargeMah);
3357         dest.writeDouble(cur.wifiRailChargeMah);
3358     }
3359 
buildBatteryLevelInt(HistoryItem h)3360     private int buildBatteryLevelInt(HistoryItem h) {
3361         return ((((int)h.batteryLevel)<<25)&0xfe000000)
3362                 | ((((int)h.batteryTemperature)<<15)&0x01ff8000)
3363                 | ((((int)h.batteryVoltage)<<1)&0x00007ffe);
3364     }
3365 
readBatteryLevelInt(int batteryLevelInt, HistoryItem out)3366     private void readBatteryLevelInt(int batteryLevelInt, HistoryItem out) {
3367         out.batteryLevel = (byte)((batteryLevelInt & 0xfe000000) >>> 25);
3368         out.batteryTemperature = (short)((batteryLevelInt & 0x01ff8000) >>> 15);
3369         out.batteryVoltage = (char)((batteryLevelInt & 0x00007ffe) >>> 1);
3370     }
3371 
buildStateInt(HistoryItem h)3372     private int buildStateInt(HistoryItem h) {
3373         int plugType = 0;
3374         if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
3375             plugType = 1;
3376         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
3377             plugType = 2;
3378         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
3379             plugType = 3;
3380         }
3381         return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT)
3382                 | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT)
3383                 | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT)
3384                 | (h.states&(~STATE_BATTERY_MASK));
3385     }
3386 
computeHistoryStepDetails(final HistoryStepDetails out, final HistoryStepDetails last)3387     private void computeHistoryStepDetails(final HistoryStepDetails out,
3388             final HistoryStepDetails last) {
3389         final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
3390 
3391         // Perform a CPU update right after we do this collection, so we have started
3392         // collecting good data for the next step.
3393         requestImmediateCpuUpdate();
3394 
3395         if (last == null) {
3396             // We are not generating a delta, so all we need to do is reset the stats
3397             // we will later be doing a delta from.
3398             final int NU = mUidStats.size();
3399             for (int i=0; i<NU; i++) {
3400                 final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3401                 uid.mLastStepUserTime = uid.mCurStepUserTime;
3402                 uid.mLastStepSystemTime = uid.mCurStepSystemTime;
3403             }
3404             mLastStepCpuUserTime = mCurStepCpuUserTime;
3405             mLastStepCpuSystemTime = mCurStepCpuSystemTime;
3406             mLastStepStatUserTime = mCurStepStatUserTime;
3407             mLastStepStatSystemTime = mCurStepStatSystemTime;
3408             mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
3409             mLastStepStatIrqTime = mCurStepStatIrqTime;
3410             mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
3411             mLastStepStatIdleTime = mCurStepStatIdleTime;
3412             tmp.clear();
3413             return;
3414         }
3415         if (DEBUG) {
3416             Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTime + " sys="
3417                     + mLastStepStatSystemTime + " io=" + mLastStepStatIOWaitTime
3418                     + " irq=" + mLastStepStatIrqTime + " sirq="
3419                     + mLastStepStatSoftIrqTime + " idle=" + mLastStepStatIdleTime);
3420             Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTime + " sys="
3421                     + mCurStepStatSystemTime + " io=" + mCurStepStatIOWaitTime
3422                     + " irq=" + mCurStepStatIrqTime + " sirq="
3423                     + mCurStepStatSoftIrqTime + " idle=" + mCurStepStatIdleTime);
3424         }
3425         out.userTime = (int)(mCurStepCpuUserTime - mLastStepCpuUserTime);
3426         out.systemTime = (int)(mCurStepCpuSystemTime - mLastStepCpuSystemTime);
3427         out.statUserTime = (int)(mCurStepStatUserTime - mLastStepStatUserTime);
3428         out.statSystemTime = (int)(mCurStepStatSystemTime - mLastStepStatSystemTime);
3429         out.statIOWaitTime = (int)(mCurStepStatIOWaitTime - mLastStepStatIOWaitTime);
3430         out.statIrqTime = (int)(mCurStepStatIrqTime - mLastStepStatIrqTime);
3431         out.statSoftIrqTime = (int)(mCurStepStatSoftIrqTime - mLastStepStatSoftIrqTime);
3432         out.statIdlTime = (int)(mCurStepStatIdleTime - mLastStepStatIdleTime);
3433         out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
3434         out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
3435         out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
3436         final int NU = mUidStats.size();
3437         for (int i=0; i<NU; i++) {
3438             final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3439             final int totalUTime = (int)(uid.mCurStepUserTime - uid.mLastStepUserTime);
3440             final int totalSTime = (int)(uid.mCurStepSystemTime - uid.mLastStepSystemTime);
3441             final int totalTime = totalUTime + totalSTime;
3442             uid.mLastStepUserTime = uid.mCurStepUserTime;
3443             uid.mLastStepSystemTime = uid.mCurStepSystemTime;
3444             if (totalTime <= (out.appCpuUTime3+out.appCpuSTime3)) {
3445                 continue;
3446             }
3447             if (totalTime <= (out.appCpuUTime2+out.appCpuSTime2)) {
3448                 out.appCpuUid3 = uid.mUid;
3449                 out.appCpuUTime3 = totalUTime;
3450                 out.appCpuSTime3 = totalSTime;
3451             } else {
3452                 out.appCpuUid3 = out.appCpuUid2;
3453                 out.appCpuUTime3 = out.appCpuUTime2;
3454                 out.appCpuSTime3 = out.appCpuSTime2;
3455                 if (totalTime <= (out.appCpuUTime1+out.appCpuSTime1)) {
3456                     out.appCpuUid2 = uid.mUid;
3457                     out.appCpuUTime2 = totalUTime;
3458                     out.appCpuSTime2 = totalSTime;
3459                 } else {
3460                     out.appCpuUid2 = out.appCpuUid1;
3461                     out.appCpuUTime2 = out.appCpuUTime1;
3462                     out.appCpuSTime2 = out.appCpuSTime1;
3463                     out.appCpuUid1 = uid.mUid;
3464                     out.appCpuUTime1 = totalUTime;
3465                     out.appCpuSTime1 = totalSTime;
3466                 }
3467             }
3468         }
3469         mLastStepCpuUserTime = mCurStepCpuUserTime;
3470         mLastStepCpuSystemTime = mCurStepCpuSystemTime;
3471         mLastStepStatUserTime = mCurStepStatUserTime;
3472         mLastStepStatSystemTime = mCurStepStatSystemTime;
3473         mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
3474         mLastStepStatIrqTime = mCurStepStatIrqTime;
3475         mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
3476         mLastStepStatIdleTime = mCurStepStatIdleTime;
3477     }
3478 
readHistoryDelta(Parcel src, HistoryItem cur)3479     public void readHistoryDelta(Parcel src, HistoryItem cur) {
3480         int firstToken = src.readInt();
3481         int deltaTimeToken = firstToken&DELTA_TIME_MASK;
3482         cur.cmd = HistoryItem.CMD_UPDATE;
3483         cur.numReadInts = 1;
3484         if (DEBUG) Slog.i(TAG, "READ DELTA: firstToken=0x" + Integer.toHexString(firstToken)
3485                 + " deltaTimeToken=" + deltaTimeToken);
3486 
3487         if (deltaTimeToken < DELTA_TIME_ABS) {
3488             cur.time += deltaTimeToken;
3489         } else if (deltaTimeToken == DELTA_TIME_ABS) {
3490             cur.readFromParcel(src);
3491             if (DEBUG) Slog.i(TAG, "READ DELTA: ABS time=" + cur.time);
3492             return;
3493         } else if (deltaTimeToken == DELTA_TIME_INT) {
3494             int delta = src.readInt();
3495             cur.time += delta;
3496             cur.numReadInts += 1;
3497             if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
3498         } else {
3499             long delta = src.readLong();
3500             if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
3501             cur.time += delta;
3502             cur.numReadInts += 2;
3503         }
3504 
3505         final int batteryLevelInt;
3506         if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
3507             batteryLevelInt = src.readInt();
3508             readBatteryLevelInt(batteryLevelInt, cur);
3509             cur.numReadInts += 1;
3510             if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x"
3511                     + Integer.toHexString(batteryLevelInt)
3512                     + " batteryLevel=" + cur.batteryLevel
3513                     + " batteryTemp=" + cur.batteryTemperature
3514                     + " batteryVolt=" + (int)cur.batteryVoltage);
3515         } else {
3516             batteryLevelInt = 0;
3517         }
3518 
3519         if ((firstToken&DELTA_STATE_FLAG) != 0) {
3520             int stateInt = src.readInt();
3521             cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~STATE_BATTERY_MASK));
3522             cur.batteryStatus = (byte)((stateInt>>STATE_BATTERY_STATUS_SHIFT)
3523                     & STATE_BATTERY_STATUS_MASK);
3524             cur.batteryHealth = (byte)((stateInt>>STATE_BATTERY_HEALTH_SHIFT)
3525                     & STATE_BATTERY_HEALTH_MASK);
3526             cur.batteryPlugType = (byte)((stateInt>>STATE_BATTERY_PLUG_SHIFT)
3527                     & STATE_BATTERY_PLUG_MASK);
3528             switch (cur.batteryPlugType) {
3529                 case 1:
3530                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_AC;
3531                     break;
3532                 case 2:
3533                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_USB;
3534                     break;
3535                 case 3:
3536                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
3537                     break;
3538             }
3539             cur.numReadInts += 1;
3540             if (DEBUG) Slog.i(TAG, "READ DELTA: stateToken=0x"
3541                     + Integer.toHexString(stateInt)
3542                     + " batteryStatus=" + cur.batteryStatus
3543                     + " batteryHealth=" + cur.batteryHealth
3544                     + " batteryPlugType=" + cur.batteryPlugType
3545                     + " states=0x" + Integer.toHexString(cur.states));
3546         } else {
3547             cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~STATE_BATTERY_MASK));
3548         }
3549 
3550         if ((firstToken&DELTA_STATE2_FLAG) != 0) {
3551             cur.states2 = src.readInt();
3552             if (DEBUG) Slog.i(TAG, "READ DELTA: states2=0x"
3553                     + Integer.toHexString(cur.states2));
3554         }
3555 
3556         if ((firstToken&DELTA_WAKELOCK_FLAG) != 0) {
3557             int indexes = src.readInt();
3558             int wakeLockIndex = indexes&0xffff;
3559             int wakeReasonIndex = (indexes>>16)&0xffff;
3560             if (wakeLockIndex != 0xffff) {
3561                 cur.wakelockTag = cur.localWakelockTag;
3562                 readHistoryTag(wakeLockIndex, cur.wakelockTag);
3563                 if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
3564                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
3565             } else {
3566                 cur.wakelockTag = null;
3567             }
3568             if (wakeReasonIndex != 0xffff) {
3569                 cur.wakeReasonTag = cur.localWakeReasonTag;
3570                 readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
3571                 if (DEBUG) Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
3572                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
3573             } else {
3574                 cur.wakeReasonTag = null;
3575             }
3576             cur.numReadInts += 1;
3577         } else {
3578             cur.wakelockTag = null;
3579             cur.wakeReasonTag = null;
3580         }
3581 
3582         if ((firstToken&DELTA_EVENT_FLAG) != 0) {
3583             cur.eventTag = cur.localEventTag;
3584             final int codeAndIndex = src.readInt();
3585             cur.eventCode = (codeAndIndex&0xffff);
3586             final int index = ((codeAndIndex>>16)&0xffff);
3587             readHistoryTag(index, cur.eventTag);
3588             cur.numReadInts += 1;
3589             if (DEBUG) Slog.i(TAG, "READ DELTA: event=" + cur.eventCode + " tag=#"
3590                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
3591                     + cur.eventTag.string);
3592         } else {
3593             cur.eventCode = HistoryItem.EVENT_NONE;
3594         }
3595 
3596         if ((batteryLevelInt&BATTERY_DELTA_LEVEL_FLAG) != 0) {
3597             cur.stepDetails = mReadHistoryStepDetails;
3598             cur.stepDetails.readFromParcel(src);
3599         } else {
3600             cur.stepDetails = null;
3601         }
3602 
3603         if ((firstToken&DELTA_BATTERY_CHARGE_FLAG) != 0) {
3604             cur.batteryChargeUAh = src.readInt();
3605         }
3606         cur.modemRailChargeMah = src.readDouble();
3607         cur.wifiRailChargeMah = src.readDouble();
3608     }
3609 
3610     @Override
commitCurrentHistoryBatchLocked()3611     public void commitCurrentHistoryBatchLocked() {
3612         mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
3613     }
3614 
createFakeHistoryEvents(long numEvents)3615     public void createFakeHistoryEvents(long numEvents) {
3616         for(long i = 0; i < numEvents; i++) {
3617             noteLongPartialWakelockStart("name1", "historyName1", 1000);
3618             noteLongPartialWakelockFinish("name1", "historyName1", 1000);
3619         }
3620     }
3621 
addHistoryBufferLocked(long elapsedRealtimeMs, HistoryItem cur)3622     void addHistoryBufferLocked(long elapsedRealtimeMs, HistoryItem cur) {
3623         if (!mHaveBatteryLevel || !mRecordingHistory) {
3624             return;
3625         }
3626 
3627         final long timeDiff = (mHistoryBaseTime+elapsedRealtimeMs) - mHistoryLastWritten.time;
3628         final int diffStates = mHistoryLastWritten.states^(cur.states&mActiveHistoryStates);
3629         final int diffStates2 = mHistoryLastWritten.states2^(cur.states2&mActiveHistoryStates2);
3630         final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
3631         final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
3632         if (DEBUG) Slog.i(TAG, "ADD: tdelta=" + timeDiff + " diff="
3633                 + Integer.toHexString(diffStates) + " lastDiff="
3634                 + Integer.toHexString(lastDiffStates) + " diff2="
3635                 + Integer.toHexString(diffStates2) + " lastDiff2="
3636                 + Integer.toHexString(lastDiffStates2));
3637         if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
3638                 && timeDiff < 1000 && (diffStates&lastDiffStates) == 0
3639                 && (diffStates2&lastDiffStates2) == 0
3640                 && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
3641                 && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
3642                 && mHistoryLastWritten.stepDetails == null
3643                 && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
3644                         || cur.eventCode == HistoryItem.EVENT_NONE)
3645                 && mHistoryLastWritten.batteryLevel == cur.batteryLevel
3646                 && mHistoryLastWritten.batteryStatus == cur.batteryStatus
3647                 && mHistoryLastWritten.batteryHealth == cur.batteryHealth
3648                 && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
3649                 && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
3650                 && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
3651             // We can merge this new change in with the last one.  Merging is
3652             // allowed as long as only the states have changed, and within those states
3653             // as long as no bit has changed both between now and the last entry, as
3654             // well as the last entry and the one before it (so we capture any toggles).
3655             if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
3656             mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
3657             mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
3658             mHistoryBufferLastPos = -1;
3659             elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTime;
3660             // If the last written history had a wakelock tag, we need to retain it.
3661             // Note that the condition above made sure that we aren't in a case where
3662             // both it and the current history item have a wakelock tag.
3663             if (mHistoryLastWritten.wakelockTag != null) {
3664                 cur.wakelockTag = cur.localWakelockTag;
3665                 cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
3666             }
3667             // If the last written history had a wake reason tag, we need to retain it.
3668             // Note that the condition above made sure that we aren't in a case where
3669             // both it and the current history item have a wakelock tag.
3670             if (mHistoryLastWritten.wakeReasonTag != null) {
3671                 cur.wakeReasonTag = cur.localWakeReasonTag;
3672                 cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
3673             }
3674             // If the last written history had an event, we need to retain it.
3675             // Note that the condition above made sure that we aren't in a case where
3676             // both it and the current history item have an event.
3677             if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
3678                 cur.eventCode = mHistoryLastWritten.eventCode;
3679                 cur.eventTag = cur.localEventTag;
3680                 cur.eventTag.setTo(mHistoryLastWritten.eventTag);
3681             }
3682             mHistoryLastWritten.setTo(mHistoryLastLastWritten);
3683         }
3684         final int dataSize = mHistoryBuffer.dataSize();
3685 
3686         if (dataSize >= mConstants.MAX_HISTORY_BUFFER) {
3687             //open a new history file.
3688             final long start = SystemClock.uptimeMillis();
3689             writeHistoryLocked(true);
3690             if (DEBUG) {
3691                 Slog.d(TAG, "addHistoryBufferLocked writeHistoryLocked takes ms:"
3692                         + (SystemClock.uptimeMillis() - start));
3693             }
3694             mBatteryStatsHistory.startNextFile();
3695             mHistoryBuffer.setDataSize(0);
3696             mHistoryBuffer.setDataPosition(0);
3697             mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
3698             mHistoryBufferLastPos = -1;
3699             final long elapsedRealtime = mClocks.elapsedRealtime();
3700             final long uptime = mClocks.uptimeMillis();
3701             HistoryItem newItem = new HistoryItem();
3702             newItem.setTo(cur);
3703             startRecordingHistory(elapsedRealtime, uptime, false);
3704             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, newItem);
3705             return;
3706         }
3707 
3708         if (dataSize == 0) {
3709             // The history is currently empty; we need it to start with a time stamp.
3710             cur.currentTime = System.currentTimeMillis();
3711             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
3712         }
3713         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3714     }
3715 
addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur)3716     private void addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur) {
3717         if (mIteratingHistory) {
3718             throw new IllegalStateException("Can't do this while iterating history!");
3719         }
3720         mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
3721         mHistoryLastLastWritten.setTo(mHistoryLastWritten);
3722         mHistoryLastWritten.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
3723         mHistoryLastWritten.states &= mActiveHistoryStates;
3724         mHistoryLastWritten.states2 &= mActiveHistoryStates2;
3725         writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
3726         mLastHistoryElapsedRealtime = elapsedRealtimeMs;
3727         cur.wakelockTag = null;
3728         cur.wakeReasonTag = null;
3729         cur.eventCode = HistoryItem.EVENT_NONE;
3730         cur.eventTag = null;
3731         if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
3732                 + " now " + mHistoryBuffer.dataPosition()
3733                 + " size is now " + mHistoryBuffer.dataSize());
3734     }
3735 
3736     int mChangedStates = 0;
3737     int mChangedStates2 = 0;
3738 
addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs)3739     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
3740         if (mTrackRunningHistoryElapsedRealtime != 0) {
3741             final long diffElapsed = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtime;
3742             final long diffUptime = uptimeMs - mTrackRunningHistoryUptime;
3743             if (diffUptime < (diffElapsed-20)) {
3744                 final long wakeElapsedTime = elapsedRealtimeMs - (diffElapsed - diffUptime);
3745                 mHistoryAddTmp.setTo(mHistoryLastWritten);
3746                 mHistoryAddTmp.wakelockTag = null;
3747                 mHistoryAddTmp.wakeReasonTag = null;
3748                 mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
3749                 mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
3750                 addHistoryRecordInnerLocked(wakeElapsedTime, mHistoryAddTmp);
3751             }
3752         }
3753         mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
3754         mTrackRunningHistoryElapsedRealtime = elapsedRealtimeMs;
3755         mTrackRunningHistoryUptime = uptimeMs;
3756         addHistoryRecordInnerLocked(elapsedRealtimeMs, mHistoryCur);
3757     }
3758 
addHistoryRecordInnerLocked(long elapsedRealtimeMs, HistoryItem cur)3759     void addHistoryRecordInnerLocked(long elapsedRealtimeMs, HistoryItem cur) {
3760         addHistoryBufferLocked(elapsedRealtimeMs, cur);
3761 
3762         if (!USE_OLD_HISTORY) {
3763             return;
3764         }
3765 
3766         if (!mHaveBatteryLevel || !mRecordingHistory) {
3767             return;
3768         }
3769 
3770         // If the current time is basically the same as the last time,
3771         // and no states have since the last recorded entry changed and
3772         // are now resetting back to their original value, then just collapse
3773         // into one record.
3774         if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE
3775                 && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+1000)
3776                 && ((mHistoryEnd.states^cur.states)&mChangedStates&mActiveHistoryStates) == 0
3777                 && ((mHistoryEnd.states2^cur.states2)&mChangedStates2&mActiveHistoryStates2) == 0) {
3778             // If the current is the same as the one before, then we no
3779             // longer need the entry.
3780             if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE
3781                     && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+500)
3782                     && mHistoryLastEnd.sameNonEvent(cur)) {
3783                 mHistoryLastEnd.next = null;
3784                 mHistoryEnd.next = mHistoryCache;
3785                 mHistoryCache = mHistoryEnd;
3786                 mHistoryEnd = mHistoryLastEnd;
3787                 mHistoryLastEnd = null;
3788             } else {
3789                 mChangedStates |= mHistoryEnd.states^(cur.states&mActiveHistoryStates);
3790                 mChangedStates2 |= mHistoryEnd.states^(cur.states2&mActiveHistoryStates2);
3791                 mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, cur);
3792             }
3793             return;
3794         }
3795 
3796         mChangedStates = 0;
3797         mChangedStates2 = 0;
3798         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3799     }
3800 
addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code, String name, int uid)3801     public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
3802             String name, int uid) {
3803         mHistoryCur.eventCode = code;
3804         mHistoryCur.eventTag = mHistoryCur.localEventTag;
3805         mHistoryCur.eventTag.string = name;
3806         mHistoryCur.eventTag.uid = uid;
3807         addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
3808     }
3809 
addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur)3810     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) {
3811         HistoryItem rec = mHistoryCache;
3812         if (rec != null) {
3813             mHistoryCache = rec.next;
3814         } else {
3815             rec = new HistoryItem();
3816         }
3817         rec.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
3818 
3819         addHistoryRecordLocked(rec);
3820     }
3821 
addHistoryRecordLocked(HistoryItem rec)3822     void addHistoryRecordLocked(HistoryItem rec) {
3823         mNumHistoryItems++;
3824         rec.next = null;
3825         mHistoryLastEnd = mHistoryEnd;
3826         if (mHistoryEnd != null) {
3827             mHistoryEnd.next = rec;
3828             mHistoryEnd = rec;
3829         } else {
3830             mHistory = mHistoryEnd = rec;
3831         }
3832     }
3833 
clearHistoryLocked()3834     void clearHistoryLocked() {
3835         if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
3836         if (USE_OLD_HISTORY) {
3837             if (mHistory != null) {
3838                 mHistoryEnd.next = mHistoryCache;
3839                 mHistoryCache = mHistory;
3840                 mHistory = mHistoryLastEnd = mHistoryEnd = null;
3841             }
3842             mNumHistoryItems = 0;
3843         }
3844 
3845         mHistoryBaseTime = 0;
3846         mLastHistoryElapsedRealtime = 0;
3847         mTrackRunningHistoryElapsedRealtime = 0;
3848         mTrackRunningHistoryUptime = 0;
3849 
3850         mHistoryBuffer.setDataSize(0);
3851         mHistoryBuffer.setDataPosition(0);
3852         mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
3853         mHistoryLastLastWritten.clear();
3854         mHistoryLastWritten.clear();
3855         mHistoryTagPool.clear();
3856         mNextHistoryTagIdx = 0;
3857         mNumHistoryTagChars = 0;
3858         mHistoryBufferLastPos = -1;
3859         mActiveHistoryStates = 0xffffffff;
3860         mActiveHistoryStates2 = 0xffffffff;
3861     }
3862 
3863     @GuardedBy("this")
updateTimeBasesLocked(boolean unplugged, int screenState, long uptime, long realtime)3864     public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptime,
3865             long realtime) {
3866         final boolean screenOff = !isScreenOn(screenState);
3867         final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
3868         final boolean updateOnBatteryScreenOffTimeBase =
3869                 (unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
3870 
3871         if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) {
3872             if (updateOnBatteryScreenOffTimeBase) {
3873                 updateKernelWakelocksLocked();
3874                 updateBatteryPropertiesLocked();
3875             }
3876             // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
3877             // updateRpmStatsLocked is too slow to run each screen change. When the speed is
3878             // improved, remove the surrounding if{}.
3879             if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
3880                 updateRpmStatsLocked(); // if either OnBattery or OnBatteryScreenOff timebase changes.
3881             }
3882             if (DEBUG_ENERGY_CPU) {
3883                 Slog.d(TAG, "Updating cpu time because screen is now "
3884                         + Display.stateToString(screenState)
3885                         + " and battery is " + (unplugged ? "on" : "off"));
3886             }
3887 
3888             mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime);
3889             if (updateOnBatteryTimeBase) {
3890                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
3891                     mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptime, realtime);
3892                 }
3893             }
3894             if (updateOnBatteryScreenOffTimeBase) {
3895                 mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff, uptime, realtime);
3896                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
3897                     mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptime, realtime);
3898                 }
3899             }
3900         }
3901     }
3902 
updateBatteryPropertiesLocked()3903     private void updateBatteryPropertiesLocked() {
3904         try {
3905             IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
3906                     ServiceManager.getService("batteryproperties"));
3907             if (registrar != null) {
3908                 registrar.scheduleUpdate();
3909             }
3910         } catch (RemoteException e) {
3911             // Ignore.
3912         }
3913     }
3914 
addIsolatedUidLocked(int isolatedUid, int appUid)3915     public void addIsolatedUidLocked(int isolatedUid, int appUid) {
3916         mIsolatedUids.put(isolatedUid, appUid);
3917         final Uid u = getUidStatsLocked(appUid);
3918         u.addIsolatedUid(isolatedUid);
3919     }
3920 
3921     /**
3922      * Schedules a read of the latest cpu times before removing the isolated UID.
3923      * @see #removeIsolatedUidLocked(int)
3924      */
scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid)3925     public void scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid) {
3926         int curUid = mIsolatedUids.get(isolatedUid, -1);
3927         if (curUid == appUid) {
3928             if (mExternalSync != null) {
3929                 mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
3930             }
3931         }
3932     }
3933 
3934     /**
3935      * This should only be called after the cpu times have been read.
3936      * @see #scheduleRemoveIsolatedUidLocked(int, int)
3937      */
3938     @GuardedBy("this")
removeIsolatedUidLocked(int isolatedUid)3939     public void removeIsolatedUidLocked(int isolatedUid) {
3940         final int idx = mIsolatedUids.indexOfKey(isolatedUid);
3941         if (idx >= 0) {
3942             final int ownerUid = mIsolatedUids.valueAt(idx);
3943             final Uid u = getUidStatsLocked(ownerUid);
3944             u.removeIsolatedUid(isolatedUid);
3945             mIsolatedUids.removeAt(idx);
3946         }
3947         mPendingRemovedUids.add(new UidToRemove(isolatedUid, mClocks.elapsedRealtime()));
3948     }
3949 
mapUid(int uid)3950     public int mapUid(int uid) {
3951         int isolated = mIsolatedUids.get(uid, -1);
3952         return isolated > 0 ? isolated : uid;
3953     }
3954 
noteEventLocked(int code, String name, int uid)3955     public void noteEventLocked(int code, String name, int uid) {
3956         uid = mapUid(uid);
3957         if (!mActiveEvents.updateState(code, name, uid, 0)) {
3958             return;
3959         }
3960         final long elapsedRealtime = mClocks.elapsedRealtime();
3961         final long uptime = mClocks.uptimeMillis();
3962         addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
3963     }
3964 
noteCurrentTimeChangedLocked()3965     public void noteCurrentTimeChangedLocked() {
3966         final long currentTime = System.currentTimeMillis();
3967         final long elapsedRealtime = mClocks.elapsedRealtime();
3968         final long uptime = mClocks.uptimeMillis();
3969         recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
3970     }
3971 
noteProcessStartLocked(String name, int uid)3972     public void noteProcessStartLocked(String name, int uid) {
3973         uid = mapUid(uid);
3974         if (isOnBattery()) {
3975             Uid u = getUidStatsLocked(uid);
3976             u.getProcessStatsLocked(name).incStartsLocked();
3977         }
3978         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
3979             return;
3980         }
3981         if (!mRecordAllHistory) {
3982             return;
3983         }
3984         final long elapsedRealtime = mClocks.elapsedRealtime();
3985         final long uptime = mClocks.uptimeMillis();
3986         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid);
3987     }
3988 
noteProcessCrashLocked(String name, int uid)3989     public void noteProcessCrashLocked(String name, int uid) {
3990         uid = mapUid(uid);
3991         if (isOnBattery()) {
3992             Uid u = getUidStatsLocked(uid);
3993             u.getProcessStatsLocked(name).incNumCrashesLocked();
3994         }
3995     }
3996 
noteProcessAnrLocked(String name, int uid)3997     public void noteProcessAnrLocked(String name, int uid) {
3998         uid = mapUid(uid);
3999         if (isOnBattery()) {
4000             Uid u = getUidStatsLocked(uid);
4001             u.getProcessStatsLocked(name).incNumAnrsLocked();
4002         }
4003     }
4004 
noteUidProcessStateLocked(int uid, int state)4005     public void noteUidProcessStateLocked(int uid, int state) {
4006         int parentUid = mapUid(uid);
4007         if (uid != parentUid) {
4008             // Isolated UIDs process state is already rolled up into parent, so no need to track
4009             // Otherwise the parent's process state will get downgraded incorrectly
4010             return;
4011         }
4012         // TODO(b/155216561): It is possible for isolated uids to be in a higher
4013         // state than its parent uid. We should track the highest state within the union of host
4014         // and isolated uids rather than only the parent uid.
4015         FrameworkStatsLog.write(FrameworkStatsLog.UID_PROCESS_STATE_CHANGED, uid,
4016                 ActivityManager.processStateAmToProto(state));
4017         getUidStatsLocked(uid).updateUidProcessStateLocked(state);
4018     }
4019 
noteProcessFinishLocked(String name, int uid)4020     public void noteProcessFinishLocked(String name, int uid) {
4021         uid = mapUid(uid);
4022         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
4023             return;
4024         }
4025         if (!mRecordAllHistory) {
4026             return;
4027         }
4028         final long elapsedRealtime = mClocks.elapsedRealtime();
4029         final long uptime = mClocks.uptimeMillis();
4030         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
4031     }
4032 
noteSyncStartLocked(String name, int uid)4033     public void noteSyncStartLocked(String name, int uid) {
4034         uid = mapUid(uid);
4035         final long elapsedRealtime = mClocks.elapsedRealtime();
4036         final long uptime = mClocks.uptimeMillis();
4037         getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime);
4038         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
4039             return;
4040         }
4041         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_START, name, uid);
4042     }
4043 
noteSyncFinishLocked(String name, int uid)4044     public void noteSyncFinishLocked(String name, int uid) {
4045         uid = mapUid(uid);
4046         final long elapsedRealtime = mClocks.elapsedRealtime();
4047         final long uptime = mClocks.uptimeMillis();
4048         getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime);
4049         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
4050             return;
4051         }
4052         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_FINISH, name, uid);
4053     }
4054 
noteJobStartLocked(String name, int uid)4055     public void noteJobStartLocked(String name, int uid) {
4056         uid = mapUid(uid);
4057         final long elapsedRealtime = mClocks.elapsedRealtime();
4058         final long uptime = mClocks.uptimeMillis();
4059         getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime);
4060         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
4061             return;
4062         }
4063         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid);
4064     }
4065 
noteJobFinishLocked(String name, int uid, int stopReason)4066     public void noteJobFinishLocked(String name, int uid, int stopReason) {
4067         uid = mapUid(uid);
4068         final long elapsedRealtime = mClocks.elapsedRealtime();
4069         final long uptime = mClocks.uptimeMillis();
4070         getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime, stopReason);
4071         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
4072             return;
4073         }
4074         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
4075     }
4076 
noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast)4077     public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast) {
4078         uid = mapUid(uid);
4079         getUidStatsLocked(uid).noteJobsDeferredLocked(numDeferred, sinceLast);
4080     }
4081 
noteAlarmStartLocked(String name, WorkSource workSource, int uid)4082     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
4083         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid);
4084     }
4085 
noteAlarmFinishLocked(String name, WorkSource workSource, int uid)4086     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
4087         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid);
4088     }
4089 
noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, int uid)4090     private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
4091             int uid) {
4092         if (!mRecordAllHistory) {
4093             return;
4094         }
4095 
4096         final long elapsedRealtime = mClocks.elapsedRealtime();
4097         final long uptime = mClocks.uptimeMillis();
4098 
4099         if (workSource != null) {
4100             for (int i = 0; i < workSource.size(); ++i) {
4101                 uid = mapUid(workSource.getUid(i));
4102                 if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4103                     addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4104                 }
4105             }
4106 
4107             List<WorkChain> workChains = workSource.getWorkChains();
4108             if (workChains != null) {
4109                 for (int i = 0; i < workChains.size(); ++i) {
4110                     uid = mapUid(workChains.get(i).getAttributionUid());
4111                     if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4112                         addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4113                     }
4114                 }
4115             }
4116         } else {
4117             uid = mapUid(uid);
4118 
4119             if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4120                 addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4121             }
4122         }
4123     }
4124 
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag)4125     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4126             String tag) {
4127         if (workSource != null) {
4128             for (int i = 0; i < workSource.size(); ++i) {
4129                 uid = workSource.getUid(i);
4130                 final String workSourceName = workSource.getPackageName(i);
4131 
4132                 if (isOnBattery()) {
4133                     BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
4134                             workSourceName != null ? workSourceName : packageName);
4135                     pkg.noteWakeupAlarmLocked(tag);
4136                 }
4137             }
4138 
4139             List<WorkChain> workChains = workSource.getWorkChains();
4140             if (workChains != null) {
4141                 for (int i = 0; i < workChains.size(); ++i) {
4142                     final WorkChain wc = workChains.get(i);
4143                     uid = wc.getAttributionUid();
4144 
4145                     if (isOnBattery()) {
4146                         BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
4147                         pkg.noteWakeupAlarmLocked(tag);
4148                     }
4149                 }
4150             }
4151         } else {
4152             if (isOnBattery()) {
4153                 BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
4154                 pkg.noteWakeupAlarmLocked(tag);
4155             }
4156         }
4157     }
4158 
requestWakelockCpuUpdate()4159     private void requestWakelockCpuUpdate() {
4160         mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS);
4161     }
4162 
requestImmediateCpuUpdate()4163     private void requestImmediateCpuUpdate() {
4164         mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
4165     }
4166 
setRecordAllHistoryLocked(boolean enabled)4167     public void setRecordAllHistoryLocked(boolean enabled) {
4168         mRecordAllHistory = enabled;
4169         if (!enabled) {
4170             // Clear out any existing state.
4171             mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
4172             mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
4173             // Record the currently running processes as stopping, now that we are no
4174             // longer tracking them.
4175             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4176                     HistoryItem.EVENT_PROC);
4177             if (active != null) {
4178                 long mSecRealtime = mClocks.elapsedRealtime();
4179                 final long mSecUptime = mClocks.uptimeMillis();
4180                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4181                     SparseIntArray uids = ent.getValue();
4182                     for (int j=0; j<uids.size(); j++) {
4183                         addHistoryEventLocked(mSecRealtime, mSecUptime,
4184                                 HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
4185                     }
4186                 }
4187             }
4188         } else {
4189             // Record the currently running processes as starting, now that we are tracking them.
4190             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4191                     HistoryItem.EVENT_PROC);
4192             if (active != null) {
4193                 long mSecRealtime = mClocks.elapsedRealtime();
4194                 final long mSecUptime = mClocks.uptimeMillis();
4195                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4196                     SparseIntArray uids = ent.getValue();
4197                     for (int j=0; j<uids.size(); j++) {
4198                         addHistoryEventLocked(mSecRealtime, mSecUptime,
4199                                 HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
4200                     }
4201                 }
4202             }
4203         }
4204     }
4205 
setNoAutoReset(boolean enabled)4206     public void setNoAutoReset(boolean enabled) {
4207         mNoAutoReset = enabled;
4208     }
4209 
setPretendScreenOff(boolean pretendScreenOff)4210     public void setPretendScreenOff(boolean pretendScreenOff) {
4211         if (mPretendScreenOff != pretendScreenOff) {
4212             mPretendScreenOff = pretendScreenOff;
4213             noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON);
4214         }
4215     }
4216 
4217     private String mInitialAcquireWakeName;
4218     private int mInitialAcquireWakeUid = -1;
4219 
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtime, long uptime)4220     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4221         int type, boolean unimportantForLogging, long elapsedRealtime, long uptime) {
4222         uid = mapUid(uid);
4223         if (type == WAKE_TYPE_PARTIAL) {
4224             // Only care about partial wake locks, since full wake locks
4225             // will be canceled when the user puts the screen to sleep.
4226             aggregateLastWakeupUptimeLocked(uptime);
4227             if (historyName == null) {
4228                 historyName = name;
4229             }
4230             if (mRecordAllHistory) {
4231                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
4232                         uid, 0)) {
4233                     addHistoryEventLocked(elapsedRealtime, uptime,
4234                             HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
4235                 }
4236             }
4237             if (mWakeLockNesting == 0) {
4238                 mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
4239                 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
4240                         + Integer.toHexString(mHistoryCur.states));
4241                 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
4242                 mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
4243                 mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
4244                 mWakeLockImportant = !unimportantForLogging;
4245                 addHistoryRecordLocked(elapsedRealtime, uptime);
4246             } else if (!mWakeLockImportant && !unimportantForLogging
4247                     && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
4248                 if (mHistoryLastWritten.wakelockTag != null) {
4249                     // We'll try to update the last tag.
4250                     mHistoryLastWritten.wakelockTag = null;
4251                     mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
4252                     mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
4253                     mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
4254                     addHistoryRecordLocked(elapsedRealtime, uptime);
4255                 }
4256                 mWakeLockImportant = true;
4257             }
4258             mWakeLockNesting++;
4259         }
4260         if (uid >= 0) {
4261             if (mOnBatteryScreenOffTimeBase.isRunning()) {
4262                 // We only update the cpu time when a wake lock is acquired if the screen is off.
4263                 // If the screen is on, we don't distribute the power amongst partial wakelocks.
4264                 if (DEBUG_ENERGY_CPU) {
4265                     Slog.d(TAG, "Updating cpu time because of +wake_lock");
4266                 }
4267                 requestWakelockCpuUpdate();
4268             }
4269 
4270             getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
4271 
4272             if (wc != null) {
4273                 FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(),
4274                         wc.getTags(), getPowerManagerWakeLockLevel(type), name,
4275                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
4276             } else {
4277                 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, uid,
4278                         null, getPowerManagerWakeLockLevel(type), name,
4279                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
4280             }
4281         }
4282     }
4283 
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, long elapsedRealtime, long uptime)4284     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4285             int type, long elapsedRealtime, long uptime) {
4286         uid = mapUid(uid);
4287         if (type == WAKE_TYPE_PARTIAL) {
4288             mWakeLockNesting--;
4289             if (mRecordAllHistory) {
4290                 if (historyName == null) {
4291                     historyName = name;
4292                 }
4293                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
4294                         uid, 0)) {
4295                     addHistoryEventLocked(elapsedRealtime, uptime,
4296                             HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
4297                 }
4298             }
4299             if (mWakeLockNesting == 0) {
4300                 mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
4301                 if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
4302                         + Integer.toHexString(mHistoryCur.states));
4303                 mInitialAcquireWakeName = null;
4304                 mInitialAcquireWakeUid = -1;
4305                 addHistoryRecordLocked(elapsedRealtime, uptime);
4306             }
4307         }
4308         if (uid >= 0) {
4309             if (mOnBatteryScreenOffTimeBase.isRunning()) {
4310                 if (DEBUG_ENERGY_CPU) {
4311                     Slog.d(TAG, "Updating cpu time because of -wake_lock");
4312                 }
4313                 requestWakelockCpuUpdate();
4314             }
4315 
4316             getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
4317             if (wc != null) {
4318                 FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(),
4319                         wc.getTags(), getPowerManagerWakeLockLevel(type), name,
4320                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
4321             } else {
4322                 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, uid,
4323                         null, getPowerManagerWakeLockLevel(type), name,
4324                         FrameworkStatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
4325             }
4326         }
4327     }
4328 
4329     /**
4330      * Converts BatteryStats wakelock types back into PowerManager wakelock levels.
4331      * This is the inverse map of Notifier.getBatteryStatsWakeLockMonitorType().
4332      * These are estimations, since batterystats loses some of the original data.
4333      * TODO: Delete this. Instead, FrameworkStatsLog.write should be called from
4334      * PowerManager's Notifier.
4335      */
getPowerManagerWakeLockLevel(int battertStatsWakelockType)4336     private int getPowerManagerWakeLockLevel(int battertStatsWakelockType) {
4337         switch (battertStatsWakelockType) {
4338             // PowerManager.PARTIAL_WAKE_LOCK or PROXIMITY_SCREEN_OFF_WAKE_LOCK
4339             case BatteryStats.WAKE_TYPE_PARTIAL:
4340                 return PowerManager.PARTIAL_WAKE_LOCK;
4341 
4342             // PowerManager.SCREEN_DIM_WAKE_LOCK or SCREEN_BRIGHT_WAKE_LOCK
4343             case BatteryStats.WAKE_TYPE_FULL:
4344                 return PowerManager.FULL_WAKE_LOCK;
4345 
4346             case BatteryStats.WAKE_TYPE_DRAW:
4347                 return PowerManager.DRAW_WAKE_LOCK;
4348 
4349             // It appears that nothing can ever make a Window and PowerManager lacks an equivalent.
4350             case BatteryStats.WAKE_TYPE_WINDOW:
4351                 Slog.e(TAG, "Illegal window wakelock type observed in batterystats.");
4352                 return -1;
4353 
4354             default:
4355                 Slog.e(TAG, "Illegal wakelock type in batterystats: " + battertStatsWakelockType);
4356                 return -1;
4357         }
4358     }
4359 
noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging)4360     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
4361             String historyName, int type, boolean unimportantForLogging) {
4362         final long elapsedRealtime = mClocks.elapsedRealtime();
4363         final long uptime = mClocks.uptimeMillis();
4364         final int N = ws.size();
4365         for (int i=0; i<N; i++) {
4366             noteStartWakeLocked(ws.getUid(i), pid, null, name, historyName, type,
4367                     unimportantForLogging, elapsedRealtime, uptime);
4368         }
4369 
4370         List<WorkChain> wcs = ws.getWorkChains();
4371         if (wcs != null) {
4372             for (int i = 0; i < wcs.size(); ++i) {
4373                 final WorkChain wc = wcs.get(i);
4374                 noteStartWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4375                         unimportantForLogging, elapsedRealtime, uptime);
4376             }
4377         }
4378     }
4379 
noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, WorkSource newWs, int newPid, String newName, String newHistoryName, int newType, boolean newUnimportantForLogging)4380     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
4381             String historyName, int type, WorkSource newWs, int newPid, String newName,
4382             String newHistoryName, int newType, boolean newUnimportantForLogging) {
4383         final long elapsedRealtime = mClocks.elapsedRealtime();
4384         final long uptime = mClocks.uptimeMillis();
4385 
4386         List<WorkChain>[] wcs = WorkSource.diffChains(ws, newWs);
4387 
4388         // For correct semantics, we start the need worksources first, so that we won't
4389         // make inappropriate history items as if all wake locks went away and new ones
4390         // appeared.  This is okay because tracking of wake locks allows nesting.
4391         //
4392         // First the starts :
4393         final int NN = newWs.size();
4394         for (int i=0; i<NN; i++) {
4395             noteStartWakeLocked(newWs.getUid(i), newPid, null, newName, newHistoryName, newType,
4396                     newUnimportantForLogging, elapsedRealtime, uptime);
4397         }
4398         if (wcs != null) {
4399             List<WorkChain> newChains = wcs[0];
4400             if (newChains != null) {
4401                 for (int i = 0; i < newChains.size(); ++i) {
4402                     final WorkChain newChain = newChains.get(i);
4403                     noteStartWakeLocked(newChain.getAttributionUid(), newPid, newChain, newName,
4404                         newHistoryName, newType, newUnimportantForLogging, elapsedRealtime,
4405                         uptime);
4406                 }
4407             }
4408         }
4409 
4410         // Then the stops :
4411         final int NO = ws.size();
4412         for (int i=0; i<NO; i++) {
4413             noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtime,
4414                     uptime);
4415         }
4416         if (wcs != null) {
4417             List<WorkChain> goneChains = wcs[1];
4418             if (goneChains != null) {
4419                 for (int i = 0; i < goneChains.size(); ++i) {
4420                     final WorkChain goneChain = goneChains.get(i);
4421                     noteStopWakeLocked(goneChain.getAttributionUid(), pid, goneChain, name,
4422                             historyName, type, elapsedRealtime, uptime);
4423                 }
4424             }
4425         }
4426     }
4427 
noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type)4428     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
4429             String historyName, int type) {
4430         final long elapsedRealtime = mClocks.elapsedRealtime();
4431         final long uptime = mClocks.uptimeMillis();
4432         final int N = ws.size();
4433         for (int i=0; i<N; i++) {
4434             noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtime,
4435                     uptime);
4436         }
4437 
4438         List<WorkChain> wcs = ws.getWorkChains();
4439         if (wcs != null) {
4440             for (int i = 0; i < wcs.size(); ++i) {
4441                 final WorkChain wc = wcs.get(i);
4442                 noteStopWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4443                         elapsedRealtime, uptime);
4444             }
4445         }
4446     }
4447 
noteLongPartialWakelockStart(String name, String historyName, int uid)4448     public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
4449         uid = mapUid(uid);
4450         noteLongPartialWakeLockStartInternal(name, historyName, uid);
4451     }
4452 
noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource)4453     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
4454             WorkSource workSource) {
4455         final int N = workSource.size();
4456         for (int i = 0; i < N; ++i) {
4457             final int uid = mapUid(workSource.getUid(i));
4458             noteLongPartialWakeLockStartInternal(name, historyName, uid);
4459         }
4460 
4461         final List<WorkChain> workChains = workSource.getWorkChains();
4462         if (workChains != null) {
4463             for (int i = 0; i < workChains.size(); ++i) {
4464                 final WorkChain workChain = workChains.get(i);
4465                 final int uid = workChain.getAttributionUid();
4466                 noteLongPartialWakeLockStartInternal(name, historyName, uid);
4467             }
4468         }
4469     }
4470 
noteLongPartialWakeLockStartInternal(String name, String historyName, int uid)4471     private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid) {
4472         final long elapsedRealtime = mClocks.elapsedRealtime();
4473         final long uptime = mClocks.uptimeMillis();
4474         if (historyName == null) {
4475             historyName = name;
4476         }
4477         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid,
4478                 0)) {
4479             return;
4480         }
4481         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
4482                 historyName, uid);
4483     }
4484 
noteLongPartialWakelockFinish(String name, String historyName, int uid)4485     public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
4486         uid = mapUid(uid);
4487         noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4488     }
4489 
noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource)4490     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
4491             WorkSource workSource) {
4492         final int N = workSource.size();
4493         for (int i = 0; i < N; ++i) {
4494             final int uid = mapUid(workSource.getUid(i));
4495             noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4496         }
4497 
4498         final List<WorkChain> workChains = workSource.getWorkChains();
4499         if (workChains != null) {
4500             for (int i = 0; i < workChains.size(); ++i) {
4501                 final WorkChain workChain = workChains.get(i);
4502                 final int uid = workChain.getAttributionUid();
4503                 noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4504             }
4505         }
4506     }
4507 
noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid)4508     private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid) {
4509         final long elapsedRealtime = mClocks.elapsedRealtime();
4510         final long uptime = mClocks.uptimeMillis();
4511         if (historyName == null) {
4512             historyName = name;
4513         }
4514         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid,
4515                 0)) {
4516             return;
4517         }
4518         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
4519                 historyName, uid);
4520     }
4521 
aggregateLastWakeupUptimeLocked(long uptimeMs)4522     void aggregateLastWakeupUptimeLocked(long uptimeMs) {
4523         if (mLastWakeupReason != null) {
4524             long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
4525             SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
4526             timer.add(deltaUptime * 1000, 1); // time in in microseconds
4527             FrameworkStatsLog.write(FrameworkStatsLog.KERNEL_WAKEUP_REPORTED, mLastWakeupReason,
4528                     /* duration_usec */ deltaUptime * 1000);
4529             mLastWakeupReason = null;
4530         }
4531     }
4532 
noteWakeupReasonLocked(String reason)4533     public void noteWakeupReasonLocked(String reason) {
4534         final long elapsedRealtime = mClocks.elapsedRealtime();
4535         final long uptime = mClocks.uptimeMillis();
4536         if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
4537                 + Integer.toHexString(mHistoryCur.states));
4538         aggregateLastWakeupUptimeLocked(uptime);
4539         mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
4540         mHistoryCur.wakeReasonTag.string = reason;
4541         mHistoryCur.wakeReasonTag.uid = 0;
4542         mLastWakeupReason = reason;
4543         mLastWakeupUptimeMs = uptime;
4544         addHistoryRecordLocked(elapsedRealtime, uptime);
4545     }
4546 
startAddingCpuLocked()4547     public boolean startAddingCpuLocked() {
4548         mExternalSync.cancelCpuSyncDueToWakelockChange();
4549         return mOnBatteryInternal;
4550     }
4551 
finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime, int statSystemTime, int statIOWaitTime, int statIrqTime, int statSoftIrqTime, int statIdleTime)4552     public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime,
4553                                       int statSystemTime, int statIOWaitTime, int statIrqTime,
4554                                       int statSoftIrqTime, int statIdleTime) {
4555         if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
4556                 + " user=" + statUserTime + " sys=" + statSystemTime
4557                 + " io=" + statIOWaitTime + " irq=" + statIrqTime
4558                 + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime);
4559         mCurStepCpuUserTime += totalUTime;
4560         mCurStepCpuSystemTime += totalSTime;
4561         mCurStepStatUserTime += statUserTime;
4562         mCurStepStatSystemTime += statSystemTime;
4563         mCurStepStatIOWaitTime += statIOWaitTime;
4564         mCurStepStatIrqTime += statIrqTime;
4565         mCurStepStatSoftIrqTime += statSoftIrqTime;
4566         mCurStepStatIdleTime += statIdleTime;
4567     }
4568 
noteProcessDiedLocked(int uid, int pid)4569     public void noteProcessDiedLocked(int uid, int pid) {
4570         uid = mapUid(uid);
4571         Uid u = mUidStats.get(uid);
4572         if (u != null) {
4573             u.mPids.remove(pid);
4574         }
4575     }
4576 
getProcessWakeTime(int uid, int pid, long realtime)4577     public long getProcessWakeTime(int uid, int pid, long realtime) {
4578         uid = mapUid(uid);
4579         Uid u = mUidStats.get(uid);
4580         if (u != null) {
4581             Uid.Pid p = u.mPids.get(pid);
4582             if (p != null) {
4583                 return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0);
4584             }
4585         }
4586         return 0;
4587     }
4588 
reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime)4589     public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
4590         uid = mapUid(uid);
4591         Uid u = mUidStats.get(uid);
4592         if (u != null) {
4593             u.reportExcessiveCpuLocked(proc, overTime, usedTime);
4594         }
4595     }
4596 
4597     int mSensorNesting;
4598 
noteStartSensorLocked(int uid, int sensor)4599     public void noteStartSensorLocked(int uid, int sensor) {
4600         uid = mapUid(uid);
4601         final long elapsedRealtime = mClocks.elapsedRealtime();
4602         final long uptime = mClocks.uptimeMillis();
4603         if (mSensorNesting == 0) {
4604             mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
4605             if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
4606                     + Integer.toHexString(mHistoryCur.states));
4607             addHistoryRecordLocked(elapsedRealtime, uptime);
4608         }
4609         mSensorNesting++;
4610         getUidStatsLocked(uid).noteStartSensor(sensor, elapsedRealtime);
4611     }
4612 
noteStopSensorLocked(int uid, int sensor)4613     public void noteStopSensorLocked(int uid, int sensor) {
4614         uid = mapUid(uid);
4615         final long elapsedRealtime = mClocks.elapsedRealtime();
4616         final long uptime = mClocks.uptimeMillis();
4617         mSensorNesting--;
4618         if (mSensorNesting == 0) {
4619             mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
4620             if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
4621                     + Integer.toHexString(mHistoryCur.states));
4622             addHistoryRecordLocked(elapsedRealtime, uptime);
4623         }
4624         getUidStatsLocked(uid).noteStopSensor(sensor, elapsedRealtime);
4625     }
4626 
4627     int mGpsNesting;
4628 
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs)4629     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
4630         for (int i = 0; i < newWs.size(); ++i) {
4631             noteStartGpsLocked(newWs.getUid(i), null);
4632         }
4633 
4634         for (int i = 0; i < oldWs.size(); ++i) {
4635             noteStopGpsLocked((oldWs.getUid(i)), null);
4636         }
4637 
4638         List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
4639         if (wcs != null) {
4640             if (wcs[0] != null) {
4641                 final List<WorkChain> newChains = wcs[0];
4642                 for (int i = 0; i < newChains.size(); ++i) {
4643                     noteStartGpsLocked(-1, newChains.get(i));
4644                 }
4645             }
4646 
4647             if (wcs[1] != null) {
4648                 final List<WorkChain> goneChains = wcs[1];
4649                 for (int i = 0; i < goneChains.size(); ++i) {
4650                     noteStopGpsLocked(-1, goneChains.get(i));
4651                 }
4652             }
4653         }
4654     }
4655 
noteStartGpsLocked(int uid, WorkChain workChain)4656     private void noteStartGpsLocked(int uid, WorkChain workChain) {
4657         uid = getAttributionUid(uid, workChain);
4658         final long elapsedRealtime = mClocks.elapsedRealtime();
4659         final long uptime = mClocks.uptimeMillis();
4660         if (mGpsNesting == 0) {
4661             mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
4662             if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
4663                     + Integer.toHexString(mHistoryCur.states));
4664             addHistoryRecordLocked(elapsedRealtime, uptime);
4665         }
4666         mGpsNesting++;
4667 
4668         if (workChain == null) {
4669             FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
4670                     FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
4671         } else {
4672             FrameworkStatsLog.write(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED,
4673                     workChain.getUids(), workChain.getTags(),
4674                     FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
4675         }
4676 
4677         getUidStatsLocked(uid).noteStartGps(elapsedRealtime);
4678     }
4679 
noteStopGpsLocked(int uid, WorkChain workChain)4680     private void noteStopGpsLocked(int uid, WorkChain workChain) {
4681         uid = getAttributionUid(uid, workChain);
4682         final long elapsedRealtime = mClocks.elapsedRealtime();
4683         final long uptime = mClocks.uptimeMillis();
4684         mGpsNesting--;
4685         if (mGpsNesting == 0) {
4686             mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
4687             if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
4688                     + Integer.toHexString(mHistoryCur.states));
4689             addHistoryRecordLocked(elapsedRealtime, uptime);
4690             stopAllGpsSignalQualityTimersLocked(-1);
4691             mGpsSignalQualityBin = -1;
4692         }
4693 
4694         if (workChain == null) {
4695             FrameworkStatsLog.write_non_chained(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
4696                     FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
4697         } else {
4698             FrameworkStatsLog.write(FrameworkStatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(),
4699                     workChain.getTags(), FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
4700         }
4701 
4702         getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
4703     }
4704 
noteGpsSignalQualityLocked(int signalLevel)4705     public void noteGpsSignalQualityLocked(int signalLevel) {
4706         if (mGpsNesting == 0) {
4707             return;
4708         }
4709         if (signalLevel < 0 || signalLevel >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
4710             stopAllGpsSignalQualityTimersLocked(-1);
4711             return;
4712         }
4713         final long elapsedRealtime = mClocks.elapsedRealtime();
4714         final long uptime = mClocks.uptimeMillis();
4715         if (mGpsSignalQualityBin != signalLevel) {
4716             if (mGpsSignalQualityBin >= 0) {
4717                 mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtime);
4718             }
4719             if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
4720                 mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtime);
4721             }
4722             mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
4723                     | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
4724             addHistoryRecordLocked(elapsedRealtime, uptime);
4725             mGpsSignalQualityBin = signalLevel;
4726         }
4727         return;
4728     }
4729 
4730     @GuardedBy("this")
noteScreenStateLocked(int state)4731     public void noteScreenStateLocked(int state) {
4732         state = mPretendScreenOff ? Display.STATE_OFF : state;
4733 
4734         // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
4735         // original 4 are mapped to one of the originals.
4736         if (state > MAX_TRACKED_SCREEN_STATE) {
4737             switch (state) {
4738                 case Display.STATE_VR:
4739                     state = Display.STATE_ON;
4740                     break;
4741                 default:
4742                     Slog.wtf(TAG, "Unknown screen state (not mapped): " + state);
4743                     break;
4744             }
4745         }
4746 
4747         if (mScreenState != state) {
4748             recordDailyStatsIfNeededLocked(true);
4749             final int oldState = mScreenState;
4750             mScreenState = state;
4751             if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
4752                     + ", newState=" + Display.stateToString(state));
4753 
4754             if (state != Display.STATE_UNKNOWN) {
4755                 int stepState = state-1;
4756                 if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
4757                     mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
4758                     mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
4759                 } else {
4760                     Slog.wtf(TAG, "Unexpected screen state: " + state);
4761                 }
4762             }
4763 
4764             final long elapsedRealtime = mClocks.elapsedRealtime();
4765             final long uptime = mClocks.uptimeMillis();
4766 
4767             boolean updateHistory = false;
4768             if (isScreenDoze(state) && !isScreenDoze(oldState)) {
4769                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
4770                 mScreenDozeTimer.startRunningLocked(elapsedRealtime);
4771                 updateHistory = true;
4772             } else if (isScreenDoze(oldState) && !isScreenDoze(state)) {
4773                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG;
4774                 mScreenDozeTimer.stopRunningLocked(elapsedRealtime);
4775                 updateHistory = true;
4776             }
4777             if (isScreenOn(state)) {
4778                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
4779                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
4780                         + Integer.toHexString(mHistoryCur.states));
4781                 mScreenOnTimer.startRunningLocked(elapsedRealtime);
4782                 if (mScreenBrightnessBin >= 0) {
4783                     mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
4784                 }
4785                 updateHistory = true;
4786             } else if (isScreenOn(oldState)) {
4787                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
4788                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
4789                         + Integer.toHexString(mHistoryCur.states));
4790                 mScreenOnTimer.stopRunningLocked(elapsedRealtime);
4791                 if (mScreenBrightnessBin >= 0) {
4792                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
4793                 }
4794                 updateHistory = true;
4795             }
4796             if (updateHistory) {
4797                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: "
4798                         + Display.stateToString(state));
4799                 addHistoryRecordLocked(elapsedRealtime, uptime);
4800             }
4801             mExternalSync.scheduleCpuSyncDueToScreenStateChange(
4802                     mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
4803             if (isScreenOn(state)) {
4804                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
4805                         mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
4806                 // Fake a wake lock, so we consider the device waked as long as the screen is on.
4807                 noteStartWakeLocked(-1, -1, null, "screen", null, WAKE_TYPE_PARTIAL, false,
4808                         elapsedRealtime, uptime);
4809             } else if (isScreenOn(oldState)) {
4810                 noteStopWakeLocked(-1, -1, null, "screen", "screen", WAKE_TYPE_PARTIAL,
4811                         elapsedRealtime, uptime);
4812                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
4813                         mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
4814             }
4815             // Update discharge amounts.
4816             if (mOnBatteryInternal) {
4817                 updateDischargeScreenLevelsLocked(oldState, state);
4818             }
4819         }
4820     }
4821 
4822     @UnsupportedAppUsage
noteScreenBrightnessLocked(int brightness)4823     public void noteScreenBrightnessLocked(int brightness) {
4824         // Bin the brightness.
4825         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
4826         if (bin < 0) bin = 0;
4827         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
4828         if (mScreenBrightnessBin != bin) {
4829             final long elapsedRealtime = mClocks.elapsedRealtime();
4830             final long uptime = mClocks.uptimeMillis();
4831             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
4832                     | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
4833             if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
4834                     + Integer.toHexString(mHistoryCur.states));
4835             addHistoryRecordLocked(elapsedRealtime, uptime);
4836             if (mScreenState == Display.STATE_ON) {
4837                 if (mScreenBrightnessBin >= 0) {
4838                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
4839                 }
4840                 mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime);
4841             }
4842             mScreenBrightnessBin = bin;
4843         }
4844     }
4845 
4846     @UnsupportedAppUsage
noteUserActivityLocked(int uid, int event)4847     public void noteUserActivityLocked(int uid, int event) {
4848         if (mOnBatteryInternal) {
4849             uid = mapUid(uid);
4850             getUidStatsLocked(uid).noteUserActivityLocked(event);
4851         }
4852     }
4853 
noteWakeUpLocked(String reason, int reasonUid)4854     public void noteWakeUpLocked(String reason, int reasonUid) {
4855         final long elapsedRealtime = mClocks.elapsedRealtime();
4856         final long uptime = mClocks.uptimeMillis();
4857         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SCREEN_WAKE_UP,
4858                 reason, reasonUid);
4859     }
4860 
noteInteractiveLocked(boolean interactive)4861     public void noteInteractiveLocked(boolean interactive) {
4862         if (mInteractive != interactive) {
4863             final long elapsedRealtime = mClocks.elapsedRealtime();
4864             mInteractive = interactive;
4865             if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
4866             if (interactive) {
4867                 mInteractiveTimer.startRunningLocked(elapsedRealtime);
4868             } else {
4869                 mInteractiveTimer.stopRunningLocked(elapsedRealtime);
4870             }
4871         }
4872     }
4873 
noteConnectivityChangedLocked(int type, String extra)4874     public void noteConnectivityChangedLocked(int type, String extra) {
4875         final long elapsedRealtime = mClocks.elapsedRealtime();
4876         final long uptime = mClocks.uptimeMillis();
4877         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
4878                 extra, type);
4879         mNumConnectivityChange++;
4880     }
4881 
noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)4882     private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
4883             final long uptimeMillis, int uid) {
4884         uid = mapUid(uid);
4885         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
4886                 uid);
4887         getUidStatsLocked(uid).noteMobileRadioApWakeupLocked();
4888     }
4889 
4890     /**
4891      * Updates the radio power state and returns true if an external stats collection should occur.
4892      */
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid)4893     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
4894         final long elapsedRealtime = mClocks.elapsedRealtime();
4895         final long uptime = mClocks.uptimeMillis();
4896         if (mMobileRadioPowerState != powerState) {
4897             long realElapsedRealtimeMs;
4898             final boolean active =
4899                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
4900                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
4901             if (active) {
4902                 if (uid > 0) {
4903                     noteMobileRadioApWakeupLocked(elapsedRealtime, uptime, uid);
4904                 }
4905 
4906                 mMobileRadioActiveStartTime = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
4907                 mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
4908             } else {
4909                 realElapsedRealtimeMs = timestampNs / (1000*1000);
4910                 long lastUpdateTimeMs = mMobileRadioActiveStartTime;
4911                 if (realElapsedRealtimeMs < lastUpdateTimeMs) {
4912                     Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
4913                             + " is before start time " + lastUpdateTimeMs);
4914                     realElapsedRealtimeMs = elapsedRealtime;
4915                 } else if (realElapsedRealtimeMs < elapsedRealtime) {
4916                     mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
4917                             - realElapsedRealtimeMs);
4918                 }
4919                 mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
4920             }
4921             if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
4922                     + Integer.toHexString(mHistoryCur.states));
4923             addHistoryRecordLocked(elapsedRealtime, uptime);
4924             mMobileRadioPowerState = powerState;
4925             if (active) {
4926                 mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
4927                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
4928             } else {
4929                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
4930                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
4931                 // Tell the caller to collect radio network/power stats.
4932                 return true;
4933             }
4934         }
4935         return false;
4936     }
4937 
notePowerSaveModeLocked(boolean enabled)4938     public void notePowerSaveModeLocked(boolean enabled) {
4939         if (mPowerSaveModeEnabled != enabled) {
4940             int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
4941             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
4942             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
4943             final long elapsedRealtime = mClocks.elapsedRealtime();
4944             final long uptime = mClocks.uptimeMillis();
4945             mPowerSaveModeEnabled = enabled;
4946             if (enabled) {
4947                 mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
4948                 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
4949                         + Integer.toHexString(mHistoryCur.states2));
4950                 mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtime);
4951             } else {
4952                 mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
4953                 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
4954                         + Integer.toHexString(mHistoryCur.states2));
4955                 mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtime);
4956             }
4957             addHistoryRecordLocked(elapsedRealtime, uptime);
4958             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
4959                     enabled
4960                         ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
4961                         : FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
4962         }
4963     }
4964 
noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid)4965     public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid) {
4966         final long elapsedRealtime = mClocks.elapsedRealtime();
4967         final long uptime = mClocks.uptimeMillis();
4968         boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
4969         if (mDeviceIdling && !nowIdling && activeReason == null) {
4970             // We don't go out of general idling mode until explicitly taken out of
4971             // device idle through going active or significant motion.
4972             nowIdling = true;
4973         }
4974         boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
4975         if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
4976             // We don't go out of general light idling mode until explicitly taken out of
4977             // device idle through going active or significant motion.
4978             nowLightIdling = true;
4979         }
4980         if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
4981             addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
4982                     activeReason, activeUid);
4983         }
4984         if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
4985             int statsmode;
4986             if (nowIdling)           statsmode = DEVICE_IDLE_MODE_DEEP;
4987             else if (nowLightIdling) statsmode = DEVICE_IDLE_MODE_LIGHT;
4988             else                     statsmode = DEVICE_IDLE_MODE_OFF;
4989             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLING_MODE_STATE_CHANGED, statsmode);
4990         }
4991         if (mDeviceIdling != nowIdling) {
4992             mDeviceIdling = nowIdling;
4993             int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
4994             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
4995             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
4996             if (nowIdling) {
4997                 mDeviceIdlingTimer.startRunningLocked(elapsedRealtime);
4998             } else {
4999                 mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime);
5000             }
5001         }
5002         if (mDeviceLightIdling != nowLightIdling) {
5003             mDeviceLightIdling = nowLightIdling;
5004             if (nowLightIdling) {
5005                 mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtime);
5006             } else {
5007                 mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtime);
5008             }
5009         }
5010         if (mDeviceIdleMode != mode) {
5011             mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
5012                     | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
5013             if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
5014                     + Integer.toHexString(mHistoryCur.states2));
5015             addHistoryRecordLocked(elapsedRealtime, uptime);
5016             long lastDuration = elapsedRealtime - mLastIdleTimeStart;
5017             mLastIdleTimeStart = elapsedRealtime;
5018             if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
5019                 if (lastDuration > mLongestLightIdleTime) {
5020                     mLongestLightIdleTime = lastDuration;
5021                 }
5022                 mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtime);
5023             } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
5024                 if (lastDuration > mLongestFullIdleTime) {
5025                     mLongestFullIdleTime = lastDuration;
5026                 }
5027                 mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtime);
5028             }
5029             if (mode == DEVICE_IDLE_MODE_LIGHT) {
5030                 mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtime);
5031             } else if (mode == DEVICE_IDLE_MODE_DEEP) {
5032                 mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtime);
5033             }
5034             mDeviceIdleMode = mode;
5035             FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mode);
5036         }
5037     }
5038 
notePackageInstalledLocked(String pkgName, long versionCode)5039     public void notePackageInstalledLocked(String pkgName, long versionCode) {
5040         final long elapsedRealtime = mClocks.elapsedRealtime();
5041         final long uptime = mClocks.uptimeMillis();
5042         // XXX need to figure out what to do with long version codes.
5043         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED,
5044                 pkgName, (int)versionCode);
5045         PackageChange pc = new PackageChange();
5046         pc.mPackageName = pkgName;
5047         pc.mUpdate = true;
5048         pc.mVersionCode = versionCode;
5049         addPackageChange(pc);
5050     }
5051 
notePackageUninstalledLocked(String pkgName)5052     public void notePackageUninstalledLocked(String pkgName) {
5053         final long elapsedRealtime = mClocks.elapsedRealtime();
5054         final long uptime = mClocks.uptimeMillis();
5055         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
5056                 pkgName, 0);
5057         PackageChange pc = new PackageChange();
5058         pc.mPackageName = pkgName;
5059         pc.mUpdate = true;
5060         addPackageChange(pc);
5061     }
5062 
addPackageChange(PackageChange pc)5063     private void addPackageChange(PackageChange pc) {
5064         if (mDailyPackageChanges == null) {
5065             mDailyPackageChanges = new ArrayList<>();
5066         }
5067         mDailyPackageChanges.add(pc);
5068     }
5069 
stopAllGpsSignalQualityTimersLocked(int except)5070     void stopAllGpsSignalQualityTimersLocked(int except) {
5071         final long elapsedRealtime = mClocks.elapsedRealtime();
5072         for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
5073             if (i == except) {
5074                 continue;
5075             }
5076             while (mGpsSignalQualityTimer[i].isRunningLocked()) {
5077                 mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtime);
5078             }
5079         }
5080     }
5081 
5082     @UnsupportedAppUsage
notePhoneOnLocked()5083     public void notePhoneOnLocked() {
5084         if (!mPhoneOn) {
5085             final long elapsedRealtime = mClocks.elapsedRealtime();
5086             final long uptime = mClocks.uptimeMillis();
5087             mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
5088             if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
5089                     + Integer.toHexString(mHistoryCur.states));
5090             addHistoryRecordLocked(elapsedRealtime, uptime);
5091             mPhoneOn = true;
5092             mPhoneOnTimer.startRunningLocked(elapsedRealtime);
5093         }
5094     }
5095 
5096     @UnsupportedAppUsage
notePhoneOffLocked()5097     public void notePhoneOffLocked() {
5098         if (mPhoneOn) {
5099             final long elapsedRealtime = mClocks.elapsedRealtime();
5100             final long uptime = mClocks.uptimeMillis();
5101             mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
5102             if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
5103                     + Integer.toHexString(mHistoryCur.states));
5104             addHistoryRecordLocked(elapsedRealtime, uptime);
5105             mPhoneOn = false;
5106             mPhoneOnTimer.stopRunningLocked(elapsedRealtime);
5107         }
5108     }
5109 
registerUsbStateReceiver(Context context)5110     private void registerUsbStateReceiver(Context context) {
5111         final IntentFilter usbStateFilter = new IntentFilter();
5112         usbStateFilter.addAction(UsbManager.ACTION_USB_STATE);
5113         context.registerReceiver(new BroadcastReceiver() {
5114             @Override
5115             public void onReceive(Context context, Intent intent) {
5116                 final boolean state = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
5117                 synchronized (BatteryStatsImpl.this) {
5118                     noteUsbConnectionStateLocked(state);
5119                 }
5120             }
5121         }, usbStateFilter);
5122         synchronized (this) {
5123             if (mUsbDataState == USB_DATA_UNKNOWN) {
5124                 final Intent usbState = context.registerReceiver(null, usbStateFilter);
5125                 final boolean initState = usbState != null && usbState.getBooleanExtra(
5126                         UsbManager.USB_CONNECTED, false);
5127                 noteUsbConnectionStateLocked(initState);
5128             }
5129         }
5130     }
5131 
noteUsbConnectionStateLocked(boolean connected)5132     private void noteUsbConnectionStateLocked(boolean connected) {
5133         int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED;
5134         if (mUsbDataState != newState) {
5135             mUsbDataState = newState;
5136             if (connected) {
5137                 mHistoryCur.states2 |= HistoryItem.STATE2_USB_DATA_LINK_FLAG;
5138             } else {
5139                 mHistoryCur.states2 &= ~HistoryItem.STATE2_USB_DATA_LINK_FLAG;
5140             }
5141             addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5142         }
5143     }
5144 
stopAllPhoneSignalStrengthTimersLocked(int except)5145     void stopAllPhoneSignalStrengthTimersLocked(int except) {
5146         final long elapsedRealtime = mClocks.elapsedRealtime();
5147         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
5148             if (i == except) {
5149                 continue;
5150             }
5151             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
5152                 mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
5153             }
5154         }
5155     }
5156 
fixPhoneServiceState(int state, int signalBin)5157     private int fixPhoneServiceState(int state, int signalBin) {
5158         if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
5159             // In this case we will always be STATE_OUT_OF_SERVICE, so need
5160             // to infer that we are scanning from other data.
5161             if (state == ServiceState.STATE_OUT_OF_SERVICE
5162                     && signalBin > CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5163                 state = ServiceState.STATE_IN_SERVICE;
5164             }
5165         }
5166 
5167         return state;
5168     }
5169 
updateAllPhoneStateLocked(int state, int simState, int strengthBin)5170     private void updateAllPhoneStateLocked(int state, int simState, int strengthBin) {
5171         boolean scanning = false;
5172         boolean newHistory = false;
5173 
5174         mPhoneServiceStateRaw = state;
5175         mPhoneSimStateRaw = simState;
5176         mPhoneSignalStrengthBinRaw = strengthBin;
5177 
5178         final long elapsedRealtime = mClocks.elapsedRealtime();
5179         final long uptime = mClocks.uptimeMillis();
5180 
5181         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
5182             // In this case we will always be STATE_OUT_OF_SERVICE, so need
5183             // to infer that we are scanning from other data.
5184             if (state == ServiceState.STATE_OUT_OF_SERVICE
5185                     && strengthBin > CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5186                 state = ServiceState.STATE_IN_SERVICE;
5187             }
5188         }
5189 
5190         // If the phone is powered off, stop all timers.
5191         if (state == ServiceState.STATE_POWER_OFF) {
5192             strengthBin = -1;
5193 
5194         // If we are in service, make sure the correct signal string timer is running.
5195         } else if (state == ServiceState.STATE_IN_SERVICE) {
5196             // Bin will be changed below.
5197 
5198         // If we're out of service, we are in the lowest signal strength
5199         // bin and have the scanning bit set.
5200         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
5201             scanning = true;
5202             strengthBin = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
5203             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
5204                 mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
5205                 newHistory = true;
5206                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
5207                         + Integer.toHexString(mHistoryCur.states));
5208                 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
5209                 FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
5210                         simState, strengthBin);
5211             }
5212         }
5213 
5214         if (!scanning) {
5215             // If we are no longer scanning, then stop the scanning timer.
5216             if (mPhoneSignalScanningTimer.isRunningLocked()) {
5217                 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
5218                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
5219                         + Integer.toHexString(mHistoryCur.states));
5220                 newHistory = true;
5221                 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
5222                 FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
5223                         simState, strengthBin);
5224             }
5225         }
5226 
5227         if (mPhoneServiceState != state) {
5228             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
5229                     | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
5230             if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
5231                     + Integer.toHexString(mHistoryCur.states));
5232             newHistory = true;
5233             mPhoneServiceState = state;
5234         }
5235 
5236         if (mPhoneSignalStrengthBin != strengthBin) {
5237             if (mPhoneSignalStrengthBin >= 0) {
5238                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
5239                         elapsedRealtime);
5240             }
5241             if (strengthBin >= 0) {
5242                 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
5243                     mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
5244                 }
5245                 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
5246                         | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
5247                 if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
5248                         + Integer.toHexString(mHistoryCur.states));
5249                 newHistory = true;
5250                 FrameworkStatsLog.write(
5251                         FrameworkStatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
5252             } else {
5253                 stopAllPhoneSignalStrengthTimersLocked(-1);
5254             }
5255             mPhoneSignalStrengthBin = strengthBin;
5256         }
5257 
5258         if (newHistory) {
5259             addHistoryRecordLocked(elapsedRealtime, uptime);
5260         }
5261     }
5262 
5263     /**
5264      * Telephony stack updates the phone state.
5265      * @param state phone state from ServiceState.getState()
5266      */
notePhoneStateLocked(int state, int simState)5267     public void notePhoneStateLocked(int state, int simState) {
5268         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
5269     }
5270 
5271     @UnsupportedAppUsage
notePhoneSignalStrengthLocked(SignalStrength signalStrength)5272     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
5273         // Bin the strength.
5274         int bin = signalStrength.getLevel();
5275         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
5276     }
5277 
5278     @UnsupportedAppUsage
notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType)5279     public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType) {
5280         // BatteryStats uses 0 to represent no network type.
5281         // Telephony does not have a concept of no network type, and uses 0 to represent unknown.
5282         // Unknown is included in DATA_CONNECTION_OTHER.
5283         int bin = DATA_CONNECTION_OUT_OF_SERVICE;
5284         if (hasData) {
5285             if (dataType > 0 && dataType <= TelephonyManager.getAllNetworkTypes().length) {
5286                 bin = dataType;
5287             } else {
5288                 switch (serviceType) {
5289                     case ServiceState.STATE_OUT_OF_SERVICE:
5290                         bin = DATA_CONNECTION_OUT_OF_SERVICE;
5291                         break;
5292                     case ServiceState.STATE_EMERGENCY_ONLY:
5293                         bin = DATA_CONNECTION_EMERGENCY_SERVICE;
5294                         break;
5295                     default:
5296                         bin = DATA_CONNECTION_OTHER;
5297                         break;
5298                 }
5299             }
5300         }
5301         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
5302         if (mPhoneDataConnectionType != bin) {
5303             final long elapsedRealtime = mClocks.elapsedRealtime();
5304             final long uptime = mClocks.uptimeMillis();
5305             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
5306                     | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
5307             if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
5308                     + Integer.toHexString(mHistoryCur.states));
5309             addHistoryRecordLocked(elapsedRealtime, uptime);
5310             if (mPhoneDataConnectionType >= 0) {
5311                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
5312                         elapsedRealtime);
5313             }
5314             mPhoneDataConnectionType = bin;
5315             mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime);
5316         }
5317     }
5318 
noteWifiOnLocked()5319     public void noteWifiOnLocked() {
5320         if (!mWifiOn) {
5321             final long elapsedRealtime = mClocks.elapsedRealtime();
5322             final long uptime = mClocks.uptimeMillis();
5323             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
5324             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
5325                     + Integer.toHexString(mHistoryCur.states));
5326             addHistoryRecordLocked(elapsedRealtime, uptime);
5327             mWifiOn = true;
5328             mWifiOnTimer.startRunningLocked(elapsedRealtime);
5329             scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
5330         }
5331     }
5332 
noteWifiOffLocked()5333     public void noteWifiOffLocked() {
5334         final long elapsedRealtime = mClocks.elapsedRealtime();
5335         final long uptime = mClocks.uptimeMillis();
5336         if (mWifiOn) {
5337             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
5338             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
5339                     + Integer.toHexString(mHistoryCur.states));
5340             addHistoryRecordLocked(elapsedRealtime, uptime);
5341             mWifiOn = false;
5342             mWifiOnTimer.stopRunningLocked(elapsedRealtime);
5343             scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
5344         }
5345     }
5346 
5347     @UnsupportedAppUsage
noteAudioOnLocked(int uid)5348     public void noteAudioOnLocked(int uid) {
5349         uid = mapUid(uid);
5350         final long elapsedRealtime = mClocks.elapsedRealtime();
5351         final long uptime = mClocks.uptimeMillis();
5352         if (mAudioOnNesting == 0) {
5353             mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
5354             if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
5355                     + Integer.toHexString(mHistoryCur.states));
5356             addHistoryRecordLocked(elapsedRealtime, uptime);
5357             mAudioOnTimer.startRunningLocked(elapsedRealtime);
5358         }
5359         mAudioOnNesting++;
5360         getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
5361     }
5362 
5363     @UnsupportedAppUsage
noteAudioOffLocked(int uid)5364     public void noteAudioOffLocked(int uid) {
5365         if (mAudioOnNesting == 0) {
5366             return;
5367         }
5368         uid = mapUid(uid);
5369         final long elapsedRealtime = mClocks.elapsedRealtime();
5370         final long uptime = mClocks.uptimeMillis();
5371         if (--mAudioOnNesting == 0) {
5372             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
5373             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
5374                     + Integer.toHexString(mHistoryCur.states));
5375             addHistoryRecordLocked(elapsedRealtime, uptime);
5376             mAudioOnTimer.stopRunningLocked(elapsedRealtime);
5377         }
5378         getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
5379     }
5380 
5381     @UnsupportedAppUsage
noteVideoOnLocked(int uid)5382     public void noteVideoOnLocked(int uid) {
5383         uid = mapUid(uid);
5384         final long elapsedRealtime = mClocks.elapsedRealtime();
5385         final long uptime = mClocks.uptimeMillis();
5386         if (mVideoOnNesting == 0) {
5387             mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
5388             if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
5389                     + Integer.toHexString(mHistoryCur.states));
5390             addHistoryRecordLocked(elapsedRealtime, uptime);
5391             mVideoOnTimer.startRunningLocked(elapsedRealtime);
5392         }
5393         mVideoOnNesting++;
5394         getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
5395     }
5396 
5397     @UnsupportedAppUsage
noteVideoOffLocked(int uid)5398     public void noteVideoOffLocked(int uid) {
5399         if (mVideoOnNesting == 0) {
5400             return;
5401         }
5402         uid = mapUid(uid);
5403         final long elapsedRealtime = mClocks.elapsedRealtime();
5404         final long uptime = mClocks.uptimeMillis();
5405         if (--mVideoOnNesting == 0) {
5406             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
5407             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
5408                     + Integer.toHexString(mHistoryCur.states));
5409             addHistoryRecordLocked(elapsedRealtime, uptime);
5410             mVideoOnTimer.stopRunningLocked(elapsedRealtime);
5411         }
5412         getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime);
5413     }
5414 
noteResetAudioLocked()5415     public void noteResetAudioLocked() {
5416         if (mAudioOnNesting > 0) {
5417             final long elapsedRealtime = mClocks.elapsedRealtime();
5418             final long uptime = mClocks.uptimeMillis();
5419             mAudioOnNesting = 0;
5420             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
5421             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
5422                     + Integer.toHexString(mHistoryCur.states));
5423             addHistoryRecordLocked(elapsedRealtime, uptime);
5424             mAudioOnTimer.stopAllRunningLocked(elapsedRealtime);
5425             for (int i=0; i<mUidStats.size(); i++) {
5426                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5427                 uid.noteResetAudioLocked(elapsedRealtime);
5428             }
5429         }
5430     }
5431 
noteResetVideoLocked()5432     public void noteResetVideoLocked() {
5433         if (mVideoOnNesting > 0) {
5434             final long elapsedRealtime = mClocks.elapsedRealtime();
5435             final long uptime = mClocks.uptimeMillis();
5436             mAudioOnNesting = 0;
5437             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
5438             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
5439                     + Integer.toHexString(mHistoryCur.states));
5440             addHistoryRecordLocked(elapsedRealtime, uptime);
5441             mVideoOnTimer.stopAllRunningLocked(elapsedRealtime);
5442             for (int i=0; i<mUidStats.size(); i++) {
5443                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5444                 uid.noteResetVideoLocked(elapsedRealtime);
5445             }
5446         }
5447     }
5448 
noteActivityResumedLocked(int uid)5449     public void noteActivityResumedLocked(int uid) {
5450         uid = mapUid(uid);
5451         getUidStatsLocked(uid).noteActivityResumedLocked(mClocks.elapsedRealtime());
5452     }
5453 
noteActivityPausedLocked(int uid)5454     public void noteActivityPausedLocked(int uid) {
5455         uid = mapUid(uid);
5456         getUidStatsLocked(uid).noteActivityPausedLocked(mClocks.elapsedRealtime());
5457     }
5458 
noteVibratorOnLocked(int uid, long durationMillis)5459     public void noteVibratorOnLocked(int uid, long durationMillis) {
5460         uid = mapUid(uid);
5461         getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis);
5462     }
5463 
noteVibratorOffLocked(int uid)5464     public void noteVibratorOffLocked(int uid) {
5465         uid = mapUid(uid);
5466         getUidStatsLocked(uid).noteVibratorOffLocked();
5467     }
5468 
noteFlashlightOnLocked(int uid)5469     public void noteFlashlightOnLocked(int uid) {
5470         uid = mapUid(uid);
5471         final long elapsedRealtime = mClocks.elapsedRealtime();
5472         final long uptime = mClocks.uptimeMillis();
5473         if (mFlashlightOnNesting++ == 0) {
5474             mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
5475             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
5476                     + Integer.toHexString(mHistoryCur.states2));
5477             addHistoryRecordLocked(elapsedRealtime, uptime);
5478             mFlashlightOnTimer.startRunningLocked(elapsedRealtime);
5479         }
5480         getUidStatsLocked(uid).noteFlashlightTurnedOnLocked(elapsedRealtime);
5481     }
5482 
noteFlashlightOffLocked(int uid)5483     public void noteFlashlightOffLocked(int uid) {
5484         if (mFlashlightOnNesting == 0) {
5485             return;
5486         }
5487         uid = mapUid(uid);
5488         final long elapsedRealtime = mClocks.elapsedRealtime();
5489         final long uptime = mClocks.uptimeMillis();
5490         if (--mFlashlightOnNesting == 0) {
5491             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
5492             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
5493                     + Integer.toHexString(mHistoryCur.states2));
5494             addHistoryRecordLocked(elapsedRealtime, uptime);
5495             mFlashlightOnTimer.stopRunningLocked(elapsedRealtime);
5496         }
5497         getUidStatsLocked(uid).noteFlashlightTurnedOffLocked(elapsedRealtime);
5498     }
5499 
noteCameraOnLocked(int uid)5500     public void noteCameraOnLocked(int uid) {
5501         uid = mapUid(uid);
5502         final long elapsedRealtime = mClocks.elapsedRealtime();
5503         final long uptime = mClocks.uptimeMillis();
5504         if (mCameraOnNesting++ == 0) {
5505             mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
5506             if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
5507                     + Integer.toHexString(mHistoryCur.states2));
5508             addHistoryRecordLocked(elapsedRealtime, uptime);
5509             mCameraOnTimer.startRunningLocked(elapsedRealtime);
5510         }
5511         getUidStatsLocked(uid).noteCameraTurnedOnLocked(elapsedRealtime);
5512     }
5513 
noteCameraOffLocked(int uid)5514     public void noteCameraOffLocked(int uid) {
5515         if (mCameraOnNesting == 0) {
5516             return;
5517         }
5518         uid = mapUid(uid);
5519         final long elapsedRealtime = mClocks.elapsedRealtime();
5520         final long uptime = mClocks.uptimeMillis();
5521         if (--mCameraOnNesting == 0) {
5522             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
5523             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
5524                     + Integer.toHexString(mHistoryCur.states2));
5525             addHistoryRecordLocked(elapsedRealtime, uptime);
5526             mCameraOnTimer.stopRunningLocked(elapsedRealtime);
5527         }
5528         getUidStatsLocked(uid).noteCameraTurnedOffLocked(elapsedRealtime);
5529     }
5530 
noteResetCameraLocked()5531     public void noteResetCameraLocked() {
5532         if (mCameraOnNesting > 0) {
5533             final long elapsedRealtime = mClocks.elapsedRealtime();
5534             final long uptime = mClocks.uptimeMillis();
5535             mCameraOnNesting = 0;
5536             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
5537             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
5538                     + Integer.toHexString(mHistoryCur.states2));
5539             addHistoryRecordLocked(elapsedRealtime, uptime);
5540             mCameraOnTimer.stopAllRunningLocked(elapsedRealtime);
5541             for (int i=0; i<mUidStats.size(); i++) {
5542                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5543                 uid.noteResetCameraLocked(elapsedRealtime);
5544             }
5545         }
5546     }
5547 
noteResetFlashlightLocked()5548     public void noteResetFlashlightLocked() {
5549         if (mFlashlightOnNesting > 0) {
5550             final long elapsedRealtime = mClocks.elapsedRealtime();
5551             final long uptime = mClocks.uptimeMillis();
5552             mFlashlightOnNesting = 0;
5553             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
5554             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
5555                     + Integer.toHexString(mHistoryCur.states2));
5556             addHistoryRecordLocked(elapsedRealtime, uptime);
5557             mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtime);
5558             for (int i=0; i<mUidStats.size(); i++) {
5559                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5560                 uid.noteResetFlashlightLocked(elapsedRealtime);
5561             }
5562         }
5563     }
5564 
noteBluetoothScanStartedLocked(WorkChain workChain, int uid, boolean isUnoptimized)5565     private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
5566             boolean isUnoptimized) {
5567         uid = getAttributionUid(uid, workChain);
5568         final long elapsedRealtime = mClocks.elapsedRealtime();
5569         final long uptime = mClocks.uptimeMillis();
5570         if (mBluetoothScanNesting == 0) {
5571             mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5572             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
5573                     + Integer.toHexString(mHistoryCur.states2));
5574             addHistoryRecordLocked(elapsedRealtime, uptime);
5575             mBluetoothScanTimer.startRunningLocked(elapsedRealtime);
5576         }
5577         mBluetoothScanNesting++;
5578         getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime, isUnoptimized);
5579     }
5580 
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized)5581     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
5582         final int N = ws.size();
5583         for (int i = 0; i < N; i++) {
5584             noteBluetoothScanStartedLocked(null, ws.getUid(i), isUnoptimized);
5585         }
5586 
5587         final List<WorkChain> workChains = ws.getWorkChains();
5588         if (workChains != null) {
5589             for (int i = 0; i < workChains.size(); ++i) {
5590                 noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized);
5591             }
5592         }
5593     }
5594 
noteBluetoothScanStoppedLocked(WorkChain workChain, int uid, boolean isUnoptimized)5595     private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
5596             boolean isUnoptimized) {
5597         uid = getAttributionUid(uid, workChain);
5598         final long elapsedRealtime = mClocks.elapsedRealtime();
5599         final long uptime = mClocks.uptimeMillis();
5600         mBluetoothScanNesting--;
5601         if (mBluetoothScanNesting == 0) {
5602             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5603             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
5604                     + Integer.toHexString(mHistoryCur.states2));
5605             addHistoryRecordLocked(elapsedRealtime, uptime);
5606             mBluetoothScanTimer.stopRunningLocked(elapsedRealtime);
5607         }
5608         getUidStatsLocked(uid).noteBluetoothScanStoppedLocked(elapsedRealtime, isUnoptimized);
5609     }
5610 
getAttributionUid(int uid, WorkChain workChain)5611     private int getAttributionUid(int uid, WorkChain workChain) {
5612         if (workChain != null) {
5613             return mapUid(workChain.getAttributionUid());
5614         }
5615 
5616         return mapUid(uid);
5617     }
5618 
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized)5619     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
5620         final int N = ws.size();
5621         for (int i = 0; i < N; i++) {
5622             noteBluetoothScanStoppedLocked(null, ws.getUid(i), isUnoptimized);
5623         }
5624 
5625         final List<WorkChain> workChains = ws.getWorkChains();
5626         if (workChains != null) {
5627             for (int i = 0; i < workChains.size(); ++i) {
5628                 noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized);
5629             }
5630         }
5631     }
5632 
noteResetBluetoothScanLocked()5633     public void noteResetBluetoothScanLocked() {
5634         if (mBluetoothScanNesting > 0) {
5635             final long elapsedRealtime = mClocks.elapsedRealtime();
5636             final long uptime = mClocks.uptimeMillis();
5637             mBluetoothScanNesting = 0;
5638             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5639             if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
5640                     + Integer.toHexString(mHistoryCur.states2));
5641             addHistoryRecordLocked(elapsedRealtime, uptime);
5642             mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtime);
5643             for (int i=0; i<mUidStats.size(); i++) {
5644                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5645                 uid.noteResetBluetoothScanLocked(elapsedRealtime);
5646             }
5647         }
5648     }
5649 
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults)5650     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
5651         final int N = ws.size();
5652         for (int i = 0; i < N; i++) {
5653             int uid = mapUid(ws.getUid(i));
5654             getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
5655         }
5656 
5657         final List<WorkChain> workChains = ws.getWorkChains();
5658         if (workChains != null) {
5659             for (int i = 0; i < workChains.size(); ++i) {
5660                 final WorkChain wc = workChains.get(i);
5661                 int uid = mapUid(wc.getAttributionUid());
5662                 getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
5663             }
5664         }
5665     }
5666 
noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)5667     private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
5668             final long uptimeMillis, int uid) {
5669         uid = mapUid(uid);
5670         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
5671                 uid);
5672         getUidStatsLocked(uid).noteWifiRadioApWakeupLocked();
5673     }
5674 
noteWifiRadioPowerState(int powerState, long timestampNs, int uid)5675     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) {
5676         final long elapsedRealtime = mClocks.elapsedRealtime();
5677         final long uptime = mClocks.uptimeMillis();
5678         if (mWifiRadioPowerState != powerState) {
5679             final boolean active =
5680                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
5681                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
5682             if (active) {
5683                 if (uid > 0) {
5684                     noteWifiRadioApWakeupLocked(elapsedRealtime, uptime, uid);
5685                 }
5686                 mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
5687                 mWifiActiveTimer.startRunningLocked(elapsedRealtime);
5688             } else {
5689                 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
5690                 mWifiActiveTimer.stopRunningLocked(
5691                     timestampNs / (1000 * 1000));
5692             }
5693             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
5694                     + Integer.toHexString(mHistoryCur.states));
5695             addHistoryRecordLocked(elapsedRealtime, uptime);
5696             mWifiRadioPowerState = powerState;
5697         }
5698     }
5699 
noteWifiRunningLocked(WorkSource ws)5700     public void noteWifiRunningLocked(WorkSource ws) {
5701         if (!mGlobalWifiRunning) {
5702             final long elapsedRealtime = mClocks.elapsedRealtime();
5703             final long uptime = mClocks.uptimeMillis();
5704             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
5705             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
5706                     + Integer.toHexString(mHistoryCur.states));
5707             addHistoryRecordLocked(elapsedRealtime, uptime);
5708             mGlobalWifiRunning = true;
5709             mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
5710             int N = ws.size();
5711             for (int i=0; i<N; i++) {
5712                 int uid = mapUid(ws.getUid(i));
5713                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5714             }
5715 
5716             List<WorkChain> workChains = ws.getWorkChains();
5717             if (workChains != null) {
5718                 for (int i = 0; i < workChains.size(); ++i) {
5719                     int uid = mapUid(workChains.get(i).getAttributionUid());
5720                     getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5721                 }
5722             }
5723 
5724             scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
5725         } else {
5726             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
5727         }
5728     }
5729 
noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs)5730     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
5731         if (mGlobalWifiRunning) {
5732             final long elapsedRealtime = mClocks.elapsedRealtime();
5733             int N = oldWs.size();
5734             for (int i=0; i<N; i++) {
5735                 int uid = mapUid(oldWs.getUid(i));
5736                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5737             }
5738 
5739             List<WorkChain> workChains = oldWs.getWorkChains();
5740             if (workChains != null) {
5741                 for (int i = 0; i < workChains.size(); ++i) {
5742                     int uid = mapUid(workChains.get(i).getAttributionUid());
5743                     getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5744                 }
5745             }
5746 
5747             N = newWs.size();
5748             for (int i=0; i<N; i++) {
5749                 int uid = mapUid(newWs.getUid(i));
5750                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5751             }
5752 
5753             workChains = newWs.getWorkChains();
5754             if (workChains != null) {
5755                 for (int i = 0; i < workChains.size(); ++i) {
5756                     int uid = mapUid(workChains.get(i).getAttributionUid());
5757                     getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5758                 }
5759             }
5760         } else {
5761             Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
5762         }
5763     }
5764 
noteWifiStoppedLocked(WorkSource ws)5765     public void noteWifiStoppedLocked(WorkSource ws) {
5766         if (mGlobalWifiRunning) {
5767             final long elapsedRealtime = mClocks.elapsedRealtime();
5768             final long uptime = mClocks.uptimeMillis();
5769             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
5770             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
5771                     + Integer.toHexString(mHistoryCur.states));
5772             addHistoryRecordLocked(elapsedRealtime, uptime);
5773             mGlobalWifiRunning = false;
5774             mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
5775             int N = ws.size();
5776             for (int i=0; i<N; i++) {
5777                 int uid = mapUid(ws.getUid(i));
5778                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5779             }
5780 
5781             List<WorkChain> workChains = ws.getWorkChains();
5782             if (workChains != null) {
5783                 for (int i = 0; i < workChains.size(); ++i) {
5784                     int uid = mapUid(workChains.get(i).getAttributionUid());
5785                     getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5786                 }
5787             }
5788 
5789             scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
5790         } else {
5791             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
5792         }
5793     }
5794 
noteWifiStateLocked(int wifiState, String accessPoint)5795     public void noteWifiStateLocked(int wifiState, String accessPoint) {
5796         if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
5797         if (mWifiState != wifiState) {
5798             final long elapsedRealtime = mClocks.elapsedRealtime();
5799             if (mWifiState >= 0) {
5800                 mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
5801             }
5802             mWifiState = wifiState;
5803             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
5804             scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
5805         }
5806     }
5807 
noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth)5808     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
5809         if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
5810         if (mWifiSupplState != supplState) {
5811             final long elapsedRealtime = mClocks.elapsedRealtime();
5812             final long uptime = mClocks.uptimeMillis();
5813             if (mWifiSupplState >= 0) {
5814                 mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime);
5815             }
5816             mWifiSupplState = supplState;
5817             mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtime);
5818             mHistoryCur.states2 =
5819                     (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
5820                     | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
5821             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
5822                     + Integer.toHexString(mHistoryCur.states2));
5823             addHistoryRecordLocked(elapsedRealtime, uptime);
5824         }
5825     }
5826 
stopAllWifiSignalStrengthTimersLocked(int except)5827     void stopAllWifiSignalStrengthTimersLocked(int except) {
5828         final long elapsedRealtime = mClocks.elapsedRealtime();
5829         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
5830             if (i == except) {
5831                 continue;
5832             }
5833             while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
5834                 mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
5835             }
5836         }
5837     }
5838 
noteWifiRssiChangedLocked(int newRssi)5839     public void noteWifiRssiChangedLocked(int newRssi) {
5840         int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
5841         if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
5842         if (mWifiSignalStrengthBin != strengthBin) {
5843             final long elapsedRealtime = mClocks.elapsedRealtime();
5844             final long uptime = mClocks.uptimeMillis();
5845             if (mWifiSignalStrengthBin >= 0) {
5846                 mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
5847                         elapsedRealtime);
5848             }
5849             if (strengthBin >= 0) {
5850                 if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
5851                     mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
5852                 }
5853                 mHistoryCur.states2 =
5854                         (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
5855                         | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
5856                 if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
5857                         + Integer.toHexString(mHistoryCur.states2));
5858                 addHistoryRecordLocked(elapsedRealtime, uptime);
5859             } else {
5860                 stopAllWifiSignalStrengthTimersLocked(-1);
5861             }
5862             mWifiSignalStrengthBin = strengthBin;
5863         }
5864     }
5865 
5866     int mWifiFullLockNesting = 0;
5867 
5868     @UnsupportedAppUsage
noteFullWifiLockAcquiredLocked(int uid)5869     public void noteFullWifiLockAcquiredLocked(int uid) {
5870         final long elapsedRealtime = mClocks.elapsedRealtime();
5871         final long uptime = mClocks.uptimeMillis();
5872         if (mWifiFullLockNesting == 0) {
5873             mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
5874             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
5875                     + Integer.toHexString(mHistoryCur.states));
5876             addHistoryRecordLocked(elapsedRealtime, uptime);
5877         }
5878         mWifiFullLockNesting++;
5879         getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
5880     }
5881 
5882     @UnsupportedAppUsage
noteFullWifiLockReleasedLocked(int uid)5883     public void noteFullWifiLockReleasedLocked(int uid) {
5884         final long elapsedRealtime = mClocks.elapsedRealtime();
5885         final long uptime = mClocks.uptimeMillis();
5886         mWifiFullLockNesting--;
5887         if (mWifiFullLockNesting == 0) {
5888             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
5889             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
5890                     + Integer.toHexString(mHistoryCur.states));
5891             addHistoryRecordLocked(elapsedRealtime, uptime);
5892         }
5893         getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime);
5894     }
5895 
5896     int mWifiScanNesting = 0;
5897 
noteWifiScanStartedLocked(int uid)5898     public void noteWifiScanStartedLocked(int uid) {
5899         final long elapsedRealtime = mClocks.elapsedRealtime();
5900         final long uptime = mClocks.uptimeMillis();
5901         if (mWifiScanNesting == 0) {
5902             mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
5903             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
5904                     + Integer.toHexString(mHistoryCur.states));
5905             addHistoryRecordLocked(elapsedRealtime, uptime);
5906         }
5907         mWifiScanNesting++;
5908         getUidStatsLocked(uid).noteWifiScanStartedLocked(elapsedRealtime);
5909     }
5910 
noteWifiScanStoppedLocked(int uid)5911     public void noteWifiScanStoppedLocked(int uid) {
5912         final long elapsedRealtime = mClocks.elapsedRealtime();
5913         final long uptime = mClocks.uptimeMillis();
5914         mWifiScanNesting--;
5915         if (mWifiScanNesting == 0) {
5916             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
5917             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
5918                     + Integer.toHexString(mHistoryCur.states));
5919             addHistoryRecordLocked(elapsedRealtime, uptime);
5920         }
5921         getUidStatsLocked(uid).noteWifiScanStoppedLocked(elapsedRealtime);
5922     }
5923 
noteWifiBatchedScanStartedLocked(int uid, int csph)5924     public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
5925         uid = mapUid(uid);
5926         final long elapsedRealtime = mClocks.elapsedRealtime();
5927         getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime);
5928     }
5929 
noteWifiBatchedScanStoppedLocked(int uid)5930     public void noteWifiBatchedScanStoppedLocked(int uid) {
5931         uid = mapUid(uid);
5932         final long elapsedRealtime = mClocks.elapsedRealtime();
5933         getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime);
5934     }
5935 
5936     int mWifiMulticastNesting = 0;
5937 
5938     @UnsupportedAppUsage
noteWifiMulticastEnabledLocked(int uid)5939     public void noteWifiMulticastEnabledLocked(int uid) {
5940         uid = mapUid(uid);
5941         final long elapsedRealtime = mClocks.elapsedRealtime();
5942         final long uptime = mClocks.uptimeMillis();
5943         if (mWifiMulticastNesting == 0) {
5944             mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
5945             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
5946                     + Integer.toHexString(mHistoryCur.states));
5947             addHistoryRecordLocked(elapsedRealtime, uptime);
5948 
5949             // Start Wifi Multicast overall timer
5950             if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
5951                 if (DEBUG_HISTORY) Slog.v(TAG, "WiFi Multicast Overall Timer Started");
5952                 mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtime);
5953             }
5954         }
5955         mWifiMulticastNesting++;
5956         getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
5957     }
5958 
5959     @UnsupportedAppUsage
noteWifiMulticastDisabledLocked(int uid)5960     public void noteWifiMulticastDisabledLocked(int uid) {
5961         uid = mapUid(uid);
5962         final long elapsedRealtime = mClocks.elapsedRealtime();
5963         final long uptime = mClocks.uptimeMillis();
5964         mWifiMulticastNesting--;
5965         if (mWifiMulticastNesting == 0) {
5966             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
5967             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
5968                     + Integer.toHexString(mHistoryCur.states));
5969             addHistoryRecordLocked(elapsedRealtime, uptime);
5970 
5971             // Stop Wifi Multicast overall timer
5972             if (mWifiMulticastWakelockTimer.isRunningLocked()) {
5973                 if (DEBUG_HISTORY) Slog.v(TAG, "Multicast Overall Timer Stopped");
5974                 mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtime);
5975             }
5976         }
5977         getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime);
5978     }
5979 
noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws)5980     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
5981         int N = ws.size();
5982         for (int i=0; i<N; i++) {
5983             final int uid = mapUid(ws.getUid(i));
5984             noteFullWifiLockAcquiredLocked(uid);
5985         }
5986 
5987         final List<WorkChain> workChains = ws.getWorkChains();
5988         if (workChains != null) {
5989             for (int i = 0; i < workChains.size(); ++i) {
5990                 final WorkChain workChain = workChains.get(i);
5991                 final int uid = mapUid(workChain.getAttributionUid());
5992                 noteFullWifiLockAcquiredLocked(uid);
5993             }
5994         }
5995     }
5996 
noteFullWifiLockReleasedFromSourceLocked(WorkSource ws)5997     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
5998         int N = ws.size();
5999         for (int i=0; i<N; i++) {
6000             final int uid = mapUid(ws.getUid(i));
6001             noteFullWifiLockReleasedLocked(uid);
6002         }
6003 
6004         final List<WorkChain> workChains = ws.getWorkChains();
6005         if (workChains != null) {
6006             for (int i = 0; i < workChains.size(); ++i) {
6007                 final WorkChain workChain = workChains.get(i);
6008                 final int uid = mapUid(workChain.getAttributionUid());
6009                 noteFullWifiLockReleasedLocked(uid);
6010             }
6011         }
6012     }
6013 
noteWifiScanStartedFromSourceLocked(WorkSource ws)6014     public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
6015         int N = ws.size();
6016         for (int i=0; i<N; i++) {
6017             final int uid = mapUid(ws.getUid(i));
6018             noteWifiScanStartedLocked(uid);
6019         }
6020 
6021         final List<WorkChain> workChains = ws.getWorkChains();
6022         if (workChains != null) {
6023             for (int i = 0; i < workChains.size(); ++i) {
6024                 final WorkChain workChain = workChains.get(i);
6025                 final int uid = mapUid(workChain.getAttributionUid());
6026                 noteWifiScanStartedLocked(uid);
6027             }
6028         }
6029     }
6030 
noteWifiScanStoppedFromSourceLocked(WorkSource ws)6031     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
6032         int N = ws.size();
6033         for (int i=0; i<N; i++) {
6034             final int uid = mapUid(ws.getUid(i));
6035             noteWifiScanStoppedLocked(uid);
6036         }
6037 
6038         final List<WorkChain> workChains = ws.getWorkChains();
6039         if (workChains != null) {
6040             for (int i = 0; i < workChains.size(); ++i) {
6041                 final WorkChain workChain = workChains.get(i);
6042                 final int uid = mapUid(workChain.getAttributionUid());
6043                 noteWifiScanStoppedLocked(uid);
6044             }
6045         }
6046     }
6047 
noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph)6048     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
6049         int N = ws.size();
6050         for (int i=0; i<N; i++) {
6051             noteWifiBatchedScanStartedLocked(ws.getUid(i), csph);
6052         }
6053 
6054         final List<WorkChain> workChains = ws.getWorkChains();
6055         if (workChains != null) {
6056             for (int i = 0; i < workChains.size(); ++i) {
6057                 noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph);
6058             }
6059         }
6060     }
6061 
noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws)6062     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
6063         int N = ws.size();
6064         for (int i=0; i<N; i++) {
6065             noteWifiBatchedScanStoppedLocked(ws.getUid(i));
6066         }
6067 
6068         final List<WorkChain> workChains = ws.getWorkChains();
6069         if (workChains != null) {
6070             for (int i = 0; i < workChains.size(); ++i) {
6071                 noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid());
6072             }
6073         }
6074     }
6075 
includeInStringArray(String[] array, String str)6076     private static String[] includeInStringArray(String[] array, String str) {
6077         if (ArrayUtils.indexOf(array, str) >= 0) {
6078             return array;
6079         }
6080         String[] newArray = new String[array.length+1];
6081         System.arraycopy(array, 0, newArray, 0, array.length);
6082         newArray[array.length] = str;
6083         return newArray;
6084     }
6085 
excludeFromStringArray(String[] array, String str)6086     private static String[] excludeFromStringArray(String[] array, String str) {
6087         int index = ArrayUtils.indexOf(array, str);
6088         if (index >= 0) {
6089             String[] newArray = new String[array.length-1];
6090             if (index > 0) {
6091                 System.arraycopy(array, 0, newArray, 0, index);
6092             }
6093             if (index < array.length-1) {
6094                 System.arraycopy(array, index+1, newArray, index, array.length-index-1);
6095             }
6096             return newArray;
6097         }
6098         return array;
6099     }
6100 
6101     /** @hide */
noteNetworkInterfaceType(String iface, int networkType)6102     public void noteNetworkInterfaceType(String iface, int networkType) {
6103         if (TextUtils.isEmpty(iface)) return;
6104 
6105         synchronized (mModemNetworkLock) {
6106             if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
6107                 mModemIfaces = includeInStringArray(mModemIfaces, iface);
6108                 if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mModemIfaces);
6109             } else {
6110                 mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
6111                 if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mModemIfaces);
6112             }
6113         }
6114 
6115         synchronized (mWifiNetworkLock) {
6116             if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
6117                 mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
6118                 if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
6119             } else {
6120                 mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
6121                 if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
6122             }
6123         }
6124     }
6125 
getWifiIfaces()6126     public String[] getWifiIfaces() {
6127         synchronized (mWifiNetworkLock) {
6128             return mWifiIfaces;
6129         }
6130     }
6131 
getMobileIfaces()6132     public String[] getMobileIfaces() {
6133         synchronized (mModemNetworkLock) {
6134             return mModemIfaces;
6135         }
6136     }
6137 
6138     @UnsupportedAppUsage
getScreenOnTime(long elapsedRealtimeUs, int which)6139     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
6140         return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6141     }
6142 
getScreenOnCount(int which)6143     @Override public int getScreenOnCount(int which) {
6144         return mScreenOnTimer.getCountLocked(which);
6145     }
6146 
getScreenDozeTime(long elapsedRealtimeUs, int which)6147     @Override public long getScreenDozeTime(long elapsedRealtimeUs, int which) {
6148         return mScreenDozeTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6149     }
6150 
getScreenDozeCount(int which)6151     @Override public int getScreenDozeCount(int which) {
6152         return mScreenDozeTimer.getCountLocked(which);
6153     }
6154 
6155     @UnsupportedAppUsage
getScreenBrightnessTime(int brightnessBin, long elapsedRealtimeUs, int which)6156     @Override public long getScreenBrightnessTime(int brightnessBin,
6157             long elapsedRealtimeUs, int which) {
6158         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
6159                 elapsedRealtimeUs, which);
6160     }
6161 
getScreenBrightnessTimer(int brightnessBin)6162     @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
6163         return mScreenBrightnessTimer[brightnessBin];
6164     }
6165 
getInteractiveTime(long elapsedRealtimeUs, int which)6166     @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
6167         return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6168     }
6169 
getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which)6170     @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
6171         return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6172     }
6173 
getPowerSaveModeEnabledCount(int which)6174     @Override public int getPowerSaveModeEnabledCount(int which) {
6175         return mPowerSaveModeEnabledTimer.getCountLocked(which);
6176     }
6177 
getDeviceIdleModeTime(int mode, long elapsedRealtimeUs, int which)6178     @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
6179             int which) {
6180         switch (mode) {
6181             case DEVICE_IDLE_MODE_LIGHT:
6182                 return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6183             case DEVICE_IDLE_MODE_DEEP:
6184                 return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6185         }
6186         return 0;
6187     }
6188 
getDeviceIdleModeCount(int mode, int which)6189     @Override public int getDeviceIdleModeCount(int mode, int which) {
6190         switch (mode) {
6191             case DEVICE_IDLE_MODE_LIGHT:
6192                 return mDeviceIdleModeLightTimer.getCountLocked(which);
6193             case DEVICE_IDLE_MODE_DEEP:
6194                 return mDeviceIdleModeFullTimer.getCountLocked(which);
6195         }
6196         return 0;
6197     }
6198 
getLongestDeviceIdleModeTime(int mode)6199     @Override public long getLongestDeviceIdleModeTime(int mode) {
6200         switch (mode) {
6201             case DEVICE_IDLE_MODE_LIGHT:
6202                 return mLongestLightIdleTime;
6203             case DEVICE_IDLE_MODE_DEEP:
6204                 return mLongestFullIdleTime;
6205         }
6206         return 0;
6207     }
6208 
getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which)6209     @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
6210         switch (mode) {
6211             case DEVICE_IDLE_MODE_LIGHT:
6212                 return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6213             case DEVICE_IDLE_MODE_DEEP:
6214                 return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6215         }
6216         return 0;
6217     }
6218 
getDeviceIdlingCount(int mode, int which)6219     @Override public int getDeviceIdlingCount(int mode, int which) {
6220         switch (mode) {
6221             case DEVICE_IDLE_MODE_LIGHT:
6222                 return mDeviceLightIdlingTimer.getCountLocked(which);
6223             case DEVICE_IDLE_MODE_DEEP:
6224                 return mDeviceIdlingTimer.getCountLocked(which);
6225         }
6226         return 0;
6227     }
6228 
getNumConnectivityChange(int which)6229     @Override public int getNumConnectivityChange(int which) {
6230         return mNumConnectivityChange;
6231     }
6232 
getGpsSignalQualityTime(int strengthBin, long elapsedRealtimeUs, int which)6233     @Override public long getGpsSignalQualityTime(int strengthBin,
6234         long elapsedRealtimeUs, int which) {
6235         if (strengthBin < 0 || strengthBin >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
6236             return 0;
6237         }
6238         return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
6239             elapsedRealtimeUs, which);
6240     }
6241 
getGpsBatteryDrainMaMs()6242     @Override public long getGpsBatteryDrainMaMs() {
6243         final double opVolt = mPowerProfile.getAveragePower(
6244             PowerProfile.POWER_GPS_OPERATING_VOLTAGE) / 1000.0;
6245         if (opVolt == 0) {
6246             return 0;
6247         }
6248         double energyUsedMaMs = 0.0;
6249         final int which = STATS_SINCE_CHARGED;
6250         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
6251         for(int i=0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
6252             energyUsedMaMs
6253                 += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
6254                 * (getGpsSignalQualityTime(i, rawRealtime, which) / 1000);
6255         }
6256         return (long) energyUsedMaMs;
6257     }
6258 
6259     @UnsupportedAppUsage
getPhoneOnTime(long elapsedRealtimeUs, int which)6260     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
6261         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6262     }
6263 
getPhoneOnCount(int which)6264     @Override public int getPhoneOnCount(int which) {
6265         return mPhoneOnTimer.getCountLocked(which);
6266     }
6267 
6268     @UnsupportedAppUsage
getPhoneSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)6269     @Override public long getPhoneSignalStrengthTime(int strengthBin,
6270             long elapsedRealtimeUs, int which) {
6271         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
6272                 elapsedRealtimeUs, which);
6273     }
6274 
6275     @UnsupportedAppUsage
getPhoneSignalScanningTime( long elapsedRealtimeUs, int which)6276     @Override public long getPhoneSignalScanningTime(
6277             long elapsedRealtimeUs, int which) {
6278         return mPhoneSignalScanningTimer.getTotalTimeLocked(
6279                 elapsedRealtimeUs, which);
6280     }
6281 
getPhoneSignalScanningTimer()6282     @Override public Timer getPhoneSignalScanningTimer() {
6283         return mPhoneSignalScanningTimer;
6284     }
6285 
6286     @UnsupportedAppUsage
getPhoneSignalStrengthCount(int strengthBin, int which)6287     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
6288         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
6289     }
6290 
getPhoneSignalStrengthTimer(int strengthBin)6291     @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
6292         return mPhoneSignalStrengthsTimer[strengthBin];
6293     }
6294 
6295     @UnsupportedAppUsage
getPhoneDataConnectionTime(int dataType, long elapsedRealtimeUs, int which)6296     @Override public long getPhoneDataConnectionTime(int dataType,
6297             long elapsedRealtimeUs, int which) {
6298         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
6299                 elapsedRealtimeUs, which);
6300     }
6301 
6302     @UnsupportedAppUsage
getPhoneDataConnectionCount(int dataType, int which)6303     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
6304         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
6305     }
6306 
getPhoneDataConnectionTimer(int dataType)6307     @Override public Timer getPhoneDataConnectionTimer(int dataType) {
6308         return mPhoneDataConnectionsTimer[dataType];
6309     }
6310 
6311     @UnsupportedAppUsage
getMobileRadioActiveTime(long elapsedRealtimeUs, int which)6312     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
6313         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6314     }
6315 
getMobileRadioActiveCount(int which)6316     @Override public int getMobileRadioActiveCount(int which) {
6317         return mMobileRadioActiveTimer.getCountLocked(which);
6318     }
6319 
getMobileRadioActiveAdjustedTime(int which)6320     @Override public long getMobileRadioActiveAdjustedTime(int which) {
6321         return mMobileRadioActiveAdjustedTime.getCountLocked(which);
6322     }
6323 
getMobileRadioActiveUnknownTime(int which)6324     @Override public long getMobileRadioActiveUnknownTime(int which) {
6325         return mMobileRadioActiveUnknownTime.getCountLocked(which);
6326     }
6327 
getMobileRadioActiveUnknownCount(int which)6328     @Override public int getMobileRadioActiveUnknownCount(int which) {
6329         return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
6330     }
6331 
getWifiMulticastWakelockTime( long elapsedRealtimeUs, int which)6332     @Override public long getWifiMulticastWakelockTime(
6333             long elapsedRealtimeUs, int which) {
6334         return mWifiMulticastWakelockTimer.getTotalTimeLocked(
6335                 elapsedRealtimeUs, which);
6336     }
6337 
getWifiMulticastWakelockCount(int which)6338     @Override public int getWifiMulticastWakelockCount(int which) {
6339         return mWifiMulticastWakelockTimer.getCountLocked(which);
6340     }
6341 
6342     @UnsupportedAppUsage
getWifiOnTime(long elapsedRealtimeUs, int which)6343     @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
6344         return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6345     }
6346 
getWifiActiveTime(long elapsedRealtimeUs, int which)6347     @Override public long getWifiActiveTime(long elapsedRealtimeUs, int which) {
6348         return mWifiActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6349     }
6350 
6351     @UnsupportedAppUsage
getGlobalWifiRunningTime(long elapsedRealtimeUs, int which)6352     @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
6353         return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6354     }
6355 
getWifiStateTime(int wifiState, long elapsedRealtimeUs, int which)6356     @Override public long getWifiStateTime(int wifiState,
6357             long elapsedRealtimeUs, int which) {
6358         return mWifiStateTimer[wifiState].getTotalTimeLocked(
6359                 elapsedRealtimeUs, which);
6360     }
6361 
getWifiStateCount(int wifiState, int which)6362     @Override public int getWifiStateCount(int wifiState, int which) {
6363         return mWifiStateTimer[wifiState].getCountLocked(which);
6364     }
6365 
getWifiStateTimer(int wifiState)6366     @Override public Timer getWifiStateTimer(int wifiState) {
6367         return mWifiStateTimer[wifiState];
6368     }
6369 
getWifiSupplStateTime(int state, long elapsedRealtimeUs, int which)6370     @Override public long getWifiSupplStateTime(int state,
6371             long elapsedRealtimeUs, int which) {
6372         return mWifiSupplStateTimer[state].getTotalTimeLocked(
6373                 elapsedRealtimeUs, which);
6374     }
6375 
getWifiSupplStateCount(int state, int which)6376     @Override public int getWifiSupplStateCount(int state, int which) {
6377         return mWifiSupplStateTimer[state].getCountLocked(which);
6378     }
6379 
getWifiSupplStateTimer(int state)6380     @Override public Timer getWifiSupplStateTimer(int state) {
6381         return mWifiSupplStateTimer[state];
6382     }
6383 
getWifiSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)6384     @Override public long getWifiSignalStrengthTime(int strengthBin,
6385             long elapsedRealtimeUs, int which) {
6386         return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
6387                 elapsedRealtimeUs, which);
6388     }
6389 
getWifiSignalStrengthCount(int strengthBin, int which)6390     @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
6391         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
6392     }
6393 
getWifiSignalStrengthTimer(int strengthBin)6394     @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
6395         return mWifiSignalStrengthsTimer[strengthBin];
6396     }
6397 
6398     @Override
getBluetoothControllerActivity()6399     public ControllerActivityCounter getBluetoothControllerActivity() {
6400         return mBluetoothActivity;
6401     }
6402 
6403     @Override
getWifiControllerActivity()6404     public ControllerActivityCounter getWifiControllerActivity() {
6405         return mWifiActivity;
6406     }
6407 
6408     @Override
getModemControllerActivity()6409     public ControllerActivityCounter getModemControllerActivity() {
6410         return mModemActivity;
6411     }
6412 
6413     @Override
hasBluetoothActivityReporting()6414     public boolean hasBluetoothActivityReporting() {
6415         return mHasBluetoothReporting;
6416     }
6417 
6418     @Override
hasWifiActivityReporting()6419     public boolean hasWifiActivityReporting() {
6420         return mHasWifiReporting;
6421     }
6422 
6423     @Override
hasModemActivityReporting()6424     public boolean hasModemActivityReporting() {
6425         return mHasModemReporting;
6426     }
6427 
6428     @Override
getFlashlightOnTime(long elapsedRealtimeUs, int which)6429     public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
6430         return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6431     }
6432 
6433     @Override
getFlashlightOnCount(int which)6434     public long getFlashlightOnCount(int which) {
6435         return mFlashlightOnTimer.getCountLocked(which);
6436     }
6437 
6438     @Override
getCameraOnTime(long elapsedRealtimeUs, int which)6439     public long getCameraOnTime(long elapsedRealtimeUs, int which) {
6440         return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6441     }
6442 
6443     @Override
getBluetoothScanTime(long elapsedRealtimeUs, int which)6444     public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
6445         return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6446     }
6447 
6448     @Override
6449     @UnsupportedAppUsage
getNetworkActivityBytes(int type, int which)6450     public long getNetworkActivityBytes(int type, int which) {
6451         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
6452             return mNetworkByteActivityCounters[type].getCountLocked(which);
6453         } else {
6454             return 0;
6455         }
6456     }
6457 
6458     @Override
getNetworkActivityPackets(int type, int which)6459     public long getNetworkActivityPackets(int type, int which) {
6460         if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
6461             return mNetworkPacketActivityCounters[type].getCountLocked(which);
6462         } else {
6463             return 0;
6464         }
6465     }
6466 
getStartClockTime()6467     @Override public long getStartClockTime() {
6468         final long currentTime = System.currentTimeMillis();
6469         if ((currentTime > MILLISECONDS_IN_YEAR
6470                 && mStartClockTime < (currentTime - MILLISECONDS_IN_YEAR))
6471                 || (mStartClockTime > currentTime)) {
6472             // If the start clock time has changed by more than a year, then presumably
6473             // the previous time was completely bogus.  So we are going to figure out a
6474             // new time based on how much time has elapsed since we started counting.
6475             recordCurrentTimeChangeLocked(currentTime, mClocks.elapsedRealtime(),
6476                     mClocks.uptimeMillis());
6477             return currentTime - (mClocks.elapsedRealtime() - (mRealtimeStart / 1000));
6478         }
6479         return mStartClockTime;
6480     }
6481 
getStartPlatformVersion()6482     @Override public String getStartPlatformVersion() {
6483         return mStartPlatformVersion;
6484     }
6485 
getEndPlatformVersion()6486     @Override public String getEndPlatformVersion() {
6487         return mEndPlatformVersion;
6488     }
6489 
getParcelVersion()6490     @Override public int getParcelVersion() {
6491         return VERSION;
6492     }
6493 
getIsOnBattery()6494     @Override public boolean getIsOnBattery() {
6495         return mOnBattery;
6496     }
6497 
6498     @UnsupportedAppUsage
getUidStats()6499     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
6500         return mUidStats;
6501     }
6502 
resetIfNotNull(T t, boolean detachIfReset)6503     private static <T extends TimeBaseObs> boolean resetIfNotNull(T t, boolean detachIfReset) {
6504         if (t != null) {
6505             return t.reset(detachIfReset);
6506         }
6507         return true;
6508     }
6509 
resetIfNotNull(T[] t, boolean detachIfReset)6510     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[] t, boolean detachIfReset) {
6511         if (t != null) {
6512             boolean ret = true;
6513             for (int i = 0; i < t.length; i++) {
6514                 ret &= resetIfNotNull(t[i], detachIfReset);
6515             }
6516             return ret;
6517         }
6518         return true;
6519     }
6520 
resetIfNotNull(T[][] t, boolean detachIfReset)6521     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[][] t, boolean detachIfReset) {
6522         if (t != null) {
6523             boolean ret = true;
6524             for (int i = 0; i < t.length; i++) {
6525                 ret &= resetIfNotNull(t[i], detachIfReset);
6526             }
6527             return ret;
6528         }
6529         return true;
6530     }
6531 
resetIfNotNull(ControllerActivityCounterImpl counter, boolean detachIfReset)6532     private static boolean resetIfNotNull(ControllerActivityCounterImpl counter,
6533             boolean detachIfReset) {
6534         if (counter != null) {
6535             counter.reset(detachIfReset);
6536         }
6537         return true;
6538     }
6539 
detachIfNotNull(T t)6540     private static <T extends TimeBaseObs> void detachIfNotNull(T t) {
6541         if (t != null) {
6542             t.detach();
6543         }
6544     }
6545 
detachIfNotNull(T[] t)6546     private static <T extends TimeBaseObs> void detachIfNotNull(T[] t) {
6547         if (t != null) {
6548             for (int i = 0; i < t.length; i++) {
6549                 detachIfNotNull(t[i]);
6550             }
6551         }
6552     }
6553 
detachIfNotNull(T[][] t)6554     private static <T extends TimeBaseObs> void detachIfNotNull(T[][] t) {
6555         if (t != null) {
6556             for (int i = 0; i < t.length; i++) {
6557                 detachIfNotNull(t[i]);
6558             }
6559         }
6560     }
6561 
detachIfNotNull(ControllerActivityCounterImpl counter)6562     private static void detachIfNotNull(ControllerActivityCounterImpl counter) {
6563         if (counter != null) {
6564             counter.detach();
6565         }
6566     }
6567 
6568     /**
6569      * The statistics associated with a particular uid.
6570      */
6571     public static class Uid extends BatteryStats.Uid {
6572         /**
6573          * BatteryStatsImpl that we are associated with.
6574          */
6575         protected BatteryStatsImpl mBsi;
6576 
6577         final int mUid;
6578 
6579         /** TimeBase for when uid is in background and device is on battery. */
6580         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
6581         public final TimeBase mOnBatteryBackgroundTimeBase;
6582         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
6583         public final TimeBase mOnBatteryScreenOffBackgroundTimeBase;
6584 
6585         boolean mWifiRunning;
6586         StopwatchTimer mWifiRunningTimer;
6587 
6588         boolean mFullWifiLockOut;
6589         StopwatchTimer mFullWifiLockTimer;
6590 
6591         boolean mWifiScanStarted;
6592         DualTimer mWifiScanTimer;
6593 
6594         static final int NO_BATCHED_SCAN_STARTED = -1;
6595         int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
6596         StopwatchTimer[] mWifiBatchedScanTimer;
6597 
6598         int mWifiMulticastWakelockCount;
6599         StopwatchTimer mWifiMulticastTimer;
6600 
6601         StopwatchTimer mAudioTurnedOnTimer;
6602         StopwatchTimer mVideoTurnedOnTimer;
6603         StopwatchTimer mFlashlightTurnedOnTimer;
6604         StopwatchTimer mCameraTurnedOnTimer;
6605         StopwatchTimer mForegroundActivityTimer;
6606         StopwatchTimer mForegroundServiceTimer;
6607         /** Total time spent by the uid holding any partial wakelocks. */
6608         DualTimer mAggregatedPartialWakelockTimer;
6609         DualTimer mBluetoothScanTimer;
6610         DualTimer mBluetoothUnoptimizedScanTimer;
6611         Counter mBluetoothScanResultCounter;
6612         Counter mBluetoothScanResultBgCounter;
6613 
6614         int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
6615         StopwatchTimer[] mProcessStateTimer;
6616 
6617         boolean mInForegroundService = false;
6618 
6619         BatchTimer mVibratorOnTimer;
6620 
6621         Counter[] mUserActivityCounters;
6622 
6623         LongSamplingCounter[] mNetworkByteActivityCounters;
6624         LongSamplingCounter[] mNetworkPacketActivityCounters;
6625         LongSamplingCounter mMobileRadioActiveTime;
6626         LongSamplingCounter mMobileRadioActiveCount;
6627 
6628         /**
6629          * How many times this UID woke up the Application Processor due to a Mobile radio packet.
6630          */
6631         private LongSamplingCounter mMobileRadioApWakeupCount;
6632 
6633         /**
6634          * How many times this UID woke up the Application Processor due to a Wifi packet.
6635          */
6636         private LongSamplingCounter mWifiRadioApWakeupCount;
6637 
6638         /**
6639          * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
6640          * Can be null if the UID has had no such activity.
6641          */
6642         private ControllerActivityCounterImpl mWifiControllerActivity;
6643 
6644         /**
6645          * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
6646          * Can be null if the UID has had no such activity.
6647          */
6648         private ControllerActivityCounterImpl mBluetoothControllerActivity;
6649 
6650         /**
6651          * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
6652          * Can be null if the UID has had no such activity.
6653          */
6654         private ControllerActivityCounterImpl mModemControllerActivity;
6655 
6656         /**
6657          * The CPU times we had at the last history details update.
6658          */
6659         long mLastStepUserTime;
6660         long mLastStepSystemTime;
6661         long mCurStepUserTime;
6662         long mCurStepSystemTime;
6663 
6664         LongSamplingCounter mUserCpuTime;
6665         LongSamplingCounter mSystemCpuTime;
6666         LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
6667         LongSamplingCounter mCpuActiveTimeMs;
6668 
6669         LongSamplingCounterArray mCpuFreqTimeMs;
6670         LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
6671         LongSamplingCounterArray mCpuClusterTimesMs;
6672 
6673         LongSamplingCounterArray[] mProcStateTimeMs;
6674         LongSamplingCounterArray[] mProcStateScreenOffTimeMs;
6675 
6676         IntArray mChildUids;
6677 
6678         /**
6679          * The statistics we have collected for this uid's wake locks.
6680          */
6681         final OverflowArrayMap<Wakelock> mWakelockStats;
6682 
6683         /**
6684          * The statistics we have collected for this uid's syncs.
6685          */
6686         final OverflowArrayMap<DualTimer> mSyncStats;
6687 
6688         /**
6689          * The statistics we have collected for this uid's jobs.
6690          */
6691         final OverflowArrayMap<DualTimer> mJobStats;
6692 
6693         /**
6694          * Count of the jobs that have completed and the reasons why they completed.
6695          */
6696         final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
6697 
6698         /**
6699          * Count of app launch events that had associated deferred job counts or info about
6700          * last time a job was run.
6701          */
6702         Counter mJobsDeferredEventCount;
6703 
6704         /**
6705          * Count of deferred jobs that were pending when the app was launched or brought to
6706          * the foreground through a user interaction.
6707          */
6708         Counter mJobsDeferredCount;
6709 
6710         /**
6711          * Sum of time since the last time a job was run for this app before it was launched.
6712          */
6713         LongSamplingCounter mJobsFreshnessTimeMs;
6714 
6715         /**
6716          * Array of counts of instances where the time since the last job was run for the app
6717          * fell within one of the thresholds in {@link #JOB_FRESHNESS_BUCKETS}.
6718          */
6719         final Counter[] mJobsFreshnessBuckets;
6720 
6721         /**
6722          * The statistics we have collected for this uid's sensor activations.
6723          */
6724         final SparseArray<Sensor> mSensorStats = new SparseArray<>();
6725 
6726         /**
6727          * The statistics we have collected for this uid's processes.
6728          */
6729         final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
6730 
6731         /**
6732          * The statistics we have collected for this uid's processes.
6733          */
6734         final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
6735 
6736         /**
6737          * The transient wake stats we have collected for this uid's pids.
6738          */
6739         final SparseArray<Pid> mPids = new SparseArray<>();
6740 
Uid(BatteryStatsImpl bsi, int uid)6741         public Uid(BatteryStatsImpl bsi, int uid) {
6742             mBsi = bsi;
6743             mUid = uid;
6744 
6745             /* Observer list of TimeBase object in Uid is short */
6746             mOnBatteryBackgroundTimeBase = new TimeBase(false);
6747             mOnBatteryBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
6748                     mBsi.mClocks.elapsedRealtime() * 1000);
6749             /* Observer list of TimeBase object in Uid is short */
6750             mOnBatteryScreenOffBackgroundTimeBase = new TimeBase(false);
6751             mOnBatteryScreenOffBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
6752                     mBsi.mClocks.elapsedRealtime() * 1000);
6753 
6754             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6755             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6756             mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6757             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase);
6758 
6759             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
6760                 @Override public Wakelock instantiateObject() {
6761                     return new Wakelock(mBsi, Uid.this);
6762                 }
6763             };
6764             mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
6765                 @Override public DualTimer instantiateObject() {
6766                     return new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
6767                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6768                 }
6769             };
6770             mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
6771                 @Override public DualTimer instantiateObject() {
6772                     return new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
6773                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6774                 }
6775             };
6776 
6777             mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_RUNNING,
6778                     mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
6779             mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, this, FULL_WIFI_LOCK,
6780                     mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
6781             mWifiScanTimer = new DualTimer(mBsi.mClocks, this, WIFI_SCAN,
6782                     mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6783             mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
6784             mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_MULTICAST_ENABLED,
6785                     mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
6786             mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
6787             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase);
6788             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase);
6789             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6790             mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length];
6791         }
6792 
6793         @VisibleForTesting
setProcessStateForTest(int procState)6794         public void setProcessStateForTest(int procState) {
6795             mProcessState = procState;
6796         }
6797 
6798         @Override
getCpuFreqTimes(int which)6799         public long[] getCpuFreqTimes(int which) {
6800             return nullIfAllZeros(mCpuFreqTimeMs, which);
6801         }
6802 
6803         @Override
getScreenOffCpuFreqTimes(int which)6804         public long[] getScreenOffCpuFreqTimes(int which) {
6805             return nullIfAllZeros(mScreenOffCpuFreqTimeMs, which);
6806         }
6807 
6808         @Override
getCpuActiveTime()6809         public long getCpuActiveTime() {
6810             return mCpuActiveTimeMs.getCountLocked(STATS_SINCE_CHARGED);
6811         }
6812 
6813         @Override
getCpuClusterTimes()6814         public long[] getCpuClusterTimes() {
6815             return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
6816         }
6817 
6818 
6819         @Override
getCpuFreqTimes(int which, int procState)6820         public long[] getCpuFreqTimes(int which, int procState) {
6821             if (which < 0 || which >= NUM_PROCESS_STATE) {
6822                 return null;
6823             }
6824             if (mProcStateTimeMs == null) {
6825                 return null;
6826             }
6827             if (!mBsi.mPerProcStateCpuTimesAvailable) {
6828                 mProcStateTimeMs = null;
6829                 return null;
6830             }
6831             return nullIfAllZeros(mProcStateTimeMs[procState], which);
6832         }
6833 
6834         @Override
getScreenOffCpuFreqTimes(int which, int procState)6835         public long[] getScreenOffCpuFreqTimes(int which, int procState) {
6836             if (which < 0 || which >= NUM_PROCESS_STATE) {
6837                 return null;
6838             }
6839             if (mProcStateScreenOffTimeMs == null) {
6840                 return null;
6841             }
6842             if (!mBsi.mPerProcStateCpuTimesAvailable) {
6843                 mProcStateScreenOffTimeMs = null;
6844                 return null;
6845             }
6846             return nullIfAllZeros(mProcStateScreenOffTimeMs[procState], which);
6847         }
6848 
addIsolatedUid(int isolatedUid)6849         public void addIsolatedUid(int isolatedUid) {
6850             if (mChildUids == null) {
6851                 mChildUids = new IntArray();
6852             } else if (mChildUids.indexOf(isolatedUid) >= 0) {
6853                 return;
6854             }
6855             mChildUids.add(isolatedUid);
6856         }
6857 
removeIsolatedUid(int isolatedUid)6858         public void removeIsolatedUid(int isolatedUid) {
6859             final int idx = mChildUids == null ? -1 : mChildUids.indexOf(isolatedUid);
6860             if (idx < 0) {
6861                 return;
6862             }
6863             mChildUids.remove(idx);
6864         }
6865 
nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which)6866         private long[] nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which) {
6867             if (cpuTimesMs == null) {
6868                 return null;
6869             }
6870             final long[] counts = cpuTimesMs.getCountsLocked(which);
6871             if (counts == null) {
6872                 return null;
6873             }
6874             // Return counts only if at least one of the elements is non-zero.
6875             for (int i = counts.length - 1; i >= 0; --i) {
6876                 if (counts[i] != 0) {
6877                     return counts;
6878                 }
6879             }
6880             return null;
6881         }
6882 
addProcStateTimesMs(int procState, long[] cpuTimesMs, boolean onBattery)6883         private void addProcStateTimesMs(int procState, long[] cpuTimesMs, boolean onBattery) {
6884             if (mProcStateTimeMs == null) {
6885                 mProcStateTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
6886             }
6887             if (mProcStateTimeMs[procState] == null
6888                     || mProcStateTimeMs[procState].getSize() != cpuTimesMs.length) {
6889                 detachIfNotNull(mProcStateTimeMs[procState]);
6890                 mProcStateTimeMs[procState] = new LongSamplingCounterArray(
6891                         mBsi.mOnBatteryTimeBase);
6892             }
6893             mProcStateTimeMs[procState].addCountLocked(cpuTimesMs, onBattery);
6894         }
6895 
addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs, boolean onBatteryScreenOff)6896         private void addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs,
6897                 boolean onBatteryScreenOff) {
6898             if (mProcStateScreenOffTimeMs == null) {
6899                 mProcStateScreenOffTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
6900             }
6901             if (mProcStateScreenOffTimeMs[procState] == null
6902                     || mProcStateScreenOffTimeMs[procState].getSize() != cpuTimesMs.length) {
6903                 detachIfNotNull(mProcStateScreenOffTimeMs[procState]);
6904                 mProcStateScreenOffTimeMs[procState] = new LongSamplingCounterArray(
6905                         mBsi.mOnBatteryScreenOffTimeBase);
6906             }
6907             mProcStateScreenOffTimeMs[procState].addCountLocked(cpuTimesMs, onBatteryScreenOff);
6908         }
6909 
6910         @Override
getAggregatedPartialWakelockTimer()6911         public Timer getAggregatedPartialWakelockTimer() {
6912             return mAggregatedPartialWakelockTimer;
6913         }
6914 
6915         @Override
6916         @UnsupportedAppUsage
getWakelockStats()6917         public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
6918             return mWakelockStats.getMap();
6919         }
6920 
6921         @Override
getMulticastWakelockStats()6922         public Timer getMulticastWakelockStats() {
6923             return mWifiMulticastTimer;
6924         }
6925 
6926         @Override
getSyncStats()6927         public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
6928             return mSyncStats.getMap();
6929         }
6930 
6931         @Override
getJobStats()6932         public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
6933             return mJobStats.getMap();
6934         }
6935 
6936         @Override
getJobCompletionStats()6937         public ArrayMap<String, SparseIntArray> getJobCompletionStats() {
6938             return mJobCompletions;
6939         }
6940 
6941         @Override
6942         @UnsupportedAppUsage
getSensorStats()6943         public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
6944             return mSensorStats;
6945         }
6946 
6947         @Override
6948         @UnsupportedAppUsage
getProcessStats()6949         public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
6950             return mProcessStats;
6951         }
6952 
6953         @Override
getPackageStats()6954         public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
6955             return mPackageStats;
6956         }
6957 
6958         @Override
6959         @UnsupportedAppUsage
getUid()6960         public int getUid() {
6961             return mUid;
6962         }
6963 
6964         @Override
noteWifiRunningLocked(long elapsedRealtimeMs)6965         public void noteWifiRunningLocked(long elapsedRealtimeMs) {
6966             if (!mWifiRunning) {
6967                 mWifiRunning = true;
6968                 if (mWifiRunningTimer == null) {
6969                     mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
6970                             mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
6971                 }
6972                 mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
6973             }
6974         }
6975 
6976         @Override
noteWifiStoppedLocked(long elapsedRealtimeMs)6977         public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
6978             if (mWifiRunning) {
6979                 mWifiRunning = false;
6980                 mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
6981             }
6982         }
6983 
6984         @Override
noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs)6985         public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
6986             if (!mFullWifiLockOut) {
6987                 mFullWifiLockOut = true;
6988                 if (mFullWifiLockTimer == null) {
6989                     mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
6990                             mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
6991                 }
6992                 mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
6993             }
6994         }
6995 
6996         @Override
noteFullWifiLockReleasedLocked(long elapsedRealtimeMs)6997         public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
6998             if (mFullWifiLockOut) {
6999                 mFullWifiLockOut = false;
7000                 mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
7001             }
7002         }
7003 
7004         @Override
noteWifiScanStartedLocked(long elapsedRealtimeMs)7005         public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
7006             if (!mWifiScanStarted) {
7007                 mWifiScanStarted = true;
7008                 if (mWifiScanTimer == null) {
7009                     mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
7010                             mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase,
7011                             mOnBatteryBackgroundTimeBase);
7012                 }
7013                 mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
7014             }
7015         }
7016 
7017         @Override
noteWifiScanStoppedLocked(long elapsedRealtimeMs)7018         public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
7019             if (mWifiScanStarted) {
7020                 mWifiScanStarted = false;
7021                 mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
7022             }
7023         }
7024 
7025         @Override
noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs)7026         public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
7027             int bin = 0;
7028             while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
7029                 csph = csph >> 3;
7030                 bin++;
7031             }
7032 
7033             if (mWifiBatchedScanBinStarted == bin) return;
7034 
7035             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
7036                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
7037                         stopRunningLocked(elapsedRealtimeMs);
7038             }
7039             mWifiBatchedScanBinStarted = bin;
7040             if (mWifiBatchedScanTimer[bin] == null) {
7041                 makeWifiBatchedScanBin(bin, null);
7042             }
7043             mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
7044         }
7045 
7046         @Override
noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs)7047         public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
7048             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
7049                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
7050                         stopRunningLocked(elapsedRealtimeMs);
7051                 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
7052             }
7053         }
7054 
7055         @Override
noteWifiMulticastEnabledLocked(long elapsedRealtimeMs)7056         public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
7057             if (mWifiMulticastWakelockCount == 0) {
7058                 if (mWifiMulticastTimer == null) {
7059                     mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7060                             WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
7061                 }
7062                 mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
7063             }
7064             mWifiMulticastWakelockCount++;
7065         }
7066 
7067         @Override
noteWifiMulticastDisabledLocked(long elapsedRealtimeMs)7068         public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
7069             if (mWifiMulticastWakelockCount == 0) {
7070                 return;
7071             }
7072 
7073             mWifiMulticastWakelockCount--;
7074             if (mWifiMulticastWakelockCount == 0) {
7075                 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
7076             }
7077         }
7078 
7079         @Override
getWifiControllerActivity()7080         public ControllerActivityCounter getWifiControllerActivity() {
7081             return mWifiControllerActivity;
7082         }
7083 
7084         @Override
getBluetoothControllerActivity()7085         public ControllerActivityCounter getBluetoothControllerActivity() {
7086             return mBluetoothControllerActivity;
7087         }
7088 
7089         @Override
getModemControllerActivity()7090         public ControllerActivityCounter getModemControllerActivity() {
7091             return mModemControllerActivity;
7092         }
7093 
getOrCreateWifiControllerActivityLocked()7094         public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
7095             if (mWifiControllerActivity == null) {
7096                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7097                         NUM_BT_TX_LEVELS);
7098             }
7099             return mWifiControllerActivity;
7100         }
7101 
getOrCreateBluetoothControllerActivityLocked()7102         public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
7103             if (mBluetoothControllerActivity == null) {
7104                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7105                         NUM_BT_TX_LEVELS);
7106             }
7107             return mBluetoothControllerActivity;
7108         }
7109 
getOrCreateModemControllerActivityLocked()7110         public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
7111             if (mModemControllerActivity == null) {
7112                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7113                         ModemActivityInfo.TX_POWER_LEVELS);
7114             }
7115             return mModemControllerActivity;
7116         }
7117 
createAudioTurnedOnTimerLocked()7118         public StopwatchTimer createAudioTurnedOnTimerLocked() {
7119             if (mAudioTurnedOnTimer == null) {
7120                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
7121                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7122             }
7123             return mAudioTurnedOnTimer;
7124         }
7125 
noteAudioTurnedOnLocked(long elapsedRealtimeMs)7126         public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
7127             createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7128         }
7129 
noteAudioTurnedOffLocked(long elapsedRealtimeMs)7130         public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
7131             if (mAudioTurnedOnTimer != null) {
7132                 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7133             }
7134         }
7135 
noteResetAudioLocked(long elapsedRealtimeMs)7136         public void noteResetAudioLocked(long elapsedRealtimeMs) {
7137             if (mAudioTurnedOnTimer != null) {
7138                 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7139             }
7140         }
7141 
createVideoTurnedOnTimerLocked()7142         public StopwatchTimer createVideoTurnedOnTimerLocked() {
7143             if (mVideoTurnedOnTimer == null) {
7144                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
7145                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7146             }
7147             return mVideoTurnedOnTimer;
7148         }
7149 
noteVideoTurnedOnLocked(long elapsedRealtimeMs)7150         public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
7151             createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7152         }
7153 
noteVideoTurnedOffLocked(long elapsedRealtimeMs)7154         public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
7155             if (mVideoTurnedOnTimer != null) {
7156                 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7157             }
7158         }
7159 
noteResetVideoLocked(long elapsedRealtimeMs)7160         public void noteResetVideoLocked(long elapsedRealtimeMs) {
7161             if (mVideoTurnedOnTimer != null) {
7162                 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7163             }
7164         }
7165 
createFlashlightTurnedOnTimerLocked()7166         public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
7167             if (mFlashlightTurnedOnTimer == null) {
7168                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7169                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7170             }
7171             return mFlashlightTurnedOnTimer;
7172         }
7173 
noteFlashlightTurnedOnLocked(long elapsedRealtimeMs)7174         public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
7175             createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7176         }
7177 
noteFlashlightTurnedOffLocked(long elapsedRealtimeMs)7178         public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
7179             if (mFlashlightTurnedOnTimer != null) {
7180                 mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7181             }
7182         }
7183 
noteResetFlashlightLocked(long elapsedRealtimeMs)7184         public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
7185             if (mFlashlightTurnedOnTimer != null) {
7186                 mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7187             }
7188         }
7189 
createCameraTurnedOnTimerLocked()7190         public StopwatchTimer createCameraTurnedOnTimerLocked() {
7191             if (mCameraTurnedOnTimer == null) {
7192                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
7193                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7194             }
7195             return mCameraTurnedOnTimer;
7196         }
7197 
noteCameraTurnedOnLocked(long elapsedRealtimeMs)7198         public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
7199             createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7200         }
7201 
noteCameraTurnedOffLocked(long elapsedRealtimeMs)7202         public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
7203             if (mCameraTurnedOnTimer != null) {
7204                 mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7205             }
7206         }
7207 
noteResetCameraLocked(long elapsedRealtimeMs)7208         public void noteResetCameraLocked(long elapsedRealtimeMs) {
7209             if (mCameraTurnedOnTimer != null) {
7210                 mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7211             }
7212         }
7213 
createForegroundActivityTimerLocked()7214         public StopwatchTimer createForegroundActivityTimerLocked() {
7215             if (mForegroundActivityTimer == null) {
7216                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7217                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
7218             }
7219             return mForegroundActivityTimer;
7220         }
7221 
createForegroundServiceTimerLocked()7222         public StopwatchTimer createForegroundServiceTimerLocked() {
7223             if (mForegroundServiceTimer == null) {
7224                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7225                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase);
7226             }
7227             return mForegroundServiceTimer;
7228         }
7229 
createAggregatedPartialWakelockTimerLocked()7230         public DualTimer createAggregatedPartialWakelockTimerLocked() {
7231             if (mAggregatedPartialWakelockTimer == null) {
7232                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
7233                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
7234                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase);
7235             }
7236             return mAggregatedPartialWakelockTimer;
7237         }
7238 
createBluetoothScanTimerLocked()7239         public DualTimer createBluetoothScanTimerLocked() {
7240             if (mBluetoothScanTimer == null) {
7241                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
7242                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
7243                         mOnBatteryBackgroundTimeBase);
7244             }
7245             return mBluetoothScanTimer;
7246         }
7247 
createBluetoothUnoptimizedScanTimerLocked()7248         public DualTimer createBluetoothUnoptimizedScanTimerLocked() {
7249             if (mBluetoothUnoptimizedScanTimer == null) {
7250                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
7251                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
7252                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
7253             }
7254             return mBluetoothUnoptimizedScanTimer;
7255         }
7256 
noteBluetoothScanStartedLocked(long elapsedRealtimeMs, boolean isUnoptimized)7257         public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs,
7258                 boolean isUnoptimized) {
7259             createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
7260             if (isUnoptimized) {
7261                 createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
7262             }
7263         }
7264 
noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized)7265         public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
7266             if (mBluetoothScanTimer != null) {
7267                 mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
7268             }
7269             if (isUnoptimized && mBluetoothUnoptimizedScanTimer != null) {
7270                 mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs);
7271             }
7272         }
7273 
noteResetBluetoothScanLocked(long elapsedRealtimeMs)7274         public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
7275             if (mBluetoothScanTimer != null) {
7276                 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
7277             }
7278             if (mBluetoothUnoptimizedScanTimer != null) {
7279                 mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
7280             }
7281         }
7282 
createBluetoothScanResultCounterLocked()7283         public Counter createBluetoothScanResultCounterLocked() {
7284             if (mBluetoothScanResultCounter == null) {
7285                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase);
7286             }
7287             return mBluetoothScanResultCounter;
7288         }
7289 
createBluetoothScanResultBgCounterLocked()7290         public Counter createBluetoothScanResultBgCounterLocked() {
7291             if (mBluetoothScanResultBgCounter == null) {
7292                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase);
7293             }
7294             return mBluetoothScanResultBgCounter;
7295         }
7296 
noteBluetoothScanResultsLocked(int numNewResults)7297         public void noteBluetoothScanResultsLocked(int numNewResults) {
7298             createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
7299             // Uses background timebase, so the count will only be incremented if uid in background.
7300             createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults);
7301         }
7302 
7303         @Override
noteActivityResumedLocked(long elapsedRealtimeMs)7304         public void noteActivityResumedLocked(long elapsedRealtimeMs) {
7305             // We always start, since we want multiple foreground PIDs to nest
7306             createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
7307         }
7308 
7309         @Override
noteActivityPausedLocked(long elapsedRealtimeMs)7310         public void noteActivityPausedLocked(long elapsedRealtimeMs) {
7311             if (mForegroundActivityTimer != null) {
7312                 mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
7313             }
7314         }
7315 
noteForegroundServiceResumedLocked(long elapsedRealtimeMs)7316         public void noteForegroundServiceResumedLocked(long elapsedRealtimeMs) {
7317             createForegroundServiceTimerLocked().startRunningLocked(elapsedRealtimeMs);
7318         }
7319 
noteForegroundServicePausedLocked(long elapsedRealtimeMs)7320         public void noteForegroundServicePausedLocked(long elapsedRealtimeMs) {
7321             if (mForegroundServiceTimer != null) {
7322                 mForegroundServiceTimer.stopRunningLocked(elapsedRealtimeMs);
7323             }
7324         }
7325 
createVibratorOnTimerLocked()7326         public BatchTimer createVibratorOnTimerLocked() {
7327             if (mVibratorOnTimer == null) {
7328                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
7329                         mBsi.mOnBatteryTimeBase);
7330             }
7331             return mVibratorOnTimer;
7332         }
7333 
noteVibratorOnLocked(long durationMillis)7334         public void noteVibratorOnLocked(long durationMillis) {
7335             createVibratorOnTimerLocked().addDuration(mBsi, durationMillis);
7336         }
7337 
noteVibratorOffLocked()7338         public void noteVibratorOffLocked() {
7339             if (mVibratorOnTimer != null) {
7340                 mVibratorOnTimer.abortLastDuration(mBsi);
7341             }
7342         }
7343 
7344         @Override
7345         @UnsupportedAppUsage
getWifiRunningTime(long elapsedRealtimeUs, int which)7346         public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
7347             if (mWifiRunningTimer == null) {
7348                 return 0;
7349             }
7350             return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7351         }
7352 
7353         @Override
getFullWifiLockTime(long elapsedRealtimeUs, int which)7354         public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
7355             if (mFullWifiLockTimer == null) {
7356                 return 0;
7357             }
7358             return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7359         }
7360 
7361         @Override
7362         @UnsupportedAppUsage
getWifiScanTime(long elapsedRealtimeUs, int which)7363         public long getWifiScanTime(long elapsedRealtimeUs, int which) {
7364             if (mWifiScanTimer == null) {
7365                 return 0;
7366             }
7367             return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7368         }
7369 
7370         @Override
getWifiScanCount(int which)7371         public int getWifiScanCount(int which) {
7372             if (mWifiScanTimer == null) {
7373                 return 0;
7374             }
7375             return mWifiScanTimer.getCountLocked(which);
7376         }
7377 
7378         @Override
getWifiScanTimer()7379         public Timer getWifiScanTimer() {
7380             return mWifiScanTimer;
7381         }
7382 
7383         @Override
getWifiScanBackgroundCount(int which)7384         public int getWifiScanBackgroundCount(int which) {
7385             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
7386                 return 0;
7387             }
7388             return mWifiScanTimer.getSubTimer().getCountLocked(which);
7389         }
7390 
7391         @Override
getWifiScanActualTime(final long elapsedRealtimeUs)7392         public long getWifiScanActualTime(final long elapsedRealtimeUs) {
7393             if (mWifiScanTimer == null) {
7394                 return 0;
7395             }
7396             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
7397             return mWifiScanTimer.getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
7398         }
7399 
7400         @Override
getWifiScanBackgroundTime(final long elapsedRealtimeUs)7401         public long getWifiScanBackgroundTime(final long elapsedRealtimeUs) {
7402             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
7403                 return 0;
7404             }
7405             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
7406             return mWifiScanTimer.getSubTimer().getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
7407         }
7408 
7409         @Override
getWifiScanBackgroundTimer()7410         public Timer getWifiScanBackgroundTimer() {
7411             if (mWifiScanTimer == null) {
7412                 return null;
7413             }
7414             return mWifiScanTimer.getSubTimer();
7415         }
7416 
7417         @Override
getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which)7418         public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
7419             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
7420             if (mWifiBatchedScanTimer[csphBin] == null) {
7421                 return 0;
7422             }
7423             return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
7424         }
7425 
7426         @Override
getWifiBatchedScanCount(int csphBin, int which)7427         public int getWifiBatchedScanCount(int csphBin, int which) {
7428             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
7429             if (mWifiBatchedScanTimer[csphBin] == null) {
7430                 return 0;
7431             }
7432             return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
7433         }
7434 
7435         @Override
getWifiMulticastTime(long elapsedRealtimeUs, int which)7436         public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
7437             if (mWifiMulticastTimer == null) {
7438                 return 0;
7439             }
7440             return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7441         }
7442 
7443         @Override
getAudioTurnedOnTimer()7444         public Timer getAudioTurnedOnTimer() {
7445             return mAudioTurnedOnTimer;
7446         }
7447 
7448         @Override
getVideoTurnedOnTimer()7449         public Timer getVideoTurnedOnTimer() {
7450             return mVideoTurnedOnTimer;
7451         }
7452 
7453         @Override
getFlashlightTurnedOnTimer()7454         public Timer getFlashlightTurnedOnTimer() {
7455             return mFlashlightTurnedOnTimer;
7456         }
7457 
7458         @Override
getCameraTurnedOnTimer()7459         public Timer getCameraTurnedOnTimer() {
7460             return mCameraTurnedOnTimer;
7461         }
7462 
7463         @Override
getForegroundActivityTimer()7464         public Timer getForegroundActivityTimer() {
7465             return mForegroundActivityTimer;
7466         }
7467 
7468         @Override
getForegroundServiceTimer()7469         public Timer getForegroundServiceTimer() {
7470             return mForegroundServiceTimer;
7471         }
7472 
7473         @Override
getBluetoothScanTimer()7474         public Timer getBluetoothScanTimer() {
7475             return mBluetoothScanTimer;
7476         }
7477 
7478         @Override
getBluetoothScanBackgroundTimer()7479         public Timer getBluetoothScanBackgroundTimer() {
7480             if (mBluetoothScanTimer == null) {
7481                 return null;
7482             }
7483             return mBluetoothScanTimer.getSubTimer();
7484         }
7485 
7486         @Override
getBluetoothUnoptimizedScanTimer()7487         public Timer getBluetoothUnoptimizedScanTimer() {
7488             return mBluetoothUnoptimizedScanTimer;
7489         }
7490 
7491         @Override
getBluetoothUnoptimizedScanBackgroundTimer()7492         public Timer getBluetoothUnoptimizedScanBackgroundTimer() {
7493             if (mBluetoothUnoptimizedScanTimer == null) {
7494                 return null;
7495             }
7496             return mBluetoothUnoptimizedScanTimer.getSubTimer();
7497         }
7498 
7499         @Override
getBluetoothScanResultCounter()7500         public Counter getBluetoothScanResultCounter() {
7501             return mBluetoothScanResultCounter;
7502         }
7503 
7504         @Override
getBluetoothScanResultBgCounter()7505         public Counter getBluetoothScanResultBgCounter() {
7506             return mBluetoothScanResultBgCounter;
7507         }
7508 
makeProcessState(int i, Parcel in)7509         void makeProcessState(int i, Parcel in) {
7510             if (i < 0 || i >= NUM_PROCESS_STATE) return;
7511 
7512             detachIfNotNull(mProcessStateTimer[i]);
7513             if (in == null) {
7514                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
7515                         mBsi.mOnBatteryTimeBase);
7516             } else {
7517                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
7518                         mBsi.mOnBatteryTimeBase, in);
7519             }
7520         }
7521 
7522         @Override
getProcessStateTime(int state, long elapsedRealtimeUs, int which)7523         public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
7524             if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
7525             if (mProcessStateTimer[state] == null) {
7526                 return 0;
7527             }
7528             return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
7529         }
7530 
7531         @Override
getProcessStateTimer(int state)7532         public Timer getProcessStateTimer(int state) {
7533             if (state < 0 || state >= NUM_PROCESS_STATE) return null;
7534             return mProcessStateTimer[state];
7535         }
7536 
7537         @Override
getVibratorOnTimer()7538         public Timer getVibratorOnTimer() {
7539             return mVibratorOnTimer;
7540         }
7541 
7542         @Override
noteUserActivityLocked(int type)7543         public void noteUserActivityLocked(int type) {
7544             if (mUserActivityCounters == null) {
7545                 initUserActivityLocked();
7546             }
7547             if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
7548                 mUserActivityCounters[type].stepAtomic();
7549             } else {
7550                 Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
7551                         new Throwable());
7552             }
7553         }
7554 
7555         @Override
hasUserActivity()7556         public boolean hasUserActivity() {
7557             return mUserActivityCounters != null;
7558         }
7559 
7560         @Override
getUserActivityCount(int type, int which)7561         public int getUserActivityCount(int type, int which) {
7562             if (mUserActivityCounters == null) {
7563                 return 0;
7564             }
7565             return mUserActivityCounters[type].getCountLocked(which);
7566         }
7567 
makeWifiBatchedScanBin(int i, Parcel in)7568         void makeWifiBatchedScanBin(int i, Parcel in) {
7569             if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
7570 
7571             ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
7572             if (collected == null) {
7573                 collected = new ArrayList<StopwatchTimer>();
7574                 mBsi.mWifiBatchedScanTimers.put(i, collected);
7575             }
7576             detachIfNotNull(mWifiBatchedScanTimer[i]);
7577             if (in == null) {
7578                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
7579                         collected, mBsi.mOnBatteryTimeBase);
7580             } else {
7581                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
7582                         collected, mBsi.mOnBatteryTimeBase, in);
7583             }
7584         }
7585 
7586 
initUserActivityLocked()7587         void initUserActivityLocked() {
7588             detachIfNotNull(mUserActivityCounters);
7589             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
7590             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
7591                 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
7592             }
7593         }
7594 
noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets)7595         void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
7596             if (mNetworkByteActivityCounters == null) {
7597                 initNetworkActivityLocked();
7598             }
7599             if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
7600                 mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
7601                 mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
7602             } else {
7603                 Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
7604                         new Throwable());
7605             }
7606         }
7607 
noteMobileRadioActiveTimeLocked(long batteryUptime)7608         void noteMobileRadioActiveTimeLocked(long batteryUptime) {
7609             if (mNetworkByteActivityCounters == null) {
7610                 initNetworkActivityLocked();
7611             }
7612             mMobileRadioActiveTime.addCountLocked(batteryUptime);
7613             mMobileRadioActiveCount.addCountLocked(1);
7614         }
7615 
7616         @Override
hasNetworkActivity()7617         public boolean hasNetworkActivity() {
7618             return mNetworkByteActivityCounters != null;
7619         }
7620 
7621         @Override
getNetworkActivityBytes(int type, int which)7622         public long getNetworkActivityBytes(int type, int which) {
7623             if (mNetworkByteActivityCounters != null && type >= 0
7624                     && type < mNetworkByteActivityCounters.length) {
7625                 return mNetworkByteActivityCounters[type].getCountLocked(which);
7626             } else {
7627                 return 0;
7628             }
7629         }
7630 
7631         @Override
getNetworkActivityPackets(int type, int which)7632         public long getNetworkActivityPackets(int type, int which) {
7633             if (mNetworkPacketActivityCounters != null && type >= 0
7634                     && type < mNetworkPacketActivityCounters.length) {
7635                 return mNetworkPacketActivityCounters[type].getCountLocked(which);
7636             } else {
7637                 return 0;
7638             }
7639         }
7640 
7641         @Override
getMobileRadioActiveTime(int which)7642         public long getMobileRadioActiveTime(int which) {
7643             return mMobileRadioActiveTime != null
7644                     ? mMobileRadioActiveTime.getCountLocked(which) : 0;
7645         }
7646 
7647         @Override
getMobileRadioActiveCount(int which)7648         public int getMobileRadioActiveCount(int which) {
7649             return mMobileRadioActiveCount != null
7650                     ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
7651         }
7652 
7653         @Override
getUserCpuTimeUs(int which)7654         public long getUserCpuTimeUs(int which) {
7655             return mUserCpuTime.getCountLocked(which);
7656         }
7657 
7658         @Override
getSystemCpuTimeUs(int which)7659         public long getSystemCpuTimeUs(int which) {
7660             return mSystemCpuTime.getCountLocked(which);
7661         }
7662 
7663         @Override
getTimeAtCpuSpeed(int cluster, int step, int which)7664         public long getTimeAtCpuSpeed(int cluster, int step, int which) {
7665             if (mCpuClusterSpeedTimesUs != null) {
7666                 if (cluster >= 0 && cluster < mCpuClusterSpeedTimesUs.length) {
7667                     final LongSamplingCounter[] cpuSpeedTimesUs = mCpuClusterSpeedTimesUs[cluster];
7668                     if (cpuSpeedTimesUs != null) {
7669                         if (step >= 0 && step < cpuSpeedTimesUs.length) {
7670                             final LongSamplingCounter c = cpuSpeedTimesUs[step];
7671                             if (c != null) {
7672                                 return c.getCountLocked(which);
7673                             }
7674                         }
7675                     }
7676                 }
7677             }
7678             return 0;
7679         }
7680 
noteMobileRadioApWakeupLocked()7681         public void noteMobileRadioApWakeupLocked() {
7682             if (mMobileRadioApWakeupCount == null) {
7683                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7684             }
7685             mMobileRadioApWakeupCount.addCountLocked(1);
7686         }
7687 
7688         @Override
getMobileRadioApWakeupCount(int which)7689         public long getMobileRadioApWakeupCount(int which) {
7690             if (mMobileRadioApWakeupCount != null) {
7691                 return mMobileRadioApWakeupCount.getCountLocked(which);
7692             }
7693             return 0;
7694         }
7695 
noteWifiRadioApWakeupLocked()7696         public void noteWifiRadioApWakeupLocked() {
7697             if (mWifiRadioApWakeupCount == null) {
7698                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7699             }
7700             mWifiRadioApWakeupCount.addCountLocked(1);
7701         }
7702 
7703         @Override
getWifiRadioApWakeupCount(int which)7704         public long getWifiRadioApWakeupCount(int which) {
7705             if (mWifiRadioApWakeupCount != null) {
7706                 return mWifiRadioApWakeupCount.getCountLocked(which);
7707             }
7708             return 0;
7709         }
7710 
7711         @Override
getDeferredJobsCheckinLineLocked(StringBuilder sb, int which)7712         public void getDeferredJobsCheckinLineLocked(StringBuilder sb, int which) {
7713             sb.setLength(0);
7714             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
7715             if (deferredEventCount == 0) {
7716                 return;
7717             }
7718             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
7719             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
7720             sb.append(deferredEventCount); sb.append(',');
7721             sb.append(deferredCount); sb.append(',');
7722             sb.append(totalLatency);
7723             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
7724                 if (mJobsFreshnessBuckets[i] == null) {
7725                     sb.append(",0");
7726                 } else {
7727                     sb.append(",");
7728                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
7729                 }
7730             }
7731         }
7732 
7733         @Override
getDeferredJobsLineLocked(StringBuilder sb, int which)7734         public void getDeferredJobsLineLocked(StringBuilder sb, int which) {
7735             sb.setLength(0);
7736             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
7737             if (deferredEventCount == 0) {
7738                 return;
7739             }
7740             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
7741             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
7742             sb.append("times="); sb.append(deferredEventCount); sb.append(", ");
7743             sb.append("count="); sb.append(deferredCount); sb.append(", ");
7744             sb.append("totalLatencyMs="); sb.append(totalLatency); sb.append(", ");
7745             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
7746                 sb.append("<"); sb.append(JOB_FRESHNESS_BUCKETS[i]); sb.append("ms=");
7747                 if (mJobsFreshnessBuckets[i] == null) {
7748                     sb.append("0");
7749                 } else {
7750                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
7751                 }
7752                 sb.append(" ");
7753             }
7754         }
7755 
initNetworkActivityLocked()7756         void initNetworkActivityLocked() {
7757             detachIfNotNull(mNetworkByteActivityCounters);
7758             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
7759             detachIfNotNull(mNetworkPacketActivityCounters);
7760             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
7761             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7762                 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7763                 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7764             }
7765             detachIfNotNull(mMobileRadioActiveTime);
7766             mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7767             detachIfNotNull(mMobileRadioActiveCount);
7768             mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7769         }
7770 
7771         /**
7772          * Clear all stats for this uid.  Returns true if the uid is completely
7773          * inactive so can be dropped.
7774          */
7775         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
reset(long uptime, long realtime)7776         public boolean reset(long uptime, long realtime) {
7777             boolean active = false;
7778 
7779             mOnBatteryBackgroundTimeBase.init(uptime, realtime);
7780             mOnBatteryScreenOffBackgroundTimeBase.init(uptime, realtime);
7781 
7782             if (mWifiRunningTimer != null) {
7783                 active |= !mWifiRunningTimer.reset(false);
7784                 active |= mWifiRunning;
7785             }
7786             if (mFullWifiLockTimer != null) {
7787                 active |= !mFullWifiLockTimer.reset(false);
7788                 active |= mFullWifiLockOut;
7789             }
7790             if (mWifiScanTimer != null) {
7791                 active |= !mWifiScanTimer.reset(false);
7792                 active |= mWifiScanStarted;
7793             }
7794             if (mWifiBatchedScanTimer != null) {
7795                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
7796                     if (mWifiBatchedScanTimer[i] != null) {
7797                         active |= !mWifiBatchedScanTimer[i].reset(false);
7798                     }
7799                 }
7800                 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
7801             }
7802             if (mWifiMulticastTimer != null) {
7803                 active |= !mWifiMulticastTimer.reset(false);
7804                 active |= (mWifiMulticastWakelockCount > 0);
7805             }
7806 
7807             active |= !resetIfNotNull(mAudioTurnedOnTimer, false);
7808             active |= !resetIfNotNull(mVideoTurnedOnTimer, false);
7809             active |= !resetIfNotNull(mFlashlightTurnedOnTimer, false);
7810             active |= !resetIfNotNull(mCameraTurnedOnTimer, false);
7811             active |= !resetIfNotNull(mForegroundActivityTimer, false);
7812             active |= !resetIfNotNull(mForegroundServiceTimer, false);
7813             active |= !resetIfNotNull(mAggregatedPartialWakelockTimer, false);
7814             active |= !resetIfNotNull(mBluetoothScanTimer, false);
7815             active |= !resetIfNotNull(mBluetoothUnoptimizedScanTimer, false);
7816 
7817             resetIfNotNull(mBluetoothScanResultCounter, false);
7818             resetIfNotNull(mBluetoothScanResultBgCounter, false);
7819 
7820             if (mProcessStateTimer != null) {
7821                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
7822                     active |= !resetIfNotNull(mProcessStateTimer[i], false);
7823                 }
7824                 active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
7825             }
7826             if (mVibratorOnTimer != null) {
7827                 if (mVibratorOnTimer.reset(false)) {
7828                     mVibratorOnTimer.detach();
7829                     mVibratorOnTimer = null;
7830                 } else {
7831                     active = true;
7832                 }
7833             }
7834 
7835             resetIfNotNull(mUserActivityCounters, false);
7836 
7837             resetIfNotNull(mNetworkByteActivityCounters, false);
7838             resetIfNotNull(mNetworkPacketActivityCounters, false);
7839             resetIfNotNull(mMobileRadioActiveTime, false);
7840             resetIfNotNull(mMobileRadioActiveCount, false);
7841 
7842             resetIfNotNull(mWifiControllerActivity, false);
7843             resetIfNotNull(mBluetoothControllerActivity, false);
7844             resetIfNotNull(mModemControllerActivity, false);
7845 
7846             resetIfNotNull(mUserCpuTime, false);
7847             resetIfNotNull(mSystemCpuTime, false);
7848 
7849             resetIfNotNull(mCpuClusterSpeedTimesUs, false);
7850 
7851             resetIfNotNull(mCpuFreqTimeMs, false);
7852             resetIfNotNull(mScreenOffCpuFreqTimeMs, false);
7853 
7854 
7855             resetIfNotNull(mCpuActiveTimeMs, false);
7856             resetIfNotNull(mCpuClusterTimesMs, false);
7857 
7858             resetIfNotNull(mProcStateTimeMs, false);
7859 
7860             resetIfNotNull(mProcStateScreenOffTimeMs, false);
7861 
7862             resetIfNotNull(mMobileRadioApWakeupCount, false);
7863 
7864             resetIfNotNull(mWifiRadioApWakeupCount, false);
7865 
7866 
7867             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
7868             for (int iw=wakeStats.size()-1; iw>=0; iw--) {
7869                 Wakelock wl = wakeStats.valueAt(iw);
7870                 if (wl.reset()) {
7871                     wakeStats.removeAt(iw);
7872                 } else {
7873                     active = true;
7874                 }
7875             }
7876             mWakelockStats.cleanup();
7877             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
7878             for (int is=syncStats.size()-1; is>=0; is--) {
7879                 DualTimer timer = syncStats.valueAt(is);
7880                 if (timer.reset(false)) {
7881                     syncStats.removeAt(is);
7882                     timer.detach();
7883                 } else {
7884                     active = true;
7885                 }
7886             }
7887             mSyncStats.cleanup();
7888             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
7889             for (int ij=jobStats.size()-1; ij>=0; ij--) {
7890                 DualTimer timer = jobStats.valueAt(ij);
7891                 if (timer.reset(false)) {
7892                     jobStats.removeAt(ij);
7893                     timer.detach();
7894                 } else {
7895                     active = true;
7896                 }
7897             }
7898             mJobStats.cleanup();
7899             mJobCompletions.clear();
7900 
7901             resetIfNotNull(mJobsDeferredEventCount, false);
7902             resetIfNotNull(mJobsDeferredCount, false);
7903             resetIfNotNull(mJobsFreshnessTimeMs, false);
7904             resetIfNotNull(mJobsFreshnessBuckets, false);
7905 
7906             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
7907                 Sensor s = mSensorStats.valueAt(ise);
7908                 if (s.reset()) {
7909                     mSensorStats.removeAt(ise);
7910                 } else {
7911                     active = true;
7912                 }
7913             }
7914 
7915             for (int ip = mProcessStats.size() - 1; ip >= 0; ip--) {
7916                 Proc proc = mProcessStats.valueAt(ip);
7917                 proc.detach();
7918             }
7919             mProcessStats.clear();
7920 
7921             for (int i = mPids.size() - 1; i >= 0; i--) {
7922                 Pid pid = mPids.valueAt(i);
7923                 if (pid.mWakeNesting > 0) {
7924                     active = true;
7925                 } else {
7926                     mPids.removeAt(i);
7927                 }
7928             }
7929 
7930 
7931             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
7932                 Pkg p = mPackageStats.valueAt(i);
7933                 p.detach();
7934             }
7935             mPackageStats.clear();
7936 
7937             mLastStepUserTime = mLastStepSystemTime = 0;
7938             mCurStepUserTime = mCurStepSystemTime = 0;
7939 
7940             return !active;
7941         }
7942 
7943         /**
7944          * This method MUST be called whenever the Uid object is destructed, otherwise it is a
7945          * memory leak in {@link TimeBase#mObservers} list.
7946          * Typically the Uid object is destructed when it is removed from
7947          * {@link BatteryStatsImpl#mUidStats}
7948          */
detachFromTimeBase()7949         void detachFromTimeBase() {
7950             detachIfNotNull(mWifiRunningTimer);
7951             detachIfNotNull(mFullWifiLockTimer);
7952             detachIfNotNull(mWifiScanTimer);
7953             detachIfNotNull(mWifiBatchedScanTimer);
7954             detachIfNotNull(mWifiMulticastTimer);
7955             detachIfNotNull(mAudioTurnedOnTimer);
7956             detachIfNotNull(mVideoTurnedOnTimer);
7957             detachIfNotNull(mFlashlightTurnedOnTimer);
7958 
7959             detachIfNotNull(mCameraTurnedOnTimer);
7960             detachIfNotNull(mForegroundActivityTimer);
7961             detachIfNotNull(mForegroundServiceTimer);
7962 
7963             detachIfNotNull(mAggregatedPartialWakelockTimer);
7964 
7965             detachIfNotNull(mBluetoothScanTimer);
7966             detachIfNotNull(mBluetoothUnoptimizedScanTimer);
7967             detachIfNotNull(mBluetoothScanResultCounter);
7968             detachIfNotNull(mBluetoothScanResultBgCounter);
7969 
7970             detachIfNotNull(mProcessStateTimer);
7971 
7972             detachIfNotNull(mVibratorOnTimer);
7973 
7974             detachIfNotNull(mUserActivityCounters);
7975 
7976             detachIfNotNull(mNetworkByteActivityCounters);
7977             detachIfNotNull(mNetworkPacketActivityCounters);
7978 
7979             detachIfNotNull(mMobileRadioActiveTime);
7980             detachIfNotNull(mMobileRadioActiveCount);
7981             detachIfNotNull(mMobileRadioApWakeupCount);
7982             detachIfNotNull(mWifiRadioApWakeupCount);
7983 
7984             detachIfNotNull(mWifiControllerActivity);
7985             detachIfNotNull(mBluetoothControllerActivity);
7986             detachIfNotNull(mModemControllerActivity);
7987 
7988             mPids.clear();
7989 
7990             detachIfNotNull(mUserCpuTime);
7991             detachIfNotNull(mSystemCpuTime);
7992 
7993             detachIfNotNull(mCpuClusterSpeedTimesUs);
7994 
7995             detachIfNotNull(mCpuActiveTimeMs);
7996             detachIfNotNull(mCpuFreqTimeMs);
7997 
7998             detachIfNotNull(mScreenOffCpuFreqTimeMs);
7999 
8000             detachIfNotNull(mCpuClusterTimesMs);
8001 
8002             detachIfNotNull(mProcStateTimeMs);
8003 
8004             detachIfNotNull(mProcStateScreenOffTimeMs);
8005 
8006             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
8007             for (int iw = wakeStats.size() - 1; iw >= 0; iw--) {
8008                 Wakelock wl = wakeStats.valueAt(iw);
8009                 wl.detachFromTimeBase();
8010             }
8011             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
8012             for (int is = syncStats.size() - 1; is >= 0; is--) {
8013                 DualTimer timer = syncStats.valueAt(is);
8014                 detachIfNotNull(timer);
8015             }
8016             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
8017             for (int ij = jobStats.size() - 1; ij >= 0; ij--) {
8018                 DualTimer timer = jobStats.valueAt(ij);
8019                 detachIfNotNull(timer);
8020             }
8021 
8022             detachIfNotNull(mJobsDeferredEventCount);
8023             detachIfNotNull(mJobsDeferredCount);
8024             detachIfNotNull(mJobsFreshnessTimeMs);
8025             detachIfNotNull(mJobsFreshnessBuckets);
8026 
8027 
8028             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
8029                 Sensor s = mSensorStats.valueAt(ise);
8030                 s.detachFromTimeBase();
8031             }
8032 
8033             for (int ip= mProcessStats.size() - 1; ip >= 0; ip--) {
8034                 Proc proc = mProcessStats.valueAt(ip);
8035                 proc.detach();
8036             }
8037             mProcessStats.clear();
8038 
8039             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
8040                 Pkg p = mPackageStats.valueAt(i);
8041                 p.detach();
8042             }
8043             mPackageStats.clear();
8044         }
8045 
writeJobCompletionsToParcelLocked(Parcel out)8046         void writeJobCompletionsToParcelLocked(Parcel out) {
8047             int NJC = mJobCompletions.size();
8048             out.writeInt(NJC);
8049             for (int ijc=0; ijc<NJC; ijc++) {
8050                 out.writeString(mJobCompletions.keyAt(ijc));
8051                 SparseIntArray types = mJobCompletions.valueAt(ijc);
8052                 int NT = types.size();
8053                 out.writeInt(NT);
8054                 for (int it=0; it<NT; it++) {
8055                     out.writeInt(types.keyAt(it));
8056                     out.writeInt(types.valueAt(it));
8057                 }
8058             }
8059         }
8060 
writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs)8061         void writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
8062             mOnBatteryBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
8063             mOnBatteryScreenOffBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
8064 
8065             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
8066             int NW = wakeStats.size();
8067             out.writeInt(NW);
8068             for (int iw=0; iw<NW; iw++) {
8069                 out.writeString(wakeStats.keyAt(iw));
8070                 Uid.Wakelock wakelock = wakeStats.valueAt(iw);
8071                 wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
8072             }
8073 
8074             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
8075             int NS = syncStats.size();
8076             out.writeInt(NS);
8077             for (int is=0; is<NS; is++) {
8078                 out.writeString(syncStats.keyAt(is));
8079                 DualTimer timer = syncStats.valueAt(is);
8080                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
8081             }
8082 
8083             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
8084             int NJ = jobStats.size();
8085             out.writeInt(NJ);
8086             for (int ij=0; ij<NJ; ij++) {
8087                 out.writeString(jobStats.keyAt(ij));
8088                 DualTimer timer = jobStats.valueAt(ij);
8089                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
8090             }
8091 
8092             writeJobCompletionsToParcelLocked(out);
8093 
8094             mJobsDeferredEventCount.writeToParcel(out);
8095             mJobsDeferredCount.writeToParcel(out);
8096             mJobsFreshnessTimeMs.writeToParcel(out);
8097             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8098                 Counter.writeCounterToParcel(out, mJobsFreshnessBuckets[i]);
8099             }
8100 
8101             int NSE = mSensorStats.size();
8102             out.writeInt(NSE);
8103             for (int ise=0; ise<NSE; ise++) {
8104                 out.writeInt(mSensorStats.keyAt(ise));
8105                 Uid.Sensor sensor = mSensorStats.valueAt(ise);
8106                 sensor.writeToParcelLocked(out, elapsedRealtimeUs);
8107             }
8108 
8109             int NP = mProcessStats.size();
8110             out.writeInt(NP);
8111             for (int ip=0; ip<NP; ip++) {
8112                 out.writeString(mProcessStats.keyAt(ip));
8113                 Uid.Proc proc = mProcessStats.valueAt(ip);
8114                 proc.writeToParcelLocked(out);
8115             }
8116 
8117             out.writeInt(mPackageStats.size());
8118             for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
8119                 out.writeString(pkgEntry.getKey());
8120                 Uid.Pkg pkg = pkgEntry.getValue();
8121                 pkg.writeToParcelLocked(out);
8122             }
8123 
8124             if (mWifiRunningTimer != null) {
8125                 out.writeInt(1);
8126                 mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
8127             } else {
8128                 out.writeInt(0);
8129             }
8130             if (mFullWifiLockTimer != null) {
8131                 out.writeInt(1);
8132                 mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
8133             } else {
8134                 out.writeInt(0);
8135             }
8136             if (mWifiScanTimer != null) {
8137                 out.writeInt(1);
8138                 mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
8139             } else {
8140                 out.writeInt(0);
8141             }
8142             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8143                 if (mWifiBatchedScanTimer[i] != null) {
8144                     out.writeInt(1);
8145                     mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
8146                 } else {
8147                     out.writeInt(0);
8148                 }
8149             }
8150             if (mWifiMulticastTimer != null) {
8151                 out.writeInt(1);
8152                 mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
8153             } else {
8154                 out.writeInt(0);
8155             }
8156 
8157             if (mAudioTurnedOnTimer != null) {
8158                 out.writeInt(1);
8159                 mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8160             } else {
8161                 out.writeInt(0);
8162             }
8163             if (mVideoTurnedOnTimer != null) {
8164                 out.writeInt(1);
8165                 mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8166             } else {
8167                 out.writeInt(0);
8168             }
8169             if (mFlashlightTurnedOnTimer != null) {
8170                 out.writeInt(1);
8171                 mFlashlightTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8172             } else {
8173                 out.writeInt(0);
8174             }
8175             if (mCameraTurnedOnTimer != null) {
8176                 out.writeInt(1);
8177                 mCameraTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8178             } else {
8179                 out.writeInt(0);
8180             }
8181             if (mForegroundActivityTimer != null) {
8182                 out.writeInt(1);
8183                 mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
8184             } else {
8185                 out.writeInt(0);
8186             }
8187             if (mForegroundServiceTimer != null) {
8188                 out.writeInt(1);
8189                 mForegroundServiceTimer.writeToParcel(out, elapsedRealtimeUs);
8190             } else {
8191                 out.writeInt(0);
8192             }
8193             if (mAggregatedPartialWakelockTimer != null) {
8194                 out.writeInt(1);
8195                 mAggregatedPartialWakelockTimer.writeToParcel(out, elapsedRealtimeUs);
8196             } else {
8197                 out.writeInt(0);
8198             }
8199             if (mBluetoothScanTimer != null) {
8200                 out.writeInt(1);
8201                 mBluetoothScanTimer.writeToParcel(out, elapsedRealtimeUs);
8202             } else {
8203                 out.writeInt(0);
8204             }
8205             if (mBluetoothUnoptimizedScanTimer != null) {
8206                 out.writeInt(1);
8207                 mBluetoothUnoptimizedScanTimer.writeToParcel(out, elapsedRealtimeUs);
8208             } else {
8209                 out.writeInt(0);
8210             }
8211             if (mBluetoothScanResultCounter != null) {
8212                 out.writeInt(1);
8213                 mBluetoothScanResultCounter.writeToParcel(out);
8214             } else {
8215                 out.writeInt(0);
8216             }
8217             if (mBluetoothScanResultBgCounter != null) {
8218                 out.writeInt(1);
8219                 mBluetoothScanResultBgCounter.writeToParcel(out);
8220             } else {
8221                 out.writeInt(0);
8222             }
8223             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
8224                 if (mProcessStateTimer[i] != null) {
8225                     out.writeInt(1);
8226                     mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
8227                 } else {
8228                     out.writeInt(0);
8229                 }
8230             }
8231             if (mVibratorOnTimer != null) {
8232                 out.writeInt(1);
8233                 mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
8234             } else {
8235                 out.writeInt(0);
8236             }
8237             if (mUserActivityCounters != null) {
8238                 out.writeInt(1);
8239                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8240                     mUserActivityCounters[i].writeToParcel(out);
8241                 }
8242             } else {
8243                 out.writeInt(0);
8244             }
8245             if (mNetworkByteActivityCounters != null) {
8246                 out.writeInt(1);
8247                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8248                     mNetworkByteActivityCounters[i].writeToParcel(out);
8249                     mNetworkPacketActivityCounters[i].writeToParcel(out);
8250                 }
8251                 mMobileRadioActiveTime.writeToParcel(out);
8252                 mMobileRadioActiveCount.writeToParcel(out);
8253             } else {
8254                 out.writeInt(0);
8255             }
8256 
8257             if (mWifiControllerActivity != null) {
8258                 out.writeInt(1);
8259                 mWifiControllerActivity.writeToParcel(out, 0);
8260             } else {
8261                 out.writeInt(0);
8262             }
8263 
8264             if (mBluetoothControllerActivity != null) {
8265                 out.writeInt(1);
8266                 mBluetoothControllerActivity.writeToParcel(out, 0);
8267             } else {
8268                 out.writeInt(0);
8269             }
8270 
8271             if (mModemControllerActivity != null) {
8272                 out.writeInt(1);
8273                 mModemControllerActivity.writeToParcel(out, 0);
8274             } else {
8275                 out.writeInt(0);
8276             }
8277 
8278             mUserCpuTime.writeToParcel(out);
8279             mSystemCpuTime.writeToParcel(out);
8280 
8281             if (mCpuClusterSpeedTimesUs != null) {
8282                 out.writeInt(1);
8283                 out.writeInt(mCpuClusterSpeedTimesUs.length);
8284                 for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) {
8285                     if (cpuSpeeds != null) {
8286                         out.writeInt(1);
8287                         out.writeInt(cpuSpeeds.length);
8288                         for (LongSamplingCounter c : cpuSpeeds) {
8289                             if (c != null) {
8290                                 out.writeInt(1);
8291                                 c.writeToParcel(out);
8292                             } else {
8293                                 out.writeInt(0);
8294                             }
8295                         }
8296                     } else {
8297                         out.writeInt(0);
8298                     }
8299                 }
8300             } else {
8301                 out.writeInt(0);
8302             }
8303 
8304             LongSamplingCounterArray.writeToParcel(out, mCpuFreqTimeMs);
8305             LongSamplingCounterArray.writeToParcel(out, mScreenOffCpuFreqTimeMs);
8306 
8307             mCpuActiveTimeMs.writeToParcel(out);
8308             mCpuClusterTimesMs.writeToParcel(out);
8309 
8310             if (mProcStateTimeMs != null) {
8311                 out.writeInt(mProcStateTimeMs.length);
8312                 for (LongSamplingCounterArray counters : mProcStateTimeMs) {
8313                     LongSamplingCounterArray.writeToParcel(out, counters);
8314                 }
8315             } else {
8316                 out.writeInt(0);
8317             }
8318             if (mProcStateScreenOffTimeMs != null) {
8319                 out.writeInt(mProcStateScreenOffTimeMs.length);
8320                 for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
8321                     LongSamplingCounterArray.writeToParcel(out, counters);
8322                 }
8323             } else {
8324                 out.writeInt(0);
8325             }
8326 
8327             if (mMobileRadioApWakeupCount != null) {
8328                 out.writeInt(1);
8329                 mMobileRadioApWakeupCount.writeToParcel(out);
8330             } else {
8331                 out.writeInt(0);
8332             }
8333 
8334             if (mWifiRadioApWakeupCount != null) {
8335                 out.writeInt(1);
8336                 mWifiRadioApWakeupCount.writeToParcel(out);
8337             } else {
8338                 out.writeInt(0);
8339             }
8340         }
8341 
readJobCompletionsFromParcelLocked(Parcel in)8342         void readJobCompletionsFromParcelLocked(Parcel in) {
8343             int numJobCompletions = in.readInt();
8344             mJobCompletions.clear();
8345             for (int j = 0; j < numJobCompletions; j++) {
8346                 String jobName = in.readString();
8347                 int numTypes = in.readInt();
8348                 if (numTypes > 0) {
8349                     SparseIntArray types = new SparseIntArray();
8350                     for (int k = 0; k < numTypes; k++) {
8351                         int type = in.readInt();
8352                         int count = in.readInt();
8353                         types.put(type, count);
8354                     }
8355                     mJobCompletions.put(jobName, types);
8356                 }
8357             }
8358         }
8359 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in)8360         void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
8361             mOnBatteryBackgroundTimeBase.readFromParcel(in);
8362             mOnBatteryScreenOffBackgroundTimeBase.readFromParcel(in);
8363 
8364             int numWakelocks = in.readInt();
8365             mWakelockStats.clear();
8366             for (int j = 0; j < numWakelocks; j++) {
8367                 String wakelockName = in.readString();
8368                 Uid.Wakelock wakelock = new Wakelock(mBsi, this);
8369                 wakelock.readFromParcelLocked(
8370                         timeBase, screenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase, in);
8371                 mWakelockStats.add(wakelockName, wakelock);
8372             }
8373 
8374             int numSyncs = in.readInt();
8375             mSyncStats.clear();
8376             for (int j = 0; j < numSyncs; j++) {
8377                 String syncName = in.readString();
8378                 if (in.readInt() != 0) {
8379                     mSyncStats.add(syncName, new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
8380                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
8381                 }
8382             }
8383 
8384             int numJobs = in.readInt();
8385             mJobStats.clear();
8386             for (int j = 0; j < numJobs; j++) {
8387                 String jobName = in.readString();
8388                 if (in.readInt() != 0) {
8389                     mJobStats.add(jobName, new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
8390                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
8391                 }
8392             }
8393 
8394             readJobCompletionsFromParcelLocked(in);
8395 
8396             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase, in);
8397             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase, in);
8398             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8399             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8400                 mJobsFreshnessBuckets[i] = Counter.readCounterFromParcel(mBsi.mOnBatteryTimeBase,
8401                         in);
8402             }
8403 
8404             int numSensors = in.readInt();
8405             mSensorStats.clear();
8406             for (int k = 0; k < numSensors; k++) {
8407                 int sensorNumber = in.readInt();
8408                 Uid.Sensor sensor = new Sensor(mBsi, this, sensorNumber);
8409                 sensor.readFromParcelLocked(mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
8410                         in);
8411                 mSensorStats.put(sensorNumber, sensor);
8412             }
8413 
8414             int numProcs = in.readInt();
8415             mProcessStats.clear();
8416             for (int k = 0; k < numProcs; k++) {
8417                 String processName = in.readString();
8418                 Uid.Proc proc = new Proc(mBsi, processName);
8419                 proc.readFromParcelLocked(in);
8420                 mProcessStats.put(processName, proc);
8421             }
8422 
8423             int numPkgs = in.readInt();
8424             mPackageStats.clear();
8425             for (int l = 0; l < numPkgs; l++) {
8426                 String packageName = in.readString();
8427                 Uid.Pkg pkg = new Pkg(mBsi);
8428                 pkg.readFromParcelLocked(in);
8429                 mPackageStats.put(packageName, pkg);
8430             }
8431 
8432             mWifiRunning = false;
8433             if (in.readInt() != 0) {
8434                 mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
8435                         mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase, in);
8436             } else {
8437                 mWifiRunningTimer = null;
8438             }
8439             mFullWifiLockOut = false;
8440             if (in.readInt() != 0) {
8441                 mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
8442                         mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase, in);
8443             } else {
8444                 mFullWifiLockTimer = null;
8445             }
8446             mWifiScanStarted = false;
8447             if (in.readInt() != 0) {
8448                 mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
8449                         mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
8450                         in);
8451             } else {
8452                 mWifiScanTimer = null;
8453             }
8454             mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
8455             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8456                 if (in.readInt() != 0) {
8457                     makeWifiBatchedScanBin(i, in);
8458                 } else {
8459                     mWifiBatchedScanTimer[i] = null;
8460                 }
8461             }
8462             mWifiMulticastWakelockCount = 0;
8463             if (in.readInt() != 0) {
8464                 mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_MULTICAST_ENABLED,
8465                         mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase, in);
8466             } else {
8467                 mWifiMulticastTimer = null;
8468             }
8469             if (in.readInt() != 0) {
8470                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
8471                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8472             } else {
8473                 mAudioTurnedOnTimer = null;
8474             }
8475             if (in.readInt() != 0) {
8476                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
8477                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8478             } else {
8479                 mVideoTurnedOnTimer = null;
8480             }
8481             if (in.readInt() != 0) {
8482                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8483                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8484             } else {
8485                 mFlashlightTurnedOnTimer = null;
8486             }
8487             if (in.readInt() != 0) {
8488                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
8489                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8490             } else {
8491                 mCameraTurnedOnTimer = null;
8492             }
8493             if (in.readInt() != 0) {
8494                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8495                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase, in);
8496             } else {
8497                 mForegroundActivityTimer = null;
8498             }
8499             if (in.readInt() != 0) {
8500                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8501                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase, in);
8502             } else {
8503                 mForegroundServiceTimer = null;
8504             }
8505             if (in.readInt() != 0) {
8506                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
8507                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
8508                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase,
8509                         in);
8510             } else {
8511                 mAggregatedPartialWakelockTimer = null;
8512             }
8513             if (in.readInt() != 0) {
8514                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
8515                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
8516                         mOnBatteryBackgroundTimeBase, in);
8517             } else {
8518                 mBluetoothScanTimer = null;
8519             }
8520             if (in.readInt() != 0) {
8521                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
8522                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
8523                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in);
8524             } else {
8525                 mBluetoothUnoptimizedScanTimer = null;
8526             }
8527             if (in.readInt() != 0) {
8528                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase, in);
8529             } else {
8530                 mBluetoothScanResultCounter = null;
8531             }
8532             if (in.readInt() != 0) {
8533                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase, in);
8534             } else {
8535                 mBluetoothScanResultBgCounter = null;
8536             }
8537             mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
8538             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
8539                 if (in.readInt() != 0) {
8540                     makeProcessState(i, in);
8541                 } else {
8542                     mProcessStateTimer[i] = null;
8543                 }
8544             }
8545             if (in.readInt() != 0) {
8546                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
8547                         mBsi.mOnBatteryTimeBase, in);
8548             } else {
8549                 mVibratorOnTimer = null;
8550             }
8551             if (in.readInt() != 0) {
8552                 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
8553                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8554                     mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase, in);
8555                 }
8556             } else {
8557                 mUserActivityCounters = null;
8558             }
8559             if (in.readInt() != 0) {
8560                 mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
8561                 mNetworkPacketActivityCounters
8562                         = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
8563                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8564                     mNetworkByteActivityCounters[i]
8565                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8566                     mNetworkPacketActivityCounters[i]
8567                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8568                 }
8569                 mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8570                 mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8571             } else {
8572                 mNetworkByteActivityCounters = null;
8573                 mNetworkPacketActivityCounters = null;
8574             }
8575 
8576             if (in.readInt() != 0) {
8577                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8578                         NUM_WIFI_TX_LEVELS, in);
8579             } else {
8580                 mWifiControllerActivity = null;
8581             }
8582 
8583             if (in.readInt() != 0) {
8584                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8585                         NUM_BT_TX_LEVELS, in);
8586             } else {
8587                 mBluetoothControllerActivity = null;
8588             }
8589 
8590             if (in.readInt() != 0) {
8591                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8592                         ModemActivityInfo.TX_POWER_LEVELS, in);
8593             } else {
8594                 mModemControllerActivity = null;
8595             }
8596 
8597             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8598             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8599 
8600             if (in.readInt() != 0) {
8601                 int numCpuClusters = in.readInt();
8602                 if (mBsi.mPowerProfile != null && mBsi.mPowerProfile.getNumCpuClusters() != numCpuClusters) {
8603                     throw new ParcelFormatException("Incompatible number of cpu clusters");
8604                 }
8605 
8606                 mCpuClusterSpeedTimesUs = new LongSamplingCounter[numCpuClusters][];
8607                 for (int cluster = 0; cluster < numCpuClusters; cluster++) {
8608                     if (in.readInt() != 0) {
8609                         int numSpeeds = in.readInt();
8610                         if (mBsi.mPowerProfile != null &&
8611                                 mBsi.mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
8612                             throw new ParcelFormatException("Incompatible number of cpu speeds");
8613                         }
8614 
8615                         final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
8616                         mCpuClusterSpeedTimesUs[cluster] = cpuSpeeds;
8617                         for (int speed = 0; speed < numSpeeds; speed++) {
8618                             if (in.readInt() != 0) {
8619                                 cpuSpeeds[speed] = new LongSamplingCounter(
8620                                         mBsi.mOnBatteryTimeBase, in);
8621                             }
8622                         }
8623                     } else {
8624                         mCpuClusterSpeedTimesUs[cluster] = null;
8625                     }
8626                 }
8627             } else {
8628                 mCpuClusterSpeedTimesUs = null;
8629             }
8630 
8631             mCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(in, mBsi.mOnBatteryTimeBase);
8632             mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(
8633                     in, mBsi.mOnBatteryScreenOffTimeBase);
8634 
8635             mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8636             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
8637 
8638             int length = in.readInt();
8639             if (length == NUM_PROCESS_STATE) {
8640                 mProcStateTimeMs = new LongSamplingCounterArray[length];
8641                 for (int procState = 0; procState < length; ++procState) {
8642                     mProcStateTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
8643                             in, mBsi.mOnBatteryTimeBase);
8644                 }
8645             } else {
8646                 mProcStateTimeMs = null;
8647             }
8648             length = in.readInt();
8649             if (length == NUM_PROCESS_STATE) {
8650                 mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
8651                 for (int procState = 0; procState < length; ++procState) {
8652                     mProcStateScreenOffTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
8653                             in, mBsi.mOnBatteryScreenOffTimeBase);
8654                 }
8655             } else {
8656                 mProcStateScreenOffTimeMs = null;
8657             }
8658 
8659             if (in.readInt() != 0) {
8660                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8661             } else {
8662                 mMobileRadioApWakeupCount = null;
8663             }
8664 
8665             if (in.readInt() != 0) {
8666                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8667             } else {
8668                 mWifiRadioApWakeupCount = null;
8669             }
8670         }
8671 
noteJobsDeferredLocked(int numDeferred, long sinceLast)8672         public void noteJobsDeferredLocked(int numDeferred, long sinceLast) {
8673             mJobsDeferredEventCount.addAtomic(1);
8674             mJobsDeferredCount.addAtomic(numDeferred);
8675             if (sinceLast != 0) {
8676                 // Add the total time, which can be divided by the event count to get an average
8677                 mJobsFreshnessTimeMs.addCountLocked(sinceLast);
8678                 // Also keep track of how many times there were in these different buckets.
8679                 for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8680                     if (sinceLast < JOB_FRESHNESS_BUCKETS[i]) {
8681                         if (mJobsFreshnessBuckets[i] == null) {
8682                             mJobsFreshnessBuckets[i] = new Counter(
8683                                     mBsi.mOnBatteryTimeBase);
8684                         }
8685                         mJobsFreshnessBuckets[i].addAtomic(1);
8686                         break;
8687                     }
8688                 }
8689             }
8690         }
8691 
8692         /**
8693          * The statistics associated with a particular wake lock.
8694          */
8695         public static class Wakelock extends BatteryStats.Uid.Wakelock {
8696             /**
8697              * BatteryStatsImpl that we are associated with.
8698              */
8699             protected BatteryStatsImpl mBsi;
8700 
8701             /**
8702              * BatteryStatsImpl that we are associated with.
8703              */
8704             protected Uid mUid;
8705 
8706             /**
8707              * How long (in ms) this uid has been keeping the device partially awake.
8708              * Tracks both the total time and the time while the app was in the background.
8709              */
8710             DualTimer mTimerPartial;
8711 
8712             /**
8713              * How long (in ms) this uid has been keeping the device fully awake.
8714              */
8715             StopwatchTimer mTimerFull;
8716 
8717             /**
8718              * How long (in ms) this uid has had a window keeping the device awake.
8719              */
8720             StopwatchTimer mTimerWindow;
8721 
8722             /**
8723              * How long (in ms) this uid has had a draw wake lock.
8724              */
8725             StopwatchTimer mTimerDraw;
8726 
Wakelock(BatteryStatsImpl bsi, Uid uid)8727             public Wakelock(BatteryStatsImpl bsi, Uid uid) {
8728                 mBsi = bsi;
8729                 mUid = uid;
8730             }
8731 
8732             /**
8733              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
8734              * proper timer pool from the given BatteryStatsImpl object.
8735              *
8736              * @param in the Parcel to be read from.
8737              * return a new Timer, or null.
8738              */
readStopwatchTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in)8739             private StopwatchTimer readStopwatchTimerFromParcel(int type,
8740                     ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
8741                 if (in.readInt() == 0) {
8742                     return null;
8743                 }
8744 
8745                 return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
8746             }
8747 
8748             /**
8749              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
8750              * proper timer pool from the given BatteryStatsImpl object.
8751              *
8752              * @param in the Parcel to be read from.
8753              * return a new Timer, or null.
8754              */
readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, TimeBase bgTimeBase, Parcel in)8755             private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
8756                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
8757                 if (in.readInt() == 0) {
8758                     return null;
8759                 }
8760 
8761                 return new DualTimer(mBsi.mClocks, mUid, type, pool, timeBase, bgTimeBase, in);
8762             }
8763 
reset()8764             boolean reset() {
8765                 boolean wlactive = false;
8766 
8767                 wlactive |= !resetIfNotNull(mTimerFull,false);
8768                 wlactive |= !resetIfNotNull(mTimerPartial,false);
8769                 wlactive |= !resetIfNotNull(mTimerWindow,false);
8770                 wlactive |= !resetIfNotNull(mTimerDraw,false);
8771 
8772                 if (!wlactive) {
8773                     detachIfNotNull(mTimerFull);
8774                     mTimerFull = null;
8775 
8776                     detachIfNotNull(mTimerPartial);
8777                     mTimerPartial = null;
8778 
8779                     detachIfNotNull(mTimerWindow);
8780                     mTimerWindow = null;
8781 
8782                     detachIfNotNull(mTimerDraw);
8783                     mTimerDraw = null;
8784                 }
8785                 return !wlactive;
8786             }
8787 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, TimeBase screenOffBgTimeBase, Parcel in)8788             void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase,
8789                     TimeBase screenOffBgTimeBase, Parcel in) {
8790                 mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL,
8791                         mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in);
8792                 mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
8793                         mBsi.mFullTimers, timeBase, in);
8794                 mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
8795                         mBsi.mWindowTimers, timeBase, in);
8796                 mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
8797                         mBsi.mDrawTimers, timeBase, in);
8798             }
8799 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)8800             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
8801                 Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
8802                 Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
8803                 Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
8804                 Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
8805             }
8806 
8807             @Override
8808             @UnsupportedAppUsage
getWakeTime(int type)8809             public Timer getWakeTime(int type) {
8810                 switch (type) {
8811                 case WAKE_TYPE_FULL: return mTimerFull;
8812                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
8813                 case WAKE_TYPE_WINDOW: return mTimerWindow;
8814                 case WAKE_TYPE_DRAW: return mTimerDraw;
8815                 default: throw new IllegalArgumentException("type = " + type);
8816                 }
8817             }
8818 
detachFromTimeBase()8819             public void detachFromTimeBase() {
8820                 detachIfNotNull(mTimerPartial);
8821                 detachIfNotNull(mTimerFull);
8822                 detachIfNotNull(mTimerWindow);
8823                 detachIfNotNull(mTimerDraw);
8824             }
8825         }
8826 
8827         public static class Sensor extends BatteryStats.Uid.Sensor {
8828             /**
8829              * BatteryStatsImpl that we are associated with.
8830              */
8831             protected BatteryStatsImpl mBsi;
8832 
8833             /**
8834              * Uid that we are associated with.
8835              */
8836             protected Uid mUid;
8837 
8838             final int mHandle;
8839             DualTimer mTimer;
8840 
Sensor(BatteryStatsImpl bsi, Uid uid, int handle)8841             public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
8842                 mBsi = bsi;
8843                 mUid = uid;
8844                 mHandle = handle;
8845             }
8846 
readTimersFromParcel( TimeBase timeBase, TimeBase bgTimeBase, Parcel in)8847             private DualTimer readTimersFromParcel(
8848                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
8849                 if (in.readInt() == 0) {
8850                     return null;
8851                 }
8852 
8853                 ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
8854                 if (pool == null) {
8855                     pool = new ArrayList<StopwatchTimer>();
8856                     mBsi.mSensorTimers.put(mHandle, pool);
8857                 }
8858                 return new DualTimer(mBsi.mClocks, mUid, 0, pool, timeBase, bgTimeBase, in);
8859             }
8860 
reset()8861             boolean reset() {
8862                 if (mTimer.reset(true)) {
8863                     mTimer = null;
8864                     return true;
8865                 }
8866                 return false;
8867             }
8868 
readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in)8869             void readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
8870                 mTimer = readTimersFromParcel(timeBase, bgTimeBase, in);
8871             }
8872 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)8873             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
8874                 Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
8875             }
8876 
8877             @Override
8878             @UnsupportedAppUsage
getSensorTime()8879             public Timer getSensorTime() {
8880                 return mTimer;
8881             }
8882 
8883             @Override
getSensorBackgroundTime()8884             public Timer getSensorBackgroundTime() {
8885                 if (mTimer == null) {
8886                     return null;
8887                 }
8888                 return mTimer.getSubTimer();
8889             }
8890 
8891             @Override
8892             @UnsupportedAppUsage
getHandle()8893             public int getHandle() {
8894                 return mHandle;
8895             }
8896 
detachFromTimeBase()8897             public void  detachFromTimeBase() {
8898                 detachIfNotNull(mTimer);
8899             }
8900         }
8901 
8902         /**
8903          * The statistics associated with a particular process.
8904          */
8905         public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
8906             /**
8907              * BatteryStatsImpl that we are associated with.
8908              */
8909             protected BatteryStatsImpl mBsi;
8910 
8911             /**
8912              * The name of this process.
8913              */
8914             final String mName;
8915 
8916             /**
8917              * Remains true until removed from the stats.
8918              */
8919             boolean mActive = true;
8920 
8921             /**
8922              * Total time (in ms) spent executing in user code.
8923              */
8924             long mUserTime;
8925 
8926             /**
8927              * Total time (in ms) spent executing in kernel code.
8928              */
8929             long mSystemTime;
8930 
8931             /**
8932              * Amount of time (in ms) the process was running in the foreground.
8933              */
8934             long mForegroundTime;
8935 
8936             /**
8937              * Number of times the process has been started.
8938              */
8939             int mStarts;
8940 
8941             /**
8942              * Number of times the process has crashed.
8943              */
8944             int mNumCrashes;
8945 
8946             /**
8947              * Number of times the process has had an ANR.
8948              */
8949             int mNumAnrs;
8950 
8951             ArrayList<ExcessivePower> mExcessivePower;
8952 
Proc(BatteryStatsImpl bsi, String name)8953             public Proc(BatteryStatsImpl bsi, String name) {
8954                 mBsi = bsi;
8955                 mName = name;
8956                 mBsi.mOnBatteryTimeBase.add(this);
8957             }
8958 
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)8959             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
8960             }
8961 
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)8962             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
8963             }
8964 
8965             @Override
reset(boolean detachIfReset)8966             public boolean reset(boolean detachIfReset) {
8967                 if (detachIfReset) {
8968                     this.detach();
8969                 }
8970                 return true;
8971             }
8972 
8973             @Override
detach()8974             public void detach() {
8975                 mActive = false;
8976                 mBsi.mOnBatteryTimeBase.remove(this);
8977             }
8978 
countExcessivePowers()8979             public int countExcessivePowers() {
8980                 return mExcessivePower != null ? mExcessivePower.size() : 0;
8981             }
8982 
getExcessivePower(int i)8983             public ExcessivePower getExcessivePower(int i) {
8984                 if (mExcessivePower != null) {
8985                     return mExcessivePower.get(i);
8986                 }
8987                 return null;
8988             }
8989 
addExcessiveCpu(long overTime, long usedTime)8990             public void addExcessiveCpu(long overTime, long usedTime) {
8991                 if (mExcessivePower == null) {
8992                     mExcessivePower = new ArrayList<ExcessivePower>();
8993                 }
8994                 ExcessivePower ew = new ExcessivePower();
8995                 ew.type = ExcessivePower.TYPE_CPU;
8996                 ew.overTime = overTime;
8997                 ew.usedTime = usedTime;
8998                 mExcessivePower.add(ew);
8999             }
9000 
writeExcessivePowerToParcelLocked(Parcel out)9001             void writeExcessivePowerToParcelLocked(Parcel out) {
9002                 if (mExcessivePower == null) {
9003                     out.writeInt(0);
9004                     return;
9005                 }
9006 
9007                 final int N = mExcessivePower.size();
9008                 out.writeInt(N);
9009                 for (int i=0; i<N; i++) {
9010                     ExcessivePower ew = mExcessivePower.get(i);
9011                     out.writeInt(ew.type);
9012                     out.writeLong(ew.overTime);
9013                     out.writeLong(ew.usedTime);
9014                 }
9015             }
9016 
readExcessivePowerFromParcelLocked(Parcel in)9017             void readExcessivePowerFromParcelLocked(Parcel in) {
9018                 final int N = in.readInt();
9019                 if (N == 0) {
9020                     mExcessivePower = null;
9021                     return;
9022                 }
9023 
9024                 if (N > 10000) {
9025                     throw new ParcelFormatException(
9026                             "File corrupt: too many excessive power entries " + N);
9027                 }
9028 
9029                 mExcessivePower = new ArrayList<>();
9030                 for (int i=0; i<N; i++) {
9031                     ExcessivePower ew = new ExcessivePower();
9032                     ew.type = in.readInt();
9033                     ew.overTime = in.readLong();
9034                     ew.usedTime = in.readLong();
9035                     mExcessivePower.add(ew);
9036                 }
9037             }
9038 
writeToParcelLocked(Parcel out)9039             void writeToParcelLocked(Parcel out) {
9040                 out.writeLong(mUserTime);
9041                 out.writeLong(mSystemTime);
9042                 out.writeLong(mForegroundTime);
9043                 out.writeInt(mStarts);
9044                 out.writeInt(mNumCrashes);
9045                 out.writeInt(mNumAnrs);
9046                 writeExcessivePowerToParcelLocked(out);
9047             }
9048 
readFromParcelLocked(Parcel in)9049             void readFromParcelLocked(Parcel in) {
9050                 mUserTime = in.readLong();
9051                 mSystemTime = in.readLong();
9052                 mForegroundTime = in.readLong();
9053                 mStarts = in.readInt();
9054                 mNumCrashes = in.readInt();
9055                 mNumAnrs = in.readInt();
9056                 readExcessivePowerFromParcelLocked(in);
9057             }
9058 
9059             @UnsupportedAppUsage
addCpuTimeLocked(int utime, int stime)9060             public void addCpuTimeLocked(int utime, int stime) {
9061                 addCpuTimeLocked(utime, stime, mBsi.mOnBatteryTimeBase.isRunning());
9062             }
9063 
addCpuTimeLocked(int utime, int stime, boolean isRunning)9064             public void addCpuTimeLocked(int utime, int stime, boolean isRunning) {
9065                 if (isRunning) {
9066                     mUserTime += utime;
9067                     mSystemTime += stime;
9068                 }
9069             }
9070 
9071             @UnsupportedAppUsage
addForegroundTimeLocked(long ttime)9072             public void addForegroundTimeLocked(long ttime) {
9073                 mForegroundTime += ttime;
9074             }
9075 
9076             @UnsupportedAppUsage
incStartsLocked()9077             public void incStartsLocked() {
9078                 mStarts++;
9079             }
9080 
incNumCrashesLocked()9081             public void incNumCrashesLocked() {
9082                 mNumCrashes++;
9083             }
9084 
incNumAnrsLocked()9085             public void incNumAnrsLocked() {
9086                 mNumAnrs++;
9087             }
9088 
9089             @Override
isActive()9090             public boolean isActive() {
9091                 return mActive;
9092             }
9093 
9094             @Override
9095             @UnsupportedAppUsage
getUserTime(int which)9096             public long getUserTime(int which) {
9097                 return mUserTime;
9098             }
9099 
9100             @Override
9101             @UnsupportedAppUsage
getSystemTime(int which)9102             public long getSystemTime(int which) {
9103                 return mSystemTime;
9104             }
9105 
9106             @Override
9107             @UnsupportedAppUsage
getForegroundTime(int which)9108             public long getForegroundTime(int which) {
9109                 return mForegroundTime;
9110             }
9111 
9112             @Override
9113             @UnsupportedAppUsage
getStarts(int which)9114             public int getStarts(int which) {
9115                 return mStarts;
9116             }
9117 
9118             @Override
getNumCrashes(int which)9119             public int getNumCrashes(int which) {
9120                 return mNumCrashes;
9121             }
9122 
9123             @Override
getNumAnrs(int which)9124             public int getNumAnrs(int which) {
9125                 return mNumAnrs;
9126             }
9127         }
9128 
9129         /**
9130          * The statistics associated with a particular package.
9131          */
9132         public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
9133             /**
9134              * BatteryStatsImpl that we are associated with.
9135              */
9136             protected BatteryStatsImpl mBsi;
9137 
9138             /**
9139              * Number of times wakeup alarms have occurred for this app.
9140              * On screen-off timebase starting in report v25.
9141              */
9142             ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
9143 
9144             /**
9145              * The statics we have collected for this package's services.
9146              */
9147             final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
9148 
Pkg(BatteryStatsImpl bsi)9149             public Pkg(BatteryStatsImpl bsi) {
9150                 mBsi = bsi;
9151                 mBsi.mOnBatteryScreenOffTimeBase.add(this);
9152             }
9153 
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)9154             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
9155             }
9156 
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)9157             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
9158             }
9159 
9160             @Override
reset(boolean detachIfReset)9161             public boolean reset(boolean detachIfReset) {
9162                 if (detachIfReset) {
9163                     this.detach();
9164                 }
9165                 return true;
9166             }
9167 
9168             @Override
detach()9169             public void detach() {
9170                 mBsi.mOnBatteryScreenOffTimeBase.remove(this);
9171                 for (int j = mWakeupAlarms.size() - 1; j >= 0; j--) {
9172                     detachIfNotNull(mWakeupAlarms.valueAt(j));
9173                 }
9174                 for (int j = mServiceStats.size() - 1; j >= 0; j--) {
9175                     detachIfNotNull(mServiceStats.valueAt(j));
9176                 }
9177             }
9178 
readFromParcelLocked(Parcel in)9179             void readFromParcelLocked(Parcel in) {
9180                 int numWA = in.readInt();
9181                 mWakeupAlarms.clear();
9182                 for (int i=0; i<numWA; i++) {
9183                     String tag = in.readString();
9184                     mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryScreenOffTimeBase, in));
9185                 }
9186 
9187                 int numServs = in.readInt();
9188                 mServiceStats.clear();
9189                 for (int m = 0; m < numServs; m++) {
9190                     String serviceName = in.readString();
9191                     Uid.Pkg.Serv serv = new Serv(mBsi);
9192                     mServiceStats.put(serviceName, serv);
9193 
9194                     serv.readFromParcelLocked(in);
9195                 }
9196             }
9197 
writeToParcelLocked(Parcel out)9198             void writeToParcelLocked(Parcel out) {
9199                 int numWA = mWakeupAlarms.size();
9200                 out.writeInt(numWA);
9201                 for (int i=0; i<numWA; i++) {
9202                     out.writeString(mWakeupAlarms.keyAt(i));
9203                     mWakeupAlarms.valueAt(i).writeToParcel(out);
9204                 }
9205 
9206                 final int NS = mServiceStats.size();
9207                 out.writeInt(NS);
9208                 for (int i=0; i<NS; i++) {
9209                     out.writeString(mServiceStats.keyAt(i));
9210                     Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
9211                     serv.writeToParcelLocked(out);
9212                 }
9213             }
9214 
9215             @Override
getWakeupAlarmStats()9216             public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
9217                 return mWakeupAlarms;
9218             }
9219 
noteWakeupAlarmLocked(String tag)9220             public void noteWakeupAlarmLocked(String tag) {
9221                 Counter c = mWakeupAlarms.get(tag);
9222                 if (c == null) {
9223                     c = new Counter(mBsi.mOnBatteryScreenOffTimeBase);
9224                     mWakeupAlarms.put(tag, c);
9225                 }
9226                 c.stepAtomic();
9227             }
9228 
9229             @Override
getServiceStats()9230             public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
9231                 return mServiceStats;
9232             }
9233 
9234             /**
9235              * The statistics associated with a particular service.
9236              */
9237             public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
9238                 /**
9239                  * BatteryStatsImpl that we are associated with.
9240                  */
9241                 protected BatteryStatsImpl mBsi;
9242 
9243                 /**
9244                  * The android package in which this service resides.
9245                  */
9246                 protected Pkg mPkg;
9247 
9248                 /**
9249                  * Total time (ms in battery uptime) the service has been left started.
9250                  */
9251                 protected long mStartTime;
9252 
9253                 /**
9254                  * If service has been started and not yet stopped, this is
9255                  * when it was started.
9256                  */
9257                 protected long mRunningSince;
9258 
9259                 /**
9260                  * True if we are currently running.
9261                  */
9262                 protected boolean mRunning;
9263 
9264                 /**
9265                  * Total number of times startService() has been called.
9266                  */
9267                 protected int mStarts;
9268 
9269                 /**
9270                  * Total time (ms in battery uptime) the service has been left launched.
9271                  */
9272                 protected long mLaunchedTime;
9273 
9274                 /**
9275                  * If service has been launched and not yet exited, this is
9276                  * when it was launched (ms in battery uptime).
9277                  */
9278                 protected long mLaunchedSince;
9279 
9280                 /**
9281                  * True if we are currently launched.
9282                  */
9283                 protected boolean mLaunched;
9284 
9285                 /**
9286                  * Total number times the service has been launched.
9287                  */
9288                 protected int mLaunches;
9289 
9290                 /**
9291                  * Construct a Serv. Also adds it to the on-battery time base as a listener.
9292                  */
Serv(BatteryStatsImpl bsi)9293                 public Serv(BatteryStatsImpl bsi) {
9294                     mBsi = bsi;
9295                     mBsi.mOnBatteryTimeBase.add(this);
9296                 }
9297 
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)9298                 public void onTimeStarted(long elapsedRealtime, long baseUptime,
9299                         long baseRealtime) {
9300                 }
9301 
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)9302                 public void onTimeStopped(long elapsedRealtime, long baseUptime,
9303                         long baseRealtime) {
9304                 }
9305 
9306                 @Override
reset(boolean detachIfReset)9307                 public boolean reset(boolean detachIfReset) {
9308                     if (detachIfReset) {
9309                         this.detach();
9310                     }
9311                     return true;
9312                 }
9313 
9314                 /**
9315                  * Remove this Serv as a listener from the time base.
9316                  */
9317                 @Override
detach()9318                 public void detach() {
9319                     mBsi.mOnBatteryTimeBase.remove(this);
9320                 }
9321 
readFromParcelLocked(Parcel in)9322                 public void readFromParcelLocked(Parcel in) {
9323                     mStartTime = in.readLong();
9324                     mRunningSince = in.readLong();
9325                     mRunning = in.readInt() != 0;
9326                     mStarts = in.readInt();
9327                     mLaunchedTime = in.readLong();
9328                     mLaunchedSince = in.readLong();
9329                     mLaunched = in.readInt() != 0;
9330                     mLaunches = in.readInt();
9331                 }
9332 
writeToParcelLocked(Parcel out)9333                 public void writeToParcelLocked(Parcel out) {
9334                     out.writeLong(mStartTime);
9335                     out.writeLong(mRunningSince);
9336                     out.writeInt(mRunning ? 1 : 0);
9337                     out.writeInt(mStarts);
9338                     out.writeLong(mLaunchedTime);
9339                     out.writeLong(mLaunchedSince);
9340                     out.writeInt(mLaunched ? 1 : 0);
9341                     out.writeInt(mLaunches);
9342                 }
9343 
getLaunchTimeToNowLocked(long batteryUptime)9344                 public long getLaunchTimeToNowLocked(long batteryUptime) {
9345                     if (!mLaunched) return mLaunchedTime;
9346                     return mLaunchedTime + batteryUptime - mLaunchedSince;
9347                 }
9348 
getStartTimeToNowLocked(long batteryUptime)9349                 public long getStartTimeToNowLocked(long batteryUptime) {
9350                     if (!mRunning) return mStartTime;
9351                     return mStartTime + batteryUptime - mRunningSince;
9352                 }
9353 
9354                 @UnsupportedAppUsage
startLaunchedLocked()9355                 public void startLaunchedLocked() {
9356                     if (!mLaunched) {
9357                         mLaunches++;
9358                         mLaunchedSince = mBsi.getBatteryUptimeLocked();
9359                         mLaunched = true;
9360                     }
9361                 }
9362 
9363                 @UnsupportedAppUsage
stopLaunchedLocked()9364                 public void stopLaunchedLocked() {
9365                     if (mLaunched) {
9366                         long time = mBsi.getBatteryUptimeLocked() - mLaunchedSince;
9367                         if (time > 0) {
9368                             mLaunchedTime += time;
9369                         } else {
9370                             mLaunches--;
9371                         }
9372                         mLaunched = false;
9373                     }
9374                 }
9375 
9376                 @UnsupportedAppUsage
startRunningLocked()9377                 public void startRunningLocked() {
9378                     if (!mRunning) {
9379                         mStarts++;
9380                         mRunningSince = mBsi.getBatteryUptimeLocked();
9381                         mRunning = true;
9382                     }
9383                 }
9384 
9385                 @UnsupportedAppUsage
stopRunningLocked()9386                 public void stopRunningLocked() {
9387                     if (mRunning) {
9388                         long time = mBsi.getBatteryUptimeLocked() - mRunningSince;
9389                         if (time > 0) {
9390                             mStartTime += time;
9391                         } else {
9392                             mStarts--;
9393                         }
9394                         mRunning = false;
9395                     }
9396                 }
9397 
9398                 @UnsupportedAppUsage
getBatteryStats()9399                 public BatteryStatsImpl getBatteryStats() {
9400                     return mBsi;
9401                 }
9402 
9403                 @Override
getLaunches(int which)9404                 public int getLaunches(int which) {
9405                     return mLaunches;
9406                 }
9407 
9408                 @Override
getStartTime(long now, int which)9409                 public long getStartTime(long now, int which) {
9410                     return getStartTimeToNowLocked(now);
9411                 }
9412 
9413                 @Override
getStarts(int which)9414                 public int getStarts(int which) {
9415                     return mStarts;
9416                 }
9417             }
9418 
newServiceStatsLocked()9419             final Serv newServiceStatsLocked() {
9420                 return new Serv(mBsi);
9421             }
9422         }
9423 
9424         /**
9425          * Retrieve the statistics object for a particular process, creating
9426          * if needed.
9427          */
getProcessStatsLocked(String name)9428         public Proc getProcessStatsLocked(String name) {
9429             Proc ps = mProcessStats.get(name);
9430             if (ps == null) {
9431                 ps = new Proc(mBsi, name);
9432                 mProcessStats.put(name, ps);
9433             }
9434 
9435             return ps;
9436         }
9437 
9438         @GuardedBy("mBsi")
updateUidProcessStateLocked(int procState)9439         public void updateUidProcessStateLocked(int procState) {
9440             int uidRunningState;
9441             // Make special note of Foreground Services
9442             final boolean userAwareService =
9443                     (ActivityManager.isForegroundService(procState));
9444             uidRunningState = BatteryStats.mapToInternalProcessState(procState);
9445 
9446             if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
9447                 return;
9448             }
9449 
9450             final long elapsedRealtimeMs = mBsi.mClocks.elapsedRealtime();
9451             if (mProcessState != uidRunningState) {
9452                 final long uptimeMs = mBsi.mClocks.uptimeMillis();
9453 
9454                 if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
9455                     mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
9456 
9457                     if (mBsi.trackPerProcStateCpuTimes()) {
9458                         if (mBsi.mPendingUids.size() == 0) {
9459                             mBsi.mExternalSync.scheduleReadProcStateCpuTimes(
9460                                     mBsi.mOnBatteryTimeBase.isRunning(),
9461                                     mBsi.mOnBatteryScreenOffTimeBase.isRunning(),
9462                                     mBsi.mConstants.PROC_STATE_CPU_TIMES_READ_DELAY_MS);
9463                             mBsi.mNumSingleUidCpuTimeReads++;
9464                         } else {
9465                             mBsi.mNumBatchedSingleUidCpuTimeReads++;
9466                         }
9467                         if (mBsi.mPendingUids.indexOfKey(mUid) < 0
9468                                 || ArrayUtils.contains(CRITICAL_PROC_STATES, mProcessState)) {
9469                             mBsi.mPendingUids.put(mUid, mProcessState);
9470                         }
9471                     } else {
9472                         mBsi.mPendingUids.clear();
9473                     }
9474                 }
9475                 mProcessState = uidRunningState;
9476                 if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
9477                     if (mProcessStateTimer[uidRunningState] == null) {
9478                         makeProcessState(uidRunningState, null);
9479                     }
9480                     mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
9481                 }
9482 
9483                 updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
9484                 updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
9485             }
9486 
9487             if (userAwareService != mInForegroundService) {
9488                 if (userAwareService) {
9489                     noteForegroundServiceResumedLocked(elapsedRealtimeMs);
9490                 } else {
9491                     noteForegroundServicePausedLocked(elapsedRealtimeMs);
9492                 }
9493                 mInForegroundService = userAwareService;
9494             }
9495         }
9496 
9497         /** Whether to consider Uid to be in the background for background timebase purposes. */
isInBackground()9498         public boolean isInBackground() {
9499             // Note that PROCESS_STATE_CACHED and ActivityManager.PROCESS_STATE_NONEXISTENT is
9500             // also considered to be 'background' for our purposes, because it's not foreground.
9501             return mProcessState >= PROCESS_STATE_BACKGROUND;
9502         }
9503 
updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs)9504         public boolean updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs) {
9505             boolean on = mBsi.mOnBatteryTimeBase.isRunning() && isInBackground();
9506             return mOnBatteryBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
9507         }
9508 
updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs)9509         public boolean updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs) {
9510             boolean on = mBsi.mOnBatteryScreenOffTimeBase.isRunning() && isInBackground();
9511             return mOnBatteryScreenOffBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
9512         }
9513 
getPidStats()9514         public SparseArray<? extends Pid> getPidStats() {
9515             return mPids;
9516         }
9517 
getPidStatsLocked(int pid)9518         public Pid getPidStatsLocked(int pid) {
9519             Pid p = mPids.get(pid);
9520             if (p == null) {
9521                 p = new Pid();
9522                 mPids.put(pid, p);
9523             }
9524             return p;
9525         }
9526 
9527         /**
9528          * Retrieve the statistics object for a particular service, creating
9529          * if needed.
9530          */
getPackageStatsLocked(String name)9531         public Pkg getPackageStatsLocked(String name) {
9532             Pkg ps = mPackageStats.get(name);
9533             if (ps == null) {
9534                 ps = new Pkg(mBsi);
9535                 mPackageStats.put(name, ps);
9536             }
9537 
9538             return ps;
9539         }
9540 
9541         /**
9542          * Retrieve the statistics object for a particular service, creating
9543          * if needed.
9544          */
getServiceStatsLocked(String pkg, String serv)9545         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
9546             Pkg ps = getPackageStatsLocked(pkg);
9547             Pkg.Serv ss = ps.mServiceStats.get(serv);
9548             if (ss == null) {
9549                 ss = ps.newServiceStatsLocked();
9550                 ps.mServiceStats.put(serv, ss);
9551             }
9552 
9553             return ss;
9554         }
9555 
readSyncSummaryFromParcelLocked(String name, Parcel in)9556         public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
9557             DualTimer timer = mSyncStats.instantiateObject();
9558             timer.readSummaryFromParcelLocked(in);
9559             mSyncStats.add(name, timer);
9560         }
9561 
readJobSummaryFromParcelLocked(String name, Parcel in)9562         public void readJobSummaryFromParcelLocked(String name, Parcel in) {
9563             DualTimer timer = mJobStats.instantiateObject();
9564             timer.readSummaryFromParcelLocked(in);
9565             mJobStats.add(name, timer);
9566         }
9567 
readWakeSummaryFromParcelLocked(String wlName, Parcel in)9568         public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
9569             Wakelock wl = new Wakelock(mBsi, this);
9570             mWakelockStats.add(wlName, wl);
9571             if (in.readInt() != 0) {
9572                 getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
9573             }
9574             if (in.readInt() != 0) {
9575                 getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
9576             }
9577             if (in.readInt() != 0) {
9578                 getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
9579             }
9580             if (in.readInt() != 0) {
9581                 getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
9582             }
9583         }
9584 
getSensorTimerLocked(int sensor, boolean create)9585         public DualTimer getSensorTimerLocked(int sensor, boolean create) {
9586             Sensor se = mSensorStats.get(sensor);
9587             if (se == null) {
9588                 if (!create) {
9589                     return null;
9590                 }
9591                 se = new Sensor(mBsi, this, sensor);
9592                 mSensorStats.put(sensor, se);
9593             }
9594             DualTimer t = se.mTimer;
9595             if (t != null) {
9596                 return t;
9597             }
9598             ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
9599             if (timers == null) {
9600                 timers = new ArrayList<StopwatchTimer>();
9601                 mBsi.mSensorTimers.put(sensor, timers);
9602             }
9603             t = new DualTimer(mBsi.mClocks, this, BatteryStats.SENSOR, timers,
9604                     mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
9605             se.mTimer = t;
9606             return t;
9607         }
9608 
noteStartSyncLocked(String name, long elapsedRealtimeMs)9609         public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
9610             DualTimer t = mSyncStats.startObject(name);
9611             if (t != null) {
9612                 t.startRunningLocked(elapsedRealtimeMs);
9613             }
9614         }
9615 
noteStopSyncLocked(String name, long elapsedRealtimeMs)9616         public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
9617             DualTimer t = mSyncStats.stopObject(name);
9618             if (t != null) {
9619                 t.stopRunningLocked(elapsedRealtimeMs);
9620             }
9621         }
9622 
noteStartJobLocked(String name, long elapsedRealtimeMs)9623         public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
9624             DualTimer t = mJobStats.startObject(name);
9625             if (t != null) {
9626                 t.startRunningLocked(elapsedRealtimeMs);
9627             }
9628         }
9629 
noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason)9630         public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
9631             DualTimer t = mJobStats.stopObject(name);
9632             if (t != null) {
9633                 t.stopRunningLocked(elapsedRealtimeMs);
9634             }
9635             if (mBsi.mOnBatteryTimeBase.isRunning()) {
9636                 SparseIntArray types = mJobCompletions.get(name);
9637                 if (types == null) {
9638                     types = new SparseIntArray();
9639                     mJobCompletions.put(name, types);
9640                 }
9641                 int last = types.get(stopReason, 0);
9642                 types.put(stopReason, last + 1);
9643             }
9644         }
9645 
getWakelockTimerLocked(Wakelock wl, int type)9646         public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
9647             if (wl == null) {
9648                 return null;
9649             }
9650             switch (type) {
9651                 case WAKE_TYPE_PARTIAL: {
9652                     DualTimer t = wl.mTimerPartial;
9653                     if (t == null) {
9654                         t = new DualTimer(mBsi.mClocks, this, WAKE_TYPE_PARTIAL,
9655                                 mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase,
9656                                 mOnBatteryScreenOffBackgroundTimeBase);
9657                         wl.mTimerPartial = t;
9658                     }
9659                     return t;
9660                 }
9661                 case WAKE_TYPE_FULL: {
9662                     StopwatchTimer t = wl.mTimerFull;
9663                     if (t == null) {
9664                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_FULL,
9665                                 mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
9666                         wl.mTimerFull = t;
9667                     }
9668                     return t;
9669                 }
9670                 case WAKE_TYPE_WINDOW: {
9671                     StopwatchTimer t = wl.mTimerWindow;
9672                     if (t == null) {
9673                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_WINDOW,
9674                                 mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
9675                         wl.mTimerWindow = t;
9676                     }
9677                     return t;
9678                 }
9679                 case WAKE_TYPE_DRAW: {
9680                     StopwatchTimer t = wl.mTimerDraw;
9681                     if (t == null) {
9682                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_DRAW,
9683                                 mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
9684                         wl.mTimerDraw = t;
9685                     }
9686                     return t;
9687                 }
9688                 default:
9689                     throw new IllegalArgumentException("type=" + type);
9690             }
9691         }
9692 
noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)9693         public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
9694             Wakelock wl = mWakelockStats.startObject(name);
9695             if (wl != null) {
9696                 getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
9697             }
9698             if (type == WAKE_TYPE_PARTIAL) {
9699                 createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
9700                 if (pid >= 0) {
9701                     Pid p = getPidStatsLocked(pid);
9702                     if (p.mWakeNesting++ == 0) {
9703                         p.mWakeStartMs = elapsedRealtimeMs;
9704                     }
9705                 }
9706             }
9707         }
9708 
noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)9709         public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
9710             Wakelock wl = mWakelockStats.stopObject(name);
9711             if (wl != null) {
9712                 StopwatchTimer wlt = getWakelockTimerLocked(wl, type);
9713                 wlt.stopRunningLocked(elapsedRealtimeMs);
9714             }
9715             if (type == WAKE_TYPE_PARTIAL) {
9716                 if (mAggregatedPartialWakelockTimer != null) {
9717                     mAggregatedPartialWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
9718                 }
9719                 if (pid >= 0) {
9720                     Pid p = mPids.get(pid);
9721                     if (p != null && p.mWakeNesting > 0) {
9722                         if (p.mWakeNesting-- == 1) {
9723                             p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
9724                             p.mWakeStartMs = 0;
9725                         }
9726                     }
9727                 }
9728             }
9729         }
9730 
reportExcessiveCpuLocked(String proc, long overTime, long usedTime)9731         public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
9732             Proc p = getProcessStatsLocked(proc);
9733             if (p != null) {
9734                 p.addExcessiveCpu(overTime, usedTime);
9735             }
9736         }
9737 
noteStartSensor(int sensor, long elapsedRealtimeMs)9738         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
9739             DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
9740             t.startRunningLocked(elapsedRealtimeMs);
9741         }
9742 
noteStopSensor(int sensor, long elapsedRealtimeMs)9743         public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
9744             // Don't create a timer if one doesn't already exist
9745             DualTimer t = getSensorTimerLocked(sensor, false);
9746             if (t != null) {
9747                 t.stopRunningLocked(elapsedRealtimeMs);
9748             }
9749         }
9750 
noteStartGps(long elapsedRealtimeMs)9751         public void noteStartGps(long elapsedRealtimeMs) {
9752             noteStartSensor(Sensor.GPS, elapsedRealtimeMs);
9753         }
9754 
noteStopGps(long elapsedRealtimeMs)9755         public void noteStopGps(long elapsedRealtimeMs) {
9756             noteStopSensor(Sensor.GPS, elapsedRealtimeMs);
9757         }
9758 
getBatteryStats()9759         public BatteryStatsImpl getBatteryStats() {
9760             return mBsi;
9761         }
9762     }
9763 
getCpuFreqs()9764     public long[] getCpuFreqs() {
9765         return mCpuFreqs;
9766     }
9767 
BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb, RailEnergyDataCallback railStatsCb, UserInfoProvider userInfoProvider)9768     public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
9769             RailEnergyDataCallback railStatsCb, UserInfoProvider userInfoProvider) {
9770         this(new SystemClocks(), systemDir, handler, cb, railStatsCb, userInfoProvider);
9771     }
9772 
BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler, PlatformIdleStateCallback cb, RailEnergyDataCallback railStatsCb, UserInfoProvider userInfoProvider)9773     private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
9774             PlatformIdleStateCallback cb, RailEnergyDataCallback railStatsCb,
9775             UserInfoProvider userInfoProvider) {
9776         init(clocks);
9777 
9778 
9779         if (systemDir == null) {
9780             mStatsFile = null;
9781             mBatteryStatsHistory = new BatteryStatsHistory(this, mHistoryBuffer);
9782         } else {
9783             mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
9784             mBatteryStatsHistory = new BatteryStatsHistory(this, systemDir, mHistoryBuffer);
9785         }
9786         mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
9787         mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
9788         mHandler = new MyHandler(handler.getLooper());
9789         mConstants = new Constants(mHandler);
9790         mStartCount++;
9791         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
9792         mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
9793         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
9794             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
9795                     mOnBatteryTimeBase);
9796         }
9797         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase);
9798         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
9799                 mOnBatteryTimeBase);
9800         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -11, null,
9801                 mOnBatteryTimeBase);
9802         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
9803         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null, mOnBatteryTimeBase);
9804         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase);
9805         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase);
9806         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
9807             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i, null,
9808                     mOnBatteryTimeBase);
9809         }
9810         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
9811                 mOnBatteryTimeBase);
9812         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
9813             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i, null,
9814                     mOnBatteryTimeBase);
9815         }
9816         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9817             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
9818             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
9819         }
9820         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
9821         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
9822                 NUM_BT_TX_LEVELS);
9823         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
9824                 ModemActivityInfo.TX_POWER_LEVELS);
9825         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase);
9826         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
9827                 mOnBatteryTimeBase);
9828         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
9829         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
9830         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
9831         mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null,
9832                 WIFI_AGGREGATE_MULTICAST_ENABLED, null, mOnBatteryTimeBase);
9833         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase);
9834         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null, mOnBatteryTimeBase);
9835         for (int i=0; i<NUM_WIFI_STATES; i++) {
9836             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i, null,
9837                     mOnBatteryTimeBase);
9838         }
9839         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
9840             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i, null,
9841                     mOnBatteryTimeBase);
9842         }
9843         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
9844             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
9845                     mOnBatteryTimeBase);
9846         }
9847         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null, mOnBatteryTimeBase);
9848         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
9849             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i, null,
9850                 mOnBatteryTimeBase);
9851         }
9852         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
9853         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
9854         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
9855         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase);
9856         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
9857         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
9858         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
9859         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
9860         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
9861         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
9862         mOnBattery = mOnBatteryInternal = false;
9863         long uptime = mClocks.uptimeMillis() * 1000;
9864         long realtime = mClocks.elapsedRealtime() * 1000;
9865         initTimes(uptime, realtime);
9866         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
9867         mDischargeStartLevel = 0;
9868         mDischargeUnplugLevel = 0;
9869         mDischargePlugLevel = -1;
9870         mDischargeCurrentLevel = 0;
9871         mCurrentBatteryLevel = 0;
9872         initDischarge();
9873         clearHistoryLocked();
9874         updateDailyDeadlineLocked();
9875         mPlatformIdleStateCallback = cb;
9876         mRailEnergyDataCallback = railStatsCb;
9877         mUserInfoProvider = userInfoProvider;
9878 
9879         // Notify statsd that the system is initially not in doze.
9880         mDeviceIdleMode = DEVICE_IDLE_MODE_OFF;
9881         FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mDeviceIdleMode);
9882     }
9883 
9884     @UnsupportedAppUsage
BatteryStatsImpl(Parcel p)9885     public BatteryStatsImpl(Parcel p) {
9886         this(new SystemClocks(), p);
9887     }
9888 
BatteryStatsImpl(Clocks clocks, Parcel p)9889     public BatteryStatsImpl(Clocks clocks, Parcel p) {
9890         init(clocks);
9891         mStatsFile = null;
9892         mCheckinFile = null;
9893         mDailyFile = null;
9894         mHandler = null;
9895         mExternalSync = null;
9896         mConstants = new Constants(mHandler);
9897         clearHistoryLocked();
9898         mBatteryStatsHistory = new BatteryStatsHistory(this, mHistoryBuffer);
9899         readFromParcel(p);
9900         mPlatformIdleStateCallback = null;
9901         mRailEnergyDataCallback = null;
9902     }
9903 
setPowerProfileLocked(PowerProfile profile)9904     public void setPowerProfileLocked(PowerProfile profile) {
9905         mPowerProfile = profile;
9906 
9907         // We need to initialize the KernelCpuSpeedReaders to read from
9908         // the first cpu of each core. Once we have the PowerProfile, we have access to this
9909         // information.
9910         final int numClusters = mPowerProfile.getNumCpuClusters();
9911         mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
9912         int firstCpuOfCluster = 0;
9913         for (int i = 0; i < numClusters; i++) {
9914             final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
9915             mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
9916                     numSpeedSteps);
9917             firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
9918         }
9919 
9920         if (mEstimatedBatteryCapacity == -1) {
9921             // Initialize the estimated battery capacity to a known preset one.
9922             mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
9923         }
9924     }
9925 
setCallback(BatteryCallback cb)9926     public void setCallback(BatteryCallback cb) {
9927         mCallback = cb;
9928     }
9929 
setRadioScanningTimeoutLocked(long timeout)9930     public void setRadioScanningTimeoutLocked(long timeout) {
9931         if (mPhoneSignalScanningTimer != null) {
9932             mPhoneSignalScanningTimer.setTimeout(timeout);
9933         }
9934     }
9935 
setExternalStatsSyncLocked(ExternalStatsSync sync)9936     public void setExternalStatsSyncLocked(ExternalStatsSync sync) {
9937         mExternalSync = sync;
9938     }
9939 
updateDailyDeadlineLocked()9940     public void updateDailyDeadlineLocked() {
9941         // Get the current time.
9942         long currentTime = mDailyStartTime = System.currentTimeMillis();
9943         Calendar calDeadline = Calendar.getInstance();
9944         calDeadline.setTimeInMillis(currentTime);
9945 
9946         // Move time up to the next day, ranging from 1am to 3pm.
9947         calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
9948         calDeadline.set(Calendar.MILLISECOND, 0);
9949         calDeadline.set(Calendar.SECOND, 0);
9950         calDeadline.set(Calendar.MINUTE, 0);
9951         calDeadline.set(Calendar.HOUR_OF_DAY, 1);
9952         mNextMinDailyDeadline = calDeadline.getTimeInMillis();
9953         calDeadline.set(Calendar.HOUR_OF_DAY, 3);
9954         mNextMaxDailyDeadline = calDeadline.getTimeInMillis();
9955     }
9956 
recordDailyStatsIfNeededLocked(boolean settled)9957     public void recordDailyStatsIfNeededLocked(boolean settled) {
9958         long currentTime = System.currentTimeMillis();
9959         if (currentTime >= mNextMaxDailyDeadline) {
9960             recordDailyStatsLocked();
9961         } else if (settled && currentTime >= mNextMinDailyDeadline) {
9962             recordDailyStatsLocked();
9963         } else if (currentTime < (mDailyStartTime-(1000*60*60*24))) {
9964             recordDailyStatsLocked();
9965         }
9966     }
9967 
recordDailyStatsLocked()9968     public void recordDailyStatsLocked() {
9969         DailyItem item = new DailyItem();
9970         item.mStartTime = mDailyStartTime;
9971         item.mEndTime = System.currentTimeMillis();
9972         boolean hasData = false;
9973         if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
9974             hasData = true;
9975             item.mDischargeSteps = new LevelStepTracker(
9976                     mDailyDischargeStepTracker.mNumStepDurations,
9977                     mDailyDischargeStepTracker.mStepDurations);
9978         }
9979         if (mDailyChargeStepTracker.mNumStepDurations > 0) {
9980             hasData = true;
9981             item.mChargeSteps = new LevelStepTracker(
9982                     mDailyChargeStepTracker.mNumStepDurations,
9983                     mDailyChargeStepTracker.mStepDurations);
9984         }
9985         if (mDailyPackageChanges != null) {
9986             hasData = true;
9987             item.mPackageChanges = mDailyPackageChanges;
9988             mDailyPackageChanges = null;
9989         }
9990         mDailyDischargeStepTracker.init();
9991         mDailyChargeStepTracker.init();
9992         updateDailyDeadlineLocked();
9993 
9994         if (hasData) {
9995             final long startTime = SystemClock.uptimeMillis();
9996             mDailyItems.add(item);
9997             while (mDailyItems.size() > MAX_DAILY_ITEMS) {
9998                 mDailyItems.remove(0);
9999             }
10000             final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
10001             try {
10002                 XmlSerializer out = new FastXmlSerializer();
10003                 out.setOutput(memStream, StandardCharsets.UTF_8.name());
10004                 writeDailyItemsLocked(out);
10005                 final long initialTime = SystemClock.uptimeMillis() - startTime;
10006                 BackgroundThread.getHandler().post(new Runnable() {
10007                     @Override
10008                     public void run() {
10009                         synchronized (mCheckinFile) {
10010                             final long startTime2 = SystemClock.uptimeMillis();
10011                             FileOutputStream stream = null;
10012                             try {
10013                                 stream = mDailyFile.startWrite();
10014                                 memStream.writeTo(stream);
10015                                 stream.flush();
10016                                 mDailyFile.finishWrite(stream);
10017                                 com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
10018                                         "batterystats-daily",
10019                                         initialTime + SystemClock.uptimeMillis() - startTime2);
10020                             } catch (IOException e) {
10021                                 Slog.w("BatteryStats",
10022                                         "Error writing battery daily items", e);
10023                                 mDailyFile.failWrite(stream);
10024                             }
10025                         }
10026                     }
10027                 });
10028             } catch (IOException e) {
10029             }
10030         }
10031     }
10032 
writeDailyItemsLocked(XmlSerializer out)10033     private void writeDailyItemsLocked(XmlSerializer out) throws IOException {
10034         StringBuilder sb = new StringBuilder(64);
10035         out.startDocument(null, true);
10036         out.startTag(null, "daily-items");
10037         for (int i=0; i<mDailyItems.size(); i++) {
10038             final DailyItem dit = mDailyItems.get(i);
10039             out.startTag(null, "item");
10040             out.attribute(null, "start", Long.toString(dit.mStartTime));
10041             out.attribute(null, "end", Long.toString(dit.mEndTime));
10042             writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
10043             writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
10044             if (dit.mPackageChanges != null) {
10045                 for (int j=0; j<dit.mPackageChanges.size(); j++) {
10046                     PackageChange pc = dit.mPackageChanges.get(j);
10047                     if (pc.mUpdate) {
10048                         out.startTag(null, "upd");
10049                         out.attribute(null, "pkg", pc.mPackageName);
10050                         out.attribute(null, "ver", Long.toString(pc.mVersionCode));
10051                         out.endTag(null, "upd");
10052                     } else {
10053                         out.startTag(null, "rem");
10054                         out.attribute(null, "pkg", pc.mPackageName);
10055                         out.endTag(null, "rem");
10056                     }
10057                 }
10058             }
10059             out.endTag(null, "item");
10060         }
10061         out.endTag(null, "daily-items");
10062         out.endDocument();
10063     }
10064 
writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps, StringBuilder tmpBuilder)10065     private void writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps,
10066             StringBuilder tmpBuilder) throws IOException {
10067         if (steps != null) {
10068             out.startTag(null, tag);
10069             out.attribute(null, "n", Integer.toString(steps.mNumStepDurations));
10070             for (int i=0; i<steps.mNumStepDurations; i++) {
10071                 out.startTag(null, "s");
10072                 tmpBuilder.setLength(0);
10073                 steps.encodeEntryAt(i, tmpBuilder);
10074                 out.attribute(null, "v", tmpBuilder.toString());
10075                 out.endTag(null, "s");
10076             }
10077             out.endTag(null, tag);
10078         }
10079     }
10080 
readDailyStatsLocked()10081     public void readDailyStatsLocked() {
10082         Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
10083         mDailyItems.clear();
10084         FileInputStream stream;
10085         try {
10086             stream = mDailyFile.openRead();
10087         } catch (FileNotFoundException e) {
10088             return;
10089         }
10090         try {
10091             XmlPullParser parser = Xml.newPullParser();
10092             parser.setInput(stream, StandardCharsets.UTF_8.name());
10093             readDailyItemsLocked(parser);
10094         } catch (XmlPullParserException e) {
10095         } finally {
10096             try {
10097                 stream.close();
10098             } catch (IOException e) {
10099             }
10100         }
10101     }
10102 
readDailyItemsLocked(XmlPullParser parser)10103     private void readDailyItemsLocked(XmlPullParser parser) {
10104         try {
10105             int type;
10106             while ((type = parser.next()) != XmlPullParser.START_TAG
10107                     && type != XmlPullParser.END_DOCUMENT) {
10108                 ;
10109             }
10110 
10111             if (type != XmlPullParser.START_TAG) {
10112                 throw new IllegalStateException("no start tag found");
10113             }
10114 
10115             int outerDepth = parser.getDepth();
10116             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10117                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10118                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10119                     continue;
10120                 }
10121 
10122                 String tagName = parser.getName();
10123                 if (tagName.equals("item")) {
10124                     readDailyItemTagLocked(parser);
10125                 } else {
10126                     Slog.w(TAG, "Unknown element under <daily-items>: "
10127                             + parser.getName());
10128                     XmlUtils.skipCurrentTag(parser);
10129                 }
10130             }
10131 
10132         } catch (IllegalStateException e) {
10133             Slog.w(TAG, "Failed parsing daily " + e);
10134         } catch (NullPointerException e) {
10135             Slog.w(TAG, "Failed parsing daily " + e);
10136         } catch (NumberFormatException e) {
10137             Slog.w(TAG, "Failed parsing daily " + e);
10138         } catch (XmlPullParserException e) {
10139             Slog.w(TAG, "Failed parsing daily " + e);
10140         } catch (IOException e) {
10141             Slog.w(TAG, "Failed parsing daily " + e);
10142         } catch (IndexOutOfBoundsException e) {
10143             Slog.w(TAG, "Failed parsing daily " + e);
10144         }
10145     }
10146 
readDailyItemTagLocked(XmlPullParser parser)10147     void readDailyItemTagLocked(XmlPullParser parser) throws NumberFormatException,
10148             XmlPullParserException, IOException {
10149         DailyItem dit = new DailyItem();
10150         String attr = parser.getAttributeValue(null, "start");
10151         if (attr != null) {
10152             dit.mStartTime = Long.parseLong(attr);
10153         }
10154         attr = parser.getAttributeValue(null, "end");
10155         if (attr != null) {
10156             dit.mEndTime = Long.parseLong(attr);
10157         }
10158         int outerDepth = parser.getDepth();
10159         int type;
10160         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10161                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10162             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10163                 continue;
10164             }
10165 
10166             String tagName = parser.getName();
10167             if (tagName.equals("dis")) {
10168                 readDailyItemTagDetailsLocked(parser, dit, false, "dis");
10169             } else if (tagName.equals("chg")) {
10170                 readDailyItemTagDetailsLocked(parser, dit, true, "chg");
10171             } else if (tagName.equals("upd")) {
10172                 if (dit.mPackageChanges == null) {
10173                     dit.mPackageChanges = new ArrayList<>();
10174                 }
10175                 PackageChange pc = new PackageChange();
10176                 pc.mUpdate = true;
10177                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
10178                 String verStr = parser.getAttributeValue(null, "ver");
10179                 pc.mVersionCode = verStr != null ? Long.parseLong(verStr) : 0;
10180                 dit.mPackageChanges.add(pc);
10181                 XmlUtils.skipCurrentTag(parser);
10182             } else if (tagName.equals("rem")) {
10183                 if (dit.mPackageChanges == null) {
10184                     dit.mPackageChanges = new ArrayList<>();
10185                 }
10186                 PackageChange pc = new PackageChange();
10187                 pc.mUpdate = false;
10188                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
10189                 dit.mPackageChanges.add(pc);
10190                 XmlUtils.skipCurrentTag(parser);
10191             } else {
10192                 Slog.w(TAG, "Unknown element under <item>: "
10193                         + parser.getName());
10194                 XmlUtils.skipCurrentTag(parser);
10195             }
10196         }
10197         mDailyItems.add(dit);
10198     }
10199 
readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge, String tag)10200     void readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge,
10201             String tag)
10202             throws NumberFormatException, XmlPullParserException, IOException {
10203         final String numAttr = parser.getAttributeValue(null, "n");
10204         if (numAttr == null) {
10205             Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
10206             XmlUtils.skipCurrentTag(parser);
10207             return;
10208         }
10209         final int num = Integer.parseInt(numAttr);
10210         LevelStepTracker steps = new LevelStepTracker(num);
10211         if (isCharge) {
10212             dit.mChargeSteps = steps;
10213         } else {
10214             dit.mDischargeSteps = steps;
10215         }
10216         int i = 0;
10217         int outerDepth = parser.getDepth();
10218         int type;
10219         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10220                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10221             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10222                 continue;
10223             }
10224 
10225             String tagName = parser.getName();
10226             if ("s".equals(tagName)) {
10227                 if (i < num) {
10228                     String valueAttr = parser.getAttributeValue(null, "v");
10229                     if (valueAttr != null) {
10230                         steps.decodeEntryAt(i, valueAttr);
10231                         i++;
10232                     }
10233                 }
10234             } else {
10235                 Slog.w(TAG, "Unknown element under <" + tag + ">: "
10236                         + parser.getName());
10237                 XmlUtils.skipCurrentTag(parser);
10238             }
10239         }
10240         steps.mNumStepDurations = i;
10241     }
10242 
10243     @Override
getDailyItemLocked(int daysAgo)10244     public DailyItem getDailyItemLocked(int daysAgo) {
10245         int index = mDailyItems.size()-1-daysAgo;
10246         return index >= 0 ? mDailyItems.get(index) : null;
10247     }
10248 
10249     @Override
getCurrentDailyStartTime()10250     public long getCurrentDailyStartTime() {
10251         return mDailyStartTime;
10252     }
10253 
10254     @Override
getNextMinDailyDeadline()10255     public long getNextMinDailyDeadline() {
10256         return mNextMinDailyDeadline;
10257     }
10258 
10259     @Override
getNextMaxDailyDeadline()10260     public long getNextMaxDailyDeadline() {
10261         return mNextMaxDailyDeadline;
10262     }
10263 
10264     @Override
startIteratingOldHistoryLocked()10265     public boolean startIteratingOldHistoryLocked() {
10266         if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
10267                 + " pos=" + mHistoryBuffer.dataPosition());
10268         if ((mHistoryIterator = mHistory) == null) {
10269             return false;
10270         }
10271         mHistoryBuffer.setDataPosition(0);
10272         mHistoryReadTmp.clear();
10273         mReadOverflow = false;
10274         mIteratingHistory = true;
10275         return true;
10276     }
10277 
10278     @Override
getNextOldHistoryLocked(HistoryItem out)10279     public boolean getNextOldHistoryLocked(HistoryItem out) {
10280         boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
10281         if (!end) {
10282             readHistoryDelta(mHistoryBuffer, mHistoryReadTmp);
10283             mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
10284         }
10285         HistoryItem cur = mHistoryIterator;
10286         if (cur == null) {
10287             if (!mReadOverflow && !end) {
10288                 Slog.w(TAG, "Old history ends before new history!");
10289             }
10290             return false;
10291         }
10292         out.setTo(cur);
10293         mHistoryIterator = cur.next;
10294         if (!mReadOverflow) {
10295             if (end) {
10296                 Slog.w(TAG, "New history ends before old history!");
10297             } else if (!out.same(mHistoryReadTmp)) {
10298                 PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
10299                 pw.println("Histories differ!");
10300                 pw.println("Old history:");
10301                 (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
10302                 pw.println("New history:");
10303                 (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
10304                         true);
10305                 pw.flush();
10306             }
10307         }
10308         return true;
10309     }
10310 
10311     @Override
finishIteratingOldHistoryLocked()10312     public void finishIteratingOldHistoryLocked() {
10313         mIteratingHistory = false;
10314         mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
10315         mHistoryIterator = null;
10316     }
10317 
getHistoryTotalSize()10318     public int getHistoryTotalSize() {
10319         return mConstants.MAX_HISTORY_BUFFER * mConstants.MAX_HISTORY_FILES;
10320     }
10321 
getHistoryUsedSize()10322     public int getHistoryUsedSize() {
10323         return mBatteryStatsHistory.getHistoryUsedSize();
10324     }
10325 
10326     @Override
10327     @UnsupportedAppUsage
startIteratingHistoryLocked()10328     public boolean startIteratingHistoryLocked() {
10329         mBatteryStatsHistory.startIteratingHistory();
10330         mReadOverflow = false;
10331         mIteratingHistory = true;
10332         mReadHistoryStrings = new String[mHistoryTagPool.size()];
10333         mReadHistoryUids = new int[mHistoryTagPool.size()];
10334         mReadHistoryChars = 0;
10335         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
10336             final HistoryTag tag = ent.getKey();
10337             final int idx = ent.getValue();
10338             mReadHistoryStrings[idx] = tag.string;
10339             mReadHistoryUids[idx] = tag.uid;
10340             mReadHistoryChars += tag.string.length() + 1;
10341         }
10342         return true;
10343     }
10344 
10345     @Override
getHistoryStringPoolSize()10346     public int getHistoryStringPoolSize() {
10347         return mReadHistoryStrings.length;
10348     }
10349 
10350     @Override
getHistoryStringPoolBytes()10351     public int getHistoryStringPoolBytes() {
10352         // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
10353         // Each string character is 2 bytes.
10354         return (mReadHistoryStrings.length * 12) + (mReadHistoryChars * 2);
10355     }
10356 
10357     @Override
getHistoryTagPoolString(int index)10358     public String getHistoryTagPoolString(int index) {
10359         return mReadHistoryStrings[index];
10360     }
10361 
10362     @Override
getHistoryTagPoolUid(int index)10363     public int getHistoryTagPoolUid(int index) {
10364         return mReadHistoryUids[index];
10365     }
10366 
10367     @Override
10368     @UnsupportedAppUsage
getNextHistoryLocked(HistoryItem out)10369     public boolean getNextHistoryLocked(HistoryItem out) {
10370         Parcel p = mBatteryStatsHistory.getNextParcel(out);
10371         if (p == null) {
10372             return false;
10373         }
10374         final long lastRealtime = out.time;
10375         final long lastWalltime = out.currentTime;
10376         readHistoryDelta(p, out);
10377         if (out.cmd != HistoryItem.CMD_CURRENT_TIME
10378                 && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
10379             out.currentTime = lastWalltime + (out.time - lastRealtime);
10380         }
10381         return true;
10382     }
10383 
10384     @Override
finishIteratingHistoryLocked()10385     public void finishIteratingHistoryLocked() {
10386         mBatteryStatsHistory.finishIteratingHistory();
10387         mIteratingHistory = false;
10388         mReadHistoryStrings = null;
10389         mReadHistoryUids = null;
10390     }
10391 
10392     @Override
getHistoryBaseTime()10393     public long getHistoryBaseTime() {
10394         return mHistoryBaseTime;
10395     }
10396 
10397     @Override
getStartCount()10398     public int getStartCount() {
10399         return mStartCount;
10400     }
10401 
10402     @UnsupportedAppUsage
isOnBattery()10403     public boolean isOnBattery() {
10404         return mOnBattery;
10405     }
10406 
isCharging()10407     public boolean isCharging() {
10408         return mCharging;
10409     }
10410 
isScreenOn(int state)10411     public boolean isScreenOn(int state) {
10412         return state == Display.STATE_ON || state == Display.STATE_VR
10413             || state == Display.STATE_ON_SUSPEND;
10414     }
10415 
isScreenOff(int state)10416     public boolean isScreenOff(int state) {
10417         return state == Display.STATE_OFF;
10418     }
10419 
isScreenDoze(int state)10420     public boolean isScreenDoze(int state) {
10421         return state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND;
10422     }
10423 
initTimes(long uptime, long realtime)10424     void initTimes(long uptime, long realtime) {
10425         mStartClockTime = System.currentTimeMillis();
10426         mOnBatteryTimeBase.init(uptime, realtime);
10427         mOnBatteryScreenOffTimeBase.init(uptime, realtime);
10428         mRealtime = 0;
10429         mUptime = 0;
10430         mRealtimeStart = realtime;
10431         mUptimeStart = uptime;
10432     }
10433 
initDischarge()10434     void initDischarge() {
10435         mLowDischargeAmountSinceCharge = 0;
10436         mHighDischargeAmountSinceCharge = 0;
10437         mDischargeAmountScreenOn = 0;
10438         mDischargeAmountScreenOnSinceCharge = 0;
10439         mDischargeAmountScreenOff = 0;
10440         mDischargeAmountScreenOffSinceCharge = 0;
10441         mDischargeAmountScreenDoze = 0;
10442         mDischargeAmountScreenDozeSinceCharge = 0;
10443         mDischargeStepTracker.init();
10444         mChargeStepTracker.init();
10445         mDischargeScreenOffCounter.reset(false);
10446         mDischargeScreenDozeCounter.reset(false);
10447         mDischargeLightDozeCounter.reset(false);
10448         mDischargeDeepDozeCounter.reset(false);
10449         mDischargeCounter.reset(false);
10450     }
10451 
resetAllStatsCmdLocked()10452     public void resetAllStatsCmdLocked() {
10453         resetAllStatsLocked();
10454         final long mSecUptime = mClocks.uptimeMillis();
10455         long uptime = mSecUptime * 1000;
10456         long mSecRealtime = mClocks.elapsedRealtime();
10457         long realtime = mSecRealtime * 1000;
10458         mDischargeStartLevel = mHistoryCur.batteryLevel;
10459         pullPendingStateUpdatesLocked();
10460         addHistoryRecordLocked(mSecRealtime, mSecUptime);
10461         mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
10462                 = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
10463         mOnBatteryTimeBase.reset(uptime, realtime);
10464         mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
10465         if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
10466             if (isScreenOn(mScreenState)) {
10467                 mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
10468                 mDischargeScreenDozeUnplugLevel = 0;
10469                 mDischargeScreenOffUnplugLevel = 0;
10470             } else if (isScreenDoze(mScreenState)) {
10471                 mDischargeScreenOnUnplugLevel = 0;
10472                 mDischargeScreenDozeUnplugLevel = mHistoryCur.batteryLevel;
10473                 mDischargeScreenOffUnplugLevel = 0;
10474             } else {
10475                 mDischargeScreenOnUnplugLevel = 0;
10476                 mDischargeScreenDozeUnplugLevel = 0;
10477                 mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
10478             }
10479             mDischargeAmountScreenOn = 0;
10480             mDischargeAmountScreenOff = 0;
10481             mDischargeAmountScreenDoze = 0;
10482         }
10483         initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
10484     }
10485 
resetAllStatsLocked()10486     private void resetAllStatsLocked() {
10487         final long uptimeMillis = mClocks.uptimeMillis();
10488         final long elapsedRealtimeMillis = mClocks.elapsedRealtime();
10489         mStartCount = 0;
10490         initTimes(uptimeMillis * 1000, elapsedRealtimeMillis * 1000);
10491         mScreenOnTimer.reset(false);
10492         mScreenDozeTimer.reset(false);
10493         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10494             mScreenBrightnessTimer[i].reset(false);
10495         }
10496 
10497         if (mPowerProfile != null) {
10498             mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
10499         } else {
10500             mEstimatedBatteryCapacity = -1;
10501         }
10502         mMinLearnedBatteryCapacity = -1;
10503         mMaxLearnedBatteryCapacity = -1;
10504         mInteractiveTimer.reset(false);
10505         mPowerSaveModeEnabledTimer.reset(false);
10506         mLastIdleTimeStart = elapsedRealtimeMillis;
10507         mLongestLightIdleTime = 0;
10508         mLongestFullIdleTime = 0;
10509         mDeviceIdleModeLightTimer.reset(false);
10510         mDeviceIdleModeFullTimer.reset(false);
10511         mDeviceLightIdlingTimer.reset(false);
10512         mDeviceIdlingTimer.reset(false);
10513         mPhoneOnTimer.reset(false);
10514         mAudioOnTimer.reset(false);
10515         mVideoOnTimer.reset(false);
10516         mFlashlightOnTimer.reset(false);
10517         mCameraOnTimer.reset(false);
10518         mBluetoothScanTimer.reset(false);
10519         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
10520             mPhoneSignalStrengthsTimer[i].reset(false);
10521         }
10522         mPhoneSignalScanningTimer.reset(false);
10523         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10524             mPhoneDataConnectionsTimer[i].reset(false);
10525         }
10526         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10527             mNetworkByteActivityCounters[i].reset(false);
10528             mNetworkPacketActivityCounters[i].reset(false);
10529         }
10530         mMobileRadioActiveTimer.reset(false);
10531         mMobileRadioActivePerAppTimer.reset(false);
10532         mMobileRadioActiveAdjustedTime.reset(false);
10533         mMobileRadioActiveUnknownTime.reset(false);
10534         mMobileRadioActiveUnknownCount.reset(false);
10535         mWifiOnTimer.reset(false);
10536         mGlobalWifiRunningTimer.reset(false);
10537         for (int i=0; i<NUM_WIFI_STATES; i++) {
10538             mWifiStateTimer[i].reset(false);
10539         }
10540         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10541             mWifiSupplStateTimer[i].reset(false);
10542         }
10543         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10544             mWifiSignalStrengthsTimer[i].reset(false);
10545         }
10546         mWifiMulticastWakelockTimer.reset(false);
10547         mWifiActiveTimer.reset(false);
10548         mWifiActivity.reset(false);
10549         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
10550             mGpsSignalQualityTimer[i].reset(false);
10551         }
10552         mBluetoothActivity.reset(false);
10553         mModemActivity.reset(false);
10554         mNumConnectivityChange = 0;
10555 
10556         for (int i=0; i<mUidStats.size(); i++) {
10557             if (mUidStats.valueAt(i).reset(uptimeMillis * 1000, elapsedRealtimeMillis * 1000)) {
10558                 mUidStats.valueAt(i).detachFromTimeBase();
10559                 mUidStats.remove(mUidStats.keyAt(i));
10560                 i--;
10561             }
10562         }
10563 
10564         if (mRpmStats.size() > 0) {
10565             for (SamplingTimer timer : mRpmStats.values()) {
10566                 mOnBatteryTimeBase.remove(timer);
10567             }
10568             mRpmStats.clear();
10569         }
10570         if (mScreenOffRpmStats.size() > 0) {
10571             for (SamplingTimer timer : mScreenOffRpmStats.values()) {
10572                 mOnBatteryScreenOffTimeBase.remove(timer);
10573             }
10574             mScreenOffRpmStats.clear();
10575         }
10576 
10577         if (mKernelWakelockStats.size() > 0) {
10578             for (SamplingTimer timer : mKernelWakelockStats.values()) {
10579                 mOnBatteryScreenOffTimeBase.remove(timer);
10580             }
10581             mKernelWakelockStats.clear();
10582         }
10583 
10584         if (mKernelMemoryStats.size() > 0) {
10585             for (int i = 0; i < mKernelMemoryStats.size(); i++) {
10586                 mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i));
10587             }
10588             mKernelMemoryStats.clear();
10589         }
10590 
10591         if (mWakeupReasonStats.size() > 0) {
10592             for (SamplingTimer timer : mWakeupReasonStats.values()) {
10593                 mOnBatteryTimeBase.remove(timer);
10594             }
10595             mWakeupReasonStats.clear();
10596         }
10597 
10598         mTmpRailStats.reset();
10599 
10600         mLastHistoryStepDetails = null;
10601         mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
10602         mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
10603         mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
10604         mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
10605         mLastStepStatUserTime = mCurStepStatUserTime = 0;
10606         mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
10607         mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
10608         mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
10609         mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
10610         mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
10611 
10612         mNumAllUidCpuTimeReads = 0;
10613         mNumUidsRemoved = 0;
10614 
10615         initDischarge();
10616 
10617         clearHistoryLocked();
10618         mBatteryStatsHistory.resetAllFiles();
10619 
10620         mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
10621     }
10622 
initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs)10623     private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
10624         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
10625             if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
10626                 // Not recording process starts/stops.
10627                 continue;
10628             }
10629             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
10630             if (active == null) {
10631                 continue;
10632             }
10633             for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
10634                 SparseIntArray uids = ent.getValue();
10635                 for (int j=0; j<uids.size(); j++) {
10636                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
10637                             uids.keyAt(j));
10638                 }
10639             }
10640         }
10641     }
10642 
updateDischargeScreenLevelsLocked(int oldState, int newState)10643     void updateDischargeScreenLevelsLocked(int oldState, int newState) {
10644         updateOldDischargeScreenLevelLocked(oldState);
10645         updateNewDischargeScreenLevelLocked(newState);
10646     }
10647 
updateOldDischargeScreenLevelLocked(int state)10648     private void updateOldDischargeScreenLevelLocked(int state) {
10649         if (isScreenOn(state)) {
10650             int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
10651             if (diff > 0) {
10652                 mDischargeAmountScreenOn += diff;
10653                 mDischargeAmountScreenOnSinceCharge += diff;
10654             }
10655         } else if (isScreenDoze(state)) {
10656             int diff = mDischargeScreenDozeUnplugLevel - mDischargeCurrentLevel;
10657             if (diff > 0) {
10658                 mDischargeAmountScreenDoze += diff;
10659                 mDischargeAmountScreenDozeSinceCharge += diff;
10660             }
10661         } else if (isScreenOff(state)){
10662             int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
10663             if (diff > 0) {
10664                 mDischargeAmountScreenOff += diff;
10665                 mDischargeAmountScreenOffSinceCharge += diff;
10666             }
10667         }
10668     }
10669 
updateNewDischargeScreenLevelLocked(int state)10670     private void updateNewDischargeScreenLevelLocked(int state) {
10671         if (isScreenOn(state)) {
10672             mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
10673             mDischargeScreenOffUnplugLevel = 0;
10674             mDischargeScreenDozeUnplugLevel = 0;
10675         } else if (isScreenDoze(state)){
10676             mDischargeScreenOnUnplugLevel = 0;
10677             mDischargeScreenDozeUnplugLevel = mDischargeCurrentLevel;
10678             mDischargeScreenOffUnplugLevel = 0;
10679         } else if (isScreenOff(state)) {
10680             mDischargeScreenOnUnplugLevel = 0;
10681             mDischargeScreenDozeUnplugLevel = 0;
10682             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
10683         }
10684     }
10685 
pullPendingStateUpdatesLocked()10686     public void pullPendingStateUpdatesLocked() {
10687         if (mOnBatteryInternal) {
10688             updateDischargeScreenLevelsLocked(mScreenState, mScreenState);
10689         }
10690     }
10691 
10692     private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6);
10693 
10694     private final Object mWifiNetworkLock = new Object();
10695 
10696     @GuardedBy("mWifiNetworkLock")
10697     private String[] mWifiIfaces = EmptyArray.STRING;
10698 
10699     @GuardedBy("mWifiNetworkLock")
10700     private NetworkStats mLastWifiNetworkStats = new NetworkStats(0, -1);
10701 
10702     private final Object mModemNetworkLock = new Object();
10703 
10704     @GuardedBy("mModemNetworkLock")
10705     private String[] mModemIfaces = EmptyArray.STRING;
10706 
10707     @GuardedBy("mModemNetworkLock")
10708     private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
10709 
readNetworkStatsLocked(String[] ifaces)10710     private NetworkStats readNetworkStatsLocked(String[] ifaces) {
10711         try {
10712             if (!ArrayUtils.isEmpty(ifaces)) {
10713                 INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
10714                         ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
10715                 if (statsService != null) {
10716                     return statsService.getDetailedUidStats(ifaces);
10717                 } else {
10718                     Slog.e(TAG, "Failed to get networkStatsService ");
10719                 }
10720             }
10721         } catch (RemoteException e) {
10722             Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces) + e);
10723         }
10724         return null;
10725     }
10726 
10727    /**
10728      * Distribute WiFi energy info and network traffic to apps.
10729      * @param info The energy information from the WiFi controller.
10730      */
updateWifiState(@ullable final WifiActivityEnergyInfo info)10731     public void updateWifiState(@Nullable final WifiActivityEnergyInfo info) {
10732         if (DEBUG_ENERGY) {
10733             Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
10734         }
10735 
10736         // Grab a separate lock to acquire the network stats, which may do I/O.
10737         NetworkStats delta = null;
10738         synchronized (mWifiNetworkLock) {
10739             final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces);
10740             if (latestStats != null) {
10741                 delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null,
10742                         mNetworkStatsPool.acquire());
10743                 mNetworkStatsPool.release(mLastWifiNetworkStats);
10744                 mLastWifiNetworkStats = latestStats;
10745             }
10746         }
10747 
10748         synchronized (this) {
10749             if (!mOnBatteryInternal) {
10750                 if (delta != null) {
10751                     mNetworkStatsPool.release(delta);
10752                 }
10753                 return;
10754             }
10755 
10756             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
10757             SparseLongArray rxPackets = new SparseLongArray();
10758             SparseLongArray txPackets = new SparseLongArray();
10759             long totalTxPackets = 0;
10760             long totalRxPackets = 0;
10761             if (delta != null) {
10762                 NetworkStats.Entry entry = new NetworkStats.Entry();
10763                 final int size = delta.size();
10764                 for (int i = 0; i < size; i++) {
10765                     entry = delta.getValues(i, entry);
10766 
10767                     if (DEBUG_ENERGY) {
10768                         Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
10769                                 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
10770                                 + " txPackets=" + entry.txPackets);
10771                     }
10772 
10773                     if (entry.rxBytes == 0 && entry.txBytes == 0) {
10774                         // Skip the lookup below since there is no work to do.
10775                         continue;
10776                     }
10777 
10778                     final Uid u = getUidStatsLocked(mapUid(entry.uid));
10779                     if (entry.rxBytes != 0) {
10780                         u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
10781                                 entry.rxPackets);
10782                         if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
10783                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
10784                                     entry.rxPackets);
10785                         }
10786                         mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
10787                                 entry.rxBytes);
10788                         mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
10789                                 entry.rxPackets);
10790 
10791                         rxPackets.put(u.getUid(), entry.rxPackets);
10792 
10793                         // Sum the total number of packets so that the Rx Power can
10794                         // be evenly distributed amongst the apps.
10795                         totalRxPackets += entry.rxPackets;
10796                     }
10797 
10798                     if (entry.txBytes != 0) {
10799                         u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
10800                                 entry.txPackets);
10801                         if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
10802                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
10803                                     entry.txPackets);
10804                         }
10805                         mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
10806                                 entry.txBytes);
10807                         mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
10808                                 entry.txPackets);
10809 
10810                         txPackets.put(u.getUid(), entry.txPackets);
10811 
10812                         // Sum the total number of packets so that the Tx Power can
10813                         // be evenly distributed amongst the apps.
10814                         totalTxPackets += entry.txPackets;
10815                     }
10816                 }
10817                 mNetworkStatsPool.release(delta);
10818                 delta = null;
10819             }
10820 
10821             if (info != null) {
10822                 mHasWifiReporting = true;
10823 
10824                 // Measured in mAms
10825                 final long txTimeMs = info.getControllerTxDurationMillis();
10826                 final long rxTimeMs = info.getControllerRxDurationMillis();
10827                 final long scanTimeMs = info.getControllerScanDurationMillis();
10828                 final long idleTimeMs = info.getControllerIdleDurationMillis();
10829                 final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
10830 
10831                 long leftOverRxTimeMs = rxTimeMs;
10832                 long leftOverTxTimeMs = txTimeMs;
10833 
10834                 if (DEBUG_ENERGY) {
10835                     Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
10836                     Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
10837                     Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
10838                     Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
10839                     Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
10840                     Slog.d(TAG, "  Scan Time:  " + scanTimeMs + " ms");
10841                 }
10842 
10843                 long totalWifiLockTimeMs = 0;
10844                 long totalScanTimeMs = 0;
10845 
10846                 // On the first pass, collect some totals so that we can normalize power
10847                 // calculations if we need to.
10848                 final int uidStatsSize = mUidStats.size();
10849                 for (int i = 0; i < uidStatsSize; i++) {
10850                     final Uid uid = mUidStats.valueAt(i);
10851 
10852                     // Sum the total scan power for all apps.
10853                     totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
10854                             elapsedRealtimeMs * 1000) / 1000;
10855 
10856                     // Sum the total time holding wifi lock for all apps.
10857                     totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
10858                             elapsedRealtimeMs * 1000) / 1000;
10859                 }
10860 
10861                 if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
10862                     Slog.d(TAG,
10863                             "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
10864                                     + rxTimeMs + " ms). Normalizing scan time.");
10865                 }
10866                 if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
10867                     Slog.d(TAG,
10868                             "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
10869                                     + txTimeMs + " ms). Normalizing scan time.");
10870                 }
10871 
10872                 // Actually assign and distribute power usage to apps.
10873                 for (int i = 0; i < uidStatsSize; i++) {
10874                     final Uid uid = mUidStats.valueAt(i);
10875 
10876                     long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
10877                             elapsedRealtimeMs * 1000) / 1000;
10878                     if (scanTimeSinceMarkMs > 0) {
10879                         // Set the new mark so that next time we get new data since this point.
10880                         uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
10881 
10882                         long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
10883                         long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
10884 
10885                         // Our total scan time is more than the reported Tx/Rx time.
10886                         // This is possible because the cost of a scan is approximate.
10887                         // Let's normalize the result so that we evenly blame each app
10888                         // scanning.
10889                         //
10890                         // This means that we may have apps that transmitted/received packets not be
10891                         // blamed for this, but this is fine as scans are relatively more expensive.
10892                         if (totalScanTimeMs > rxTimeMs) {
10893                             scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
10894                                     totalScanTimeMs;
10895                         }
10896                         if (totalScanTimeMs > txTimeMs) {
10897                             scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
10898                                     totalScanTimeMs;
10899                         }
10900 
10901                         if (DEBUG_ENERGY) {
10902                             Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
10903                                     + scanRxTimeSinceMarkMs + " ms  Tx:"
10904                                     + scanTxTimeSinceMarkMs + " ms)");
10905                         }
10906 
10907                         ControllerActivityCounterImpl activityCounter =
10908                                 uid.getOrCreateWifiControllerActivityLocked();
10909                         activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
10910                         activityCounter.getTxTimeCounters()[0].addCountLocked(
10911                                 scanTxTimeSinceMarkMs);
10912                         leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
10913                         leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
10914                     }
10915 
10916                     // Distribute evenly the power consumed while Idle to each app holding a WiFi
10917                     // lock.
10918                     final long wifiLockTimeSinceMarkMs =
10919                             uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
10920                                     elapsedRealtimeMs * 1000) / 1000;
10921                     if (wifiLockTimeSinceMarkMs > 0) {
10922                         // Set the new mark so that next time we get new data since this point.
10923                         uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
10924 
10925                         final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
10926                                 / totalWifiLockTimeMs;
10927                         if (DEBUG_ENERGY) {
10928                             Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
10929                                     + myIdleTimeMs + " ms");
10930                         }
10931                         uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
10932                                 .addCountLocked(myIdleTimeMs);
10933                     }
10934                 }
10935 
10936                 if (DEBUG_ENERGY) {
10937                     Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
10938                     Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
10939                 }
10940 
10941                 // Distribute the remaining Tx power appropriately between all apps that transmitted
10942                 // packets.
10943                 for (int i = 0; i < txPackets.size(); i++) {
10944                     final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
10945                     final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
10946                             / totalTxPackets;
10947                     if (DEBUG_ENERGY) {
10948                         Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
10949                     }
10950                     uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
10951                             .addCountLocked(myTxTimeMs);
10952                 }
10953 
10954                 // Distribute the remaining Rx power appropriately between all apps that received
10955                 // packets.
10956                 for (int i = 0; i < rxPackets.size(); i++) {
10957                     final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
10958                     final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
10959                             / totalRxPackets;
10960                     if (DEBUG_ENERGY) {
10961                         Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
10962                     }
10963                     uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
10964                             .addCountLocked(myRxTimeMs);
10965                 }
10966 
10967                 // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
10968 
10969 
10970                 // Update WiFi controller stats.
10971                 mWifiActivity.getRxTimeCounter().addCountLocked(
10972                         info.getControllerRxDurationMillis());
10973                 mWifiActivity.getTxTimeCounters()[0].addCountLocked(
10974                         info.getControllerTxDurationMillis());
10975                 mWifiActivity.getScanTimeCounter().addCountLocked(
10976                         info.getControllerScanDurationMillis());
10977                 mWifiActivity.getIdleTimeCounter().addCountLocked(
10978                         info.getControllerIdleDurationMillis());
10979 
10980                 // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
10981                 final double opVolt = mPowerProfile.getAveragePower(
10982                         PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
10983                 if (opVolt != 0) {
10984                     // We store the power drain as mAms.
10985                     mWifiActivity.getPowerCounter().addCountLocked(
10986                             (long) (info.getControllerEnergyUsedMicroJoules() / opVolt));
10987                 }
10988                 // Converting uWs to mAms.
10989                 // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
10990                 long monitoredRailChargeConsumedMaMs =
10991                         (long) (mTmpRailStats.getWifiTotalEnergyUseduWs() / opVolt);
10992                 mWifiActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
10993                         monitoredRailChargeConsumedMaMs);
10994                 mHistoryCur.wifiRailChargeMah +=
10995                         (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
10996                 addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
10997                 mTmpRailStats.resetWifiTotalEnergyUsed();
10998             }
10999         }
11000     }
11001 
11002     private ModemActivityInfo mLastModemActivityInfo =
11003             new ModemActivityInfo(0, 0, 0, new int[0], 0);
11004 
getDeltaModemActivityInfo(ModemActivityInfo activityInfo)11005     private ModemActivityInfo getDeltaModemActivityInfo(ModemActivityInfo activityInfo) {
11006         if (activityInfo == null) {
11007             return null;
11008         }
11009         int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
11010         for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) {
11011             txTimeMs[i] = activityInfo.getTransmitPowerInfo().get(i).getTimeInMillis()
11012                     - mLastModemActivityInfo.getTransmitPowerInfo().get(i).getTimeInMillis();
11013         }
11014         ModemActivityInfo deltaInfo = new ModemActivityInfo(activityInfo.getTimestamp(),
11015                 activityInfo.getSleepTimeMillis() - mLastModemActivityInfo.getSleepTimeMillis(),
11016                 activityInfo.getIdleTimeMillis() - mLastModemActivityInfo.getIdleTimeMillis(),
11017                 txTimeMs,
11018                 activityInfo.getReceiveTimeMillis() - mLastModemActivityInfo.getReceiveTimeMillis());
11019         mLastModemActivityInfo = activityInfo;
11020         return deltaInfo;
11021     }
11022 
11023     /**
11024      * Distribute Cell radio energy info and network traffic to apps.
11025      */
updateMobileRadioState(@ullable final ModemActivityInfo activityInfo)11026     public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo) {
11027         if (DEBUG_ENERGY) {
11028             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
11029         }
11030         ModemActivityInfo deltaInfo = getDeltaModemActivityInfo(activityInfo);
11031 
11032         // Add modem tx power to history.
11033         addModemTxPowerToHistory(deltaInfo);
11034 
11035         // Grab a separate lock to acquire the network stats, which may do I/O.
11036         NetworkStats delta = null;
11037         synchronized (mModemNetworkLock) {
11038             final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces);
11039             if (latestStats != null) {
11040                 delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null,
11041                         mNetworkStatsPool.acquire());
11042                 mNetworkStatsPool.release(mLastModemNetworkStats);
11043                 mLastModemNetworkStats = latestStats;
11044             }
11045         }
11046 
11047         synchronized (this) {
11048             if (!mOnBatteryInternal) {
11049                 if (delta != null) {
11050                     mNetworkStatsPool.release(delta);
11051                 }
11052                 return;
11053             }
11054 
11055             if (deltaInfo != null) {
11056                 mHasModemReporting = true;
11057                 mModemActivity.getIdleTimeCounter().addCountLocked(
11058                         deltaInfo.getIdleTimeMillis());
11059                 mModemActivity.getSleepTimeCounter().addCountLocked(
11060                         deltaInfo.getSleepTimeMillis());
11061                 mModemActivity.getRxTimeCounter().addCountLocked(deltaInfo.getReceiveTimeMillis());
11062                 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
11063                     mModemActivity.getTxTimeCounters()[lvl]
11064                         .addCountLocked(deltaInfo.getTransmitPowerInfo()
11065                             .get(lvl).getTimeInMillis());
11066                 }
11067 
11068                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11069                 final double opVolt = mPowerProfile.getAveragePower(
11070                     PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11071                 if (opVolt != 0) {
11072                     double energyUsed =
11073                             deltaInfo.getSleepTimeMillis() *
11074                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
11075                             + deltaInfo.getIdleTimeMillis() *
11076                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
11077                             + deltaInfo.getReceiveTimeMillis() *
11078                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
11079                     List<TransmitPower> txPowerInfo = deltaInfo.getTransmitPowerInfo();
11080                     for (int i = 0; i < Math.min(txPowerInfo.size(),
11081                             CellSignalStrength.getNumSignalStrengthLevels()); i++) {
11082                         energyUsed += txPowerInfo.get(i).getTimeInMillis() * mPowerProfile
11083                             .getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
11084                     }
11085 
11086                     // We store the power drain as mAms.
11087                     mModemActivity.getPowerCounter().addCountLocked((long) energyUsed);
11088                     // Converting uWs to mAms.
11089                     // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
11090                     long monitoredRailChargeConsumedMaMs =
11091                             (long) (mTmpRailStats.getCellularTotalEnergyUseduWs() / opVolt);
11092                     mModemActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
11093                             monitoredRailChargeConsumedMaMs);
11094                     mHistoryCur.modemRailChargeMah +=
11095                             (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
11096                     addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
11097                     mTmpRailStats.resetCellularTotalEnergyUsed();
11098                 }
11099             }
11100             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
11101             long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
11102                     elapsedRealtimeMs * 1000);
11103             mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
11104 
11105             long totalRxPackets = 0;
11106             long totalTxPackets = 0;
11107             if (delta != null) {
11108                 NetworkStats.Entry entry = new NetworkStats.Entry();
11109                 final int size = delta.size();
11110                 for (int i = 0; i < size; i++) {
11111                     entry = delta.getValues(i, entry);
11112                     if (entry.rxPackets == 0 && entry.txPackets == 0) {
11113                         continue;
11114                     }
11115 
11116                     if (DEBUG_ENERGY) {
11117                         Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
11118                                 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
11119                                 + " txPackets=" + entry.txPackets);
11120                     }
11121 
11122                     totalRxPackets += entry.rxPackets;
11123                     totalTxPackets += entry.txPackets;
11124 
11125                     final Uid u = getUidStatsLocked(mapUid(entry.uid));
11126                     u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
11127                             entry.rxPackets);
11128                     u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
11129                             entry.txPackets);
11130                     if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11131                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
11132                                 entry.rxBytes, entry.rxPackets);
11133                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
11134                                 entry.txBytes, entry.txPackets);
11135                     }
11136 
11137                     mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
11138                             entry.rxBytes);
11139                     mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
11140                             entry.txBytes);
11141                     mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
11142                             entry.rxPackets);
11143                     mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
11144                             entry.txPackets);
11145                 }
11146 
11147                 // Now distribute proportional blame to the apps that did networking.
11148                 long totalPackets = totalRxPackets + totalTxPackets;
11149                 if (totalPackets > 0) {
11150                     for (int i = 0; i < size; i++) {
11151                         entry = delta.getValues(i, entry);
11152                         if (entry.rxPackets == 0 && entry.txPackets == 0) {
11153                             continue;
11154                         }
11155 
11156                         final Uid u = getUidStatsLocked(mapUid(entry.uid));
11157 
11158                         // Distribute total radio active time in to this app.
11159                         final long appPackets = entry.rxPackets + entry.txPackets;
11160                         final long appRadioTime = (radioTime * appPackets) / totalPackets;
11161                         u.noteMobileRadioActiveTimeLocked(appRadioTime);
11162 
11163                         // Remove this app from the totals, so that we don't lose any time
11164                         // due to rounding.
11165                         radioTime -= appRadioTime;
11166                         totalPackets -= appPackets;
11167 
11168                         if (deltaInfo != null) {
11169                             ControllerActivityCounterImpl activityCounter =
11170                                     u.getOrCreateModemControllerActivityLocked();
11171                             if (totalRxPackets > 0 && entry.rxPackets > 0) {
11172                                 final long rxMs = (entry.rxPackets
11173                                     * deltaInfo.getReceiveTimeMillis()) / totalRxPackets;
11174                                 activityCounter.getRxTimeCounter().addCountLocked(rxMs);
11175                             }
11176 
11177                             if (totalTxPackets > 0 && entry.txPackets > 0) {
11178                                 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
11179                                     long txMs =
11180                                             entry.txPackets * deltaInfo.getTransmitPowerInfo()
11181                                                 .get(lvl).getTimeInMillis();
11182                                     txMs /= totalTxPackets;
11183                                     activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
11184                                 }
11185                             }
11186                         }
11187                     }
11188                 }
11189 
11190                 if (radioTime > 0) {
11191                     // Whoops, there is some radio time we can't blame on an app!
11192                     mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
11193                     mMobileRadioActiveUnknownCount.addCountLocked(1);
11194                 }
11195 
11196                 mNetworkStatsPool.release(delta);
11197                 delta = null;
11198             }
11199         }
11200     }
11201 
11202     /**
11203      * Add modem tx power to history
11204      * Device is said to be in high cellular transmit power when it has spent most of the transmit
11205      * time at the highest power level.
11206      * @param activityInfo
11207      */
addModemTxPowerToHistory(final ModemActivityInfo activityInfo)11208     private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo) {
11209         if (activityInfo == null) {
11210             return;
11211         }
11212         List<TransmitPower> txPowerInfo = activityInfo.getTransmitPowerInfo();
11213         if (txPowerInfo == null || txPowerInfo.size() != ModemActivityInfo.TX_POWER_LEVELS) {
11214             return;
11215         }
11216         final long elapsedRealtime = mClocks.elapsedRealtime();
11217         final long uptime = mClocks.uptimeMillis();
11218         int levelMaxTimeSpent = 0;
11219         for (int i = 1; i < txPowerInfo.size(); i++) {
11220             if (txPowerInfo.get(i).getTimeInMillis() > txPowerInfo.get(levelMaxTimeSpent)
11221                 .getTimeInMillis()) {
11222                 levelMaxTimeSpent = i;
11223             }
11224         }
11225         if (levelMaxTimeSpent == ModemActivityInfo.TX_POWER_LEVELS - 1) {
11226             mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
11227             addHistoryRecordLocked(elapsedRealtime, uptime);
11228         }
11229     }
11230 
11231     private final class BluetoothActivityInfoCache {
11232         long idleTimeMs;
11233         long rxTimeMs;
11234         long txTimeMs;
11235         long energy;
11236 
11237         SparseLongArray uidRxBytes = new SparseLongArray();
11238         SparseLongArray uidTxBytes = new SparseLongArray();
11239 
set(BluetoothActivityEnergyInfo info)11240         void set(BluetoothActivityEnergyInfo info) {
11241             idleTimeMs = info.getControllerIdleTimeMillis();
11242             rxTimeMs = info.getControllerRxTimeMillis();
11243             txTimeMs = info.getControllerTxTimeMillis();
11244             energy = info.getControllerEnergyUsed();
11245             if (info.getUidTraffic() != null) {
11246                 for (UidTraffic traffic : info.getUidTraffic()) {
11247                     uidRxBytes.put(traffic.getUid(), traffic.getRxBytes());
11248                     uidTxBytes.put(traffic.getUid(), traffic.getTxBytes());
11249                 }
11250             }
11251         }
11252     }
11253 
11254     private final BluetoothActivityInfoCache mLastBluetoothActivityInfo
11255             = new BluetoothActivityInfoCache();
11256 
11257     /**
11258      * Distribute Bluetooth energy info and network traffic to apps.
11259      *
11260      * @param info The energy information from the bluetooth controller.
11261      */
updateBluetoothStateLocked(@ullable final BluetoothActivityEnergyInfo info)11262     public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
11263         if (DEBUG_ENERGY) {
11264             Slog.d(TAG, "Updating bluetooth stats: " + info);
11265         }
11266 
11267         if (info == null || !mOnBatteryInternal) {
11268             return;
11269         }
11270 
11271         mHasBluetoothReporting = true;
11272 
11273         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
11274         final long rxTimeMs =
11275                 info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs;
11276         final long txTimeMs =
11277                 info.getControllerTxTimeMillis() - mLastBluetoothActivityInfo.txTimeMs;
11278         final long idleTimeMs =
11279                 info.getControllerIdleTimeMillis() - mLastBluetoothActivityInfo.idleTimeMs;
11280 
11281         if (DEBUG_ENERGY) {
11282             Slog.d(TAG, "------ BEGIN BLE power blaming ------");
11283             Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
11284             Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
11285             Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
11286         }
11287 
11288         long totalScanTimeMs = 0;
11289 
11290         final int uidCount = mUidStats.size();
11291         for (int i = 0; i < uidCount; i++) {
11292             final Uid u = mUidStats.valueAt(i);
11293             if (u.mBluetoothScanTimer == null) {
11294                 continue;
11295             }
11296 
11297             totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
11298                     elapsedRealtimeMs * 1000) / 1000;
11299         }
11300 
11301         final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
11302         final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
11303 
11304         if (DEBUG_ENERGY) {
11305             Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
11306                     + " TX=" + normalizeScanTxTime);
11307         }
11308 
11309         long leftOverRxTimeMs = rxTimeMs;
11310         long leftOverTxTimeMs = txTimeMs;
11311 
11312         for (int i = 0; i < uidCount; i++) {
11313             final Uid u = mUidStats.valueAt(i);
11314             if (u.mBluetoothScanTimer == null) {
11315                 continue;
11316             }
11317 
11318             long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
11319                     elapsedRealtimeMs * 1000) / 1000;
11320             if (scanTimeSinceMarkMs > 0) {
11321                 // Set the new mark so that next time we get new data since this point.
11322                 u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
11323 
11324                 long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
11325                 long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
11326 
11327                 if (normalizeScanRxTime) {
11328                     // Scan time is longer than the total rx time in the controller,
11329                     // so distribute the scan time proportionately. This means regular traffic
11330                     // will not blamed, but scans are more expensive anyways.
11331                     scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
11332                 }
11333 
11334                 if (normalizeScanTxTime) {
11335                     // Scan time is longer than the total tx time in the controller,
11336                     // so distribute the scan time proportionately. This means regular traffic
11337                     // will not blamed, but scans are more expensive anyways.
11338                     scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
11339                 }
11340 
11341                 final ControllerActivityCounterImpl counter =
11342                         u.getOrCreateBluetoothControllerActivityLocked();
11343                 counter.getRxTimeCounter().addCountLocked(scanTimeRxSinceMarkMs);
11344                 counter.getTxTimeCounters()[0].addCountLocked(scanTimeTxSinceMarkMs);
11345 
11346                 leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
11347                 leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
11348             }
11349         }
11350 
11351         if (DEBUG_ENERGY) {
11352             Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX="
11353                     + leftOverTxTimeMs);
11354         }
11355 
11356         //
11357         // Now distribute blame to apps that did bluetooth traffic.
11358         //
11359 
11360         long totalTxBytes = 0;
11361         long totalRxBytes = 0;
11362 
11363         final UidTraffic[] uidTraffic = info.getUidTraffic();
11364         final int numUids = uidTraffic != null ? uidTraffic.length : 0;
11365         for (int i = 0; i < numUids; i++) {
11366             final UidTraffic traffic = uidTraffic[i];
11367             final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(
11368                     traffic.getUid());
11369             final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(
11370                     traffic.getUid());
11371 
11372             // Add to the global counters.
11373             mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(rxBytes);
11374             mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes);
11375 
11376             // Add to the UID counters.
11377             final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
11378             u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0);
11379             u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0);
11380 
11381             // Calculate the total traffic.
11382             totalRxBytes += rxBytes;
11383             totalTxBytes += txBytes;
11384         }
11385 
11386         if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0
11387                 || leftOverTxTimeMs != 0)) {
11388             for (int i = 0; i < numUids; i++) {
11389                 final UidTraffic traffic = uidTraffic[i];
11390                 final int uid = traffic.getUid();
11391                 final long rxBytes =
11392                         traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid);
11393                 final long txBytes =
11394                         traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid);
11395 
11396                 final Uid u = getUidStatsLocked(mapUid(uid));
11397                 final ControllerActivityCounterImpl counter =
11398                         u.getOrCreateBluetoothControllerActivityLocked();
11399 
11400                 if (totalRxBytes > 0 && rxBytes > 0) {
11401                     final long timeRxMs = (leftOverRxTimeMs * rxBytes) / totalRxBytes;
11402                     if (DEBUG_ENERGY) {
11403                         Slog.d(TAG, "UID=" + uid + " rx_bytes=" + rxBytes + " rx_time=" + timeRxMs);
11404                     }
11405                     counter.getRxTimeCounter().addCountLocked(timeRxMs);
11406                 }
11407 
11408                 if (totalTxBytes > 0 && txBytes > 0) {
11409                     final long timeTxMs = (leftOverTxTimeMs * txBytes) / totalTxBytes;
11410                     if (DEBUG_ENERGY) {
11411                         Slog.d(TAG, "UID=" + uid + " tx_bytes=" + txBytes + " tx_time=" + timeTxMs);
11412                     }
11413                     counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
11414                 }
11415             }
11416         }
11417 
11418         mBluetoothActivity.getRxTimeCounter().addCountLocked(rxTimeMs);
11419         mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(txTimeMs);
11420         mBluetoothActivity.getIdleTimeCounter().addCountLocked(idleTimeMs);
11421 
11422         // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11423         final double opVolt = mPowerProfile.getAveragePower(
11424                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11425         if (opVolt != 0) {
11426             // We store the power drain as mAms.
11427             mBluetoothActivity.getPowerCounter().addCountLocked(
11428                     (long) ((info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
11429                             / opVolt));
11430         }
11431         mLastBluetoothActivityInfo.set(info);
11432     }
11433 
11434     /**
11435      * Read and record Resource Power Manager (RPM) state and voter times.
11436      * If RPM stats were fetched more recently than RPM_STATS_UPDATE_FREQ_MS ago, uses the old data
11437      * instead of fetching it anew.
11438      */
updateRpmStatsLocked()11439     public void updateRpmStatsLocked() {
11440         if (mPlatformIdleStateCallback == null) return;
11441         long now = SystemClock.elapsedRealtime();
11442         if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
11443             mPlatformIdleStateCallback.fillLowPowerStats(mTmpRpmStats);
11444             mLastRpmStatsUpdateTimeMs = now;
11445         }
11446 
11447         for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate
11448                 : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) {
11449 
11450             // Update values for this platform state.
11451             final String pName = pstate.getKey();
11452             final long pTimeUs = pstate.getValue().mTimeMs * 1000;
11453             final int pCount = pstate.getValue().mCount;
11454             getRpmTimerLocked(pName).update(pTimeUs, pCount);
11455             if (SCREEN_OFF_RPM_STATS_ENABLED) {
11456                 getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount);
11457             }
11458 
11459             // Update values for each voter of this platform state.
11460             for (Map.Entry<String, RpmStats.PowerStateElement> voter
11461                     : pstate.getValue().mVoters.entrySet()) {
11462                 final String vName = pName + "." + voter.getKey();
11463                 final long vTimeUs = voter.getValue().mTimeMs * 1000;
11464                 final int vCount = voter.getValue().mCount;
11465                 getRpmTimerLocked(vName).update(vTimeUs, vCount);
11466                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
11467                     getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount);
11468                 }
11469             }
11470         }
11471 
11472         for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys
11473                 : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) {
11474 
11475             final String subsysName = subsys.getKey();
11476             for (Map.Entry<String, RpmStats.PowerStateElement> sstate
11477                     : subsys.getValue().mStates.entrySet()) {
11478                 final String name = subsysName + "." + sstate.getKey();
11479                 final long timeUs = sstate.getValue().mTimeMs * 1000;
11480                 final int count = sstate.getValue().mCount;
11481                 getRpmTimerLocked(name).update(timeUs, count);
11482                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
11483                     getScreenOffRpmTimerLocked(name).update(timeUs, count);
11484                 }
11485             }
11486         }
11487     }
11488 
11489     /**
11490      * Read and record Rail Energy data.
11491      */
updateRailStatsLocked()11492     public void updateRailStatsLocked() {
11493         if (mRailEnergyDataCallback == null || !mTmpRailStats.isRailStatsAvailable()) {
11494             return;
11495         }
11496         mRailEnergyDataCallback.fillRailDataStats(mTmpRailStats);
11497     }
11498 
11499     /**
11500      * Read and distribute kernel wake lock use across apps.
11501      */
updateKernelWakelocksLocked()11502     public void updateKernelWakelocksLocked() {
11503         final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
11504                 mTmpWakelockStats);
11505         if (wakelockStats == null) {
11506             // Not crashing might make board bringup easier.
11507             Slog.w(TAG, "Couldn't get kernel wake lock stats");
11508             return;
11509         }
11510 
11511         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
11512             String name = ent.getKey();
11513             KernelWakelockStats.Entry kws = ent.getValue();
11514 
11515             SamplingTimer kwlt = mKernelWakelockStats.get(name);
11516             if (kwlt == null) {
11517                 kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
11518                 mKernelWakelockStats.put(name, kwlt);
11519             }
11520 
11521             kwlt.update(kws.mTotalTime, kws.mCount);
11522             kwlt.setUpdateVersion(kws.mVersion);
11523         }
11524 
11525         int numWakelocksSetStale = 0;
11526         // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
11527         // this time.
11528         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
11529             SamplingTimer st = ent.getValue();
11530             if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
11531                 st.endSample();
11532                 numWakelocksSetStale++;
11533             }
11534         }
11535 
11536         // Record whether we've seen a non-zero time (for debugging b/22716723).
11537         if (wakelockStats.isEmpty()) {
11538             Slog.wtf(TAG, "All kernel wakelocks had time of zero");
11539         }
11540 
11541         if (numWakelocksSetStale == mKernelWakelockStats.size()) {
11542             Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
11543                     wakelockStats.kernelWakelockVersion);
11544         }
11545     }
11546 
11547     // We use an anonymous class to access these variables,
11548     // so they can't live on the stack or they'd have to be
11549     // final MutableLong objects (more allocations).
11550     // Used in updateCpuTimeLocked().
11551     long mTempTotalCpuUserTimeUs;
11552     long mTempTotalCpuSystemTimeUs;
11553     long[][] mWakeLockAllocationsUs;
11554 
11555     /**
11556      * Reads the newest memory stats from the kernel.
11557      */
updateKernelMemoryBandwidthLocked()11558     public void updateKernelMemoryBandwidthLocked() {
11559         mKernelMemoryBandwidthStats.updateStats();
11560         LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
11561         final int bandwidthEntryCount = bandwidthEntries.size();
11562         int index;
11563         for (int i = 0; i < bandwidthEntryCount; i++) {
11564             SamplingTimer timer;
11565             if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) {
11566                 timer = mKernelMemoryStats.valueAt(index);
11567             } else {
11568                 timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
11569                 mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
11570             }
11571             timer.update(bandwidthEntries.valueAt(i), 1);
11572             if (DEBUG_MEMORY) {
11573                 Slog.d(TAG, String.format("Added entry %d and updated timer to: "
11574                         + "mUnpluggedReportedTotalTime %d size %d", bandwidthEntries.keyAt(i),
11575                         mKernelMemoryStats.get(
11576                                 bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTime,
11577                         mKernelMemoryStats.size()));
11578             }
11579         }
11580     }
11581 
isOnBatteryLocked()11582     public boolean isOnBatteryLocked() {
11583         return mOnBatteryTimeBase.isRunning();
11584     }
11585 
isOnBatteryScreenOffLocked()11586     public boolean isOnBatteryScreenOffLocked() {
11587         return mOnBatteryScreenOffTimeBase.isRunning();
11588     }
11589 
11590     /**
11591      * Read and distribute CPU usage across apps. If their are partial wakelocks being held
11592      * and we are on battery with screen off, we give more of the cpu time to those apps holding
11593      * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
11594      * It's possible this will be invoked after the internal battery/screen states are updated, so
11595      * passing the appropriate battery/screen states to try attribute the cpu times to correct
11596      * buckets.
11597      */
11598     @GuardedBy("this")
updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff)11599     public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff) {
11600         if (mPowerProfile == null) {
11601             return;
11602         }
11603 
11604         if (DEBUG_ENERGY_CPU) {
11605             Slog.d(TAG, "!Cpu updating!");
11606         }
11607 
11608         if (mCpuFreqs == null) {
11609             mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
11610         }
11611 
11612         // Calculate the wakelocks we have to distribute amongst. The system is excluded as it is
11613         // usually holding the wakelock on behalf of an app.
11614         // And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
11615         ArrayList<StopwatchTimer> partialTimersToConsider = null;
11616         if (onBatteryScreenOff) {
11617             partialTimersToConsider = new ArrayList<>();
11618             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
11619                 final StopwatchTimer timer = mPartialTimers.get(i);
11620                 // Since the collection and blaming of wakelocks can be scheduled to run after
11621                 // some delay, the mPartialTimers list may have new entries. We can't blame
11622                 // the newly added timer for past cpu time, so we only consider timers that
11623                 // were present for one round of collection. Once a timer has gone through
11624                 // a round of collection, its mInList field is set to true.
11625                 if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
11626                     partialTimersToConsider.add(timer);
11627                 }
11628             }
11629         }
11630         markPartialTimersAsEligible();
11631 
11632         // When the battery is not on, we don't attribute the cpu times to any timers but we still
11633         // need to take the snapshots.
11634         if (!onBattery) {
11635             mCpuUidUserSysTimeReader.readDelta(null);
11636             mCpuUidFreqTimeReader.readDelta(null);
11637             mNumAllUidCpuTimeReads += 2;
11638             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
11639                 mCpuUidActiveTimeReader.readDelta(null);
11640                 mCpuUidClusterTimeReader.readDelta(null);
11641                 mNumAllUidCpuTimeReads += 2;
11642             }
11643             for (int cluster = mKernelCpuSpeedReaders.length - 1; cluster >= 0; --cluster) {
11644                 mKernelCpuSpeedReaders[cluster].readDelta();
11645             }
11646             return;
11647         }
11648 
11649         mUserInfoProvider.refreshUserIds();
11650         final SparseLongArray updatedUids = mCpuUidFreqTimeReader.perClusterTimesAvailable()
11651                 ? null : new SparseLongArray();
11652         readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
11653         // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
11654         // freqs, so no need to approximate these values.
11655         if (updatedUids != null) {
11656             updateClusterSpeedTimes(updatedUids, onBattery);
11657         }
11658         readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff);
11659         mNumAllUidCpuTimeReads += 2;
11660         if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
11661             readKernelUidCpuActiveTimesLocked(onBattery);
11662             readKernelUidCpuClusterTimesLocked(onBattery);
11663             mNumAllUidCpuTimeReads += 2;
11664         }
11665     }
11666 
11667     /**
11668      * Mark the current partial timers as gone through a collection so that they will be
11669      * considered in the next cpu times distribution to wakelock holders.
11670      */
11671     @VisibleForTesting
markPartialTimersAsEligible()11672     public void markPartialTimersAsEligible() {
11673         if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
11674             // No difference, so each timer is now considered for the next collection.
11675             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
11676                 mPartialTimers.get(i).mInList = true;
11677             }
11678         } else {
11679             // The lists are different, meaning we added (or removed a timer) since the last
11680             // collection.
11681             for (int i = mLastPartialTimers.size() - 1; i >= 0; --i) {
11682                 mLastPartialTimers.get(i).mInList = false;
11683             }
11684             mLastPartialTimers.clear();
11685 
11686             // Mark the current timers as gone through a collection.
11687             final int numPartialTimers = mPartialTimers.size();
11688             for (int i = 0; i < numPartialTimers; ++i) {
11689                 final StopwatchTimer timer = mPartialTimers.get(i);
11690                 timer.mInList = true;
11691                 mLastPartialTimers.add(timer);
11692             }
11693         }
11694     }
11695 
11696     /**
11697      * Take snapshot of cpu times (aggregated over all uids) at different frequencies and
11698      * calculate cpu times spent by each uid at different frequencies.
11699      *
11700      * @param updatedUids The uids for which times spent at different frequencies are calculated.
11701      */
11702     @VisibleForTesting
updateClusterSpeedTimes(@onNull SparseLongArray updatedUids, boolean onBattery)11703     public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery) {
11704         long totalCpuClustersTimeMs = 0;
11705         // Read the time spent for each cluster at various cpu frequencies.
11706         final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
11707         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
11708             clusterSpeedTimesMs[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
11709             if (clusterSpeedTimesMs[cluster] != null) {
11710                 for (int speed = clusterSpeedTimesMs[cluster].length - 1; speed >= 0; --speed) {
11711                     totalCpuClustersTimeMs += clusterSpeedTimesMs[cluster][speed];
11712                 }
11713             }
11714         }
11715         if (totalCpuClustersTimeMs != 0) {
11716             // We have cpu times per freq aggregated over all uids but we need the times per uid.
11717             // So, we distribute total time spent by an uid to different cpu freqs based on the
11718             // amount of time cpu was running at that freq.
11719             final int updatedUidsCount = updatedUids.size();
11720             for (int i = 0; i < updatedUidsCount; ++i) {
11721                 final Uid u = getUidStatsLocked(updatedUids.keyAt(i));
11722                 final long appCpuTimeUs = updatedUids.valueAt(i);
11723                 // Add the cpu speeds to this UID.
11724                 final int numClusters = mPowerProfile.getNumCpuClusters();
11725                 if (u.mCpuClusterSpeedTimesUs == null ||
11726                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
11727                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
11728                 }
11729 
11730                 for (int cluster = 0; cluster < clusterSpeedTimesMs.length; cluster++) {
11731                     final int speedsInCluster = clusterSpeedTimesMs[cluster].length;
11732                     if (u.mCpuClusterSpeedTimesUs[cluster] == null || speedsInCluster !=
11733                             u.mCpuClusterSpeedTimesUs[cluster].length) {
11734                         u.mCpuClusterSpeedTimesUs[cluster]
11735                                 = new LongSamplingCounter[speedsInCluster];
11736                     }
11737 
11738                     final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeedTimesUs[cluster];
11739                     for (int speed = 0; speed < speedsInCluster; speed++) {
11740                         if (cpuSpeeds[speed] == null) {
11741                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
11742                         }
11743                         cpuSpeeds[speed].addCountLocked(appCpuTimeUs
11744                                 * clusterSpeedTimesMs[cluster][speed]
11745                                 / totalCpuClustersTimeMs, onBattery);
11746                     }
11747                 }
11748             }
11749         }
11750     }
11751 
11752     /**
11753      * Take a snapshot of the cpu times spent by each uid and update the corresponding counters.
11754      * If {@param partialTimers} is not null and empty, then we assign a portion of cpu times to
11755      * wakelock holders.
11756      *
11757      * @param partialTimers The wakelock holders among which the cpu times will be distributed.
11758      * @param updatedUids If not null, then the uids found in the snapshot will be added to this.
11759      */
11760     @VisibleForTesting
readKernelUidCpuTimesLocked(@ullable ArrayList<StopwatchTimer> partialTimers, @Nullable SparseLongArray updatedUids, boolean onBattery)11761     public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
11762             @Nullable SparseLongArray updatedUids, boolean onBattery) {
11763         mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
11764         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
11765         final long startTimeMs = mClocks.uptimeMillis();
11766 
11767         mCpuUidUserSysTimeReader.readDelta((uid, timesUs) -> {
11768             long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
11769 
11770             uid = mapUid(uid);
11771             if (Process.isIsolated(uid)) {
11772                 // This could happen if the isolated uid mapping was removed before that process
11773                 // was actually killed.
11774                 mCpuUidUserSysTimeReader.removeUid(uid);
11775                 Slog.d(TAG, "Got readings for an isolated uid with no mapping: " + uid);
11776                 return;
11777             }
11778             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
11779                 Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
11780                 mCpuUidUserSysTimeReader.removeUid(uid);
11781                 return;
11782             }
11783             final Uid u = getUidStatsLocked(uid);
11784 
11785             // Accumulate the total system and user time.
11786             mTempTotalCpuUserTimeUs += userTimeUs;
11787             mTempTotalCpuSystemTimeUs += systemTimeUs;
11788 
11789             StringBuilder sb = null;
11790             if (DEBUG_ENERGY_CPU) {
11791                 sb = new StringBuilder();
11792                 sb.append("  got time for uid=").append(u.mUid).append(": u=");
11793                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
11794                 sb.append(" s=");
11795                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
11796                 sb.append("\n");
11797             }
11798 
11799             if (numWakelocks > 0) {
11800                 // We have wakelocks being held, so only give a portion of the
11801                 // time to the process. The rest will be distributed among wakelock
11802                 // holders.
11803                 userTimeUs = (userTimeUs * WAKE_LOCK_WEIGHT) / 100;
11804                 systemTimeUs = (systemTimeUs * WAKE_LOCK_WEIGHT) / 100;
11805             }
11806 
11807             if (sb != null) {
11808                 sb.append("  adding to uid=").append(u.mUid).append(": u=");
11809                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
11810                 sb.append(" s=");
11811                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
11812                 Slog.d(TAG, sb.toString());
11813             }
11814 
11815             u.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
11816             u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
11817             if (updatedUids != null) {
11818                 updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
11819             }
11820         });
11821 
11822         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
11823         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
11824             Slog.d(TAG, "Reading cpu stats took " + elapsedTimeMs + "ms");
11825         }
11826 
11827         if (numWakelocks > 0) {
11828             // Distribute a portion of the total cpu time to wakelock holders.
11829             mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
11830             mTempTotalCpuSystemTimeUs =
11831                     (mTempTotalCpuSystemTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
11832 
11833             for (int i = 0; i < numWakelocks; ++i) {
11834                 final StopwatchTimer timer = partialTimers.get(i);
11835                 final int userTimeUs = (int) (mTempTotalCpuUserTimeUs / (numWakelocks - i));
11836                 final int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / (numWakelocks - i));
11837 
11838                 if (DEBUG_ENERGY_CPU) {
11839                     final StringBuilder sb = new StringBuilder();
11840                     sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
11841                             .append(": u=");
11842                     TimeUtils.formatDuration(userTimeUs / 1000, sb);
11843                     sb.append(" s=");
11844                     TimeUtils.formatDuration(systemTimeUs / 1000, sb);
11845                     Slog.d(TAG, sb.toString());
11846                 }
11847 
11848                 timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
11849                 timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
11850                 if (updatedUids != null) {
11851                     final int uid = timer.mUid.getUid();
11852                     updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
11853                 }
11854 
11855                 final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
11856                 proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery);
11857 
11858                 mTempTotalCpuUserTimeUs -= userTimeUs;
11859                 mTempTotalCpuSystemTimeUs -= systemTimeUs;
11860             }
11861         }
11862     }
11863 
11864     /**
11865      * Take a snapshot of the cpu times spent by each uid in each freq and update the
11866      * corresponding counters.
11867      *
11868      * @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
11869      */
11870     @VisibleForTesting
readKernelUidCpuFreqTimesLocked(@ullable ArrayList<StopwatchTimer> partialTimers, boolean onBattery, boolean onBatteryScreenOff)11871     public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
11872             boolean onBattery, boolean onBatteryScreenOff) {
11873         final boolean perClusterTimesAvailable =
11874                 mCpuUidFreqTimeReader.perClusterTimesAvailable();
11875         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
11876         final int numClusters = mPowerProfile.getNumCpuClusters();
11877         mWakeLockAllocationsUs = null;
11878         final long startTimeMs = mClocks.uptimeMillis();
11879         mCpuUidFreqTimeReader.readDelta((uid, cpuFreqTimeMs) -> {
11880             uid = mapUid(uid);
11881             if (Process.isIsolated(uid)) {
11882                 mCpuUidFreqTimeReader.removeUid(uid);
11883                 Slog.d(TAG, "Got freq readings for an isolated uid with no mapping: " + uid);
11884                 return;
11885             }
11886             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
11887                 Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
11888                 mCpuUidFreqTimeReader.removeUid(uid);
11889                 return;
11890             }
11891             final Uid u = getUidStatsLocked(uid);
11892             if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
11893                 detachIfNotNull(u.mCpuFreqTimeMs);
11894                 u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
11895             }
11896             u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
11897             if (u.mScreenOffCpuFreqTimeMs == null ||
11898                     u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
11899                 detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
11900                 u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
11901                         mOnBatteryScreenOffTimeBase);
11902             }
11903             u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff);
11904 
11905             if (perClusterTimesAvailable) {
11906                 if (u.mCpuClusterSpeedTimesUs == null ||
11907                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
11908                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
11909                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
11910                 }
11911                 if (numWakelocks > 0 && mWakeLockAllocationsUs == null) {
11912                     mWakeLockAllocationsUs = new long[numClusters][];
11913                 }
11914 
11915                 int freqIndex = 0;
11916                 for (int cluster = 0; cluster < numClusters; ++cluster) {
11917                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
11918                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
11919                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
11920                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
11921                         u.mCpuClusterSpeedTimesUs[cluster]
11922                                 = new LongSamplingCounter[speedsInCluster];
11923                     }
11924                     if (numWakelocks > 0 && mWakeLockAllocationsUs[cluster] == null) {
11925                         mWakeLockAllocationsUs[cluster] = new long[speedsInCluster];
11926                     }
11927                     final LongSamplingCounter[] cpuTimesUs = u.mCpuClusterSpeedTimesUs[cluster];
11928                     for (int speed = 0; speed < speedsInCluster; ++speed) {
11929                         if (cpuTimesUs[speed] == null) {
11930                             cpuTimesUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
11931                         }
11932                         final long appAllocationUs;
11933                         if (mWakeLockAllocationsUs != null) {
11934                             appAllocationUs =
11935                                     (cpuFreqTimeMs[freqIndex] * 1000 * WAKE_LOCK_WEIGHT) / 100;
11936                             mWakeLockAllocationsUs[cluster][speed] +=
11937                                     (cpuFreqTimeMs[freqIndex] * 1000 - appAllocationUs);
11938                         } else {
11939                             appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
11940                         }
11941                         cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
11942                         freqIndex++;
11943                     }
11944                 }
11945             }
11946         });
11947 
11948         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
11949         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
11950             Slog.d(TAG, "Reading cpu freq times took " + elapsedTimeMs + "ms");
11951         }
11952 
11953         if (mWakeLockAllocationsUs != null) {
11954             for (int i = 0; i < numWakelocks; ++i) {
11955                 final Uid u = partialTimers.get(i).mUid;
11956                 if (u.mCpuClusterSpeedTimesUs == null ||
11957                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
11958                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
11959                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
11960                 }
11961 
11962                 for (int cluster = 0; cluster < numClusters; ++cluster) {
11963                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
11964                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
11965                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
11966                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
11967                         u.mCpuClusterSpeedTimesUs[cluster]
11968                                 = new LongSamplingCounter[speedsInCluster];
11969                     }
11970                     final LongSamplingCounter[] cpuTimeUs = u.mCpuClusterSpeedTimesUs[cluster];
11971                     for (int speed = 0; speed < speedsInCluster; ++speed) {
11972                         if (cpuTimeUs[speed] == null) {
11973                             cpuTimeUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
11974                         }
11975                         final long allocationUs =
11976                                 mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
11977                         cpuTimeUs[speed].addCountLocked(allocationUs, onBattery);
11978                         mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
11979                     }
11980                 }
11981             }
11982         }
11983     }
11984 
11985     /**
11986      * Take a snapshot of the cpu active times spent by each uid and update the corresponding
11987      * counters.
11988      */
11989     @VisibleForTesting
readKernelUidCpuActiveTimesLocked(boolean onBattery)11990     public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
11991         final long startTimeMs = mClocks.uptimeMillis();
11992         mCpuUidActiveTimeReader.readDelta((uid, cpuActiveTimesMs) -> {
11993             uid = mapUid(uid);
11994             if (Process.isIsolated(uid)) {
11995                 mCpuUidActiveTimeReader.removeUid(uid);
11996                 Slog.w(TAG, "Got active times for an isolated uid with no mapping: " + uid);
11997                 return;
11998             }
11999             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
12000                 Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
12001                 mCpuUidActiveTimeReader.removeUid(uid);
12002                 return;
12003             }
12004             final Uid u = getUidStatsLocked(uid);
12005             u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesMs, onBattery);
12006         });
12007 
12008         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
12009         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
12010             Slog.d(TAG, "Reading cpu active times took " + elapsedTimeMs + "ms");
12011         }
12012     }
12013 
12014     /**
12015      * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding
12016      * counters.
12017      */
12018     @VisibleForTesting
readKernelUidCpuClusterTimesLocked(boolean onBattery)12019     public void readKernelUidCpuClusterTimesLocked(boolean onBattery) {
12020         final long startTimeMs = mClocks.uptimeMillis();
12021         mCpuUidClusterTimeReader.readDelta((uid, cpuClusterTimesMs) -> {
12022             uid = mapUid(uid);
12023             if (Process.isIsolated(uid)) {
12024                 mCpuUidClusterTimeReader.removeUid(uid);
12025                 Slog.w(TAG, "Got cluster times for an isolated uid with no mapping: " + uid);
12026                 return;
12027             }
12028             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
12029                 Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
12030                 mCpuUidClusterTimeReader.removeUid(uid);
12031                 return;
12032             }
12033             final Uid u = getUidStatsLocked(uid);
12034             u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesMs, onBattery);
12035         });
12036 
12037         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
12038         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
12039             Slog.d(TAG, "Reading cpu cluster times took " + elapsedTimeMs + "ms");
12040         }
12041     }
12042 
setChargingLocked(boolean charging)12043     boolean setChargingLocked(boolean charging) {
12044         // if the device is no longer charging, remove the callback
12045         // if the device is now charging, it means that this is either called
12046         // 1. directly when level >= 90
12047         // 2. or from within the runnable that we deferred
12048         // For 1. if we have an existing callback, remove it, since we will immediately send a
12049         // ACTION_CHARGING
12050         // For 2. we remove existing callback so we don't send multiple ACTION_CHARGING
12051         mHandler.removeCallbacks(mDeferSetCharging);
12052         if (mCharging != charging) {
12053             mCharging = charging;
12054             if (charging) {
12055                 mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
12056             } else {
12057                 mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
12058             }
12059             mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
12060             return true;
12061         }
12062         return false;
12063     }
12064 
12065     @GuardedBy("this")
setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery, final int oldStatus, final int level, final int chargeUAh)12066     protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
12067             final boolean onBattery, final int oldStatus, final int level, final int chargeUAh) {
12068         boolean doWrite = false;
12069         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
12070         m.arg1 = onBattery ? 1 : 0;
12071         mHandler.sendMessage(m);
12072 
12073         final long uptime = mSecUptime * 1000;
12074         final long realtime = mSecRealtime * 1000;
12075         final int screenState = mScreenState;
12076         if (onBattery) {
12077             // We will reset our status if we are unplugging after the
12078             // battery was last full, or the level is at 100, or
12079             // we have gone through a significant charge (from a very low
12080             // level to a now very high level).
12081             boolean reset = false;
12082             if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
12083                     || level >= 90
12084                     || (mDischargeCurrentLevel < 20 && level >= 80))) {
12085                 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
12086                         + " dischargeLevel=" + mDischargeCurrentLevel
12087                         + " lowAmount=" + getLowDischargeAmountSinceCharge()
12088                         + " highAmount=" + getHighDischargeAmountSinceCharge());
12089                 // Before we write, collect a snapshot of the final aggregated
12090                 // stats to be reported in the next checkin.  Only do this if we have
12091                 // a sufficient amount of data to make it interesting.
12092                 if (getLowDischargeAmountSinceCharge() >= 20) {
12093                     final long startTime = SystemClock.uptimeMillis();
12094                     final Parcel parcel = Parcel.obtain();
12095                     writeSummaryToParcel(parcel, true);
12096                     final long initialTime = SystemClock.uptimeMillis() - startTime;
12097                     BackgroundThread.getHandler().post(new Runnable() {
12098                         @Override public void run() {
12099                             synchronized (mCheckinFile) {
12100                                 final long startTime2 = SystemClock.uptimeMillis();
12101                                 FileOutputStream stream = null;
12102                                 try {
12103                                     stream = mCheckinFile.startWrite();
12104                                     stream.write(parcel.marshall());
12105                                     stream.flush();
12106                                     mCheckinFile.finishWrite(stream);
12107                                     com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
12108                                             "batterystats-checkin",
12109                                             initialTime + SystemClock.uptimeMillis() - startTime2);
12110                                 } catch (IOException e) {
12111                                     Slog.w("BatteryStats",
12112                                             "Error writing checkin battery statistics", e);
12113                                     mCheckinFile.failWrite(stream);
12114                                 } finally {
12115                                     parcel.recycle();
12116                                 }
12117                             }
12118                         }
12119                     });
12120                 }
12121                 doWrite = true;
12122                 resetAllStatsLocked();
12123                 if (chargeUAh > 0 && level > 0) {
12124                     // Only use the reported coulomb charge value if it is supported and reported.
12125                     mEstimatedBatteryCapacity = (int) ((chargeUAh / 1000) / (level / 100.0));
12126                 }
12127                 mDischargeStartLevel = level;
12128                 reset = true;
12129                 mDischargeStepTracker.init();
12130             }
12131             if (mCharging) {
12132                 setChargingLocked(false);
12133             }
12134             mLastChargingStateLevel = level;
12135             mOnBattery = mOnBatteryInternal = true;
12136             mLastDischargeStepLevel = level;
12137             mMinDischargeStepLevel = level;
12138             mDischargeStepTracker.clearTime();
12139             mDailyDischargeStepTracker.clearTime();
12140             mInitStepMode = mCurStepMode;
12141             mModStepMode = 0;
12142             pullPendingStateUpdatesLocked();
12143             mHistoryCur.batteryLevel = (byte)level;
12144             mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12145             if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
12146                     + Integer.toHexString(mHistoryCur.states));
12147             if (reset) {
12148                 mRecordingHistory = true;
12149                 startRecordingHistory(mSecRealtime, mSecUptime, reset);
12150             }
12151             addHistoryRecordLocked(mSecRealtime, mSecUptime);
12152             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
12153             if (isScreenOn(screenState)) {
12154                 mDischargeScreenOnUnplugLevel = level;
12155                 mDischargeScreenDozeUnplugLevel = 0;
12156                 mDischargeScreenOffUnplugLevel = 0;
12157             } else if (isScreenDoze(screenState)) {
12158                 mDischargeScreenOnUnplugLevel = 0;
12159                 mDischargeScreenDozeUnplugLevel = level;
12160                 mDischargeScreenOffUnplugLevel = 0;
12161             } else {
12162                 mDischargeScreenOnUnplugLevel = 0;
12163                 mDischargeScreenDozeUnplugLevel = 0;
12164                 mDischargeScreenOffUnplugLevel = level;
12165             }
12166             mDischargeAmountScreenOn = 0;
12167             mDischargeAmountScreenDoze = 0;
12168             mDischargeAmountScreenOff = 0;
12169             updateTimeBasesLocked(true, screenState, uptime, realtime);
12170         } else {
12171             mLastChargingStateLevel = level;
12172             mOnBattery = mOnBatteryInternal = false;
12173             pullPendingStateUpdatesLocked();
12174             mHistoryCur.batteryLevel = (byte)level;
12175             mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12176             if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
12177                     + Integer.toHexString(mHistoryCur.states));
12178             addHistoryRecordLocked(mSecRealtime, mSecUptime);
12179             mDischargeCurrentLevel = mDischargePlugLevel = level;
12180             if (level < mDischargeUnplugLevel) {
12181                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
12182                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
12183             }
12184             updateDischargeScreenLevelsLocked(screenState, screenState);
12185             updateTimeBasesLocked(false, screenState, uptime, realtime);
12186             mChargeStepTracker.init();
12187             mLastChargeStepLevel = level;
12188             mMaxChargeStepLevel = level;
12189             mInitStepMode = mCurStepMode;
12190             mModStepMode = 0;
12191         }
12192         if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
12193             if (mStatsFile != null && mBatteryStatsHistory.getActiveFile() != null) {
12194                 writeAsyncLocked();
12195             }
12196         }
12197     }
12198 
startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs, boolean reset)12199     private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
12200             boolean reset) {
12201         mRecordingHistory = true;
12202         mHistoryCur.currentTime = System.currentTimeMillis();
12203         addHistoryBufferLocked(elapsedRealtimeMs,
12204                 reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
12205                 mHistoryCur);
12206         mHistoryCur.currentTime = 0;
12207         if (reset) {
12208             initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
12209         }
12210     }
12211 
recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs, final long uptimeMs)12212     private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
12213             final long uptimeMs) {
12214         if (mRecordingHistory) {
12215             mHistoryCur.currentTime = currentTime;
12216             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_CURRENT_TIME, mHistoryCur);
12217             mHistoryCur.currentTime = 0;
12218         }
12219     }
12220 
recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs)12221     private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
12222         if (mRecordingHistory) {
12223             mHistoryCur.currentTime = System.currentTimeMillis();
12224             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_SHUTDOWN, mHistoryCur);
12225             mHistoryCur.currentTime = 0;
12226         }
12227     }
12228 
scheduleSyncExternalStatsLocked(String reason, int updateFlags)12229     private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
12230         if (mExternalSync != null) {
12231             mExternalSync.scheduleSync(reason, updateFlags);
12232         }
12233     }
12234 
12235     // This should probably be exposed in the API, though it's not critical
12236     public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
12237 
12238     @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)12239     public void setBatteryStateLocked(final int status, final int health, final int plugType,
12240             final int level, /* not final */ int temp, final int volt, final int chargeUAh,
12241             final int chargeFullUAh, final long chargeTimeToFullSeconds) {
12242         // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
12243         temp = Math.max(0, temp);
12244 
12245         reportChangesToStatsLog(mHaveBatteryLevel ? mHistoryCur : null,
12246                 status, plugType, level);
12247 
12248         final boolean onBattery = isOnBattery(plugType, status);
12249         final long uptime = mClocks.uptimeMillis();
12250         final long elapsedRealtime = mClocks.elapsedRealtime();
12251         if (!mHaveBatteryLevel) {
12252             mHaveBatteryLevel = true;
12253             // We start out assuming that the device is plugged in (not
12254             // on battery).  If our first report is now that we are indeed
12255             // plugged in, then twiddle our state to correctly reflect that
12256             // since we won't be going through the full setOnBattery().
12257             if (onBattery == mOnBattery) {
12258                 if (onBattery) {
12259                     mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12260                 } else {
12261                     mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12262                 }
12263             }
12264             // Always start out assuming charging, that will be updated later.
12265             mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
12266             mHistoryCur.batteryStatus = (byte)status;
12267             mHistoryCur.batteryLevel = (byte)level;
12268             mHistoryCur.batteryChargeUAh = chargeUAh;
12269             mMaxChargeStepLevel = mMinDischargeStepLevel =
12270                     mLastChargeStepLevel = mLastDischargeStepLevel = level;
12271             mLastChargingStateLevel = level;
12272         } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
12273             recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
12274         }
12275         int oldStatus = mHistoryCur.batteryStatus;
12276         if (onBattery) {
12277             mDischargeCurrentLevel = level;
12278             if (!mRecordingHistory) {
12279                 mRecordingHistory = true;
12280                 startRecordingHistory(elapsedRealtime, uptime, true);
12281             }
12282         } else if (level < 96 &&
12283                 status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
12284             if (!mRecordingHistory) {
12285                 mRecordingHistory = true;
12286                 startRecordingHistory(elapsedRealtime, uptime, true);
12287             }
12288         }
12289         mCurrentBatteryLevel = level;
12290         if (mDischargePlugLevel < 0) {
12291             mDischargePlugLevel = level;
12292         }
12293 
12294         if (onBattery != mOnBattery) {
12295             mHistoryCur.batteryLevel = (byte)level;
12296             mHistoryCur.batteryStatus = (byte)status;
12297             mHistoryCur.batteryHealth = (byte)health;
12298             mHistoryCur.batteryPlugType = (byte)plugType;
12299             mHistoryCur.batteryTemperature = (short)temp;
12300             mHistoryCur.batteryVoltage = (char)volt;
12301             if (chargeUAh < mHistoryCur.batteryChargeUAh) {
12302                 // Only record discharges
12303                 final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
12304                 mDischargeCounter.addCountLocked(chargeDiff);
12305                 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
12306                 if (isScreenDoze(mScreenState)) {
12307                     mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
12308                 }
12309                 if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
12310                     mDischargeLightDozeCounter.addCountLocked(chargeDiff);
12311                 } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
12312                     mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
12313                 }
12314             }
12315             mHistoryCur.batteryChargeUAh = chargeUAh;
12316             setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level, chargeUAh);
12317         } else {
12318             boolean changed = false;
12319             if (mHistoryCur.batteryLevel != level) {
12320                 mHistoryCur.batteryLevel = (byte)level;
12321                 changed = true;
12322 
12323                 // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
12324                 // which will pull external stats.
12325                 mExternalSync.scheduleSyncDueToBatteryLevelChange(
12326                         mConstants.BATTERY_LEVEL_COLLECTION_DELAY_MS);
12327             }
12328             if (mHistoryCur.batteryStatus != status) {
12329                 mHistoryCur.batteryStatus = (byte)status;
12330                 changed = true;
12331             }
12332             if (mHistoryCur.batteryHealth != health) {
12333                 mHistoryCur.batteryHealth = (byte)health;
12334                 changed = true;
12335             }
12336             if (mHistoryCur.batteryPlugType != plugType) {
12337                 mHistoryCur.batteryPlugType = (byte)plugType;
12338                 changed = true;
12339             }
12340             if (temp >= (mHistoryCur.batteryTemperature+10)
12341                     || temp <= (mHistoryCur.batteryTemperature-10)) {
12342                 mHistoryCur.batteryTemperature = (short)temp;
12343                 changed = true;
12344             }
12345             if (volt > (mHistoryCur.batteryVoltage+20)
12346                     || volt < (mHistoryCur.batteryVoltage-20)) {
12347                 mHistoryCur.batteryVoltage = (char)volt;
12348                 changed = true;
12349             }
12350             if (chargeUAh >= (mHistoryCur.batteryChargeUAh+10)
12351                     || chargeUAh <= (mHistoryCur.batteryChargeUAh-10)) {
12352                 if (chargeUAh < mHistoryCur.batteryChargeUAh) {
12353                     // Only record discharges
12354                     final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
12355                     mDischargeCounter.addCountLocked(chargeDiff);
12356                     mDischargeScreenOffCounter.addCountLocked(chargeDiff);
12357                     if (isScreenDoze(mScreenState)) {
12358                         mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
12359                     }
12360                     if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
12361                         mDischargeLightDozeCounter.addCountLocked(chargeDiff);
12362                     } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
12363                         mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
12364                     }
12365                 }
12366                 mHistoryCur.batteryChargeUAh = chargeUAh;
12367                 changed = true;
12368             }
12369             long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
12370                     | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
12371                     | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
12372             if (onBattery) {
12373                 changed |= setChargingLocked(false);
12374                 if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
12375                     mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
12376                             modeBits, elapsedRealtime);
12377                     mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
12378                             modeBits, elapsedRealtime);
12379                     mLastDischargeStepLevel = level;
12380                     mMinDischargeStepLevel = level;
12381                     mInitStepMode = mCurStepMode;
12382                     mModStepMode = 0;
12383                 }
12384             } else {
12385                 if (level >= 90) {
12386                     // If the battery level is at least 90%, always consider the device to be
12387                     // charging even if it happens to go down a level.
12388                     changed |= setChargingLocked(true);
12389                 } else if (!mCharging) {
12390                     if (mLastChargeStepLevel < level) {
12391                         // We have not reported that we are charging, but the level has gone up,
12392                         // but we would like to not have tons of activity from charging-constraint
12393                         // jobs, so instead of reporting ACTION_CHARGING immediately, we defer it.
12394                         if (!mHandler.hasCallbacks(mDeferSetCharging)) {
12395                             mHandler.postDelayed(
12396                                     mDeferSetCharging,
12397                                     mConstants.BATTERY_CHARGED_DELAY_MS);
12398                         }
12399                     } else if (mLastChargeStepLevel > level) {
12400                         // if we had deferred a runnable due to charge level increasing, but then
12401                         // later the charge level drops (could be due to thermal issues), we don't
12402                         // want to trigger the deferred runnable, so remove it here
12403                         mHandler.removeCallbacks(mDeferSetCharging);
12404                     }
12405                 } else {
12406                     if (mLastChargeStepLevel > level) {
12407                         // We had reported that the device was charging, but here we are with
12408                         // power connected and the level going down.  Looks like the current
12409                         // power supplied isn't enough, so consider the device to now be
12410                         // discharging.
12411                         changed |= setChargingLocked(false);
12412                     }
12413                 }
12414                 if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
12415                     mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
12416                             modeBits, elapsedRealtime);
12417                     mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
12418                             modeBits, elapsedRealtime);
12419                     mMaxChargeStepLevel = level;
12420                     mInitStepMode = mCurStepMode;
12421                     mModStepMode = 0;
12422                 }
12423                 mLastChargeStepLevel = level;
12424             }
12425             if (changed) {
12426                 addHistoryRecordLocked(elapsedRealtime, uptime);
12427             }
12428         }
12429         if (!onBattery &&
12430                 (status == BatteryManager.BATTERY_STATUS_FULL ||
12431                         status == BatteryManager.BATTERY_STATUS_UNKNOWN)) {
12432             // We don't record history while we are plugged in and fully charged
12433             // (or when battery is not present).  The next time we are
12434             // unplugged, history will be cleared.
12435             mRecordingHistory = DEBUG;
12436         }
12437 
12438         if (mMinLearnedBatteryCapacity == -1) {
12439             mMinLearnedBatteryCapacity = chargeFullUAh;
12440         } else {
12441             mMinLearnedBatteryCapacity = Math.min(mMinLearnedBatteryCapacity, chargeFullUAh);
12442         }
12443         mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh);
12444 
12445         mBatteryTimeToFullSeconds = chargeTimeToFullSeconds;
12446     }
12447 
isOnBattery(int plugType, int status)12448     public static boolean isOnBattery(int plugType, int status) {
12449         return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN;
12450     }
12451 
12452     // Inform StatsLog of setBatteryState changes.
12453     // If this is the first reporting, pass in recentPast == null.
reportChangesToStatsLog(HistoryItem recentPast, final int status, final int plugType, final int level)12454     private void reportChangesToStatsLog(HistoryItem recentPast,
12455             final int status, final int plugType, final int level) {
12456 
12457         if (recentPast == null || recentPast.batteryStatus != status) {
12458             FrameworkStatsLog.write(FrameworkStatsLog.CHARGING_STATE_CHANGED, status);
12459         }
12460         if (recentPast == null || recentPast.batteryPlugType != plugType) {
12461             FrameworkStatsLog.write(FrameworkStatsLog.PLUGGED_STATE_CHANGED, plugType);
12462         }
12463         if (recentPast == null || recentPast.batteryLevel != level) {
12464             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_LEVEL_CHANGED, level);
12465         }
12466     }
12467 
12468     @UnsupportedAppUsage
getAwakeTimeBattery()12469     public long getAwakeTimeBattery() {
12470         // This previously evaluated to mOnBatteryTimeBase.getUptime(getBatteryUptimeLocked());
12471         // for over a decade, but surely that was a mistake.
12472         return getBatteryUptimeLocked();
12473     }
12474 
12475     @UnsupportedAppUsage
getAwakeTimePlugged()12476     public long getAwakeTimePlugged() {
12477         return (mClocks.uptimeMillis() * 1000) - getAwakeTimeBattery();
12478     }
12479 
12480     @Override
computeUptime(long curTime, int which)12481     public long computeUptime(long curTime, int which) {
12482         return mUptime + (curTime - mUptimeStart);
12483     }
12484 
12485     @Override
computeRealtime(long curTime, int which)12486     public long computeRealtime(long curTime, int which) {
12487         return mRealtime + (curTime - mRealtimeStart);
12488     }
12489 
12490     @Override
12491     @UnsupportedAppUsage
computeBatteryUptime(long curTime, int which)12492     public long computeBatteryUptime(long curTime, int which) {
12493         return mOnBatteryTimeBase.computeUptime(curTime, which);
12494     }
12495 
12496     @Override
12497     @UnsupportedAppUsage
computeBatteryRealtime(long curTime, int which)12498     public long computeBatteryRealtime(long curTime, int which) {
12499         return mOnBatteryTimeBase.computeRealtime(curTime, which);
12500     }
12501 
12502     @Override
computeBatteryScreenOffUptime(long curTime, int which)12503     public long computeBatteryScreenOffUptime(long curTime, int which) {
12504         return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
12505     }
12506 
12507     @Override
computeBatteryScreenOffRealtime(long curTime, int which)12508     public long computeBatteryScreenOffRealtime(long curTime, int which) {
12509         return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
12510     }
12511 
computeTimePerLevel(long[] steps, int numSteps)12512     private long computeTimePerLevel(long[] steps, int numSteps) {
12513         // For now we'll do a simple average across all steps.
12514         if (numSteps <= 0) {
12515             return -1;
12516         }
12517         long total = 0;
12518         for (int i=0; i<numSteps; i++) {
12519             total += steps[i] & STEP_LEVEL_TIME_MASK;
12520         }
12521         return total / numSteps;
12522         /*
12523         long[] buckets = new long[numSteps];
12524         int numBuckets = 0;
12525         int numToAverage = 4;
12526         int i = 0;
12527         while (i < numSteps) {
12528             long totalTime = 0;
12529             int num = 0;
12530             for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
12531                 totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
12532                 num++;
12533             }
12534             buckets[numBuckets] = totalTime / num;
12535             numBuckets++;
12536             numToAverage *= 2;
12537             i += num;
12538         }
12539         if (numBuckets < 1) {
12540             return -1;
12541         }
12542         long averageTime = buckets[numBuckets-1];
12543         for (i=numBuckets-2; i>=0; i--) {
12544             averageTime = (averageTime + buckets[i]) / 2;
12545         }
12546         return averageTime;
12547         */
12548     }
12549 
12550     @Override
12551     @UnsupportedAppUsage
computeBatteryTimeRemaining(long curTime)12552     public long computeBatteryTimeRemaining(long curTime) {
12553         if (!mOnBattery) {
12554             return -1;
12555         }
12556         /* Simple implementation just looks at the average discharge per level across the
12557            entire sample period.
12558         int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
12559         if (discharge < 2) {
12560             return -1;
12561         }
12562         long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
12563         if (duration < 1000*1000) {
12564             return -1;
12565         }
12566         long usPerLevel = duration/discharge;
12567         return usPerLevel * mCurrentBatteryLevel;
12568         */
12569         if (mDischargeStepTracker.mNumStepDurations < 1) {
12570             return -1;
12571         }
12572         long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
12573         if (msPerLevel <= 0) {
12574             return -1;
12575         }
12576         return (msPerLevel * mCurrentBatteryLevel) * 1000;
12577     }
12578 
12579     @Override
getDischargeLevelStepTracker()12580     public LevelStepTracker getDischargeLevelStepTracker() {
12581         return mDischargeStepTracker;
12582     }
12583 
12584     @Override
getDailyDischargeLevelStepTracker()12585     public LevelStepTracker getDailyDischargeLevelStepTracker() {
12586         return mDailyDischargeStepTracker;
12587     }
12588 
12589     @Override
computeChargeTimeRemaining(long curTime)12590     public long computeChargeTimeRemaining(long curTime) {
12591         if (mOnBattery) {
12592             // Not yet working.
12593             return -1;
12594         }
12595         if (mBatteryTimeToFullSeconds >= 0) {
12596             return mBatteryTimeToFullSeconds * (1000 * 1000); // s to us
12597         }
12598         // Else use algorithmic approach
12599         if (mChargeStepTracker.mNumStepDurations < 1) {
12600             return -1;
12601         }
12602         long msPerLevel = mChargeStepTracker.computeTimePerLevel();
12603         if (msPerLevel <= 0) {
12604             return -1;
12605         }
12606         return (msPerLevel * (100 - mCurrentBatteryLevel)) * 1000;
12607     }
12608 
12609     /*@hide */
getCellularBatteryStats()12610     public CellularBatteryStats getCellularBatteryStats() {
12611         final int which = STATS_SINCE_CHARGED;
12612         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
12613         final ControllerActivityCounter counter = getModemControllerActivity();
12614         final long sleepTimeMs = counter.getSleepTimeCounter().getCountLocked(which);
12615         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
12616         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
12617         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
12618         final long monitoredRailChargeConsumedMaMs =
12619                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
12620         long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
12621         for (int i = 0; i < timeInRatMs.length; i++) {
12622            timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTime, which) / 1000;
12623         }
12624         long[] timeInRxSignalStrengthLevelMs =
12625                 new long[CellSignalStrength.getNumSignalStrengthLevels()];
12626         for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
12627            timeInRxSignalStrengthLevelMs[i]
12628                = getPhoneSignalStrengthTime(i, rawRealTime, which) / 1000;
12629         }
12630         long[] txTimeMs = new long[Math.min(ModemActivityInfo.TX_POWER_LEVELS,
12631             counter.getTxTimeCounters().length)];
12632         long totalTxTimeMs = 0;
12633         for (int i = 0; i < txTimeMs.length; i++) {
12634             txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
12635             totalTxTimeMs += txTimeMs[i];
12636         }
12637 
12638         return new CellularBatteryStats(computeBatteryRealtime(rawRealTime, which) / 1000,
12639                 getMobileRadioActiveTime(rawRealTime, which) / 1000,
12640                 getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which),
12641                 getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which),
12642                 getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which),
12643                 getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which),
12644                 sleepTimeMs, idleTimeMs, rxTimeMs, energyConsumedMaMs, timeInRatMs,
12645                 timeInRxSignalStrengthLevelMs, txTimeMs,
12646                 monitoredRailChargeConsumedMaMs);
12647     }
12648 
12649     /*@hide */
getWifiBatteryStats()12650     public WifiBatteryStats getWifiBatteryStats() {
12651         final int which = STATS_SINCE_CHARGED;
12652         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
12653         final ControllerActivityCounter counter = getWifiControllerActivity();
12654         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
12655         final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which);
12656         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
12657         final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which);
12658         final long totalControllerActivityTimeMs
12659                 = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000;
12660         final long sleepTimeMs
12661                 = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs);
12662         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
12663         final long monitoredRailChargeConsumedMaMs =
12664                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
12665         long numAppScanRequest = 0;
12666         for (int i = 0; i < mUidStats.size(); i++) {
12667             numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which);
12668         }
12669         long[] timeInStateMs = new long[NUM_WIFI_STATES];
12670         for (int i=0; i<NUM_WIFI_STATES; i++) {
12671             timeInStateMs[i] = getWifiStateTime(i, rawRealTime, which) / 1000;
12672         }
12673         long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES];
12674         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
12675             timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTime, which) / 1000;
12676         }
12677         long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS];
12678         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
12679             timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTime, which) / 1000;
12680         }
12681         return new WifiBatteryStats(
12682                 computeBatteryRealtime(rawRealTime, which) / 1000,
12683                 getWifiActiveTime(rawRealTime, which) / 1000,
12684                 getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which),
12685                 getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which),
12686                 getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which),
12687                 getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which),
12688                 sleepTimeMs, scanTimeMs, idleTimeMs, rxTimeMs, txTimeMs, energyConsumedMaMs,
12689                 numAppScanRequest, timeInStateMs, timeSignalStrengthTimeMs, timeInSupplStateMs,
12690                 monitoredRailChargeConsumedMaMs);
12691     }
12692 
12693     /*@hide */
getGpsBatteryStats()12694     public GpsBatteryStats getGpsBatteryStats() {
12695         GpsBatteryStats s = new GpsBatteryStats();
12696         final int which = STATS_SINCE_CHARGED;
12697         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
12698         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
12699         s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
12700         long[] time = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
12701         for (int i=0; i<time.length; i++) {
12702             time[i] = getGpsSignalQualityTime(i, rawRealTime, which) / 1000;
12703         }
12704         s.setTimeInGpsSignalQualityLevel(time);
12705         return s;
12706     }
12707 
12708     @Override
getChargeLevelStepTracker()12709     public LevelStepTracker getChargeLevelStepTracker() {
12710         return mChargeStepTracker;
12711     }
12712 
12713     @Override
getDailyChargeLevelStepTracker()12714     public LevelStepTracker getDailyChargeLevelStepTracker() {
12715         return mDailyChargeStepTracker;
12716     }
12717 
12718     @Override
getDailyPackageChanges()12719     public ArrayList<PackageChange> getDailyPackageChanges() {
12720         return mDailyPackageChanges;
12721     }
12722 
getBatteryUptimeLocked()12723     protected long getBatteryUptimeLocked() {
12724         return mOnBatteryTimeBase.getUptime(mClocks.uptimeMillis() * 1000);
12725     }
12726 
12727     @Override
getBatteryUptime(long curTime)12728     public long getBatteryUptime(long curTime) {
12729         return mOnBatteryTimeBase.getUptime(curTime);
12730     }
12731 
12732     @Override
12733     @UnsupportedAppUsage
getBatteryRealtime(long curTime)12734     public long getBatteryRealtime(long curTime) {
12735         return mOnBatteryTimeBase.getRealtime(curTime);
12736     }
12737 
12738     @Override
12739     @UnsupportedAppUsage
getDischargeStartLevel()12740     public int getDischargeStartLevel() {
12741         synchronized(this) {
12742             return getDischargeStartLevelLocked();
12743         }
12744     }
12745 
getDischargeStartLevelLocked()12746     public int getDischargeStartLevelLocked() {
12747             return mDischargeUnplugLevel;
12748     }
12749 
12750     @Override
12751     @UnsupportedAppUsage
getDischargeCurrentLevel()12752     public int getDischargeCurrentLevel() {
12753         synchronized(this) {
12754             return getDischargeCurrentLevelLocked();
12755         }
12756     }
12757 
getDischargeCurrentLevelLocked()12758     public int getDischargeCurrentLevelLocked() {
12759         return mDischargeCurrentLevel;
12760     }
12761 
12762     @Override
getLowDischargeAmountSinceCharge()12763     public int getLowDischargeAmountSinceCharge() {
12764         synchronized(this) {
12765             int val = mLowDischargeAmountSinceCharge;
12766             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
12767                 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
12768             }
12769             return val;
12770         }
12771     }
12772 
12773     @Override
getHighDischargeAmountSinceCharge()12774     public int getHighDischargeAmountSinceCharge() {
12775         synchronized(this) {
12776             int val = mHighDischargeAmountSinceCharge;
12777             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
12778                 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
12779             }
12780             return val;
12781         }
12782     }
12783 
12784     @Override
12785     @UnsupportedAppUsage
getDischargeAmount(int which)12786     public int getDischargeAmount(int which) {
12787         int dischargeAmount = which == STATS_SINCE_CHARGED
12788                 ? getHighDischargeAmountSinceCharge()
12789                 : (getDischargeStartLevel() - getDischargeCurrentLevel());
12790         if (dischargeAmount < 0) {
12791             dischargeAmount = 0;
12792         }
12793         return dischargeAmount;
12794     }
12795 
12796     @Override
12797     @UnsupportedAppUsage
getDischargeAmountScreenOn()12798     public int getDischargeAmountScreenOn() {
12799         synchronized(this) {
12800             int val = mDischargeAmountScreenOn;
12801             if (mOnBattery && isScreenOn(mScreenState)
12802                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
12803                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
12804             }
12805             return val;
12806         }
12807     }
12808 
12809     @Override
getDischargeAmountScreenOnSinceCharge()12810     public int getDischargeAmountScreenOnSinceCharge() {
12811         synchronized(this) {
12812             int val = mDischargeAmountScreenOnSinceCharge;
12813             if (mOnBattery && isScreenOn(mScreenState)
12814                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
12815                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
12816             }
12817             return val;
12818         }
12819     }
12820 
12821     @Override
12822     @UnsupportedAppUsage
getDischargeAmountScreenOff()12823     public int getDischargeAmountScreenOff() {
12824         synchronized(this) {
12825             int val = mDischargeAmountScreenOff;
12826             if (mOnBattery && isScreenOff(mScreenState)
12827                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
12828                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
12829             }
12830             // For backward compatibility, doze discharge is counted into screen off.
12831             return val + getDischargeAmountScreenDoze();
12832         }
12833     }
12834 
12835     @Override
getDischargeAmountScreenOffSinceCharge()12836     public int getDischargeAmountScreenOffSinceCharge() {
12837         synchronized(this) {
12838             int val = mDischargeAmountScreenOffSinceCharge;
12839             if (mOnBattery && isScreenOff(mScreenState)
12840                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
12841                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
12842             }
12843             // For backward compatibility, doze discharge is counted into screen off.
12844             return val + getDischargeAmountScreenDozeSinceCharge();
12845         }
12846     }
12847 
12848     @Override
getDischargeAmountScreenDoze()12849     public int getDischargeAmountScreenDoze() {
12850         synchronized(this) {
12851             int val = mDischargeAmountScreenDoze;
12852             if (mOnBattery && isScreenDoze(mScreenState)
12853                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
12854                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
12855             }
12856             return val;
12857         }
12858     }
12859 
12860     @Override
getDischargeAmountScreenDozeSinceCharge()12861     public int getDischargeAmountScreenDozeSinceCharge() {
12862         synchronized(this) {
12863             int val = mDischargeAmountScreenDozeSinceCharge;
12864             if (mOnBattery && isScreenDoze(mScreenState)
12865                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
12866                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
12867             }
12868             return val;
12869         }
12870     }
12871 
12872     /**
12873      * Retrieve the statistics object for a particular uid, creating if needed.
12874      */
12875     @UnsupportedAppUsage
getUidStatsLocked(int uid)12876     public Uid getUidStatsLocked(int uid) {
12877         Uid u = mUidStats.get(uid);
12878         if (u == null) {
12879             u = new Uid(this, uid);
12880             mUidStats.put(uid, u);
12881         }
12882         return u;
12883     }
12884 
12885     /**
12886      * Retrieve the statistics object for a particular uid. Returns null if the object is not
12887      * available.
12888      */
getAvailableUidStatsLocked(int uid)12889     public Uid getAvailableUidStatsLocked(int uid) {
12890         Uid u = mUidStats.get(uid);
12891         return u;
12892     }
12893 
onCleanupUserLocked(int userId)12894     public void onCleanupUserLocked(int userId) {
12895         final int firstUidForUser = UserHandle.getUid(userId, 0);
12896         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
12897         mPendingRemovedUids.add(
12898                 new UidToRemove(firstUidForUser, lastUidForUser, mClocks.elapsedRealtime()));
12899     }
12900 
onUserRemovedLocked(int userId)12901     public void onUserRemovedLocked(int userId) {
12902         final int firstUidForUser = UserHandle.getUid(userId, 0);
12903         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
12904         mUidStats.put(firstUidForUser, null);
12905         mUidStats.put(lastUidForUser, null);
12906         final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
12907         final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
12908         for (int i = firstIndex; i <= lastIndex; i++) {
12909             final Uid uid = mUidStats.valueAt(i);
12910             if (uid != null) {
12911                 uid.detachFromTimeBase();
12912             }
12913         }
12914         mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
12915     }
12916 
12917     /**
12918      * Remove the statistics object for a particular uid.
12919      */
12920     @UnsupportedAppUsage
removeUidStatsLocked(int uid)12921     public void removeUidStatsLocked(int uid) {
12922         final Uid u = mUidStats.get(uid);
12923         if (u != null) {
12924             u.detachFromTimeBase();
12925         }
12926         mUidStats.remove(uid);
12927         mPendingRemovedUids.add(new UidToRemove(uid, mClocks.elapsedRealtime()));
12928     }
12929 
12930     /**
12931      * Retrieve the statistics object for a particular process, creating
12932      * if needed.
12933      */
12934     @UnsupportedAppUsage
getProcessStatsLocked(int uid, String name)12935     public Uid.Proc getProcessStatsLocked(int uid, String name) {
12936         uid = mapUid(uid);
12937         Uid u = getUidStatsLocked(uid);
12938         return u.getProcessStatsLocked(name);
12939     }
12940 
12941     /**
12942      * Retrieve the statistics object for a particular process, creating
12943      * if needed.
12944      */
12945     @UnsupportedAppUsage
getPackageStatsLocked(int uid, String pkg)12946     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
12947         uid = mapUid(uid);
12948         Uid u = getUidStatsLocked(uid);
12949         return u.getPackageStatsLocked(pkg);
12950     }
12951 
12952     /**
12953      * Retrieve the statistics object for a particular service, creating
12954      * if needed.
12955      */
12956     @UnsupportedAppUsage
getServiceStatsLocked(int uid, String pkg, String name)12957     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
12958         uid = mapUid(uid);
12959         Uid u = getUidStatsLocked(uid);
12960         return u.getServiceStatsLocked(pkg, name);
12961     }
12962 
shutdownLocked()12963     public void shutdownLocked() {
12964         recordShutdownLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
12965         writeSyncLocked();
12966         mShuttingDown = true;
12967     }
12968 
trackPerProcStateCpuTimes()12969     public boolean trackPerProcStateCpuTimes() {
12970         return mConstants.TRACK_CPU_TIMES_BY_PROC_STATE && mPerProcStateCpuTimesAvailable;
12971     }
12972 
systemServicesReady(Context context)12973     public void systemServicesReady(Context context) {
12974         mConstants.startObserving(context.getContentResolver());
12975         registerUsbStateReceiver(context);
12976     }
12977 
12978     @VisibleForTesting
12979     public final class Constants extends ContentObserver {
12980         public static final String KEY_TRACK_CPU_TIMES_BY_PROC_STATE
12981                 = "track_cpu_times_by_proc_state";
12982         public static final String KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME
12983                 = "track_cpu_active_cluster_time";
12984         public static final String KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS
12985                 = "proc_state_cpu_times_read_delay_ms";
12986         public static final String KEY_KERNEL_UID_READERS_THROTTLE_TIME
12987                 = "kernel_uid_readers_throttle_time";
12988         public static final String KEY_UID_REMOVE_DELAY_MS
12989                 = "uid_remove_delay_ms";
12990         public static final String KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
12991                 = "external_stats_collection_rate_limit_ms";
12992         public static final String KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS
12993                 = "battery_level_collection_delay_ms";
12994         public static final String KEY_MAX_HISTORY_FILES = "max_history_files";
12995         public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
12996         public static final String KEY_BATTERY_CHARGED_DELAY_MS =
12997                 "battery_charged_delay_ms";
12998 
12999         private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = false;
13000         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
13001         private static final long DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS = 5_000;
13002         private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000;
13003         private static final long DEFAULT_UID_REMOVE_DELAY_MS = 5L * 60L * 1000L;
13004         private static final long DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = 600_000;
13005         private static final long DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS = 300_000;
13006         private static final int DEFAULT_MAX_HISTORY_FILES = 32;
13007         private static final int DEFAULT_MAX_HISTORY_BUFFER_KB = 128; /*Kilo Bytes*/
13008         private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64;
13009         private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
13010         private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
13011 
13012         public boolean TRACK_CPU_TIMES_BY_PROC_STATE = DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE;
13013         public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
13014         public long PROC_STATE_CPU_TIMES_READ_DELAY_MS = DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS;
13015         /* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
13016          * update when startObserving. */
13017         public long KERNEL_UID_READERS_THROTTLE_TIME;
13018         public long UID_REMOVE_DELAY_MS = DEFAULT_UID_REMOVE_DELAY_MS;
13019         public long EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
13020                 = DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
13021         public long BATTERY_LEVEL_COLLECTION_DELAY_MS
13022                 = DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS;
13023         public int MAX_HISTORY_FILES;
13024         public int MAX_HISTORY_BUFFER; /*Bytes*/
13025         public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
13026 
13027         private ContentResolver mResolver;
13028         private final KeyValueListParser mParser = new KeyValueListParser(',');
13029 
Constants(Handler handler)13030         public Constants(Handler handler) {
13031             super(handler);
13032             if (ActivityManager.isLowRamDeviceStatic()) {
13033                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE;
13034                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB * 1024;
13035             } else {
13036                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES;
13037                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_KB * 1024;
13038             }
13039         }
13040 
startObserving(ContentResolver resolver)13041         public void startObserving(ContentResolver resolver) {
13042             mResolver = resolver;
13043             mResolver.registerContentObserver(
13044                     Settings.Global.getUriFor(Settings.Global.BATTERY_STATS_CONSTANTS),
13045                     false /* notifyForDescendants */, this);
13046             mResolver.registerContentObserver(
13047                     Settings.Global.getUriFor(Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY),
13048                     false /* notifyForDescendants */, this);
13049             updateConstants();
13050         }
13051 
13052         @Override
onChange(boolean selfChange, Uri uri)13053         public void onChange(boolean selfChange, Uri uri) {
13054             if (uri.equals(
13055                     Settings.Global.getUriFor(
13056                             Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY))) {
13057                 synchronized (BatteryStatsImpl.this) {
13058                     updateBatteryChargedDelayMsLocked();
13059                 }
13060                 return;
13061             }
13062             updateConstants();
13063         }
13064 
updateConstants()13065         private void updateConstants() {
13066             synchronized (BatteryStatsImpl.this) {
13067                 try {
13068                     mParser.setString(Settings.Global.getString(mResolver,
13069                             Settings.Global.BATTERY_STATS_CONSTANTS));
13070                 } catch (IllegalArgumentException e) {
13071                     // Failed to parse the settings string, log this and move on
13072                     // with defaults.
13073                     Slog.e(TAG, "Bad batterystats settings", e);
13074                 }
13075 
13076                 updateTrackCpuTimesByProcStateLocked(TRACK_CPU_TIMES_BY_PROC_STATE,
13077                         mParser.getBoolean(KEY_TRACK_CPU_TIMES_BY_PROC_STATE,
13078                                 DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE));
13079                 TRACK_CPU_ACTIVE_CLUSTER_TIME = mParser.getBoolean(
13080                         KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME, DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME);
13081                 updateProcStateCpuTimesReadDelayMs(PROC_STATE_CPU_TIMES_READ_DELAY_MS,
13082                         mParser.getLong(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS,
13083                                 DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS));
13084                 updateKernelUidReadersThrottleTime(KERNEL_UID_READERS_THROTTLE_TIME,
13085                         mParser.getLong(KEY_KERNEL_UID_READERS_THROTTLE_TIME,
13086                                 DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME));
13087                 updateUidRemoveDelay(
13088                         mParser.getLong(KEY_UID_REMOVE_DELAY_MS, DEFAULT_UID_REMOVE_DELAY_MS));
13089                 EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = mParser.getLong(
13090                         KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS,
13091                         DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
13092                 BATTERY_LEVEL_COLLECTION_DELAY_MS = mParser.getLong(
13093                         KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS,
13094                         DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS);
13095 
13096                 MAX_HISTORY_FILES = mParser.getInt(KEY_MAX_HISTORY_FILES,
13097                         ActivityManager.isLowRamDeviceStatic() ?
13098                                 DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE
13099                         : DEFAULT_MAX_HISTORY_FILES);
13100                 MAX_HISTORY_BUFFER = mParser.getInt(KEY_MAX_HISTORY_BUFFER_KB,
13101                         ActivityManager.isLowRamDeviceStatic() ?
13102                                 DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB
13103                                 : DEFAULT_MAX_HISTORY_BUFFER_KB)
13104                         * 1024;
13105                 updateBatteryChargedDelayMsLocked();
13106             }
13107         }
13108 
updateBatteryChargedDelayMsLocked()13109         private void updateBatteryChargedDelayMsLocked() {
13110             // a negative value indicates that we should ignore this override
13111             final int delay = Settings.Global.getInt(mResolver,
13112                     Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
13113                     -1);
13114 
13115             BATTERY_CHARGED_DELAY_MS = delay >= 0 ? delay : mParser.getInt(
13116                     KEY_BATTERY_CHARGED_DELAY_MS,
13117                     DEFAULT_BATTERY_CHARGED_DELAY_MS);
13118         }
13119 
updateTrackCpuTimesByProcStateLocked(boolean wasEnabled, boolean isEnabled)13120         private void updateTrackCpuTimesByProcStateLocked(boolean wasEnabled, boolean isEnabled) {
13121             TRACK_CPU_TIMES_BY_PROC_STATE = isEnabled;
13122             if (isEnabled && !wasEnabled) {
13123                 mIsPerProcessStateCpuDataStale = true;
13124                 mExternalSync.scheduleCpuSyncDueToSettingChange();
13125 
13126                 mNumSingleUidCpuTimeReads = 0;
13127                 mNumBatchedSingleUidCpuTimeReads = 0;
13128                 mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
13129             }
13130         }
13131 
updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis)13132         private void updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis) {
13133             PROC_STATE_CPU_TIMES_READ_DELAY_MS = newDelayMillis;
13134             if (oldDelayMillis != newDelayMillis) {
13135                 mNumSingleUidCpuTimeReads = 0;
13136                 mNumBatchedSingleUidCpuTimeReads = 0;
13137                 mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
13138             }
13139         }
13140 
updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs)13141         private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
13142             KERNEL_UID_READERS_THROTTLE_TIME = newTimeMs;
13143             if (oldTimeMs != newTimeMs) {
13144                 mCpuUidUserSysTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
13145                 mCpuUidFreqTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
13146                 mCpuUidActiveTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
13147                 mCpuUidClusterTimeReader
13148                         .setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
13149             }
13150         }
13151 
updateUidRemoveDelay(long newTimeMs)13152         private void updateUidRemoveDelay(long newTimeMs) {
13153             UID_REMOVE_DELAY_MS = newTimeMs;
13154             clearPendingRemovedUids();
13155         }
13156 
dumpLocked(PrintWriter pw)13157         public void dumpLocked(PrintWriter pw) {
13158             pw.print(KEY_TRACK_CPU_TIMES_BY_PROC_STATE); pw.print("=");
13159             pw.println(TRACK_CPU_TIMES_BY_PROC_STATE);
13160             pw.print(KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME); pw.print("=");
13161             pw.println(TRACK_CPU_ACTIVE_CLUSTER_TIME);
13162             pw.print(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS); pw.print("=");
13163             pw.println(PROC_STATE_CPU_TIMES_READ_DELAY_MS);
13164             pw.print(KEY_KERNEL_UID_READERS_THROTTLE_TIME); pw.print("=");
13165             pw.println(KERNEL_UID_READERS_THROTTLE_TIME);
13166             pw.print(KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS); pw.print("=");
13167             pw.println(EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
13168             pw.print(KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS); pw.print("=");
13169             pw.println(BATTERY_LEVEL_COLLECTION_DELAY_MS);
13170             pw.print(KEY_MAX_HISTORY_FILES); pw.print("=");
13171             pw.println(MAX_HISTORY_FILES);
13172             pw.print(KEY_MAX_HISTORY_BUFFER_KB); pw.print("=");
13173             pw.println(MAX_HISTORY_BUFFER/1024);
13174             pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("=");
13175             pw.println(BATTERY_CHARGED_DELAY_MS);
13176         }
13177     }
13178 
getExternalStatsCollectionRateLimitMs()13179     public long getExternalStatsCollectionRateLimitMs() {
13180         synchronized (this) {
13181             return mConstants.EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
13182         }
13183     }
13184 
13185     @GuardedBy("this")
dumpConstantsLocked(PrintWriter pw)13186     public void dumpConstantsLocked(PrintWriter pw) {
13187         mConstants.dumpLocked(pw);
13188     }
13189 
13190     @GuardedBy("this")
dumpCpuStatsLocked(PrintWriter pw)13191     public void dumpCpuStatsLocked(PrintWriter pw) {
13192         int size = mUidStats.size();
13193         pw.println("Per UID CPU user & system time in ms:");
13194         for (int i = 0; i < size; i++) {
13195             int u = mUidStats.keyAt(i);
13196             Uid uid = mUidStats.get(u);
13197             pw.print("  "); pw.print(u); pw.print(": ");
13198             pw.print(uid.getUserCpuTimeUs(STATS_SINCE_CHARGED) / 1000); pw.print(" ");
13199             pw.println(uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED) / 1000);
13200         }
13201         pw.println("Per UID CPU active time in ms:");
13202         for (int i = 0; i < size; i++) {
13203             int u = mUidStats.keyAt(i);
13204             Uid uid = mUidStats.get(u);
13205             if (uid.getCpuActiveTime() > 0) {
13206                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(uid.getCpuActiveTime());
13207             }
13208         }
13209         pw.println("Per UID CPU cluster time in ms:");
13210         for (int i = 0; i < size; i++) {
13211             int u = mUidStats.keyAt(i);
13212             long[] times = mUidStats.get(u).getCpuClusterTimes();
13213             if (times != null) {
13214                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
13215             }
13216         }
13217         pw.println("Per UID CPU frequency time in ms:");
13218         for (int i = 0; i < size; i++) {
13219             int u = mUidStats.keyAt(i);
13220             long[] times = mUidStats.get(u).getCpuFreqTimes(STATS_SINCE_CHARGED);
13221             if (times != null) {
13222                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
13223             }
13224         }
13225     }
13226 
13227     final ReentrantLock mWriteLock = new ReentrantLock();
13228 
writeAsyncLocked()13229     public void writeAsyncLocked() {
13230         writeStatsLocked(false);
13231         writeHistoryLocked(false);
13232     }
13233 
writeSyncLocked()13234     public void writeSyncLocked() {
13235         writeStatsLocked(true);
13236         writeHistoryLocked(true);
13237     }
13238 
writeStatsLocked(boolean sync)13239     void writeStatsLocked(boolean sync) {
13240         if (mStatsFile == null) {
13241             Slog.w(TAG,
13242                     "writeStatsLocked: no file associated with this instance");
13243             return;
13244         }
13245 
13246         if (mShuttingDown) {
13247             return;
13248         }
13249 
13250         final Parcel p = Parcel.obtain();
13251         final long start = SystemClock.uptimeMillis();
13252         writeSummaryToParcel(p, false/*history is in separate file*/);
13253         if (DEBUG) {
13254             Slog.d(TAG, "writeSummaryToParcel duration ms:"
13255                     + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
13256         }
13257         mLastWriteTime = mClocks.elapsedRealtime();
13258         writeParcelToFileLocked(p, mStatsFile, sync);
13259     }
13260 
writeHistoryLocked(boolean sync)13261     void writeHistoryLocked(boolean sync) {
13262         if (mBatteryStatsHistory.getActiveFile() == null) {
13263             Slog.w(TAG,
13264                     "writeHistoryLocked: no history file associated with this instance");
13265             return;
13266         }
13267 
13268         if (mShuttingDown) {
13269             return;
13270         }
13271 
13272         Parcel p = Parcel.obtain();
13273         final long start = SystemClock.uptimeMillis();
13274         writeHistoryBuffer(p, true, true);
13275         if (DEBUG) {
13276             Slog.d(TAG, "writeHistoryBuffer duration ms:"
13277                     + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
13278         }
13279         writeParcelToFileLocked(p, mBatteryStatsHistory.getActiveFile(), sync);
13280     }
13281 
writeParcelToFileLocked(Parcel p, AtomicFile file, boolean sync)13282     void writeParcelToFileLocked(Parcel p, AtomicFile file, boolean sync) {
13283         if (sync) {
13284             commitPendingDataToDisk(p, file);
13285         } else {
13286             BackgroundThread.getHandler().post(new Runnable() {
13287                 @Override public void run() {
13288                     commitPendingDataToDisk(p, file);
13289                 }
13290             });
13291         }
13292     }
13293 
commitPendingDataToDisk(Parcel p, AtomicFile file)13294     private void commitPendingDataToDisk(Parcel p, AtomicFile file) {
13295         mWriteLock.lock();
13296         FileOutputStream fos = null;
13297         try {
13298             final long startTime = SystemClock.uptimeMillis();
13299             fos = file.startWrite();
13300             fos.write(p.marshall());
13301             fos.flush();
13302             file.finishWrite(fos);
13303             if (DEBUG) {
13304                 Slog.d(TAG, "commitPendingDataToDisk file:" + file.getBaseFile().getPath()
13305                         + " duration ms:" + (SystemClock.uptimeMillis() - startTime)
13306                         + " bytes:" + p.dataSize());
13307             }
13308             com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
13309                     "batterystats", SystemClock.uptimeMillis() - startTime);
13310         } catch (IOException e) {
13311             Slog.w(TAG, "Error writing battery statistics", e);
13312             file.failWrite(fos);
13313         } finally {
13314             p.recycle();
13315             mWriteLock.unlock();
13316         }
13317     }
13318 
13319     @UnsupportedAppUsage
readLocked()13320     public void readLocked() {
13321         if (mDailyFile != null) {
13322             readDailyStatsLocked();
13323         }
13324 
13325         if (mStatsFile == null) {
13326             Slog.w(TAG, "readLocked: no file associated with this instance");
13327             return;
13328         }
13329 
13330         final AtomicFile activeHistoryFile = mBatteryStatsHistory.getActiveFile();
13331         if (activeHistoryFile == null) {
13332             Slog.w(TAG,
13333                     "readLocked: no history file associated with this instance");
13334             return;
13335         }
13336 
13337         mUidStats.clear();
13338 
13339         Parcel stats = Parcel.obtain();
13340         try {
13341             final long start = SystemClock.uptimeMillis();
13342             if (mStatsFile.exists()) {
13343                 byte[] raw = mStatsFile.readFully();
13344                 stats.unmarshall(raw, 0, raw.length);
13345                 stats.setDataPosition(0);
13346                 readSummaryFromParcel(stats);
13347                 if (DEBUG) {
13348                     Slog.d(TAG, "readLocked stats file:" + mStatsFile.getBaseFile().getPath()
13349                             + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
13350                             - start));
13351                 }
13352             }
13353         } catch (Exception e) {
13354             Slog.e(TAG, "Error reading battery statistics", e);
13355             resetAllStatsLocked();
13356         } finally {
13357             stats.recycle();
13358         }
13359 
13360         Parcel history = Parcel.obtain();
13361         try {
13362             final long start = SystemClock.uptimeMillis();
13363             if (activeHistoryFile.exists()) {
13364                 byte[] raw = activeHistoryFile.readFully();
13365                 if (raw.length > 0) {
13366                     history.unmarshall(raw, 0, raw.length);
13367                     history.setDataPosition(0);
13368                     readHistoryBuffer(history, true);
13369                 }
13370                 if (DEBUG) {
13371                     Slog.d(TAG, "readLocked history file::"
13372                             + activeHistoryFile.getBaseFile().getPath()
13373                             + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
13374                             - start));
13375                 }
13376             }
13377         } catch (Exception e) {
13378             Slog.e(TAG, "Error reading battery history", e);
13379             clearHistoryLocked();
13380             mBatteryStatsHistory.resetAllFiles();
13381         } finally {
13382             history.recycle();
13383         }
13384 
13385         mEndPlatformVersion = Build.ID;
13386 
13387         if (mHistoryBuffer.dataPosition() > 0
13388                 || mBatteryStatsHistory.getFilesNumbers().size() > 1) {
13389             mRecordingHistory = true;
13390             final long elapsedRealtime = mClocks.elapsedRealtime();
13391             final long uptime = mClocks.uptimeMillis();
13392             if (USE_OLD_HISTORY) {
13393                 addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
13394             }
13395             addHistoryBufferLocked(elapsedRealtime, HistoryItem.CMD_START, mHistoryCur);
13396             startRecordingHistory(elapsedRealtime, uptime, false);
13397         }
13398 
13399         recordDailyStatsIfNeededLocked(false);
13400     }
13401 
describeContents()13402     public int describeContents() {
13403         return 0;
13404     }
13405 
readHistoryBuffer(Parcel in, boolean andOldHistory)13406     void  readHistoryBuffer(Parcel in, boolean andOldHistory) throws ParcelFormatException {
13407         final int version = in.readInt();
13408         if (version != VERSION) {
13409             Slog.w("BatteryStats", "readHistoryBuffer: version got " + version
13410                     + ", expected " + VERSION + "; erasing old stats");
13411             return;
13412         }
13413 
13414         final long historyBaseTime = in.readLong();
13415 
13416         mHistoryBuffer.setDataSize(0);
13417         mHistoryBuffer.setDataPosition(0);
13418 
13419         int bufSize = in.readInt();
13420         int curPos = in.dataPosition();
13421         if (bufSize >= (mConstants.MAX_HISTORY_BUFFER*100)) {
13422             throw new ParcelFormatException("File corrupt: history data buffer too large " +
13423                     bufSize);
13424         } else if ((bufSize&~3) != bufSize) {
13425             throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
13426                     bufSize);
13427         } else {
13428             if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
13429                     + " bytes at " + curPos);
13430             mHistoryBuffer.appendFrom(in, curPos, bufSize);
13431             in.setDataPosition(curPos + bufSize);
13432         }
13433 
13434         if (andOldHistory) {
13435             readOldHistory(in);
13436         }
13437 
13438         if (DEBUG_HISTORY) {
13439             StringBuilder sb = new StringBuilder(128);
13440             sb.append("****************** OLD mHistoryBaseTime: ");
13441             TimeUtils.formatDuration(mHistoryBaseTime, sb);
13442             Slog.i(TAG, sb.toString());
13443         }
13444         mHistoryBaseTime = historyBaseTime;
13445         if (DEBUG_HISTORY) {
13446             StringBuilder sb = new StringBuilder(128);
13447             sb.append("****************** NEW mHistoryBaseTime: ");
13448             TimeUtils.formatDuration(mHistoryBaseTime, sb);
13449             Slog.i(TAG, sb.toString());
13450         }
13451 
13452         // We are just arbitrarily going to insert 1 minute from the sample of
13453         // the last run until samples in this run.
13454         if (mHistoryBaseTime > 0) {
13455             long oldnow = mClocks.elapsedRealtime();
13456             mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
13457             if (DEBUG_HISTORY) {
13458                 StringBuilder sb = new StringBuilder(128);
13459                 sb.append("****************** ADJUSTED mHistoryBaseTime: ");
13460                 TimeUtils.formatDuration(mHistoryBaseTime, sb);
13461                 Slog.i(TAG, sb.toString());
13462             }
13463         }
13464     }
13465 
readOldHistory(Parcel in)13466     void readOldHistory(Parcel in) {
13467         if (!USE_OLD_HISTORY) {
13468             return;
13469         }
13470         mHistory = mHistoryEnd = mHistoryCache = null;
13471         while (in.dataAvail() > 0) {
13472             HistoryItem rec = new HistoryItem(in);
13473             addHistoryRecordLocked(rec);
13474         }
13475     }
13476 
writeHistoryBuffer(Parcel out, boolean inclData, boolean andOldHistory)13477     void writeHistoryBuffer(Parcel out, boolean inclData, boolean andOldHistory) {
13478         if (DEBUG_HISTORY) {
13479             StringBuilder sb = new StringBuilder(128);
13480             sb.append("****************** WRITING mHistoryBaseTime: ");
13481             TimeUtils.formatDuration(mHistoryBaseTime, sb);
13482             sb.append(" mLastHistoryElapsedRealtime: ");
13483             TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
13484             Slog.i(TAG, sb.toString());
13485         }
13486         out.writeInt(VERSION);
13487         out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
13488         if (!inclData) {
13489             out.writeInt(0);
13490             out.writeInt(0);
13491             return;
13492         }
13493 
13494         out.writeInt(mHistoryBuffer.dataSize());
13495         if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
13496                 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
13497         out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
13498 
13499         if (andOldHistory) {
13500             writeOldHistory(out);
13501         }
13502     }
13503 
writeOldHistory(Parcel out)13504     void writeOldHistory(Parcel out) {
13505         if (!USE_OLD_HISTORY) {
13506             return;
13507         }
13508         HistoryItem rec = mHistory;
13509         while (rec != null) {
13510             if (rec.time >= 0) rec.writeToParcel(out, 0);
13511             rec = rec.next;
13512         }
13513         out.writeLong(-1);
13514     }
13515 
readSummaryFromParcel(Parcel in)13516     public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
13517         final int version = in.readInt();
13518         if (version != VERSION) {
13519             Slog.w("BatteryStats", "readFromParcel: version got " + version
13520                 + ", expected " + VERSION + "; erasing old stats");
13521             return;
13522         }
13523 
13524         boolean inclHistory = in.readBoolean();
13525         if (inclHistory) {
13526             readHistoryBuffer(in, true);
13527             mBatteryStatsHistory.readFromParcel(in);
13528         }
13529 
13530         mHistoryTagPool.clear();
13531         mNextHistoryTagIdx = 0;
13532         mNumHistoryTagChars = 0;
13533 
13534         int numTags = in.readInt();
13535         for (int i=0; i<numTags; i++) {
13536             int idx = in.readInt();
13537             String str = in.readString();
13538             if (str == null) {
13539                 throw new ParcelFormatException("null history tag string");
13540             }
13541             int uid = in.readInt();
13542             HistoryTag tag = new HistoryTag();
13543             tag.string = str;
13544             tag.uid = uid;
13545             tag.poolIdx = idx;
13546             mHistoryTagPool.put(tag, idx);
13547             if (idx >= mNextHistoryTagIdx) {
13548                 mNextHistoryTagIdx = idx+1;
13549             }
13550             mNumHistoryTagChars += tag.string.length() + 1;
13551         }
13552 
13553         mStartCount = in.readInt();
13554         mUptime = in.readLong();
13555         mRealtime = in.readLong();
13556         mStartClockTime = in.readLong();
13557         mStartPlatformVersion = in.readString();
13558         mEndPlatformVersion = in.readString();
13559         mOnBatteryTimeBase.readSummaryFromParcel(in);
13560         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
13561         mDischargeUnplugLevel = in.readInt();
13562         mDischargePlugLevel = in.readInt();
13563         mDischargeCurrentLevel = in.readInt();
13564         mCurrentBatteryLevel = in.readInt();
13565         mEstimatedBatteryCapacity = in.readInt();
13566         mMinLearnedBatteryCapacity = in.readInt();
13567         mMaxLearnedBatteryCapacity = in.readInt();
13568         mLowDischargeAmountSinceCharge = in.readInt();
13569         mHighDischargeAmountSinceCharge = in.readInt();
13570         mDischargeAmountScreenOnSinceCharge = in.readInt();
13571         mDischargeAmountScreenOffSinceCharge = in.readInt();
13572         mDischargeAmountScreenDozeSinceCharge = in.readInt();
13573         mDischargeStepTracker.readFromParcel(in);
13574         mChargeStepTracker.readFromParcel(in);
13575         mDailyDischargeStepTracker.readFromParcel(in);
13576         mDailyChargeStepTracker.readFromParcel(in);
13577         mDischargeCounter.readSummaryFromParcelLocked(in);
13578         mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
13579         mDischargeScreenDozeCounter.readSummaryFromParcelLocked(in);
13580         mDischargeLightDozeCounter.readSummaryFromParcelLocked(in);
13581         mDischargeDeepDozeCounter.readSummaryFromParcelLocked(in);
13582         int NPKG = in.readInt();
13583         if (NPKG > 0) {
13584             mDailyPackageChanges = new ArrayList<>(NPKG);
13585             while (NPKG > 0) {
13586                 NPKG--;
13587                 PackageChange pc = new PackageChange();
13588                 pc.mPackageName = in.readString();
13589                 pc.mUpdate = in.readInt() != 0;
13590                 pc.mVersionCode = in.readLong();
13591                 mDailyPackageChanges.add(pc);
13592             }
13593         } else {
13594             mDailyPackageChanges = null;
13595         }
13596         mDailyStartTime = in.readLong();
13597         mNextMinDailyDeadline = in.readLong();
13598         mNextMaxDailyDeadline = in.readLong();
13599 
13600         mStartCount++;
13601 
13602         mScreenState = Display.STATE_UNKNOWN;
13603         mScreenOnTimer.readSummaryFromParcelLocked(in);
13604         mScreenDozeTimer.readSummaryFromParcelLocked(in);
13605         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
13606             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
13607         }
13608         mInteractive = false;
13609         mInteractiveTimer.readSummaryFromParcelLocked(in);
13610         mPhoneOn = false;
13611         mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
13612         mLongestLightIdleTime = in.readLong();
13613         mLongestFullIdleTime = in.readLong();
13614         mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
13615         mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
13616         mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
13617         mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
13618         mPhoneOnTimer.readSummaryFromParcelLocked(in);
13619         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
13620             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
13621         }
13622         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
13623         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
13624             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
13625         }
13626         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
13627             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
13628             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
13629         }
13630         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
13631         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
13632         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
13633         mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
13634         mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
13635         mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
13636         mWifiMulticastWakelockTimer.readSummaryFromParcelLocked(in);
13637         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
13638         mWifiOn = false;
13639         mWifiOnTimer.readSummaryFromParcelLocked(in);
13640         mGlobalWifiRunning = false;
13641         mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
13642         for (int i=0; i<NUM_WIFI_STATES; i++) {
13643             mWifiStateTimer[i].readSummaryFromParcelLocked(in);
13644         }
13645         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
13646             mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
13647         }
13648         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
13649             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
13650         }
13651         mWifiActiveTimer.readSummaryFromParcelLocked(in);
13652         mWifiActivity.readSummaryFromParcel(in);
13653         for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
13654             mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
13655         }
13656         mBluetoothActivity.readSummaryFromParcel(in);
13657         mModemActivity.readSummaryFromParcel(in);
13658         mHasWifiReporting = in.readInt() != 0;
13659         mHasBluetoothReporting = in.readInt() != 0;
13660         mHasModemReporting = in.readInt() != 0;
13661 
13662         mNumConnectivityChange = in.readInt();
13663         mFlashlightOnNesting = 0;
13664         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
13665         mCameraOnNesting = 0;
13666         mCameraOnTimer.readSummaryFromParcelLocked(in);
13667         mBluetoothScanNesting = 0;
13668         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
13669 
13670         int NRPMS = in.readInt();
13671         if (NRPMS > 10000) {
13672             throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS);
13673         }
13674         for (int irpm = 0; irpm < NRPMS; irpm++) {
13675             if (in.readInt() != 0) {
13676                 String rpmName = in.readString();
13677                 getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
13678             }
13679         }
13680         int NSORPMS = in.readInt();
13681         if (NSORPMS > 10000) {
13682             throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS);
13683         }
13684         for (int irpm = 0; irpm < NSORPMS; irpm++) {
13685             if (in.readInt() != 0) {
13686                 String rpmName = in.readString();
13687                 getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
13688             }
13689         }
13690 
13691         int NKW = in.readInt();
13692         if (NKW > 10000) {
13693             throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
13694         }
13695         for (int ikw = 0; ikw < NKW; ikw++) {
13696             if (in.readInt() != 0) {
13697                 String kwltName = in.readString();
13698                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
13699             }
13700         }
13701 
13702         int NWR = in.readInt();
13703         if (NWR > 10000) {
13704             throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
13705         }
13706         for (int iwr = 0; iwr < NWR; iwr++) {
13707             if (in.readInt() != 0) {
13708                 String reasonName = in.readString();
13709                 getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
13710             }
13711         }
13712 
13713         int NMS = in.readInt();
13714         for (int ims = 0; ims < NMS; ims++) {
13715             if (in.readInt() != 0) {
13716                 long kmstName = in.readLong();
13717                 getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
13718             }
13719         }
13720 
13721         final int NU = in.readInt();
13722         if (NU > 10000) {
13723             throw new ParcelFormatException("File corrupt: too many uids " + NU);
13724         }
13725         for (int iu = 0; iu < NU; iu++) {
13726             int uid = in.readInt();
13727             Uid u = new Uid(this, uid);
13728             mUidStats.put(uid, u);
13729 
13730             u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
13731             u.mOnBatteryScreenOffBackgroundTimeBase.readSummaryFromParcel(in);
13732 
13733             u.mWifiRunning = false;
13734             if (in.readInt() != 0) {
13735                 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
13736             }
13737             u.mFullWifiLockOut = false;
13738             if (in.readInt() != 0) {
13739                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
13740             }
13741             u.mWifiScanStarted = false;
13742             if (in.readInt() != 0) {
13743                 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
13744             }
13745             u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
13746             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
13747                 if (in.readInt() != 0) {
13748                     u.makeWifiBatchedScanBin(i, null);
13749                     u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
13750                 }
13751             }
13752             u.mWifiMulticastWakelockCount = 0;
13753             if (in.readInt() != 0) {
13754                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
13755             }
13756             if (in.readInt() != 0) {
13757                 u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13758             }
13759             if (in.readInt() != 0) {
13760                 u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13761             }
13762             if (in.readInt() != 0) {
13763                 u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13764             }
13765             if (in.readInt() != 0) {
13766                 u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13767             }
13768             if (in.readInt() != 0) {
13769                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
13770             }
13771             if (in.readInt() != 0) {
13772                 u.createForegroundServiceTimerLocked().readSummaryFromParcelLocked(in);
13773             }
13774             if (in.readInt() != 0) {
13775                 u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
13776             }
13777             if (in.readInt() != 0) {
13778                 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
13779             }
13780             if (in.readInt() != 0) {
13781                 u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in);
13782             }
13783             if (in.readInt() != 0) {
13784                 u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
13785             }
13786             if (in.readInt() != 0) {
13787                 u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in);
13788             }
13789             u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
13790             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
13791                 if (in.readInt() != 0) {
13792                     u.makeProcessState(i, null);
13793                     u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
13794                 }
13795             }
13796             if (in.readInt() != 0) {
13797                 u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
13798             }
13799 
13800             if (in.readInt() != 0) {
13801                 if (u.mUserActivityCounters == null) {
13802                     u.initUserActivityLocked();
13803                 }
13804                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
13805                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
13806                 }
13807             }
13808 
13809             if (in.readInt() != 0) {
13810                 if (u.mNetworkByteActivityCounters == null) {
13811                     u.initNetworkActivityLocked();
13812                 }
13813                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
13814                     u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
13815                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
13816                 }
13817                 u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
13818                 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
13819             }
13820 
13821             u.mUserCpuTime.readSummaryFromParcelLocked(in);
13822             u.mSystemCpuTime.readSummaryFromParcelLocked(in);
13823 
13824             if (in.readInt() != 0) {
13825                 final int numClusters = in.readInt();
13826                 if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
13827                     throw new ParcelFormatException("Incompatible cpu cluster arrangement");
13828                 }
13829                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
13830                 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
13831                 for (int cluster = 0; cluster < numClusters; cluster++) {
13832                     if (in.readInt() != 0) {
13833                         final int NSB = in.readInt();
13834                         if (mPowerProfile != null &&
13835                                 mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
13836                             throw new ParcelFormatException("File corrupt: too many speed bins " +
13837                                     NSB);
13838                         }
13839 
13840                         u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[NSB];
13841                         for (int speed = 0; speed < NSB; speed++) {
13842                             if (in.readInt() != 0) {
13843                                 u.mCpuClusterSpeedTimesUs[cluster][speed] = new LongSamplingCounter(
13844                                         mOnBatteryTimeBase);
13845                                 u.mCpuClusterSpeedTimesUs[cluster][speed].readSummaryFromParcelLocked(in);
13846                             }
13847                         }
13848                     } else {
13849                         u.mCpuClusterSpeedTimesUs[cluster] = null;
13850                     }
13851                 }
13852             } else {
13853                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
13854                 u.mCpuClusterSpeedTimesUs = null;
13855             }
13856 
13857             detachIfNotNull(u.mCpuFreqTimeMs);
13858             u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
13859                     in, mOnBatteryTimeBase);
13860             detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
13861             u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
13862                     in, mOnBatteryScreenOffTimeBase);
13863 
13864             u.mCpuActiveTimeMs.readSummaryFromParcelLocked(in);
13865             u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
13866 
13867             int length = in.readInt();
13868             if (length == Uid.NUM_PROCESS_STATE) {
13869                 detachIfNotNull(u.mProcStateTimeMs);
13870                 u.mProcStateTimeMs = new LongSamplingCounterArray[length];
13871                 for (int procState = 0; procState < length; ++procState) {
13872                     u.mProcStateTimeMs[procState]
13873                             = LongSamplingCounterArray.readSummaryFromParcelLocked(
13874                                     in, mOnBatteryTimeBase);
13875                 }
13876             } else {
13877                 detachIfNotNull(u.mProcStateTimeMs);
13878                 u.mProcStateTimeMs = null;
13879             }
13880             length = in.readInt();
13881             if (length == Uid.NUM_PROCESS_STATE) {
13882                 detachIfNotNull(u.mProcStateScreenOffTimeMs);
13883                 u.mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
13884                 for (int procState = 0; procState < length; ++procState) {
13885                     u.mProcStateScreenOffTimeMs[procState]
13886                             = LongSamplingCounterArray.readSummaryFromParcelLocked(
13887                                     in, mOnBatteryScreenOffTimeBase);
13888                 }
13889             } else {
13890                 detachIfNotNull(u.mProcStateScreenOffTimeMs);
13891                 u.mProcStateScreenOffTimeMs = null;
13892             }
13893 
13894             if (in.readInt() != 0) {
13895                 detachIfNotNull(u.mMobileRadioApWakeupCount);
13896                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
13897                 u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
13898             } else {
13899                 detachIfNotNull(u.mMobileRadioApWakeupCount);
13900                 u.mMobileRadioApWakeupCount = null;
13901             }
13902 
13903             if (in.readInt() != 0) {
13904                 detachIfNotNull(u.mWifiRadioApWakeupCount);
13905                 u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
13906                 u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
13907             } else {
13908                 detachIfNotNull(u.mWifiRadioApWakeupCount);
13909                 u.mWifiRadioApWakeupCount = null;
13910             }
13911 
13912             int NW = in.readInt();
13913             if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
13914                 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
13915             }
13916             for (int iw = 0; iw < NW; iw++) {
13917                 String wlName = in.readString();
13918                 u.readWakeSummaryFromParcelLocked(wlName, in);
13919             }
13920 
13921             int NS = in.readInt();
13922             if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
13923                 throw new ParcelFormatException("File corrupt: too many syncs " + NS);
13924             }
13925             for (int is = 0; is < NS; is++) {
13926                 String name = in.readString();
13927                 u.readSyncSummaryFromParcelLocked(name, in);
13928             }
13929 
13930             int NJ = in.readInt();
13931             if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
13932                 throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
13933             }
13934             for (int ij = 0; ij < NJ; ij++) {
13935                 String name = in.readString();
13936                 u.readJobSummaryFromParcelLocked(name, in);
13937             }
13938 
13939             u.readJobCompletionsFromParcelLocked(in);
13940 
13941             u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in);
13942             u.mJobsDeferredCount.readSummaryFromParcelLocked(in);
13943             u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in);
13944             detachIfNotNull(u.mJobsFreshnessBuckets);
13945             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
13946                 if (in.readInt() != 0) {
13947                     u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase);
13948                     u.mJobsFreshnessBuckets[i].readSummaryFromParcelLocked(in);
13949                 }
13950             }
13951 
13952             int NP = in.readInt();
13953             if (NP > 1000) {
13954                 throw new ParcelFormatException("File corrupt: too many sensors " + NP);
13955             }
13956             for (int is = 0; is < NP; is++) {
13957                 int seNumber = in.readInt();
13958                 if (in.readInt() != 0) {
13959                     u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
13960                 }
13961             }
13962 
13963             NP = in.readInt();
13964             if (NP > 1000) {
13965                 throw new ParcelFormatException("File corrupt: too many processes " + NP);
13966             }
13967             for (int ip = 0; ip < NP; ip++) {
13968                 String procName = in.readString();
13969                 Uid.Proc p = u.getProcessStatsLocked(procName);
13970                 p.mUserTime = in.readLong();
13971                 p.mSystemTime = in.readLong();
13972                 p.mForegroundTime = in.readLong();
13973                 p.mStarts = in.readInt();
13974                 p.mNumCrashes = in.readInt();
13975                 p.mNumAnrs = in.readInt();
13976                 p.readExcessivePowerFromParcelLocked(in);
13977             }
13978 
13979             NP = in.readInt();
13980             if (NP > 10000) {
13981                 throw new ParcelFormatException("File corrupt: too many packages " + NP);
13982             }
13983             for (int ip = 0; ip < NP; ip++) {
13984                 String pkgName = in.readString();
13985                 detachIfNotNull(u.mPackageStats.get(pkgName));
13986                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
13987                 final int NWA = in.readInt();
13988                 if (NWA > 10000) {
13989                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
13990                 }
13991                 p.mWakeupAlarms.clear();
13992                 for (int iwa = 0; iwa < NWA; iwa++) {
13993                     String tag = in.readString();
13994                     Counter c = new Counter(mOnBatteryScreenOffTimeBase);
13995                     c.readSummaryFromParcelLocked(in);
13996                     p.mWakeupAlarms.put(tag, c);
13997                 }
13998                 NS = in.readInt();
13999                 if (NS > 10000) {
14000                     throw new ParcelFormatException("File corrupt: too many services " + NS);
14001                 }
14002                 for (int is = 0; is < NS; is++) {
14003                     String servName = in.readString();
14004                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
14005                     s.mStartTime = in.readLong();
14006                     s.mStarts = in.readInt();
14007                     s.mLaunches = in.readInt();
14008                 }
14009             }
14010         }
14011     }
14012 
14013     /**
14014      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
14015      * disk.  This format does not allow a lossless round-trip.
14016      *
14017      * @param out the Parcel to be written to.
14018      */
writeSummaryToParcel(Parcel out, boolean inclHistory)14019     public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
14020         pullPendingStateUpdatesLocked();
14021 
14022         // Pull the clock time.  This may update the time and make a new history entry
14023         // if we had originally pulled a time before the RTC was set.
14024         getStartClockTime();
14025 
14026         final long NOW_SYS = mClocks.uptimeMillis() * 1000;
14027         final long NOWREAL_SYS = mClocks.elapsedRealtime() * 1000;
14028 
14029         out.writeInt(VERSION);
14030 
14031         out.writeBoolean(inclHistory);
14032         if (inclHistory) {
14033             writeHistoryBuffer(out, true, true);
14034             mBatteryStatsHistory.writeToParcel(out);
14035         }
14036 
14037         out.writeInt(mHistoryTagPool.size());
14038         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
14039             HistoryTag tag = ent.getKey();
14040             out.writeInt(ent.getValue());
14041             out.writeString(tag.string);
14042             out.writeInt(tag.uid);
14043         }
14044 
14045         out.writeInt(mStartCount);
14046         out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
14047         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
14048         out.writeLong(mStartClockTime);
14049         out.writeString(mStartPlatformVersion);
14050         out.writeString(mEndPlatformVersion);
14051         mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14052         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14053         out.writeInt(mDischargeUnplugLevel);
14054         out.writeInt(mDischargePlugLevel);
14055         out.writeInt(mDischargeCurrentLevel);
14056         out.writeInt(mCurrentBatteryLevel);
14057         out.writeInt(mEstimatedBatteryCapacity);
14058         out.writeInt(mMinLearnedBatteryCapacity);
14059         out.writeInt(mMaxLearnedBatteryCapacity);
14060         out.writeInt(getLowDischargeAmountSinceCharge());
14061         out.writeInt(getHighDischargeAmountSinceCharge());
14062         out.writeInt(getDischargeAmountScreenOnSinceCharge());
14063         out.writeInt(getDischargeAmountScreenOffSinceCharge());
14064         out.writeInt(getDischargeAmountScreenDozeSinceCharge());
14065         mDischargeStepTracker.writeToParcel(out);
14066         mChargeStepTracker.writeToParcel(out);
14067         mDailyDischargeStepTracker.writeToParcel(out);
14068         mDailyChargeStepTracker.writeToParcel(out);
14069         mDischargeCounter.writeSummaryFromParcelLocked(out);
14070         mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
14071         mDischargeScreenDozeCounter.writeSummaryFromParcelLocked(out);
14072         mDischargeLightDozeCounter.writeSummaryFromParcelLocked(out);
14073         mDischargeDeepDozeCounter.writeSummaryFromParcelLocked(out);
14074         if (mDailyPackageChanges != null) {
14075             final int NPKG = mDailyPackageChanges.size();
14076             out.writeInt(NPKG);
14077             for (int i=0; i<NPKG; i++) {
14078                 PackageChange pc = mDailyPackageChanges.get(i);
14079                 out.writeString(pc.mPackageName);
14080                 out.writeInt(pc.mUpdate ? 1 : 0);
14081                 out.writeLong(pc.mVersionCode);
14082             }
14083         } else {
14084             out.writeInt(0);
14085         }
14086         out.writeLong(mDailyStartTime);
14087         out.writeLong(mNextMinDailyDeadline);
14088         out.writeLong(mNextMaxDailyDeadline);
14089 
14090         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14091         mScreenDozeTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14092         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14093             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14094         }
14095         mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14096         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14097         out.writeLong(mLongestLightIdleTime);
14098         out.writeLong(mLongestFullIdleTime);
14099         mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14100         mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14101         mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14102         mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14103         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14104         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
14105             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14106         }
14107         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14108         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14109             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14110         }
14111         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14112             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
14113             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
14114         }
14115         mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14116         mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14117         mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
14118         mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
14119         mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
14120         mWifiMulticastWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14121         mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14122         mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14123         for (int i=0; i<NUM_WIFI_STATES; i++) {
14124             mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14125         }
14126         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14127             mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14128         }
14129         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14130             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14131         }
14132         mWifiActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14133         mWifiActivity.writeSummaryToParcel(out);
14134         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14135             mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14136         }
14137         mBluetoothActivity.writeSummaryToParcel(out);
14138         mModemActivity.writeSummaryToParcel(out);
14139         out.writeInt(mHasWifiReporting ? 1 : 0);
14140         out.writeInt(mHasBluetoothReporting ? 1 : 0);
14141         out.writeInt(mHasModemReporting ? 1 : 0);
14142 
14143         out.writeInt(mNumConnectivityChange);
14144         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14145         mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14146         mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14147 
14148         out.writeInt(mRpmStats.size());
14149         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
14150             Timer rpmt = ent.getValue();
14151             if (rpmt != null) {
14152                 out.writeInt(1);
14153                 out.writeString(ent.getKey());
14154                 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14155             } else {
14156                 out.writeInt(0);
14157             }
14158         }
14159         out.writeInt(mScreenOffRpmStats.size());
14160         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
14161             Timer rpmt = ent.getValue();
14162             if (rpmt != null) {
14163                 out.writeInt(1);
14164                 out.writeString(ent.getKey());
14165                 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14166             } else {
14167                 out.writeInt(0);
14168             }
14169         }
14170 
14171         out.writeInt(mKernelWakelockStats.size());
14172         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
14173             Timer kwlt = ent.getValue();
14174             if (kwlt != null) {
14175                 out.writeInt(1);
14176                 out.writeString(ent.getKey());
14177                 kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14178             } else {
14179                 out.writeInt(0);
14180             }
14181         }
14182 
14183         out.writeInt(mWakeupReasonStats.size());
14184         for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
14185             SamplingTimer timer = ent.getValue();
14186             if (timer != null) {
14187                 out.writeInt(1);
14188                 out.writeString(ent.getKey());
14189                 timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14190             } else {
14191                 out.writeInt(0);
14192             }
14193         }
14194 
14195         out.writeInt(mKernelMemoryStats.size());
14196         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
14197             Timer kmt = mKernelMemoryStats.valueAt(i);
14198             if (kmt != null) {
14199                 out.writeInt(1);
14200                 out.writeLong(mKernelMemoryStats.keyAt(i));
14201                 kmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14202             } else {
14203                 out.writeInt(0);
14204             }
14205         }
14206 
14207         final int NU = mUidStats.size();
14208         out.writeInt(NU);
14209         for (int iu = 0; iu < NU; iu++) {
14210             out.writeInt(mUidStats.keyAt(iu));
14211             Uid u = mUidStats.valueAt(iu);
14212 
14213             u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14214             u.mOnBatteryScreenOffBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14215 
14216             if (u.mWifiRunningTimer != null) {
14217                 out.writeInt(1);
14218                 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14219             } else {
14220                 out.writeInt(0);
14221             }
14222             if (u.mFullWifiLockTimer != null) {
14223                 out.writeInt(1);
14224                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14225             } else {
14226                 out.writeInt(0);
14227             }
14228             if (u.mWifiScanTimer != null) {
14229                 out.writeInt(1);
14230                 u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14231             } else {
14232                 out.writeInt(0);
14233             }
14234             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
14235                 if (u.mWifiBatchedScanTimer[i] != null) {
14236                     out.writeInt(1);
14237                     u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14238                 } else {
14239                     out.writeInt(0);
14240                 }
14241             }
14242             if (u.mWifiMulticastTimer != null) {
14243                 out.writeInt(1);
14244                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14245             } else {
14246                 out.writeInt(0);
14247             }
14248             if (u.mAudioTurnedOnTimer != null) {
14249                 out.writeInt(1);
14250                 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14251             } else {
14252                 out.writeInt(0);
14253             }
14254             if (u.mVideoTurnedOnTimer != null) {
14255                 out.writeInt(1);
14256                 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14257             } else {
14258                 out.writeInt(0);
14259             }
14260             if (u.mFlashlightTurnedOnTimer != null) {
14261                 out.writeInt(1);
14262                 u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14263             } else {
14264                 out.writeInt(0);
14265             }
14266             if (u.mCameraTurnedOnTimer != null) {
14267                 out.writeInt(1);
14268                 u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14269             } else {
14270                 out.writeInt(0);
14271             }
14272             if (u.mForegroundActivityTimer != null) {
14273                 out.writeInt(1);
14274                 u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14275             } else {
14276                 out.writeInt(0);
14277             }
14278             if (u.mForegroundServiceTimer != null) {
14279                 out.writeInt(1);
14280                 u.mForegroundServiceTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14281             } else {
14282                 out.writeInt(0);
14283             }
14284             if (u.mAggregatedPartialWakelockTimer != null) {
14285                 out.writeInt(1);
14286                 u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14287             } else {
14288                 out.writeInt(0);
14289             }
14290             if (u.mBluetoothScanTimer != null) {
14291                 out.writeInt(1);
14292                 u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14293             } else {
14294                 out.writeInt(0);
14295             }
14296             if (u.mBluetoothUnoptimizedScanTimer != null) {
14297                 out.writeInt(1);
14298                 u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14299             } else {
14300                 out.writeInt(0);
14301             }
14302             if (u.mBluetoothScanResultCounter != null) {
14303                 out.writeInt(1);
14304                 u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
14305             } else {
14306                 out.writeInt(0);
14307             }
14308             if (u.mBluetoothScanResultBgCounter != null) {
14309                 out.writeInt(1);
14310                 u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out);
14311             } else {
14312                 out.writeInt(0);
14313             }
14314             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
14315                 if (u.mProcessStateTimer[i] != null) {
14316                     out.writeInt(1);
14317                     u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14318                 } else {
14319                     out.writeInt(0);
14320                 }
14321             }
14322             if (u.mVibratorOnTimer != null) {
14323                 out.writeInt(1);
14324                 u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14325             } else {
14326                 out.writeInt(0);
14327             }
14328 
14329             if (u.mUserActivityCounters == null) {
14330                 out.writeInt(0);
14331             } else {
14332                 out.writeInt(1);
14333                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
14334                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
14335                 }
14336             }
14337 
14338             if (u.mNetworkByteActivityCounters == null) {
14339                 out.writeInt(0);
14340             } else {
14341                 out.writeInt(1);
14342                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14343                     u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
14344                     u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
14345                 }
14346                 u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
14347                 u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
14348             }
14349 
14350             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
14351             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
14352 
14353             if (u.mCpuClusterSpeedTimesUs != null) {
14354                 out.writeInt(1);
14355                 out.writeInt(u.mCpuClusterSpeedTimesUs.length);
14356                 for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeedTimesUs) {
14357                     if (cpuSpeeds != null) {
14358                         out.writeInt(1);
14359                         out.writeInt(cpuSpeeds.length);
14360                         for (LongSamplingCounter c : cpuSpeeds) {
14361                             if (c != null) {
14362                                 out.writeInt(1);
14363                                 c.writeSummaryFromParcelLocked(out);
14364                             } else {
14365                                 out.writeInt(0);
14366                             }
14367                         }
14368                     } else {
14369                         out.writeInt(0);
14370                     }
14371                 }
14372             } else {
14373                 out.writeInt(0);
14374             }
14375 
14376             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
14377             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
14378 
14379             u.mCpuActiveTimeMs.writeSummaryFromParcelLocked(out);
14380             u.mCpuClusterTimesMs.writeSummaryToParcelLocked(out);
14381 
14382             if (u.mProcStateTimeMs != null) {
14383                 out.writeInt(u.mProcStateTimeMs.length);
14384                 for (LongSamplingCounterArray counters : u.mProcStateTimeMs) {
14385                     LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
14386                 }
14387             } else {
14388                 out.writeInt(0);
14389             }
14390             if (u.mProcStateScreenOffTimeMs != null) {
14391                 out.writeInt(u.mProcStateScreenOffTimeMs.length);
14392                 for (LongSamplingCounterArray counters : u.mProcStateScreenOffTimeMs) {
14393                     LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
14394                 }
14395             } else {
14396                 out.writeInt(0);
14397             }
14398 
14399             if (u.mMobileRadioApWakeupCount != null) {
14400                 out.writeInt(1);
14401                 u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
14402             } else {
14403                 out.writeInt(0);
14404             }
14405 
14406             if (u.mWifiRadioApWakeupCount != null) {
14407                 out.writeInt(1);
14408                 u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
14409             } else {
14410                 out.writeInt(0);
14411             }
14412 
14413             final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
14414             int NW = wakeStats.size();
14415             out.writeInt(NW);
14416             for (int iw=0; iw<NW; iw++) {
14417                 out.writeString(wakeStats.keyAt(iw));
14418                 Uid.Wakelock wl = wakeStats.valueAt(iw);
14419                 if (wl.mTimerFull != null) {
14420                     out.writeInt(1);
14421                     wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14422                 } else {
14423                     out.writeInt(0);
14424                 }
14425                 if (wl.mTimerPartial != null) {
14426                     out.writeInt(1);
14427                     wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14428                 } else {
14429                     out.writeInt(0);
14430                 }
14431                 if (wl.mTimerWindow != null) {
14432                     out.writeInt(1);
14433                     wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14434                 } else {
14435                     out.writeInt(0);
14436                 }
14437                 if (wl.mTimerDraw != null) {
14438                     out.writeInt(1);
14439                     wl.mTimerDraw.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14440                 } else {
14441                     out.writeInt(0);
14442                 }
14443             }
14444 
14445             final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
14446             int NS = syncStats.size();
14447             out.writeInt(NS);
14448             for (int is=0; is<NS; is++) {
14449                 out.writeString(syncStats.keyAt(is));
14450                 syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14451             }
14452 
14453             final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
14454             int NJ = jobStats.size();
14455             out.writeInt(NJ);
14456             for (int ij=0; ij<NJ; ij++) {
14457                 out.writeString(jobStats.keyAt(ij));
14458                 jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14459             }
14460 
14461             u.writeJobCompletionsToParcelLocked(out);
14462 
14463             u.mJobsDeferredEventCount.writeSummaryFromParcelLocked(out);
14464             u.mJobsDeferredCount.writeSummaryFromParcelLocked(out);
14465             u.mJobsFreshnessTimeMs.writeSummaryFromParcelLocked(out);
14466             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
14467                 if (u.mJobsFreshnessBuckets[i] != null) {
14468                     out.writeInt(1);
14469                     u.mJobsFreshnessBuckets[i].writeSummaryFromParcelLocked(out);
14470                 } else {
14471                     out.writeInt(0);
14472                 }
14473             }
14474 
14475             int NSE = u.mSensorStats.size();
14476             out.writeInt(NSE);
14477             for (int ise=0; ise<NSE; ise++) {
14478                 out.writeInt(u.mSensorStats.keyAt(ise));
14479                 Uid.Sensor se = u.mSensorStats.valueAt(ise);
14480                 if (se.mTimer != null) {
14481                     out.writeInt(1);
14482                     se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14483                 } else {
14484                     out.writeInt(0);
14485                 }
14486             }
14487 
14488             int NP = u.mProcessStats.size();
14489             out.writeInt(NP);
14490             for (int ip=0; ip<NP; ip++) {
14491                 out.writeString(u.mProcessStats.keyAt(ip));
14492                 Uid.Proc ps = u.mProcessStats.valueAt(ip);
14493                 out.writeLong(ps.mUserTime);
14494                 out.writeLong(ps.mSystemTime);
14495                 out.writeLong(ps.mForegroundTime);
14496                 out.writeInt(ps.mStarts);
14497                 out.writeInt(ps.mNumCrashes);
14498                 out.writeInt(ps.mNumAnrs);
14499                 ps.writeExcessivePowerToParcelLocked(out);
14500             }
14501 
14502             NP = u.mPackageStats.size();
14503             out.writeInt(NP);
14504             if (NP > 0) {
14505                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
14506                     : u.mPackageStats.entrySet()) {
14507                     out.writeString(ent.getKey());
14508                     Uid.Pkg ps = ent.getValue();
14509                     final int NWA = ps.mWakeupAlarms.size();
14510                     out.writeInt(NWA);
14511                     for (int iwa=0; iwa<NWA; iwa++) {
14512                         out.writeString(ps.mWakeupAlarms.keyAt(iwa));
14513                         ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
14514                     }
14515                     NS = ps.mServiceStats.size();
14516                     out.writeInt(NS);
14517                     for (int is=0; is<NS; is++) {
14518                         out.writeString(ps.mServiceStats.keyAt(is));
14519                         BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
14520                         long time = ss.getStartTimeToNowLocked(
14521                                 mOnBatteryTimeBase.getUptime(NOW_SYS));
14522                         out.writeLong(time);
14523                         out.writeInt(ss.mStarts);
14524                         out.writeInt(ss.mLaunches);
14525                     }
14526                 }
14527             }
14528         }
14529     }
14530 
readFromParcel(Parcel in)14531     public void readFromParcel(Parcel in) {
14532         readFromParcelLocked(in);
14533     }
14534 
readFromParcelLocked(Parcel in)14535     void readFromParcelLocked(Parcel in) {
14536         int magic = in.readInt();
14537         if (magic != MAGIC) {
14538             throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
14539         }
14540 
14541         readHistoryBuffer(in, false);
14542         mBatteryStatsHistory.readFromParcel(in);
14543 
14544         mStartCount = in.readInt();
14545         mStartClockTime = in.readLong();
14546         mStartPlatformVersion = in.readString();
14547         mEndPlatformVersion = in.readString();
14548         mUptime = in.readLong();
14549         mUptimeStart = in.readLong();
14550         mRealtime = in.readLong();
14551         mRealtimeStart = in.readLong();
14552         mOnBattery = in.readInt() != 0;
14553         mEstimatedBatteryCapacity = in.readInt();
14554         mMinLearnedBatteryCapacity = in.readInt();
14555         mMaxLearnedBatteryCapacity = in.readInt();
14556         mOnBatteryInternal = false; // we are no longer really running.
14557         mOnBatteryTimeBase.readFromParcel(in);
14558         mOnBatteryScreenOffTimeBase.readFromParcel(in);
14559 
14560         mScreenState = Display.STATE_UNKNOWN;
14561         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
14562         mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
14563         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14564             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
14565                     mOnBatteryTimeBase, in);
14566         }
14567         mInteractive = false;
14568         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase, in);
14569         mPhoneOn = false;
14570         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
14571                 mOnBatteryTimeBase, in);
14572         mLongestLightIdleTime = in.readLong();
14573         mLongestFullIdleTime = in.readLong();
14574         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null,
14575                 mOnBatteryTimeBase, in);
14576         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null,
14577                 mOnBatteryTimeBase, in);
14578         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null,
14579                 mOnBatteryTimeBase, in);
14580         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase, in);
14581         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase, in);
14582         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
14583             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i,
14584                     null, mOnBatteryTimeBase, in);
14585         }
14586         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
14587                 mOnBatteryTimeBase, in);
14588         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14589             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i,
14590                     null, mOnBatteryTimeBase, in);
14591         }
14592         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14593             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
14594             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
14595         }
14596         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
14597         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
14598                 mOnBatteryTimeBase, in);
14599         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
14600                 mOnBatteryTimeBase, in);
14601         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
14602         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
14603         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
14604         mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null, -4, null,
14605                 mOnBatteryTimeBase, in);
14606         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
14607         mWifiOn = false;
14608         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase, in);
14609         mGlobalWifiRunning = false;
14610         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null,
14611                 mOnBatteryTimeBase, in);
14612         for (int i=0; i<NUM_WIFI_STATES; i++) {
14613             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i,
14614                     null, mOnBatteryTimeBase, in);
14615         }
14616         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14617             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i,
14618                     null, mOnBatteryTimeBase, in);
14619         }
14620         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14621             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
14622                     null, mOnBatteryTimeBase, in);
14623         }
14624         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null,
14625             mOnBatteryTimeBase, in);
14626         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14627                 NUM_WIFI_TX_LEVELS, in);
14628         for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14629             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i,
14630                 null, mOnBatteryTimeBase, in);
14631         }
14632         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14633                 NUM_BT_TX_LEVELS, in);
14634         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14635                 ModemActivityInfo.TX_POWER_LEVELS, in);
14636         mHasWifiReporting = in.readInt() != 0;
14637         mHasBluetoothReporting = in.readInt() != 0;
14638         mHasModemReporting = in.readInt() != 0;
14639 
14640         mNumConnectivityChange = in.readInt();
14641         mAudioOnNesting = 0;
14642         // TODO: It's likely a mistake that mAudioOnTimer/mVideoOnTimer don't write/read to parcel!
14643         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
14644         mVideoOnNesting = 0;
14645         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
14646         mFlashlightOnNesting = 0;
14647         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase, in);
14648         mCameraOnNesting = 0;
14649         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
14650         mBluetoothScanNesting = 0;
14651         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
14652         mDischargeUnplugLevel = in.readInt();
14653         mDischargePlugLevel = in.readInt();
14654         mDischargeCurrentLevel = in.readInt();
14655         mCurrentBatteryLevel = in.readInt();
14656         mLowDischargeAmountSinceCharge = in.readInt();
14657         mHighDischargeAmountSinceCharge = in.readInt();
14658         mDischargeAmountScreenOn = in.readInt();
14659         mDischargeAmountScreenOnSinceCharge = in.readInt();
14660         mDischargeAmountScreenOff = in.readInt();
14661         mDischargeAmountScreenOffSinceCharge = in.readInt();
14662         mDischargeAmountScreenDoze = in.readInt();
14663         mDischargeAmountScreenDozeSinceCharge = in.readInt();
14664         mDischargeStepTracker.readFromParcel(in);
14665         mChargeStepTracker.readFromParcel(in);
14666         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14667         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase, in);
14668         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14669         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14670         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14671         mLastWriteTime = in.readLong();
14672 
14673         mRpmStats.clear();
14674         int NRPMS = in.readInt();
14675         for (int irpm = 0; irpm < NRPMS; irpm++) {
14676             if (in.readInt() != 0) {
14677                 String rpmName = in.readString();
14678                 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14679                 mRpmStats.put(rpmName, rpmt);
14680             }
14681         }
14682         mScreenOffRpmStats.clear();
14683         int NSORPMS = in.readInt();
14684         for (int irpm = 0; irpm < NSORPMS; irpm++) {
14685             if (in.readInt() != 0) {
14686                 String rpmName = in.readString();
14687                 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
14688                 mScreenOffRpmStats.put(rpmName, rpmt);
14689             }
14690         }
14691 
14692         mKernelWakelockStats.clear();
14693         int NKW = in.readInt();
14694         for (int ikw = 0; ikw < NKW; ikw++) {
14695             if (in.readInt() != 0) {
14696                 String wakelockName = in.readString();
14697                 SamplingTimer kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
14698                 mKernelWakelockStats.put(wakelockName, kwlt);
14699             }
14700         }
14701 
14702         mWakeupReasonStats.clear();
14703         int NWR = in.readInt();
14704         for (int iwr = 0; iwr < NWR; iwr++) {
14705             if (in.readInt() != 0) {
14706                 String reasonName = in.readString();
14707                 SamplingTimer timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14708                 mWakeupReasonStats.put(reasonName, timer);
14709             }
14710         }
14711 
14712         mKernelMemoryStats.clear();
14713         int nmt = in.readInt();
14714         for (int imt = 0; imt < nmt; imt++) {
14715             if (in.readInt() != 0) {
14716                 Long bucket = in.readLong();
14717                 SamplingTimer kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14718                 mKernelMemoryStats.put(bucket, kmt);
14719             }
14720         }
14721 
14722         mPartialTimers.clear();
14723         mFullTimers.clear();
14724         mWindowTimers.clear();
14725         mWifiRunningTimers.clear();
14726         mFullWifiLockTimers.clear();
14727         mWifiScanTimers.clear();
14728         mWifiBatchedScanTimers.clear();
14729         mWifiMulticastTimers.clear();
14730         mAudioTurnedOnTimers.clear();
14731         mVideoTurnedOnTimers.clear();
14732         mFlashlightTurnedOnTimers.clear();
14733         mCameraTurnedOnTimers.clear();
14734 
14735         int numUids = in.readInt();
14736         mUidStats.clear();
14737         for (int i = 0; i < numUids; i++) {
14738             int uid = in.readInt();
14739             Uid u = new Uid(this, uid);
14740             u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
14741             mUidStats.append(uid, u);
14742         }
14743     }
14744 
writeToParcel(Parcel out, int flags)14745     public void writeToParcel(Parcel out, int flags) {
14746         writeToParcelLocked(out, true, flags);
14747     }
14748 
writeToParcelWithoutUids(Parcel out, int flags)14749     public void writeToParcelWithoutUids(Parcel out, int flags) {
14750         writeToParcelLocked(out, false, flags);
14751     }
14752 
14753     @SuppressWarnings("unused")
writeToParcelLocked(Parcel out, boolean inclUids, int flags)14754     void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
14755         // Need to update with current kernel wake lock counts.
14756         pullPendingStateUpdatesLocked();
14757 
14758         // Pull the clock time.  This may update the time and make a new history entry
14759         // if we had originally pulled a time before the RTC was set.
14760         getStartClockTime();
14761 
14762         final long uSecUptime = mClocks.uptimeMillis() * 1000;
14763         final long uSecRealtime = mClocks.elapsedRealtime() * 1000;
14764         final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
14765         final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
14766 
14767         out.writeInt(MAGIC);
14768 
14769         writeHistoryBuffer(out, true, false);
14770         mBatteryStatsHistory.writeToParcel(out);
14771 
14772         out.writeInt(mStartCount);
14773         out.writeLong(mStartClockTime);
14774         out.writeString(mStartPlatformVersion);
14775         out.writeString(mEndPlatformVersion);
14776         out.writeLong(mUptime);
14777         out.writeLong(mUptimeStart);
14778         out.writeLong(mRealtime);
14779         out.writeLong(mRealtimeStart);
14780         out.writeInt(mOnBattery ? 1 : 0);
14781         out.writeInt(mEstimatedBatteryCapacity);
14782         out.writeInt(mMinLearnedBatteryCapacity);
14783         out.writeInt(mMaxLearnedBatteryCapacity);
14784         mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
14785         mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
14786 
14787         mScreenOnTimer.writeToParcel(out, uSecRealtime);
14788         mScreenDozeTimer.writeToParcel(out, uSecRealtime);
14789         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14790             mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
14791         }
14792         mInteractiveTimer.writeToParcel(out, uSecRealtime);
14793         mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
14794         out.writeLong(mLongestLightIdleTime);
14795         out.writeLong(mLongestFullIdleTime);
14796         mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
14797         mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
14798         mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
14799         mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
14800         mPhoneOnTimer.writeToParcel(out, uSecRealtime);
14801         for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
14802             mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
14803         }
14804         mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
14805         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14806             mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
14807         }
14808         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14809             mNetworkByteActivityCounters[i].writeToParcel(out);
14810             mNetworkPacketActivityCounters[i].writeToParcel(out);
14811         }
14812         mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
14813         mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
14814         mMobileRadioActiveAdjustedTime.writeToParcel(out);
14815         mMobileRadioActiveUnknownTime.writeToParcel(out);
14816         mMobileRadioActiveUnknownCount.writeToParcel(out);
14817         mWifiMulticastWakelockTimer.writeToParcel(out, uSecRealtime);
14818         mWifiOnTimer.writeToParcel(out, uSecRealtime);
14819         mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
14820         for (int i=0; i<NUM_WIFI_STATES; i++) {
14821             mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
14822         }
14823         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14824             mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
14825         }
14826         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14827             mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
14828         }
14829         mWifiActiveTimer.writeToParcel(out, uSecRealtime);
14830         mWifiActivity.writeToParcel(out, 0);
14831         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14832             mGpsSignalQualityTimer[i].writeToParcel(out, uSecRealtime);
14833         }
14834         mBluetoothActivity.writeToParcel(out, 0);
14835         mModemActivity.writeToParcel(out, 0);
14836         out.writeInt(mHasWifiReporting ? 1 : 0);
14837         out.writeInt(mHasBluetoothReporting ? 1 : 0);
14838         out.writeInt(mHasModemReporting ? 1 : 0);
14839 
14840         out.writeInt(mNumConnectivityChange);
14841         mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
14842         mCameraOnTimer.writeToParcel(out, uSecRealtime);
14843         mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
14844         out.writeInt(mDischargeUnplugLevel);
14845         out.writeInt(mDischargePlugLevel);
14846         out.writeInt(mDischargeCurrentLevel);
14847         out.writeInt(mCurrentBatteryLevel);
14848         out.writeInt(mLowDischargeAmountSinceCharge);
14849         out.writeInt(mHighDischargeAmountSinceCharge);
14850         out.writeInt(mDischargeAmountScreenOn);
14851         out.writeInt(mDischargeAmountScreenOnSinceCharge);
14852         out.writeInt(mDischargeAmountScreenOff);
14853         out.writeInt(mDischargeAmountScreenOffSinceCharge);
14854         out.writeInt(mDischargeAmountScreenDoze);
14855         out.writeInt(mDischargeAmountScreenDozeSinceCharge);
14856         mDischargeStepTracker.writeToParcel(out);
14857         mChargeStepTracker.writeToParcel(out);
14858         mDischargeCounter.writeToParcel(out);
14859         mDischargeScreenOffCounter.writeToParcel(out);
14860         mDischargeScreenDozeCounter.writeToParcel(out);
14861         mDischargeLightDozeCounter.writeToParcel(out);
14862         mDischargeDeepDozeCounter.writeToParcel(out);
14863         out.writeLong(mLastWriteTime);
14864 
14865         out.writeInt(mRpmStats.size());
14866         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
14867             SamplingTimer rpmt = ent.getValue();
14868             if (rpmt != null) {
14869                 out.writeInt(1);
14870                 out.writeString(ent.getKey());
14871                 rpmt.writeToParcel(out, uSecRealtime);
14872             } else {
14873                 out.writeInt(0);
14874             }
14875         }
14876         out.writeInt(mScreenOffRpmStats.size());
14877         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
14878             SamplingTimer rpmt = ent.getValue();
14879             if (rpmt != null) {
14880                 out.writeInt(1);
14881                 out.writeString(ent.getKey());
14882                 rpmt.writeToParcel(out, uSecRealtime);
14883             } else {
14884                 out.writeInt(0);
14885             }
14886         }
14887 
14888         if (inclUids) {
14889             out.writeInt(mKernelWakelockStats.size());
14890             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
14891                 SamplingTimer kwlt = ent.getValue();
14892                 if (kwlt != null) {
14893                     out.writeInt(1);
14894                     out.writeString(ent.getKey());
14895                     kwlt.writeToParcel(out, uSecRealtime);
14896                 } else {
14897                     out.writeInt(0);
14898                 }
14899             }
14900             out.writeInt(mWakeupReasonStats.size());
14901             for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
14902                 SamplingTimer timer = ent.getValue();
14903                 if (timer != null) {
14904                     out.writeInt(1);
14905                     out.writeString(ent.getKey());
14906                     timer.writeToParcel(out, uSecRealtime);
14907                 } else {
14908                     out.writeInt(0);
14909                 }
14910             }
14911         } else {
14912             out.writeInt(0);
14913             out.writeInt(0);
14914         }
14915 
14916         out.writeInt(mKernelMemoryStats.size());
14917         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
14918             SamplingTimer kmt = mKernelMemoryStats.valueAt(i);
14919             if (kmt != null) {
14920                 out.writeInt(1);
14921                 out.writeLong(mKernelMemoryStats.keyAt(i));
14922                 kmt.writeToParcel(out, uSecRealtime);
14923             } else {
14924                 out.writeInt(0);
14925             }
14926         }
14927 
14928         if (inclUids) {
14929             int size = mUidStats.size();
14930             out.writeInt(size);
14931             for (int i = 0; i < size; i++) {
14932                 out.writeInt(mUidStats.keyAt(i));
14933                 Uid uid = mUidStats.valueAt(i);
14934 
14935                 uid.writeToParcelLocked(out, uSecUptime, uSecRealtime);
14936             }
14937         } else {
14938             out.writeInt(0);
14939         }
14940     }
14941 
14942     @UnsupportedAppUsage
14943     public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
14944         new Parcelable.Creator<BatteryStatsImpl>() {
14945         public BatteryStatsImpl createFromParcel(Parcel in) {
14946             return new BatteryStatsImpl(in);
14947         }
14948 
14949         public BatteryStatsImpl[] newArray(int size) {
14950             return new BatteryStatsImpl[size];
14951         }
14952     };
14953 
prepareForDumpLocked()14954     public void prepareForDumpLocked() {
14955         // Need to retrieve current kernel wake lock stats before printing.
14956         pullPendingStateUpdatesLocked();
14957 
14958         // Pull the clock time.  This may update the time and make a new history entry
14959         // if we had originally pulled a time before the RTC was set.
14960         getStartClockTime();
14961     }
14962 
dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart)14963     public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
14964         if (DEBUG) {
14965             pw.println("mOnBatteryTimeBase:");
14966             mOnBatteryTimeBase.dump(pw, "  ");
14967             pw.println("mOnBatteryScreenOffTimeBase:");
14968             mOnBatteryScreenOffTimeBase.dump(pw, "  ");
14969             Printer pr = new PrintWriterPrinter(pw);
14970             pr.println("*** Screen on timer:");
14971             mScreenOnTimer.logState(pr, "  ");
14972             pr.println("*** Screen doze timer:");
14973             mScreenDozeTimer.logState(pr, "  ");
14974             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14975                 pr.println("*** Screen brightness #" + i + ":");
14976                 mScreenBrightnessTimer[i].logState(pr, "  ");
14977             }
14978             pr.println("*** Interactive timer:");
14979             mInteractiveTimer.logState(pr, "  ");
14980             pr.println("*** Power save mode timer:");
14981             mPowerSaveModeEnabledTimer.logState(pr, "  ");
14982             pr.println("*** Device idle mode light timer:");
14983             mDeviceIdleModeLightTimer.logState(pr, "  ");
14984             pr.println("*** Device idle mode full timer:");
14985             mDeviceIdleModeFullTimer.logState(pr, "  ");
14986             pr.println("*** Device light idling timer:");
14987             mDeviceLightIdlingTimer.logState(pr, "  ");
14988             pr.println("*** Device idling timer:");
14989             mDeviceIdlingTimer.logState(pr, "  ");
14990             pr.println("*** Phone timer:");
14991             mPhoneOnTimer.logState(pr, "  ");
14992             for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
14993                 pr.println("*** Phone signal strength #" + i + ":");
14994                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
14995             }
14996             pr.println("*** Signal scanning :");
14997             mPhoneSignalScanningTimer.logState(pr, "  ");
14998             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14999                 pr.println("*** Data connection type #" + i + ":");
15000                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
15001             }
15002             pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
15003             pr.println("*** Mobile network active timer:");
15004             mMobileRadioActiveTimer.logState(pr, "  ");
15005             pr.println("*** Mobile network active adjusted timer:");
15006             mMobileRadioActiveAdjustedTime.logState(pr, "  ");
15007             pr.println("*** Wifi Multicast WakeLock Timer:");
15008             mWifiMulticastWakelockTimer.logState(pr, "  ");
15009             pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
15010             pr.println("*** Wifi timer:");
15011             mWifiOnTimer.logState(pr, "  ");
15012             pr.println("*** WifiRunning timer:");
15013             mGlobalWifiRunningTimer.logState(pr, "  ");
15014             for (int i=0; i<NUM_WIFI_STATES; i++) {
15015                 pr.println("*** Wifi state #" + i + ":");
15016                 mWifiStateTimer[i].logState(pr, "  ");
15017             }
15018             for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
15019                 pr.println("*** Wifi suppl state #" + i + ":");
15020                 mWifiSupplStateTimer[i].logState(pr, "  ");
15021             }
15022             for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
15023                 pr.println("*** Wifi signal strength #" + i + ":");
15024                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
15025             }
15026             for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
15027                 pr.println("*** GPS signal quality #" + i + ":");
15028                 mGpsSignalQualityTimer[i].logState(pr, "  ");
15029             }
15030             pr.println("*** Flashlight timer:");
15031             mFlashlightOnTimer.logState(pr, "  ");
15032             pr.println("*** Camera timer:");
15033             mCameraOnTimer.logState(pr, "  ");
15034         }
15035         super.dumpLocked(context, pw, flags, reqUid, histStart);
15036         pw.print("Total cpu time reads: ");
15037         pw.println(mNumSingleUidCpuTimeReads);
15038         pw.print("Batched cpu time reads: ");
15039         pw.println(mNumBatchedSingleUidCpuTimeReads);
15040         pw.print("Batching Duration (min): ");
15041         pw.println((mClocks.uptimeMillis() - mCpuTimeReadsTrackingStartTime) / (60 * 1000));
15042         pw.print("All UID cpu time reads since the later of device start or stats reset: ");
15043         pw.println(mNumAllUidCpuTimeReads);
15044         pw.print("UIDs removed since the later of device start or stats reset: ");
15045         pw.println(mNumUidsRemoved);
15046     }
15047 }
15048