• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006-2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.os;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.UnsupportedAppUsage;
22 import android.app.ActivityManager;
23 import android.bluetooth.BluetoothActivityEnergyInfo;
24 import android.bluetooth.UidTraffic;
25 import android.content.BroadcastReceiver;
26 import android.content.ContentResolver;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.IntentFilter;
30 import android.database.ContentObserver;
31 import android.hardware.usb.UsbManager;
32 import android.net.ConnectivityManager;
33 import android.net.INetworkStatsService;
34 import android.net.NetworkStats;
35 import android.net.Uri;
36 import android.net.wifi.WifiActivityEnergyInfo;
37 import android.net.wifi.WifiManager;
38 import android.os.BatteryManager;
39 import android.os.BatteryStats;
40 import android.os.Build;
41 import android.os.Handler;
42 import android.os.IBatteryPropertiesRegistrar;
43 import android.os.Looper;
44 import android.os.Message;
45 import android.os.OsProtoEnums;
46 import android.os.Parcel;
47 import android.os.ParcelFormatException;
48 import android.os.Parcelable;
49 import android.os.PowerManager;
50 import android.os.Process;
51 import android.os.RemoteException;
52 import android.os.ServiceManager;
53 import android.os.SystemClock;
54 import android.os.UserHandle;
55 import android.os.WorkSource;
56 import android.os.WorkSource.WorkChain;
57 import android.os.connectivity.CellularBatteryStats;
58 import android.os.connectivity.GpsBatteryStats;
59 import android.os.connectivity.WifiBatteryStats;
60 import android.provider.Settings;
61 import android.telephony.DataConnectionRealTimeInfo;
62 import android.telephony.ModemActivityInfo;
63 import android.telephony.ServiceState;
64 import android.telephony.SignalStrength;
65 import android.telephony.TelephonyManager;
66 import android.text.TextUtils;
67 import android.util.ArrayMap;
68 import android.util.IntArray;
69 import android.util.KeyValueListParser;
70 import android.util.Log;
71 import android.util.LogWriter;
72 import android.util.LongSparseArray;
73 import android.util.LongSparseLongArray;
74 import android.util.MutableInt;
75 import android.util.Pools;
76 import android.util.PrintWriterPrinter;
77 import android.util.Printer;
78 import android.util.Slog;
79 import android.util.SparseArray;
80 import android.util.SparseIntArray;
81 import android.util.SparseLongArray;
82 import android.util.StatsLog;
83 import android.util.TimeUtils;
84 import android.util.Xml;
85 import android.view.Display;
86 
87 import com.android.internal.annotations.GuardedBy;
88 import com.android.internal.annotations.VisibleForTesting;
89 import com.android.internal.location.gnssmetrics.GnssMetrics;
90 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
91 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
92 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
93 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
94 import com.android.internal.util.ArrayUtils;
95 import com.android.internal.util.FastPrintWriter;
96 import com.android.internal.util.FastXmlSerializer;
97 import com.android.internal.util.XmlUtils;
98 
99 import libcore.util.EmptyArray;
100 
101 import org.xmlpull.v1.XmlPullParser;
102 import org.xmlpull.v1.XmlPullParserException;
103 import org.xmlpull.v1.XmlSerializer;
104 
105 import java.io.ByteArrayOutputStream;
106 import java.io.File;
107 import java.io.FileInputStream;
108 import java.io.FileNotFoundException;
109 import java.io.FileOutputStream;
110 import java.io.IOException;
111 import java.io.PrintWriter;
112 import java.nio.charset.StandardCharsets;
113 import java.util.ArrayList;
114 import java.util.Arrays;
115 import java.util.Calendar;
116 import java.util.Collection;
117 import java.util.HashMap;
118 import java.util.HashSet;
119 import java.util.Iterator;
120 import java.util.LinkedList;
121 import java.util.List;
122 import java.util.Map;
123 import java.util.Queue;
124 import java.util.concurrent.Future;
125 import java.util.concurrent.atomic.AtomicInteger;
126 import java.util.concurrent.locks.ReentrantLock;
127 
128 /**
129  * All information we are collecting about things that can happen that impact
130  * battery life.  All times are represented in microseconds except where indicated
131  * otherwise.
132  */
133 public class BatteryStatsImpl extends BatteryStats {
134     private static final String TAG = "BatteryStatsImpl";
135     private static final boolean DEBUG = false;
136     public static final boolean DEBUG_ENERGY = false;
137     private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
138     private static final boolean DEBUG_MEMORY = false;
139     private static final boolean DEBUG_HISTORY = false;
140     private static final boolean USE_OLD_HISTORY = false;   // for debugging.
141 
142     // TODO: remove "tcp" from network methods, since we measure total stats.
143 
144     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
145     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
146 
147     // Current on-disk Parcel version
148     static final int VERSION = 186 + (USE_OLD_HISTORY ? 1000 : 0);
149 
150     // The maximum number of names wakelocks we will keep track of
151     // per uid; once the limit is reached, we batch the remaining wakelocks
152     // in to one common name.
153     private static final int MAX_WAKELOCKS_PER_UID;
154 
155     static {
156         if (ActivityManager.isLowRamDeviceStatic()) {
157             MAX_WAKELOCKS_PER_UID = 40;
158         } else {
159             MAX_WAKELOCKS_PER_UID = 200;
160         }
161     }
162 
163     // Number of transmit power states the Wifi controller can be in.
164     private static final int NUM_WIFI_TX_LEVELS = 1;
165 
166     // Number of transmit power states the Bluetooth controller can be in.
167     private static final int NUM_BT_TX_LEVELS = 1;
168 
169     /**
170      * Holding a wakelock costs more than just using the cpu.
171      * Currently, we assign only half the cpu time to an app that is running but
172      * not holding a wakelock. The apps holding wakelocks get the rest of the blame.
173      * If no app is holding a wakelock, then the distribution is normal.
174      */
175     @VisibleForTesting
176     public static final int WAKE_LOCK_WEIGHT = 50;
177 
178     protected Clocks mClocks;
179 
180     private final AtomicFile mStatsFile;
181     public final AtomicFile mCheckinFile;
182     public final AtomicFile mDailyFile;
183 
184     static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1;
185     static final int MSG_REPORT_POWER_CHANGE = 2;
186     static final int MSG_REPORT_CHARGING = 3;
187     static final int MSG_REPORT_RESET_STATS = 4;
188     static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
189 
190     private static final double MILLISECONDS_IN_HOUR = 3600 * 1000;
191     private static final long MILLISECONDS_IN_YEAR = 365 * 24 * 3600 * 1000L;
192 
193     private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
194     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
195 
196     @VisibleForTesting
197     protected KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader =
198             new KernelCpuUidUserSysTimeReader(true);
199     @VisibleForTesting
200     protected KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
201     @VisibleForTesting
202     protected KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader =
203             new KernelCpuUidFreqTimeReader(true);
204     @VisibleForTesting
205     protected KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader =
206             new KernelCpuUidActiveTimeReader(true);
207     @VisibleForTesting
208     protected KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader =
209             new KernelCpuUidClusterTimeReader(true);
210     @VisibleForTesting
211     protected KernelSingleUidTimeReader mKernelSingleUidTimeReader;
212 
213     private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats
214             = new KernelMemoryBandwidthStats();
215     private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>();
getKernelMemoryStats()216     public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
217         return mKernelMemoryStats;
218     }
219 
220     @GuardedBy("this")
221     public boolean mPerProcStateCpuTimesAvailable = true;
222 
223     /**
224      * When per process state cpu times tracking is off, cpu times in KernelSingleUidTimeReader are
225      * not updated. So, when the setting is turned on later, we would end up with huge cpu time
226      * deltas. This flag tracks the case where tracking is turned on from off so that we won't
227      * end up attributing the huge deltas to wrong buckets.
228      */
229     @GuardedBy("this")
230     private boolean mIsPerProcessStateCpuDataStale;
231 
232     /**
233      * Uids for which per-procstate cpu times need to be updated.
234      *
235      * Contains uid -> procState mappings.
236      */
237     @GuardedBy("this")
238     @VisibleForTesting
239     protected final SparseIntArray mPendingUids = new SparseIntArray();
240 
241     @GuardedBy("this")
242     private long mNumSingleUidCpuTimeReads;
243     @GuardedBy("this")
244     private long mNumBatchedSingleUidCpuTimeReads;
245     @GuardedBy("this")
246     private long mCpuTimeReadsTrackingStartTime = SystemClock.uptimeMillis();
247     @GuardedBy("this")
248     private int mNumUidsRemoved;
249     @GuardedBy("this")
250     private int mNumAllUidCpuTimeReads;
251 
252     /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
253     private final RpmStats mTmpRpmStats = new RpmStats();
254     /** The soonest the RPM stats can be updated after it was last updated. */
255     private static final long RPM_STATS_UPDATE_FREQ_MS = 1000;
256     /** Last time that RPM stats were updated by updateRpmStatsLocked. */
257     private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
258 
259     /** Container for Rail Energy Data stats. */
260     private final RailStats mTmpRailStats = new RailStats();
261     /**
262      * Use a queue to delay removing UIDs from {@link KernelCpuUidUserSysTimeReader},
263      * {@link KernelCpuUidActiveTimeReader}, {@link KernelCpuUidClusterTimeReader},
264      * {@link KernelCpuUidFreqTimeReader} and from the Kernel.
265      *
266      * Isolated and invalid UID info must be removed to conserve memory. However, STATSD and
267      * Batterystats both need to access UID cpu time. To resolve this race condition, only
268      * Batterystats shall remove UIDs, and a delay {@link Constants#UID_REMOVE_DELAY_MS} is
269      * implemented so that STATSD can capture those UID times before they are deleted.
270      */
271     @GuardedBy("this")
272     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
273     protected Queue<UidToRemove> mPendingRemovedUids = new LinkedList<>();
274 
275     @VisibleForTesting
276     public final class UidToRemove {
277         int startUid;
278         int endUid;
279         long timeAddedInQueue;
280 
281         /** Remove just one UID */
UidToRemove(int uid, long timestamp)282         public UidToRemove(int uid, long timestamp) {
283             this(uid, uid, timestamp);
284         }
285 
286         /** Remove a range of UIDs, startUid must be smaller than endUid. */
UidToRemove(int startUid, int endUid, long timestamp)287         public UidToRemove(int startUid, int endUid, long timestamp) {
288             this.startUid = startUid;
289             this.endUid = endUid;
290             timeAddedInQueue = timestamp;
291         }
292 
remove()293         void remove() {
294             if (startUid == endUid) {
295                 mCpuUidUserSysTimeReader.removeUid(startUid);
296                 mCpuUidFreqTimeReader.removeUid(startUid);
297                 if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
298                     mCpuUidActiveTimeReader.removeUid(startUid);
299                     mCpuUidClusterTimeReader.removeUid(startUid);
300                 }
301                 if (mKernelSingleUidTimeReader != null) {
302                     mKernelSingleUidTimeReader.removeUid(startUid);
303                 }
304                 mNumUidsRemoved++;
305             } else if (startUid < endUid) {
306                 mCpuUidFreqTimeReader.removeUidsInRange(startUid, endUid);
307                 mCpuUidUserSysTimeReader.removeUidsInRange(startUid, endUid);
308                 if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
309                     mCpuUidActiveTimeReader.removeUidsInRange(startUid, endUid);
310                     mCpuUidClusterTimeReader.removeUidsInRange(startUid, endUid);
311                 }
312                 if (mKernelSingleUidTimeReader != null) {
313                     mKernelSingleUidTimeReader.removeUidsInRange(startUid, endUid);
314                 }
315                 // Treat as one. We don't know how many uids there are in between.
316                 mNumUidsRemoved++;
317             } else {
318                 Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
319             }
320         }
321     }
322 
323     public interface BatteryCallback {
batteryNeedsCpuUpdate()324         public void batteryNeedsCpuUpdate();
batteryPowerChanged(boolean onBattery)325         public void batteryPowerChanged(boolean onBattery);
batterySendBroadcast(Intent intent)326         public void batterySendBroadcast(Intent intent);
batteryStatsReset()327         public void batteryStatsReset();
328     }
329 
330     public interface PlatformIdleStateCallback {
fillLowPowerStats(RpmStats rpmStats)331         public void fillLowPowerStats(RpmStats rpmStats);
getPlatformLowPowerStats()332         public String getPlatformLowPowerStats();
getSubsystemLowPowerStats()333         public String getSubsystemLowPowerStats();
334     }
335 
336     /** interface to update rail information for power monitor */
337     public interface RailEnergyDataCallback {
338         /** Function to fill the map for the rail data stats
339          * Used for power monitoring feature
340          * @param railStats
341          */
fillRailDataStats(RailStats railStats)342         void fillRailDataStats(RailStats railStats);
343     }
344 
345     public static abstract class UserInfoProvider {
346         private int[] userIds;
getUserIds()347         protected abstract @Nullable int[] getUserIds();
348         @VisibleForTesting
refreshUserIds()349         public final void refreshUserIds() {
350             userIds = getUserIds();
351         }
352         @VisibleForTesting
exists(int userId)353         public boolean exists(int userId) {
354             return userIds != null ? ArrayUtils.contains(userIds, userId) : true;
355         }
356     }
357 
358     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
359 
360     private final Runnable mDeferSetCharging = new Runnable() {
361         @Override
362         public void run() {
363             synchronized (BatteryStatsImpl.this) {
364                 if (mOnBattery) {
365                     // if the device gets unplugged in the time between this runnable being
366                     // executed and the lock being taken, we don't want to set charging state
367                     return;
368                 }
369                 boolean changed = setChargingLocked(true);
370                 if (changed) {
371                     final long uptime = mClocks.uptimeMillis();
372                     final long elapsedRealtime = mClocks.elapsedRealtime();
373                     addHistoryRecordLocked(elapsedRealtime, uptime);
374                 }
375             }
376         }
377     };
378 
379     public final RailEnergyDataCallback mRailEnergyDataCallback;
380 
381     /**
382      * This handler is running on {@link BackgroundThread}.
383      */
384     final class MyHandler extends Handler {
MyHandler(Looper looper)385         public MyHandler(Looper looper) {
386             super(looper, null, true);
387         }
388 
389         @Override
handleMessage(Message msg)390         public void handleMessage(Message msg) {
391             BatteryCallback cb = mCallback;
392             switch (msg.what) {
393                 case MSG_REPORT_CPU_UPDATE_NEEDED:
394                     if (cb != null) {
395                         cb.batteryNeedsCpuUpdate();
396                     }
397                     break;
398                 case MSG_REPORT_POWER_CHANGE:
399                     if (cb != null) {
400                         cb.batteryPowerChanged(msg.arg1 != 0);
401                     }
402                     break;
403                 case MSG_REPORT_CHARGING:
404                     if (cb != null) {
405                         final String action;
406                         synchronized (BatteryStatsImpl.this) {
407                             action = mCharging ? BatteryManager.ACTION_CHARGING
408                                     : BatteryManager.ACTION_DISCHARGING;
409                         }
410                         Intent intent = new Intent(action);
411                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
412                         cb.batterySendBroadcast(intent);
413                     }
414                     break;
415                 case MSG_REPORT_RESET_STATS:
416                     if (cb != null) {
417                         cb.batteryStatsReset();
418                     }
419                 }
420         }
421     }
422 
postBatteryNeedsCpuUpdateMsg()423     public void postBatteryNeedsCpuUpdateMsg() {
424         mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED);
425     }
426 
427     /**
428      * Update per-freq cpu times for all the uids in {@link #mPendingUids}.
429      */
updateProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff)430     public void updateProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
431         final SparseIntArray uidStates;
432         synchronized (BatteryStatsImpl.this) {
433             if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
434                 return;
435             }
436             if(!initKernelSingleUidTimeReaderLocked()) {
437                 return;
438             }
439             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
440             // compute deltas since it might result in mis-attributing cpu times to wrong states.
441             if (mIsPerProcessStateCpuDataStale) {
442                 mPendingUids.clear();
443                 return;
444             }
445 
446             if (mPendingUids.size() == 0) {
447                 return;
448             }
449             uidStates = mPendingUids.clone();
450             mPendingUids.clear();
451         }
452         for (int i = uidStates.size() - 1; i >= 0; --i) {
453             final int uid = uidStates.keyAt(i);
454             final int procState = uidStates.valueAt(i);
455             final int[] isolatedUids;
456             final Uid u;
457             synchronized (BatteryStatsImpl.this) {
458                 // It's possible that uid no longer exists and any internal references have
459                 // already been deleted, so using {@link #getAvailableUidStatsLocked} to avoid
460                 // creating an UidStats object if it doesn't already exist.
461                 u = getAvailableUidStatsLocked(uid);
462                 if (u == null) {
463                     continue;
464                 }
465                 if (u.mChildUids == null) {
466                     isolatedUids = null;
467                 } else {
468                     isolatedUids = u.mChildUids.toArray();
469                     for (int j = isolatedUids.length - 1; j >= 0; --j) {
470                         isolatedUids[j] = u.mChildUids.get(j);
471                     }
472                 }
473             }
474             long[] cpuTimesMs = mKernelSingleUidTimeReader.readDeltaMs(uid);
475             if (isolatedUids != null) {
476                 for (int j = isolatedUids.length - 1; j >= 0; --j) {
477                     cpuTimesMs = addCpuTimes(cpuTimesMs,
478                             mKernelSingleUidTimeReader.readDeltaMs(isolatedUids[j]));
479                 }
480             }
481             if (onBattery && cpuTimesMs != null) {
482                 synchronized (BatteryStatsImpl.this) {
483                     u.addProcStateTimesMs(procState, cpuTimesMs, onBattery);
484                     u.addProcStateScreenOffTimesMs(procState, cpuTimesMs, onBatteryScreenOff);
485                 }
486             }
487         }
488     }
489 
clearPendingRemovedUids()490     public void clearPendingRemovedUids() {
491         long cutOffTime = mClocks.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS;
492         while (!mPendingRemovedUids.isEmpty()
493                 && mPendingRemovedUids.peek().timeAddedInQueue < cutOffTime) {
494             mPendingRemovedUids.poll().remove();
495         }
496     }
497 
copyFromAllUidsCpuTimes()498     public void copyFromAllUidsCpuTimes() {
499         synchronized (BatteryStatsImpl.this) {
500             copyFromAllUidsCpuTimes(
501                     mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
502         }
503     }
504 
505     /**
506      * When the battery/screen state changes, we don't attribute the cpu times to any process
507      * but we still need to snapshots of all uids to get correct deltas later on. Since we
508      * already read this data for updating per-freq cpu times, we can use the same data for
509      * per-procstate cpu times.
510      */
copyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff)511     public void copyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
512         synchronized (BatteryStatsImpl.this) {
513             if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
514                 return;
515             }
516             if(!initKernelSingleUidTimeReaderLocked()) {
517                 return;
518             }
519 
520             final SparseArray<long[]> allUidCpuFreqTimesMs =
521                     mCpuUidFreqTimeReader.getAllUidCpuFreqTimeMs();
522             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
523             // compute deltas since it might result in mis-attributing cpu times to wrong states.
524             if (mIsPerProcessStateCpuDataStale) {
525                 mKernelSingleUidTimeReader.setAllUidsCpuTimesMs(allUidCpuFreqTimesMs);
526                 mIsPerProcessStateCpuDataStale = false;
527                 mPendingUids.clear();
528                 return;
529             }
530             for (int i = allUidCpuFreqTimesMs.size() - 1; i >= 0; --i) {
531                 final int uid = allUidCpuFreqTimesMs.keyAt(i);
532                 final Uid u = getAvailableUidStatsLocked(mapUid(uid));
533                 if (u == null) {
534                     continue;
535                 }
536                 final long[] cpuTimesMs = allUidCpuFreqTimesMs.valueAt(i);
537                 if (cpuTimesMs == null) {
538                     continue;
539                 }
540                 final long[] deltaTimesMs = mKernelSingleUidTimeReader.computeDelta(
541                         uid, cpuTimesMs.clone());
542                 if (onBattery && deltaTimesMs != null) {
543                     final int procState;
544                     final int idx = mPendingUids.indexOfKey(uid);
545                     if (idx >= 0) {
546                         procState = mPendingUids.valueAt(idx);
547                         mPendingUids.removeAt(idx);
548                     } else {
549                         procState = u.mProcessState;
550                     }
551                     if (procState >= 0 && procState < Uid.NUM_PROCESS_STATE) {
552                         u.addProcStateTimesMs(procState, deltaTimesMs, onBattery);
553                         u.addProcStateScreenOffTimesMs(procState, deltaTimesMs, onBatteryScreenOff);
554                     }
555                 }
556             }
557         }
558     }
559 
560     @VisibleForTesting
addCpuTimes(long[] timesA, long[] timesB)561     public long[] addCpuTimes(long[] timesA, long[] timesB) {
562         if (timesA != null && timesB != null) {
563             for (int i = timesA.length - 1; i >= 0; --i) {
564                 timesA[i] += timesB[i];
565             }
566             return timesA;
567         }
568         return timesA == null ? (timesB == null ? null : timesB) : timesA;
569     }
570 
571     @GuardedBy("this")
initKernelSingleUidTimeReaderLocked()572     private boolean initKernelSingleUidTimeReaderLocked() {
573         if (mKernelSingleUidTimeReader == null) {
574             if (mPowerProfile == null) {
575                 return false;
576             }
577             if (mCpuFreqs == null) {
578                 mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
579             }
580             if (mCpuFreqs != null) {
581                 mKernelSingleUidTimeReader = new KernelSingleUidTimeReader(mCpuFreqs.length);
582             } else {
583                 mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.allUidTimesAvailable();
584                 return false;
585             }
586         }
587         mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.allUidTimesAvailable()
588                 && mKernelSingleUidTimeReader.singleUidCpuTimesAvailable();
589         return true;
590     }
591 
592     public interface Clocks {
elapsedRealtime()593         public long elapsedRealtime();
uptimeMillis()594         public long uptimeMillis();
595     }
596 
597     public static class SystemClocks implements Clocks {
elapsedRealtime()598         public long elapsedRealtime() {
599             return SystemClock.elapsedRealtime();
600         }
601 
uptimeMillis()602         public long uptimeMillis() {
603             return SystemClock.uptimeMillis();
604         }
605     }
606 
607     public interface ExternalStatsSync {
608         int UPDATE_CPU = 0x01;
609         int UPDATE_WIFI = 0x02;
610         int UPDATE_RADIO = 0x04;
611         int UPDATE_BT = 0x08;
612         int UPDATE_RPM = 0x10; // 16
613         int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM;
614 
scheduleSync(String reason, int flags)615         Future<?> scheduleSync(String reason, int flags);
scheduleCpuSyncDueToRemovedUid(int uid)616         Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff, long delayMillis)617         Future<?> scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff,
618                 long delayMillis);
scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff)619         Future<?> scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff);
scheduleCpuSyncDueToSettingChange()620         Future<?> scheduleCpuSyncDueToSettingChange();
scheduleCpuSyncDueToScreenStateChange(boolean onBattery, boolean onBatteryScreenOff)621         Future<?> scheduleCpuSyncDueToScreenStateChange(boolean onBattery,
622                 boolean onBatteryScreenOff);
scheduleCpuSyncDueToWakelockChange(long delayMillis)623         Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis);
cancelCpuSyncDueToWakelockChange()624         void cancelCpuSyncDueToWakelockChange();
scheduleSyncDueToBatteryLevelChange(long delayMillis)625         Future<?> scheduleSyncDueToBatteryLevelChange(long delayMillis);
626     }
627 
628     public Handler mHandler;
629     private ExternalStatsSync mExternalSync = null;
630     @VisibleForTesting
631     protected UserInfoProvider mUserInfoProvider = null;
632 
633     private BatteryCallback mCallback;
634 
635     /**
636      * Mapping isolated uids to the actual owning app uid.
637      */
638     final SparseIntArray mIsolatedUids = new SparseIntArray();
639 
640     /**
641      * The statistics we have collected organized by uids.
642      */
643     final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
644 
645     // A set of pools of currently active timers.  When a timer is queried, we will divide the
646     // elapsed time by the number of active timers to arrive at that timer's share of the time.
647     // In order to do this, we must refresh each timer whenever the number of active timers
648     // changes.
649     @VisibleForTesting
650     @UnsupportedAppUsage
651     protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
652     @UnsupportedAppUsage
653     final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
654     @UnsupportedAppUsage
655     final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
656     final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
657     final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
658     final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
659     final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
660     final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
661     final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
662     final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers = new SparseArray<>();
663     final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
664     final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
665     final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
666     final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
667     final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
668 
669     // Last partial timers we use for distributing CPU usage.
670     @VisibleForTesting
671     protected ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
672 
673     // These are the objects that will want to do something when the device
674     // is unplugged from power.
675     protected final TimeBase mOnBatteryTimeBase = new TimeBase(true);
676 
677     // These are the objects that will want to do something when the device
678     // is unplugged from power *and* the screen is off or doze.
679     protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(true);
680 
681     // Set to true when we want to distribute CPU across wakelocks for the next
682     // CPU update, even if we aren't currently running wake locks.
683     boolean mDistributeWakelockCpu;
684 
685     boolean mShuttingDown;
686 
687     final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
688 
689     long mHistoryBaseTime;
690     protected boolean mHaveBatteryLevel = false;
691     protected boolean mRecordingHistory = false;
692     int mNumHistoryItems;
693 
694     final Parcel mHistoryBuffer = Parcel.obtain();
695     final HistoryItem mHistoryLastWritten = new HistoryItem();
696     final HistoryItem mHistoryLastLastWritten = new HistoryItem();
697     final HistoryItem mHistoryReadTmp = new HistoryItem();
698     final HistoryItem mHistoryAddTmp = new HistoryItem();
699     final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
700     String[] mReadHistoryStrings;
701     int[] mReadHistoryUids;
702     int mReadHistoryChars;
703     int mNextHistoryTagIdx = 0;
704     int mNumHistoryTagChars = 0;
705     int mHistoryBufferLastPos = -1;
706     int mActiveHistoryStates = 0xffffffff;
707     int mActiveHistoryStates2 = 0xffffffff;
708     long mLastHistoryElapsedRealtime = 0;
709     long mTrackRunningHistoryElapsedRealtime = 0;
710     long mTrackRunningHistoryUptime = 0;
711 
712     final BatteryStatsHistory mBatteryStatsHistory;
713 
714     final HistoryItem mHistoryCur = new HistoryItem();
715 
716     HistoryItem mHistory;
717     HistoryItem mHistoryEnd;
718     HistoryItem mHistoryLastEnd;
719     HistoryItem mHistoryCache;
720 
721     // Used by computeHistoryStepDetails
722     HistoryStepDetails mLastHistoryStepDetails = null;
723     byte mLastHistoryStepLevel = 0;
724     final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
725     final HistoryStepDetails mReadHistoryStepDetails = new HistoryStepDetails();
726     final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
727 
728     /**
729      * Total time (in milliseconds) spent executing in user code.
730      */
731     long mLastStepCpuUserTime;
732     long mCurStepCpuUserTime;
733     /**
734      * Total time (in milliseconds) spent executing in kernel code.
735      */
736     long mLastStepCpuSystemTime;
737     long mCurStepCpuSystemTime;
738     /**
739      * Times from /proc/stat (but measured in milliseconds).
740      */
741     long mLastStepStatUserTime;
742     long mLastStepStatSystemTime;
743     long mLastStepStatIOWaitTime;
744     long mLastStepStatIrqTime;
745     long mLastStepStatSoftIrqTime;
746     long mLastStepStatIdleTime;
747     long mCurStepStatUserTime;
748     long mCurStepStatSystemTime;
749     long mCurStepStatIOWaitTime;
750     long mCurStepStatIrqTime;
751     long mCurStepStatSoftIrqTime;
752     long mCurStepStatIdleTime;
753 
754     private HistoryItem mHistoryIterator;
755     private boolean mReadOverflow;
756     private boolean mIteratingHistory;
757 
758     int mStartCount;
759 
760     long mStartClockTime;
761     String mStartPlatformVersion;
762     String mEndPlatformVersion;
763 
764     long mUptime;
765     long mUptimeStart;
766     long mRealtime;
767     long mRealtimeStart;
768 
769     int mWakeLockNesting;
770     boolean mWakeLockImportant;
771     public boolean mRecordAllHistory;
772     boolean mNoAutoReset;
773 
774     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
775     protected int mScreenState = Display.STATE_UNKNOWN;
776     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
777     protected StopwatchTimer mScreenOnTimer;
778     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
779     protected StopwatchTimer mScreenDozeTimer;
780 
781     int mScreenBrightnessBin = -1;
782     final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
783 
784     boolean mPretendScreenOff;
785 
786     boolean mInteractive;
787     StopwatchTimer mInteractiveTimer;
788 
789     boolean mPowerSaveModeEnabled;
790     StopwatchTimer mPowerSaveModeEnabledTimer;
791 
792     boolean mDeviceIdling;
793     StopwatchTimer mDeviceIdlingTimer;
794 
795     boolean mDeviceLightIdling;
796     StopwatchTimer mDeviceLightIdlingTimer;
797 
798     int mDeviceIdleMode;
799     long mLastIdleTimeStart;
800     long mLongestLightIdleTime;
801     long mLongestFullIdleTime;
802     StopwatchTimer mDeviceIdleModeLightTimer;
803     StopwatchTimer mDeviceIdleModeFullTimer;
804 
805     boolean mPhoneOn;
806     StopwatchTimer mPhoneOnTimer;
807 
808     int mAudioOnNesting;
809     StopwatchTimer mAudioOnTimer;
810 
811     int mVideoOnNesting;
812     StopwatchTimer mVideoOnTimer;
813 
814     int mFlashlightOnNesting;
815     StopwatchTimer mFlashlightOnTimer;
816 
817     int mCameraOnNesting;
818     StopwatchTimer mCameraOnTimer;
819 
820     private static final int USB_DATA_UNKNOWN = 0;
821     private static final int USB_DATA_DISCONNECTED = 1;
822     private static final int USB_DATA_CONNECTED = 2;
823     int mUsbDataState = USB_DATA_UNKNOWN;
824 
825     int mGpsSignalQualityBin = -1;
826     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
827     protected final StopwatchTimer[] mGpsSignalQualityTimer =
828         new StopwatchTimer[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
829 
830     int mPhoneSignalStrengthBin = -1;
831     int mPhoneSignalStrengthBinRaw = -1;
832     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
833             new StopwatchTimer[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
834 
835     StopwatchTimer mPhoneSignalScanningTimer;
836 
837     int mPhoneDataConnectionType = -1;
838     final StopwatchTimer[] mPhoneDataConnectionsTimer =
839             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
840 
841     final LongSamplingCounter[] mNetworkByteActivityCounters =
842             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
843     final LongSamplingCounter[] mNetworkPacketActivityCounters =
844             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
845 
846     /**
847      * The WiFi Overall wakelock timer
848      * This timer tracks the actual aggregate time for which MC wakelocks are enabled
849      * since addition of per UID timers would not result in an accurate value due to overlapp of
850      * per uid wakelock timers
851      */
852     StopwatchTimer mWifiMulticastWakelockTimer;
853 
854     /**
855      * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
856      */
857     ControllerActivityCounterImpl mWifiActivity;
858 
859     /**
860      * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
861      */
862     ControllerActivityCounterImpl mBluetoothActivity;
863 
864     /**
865      * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
866      */
867     ControllerActivityCounterImpl mModemActivity;
868 
869     /**
870      * Whether the device supports WiFi controller energy reporting. This is set to true on
871      * the first WiFi energy report. See {@link #mWifiActivity}.
872      */
873     boolean mHasWifiReporting = false;
874 
875     /**
876      * Whether the device supports Bluetooth controller energy reporting. This is set to true on
877      * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
878      */
879     boolean mHasBluetoothReporting = false;
880 
881     /**
882      * Whether the device supports Modem controller energy reporting. This is set to true on
883      * the first Modem energy report. See {@link #mModemActivity}.
884      */
885     boolean mHasModemReporting = false;
886 
887     boolean mWifiOn;
888     StopwatchTimer mWifiOnTimer;
889 
890     boolean mGlobalWifiRunning;
891     StopwatchTimer mGlobalWifiRunningTimer;
892 
893     int mWifiState = -1;
894     final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
895 
896     int mWifiSupplState = -1;
897     final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
898 
899     int mWifiSignalStrengthBin = -1;
900     final StopwatchTimer[] mWifiSignalStrengthsTimer =
901             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
902 
903     StopwatchTimer mWifiActiveTimer;
904 
905     int mBluetoothScanNesting;
906     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
907     protected StopwatchTimer mBluetoothScanTimer;
908 
909     boolean mIsCellularTxPowerHigh = false;
910 
911     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
912     long mMobileRadioActiveStartTime;
913     StopwatchTimer mMobileRadioActiveTimer;
914     StopwatchTimer mMobileRadioActivePerAppTimer;
915     LongSamplingCounter mMobileRadioActiveAdjustedTime;
916     LongSamplingCounter mMobileRadioActiveUnknownTime;
917     LongSamplingCounter mMobileRadioActiveUnknownCount;
918 
919     int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
920 
921     /**
922      * These provide time bases that discount the time the device is plugged
923      * in to power.
924      */
925     boolean mOnBattery;
926     @VisibleForTesting
927     protected boolean mOnBatteryInternal;
928 
929     /**
930      * External reporting of whether the device is actually charging.
931      */
932     boolean mCharging = true;
933     int mLastChargingStateLevel;
934 
935     /*
936      * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
937      */
938     int mDischargeStartLevel;
939     int mDischargeUnplugLevel;
940     int mDischargePlugLevel;
941     int mDischargeCurrentLevel;
942     int mCurrentBatteryLevel;
943     int mLowDischargeAmountSinceCharge;
944     int mHighDischargeAmountSinceCharge;
945     int mDischargeScreenOnUnplugLevel;
946     int mDischargeScreenOffUnplugLevel;
947     int mDischargeScreenDozeUnplugLevel;
948     int mDischargeAmountScreenOn;
949     int mDischargeAmountScreenOnSinceCharge;
950     int mDischargeAmountScreenOff;
951     int mDischargeAmountScreenOffSinceCharge;
952     int mDischargeAmountScreenDoze;
953     int mDischargeAmountScreenDozeSinceCharge;
954 
955     private LongSamplingCounter mDischargeScreenOffCounter;
956     private LongSamplingCounter mDischargeScreenDozeCounter;
957     private LongSamplingCounter mDischargeCounter;
958     private LongSamplingCounter mDischargeLightDozeCounter;
959     private LongSamplingCounter mDischargeDeepDozeCounter;
960 
961     static final int MAX_LEVEL_STEPS = 200;
962 
963     int mInitStepMode = 0;
964     int mCurStepMode = 0;
965     int mModStepMode = 0;
966 
967     int mLastDischargeStepLevel;
968     int mMinDischargeStepLevel;
969     final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
970     final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
971     ArrayList<PackageChange> mDailyPackageChanges;
972 
973     int mLastChargeStepLevel;
974     int mMaxChargeStepLevel;
975     final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
976     final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
977 
978     static final int MAX_DAILY_ITEMS = 10;
979 
980     long mDailyStartTime = 0;
981     long mNextMinDailyDeadline = 0;
982     long mNextMaxDailyDeadline = 0;
983 
984     final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
985 
986     long mLastWriteTime = 0; // Milliseconds
987 
988     private int mPhoneServiceState = -1;
989     private int mPhoneServiceStateRaw = -1;
990     private int mPhoneSimStateRaw = -1;
991 
992     private int mNumConnectivityChange;
993 
994     private int mEstimatedBatteryCapacity = -1;
995 
996     private int mMinLearnedBatteryCapacity = -1;
997     private int mMaxLearnedBatteryCapacity = -1;
998 
999     private long[] mCpuFreqs;
1000 
1001     @VisibleForTesting
1002     protected PowerProfile mPowerProfile;
1003 
1004     @GuardedBy("this")
1005     final Constants mConstants;
1006 
1007     /*
1008      * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
1009      * recording their times when on-battery (regardless of screen state).
1010      */
1011     private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>();
1012     /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */
1013     private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>();
1014 
1015     @Override
getRpmStats()1016     public Map<String, ? extends Timer> getRpmStats() {
1017         return mRpmStats;
1018     }
1019 
1020     // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED.
1021     @Override
getScreenOffRpmStats()1022     public Map<String, ? extends Timer> getScreenOffRpmStats() {
1023         return mScreenOffRpmStats;
1024     }
1025 
1026     /*
1027      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
1028      */
1029     private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
1030 
1031     @UnsupportedAppUsage
getKernelWakelockStats()1032     public Map<String, ? extends Timer> getKernelWakelockStats() {
1033         return mKernelWakelockStats;
1034     }
1035 
1036     String mLastWakeupReason = null;
1037     long mLastWakeupUptimeMs = 0;
1038     private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
1039 
getWakeupReasonStats()1040     public Map<String, ? extends Timer> getWakeupReasonStats() {
1041         return mWakeupReasonStats;
1042     }
1043 
1044     @Override
getUahDischarge(int which)1045     public long getUahDischarge(int which) {
1046         return mDischargeCounter.getCountLocked(which);
1047     }
1048 
1049     @Override
getUahDischargeScreenOff(int which)1050     public long getUahDischargeScreenOff(int which) {
1051         return mDischargeScreenOffCounter.getCountLocked(which);
1052     }
1053 
1054     @Override
getUahDischargeScreenDoze(int which)1055     public long getUahDischargeScreenDoze(int which) {
1056         return mDischargeScreenDozeCounter.getCountLocked(which);
1057     }
1058 
1059     @Override
getUahDischargeLightDoze(int which)1060     public long getUahDischargeLightDoze(int which) {
1061         return mDischargeLightDozeCounter.getCountLocked(which);
1062     }
1063 
1064     @Override
getUahDischargeDeepDoze(int which)1065     public long getUahDischargeDeepDoze(int which) {
1066         return mDischargeDeepDozeCounter.getCountLocked(which);
1067     }
1068 
1069     @Override
getEstimatedBatteryCapacity()1070     public int getEstimatedBatteryCapacity() {
1071         return mEstimatedBatteryCapacity;
1072     }
1073 
1074     @Override
getMinLearnedBatteryCapacity()1075     public int getMinLearnedBatteryCapacity() {
1076         return mMinLearnedBatteryCapacity;
1077     }
1078 
1079     @Override
getMaxLearnedBatteryCapacity()1080     public int getMaxLearnedBatteryCapacity() {
1081         return mMaxLearnedBatteryCapacity;
1082     }
1083 
BatteryStatsImpl()1084     public BatteryStatsImpl() {
1085         this(new SystemClocks());
1086     }
1087 
BatteryStatsImpl(Clocks clocks)1088     public BatteryStatsImpl(Clocks clocks) {
1089         init(clocks);
1090         mStatsFile = null;
1091         mCheckinFile = null;
1092         mDailyFile = null;
1093         mBatteryStatsHistory = null;
1094         mHandler = null;
1095         mPlatformIdleStateCallback = null;
1096         mRailEnergyDataCallback = null;
1097         mUserInfoProvider = null;
1098         mConstants = new Constants(mHandler);
1099         clearHistoryLocked();
1100     }
1101 
init(Clocks clocks)1102     private void init(Clocks clocks) {
1103         mClocks = clocks;
1104     }
1105 
1106     /**
1107      * TimeBase observer.
1108      */
1109     public interface TimeBaseObs {
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)1110         void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1111         void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
1112 
1113         /**
1114          * Reset the observer's state, returns true if the timer/counter is inactive
1115          * so it can be destroyed.
1116          * @param detachIfReset detach if true, no-op if false.
1117          * @return Returns true if the timer/counter is inactive and can be destroyed.
1118          */
reset(boolean detachIfReset)1119         boolean reset(boolean detachIfReset);
1120         /**
1121          * Detach the observer from TimeBase.
1122          */
detach()1123         void detach();
1124     }
1125 
1126     // methods are protected not private to be VisibleForTesting
1127     public static class TimeBase {
1128         protected final Collection<TimeBaseObs> mObservers;
1129         protected long mUptime;
1130         protected long mRealtime;
1131 
1132         protected boolean mRunning;
1133 
1134         protected long mPastUptime;
1135         protected long mUptimeStart;
1136         protected long mPastRealtime;
1137         protected long mRealtimeStart;
1138         protected long mUnpluggedUptime;
1139         protected long mUnpluggedRealtime;
1140 
dump(PrintWriter pw, String prefix)1141         public void dump(PrintWriter pw, String prefix) {
1142             StringBuilder sb = new StringBuilder(128);
1143             pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
1144             sb.setLength(0);
1145             sb.append(prefix);
1146                     sb.append("mUptime=");
1147                     formatTimeMs(sb, mUptime / 1000);
1148             pw.println(sb.toString());
1149             sb.setLength(0);
1150             sb.append(prefix);
1151                     sb.append("mRealtime=");
1152                     formatTimeMs(sb, mRealtime / 1000);
1153             pw.println(sb.toString());
1154             sb.setLength(0);
1155             sb.append(prefix);
1156                     sb.append("mPastUptime=");
1157                     formatTimeMs(sb, mPastUptime / 1000); sb.append("mUptimeStart=");
1158                     formatTimeMs(sb, mUptimeStart / 1000);
1159                     sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptime / 1000);
1160             pw.println(sb.toString());
1161             sb.setLength(0);
1162             sb.append(prefix);
1163                     sb.append("mPastRealtime=");
1164                     formatTimeMs(sb, mPastRealtime / 1000); sb.append("mRealtimeStart=");
1165                     formatTimeMs(sb, mRealtimeStart / 1000);
1166                     sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000);
1167             pw.println(sb.toString());
1168         }
1169         /**
1170          * The mObservers of TimeBase in BatteryStatsImpl object can contain up to 20k entries.
1171          * The mObservers of TimeBase in BatteryStatsImpl.Uid object only contains a few or tens of
1172          * entries.
1173          * mObservers must have good performance on add(), remove(), also be memory efficient.
1174          * This is why we provide isLongList parameter for long and short list user cases.
1175          * @param isLongList If true, use HashSet for mObservers list.
1176          *                   If false, use ArrayList for mObservers list.
1177         */
TimeBase(boolean isLongList)1178         public TimeBase(boolean isLongList) {
1179             mObservers = isLongList ? new HashSet<>() : new ArrayList<>();
1180         }
1181 
TimeBase()1182         public TimeBase() {
1183             this(false);
1184         }
1185 
add(TimeBaseObs observer)1186         public void add(TimeBaseObs observer) {
1187             mObservers.add(observer);
1188         }
1189 
remove(TimeBaseObs observer)1190         public void remove(TimeBaseObs observer) {
1191             mObservers.remove(observer);
1192         }
1193 
hasObserver(TimeBaseObs observer)1194         public boolean hasObserver(TimeBaseObs observer) {
1195             return mObservers.contains(observer);
1196         }
1197 
init(long uptime, long realtime)1198         public void init(long uptime, long realtime) {
1199             mRealtime = 0;
1200             mUptime = 0;
1201             mPastUptime = 0;
1202             mPastRealtime = 0;
1203             mUptimeStart = uptime;
1204             mRealtimeStart = realtime;
1205             mUnpluggedUptime = getUptime(mUptimeStart);
1206             mUnpluggedRealtime = getRealtime(mRealtimeStart);
1207         }
1208 
reset(long uptime, long realtime)1209         public void reset(long uptime, long realtime) {
1210             if (!mRunning) {
1211                 mPastUptime = 0;
1212                 mPastRealtime = 0;
1213             } else {
1214                 mUptimeStart = uptime;
1215                 mRealtimeStart = realtime;
1216                 // TODO: Since mUptimeStart was just reset and we are running, getUptime will
1217                 // just return mPastUptime. Also, are we sure we don't want to reset that?
1218                 mUnpluggedUptime = getUptime(uptime);
1219                 // TODO: likewise.
1220                 mUnpluggedRealtime = getRealtime(realtime);
1221             }
1222         }
1223 
computeUptime(long curTime, int which)1224         public long computeUptime(long curTime, int which) {
1225             return mUptime + getUptime(curTime);
1226         }
1227 
computeRealtime(long curTime, int which)1228         public long computeRealtime(long curTime, int which) {
1229             return mRealtime + getRealtime(curTime);
1230         }
1231 
getUptime(long curTime)1232         public long getUptime(long curTime) {
1233             long time = mPastUptime;
1234             if (mRunning) {
1235                 time += curTime - mUptimeStart;
1236             }
1237             return time;
1238         }
1239 
getRealtime(long curTime)1240         public long getRealtime(long curTime) {
1241             long time = mPastRealtime;
1242             if (mRunning) {
1243                 time += curTime - mRealtimeStart;
1244             }
1245             return time;
1246         }
1247 
getUptimeStart()1248         public long getUptimeStart() {
1249             return mUptimeStart;
1250         }
1251 
getRealtimeStart()1252         public long getRealtimeStart() {
1253             return mRealtimeStart;
1254         }
1255 
isRunning()1256         public boolean isRunning() {
1257             return mRunning;
1258         }
1259 
setRunning(boolean running, long uptime, long realtime)1260         public boolean setRunning(boolean running, long uptime, long realtime) {
1261             if (mRunning != running) {
1262                 mRunning = running;
1263                 if (running) {
1264                     mUptimeStart = uptime;
1265                     mRealtimeStart = realtime;
1266                     long batteryUptime = mUnpluggedUptime = getUptime(uptime);
1267                     long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime);
1268                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
1269                     // Iterator object, here is an exception because mObservers' type is Collection
1270                     // instead of list.
1271                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
1272                     while (iter.hasNext()) {
1273                         iter.next().onTimeStarted(realtime, batteryUptime, batteryRealtime);
1274                     }
1275                 } else {
1276                     mPastUptime += uptime - mUptimeStart;
1277                     mPastRealtime += realtime - mRealtimeStart;
1278                     long batteryUptime = getUptime(uptime);
1279                     long batteryRealtime = getRealtime(realtime);
1280                     // Normally we do not use Iterator in framework code to avoid alloc/dealloc
1281                     // Iterator object, here is an exception because mObservers' type is Collection
1282                     // instead of list.
1283                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
1284                     while (iter.hasNext()) {
1285                         iter.next().onTimeStopped(realtime, batteryUptime, batteryRealtime);
1286                     }
1287                 }
1288                 return true;
1289             }
1290             return false;
1291         }
1292 
readSummaryFromParcel(Parcel in)1293         public void readSummaryFromParcel(Parcel in) {
1294             mUptime = in.readLong();
1295             mRealtime = in.readLong();
1296         }
1297 
writeSummaryToParcel(Parcel out, long uptime, long realtime)1298         public void writeSummaryToParcel(Parcel out, long uptime, long realtime) {
1299             out.writeLong(computeUptime(uptime, STATS_SINCE_CHARGED));
1300             out.writeLong(computeRealtime(realtime, STATS_SINCE_CHARGED));
1301         }
1302 
readFromParcel(Parcel in)1303         public void readFromParcel(Parcel in) {
1304             mRunning = false;
1305             mUptime = in.readLong();
1306             mPastUptime = in.readLong();
1307             mUptimeStart = in.readLong();
1308             mRealtime = in.readLong();
1309             mPastRealtime = in.readLong();
1310             mRealtimeStart = in.readLong();
1311             mUnpluggedUptime = in.readLong();
1312             mUnpluggedRealtime = in.readLong();
1313         }
1314 
writeToParcel(Parcel out, long uptime, long realtime)1315         public void writeToParcel(Parcel out, long uptime, long realtime) {
1316             final long runningUptime = getUptime(uptime);
1317             final long runningRealtime = getRealtime(realtime);
1318             out.writeLong(mUptime);
1319             out.writeLong(runningUptime);
1320             out.writeLong(mUptimeStart);
1321             out.writeLong(mRealtime);
1322             out.writeLong(runningRealtime);
1323             out.writeLong(mRealtimeStart);
1324             out.writeLong(mUnpluggedUptime);
1325             out.writeLong(mUnpluggedRealtime);
1326         }
1327     }
1328 
1329     /**
1330      * State for keeping track of counting information.
1331      */
1332     public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
1333         @UnsupportedAppUsage
1334         final AtomicInteger mCount = new AtomicInteger();
1335         final TimeBase mTimeBase;
1336 
Counter(TimeBase timeBase, Parcel in)1337         public Counter(TimeBase timeBase, Parcel in) {
1338             mTimeBase = timeBase;
1339             mCount.set(in.readInt());
1340             timeBase.add(this);
1341         }
1342 
Counter(TimeBase timeBase)1343         public Counter(TimeBase timeBase) {
1344             mTimeBase = timeBase;
1345             timeBase.add(this);
1346         }
1347 
writeToParcel(Parcel out)1348         public void writeToParcel(Parcel out) {
1349             out.writeInt(mCount.get());
1350         }
1351 
1352         @Override
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)1353         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1354         }
1355 
1356         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1357         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1358         }
1359 
1360         /**
1361          * Writes a possibly null Counter to a Parcel.
1362          *
1363          * @param out the Parcel to be written to.
1364          * @param counter a Counter, or null.
1365          */
writeCounterToParcel(Parcel out, @Nullable Counter counter)1366         public static void writeCounterToParcel(Parcel out, @Nullable Counter counter) {
1367             if (counter == null) {
1368                 out.writeInt(0); // indicates null
1369                 return;
1370             }
1371             out.writeInt(1); // indicates non-null
1372 
1373             counter.writeToParcel(out);
1374         }
1375 
1376         /**
1377          * Reads a Counter that was written using {@link #writeCounterToParcel(Parcel, Counter)}.
1378          * @param timeBase the timebase to assign to the Counter
1379          * @param in the parcel to read from
1380          * @return the Counter or null.
1381          */
readCounterFromParcel(TimeBase timeBase, Parcel in)1382         public static @Nullable Counter readCounterFromParcel(TimeBase timeBase, Parcel in) {
1383             if (in.readInt() == 0) {
1384                 return null;
1385             }
1386             return new Counter(timeBase, in);
1387         }
1388 
1389         @Override
getCountLocked(int which)1390         public int getCountLocked(int which) {
1391             return mCount.get();
1392         }
1393 
logState(Printer pw, String prefix)1394         public void logState(Printer pw, String prefix) {
1395             pw.println(prefix + "mCount=" + mCount.get());
1396         }
1397 
1398         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
stepAtomic()1399         public void stepAtomic() {
1400             if (mTimeBase.isRunning()) {
1401                 mCount.incrementAndGet();
1402             }
1403         }
1404 
addAtomic(int delta)1405         void addAtomic(int delta) {
1406             if (mTimeBase.isRunning()) {
1407                 mCount.addAndGet(delta);
1408             }
1409         }
1410 
1411         /**
1412          * Clear state of this counter.
1413          */
1414         @Override
reset(boolean detachIfReset)1415         public boolean reset(boolean detachIfReset) {
1416             mCount.set(0);
1417             if (detachIfReset) {
1418                 detach();
1419             }
1420             return true;
1421         }
1422 
1423         @Override
detach()1424         public void detach() {
1425             mTimeBase.remove(this);
1426         }
1427 
1428         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
writeSummaryFromParcelLocked(Parcel out)1429         public void writeSummaryFromParcelLocked(Parcel out) {
1430             out.writeInt(mCount.get());
1431         }
1432 
1433         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
readSummaryFromParcelLocked(Parcel in)1434         public void readSummaryFromParcelLocked(Parcel in) {
1435             mCount.set(in.readInt());
1436         }
1437     }
1438 
1439     @VisibleForTesting
1440     public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
1441         final TimeBase mTimeBase;
1442         public long[] mCounts;
1443 
LongSamplingCounterArray(TimeBase timeBase, Parcel in)1444         private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
1445             mTimeBase = timeBase;
1446             mCounts = in.createLongArray();
1447             timeBase.add(this);
1448         }
1449 
LongSamplingCounterArray(TimeBase timeBase)1450         public LongSamplingCounterArray(TimeBase timeBase) {
1451             mTimeBase = timeBase;
1452             timeBase.add(this);
1453         }
1454 
writeToParcel(Parcel out)1455         private void writeToParcel(Parcel out) {
1456             out.writeLongArray(mCounts);
1457         }
1458 
1459         @Override
onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime)1460         public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) {
1461         }
1462 
1463         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1464         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1465         }
1466 
1467         @Override
getCountsLocked(int which)1468         public long[] getCountsLocked(int which) {
1469             return mCounts == null ? null : Arrays.copyOf(mCounts, mCounts.length);
1470         }
1471 
1472         @Override
logState(Printer pw, String prefix)1473         public void logState(Printer pw, String prefix) {
1474             pw.println(prefix + "mCounts=" + Arrays.toString(mCounts));
1475         }
1476 
addCountLocked(long[] counts)1477         public void addCountLocked(long[] counts) {
1478             addCountLocked(counts, mTimeBase.isRunning());
1479         }
1480 
addCountLocked(long[] counts, boolean isRunning)1481         public void addCountLocked(long[] counts, boolean isRunning) {
1482             if (counts == null) {
1483                 return;
1484             }
1485             if (isRunning) {
1486                 if (mCounts == null) {
1487                     mCounts = new long[counts.length];
1488                 }
1489                 for (int i = 0; i < counts.length; ++i) {
1490                     mCounts[i] += counts[i];
1491                 }
1492             }
1493         }
1494 
getSize()1495         public int getSize() {
1496             return mCounts == null ? 0 : mCounts.length;
1497         }
1498 
1499         /**
1500          * Clear state of this counter.
1501          */
1502         @Override
reset(boolean detachIfReset)1503         public boolean reset(boolean detachIfReset) {
1504             if (mCounts != null) {
1505                 Arrays.fill(mCounts, 0);
1506             }
1507             if (detachIfReset) {
1508                 detach();
1509             }
1510             return true;
1511         }
1512 
1513         @Override
detach()1514         public void detach() {
1515             mTimeBase.remove(this);
1516         }
1517 
writeSummaryToParcelLocked(Parcel out)1518         private void writeSummaryToParcelLocked(Parcel out) {
1519             out.writeLongArray(mCounts);
1520         }
1521 
readSummaryFromParcelLocked(Parcel in)1522         private void readSummaryFromParcelLocked(Parcel in) {
1523             mCounts = in.createLongArray();
1524         }
1525 
writeToParcel(Parcel out, LongSamplingCounterArray counterArray)1526         public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
1527             if (counterArray != null) {
1528                 out.writeInt(1);
1529                 counterArray.writeToParcel(out);
1530             } else {
1531                 out.writeInt(0);
1532             }
1533         }
1534 
readFromParcel(Parcel in, TimeBase timeBase)1535         public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
1536             if (in.readInt() != 0) {
1537                 return new LongSamplingCounterArray(timeBase, in);
1538             } else {
1539                 return null;
1540             }
1541         }
1542 
writeSummaryToParcelLocked(Parcel out, LongSamplingCounterArray counterArray)1543         public static void writeSummaryToParcelLocked(Parcel out,
1544                 LongSamplingCounterArray counterArray) {
1545             if (counterArray != null) {
1546                 out.writeInt(1);
1547                 counterArray.writeSummaryToParcelLocked(out);
1548             } else {
1549                 out.writeInt(0);
1550             }
1551         }
1552 
readSummaryFromParcelLocked(Parcel in, TimeBase timeBase)1553         public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
1554                 TimeBase timeBase) {
1555             if (in.readInt() != 0) {
1556                 final LongSamplingCounterArray counterArray
1557                         = new LongSamplingCounterArray(timeBase);
1558                 counterArray.readSummaryFromParcelLocked(in);
1559                 return counterArray;
1560             } else {
1561                 return null;
1562             }
1563         }
1564     }
1565 
1566     @VisibleForTesting
1567     public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
1568         final TimeBase mTimeBase;
1569         private long mCount;
1570 
LongSamplingCounter(TimeBase timeBase, Parcel in)1571         public LongSamplingCounter(TimeBase timeBase, Parcel in) {
1572             mTimeBase = timeBase;
1573             mCount = in.readLong();
1574             timeBase.add(this);
1575         }
1576 
LongSamplingCounter(TimeBase timeBase)1577         public LongSamplingCounter(TimeBase timeBase) {
1578             mTimeBase = timeBase;
1579             timeBase.add(this);
1580         }
1581 
writeToParcel(Parcel out)1582         public void writeToParcel(Parcel out) {
1583             out.writeLong(mCount);
1584         }
1585 
1586         @Override
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)1587         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1588         }
1589 
1590         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1591         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1592         }
1593 
getCountLocked(int which)1594         public long getCountLocked(int which) {
1595             return mCount;
1596         }
1597 
1598         @Override
logState(Printer pw, String prefix)1599         public void logState(Printer pw, String prefix) {
1600             pw.println(prefix + "mCount=" + mCount);
1601         }
1602 
addCountLocked(long count)1603         public void addCountLocked(long count) {
1604             addCountLocked(count, mTimeBase.isRunning());
1605         }
1606 
addCountLocked(long count, boolean isRunning)1607         public void addCountLocked(long count, boolean isRunning) {
1608             if (isRunning) {
1609                 mCount += count;
1610             }
1611         }
1612 
1613         /**
1614          * Clear state of this counter.
1615          */
1616         @Override
reset(boolean detachIfReset)1617         public boolean reset(boolean detachIfReset) {
1618             mCount = 0;
1619             if (detachIfReset) {
1620                 detach();
1621             }
1622             return true;
1623         }
1624 
1625         @Override
detach()1626         public void detach() {
1627             mTimeBase.remove(this);
1628         }
1629 
writeSummaryFromParcelLocked(Parcel out)1630         public void writeSummaryFromParcelLocked(Parcel out) {
1631             out.writeLong(mCount);
1632         }
1633 
readSummaryFromParcelLocked(Parcel in)1634         public void readSummaryFromParcelLocked(Parcel in) {
1635             mCount = in.readLong();
1636         }
1637     }
1638 
1639     /**
1640      * State for keeping track of timing information.
1641      */
1642     public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
1643         protected final Clocks mClocks;
1644         protected final int mType;
1645         protected final TimeBase mTimeBase;
1646 
1647         protected int mCount;
1648 
1649         // Times are in microseconds for better accuracy when dividing by the
1650         // lock count, and are in "battery realtime" units.
1651 
1652         /**
1653          * The total time we have accumulated since the start of the original
1654          * boot, to the last time something interesting happened in the
1655          * current run.
1656          */
1657         protected long mTotalTime;
1658 
1659         /**
1660          * The total time this timer has been running until the latest mark has been set.
1661          * Subtract this from mTotalTime to get the time spent running since the mark was set.
1662          */
1663         protected long mTimeBeforeMark;
1664 
1665         /**
1666          * Constructs from a parcel.
1667          * @param type
1668          * @param timeBase
1669          * @param in
1670          */
Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in)1671         public Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in) {
1672             mClocks = clocks;
1673             mType = type;
1674             mTimeBase = timeBase;
1675 
1676             mCount = in.readInt();
1677             mTotalTime = in.readLong();
1678             mTimeBeforeMark = in.readLong();
1679             timeBase.add(this);
1680             if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTime);
1681         }
1682 
Timer(Clocks clocks, int type, TimeBase timeBase)1683         public Timer(Clocks clocks, int type, TimeBase timeBase) {
1684             mClocks = clocks;
1685             mType = type;
1686             mTimeBase = timeBase;
1687             timeBase.add(this);
1688         }
1689 
writeToParcel(Parcel out, long elapsedRealtimeUs)1690         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1691             if (DEBUG) {
1692                 Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
1693                         + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
1694             }
1695             out.writeInt(computeCurrentCountLocked());
1696             out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
1697             out.writeLong(mTimeBeforeMark);
1698         }
1699 
computeRunTimeLocked(long curBatteryRealtime)1700         protected abstract long computeRunTimeLocked(long curBatteryRealtime);
1701 
computeCurrentCountLocked()1702         protected abstract int computeCurrentCountLocked();
1703 
1704         /**
1705          * Clear state of this timer.  Returns true if the timer is inactive
1706          * so can be completely dropped.
1707          */
1708         @Override
reset(boolean detachIfReset)1709         public boolean reset(boolean detachIfReset) {
1710             mTotalTime = mTimeBeforeMark = 0;
1711             mCount = 0;
1712             if (detachIfReset) {
1713                 detach();
1714             }
1715             return true;
1716         }
1717 
1718         @Override
detach()1719         public void detach() {
1720             mTimeBase.remove(this);
1721         }
1722 
1723         @Override
onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime)1724         public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) {
1725         }
1726 
1727         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1728         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1729             if (DEBUG && mType < 0) {
1730                 Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtime
1731                         + " old mTotalTime=" + mTotalTime);
1732             }
1733             mTotalTime = computeRunTimeLocked(baseRealtime);
1734             mCount = computeCurrentCountLocked();
1735             if (DEBUG && mType < 0) {
1736                 Log.v(TAG, "plug #" + mType + ": new mTotalTime=" + mTotalTime);
1737             }
1738         }
1739 
1740         /**
1741          * Writes a possibly null Timer to a Parcel.
1742          *
1743          * @param out the Parcel to be written to.
1744          * @param timer a Timer, or null.
1745          */
1746         @UnsupportedAppUsage
writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs)1747         public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
1748             if (timer == null) {
1749                 out.writeInt(0); // indicates null
1750                 return;
1751             }
1752             out.writeInt(1); // indicates non-null
1753             timer.writeToParcel(out, elapsedRealtimeUs);
1754         }
1755 
1756         @Override
1757         @UnsupportedAppUsage
getTotalTimeLocked(long elapsedRealtimeUs, int which)1758         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
1759             return computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1760         }
1761 
1762         @Override
1763         @UnsupportedAppUsage
getCountLocked(int which)1764         public int getCountLocked(int which) {
1765             return computeCurrentCountLocked();
1766         }
1767 
1768         @Override
getTimeSinceMarkLocked(long elapsedRealtimeUs)1769         public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
1770             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1771             return val - mTimeBeforeMark;
1772         }
1773 
1774         @Override
logState(Printer pw, String prefix)1775         public void logState(Printer pw, String prefix) {
1776             pw.println(prefix + "mCount=" + mCount);
1777             pw.println(prefix + "mTotalTime=" + mTotalTime);
1778         }
1779 
1780 
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)1781         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
1782             long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1783             out.writeLong(runTime);
1784             out.writeInt(computeCurrentCountLocked());
1785         }
1786 
readSummaryFromParcelLocked(Parcel in)1787         public void readSummaryFromParcelLocked(Parcel in) {
1788             // Multiply by 1000 for backwards compatibility
1789             mTotalTime = in.readLong();
1790             mCount = in.readInt();
1791             // When reading the summary, we set the mark to be the latest information.
1792             mTimeBeforeMark = mTotalTime;
1793         }
1794     }
1795 
1796     /**
1797      * A counter meant to accept monotonically increasing values to its {@link #update(long, int)}
1798      * method. The state of the timer according to its {@link TimeBase} will determine how much
1799      * of the value is recorded.
1800      *
1801      * If the value being recorded resets, {@link #endSample()} can be called in order to
1802      * account for the change. If the value passed in to {@link #update(long, int)} decreased
1803      * between calls, the {@link #endSample()} is automatically called and the new value is
1804      * expected to increase monotonically from that point on.
1805      */
1806     public static class SamplingTimer extends Timer {
1807 
1808         /**
1809          * The most recent reported count from /proc/wakelocks.
1810          */
1811         int mCurrentReportedCount;
1812 
1813         /**
1814          * The reported count from /proc/wakelocks when unplug() was last
1815          * called.
1816          */
1817         int mUnpluggedReportedCount;
1818 
1819         /**
1820          * The most recent reported total_time from /proc/wakelocks.
1821          */
1822         long mCurrentReportedTotalTime;
1823 
1824 
1825         /**
1826          * The reported total_time from /proc/wakelocks when unplug() was last
1827          * called.
1828          */
1829         long mUnpluggedReportedTotalTime;
1830 
1831         /**
1832          * Whether we are currently in a discharge cycle.
1833          */
1834         boolean mTimeBaseRunning;
1835 
1836         /**
1837          * Whether we are currently recording reported values.
1838          */
1839         boolean mTrackingReportedValues;
1840 
1841         /*
1842          * A sequence counter, incremented once for each update of the stats.
1843          */
1844         int mUpdateVersion;
1845 
1846         @VisibleForTesting
SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in)1847         public SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in) {
1848             super(clocks, 0, timeBase, in);
1849             mCurrentReportedCount = in.readInt();
1850             mUnpluggedReportedCount = in.readInt();
1851             mCurrentReportedTotalTime = in.readLong();
1852             mUnpluggedReportedTotalTime = in.readLong();
1853             mTrackingReportedValues = in.readInt() == 1;
1854             mTimeBaseRunning = timeBase.isRunning();
1855         }
1856 
1857         @VisibleForTesting
SamplingTimer(Clocks clocks, TimeBase timeBase)1858         public SamplingTimer(Clocks clocks, TimeBase timeBase) {
1859             super(clocks, 0, timeBase);
1860             mTrackingReportedValues = false;
1861             mTimeBaseRunning = timeBase.isRunning();
1862         }
1863 
1864         /**
1865          * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to
1866          * be less than the values used for a previous invocation.
1867          */
endSample()1868         public void endSample() {
1869             mTotalTime = computeRunTimeLocked(0 /* unused by us */);
1870             mCount = computeCurrentCountLocked();
1871             mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = 0;
1872             mUnpluggedReportedCount = mCurrentReportedCount = 0;
1873         }
1874 
setUpdateVersion(int version)1875         public void setUpdateVersion(int version) {
1876             mUpdateVersion = version;
1877         }
1878 
getUpdateVersion()1879         public int getUpdateVersion() {
1880             return mUpdateVersion;
1881         }
1882 
1883         /**
1884          * Updates the current recorded values. These are meant to be monotonically increasing
1885          * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}.
1886          *
1887          * If the values being recorded have been reset, the monotonically increasing requirement
1888          * will be broken. In this case, {@link #endSample()} is automatically called and
1889          * the total value of totalTime and count are recorded, starting a new monotonically
1890          * increasing sample.
1891          *
1892          * @param totalTime total time of sample in microseconds.
1893          * @param count total number of times the event being sampled occurred.
1894          */
update(long totalTime, int count)1895         public void update(long totalTime, int count) {
1896             if (mTimeBaseRunning && !mTrackingReportedValues) {
1897                 // Updating the reported value for the first time.
1898                 mUnpluggedReportedTotalTime = totalTime;
1899                 mUnpluggedReportedCount = count;
1900             }
1901 
1902             mTrackingReportedValues = true;
1903 
1904             if (totalTime < mCurrentReportedTotalTime || count < mCurrentReportedCount) {
1905                 endSample();
1906             }
1907 
1908             mCurrentReportedTotalTime = totalTime;
1909             mCurrentReportedCount = count;
1910         }
1911 
1912         /**
1913          * Adds deltaTime and deltaCount to the current sample.
1914          *
1915          * @param deltaTime additional time recorded since the last sampled event, in microseconds.
1916          * @param deltaCount additional number of times the event being sampled occurred.
1917          */
add(long deltaTime, int deltaCount)1918         public void add(long deltaTime, int deltaCount) {
1919             update(mCurrentReportedTotalTime + deltaTime, mCurrentReportedCount + deltaCount);
1920         }
1921 
1922         @Override
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)1923         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1924             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
1925             if (mTrackingReportedValues) {
1926                 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
1927                 mUnpluggedReportedCount = mCurrentReportedCount;
1928             }
1929             mTimeBaseRunning = true;
1930         }
1931 
1932         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)1933         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1934             super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
1935             mTimeBaseRunning = false;
1936         }
1937 
1938         @Override
logState(Printer pw, String prefix)1939         public void logState(Printer pw, String prefix) {
1940             super.logState(pw, prefix);
1941             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
1942                     + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
1943                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
1944                     + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
1945         }
1946 
1947         @Override
computeRunTimeLocked(long curBatteryRealtime)1948         protected long computeRunTimeLocked(long curBatteryRealtime) {
1949             return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues
1950                     ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
1951         }
1952 
1953         @Override
computeCurrentCountLocked()1954         protected int computeCurrentCountLocked() {
1955             return mCount + (mTimeBaseRunning && mTrackingReportedValues
1956                     ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
1957         }
1958 
1959         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)1960         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1961             super.writeToParcel(out, elapsedRealtimeUs);
1962             out.writeInt(mCurrentReportedCount);
1963             out.writeInt(mUnpluggedReportedCount);
1964             out.writeLong(mCurrentReportedTotalTime);
1965             out.writeLong(mUnpluggedReportedTotalTime);
1966             out.writeInt(mTrackingReportedValues ? 1 : 0);
1967         }
1968 
1969         @Override
reset(boolean detachIfReset)1970         public boolean reset(boolean detachIfReset) {
1971             super.reset(detachIfReset);
1972             mTrackingReportedValues = false;
1973             mUnpluggedReportedTotalTime = 0;
1974             mUnpluggedReportedCount = 0;
1975             return true;
1976         }
1977     }
1978 
1979     /**
1980      * A timer that increments in batches.  It does not run for durations, but just jumps
1981      * for a pre-determined amount.
1982      */
1983     public static class BatchTimer extends Timer {
1984         final Uid mUid;
1985 
1986         /**
1987          * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
1988          */
1989         long mLastAddedTime;
1990 
1991         /**
1992          * The last duration that we added to the timer.  This is in microseconds.
1993          */
1994         long mLastAddedDuration;
1995 
1996         /**
1997          * Whether we are currently in a discharge cycle.
1998          */
1999         boolean mInDischarge;
2000 
BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in)2001         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in) {
2002             super(clocks, type, timeBase, in);
2003             mUid = uid;
2004             mLastAddedTime = in.readLong();
2005             mLastAddedDuration = in.readLong();
2006             mInDischarge = timeBase.isRunning();
2007         }
2008 
BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase)2009         BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase) {
2010             super(clocks, type, timeBase);
2011             mUid = uid;
2012             mInDischarge = timeBase.isRunning();
2013         }
2014 
2015         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2016         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2017             super.writeToParcel(out, elapsedRealtimeUs);
2018             out.writeLong(mLastAddedTime);
2019             out.writeLong(mLastAddedDuration);
2020         }
2021 
2022         @Override
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)2023         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
2024             recomputeLastDuration(mClocks.elapsedRealtime() * 1000, false);
2025             mInDischarge = false;
2026             super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
2027         }
2028 
2029         @Override
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)2030         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
2031             recomputeLastDuration(elapsedRealtime, false);
2032             mInDischarge = true;
2033             // If we are still within the last added duration, then re-added whatever remains.
2034             if (mLastAddedTime == elapsedRealtime) {
2035                 mTotalTime += mLastAddedDuration;
2036             }
2037             super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
2038         }
2039 
2040         @Override
logState(Printer pw, String prefix)2041         public void logState(Printer pw, String prefix) {
2042             super.logState(pw, prefix);
2043             pw.println(prefix + "mLastAddedTime=" + mLastAddedTime
2044                     + " mLastAddedDuration=" + mLastAddedDuration);
2045         }
2046 
computeOverage(long curTime)2047         private long computeOverage(long curTime) {
2048             if (mLastAddedTime > 0) {
2049                 return mLastAddedDuration - curTime;
2050             }
2051             return 0;
2052         }
2053 
recomputeLastDuration(long curTime, boolean abort)2054         private void recomputeLastDuration(long curTime, boolean abort) {
2055             final long overage = computeOverage(curTime);
2056             if (overage > 0) {
2057                 // Aborting before the duration ran out -- roll back the remaining
2058                 // duration.  Only do this if currently discharging; otherwise we didn't
2059                 // actually add the time.
2060                 if (mInDischarge) {
2061                     mTotalTime -= overage;
2062                 }
2063                 if (abort) {
2064                     mLastAddedTime = 0;
2065                 } else {
2066                     mLastAddedTime = curTime;
2067                     mLastAddedDuration -= overage;
2068                 }
2069             }
2070         }
2071 
addDuration(BatteryStatsImpl stats, long durationMillis)2072         public void addDuration(BatteryStatsImpl stats, long durationMillis) {
2073             final long now = mClocks.elapsedRealtime() * 1000;
2074             recomputeLastDuration(now, true);
2075             mLastAddedTime = now;
2076             mLastAddedDuration = durationMillis * 1000;
2077             if (mInDischarge) {
2078                 mTotalTime += mLastAddedDuration;
2079                 mCount++;
2080             }
2081         }
2082 
abortLastDuration(BatteryStatsImpl stats)2083         public void abortLastDuration(BatteryStatsImpl stats) {
2084             final long now = mClocks.elapsedRealtime() * 1000;
2085             recomputeLastDuration(now, true);
2086         }
2087 
2088         @Override
computeCurrentCountLocked()2089         protected int computeCurrentCountLocked() {
2090             return mCount;
2091         }
2092 
2093         @Override
computeRunTimeLocked(long curBatteryRealtime)2094         protected long computeRunTimeLocked(long curBatteryRealtime) {
2095             final long overage = computeOverage(mClocks.elapsedRealtime() * 1000);
2096             if (overage > 0) {
2097                 return mTotalTime = overage;
2098             }
2099             return mTotalTime;
2100         }
2101 
2102         @Override
reset(boolean detachIfReset)2103         public boolean reset(boolean detachIfReset) {
2104             final long now = mClocks.elapsedRealtime() * 1000;
2105             recomputeLastDuration(now, true);
2106             boolean stillActive = mLastAddedTime == now;
2107             super.reset(!stillActive && detachIfReset);
2108             return !stillActive;
2109         }
2110     }
2111 
2112 
2113     /**
2114      * A StopwatchTimer that also tracks the total and max individual
2115      * time spent active according to the given timebase.  Whereas
2116      * StopwatchTimer apportions the time amongst all in the pool,
2117      * the total and max durations are not apportioned.
2118      */
2119     public static class DurationTimer extends StopwatchTimer {
2120         /**
2121          * The time (in ms) that the timer was last acquired or the time base
2122          * last (re-)started. Increasing the nesting depth does not reset this time.
2123          *
2124          * -1 if the timer is currently not running or the time base is not running.
2125          *
2126          * If written to a parcel, the start time is reset, as is mNesting in the base class
2127          * StopwatchTimer.
2128          */
2129         long mStartTimeMs = -1;
2130 
2131         /**
2132          * The longest time period (in ms) that the timer has been active. Not pooled.
2133          */
2134         long mMaxDurationMs;
2135 
2136         /**
2137          * The time (in ms) that that the timer has been active since most recent
2138          * stopRunningLocked() or reset(). Not pooled.
2139          */
2140         long mCurrentDurationMs;
2141 
2142         /**
2143          * The total time (in ms) that that the timer has been active since most recent reset()
2144          * prior to the current startRunningLocked. This is the sum of all past currentDurations
2145          * (but not including the present currentDuration) since reset. Not pooled.
2146          */
2147         long mTotalDurationMs;
2148 
DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)2149         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2150                 TimeBase timeBase, Parcel in) {
2151             super(clocks, uid, type, timerPool, timeBase, in);
2152             mMaxDurationMs = in.readLong();
2153             mTotalDurationMs = in.readLong();
2154             mCurrentDurationMs = in.readLong();
2155         }
2156 
DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)2157         public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2158                 TimeBase timeBase) {
2159             super(clocks, uid, type, timerPool, timeBase);
2160         }
2161 
2162         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2163         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2164             super.writeToParcel(out, elapsedRealtimeUs);
2165             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2166             out.writeLong(mTotalDurationMs);
2167             out.writeLong(getCurrentDurationMsLocked(elapsedRealtimeUs / 1000));
2168         }
2169 
2170         /**
2171          * Write the summary to the parcel.
2172          *
2173          * Since the time base is probably meaningless after we come back, reading
2174          * from this will have the effect of stopping the timer. So here all we write
2175          * is the max and total durations.
2176          */
2177         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2178         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2179             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2180             out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2181             out.writeLong(getTotalDurationMsLocked(elapsedRealtimeUs / 1000));
2182         }
2183 
2184         /**
2185          * Read the summary parcel.
2186          *
2187          * Has the side effect of stopping the timer.
2188          */
2189         @Override
readSummaryFromParcelLocked(Parcel in)2190         public void readSummaryFromParcelLocked(Parcel in) {
2191             super.readSummaryFromParcelLocked(in);
2192             mMaxDurationMs = in.readLong();
2193             mTotalDurationMs = in.readLong();
2194             mStartTimeMs = -1;
2195             mCurrentDurationMs = 0;
2196         }
2197 
2198         /**
2199          * The TimeBase time started (again).
2200          *
2201          * If the timer is also running, store the start time.
2202          */
onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime)2203         public void onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime) {
2204             super.onTimeStarted(elapsedRealtimeUs, baseUptime, baseRealtime);
2205             if (mNesting > 0) {
2206                 mStartTimeMs = baseRealtime / 1000;
2207             }
2208         }
2209 
2210         /**
2211          * The TimeBase stopped running.
2212          *
2213          * If the timer is running, add the duration into mCurrentDurationMs.
2214          */
2215         @Override
onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtimeUs)2216         public void onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtimeUs) {
2217             super.onTimeStopped(elapsedRealtimeUs, baseUptime, baseRealtimeUs);
2218             if (mNesting > 0) {
2219                 // baseRealtimeUs has already been converted to the timebase's realtime.
2220                 mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
2221             }
2222             mStartTimeMs = -1;
2223         }
2224 
2225         @Override
logState(Printer pw, String prefix)2226         public void logState(Printer pw, String prefix) {
2227             super.logState(pw, prefix);
2228         }
2229 
2230         @Override
startRunningLocked(long elapsedRealtimeMs)2231         public void startRunningLocked(long elapsedRealtimeMs) {
2232             super.startRunningLocked(elapsedRealtimeMs);
2233             if (mNesting == 1 && mTimeBase.isRunning()) {
2234                 // Just started
2235                 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000;
2236             }
2237         }
2238 
2239         /**
2240          * Decrements the mNesting ref-count on this timer.
2241          *
2242          * If it actually stopped (mNesting went to 0), then possibly update
2243          * mMaxDuration if the current duration was the longest ever.
2244          */
2245         @Override
stopRunningLocked(long elapsedRealtimeMs)2246         public void stopRunningLocked(long elapsedRealtimeMs) {
2247             if (mNesting == 1) {
2248                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2249                 mTotalDurationMs += durationMs;
2250                 if (durationMs > mMaxDurationMs) {
2251                     mMaxDurationMs = durationMs;
2252                 }
2253                 mStartTimeMs = -1;
2254                 mCurrentDurationMs = 0;
2255             }
2256             // super method decrements mNesting, which getCurrentDurationMsLocked relies on,
2257             // so call super.stopRunningLocked after calling getCurrentDurationMsLocked.
2258             super.stopRunningLocked(elapsedRealtimeMs);
2259         }
2260 
2261         @Override
reset(boolean detachIfReset)2262         public boolean reset(boolean detachIfReset) {
2263             boolean result = super.reset(detachIfReset);
2264             mMaxDurationMs = 0;
2265             mTotalDurationMs = 0;
2266             mCurrentDurationMs = 0;
2267             if (mNesting > 0) {
2268                 mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000) / 1000;
2269             } else {
2270                 mStartTimeMs = -1;
2271             }
2272             return result;
2273         }
2274 
2275         /**
2276          * Returns the max duration that this timer has ever seen.
2277          *
2278          * Note that this time is NOT split between the timers in the timer group that
2279          * this timer is attached to.  It is the TOTAL time.
2280          */
2281         @Override
getMaxDurationMsLocked(long elapsedRealtimeMs)2282         public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
2283             if (mNesting > 0) {
2284                 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2285                 if (durationMs > mMaxDurationMs) {
2286                     return durationMs;
2287                 }
2288             }
2289             return mMaxDurationMs;
2290         }
2291 
2292         /**
2293          * Returns the time since the timer was started.
2294          * Returns 0 if the timer is not currently running.
2295          *
2296          * Note that this time is NOT split between the timers in the timer group that
2297          * this timer is attached to.  It is the TOTAL time.
2298          *
2299          * Note that if running timer is parceled and unparceled, this method will return
2300          * current duration value at the time of parceling even though timer may not be
2301          * currently running.
2302          */
2303         @Override
getCurrentDurationMsLocked(long elapsedRealtimeMs)2304         public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
2305             long durationMs = mCurrentDurationMs;
2306             if (mNesting > 0 && mTimeBase.isRunning()) {
2307                 durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000)
2308                         - mStartTimeMs;
2309             }
2310             return durationMs;
2311         }
2312 
2313         /**
2314          * Returns the total cumulative duration that this timer has been on since reset().
2315          * If mTimerPool == null, this should be the same
2316          * as getTotalTimeLocked(elapsedRealtimeMs*1000, STATS_SINCE_CHARGED)/1000.
2317          *
2318          * Note that this time is NOT split between the timers in the timer group that
2319          * this timer is attached to.  It is the TOTAL time. For this reason, if mTimerPool != null,
2320          * the result will not be equivalent to getTotalTimeLocked.
2321          */
2322         @Override
getTotalDurationMsLocked(long elapsedRealtimeMs)2323         public long getTotalDurationMsLocked(long elapsedRealtimeMs) {
2324             return mTotalDurationMs + getCurrentDurationMsLocked(elapsedRealtimeMs);
2325         }
2326     }
2327 
2328     /**
2329      * State for keeping track of timing information.
2330      */
2331     public static class StopwatchTimer extends Timer {
2332         final Uid mUid;
2333         final ArrayList<StopwatchTimer> mTimerPool;
2334 
2335         int mNesting;
2336 
2337         /**
2338          * The last time at which we updated the timer.  If mNesting is > 0,
2339          * subtract this from the current battery time to find the amount of
2340          * time we have been running since we last computed an update.
2341          */
2342         long mUpdateTime;
2343 
2344         /**
2345          * The total time at which the timer was acquired, to determine if it
2346          * was actually held for an interesting duration. If time base was not running when timer
2347          * was acquired, will be -1.
2348          */
2349         long mAcquireTime = -1;
2350 
2351         long mTimeout;
2352 
2353         /**
2354          * For partial wake locks, keep track of whether we are in the list
2355          * to consume CPU cycles.
2356          */
2357         @VisibleForTesting
2358         public boolean mInList;
2359 
StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, Parcel in)2360         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2361                 TimeBase timeBase, Parcel in) {
2362             super(clocks, type, timeBase, in);
2363             mUid = uid;
2364             mTimerPool = timerPool;
2365             mUpdateTime = in.readLong();
2366         }
2367 
StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase)2368         public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2369                 TimeBase timeBase) {
2370             super(clocks, type, timeBase);
2371             mUid = uid;
2372             mTimerPool = timerPool;
2373         }
2374 
setTimeout(long timeout)2375         public void setTimeout(long timeout) {
2376             mTimeout = timeout;
2377         }
2378 
writeToParcel(Parcel out, long elapsedRealtimeUs)2379         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2380             super.writeToParcel(out, elapsedRealtimeUs);
2381             out.writeLong(mUpdateTime);
2382         }
2383 
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)2384         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
2385             if (mNesting > 0) {
2386                 if (DEBUG && mType < 0) {
2387                     Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
2388                 }
2389                 super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
2390                 mUpdateTime = baseRealtime;
2391                 if (DEBUG && mType < 0) {
2392                     Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
2393                 }
2394             }
2395         }
2396 
logState(Printer pw, String prefix)2397         public void logState(Printer pw, String prefix) {
2398             super.logState(pw, prefix);
2399             pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTime
2400                     + " mAcquireTime=" + mAcquireTime);
2401         }
2402 
startRunningLocked(long elapsedRealtimeMs)2403         public void startRunningLocked(long elapsedRealtimeMs) {
2404             if (mNesting++ == 0) {
2405                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2406                 mUpdateTime = batteryRealtime;
2407                 if (mTimerPool != null) {
2408                     // Accumulate time to all currently active timers before adding
2409                     // this new one to the pool.
2410                     refreshTimersLocked(batteryRealtime, mTimerPool, null);
2411                     // Add this timer to the active pool
2412                     mTimerPool.add(this);
2413                 }
2414                 if (mTimeBase.isRunning()) {
2415                     // Increment the count
2416                     mCount++;
2417                     mAcquireTime = mTotalTime;
2418                 } else {
2419                     mAcquireTime = -1;
2420                 }
2421                 if (DEBUG && mType < 0) {
2422                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
2423                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
2424                             + " mAcquireTime=" + mAcquireTime);
2425                 }
2426             }
2427         }
2428 
isRunningLocked()2429         public boolean isRunningLocked() {
2430             return mNesting > 0;
2431         }
2432 
stopRunningLocked(long elapsedRealtimeMs)2433         public void stopRunningLocked(long elapsedRealtimeMs) {
2434             // Ignore attempt to stop a timer that isn't running
2435             if (mNesting == 0) {
2436                 return;
2437             }
2438             if (--mNesting == 0) {
2439                 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2440                 if (mTimerPool != null) {
2441                     // Accumulate time to all active counters, scaled by the total
2442                     // active in the pool, before taking this one out of the pool.
2443                     refreshTimersLocked(batteryRealtime, mTimerPool, null);
2444                     // Remove this timer from the active pool
2445                     mTimerPool.remove(this);
2446                 } else {
2447                     mNesting = 1;
2448                     mTotalTime = computeRunTimeLocked(batteryRealtime);
2449                     mNesting = 0;
2450                 }
2451 
2452                 if (DEBUG && mType < 0) {
2453                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
2454                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
2455                             + " mAcquireTime=" + mAcquireTime);
2456                 }
2457 
2458                 if (mAcquireTime >= 0 && mTotalTime == mAcquireTime) {
2459                     // If there was no change in the time, then discard this
2460                     // count.  A somewhat cheezy strategy, but hey.
2461                     mCount--;
2462                 }
2463             }
2464         }
2465 
stopAllRunningLocked(long elapsedRealtimeMs)2466         public void stopAllRunningLocked(long elapsedRealtimeMs) {
2467             if (mNesting > 0) {
2468                 mNesting = 1;
2469                 stopRunningLocked(elapsedRealtimeMs);
2470             }
2471         }
2472 
2473         // Update the total time for all other running Timers with the same type as this Timer
2474         // due to a change in timer count
refreshTimersLocked(long batteryRealtime, final ArrayList<StopwatchTimer> pool, StopwatchTimer self)2475         private static long refreshTimersLocked(long batteryRealtime,
2476                 final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
2477             long selfTime = 0;
2478             final int N = pool.size();
2479             for (int i=N-1; i>= 0; i--) {
2480                 final StopwatchTimer t = pool.get(i);
2481                 long heldTime = batteryRealtime - t.mUpdateTime;
2482                 if (heldTime > 0) {
2483                     final long myTime = heldTime / N;
2484                     if (t == self) {
2485                         selfTime = myTime;
2486                     }
2487                     t.mTotalTime += myTime;
2488                 }
2489                 t.mUpdateTime = batteryRealtime;
2490             }
2491             return selfTime;
2492         }
2493 
2494         @Override
computeRunTimeLocked(long curBatteryRealtime)2495         protected long computeRunTimeLocked(long curBatteryRealtime) {
2496             if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) {
2497                 curBatteryRealtime = mUpdateTime + mTimeout;
2498             }
2499             return mTotalTime + (mNesting > 0
2500                     ? (curBatteryRealtime - mUpdateTime)
2501                             / (mTimerPool != null ? mTimerPool.size() : 1)
2502                     : 0);
2503         }
2504 
2505         @Override
computeCurrentCountLocked()2506         protected int computeCurrentCountLocked() {
2507             return mCount;
2508         }
2509 
2510         @Override
reset(boolean detachIfReset)2511         public boolean reset(boolean detachIfReset) {
2512             boolean canDetach = mNesting <= 0;
2513             super.reset(canDetach && detachIfReset);
2514             if (mNesting > 0) {
2515                 mUpdateTime = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000);
2516             }
2517             mAcquireTime = -1; // to ensure mCount isn't decreased to -1 if timer is stopped later.
2518             return canDetach;
2519         }
2520 
2521         @Override
2522         @UnsupportedAppUsage
detach()2523         public void detach() {
2524             super.detach();
2525             if (mTimerPool != null) {
2526                 mTimerPool.remove(this);
2527             }
2528         }
2529 
2530         @Override
readSummaryFromParcelLocked(Parcel in)2531         public void readSummaryFromParcelLocked(Parcel in) {
2532             super.readSummaryFromParcelLocked(in);
2533             mNesting = 0;
2534         }
2535 
2536         /**
2537          * Set the mark so that we can query later for the total time the timer has
2538          * accumulated since this point. The timer can be running or not.
2539          *
2540          * @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
2541          */
setMark(long elapsedRealtimeMs)2542         public void setMark(long elapsedRealtimeMs) {
2543             final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2544             if (mNesting > 0) {
2545                 // We are running.
2546                 if (mTimerPool != null) {
2547                     refreshTimersLocked(batteryRealtime, mTimerPool, this);
2548                 } else {
2549                     mTotalTime += batteryRealtime - mUpdateTime;
2550                     mUpdateTime = batteryRealtime;
2551                 }
2552             }
2553             mTimeBeforeMark = mTotalTime;
2554         }
2555     }
2556 
2557     /**
2558      * State for keeping track of two DurationTimers with different TimeBases, presumably where one
2559      * TimeBase is effectively a subset of the other.
2560      */
2561     public static class DualTimer extends DurationTimer {
2562         // This class both is a DurationTimer and also holds a second DurationTimer.
2563         // The main timer (this) typically tracks the total time. It may be pooled (but since it's a
2564         // durationTimer, it also has the unpooled getTotalDurationMsLocked() for
2565         // STATS_SINCE_CHARGED).
2566         // mSubTimer typically tracks only part of the total time, such as background time, as
2567         // determined by a subTimeBase. It is NOT pooled.
2568         private final DurationTimer mSubTimer;
2569 
2570         /**
2571          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2572          * The main timer (this) is based on the given timeBase and timerPool.
2573          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2574          * the main timer is.
2575          */
DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase, Parcel in)2576         public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2577                 TimeBase timeBase, TimeBase subTimeBase, Parcel in) {
2578             super(clocks, uid, type, timerPool, timeBase, in);
2579             mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase, in);
2580         }
2581 
2582         /**
2583          * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2584          * The main timer (this) is based on the given timeBase and timerPool.
2585          * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2586          * the main timer is.
2587          */
DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, TimeBase timeBase, TimeBase subTimeBase)2588         public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2589                 TimeBase timeBase, TimeBase subTimeBase) {
2590             super(clocks, uid, type, timerPool, timeBase);
2591             mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase);
2592         }
2593 
2594         /** Get the secondary timer. */
2595         @Override
getSubTimer()2596         public DurationTimer getSubTimer() {
2597             return mSubTimer;
2598         }
2599 
2600         @Override
startRunningLocked(long elapsedRealtimeMs)2601         public void startRunningLocked(long elapsedRealtimeMs) {
2602             super.startRunningLocked(elapsedRealtimeMs);
2603             mSubTimer.startRunningLocked(elapsedRealtimeMs);
2604         }
2605 
2606         @Override
stopRunningLocked(long elapsedRealtimeMs)2607         public void stopRunningLocked(long elapsedRealtimeMs) {
2608             super.stopRunningLocked(elapsedRealtimeMs);
2609             mSubTimer.stopRunningLocked(elapsedRealtimeMs);
2610         }
2611 
2612         @Override
stopAllRunningLocked(long elapsedRealtimeMs)2613         public void stopAllRunningLocked(long elapsedRealtimeMs) {
2614             super.stopAllRunningLocked(elapsedRealtimeMs);
2615             mSubTimer.stopAllRunningLocked(elapsedRealtimeMs);
2616         }
2617 
2618         @Override
reset(boolean detachIfReset)2619         public boolean reset(boolean detachIfReset) {
2620             boolean active = false;
2621             // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
2622             active |= !mSubTimer.reset(false);
2623             active |= !super.reset(detachIfReset);
2624             return !active;
2625         }
2626 
2627         @Override
detach()2628         public void detach() {
2629             mSubTimer.detach();
2630             super.detach();
2631         }
2632 
2633         @Override
writeToParcel(Parcel out, long elapsedRealtimeUs)2634         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2635             super.writeToParcel(out, elapsedRealtimeUs);
2636             mSubTimer.writeToParcel(out, elapsedRealtimeUs);
2637         }
2638 
2639         @Override
writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs)2640         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2641             super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2642             mSubTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2643         }
2644 
2645         @Override
readSummaryFromParcelLocked(Parcel in)2646         public void readSummaryFromParcelLocked(Parcel in) {
2647             super.readSummaryFromParcelLocked(in);
2648             mSubTimer.readSummaryFromParcelLocked(in);
2649         }
2650     }
2651 
2652 
2653     public abstract class OverflowArrayMap<T> {
2654         private static final String OVERFLOW_NAME = "*overflow*";
2655 
2656         final int mUid;
2657         final ArrayMap<String, T> mMap = new ArrayMap<>();
2658         T mCurOverflow;
2659         ArrayMap<String, MutableInt> mActiveOverflow;
2660         long mLastOverflowTime;
2661         long mLastOverflowFinishTime;
2662         long mLastClearTime;
2663         long mLastCleanupTime;
2664 
OverflowArrayMap(int uid)2665         public OverflowArrayMap(int uid) {
2666             mUid = uid;
2667         }
2668 
getMap()2669         public ArrayMap<String, T> getMap() {
2670             return mMap;
2671         }
2672 
clear()2673         public void clear() {
2674             mLastClearTime = SystemClock.elapsedRealtime();
2675             mMap.clear();
2676             mCurOverflow = null;
2677             mActiveOverflow = null;
2678         }
2679 
add(String name, T obj)2680         public void add(String name, T obj) {
2681             if (name == null) {
2682                 name = "";
2683             }
2684             mMap.put(name, obj);
2685             if (OVERFLOW_NAME.equals(name)) {
2686                 mCurOverflow = obj;
2687             }
2688         }
2689 
cleanup()2690         public void cleanup() {
2691             mLastCleanupTime = SystemClock.elapsedRealtime();
2692             if (mActiveOverflow != null) {
2693                 if (mActiveOverflow.size() == 0) {
2694                     mActiveOverflow = null;
2695                 }
2696             }
2697             if (mActiveOverflow == null) {
2698                 // There is no currently active overflow, so we should no longer have
2699                 // an overflow entry.
2700                 if (mMap.containsKey(OVERFLOW_NAME)) {
2701                     Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
2702                             + mMap.get(OVERFLOW_NAME));
2703                     mMap.remove(OVERFLOW_NAME);
2704                 }
2705                 mCurOverflow = null;
2706             } else {
2707                 // There is currently active overflow, so we should still have an overflow entry.
2708                 if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
2709                     Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
2710                             + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
2711                 }
2712             }
2713         }
2714 
startObject(String name)2715         public T startObject(String name) {
2716             if (name == null) {
2717                 name = "";
2718             }
2719             T obj = mMap.get(name);
2720             if (obj != null) {
2721                 return obj;
2722             }
2723 
2724             // No object exists for the given name, but do we currently have it
2725             // running as part of the overflow?
2726             if (mActiveOverflow != null) {
2727                 MutableInt over = mActiveOverflow.get(name);
2728                 if (over != null) {
2729                     // We are already actively counting this name in the overflow object.
2730                     obj = mCurOverflow;
2731                     if (obj == null) {
2732                         // Shouldn't be here, but we'll try to recover.
2733                         Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
2734                         obj = mCurOverflow = instantiateObject();
2735                         mMap.put(OVERFLOW_NAME, obj);
2736                     }
2737                     over.value++;
2738                     return obj;
2739                 }
2740             }
2741 
2742             // No object exists for given name nor in the overflow; we need to make
2743             // a new one.
2744             final int N = mMap.size();
2745             if (N >= MAX_WAKELOCKS_PER_UID) {
2746                 // Went over the limit on number of objects to track; this one goes
2747                 // in to the overflow.
2748                 obj = mCurOverflow;
2749                 if (obj == null) {
2750                     // Need to start overflow now...
2751                     obj = mCurOverflow = instantiateObject();
2752                     mMap.put(OVERFLOW_NAME, obj);
2753                 }
2754                 if (mActiveOverflow == null) {
2755                     mActiveOverflow = new ArrayMap<>();
2756                 }
2757                 mActiveOverflow.put(name, new MutableInt(1));
2758                 mLastOverflowTime = SystemClock.elapsedRealtime();
2759                 return obj;
2760             }
2761 
2762             // Normal case where we just need to make a new object.
2763             obj = instantiateObject();
2764             mMap.put(name, obj);
2765             return obj;
2766         }
2767 
stopObject(String name)2768         public T stopObject(String name) {
2769             if (name == null) {
2770                 name = "";
2771             }
2772             T obj = mMap.get(name);
2773             if (obj != null) {
2774                 return obj;
2775             }
2776 
2777             // No object exists for the given name, but do we currently have it
2778             // running as part of the overflow?
2779             if (mActiveOverflow != null) {
2780                 MutableInt over = mActiveOverflow.get(name);
2781                 if (over != null) {
2782                     // We are already actively counting this name in the overflow object.
2783                     obj = mCurOverflow;
2784                     if (obj != null) {
2785                         over.value--;
2786                         if (over.value <= 0) {
2787                             mActiveOverflow.remove(name);
2788                             mLastOverflowFinishTime = SystemClock.elapsedRealtime();
2789                         }
2790                         return obj;
2791                     }
2792                 }
2793             }
2794 
2795             // Huh, they are stopping an active operation but we can't find one!
2796             // That's not good.
2797             StringBuilder sb = new StringBuilder();
2798             sb.append("Unable to find object for ");
2799             sb.append(name);
2800             sb.append(" in uid ");
2801             sb.append(mUid);
2802             sb.append(" mapsize=");
2803             sb.append(mMap.size());
2804             sb.append(" activeoverflow=");
2805             sb.append(mActiveOverflow);
2806             sb.append(" curoverflow=");
2807             sb.append(mCurOverflow);
2808             long now = SystemClock.elapsedRealtime();
2809             if (mLastOverflowTime != 0) {
2810                 sb.append(" lastOverflowTime=");
2811                 TimeUtils.formatDuration(mLastOverflowTime-now, sb);
2812             }
2813             if (mLastOverflowFinishTime != 0) {
2814                 sb.append(" lastOverflowFinishTime=");
2815                 TimeUtils.formatDuration(mLastOverflowFinishTime-now, sb);
2816             }
2817             if (mLastClearTime != 0) {
2818                 sb.append(" lastClearTime=");
2819                 TimeUtils.formatDuration(mLastClearTime-now, sb);
2820             }
2821             if (mLastCleanupTime != 0) {
2822                 sb.append(" lastCleanupTime=");
2823                 TimeUtils.formatDuration(mLastCleanupTime-now, sb);
2824             }
2825             Slog.wtf(TAG, sb.toString());
2826             return null;
2827         }
2828 
instantiateObject()2829         public abstract T instantiateObject();
2830     }
2831 
2832     public static class ControllerActivityCounterImpl extends ControllerActivityCounter
2833             implements Parcelable {
2834         private final LongSamplingCounter mIdleTimeMillis;
2835         private final LongSamplingCounter mScanTimeMillis;
2836         private final LongSamplingCounter mSleepTimeMillis;
2837         private final LongSamplingCounter mRxTimeMillis;
2838         private final LongSamplingCounter[] mTxTimeMillis;
2839         private final LongSamplingCounter mPowerDrainMaMs;
2840         private final LongSamplingCounter mMonitoredRailChargeConsumedMaMs;
2841 
ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates)2842         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates) {
2843             mIdleTimeMillis = new LongSamplingCounter(timeBase);
2844             mScanTimeMillis = new LongSamplingCounter(timeBase);
2845             mSleepTimeMillis = new LongSamplingCounter(timeBase);
2846             mRxTimeMillis = new LongSamplingCounter(timeBase);
2847             mTxTimeMillis = new LongSamplingCounter[numTxStates];
2848             for (int i = 0; i < numTxStates; i++) {
2849                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase);
2850             }
2851             mPowerDrainMaMs = new LongSamplingCounter(timeBase);
2852             mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase);
2853         }
2854 
ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in)2855         public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in) {
2856             mIdleTimeMillis = new LongSamplingCounter(timeBase, in);
2857             mScanTimeMillis = new LongSamplingCounter(timeBase, in);
2858             mSleepTimeMillis = new LongSamplingCounter(timeBase, in);
2859             mRxTimeMillis = new LongSamplingCounter(timeBase, in);
2860             final int recordedTxStates = in.readInt();
2861             if (recordedTxStates != numTxStates) {
2862                 throw new ParcelFormatException("inconsistent tx state lengths");
2863             }
2864 
2865             mTxTimeMillis = new LongSamplingCounter[numTxStates];
2866             for (int i = 0; i < numTxStates; i++) {
2867                 mTxTimeMillis[i] = new LongSamplingCounter(timeBase, in);
2868             }
2869             mPowerDrainMaMs = new LongSamplingCounter(timeBase, in);
2870             mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase, in);
2871         }
2872 
readSummaryFromParcel(Parcel in)2873         public void readSummaryFromParcel(Parcel in) {
2874             mIdleTimeMillis.readSummaryFromParcelLocked(in);
2875             mScanTimeMillis.readSummaryFromParcelLocked(in);
2876             mSleepTimeMillis.readSummaryFromParcelLocked(in);
2877             mRxTimeMillis.readSummaryFromParcelLocked(in);
2878             final int recordedTxStates = in.readInt();
2879             if (recordedTxStates != mTxTimeMillis.length) {
2880                 throw new ParcelFormatException("inconsistent tx state lengths");
2881             }
2882             for (LongSamplingCounter counter : mTxTimeMillis) {
2883                 counter.readSummaryFromParcelLocked(in);
2884             }
2885             mPowerDrainMaMs.readSummaryFromParcelLocked(in);
2886             mMonitoredRailChargeConsumedMaMs.readSummaryFromParcelLocked(in);
2887         }
2888 
2889         @Override
describeContents()2890         public int describeContents() {
2891             return 0;
2892         }
2893 
writeSummaryToParcel(Parcel dest)2894         public void writeSummaryToParcel(Parcel dest) {
2895             mIdleTimeMillis.writeSummaryFromParcelLocked(dest);
2896             mScanTimeMillis.writeSummaryFromParcelLocked(dest);
2897             mSleepTimeMillis.writeSummaryFromParcelLocked(dest);
2898             mRxTimeMillis.writeSummaryFromParcelLocked(dest);
2899             dest.writeInt(mTxTimeMillis.length);
2900             for (LongSamplingCounter counter : mTxTimeMillis) {
2901                 counter.writeSummaryFromParcelLocked(dest);
2902             }
2903             mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
2904             mMonitoredRailChargeConsumedMaMs.writeSummaryFromParcelLocked(dest);
2905         }
2906 
2907         @Override
writeToParcel(Parcel dest, int flags)2908         public void writeToParcel(Parcel dest, int flags) {
2909             mIdleTimeMillis.writeToParcel(dest);
2910             mScanTimeMillis.writeToParcel(dest);
2911             mSleepTimeMillis.writeToParcel(dest);
2912             mRxTimeMillis.writeToParcel(dest);
2913             dest.writeInt(mTxTimeMillis.length);
2914             for (LongSamplingCounter counter : mTxTimeMillis) {
2915                 counter.writeToParcel(dest);
2916             }
2917             mPowerDrainMaMs.writeToParcel(dest);
2918             mMonitoredRailChargeConsumedMaMs.writeToParcel(dest);
2919         }
2920 
reset(boolean detachIfReset)2921         public void reset(boolean detachIfReset) {
2922             mIdleTimeMillis.reset(detachIfReset);
2923             mScanTimeMillis.reset(detachIfReset);
2924             mSleepTimeMillis.reset(detachIfReset);
2925             mRxTimeMillis.reset(detachIfReset);
2926             for (LongSamplingCounter counter : mTxTimeMillis) {
2927                 counter.reset(detachIfReset);
2928             }
2929             mPowerDrainMaMs.reset(detachIfReset);
2930             mMonitoredRailChargeConsumedMaMs.reset(detachIfReset);
2931         }
2932 
detach()2933         public void detach() {
2934             mIdleTimeMillis.detach();
2935             mScanTimeMillis.detach();
2936             mSleepTimeMillis.detach();
2937             mRxTimeMillis.detach();
2938             for (LongSamplingCounter counter : mTxTimeMillis) {
2939                 counter.detach();
2940             }
2941             mPowerDrainMaMs.detach();
2942             mMonitoredRailChargeConsumedMaMs.detach();
2943         }
2944 
2945         /**
2946          * @return a LongSamplingCounter, measuring time spent in the idle state in
2947          * milliseconds.
2948          */
2949         @Override
getIdleTimeCounter()2950         public LongSamplingCounter getIdleTimeCounter() {
2951             return mIdleTimeMillis;
2952         }
2953 
2954         /**
2955          * @return a LongSamplingCounter, measuring time spent in the scan state in
2956          * milliseconds.
2957          */
2958         @Override
getScanTimeCounter()2959         public LongSamplingCounter getScanTimeCounter() {
2960             return mScanTimeMillis;
2961         }
2962 
2963         /**
2964          * @return a LongSamplingCounter, measuring time spent in the sleep state in
2965          * milliseconds.
2966          */
2967         @Override
getSleepTimeCounter()2968         public LongSamplingCounter getSleepTimeCounter() {
2969             return mSleepTimeMillis;
2970         }
2971 
2972         /**
2973          * @return a LongSamplingCounter, measuring time spent in the receive state in
2974          * milliseconds.
2975          */
2976         @Override
getRxTimeCounter()2977         public LongSamplingCounter getRxTimeCounter() {
2978             return mRxTimeMillis;
2979         }
2980 
2981         /**
2982          * @return a LongSamplingCounter[], measuring time spent in various transmit states in
2983          * milliseconds.
2984          */
2985         @Override
getTxTimeCounters()2986         public LongSamplingCounter[] getTxTimeCounters() {
2987             return mTxTimeMillis;
2988         }
2989 
2990         /**
2991          * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
2992          */
2993         @Override
getPowerCounter()2994         public LongSamplingCounter getPowerCounter() {
2995             return mPowerDrainMaMs;
2996         }
2997 
2998         /**
2999          * @return a LongSamplingCounter, measuring actual monitored rail energy consumed
3000          * milli-ampere milli-seconds (mAmS).
3001          */
3002         @Override
getMonitoredRailChargeConsumedMaMs()3003         public LongSamplingCounter getMonitoredRailChargeConsumedMaMs() {
3004             return mMonitoredRailChargeConsumedMaMs;
3005         }
3006     }
3007 
3008     /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */
getRpmTimerLocked(String name)3009     public SamplingTimer getRpmTimerLocked(String name) {
3010         SamplingTimer rpmt = mRpmStats.get(name);
3011         if (rpmt == null) {
3012             rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3013             mRpmStats.put(name, rpmt);
3014         }
3015         return rpmt;
3016     }
3017 
3018     /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */
getScreenOffRpmTimerLocked(String name)3019     public SamplingTimer getScreenOffRpmTimerLocked(String name) {
3020         SamplingTimer rpmt = mScreenOffRpmStats.get(name);
3021         if (rpmt == null) {
3022             rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
3023             mScreenOffRpmStats.put(name, rpmt);
3024         }
3025         return rpmt;
3026     }
3027 
3028     /*
3029      * Get the wakeup reason counter, and create a new one if one
3030      * doesn't already exist.
3031      */
getWakeupReasonTimerLocked(String name)3032     public SamplingTimer getWakeupReasonTimerLocked(String name) {
3033         SamplingTimer timer = mWakeupReasonStats.get(name);
3034         if (timer == null) {
3035             timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3036             mWakeupReasonStats.put(name, timer);
3037         }
3038         return timer;
3039     }
3040 
3041     /*
3042      * Get the KernelWakelockTimer associated with name, and create a new one if one
3043      * doesn't already exist.
3044      */
getKernelWakelockTimerLocked(String name)3045     public SamplingTimer getKernelWakelockTimerLocked(String name) {
3046         SamplingTimer kwlt = mKernelWakelockStats.get(name);
3047         if (kwlt == null) {
3048             kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
3049             mKernelWakelockStats.put(name, kwlt);
3050         }
3051         return kwlt;
3052     }
3053 
getKernelMemoryTimerLocked(long bucket)3054     public SamplingTimer getKernelMemoryTimerLocked(long bucket) {
3055         SamplingTimer kmt = mKernelMemoryStats.get(bucket);
3056         if (kmt == null) {
3057             kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3058             mKernelMemoryStats.put(bucket, kmt);
3059         }
3060         return kmt;
3061     }
3062 
writeHistoryTag(HistoryTag tag)3063     private int writeHistoryTag(HistoryTag tag) {
3064         Integer idxObj = mHistoryTagPool.get(tag);
3065         int idx;
3066         if (idxObj != null) {
3067             idx = idxObj;
3068         } else {
3069             idx = mNextHistoryTagIdx;
3070             HistoryTag key = new HistoryTag();
3071             key.setTo(tag);
3072             tag.poolIdx = idx;
3073             mHistoryTagPool.put(key, idx);
3074             mNextHistoryTagIdx++;
3075             mNumHistoryTagChars += key.string.length() + 1;
3076         }
3077         return idx;
3078     }
3079 
readHistoryTag(int index, HistoryTag tag)3080     private void readHistoryTag(int index, HistoryTag tag) {
3081         if (index < mReadHistoryStrings.length) {
3082             tag.string = mReadHistoryStrings[index];
3083             tag.uid = mReadHistoryUids[index];
3084         } else {
3085             tag.string = null;
3086             tag.uid = 0;
3087         }
3088         tag.poolIdx = index;
3089     }
3090 
3091     /*
3092         The history delta format uses flags to denote further data in subsequent ints in the parcel.
3093 
3094         There is always the first token, which may contain the delta time, or an indicator of
3095         the length of the time (int or long) following this token.
3096 
3097         First token: always present,
3098         31              23              15               7             0
3099         █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█
3100 
3101         T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
3102            follows containing the time, and 0x7ffff indicates a long immediately follows with the
3103            delta time.
3104         A: battery level changed and an int follows with battery data.
3105         B: state changed and an int follows with state change data.
3106         C: state2 has changed and an int follows with state2 change data.
3107         D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
3108         E: event data has changed and an event struct follows.
3109         F: battery charge in coulombs has changed and an int with the charge follows.
3110         G: state flag denoting that the mobile radio was active.
3111         H: state flag denoting that the wifi radio was active.
3112         I: state flag denoting that a wifi scan occurred.
3113         J: state flag denoting that a wifi full lock was held.
3114         K: state flag denoting that the gps was on.
3115         L: state flag denoting that a wakelock was held.
3116         M: state flag denoting that the cpu was running.
3117 
3118         Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
3119         with the time delta.
3120 
3121         Battery level int: if A in the first token is set,
3122         31              23              15               7             0
3123         █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█
3124 
3125         D: indicates that extra history details follow.
3126         V: the battery voltage.
3127         T: the battery temperature.
3128         L: the battery level (out of 100).
3129 
3130         State change int: if B in the first token is set,
3131         31              23              15               7             0
3132         █S|S|S|H|H|H|P|P█F|E|D|C|B| | |A█ | | | | | | | █ | | | | | | | █
3133 
3134         A: wifi multicast was on.
3135         B: battery was plugged in.
3136         C: screen was on.
3137         D: phone was scanning for signal.
3138         E: audio was on.
3139         F: a sensor was active.
3140 
3141         State2 change int: if C in the first token is set,
3142         31              23              15               7             0
3143         █M|L|K|J|I|H|H|G█F|E|D|C| | | | █ | | | | | | | █ |B|B|B|A|A|A|A█
3144 
3145         A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
3146         B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
3147         C: a bluetooth scan was active.
3148         D: the camera was active.
3149         E: bluetooth was on.
3150         F: a phone call was active.
3151         G: the device was charging.
3152         H: 2 bits indicating the device-idle (doze) state: off, light, full
3153         I: the flashlight was on.
3154         J: wifi was on.
3155         K: wifi was running.
3156         L: video was playing.
3157         M: power save mode was on.
3158 
3159         Wakelock/wakereason struct: if D in the first token is set,
3160         TODO(adamlesinski): describe wakelock/wakereason struct.
3161 
3162         Event struct: if E in the first token is set,
3163         TODO(adamlesinski): describe the event struct.
3164 
3165         History step details struct: if D in the battery level int is set,
3166         TODO(adamlesinski): describe the history step details struct.
3167 
3168         Battery charge int: if F in the first token is set, an int representing the battery charge
3169         in coulombs follows.
3170      */
3171 
3172     // Part of initial delta int that specifies the time delta.
3173     static final int DELTA_TIME_MASK = 0x7ffff;
3174     static final int DELTA_TIME_LONG = 0x7ffff;   // The delta is a following long
3175     static final int DELTA_TIME_INT = 0x7fffe;    // The delta is a following int
3176     static final int DELTA_TIME_ABS = 0x7fffd;    // Following is an entire abs update.
3177     // Flag in delta int: a new battery level int follows.
3178     static final int DELTA_BATTERY_LEVEL_FLAG               = 0x00080000;
3179     // Flag in delta int: a new full state and battery status int follows.
3180     static final int DELTA_STATE_FLAG                       = 0x00100000;
3181     // Flag in delta int: a new full state2 int follows.
3182     static final int DELTA_STATE2_FLAG                      = 0x00200000;
3183     // Flag in delta int: contains a wakelock or wakeReason tag.
3184     static final int DELTA_WAKELOCK_FLAG                    = 0x00400000;
3185     // Flag in delta int: contains an event description.
3186     static final int DELTA_EVENT_FLAG                       = 0x00800000;
3187     // Flag in delta int: contains the battery charge count in uAh.
3188     static final int DELTA_BATTERY_CHARGE_FLAG              = 0x01000000;
3189     // These upper bits are the frequently changing state bits.
3190     static final int DELTA_STATE_MASK                       = 0xfe000000;
3191 
3192     // These are the pieces of battery state that are packed in to the upper bits of
3193     // the state int that have been packed in to the first delta int.  They must fit
3194     // in STATE_BATTERY_MASK.
3195     static final int STATE_BATTERY_MASK         = 0xff000000;
3196     static final int STATE_BATTERY_STATUS_MASK  = 0x00000007;
3197     static final int STATE_BATTERY_STATUS_SHIFT = 29;
3198     static final int STATE_BATTERY_HEALTH_MASK  = 0x00000007;
3199     static final int STATE_BATTERY_HEALTH_SHIFT = 26;
3200     static final int STATE_BATTERY_PLUG_MASK    = 0x00000003;
3201     static final int STATE_BATTERY_PLUG_SHIFT   = 24;
3202 
3203     // We use the low bit of the battery state int to indicate that we have full details
3204     // from a battery level change.
3205     static final int BATTERY_DELTA_LEVEL_FLAG   = 0x00000001;
3206 
writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last)3207     public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
3208         if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
3209             dest.writeInt(DELTA_TIME_ABS);
3210             cur.writeToParcel(dest, 0);
3211             return;
3212         }
3213 
3214         final long deltaTime = cur.time - last.time;
3215         final int lastBatteryLevelInt = buildBatteryLevelInt(last);
3216         final int lastStateInt = buildStateInt(last);
3217 
3218         int deltaTimeToken;
3219         if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
3220             deltaTimeToken = DELTA_TIME_LONG;
3221         } else if (deltaTime >= DELTA_TIME_ABS) {
3222             deltaTimeToken = DELTA_TIME_INT;
3223         } else {
3224             deltaTimeToken = (int)deltaTime;
3225         }
3226         int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
3227         final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
3228                 ? BATTERY_DELTA_LEVEL_FLAG : 0;
3229         final boolean computeStepDetails = includeStepDetails != 0
3230                 || mLastHistoryStepDetails == null;
3231         final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
3232         final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
3233         if (batteryLevelIntChanged) {
3234             firstToken |= DELTA_BATTERY_LEVEL_FLAG;
3235         }
3236         final int stateInt = buildStateInt(cur);
3237         final boolean stateIntChanged = stateInt != lastStateInt;
3238         if (stateIntChanged) {
3239             firstToken |= DELTA_STATE_FLAG;
3240         }
3241         final boolean state2IntChanged = cur.states2 != last.states2;
3242         if (state2IntChanged) {
3243             firstToken |= DELTA_STATE2_FLAG;
3244         }
3245         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
3246             firstToken |= DELTA_WAKELOCK_FLAG;
3247         }
3248         if (cur.eventCode != HistoryItem.EVENT_NONE) {
3249             firstToken |= DELTA_EVENT_FLAG;
3250         }
3251 
3252         final boolean batteryChargeChanged = cur.batteryChargeUAh != last.batteryChargeUAh;
3253         if (batteryChargeChanged) {
3254             firstToken |= DELTA_BATTERY_CHARGE_FLAG;
3255         }
3256         dest.writeInt(firstToken);
3257         if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
3258                 + " deltaTime=" + deltaTime);
3259 
3260         if (deltaTimeToken >= DELTA_TIME_INT) {
3261             if (deltaTimeToken == DELTA_TIME_INT) {
3262                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
3263                 dest.writeInt((int)deltaTime);
3264             } else {
3265                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
3266                 dest.writeLong(deltaTime);
3267             }
3268         }
3269         if (batteryLevelIntChanged) {
3270             dest.writeInt(batteryLevelInt);
3271             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
3272                     + Integer.toHexString(batteryLevelInt)
3273                     + " batteryLevel=" + cur.batteryLevel
3274                     + " batteryTemp=" + cur.batteryTemperature
3275                     + " batteryVolt=" + (int)cur.batteryVoltage);
3276         }
3277         if (stateIntChanged) {
3278             dest.writeInt(stateInt);
3279             if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
3280                     + Integer.toHexString(stateInt)
3281                     + " batteryStatus=" + cur.batteryStatus
3282                     + " batteryHealth=" + cur.batteryHealth
3283                     + " batteryPlugType=" + cur.batteryPlugType
3284                     + " states=0x" + Integer.toHexString(cur.states));
3285         }
3286         if (state2IntChanged) {
3287             dest.writeInt(cur.states2);
3288             if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x"
3289                     + Integer.toHexString(cur.states2));
3290         }
3291         if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
3292             int wakeLockIndex;
3293             int wakeReasonIndex;
3294             if (cur.wakelockTag != null) {
3295                 wakeLockIndex = writeHistoryTag(cur.wakelockTag);
3296                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
3297                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
3298             } else {
3299                 wakeLockIndex = 0xffff;
3300             }
3301             if (cur.wakeReasonTag != null) {
3302                 wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
3303                 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
3304                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
3305             } else {
3306                 wakeReasonIndex = 0xffff;
3307             }
3308             dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
3309         }
3310         if (cur.eventCode != HistoryItem.EVENT_NONE) {
3311             int index = writeHistoryTag(cur.eventTag);
3312             int codeAndIndex = (cur.eventCode&0xffff) | (index<<16);
3313             dest.writeInt(codeAndIndex);
3314             if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
3315                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
3316                     + cur.eventTag.string);
3317         }
3318         if (computeStepDetails) {
3319             if (mPlatformIdleStateCallback != null) {
3320                 mCurHistoryStepDetails.statPlatformIdleState =
3321                         mPlatformIdleStateCallback.getPlatformLowPowerStats();
3322                 if (DEBUG) Slog.i(TAG, "WRITE PlatformIdleState:" +
3323                         mCurHistoryStepDetails.statPlatformIdleState);
3324 
3325                 mCurHistoryStepDetails.statSubsystemPowerState =
3326                         mPlatformIdleStateCallback.getSubsystemLowPowerStats();
3327                 if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
3328                         mCurHistoryStepDetails.statSubsystemPowerState);
3329 
3330             }
3331             computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
3332             if (includeStepDetails != 0) {
3333                 mCurHistoryStepDetails.writeToParcel(dest);
3334             }
3335             cur.stepDetails = mCurHistoryStepDetails;
3336             mLastHistoryStepDetails = mCurHistoryStepDetails;
3337         } else {
3338             cur.stepDetails = null;
3339         }
3340         if (mLastHistoryStepLevel < cur.batteryLevel) {
3341             mLastHistoryStepDetails = null;
3342         }
3343         mLastHistoryStepLevel = cur.batteryLevel;
3344 
3345         if (batteryChargeChanged) {
3346             if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUAh=" + cur.batteryChargeUAh);
3347             dest.writeInt(cur.batteryChargeUAh);
3348         }
3349         dest.writeDouble(cur.modemRailChargeMah);
3350         dest.writeDouble(cur.wifiRailChargeMah);
3351     }
3352 
buildBatteryLevelInt(HistoryItem h)3353     private int buildBatteryLevelInt(HistoryItem h) {
3354         return ((((int)h.batteryLevel)<<25)&0xfe000000)
3355                 | ((((int)h.batteryTemperature)<<15)&0x01ff8000)
3356                 | ((((int)h.batteryVoltage)<<1)&0x00007ffe);
3357     }
3358 
readBatteryLevelInt(int batteryLevelInt, HistoryItem out)3359     private void readBatteryLevelInt(int batteryLevelInt, HistoryItem out) {
3360         out.batteryLevel = (byte)((batteryLevelInt & 0xfe000000) >>> 25);
3361         out.batteryTemperature = (short)((batteryLevelInt & 0x01ff8000) >>> 15);
3362         out.batteryVoltage = (char)((batteryLevelInt & 0x00007ffe) >>> 1);
3363     }
3364 
buildStateInt(HistoryItem h)3365     private int buildStateInt(HistoryItem h) {
3366         int plugType = 0;
3367         if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
3368             plugType = 1;
3369         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
3370             plugType = 2;
3371         } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
3372             plugType = 3;
3373         }
3374         return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT)
3375                 | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT)
3376                 | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT)
3377                 | (h.states&(~STATE_BATTERY_MASK));
3378     }
3379 
computeHistoryStepDetails(final HistoryStepDetails out, final HistoryStepDetails last)3380     private void computeHistoryStepDetails(final HistoryStepDetails out,
3381             final HistoryStepDetails last) {
3382         final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
3383 
3384         // Perform a CPU update right after we do this collection, so we have started
3385         // collecting good data for the next step.
3386         requestImmediateCpuUpdate();
3387 
3388         if (last == null) {
3389             // We are not generating a delta, so all we need to do is reset the stats
3390             // we will later be doing a delta from.
3391             final int NU = mUidStats.size();
3392             for (int i=0; i<NU; i++) {
3393                 final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3394                 uid.mLastStepUserTime = uid.mCurStepUserTime;
3395                 uid.mLastStepSystemTime = uid.mCurStepSystemTime;
3396             }
3397             mLastStepCpuUserTime = mCurStepCpuUserTime;
3398             mLastStepCpuSystemTime = mCurStepCpuSystemTime;
3399             mLastStepStatUserTime = mCurStepStatUserTime;
3400             mLastStepStatSystemTime = mCurStepStatSystemTime;
3401             mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
3402             mLastStepStatIrqTime = mCurStepStatIrqTime;
3403             mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
3404             mLastStepStatIdleTime = mCurStepStatIdleTime;
3405             tmp.clear();
3406             return;
3407         }
3408         if (DEBUG) {
3409             Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTime + " sys="
3410                     + mLastStepStatSystemTime + " io=" + mLastStepStatIOWaitTime
3411                     + " irq=" + mLastStepStatIrqTime + " sirq="
3412                     + mLastStepStatSoftIrqTime + " idle=" + mLastStepStatIdleTime);
3413             Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTime + " sys="
3414                     + mCurStepStatSystemTime + " io=" + mCurStepStatIOWaitTime
3415                     + " irq=" + mCurStepStatIrqTime + " sirq="
3416                     + mCurStepStatSoftIrqTime + " idle=" + mCurStepStatIdleTime);
3417         }
3418         out.userTime = (int)(mCurStepCpuUserTime - mLastStepCpuUserTime);
3419         out.systemTime = (int)(mCurStepCpuSystemTime - mLastStepCpuSystemTime);
3420         out.statUserTime = (int)(mCurStepStatUserTime - mLastStepStatUserTime);
3421         out.statSystemTime = (int)(mCurStepStatSystemTime - mLastStepStatSystemTime);
3422         out.statIOWaitTime = (int)(mCurStepStatIOWaitTime - mLastStepStatIOWaitTime);
3423         out.statIrqTime = (int)(mCurStepStatIrqTime - mLastStepStatIrqTime);
3424         out.statSoftIrqTime = (int)(mCurStepStatSoftIrqTime - mLastStepStatSoftIrqTime);
3425         out.statIdlTime = (int)(mCurStepStatIdleTime - mLastStepStatIdleTime);
3426         out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
3427         out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
3428         out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
3429         final int NU = mUidStats.size();
3430         for (int i=0; i<NU; i++) {
3431             final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3432             final int totalUTime = (int)(uid.mCurStepUserTime - uid.mLastStepUserTime);
3433             final int totalSTime = (int)(uid.mCurStepSystemTime - uid.mLastStepSystemTime);
3434             final int totalTime = totalUTime + totalSTime;
3435             uid.mLastStepUserTime = uid.mCurStepUserTime;
3436             uid.mLastStepSystemTime = uid.mCurStepSystemTime;
3437             if (totalTime <= (out.appCpuUTime3+out.appCpuSTime3)) {
3438                 continue;
3439             }
3440             if (totalTime <= (out.appCpuUTime2+out.appCpuSTime2)) {
3441                 out.appCpuUid3 = uid.mUid;
3442                 out.appCpuUTime3 = totalUTime;
3443                 out.appCpuSTime3 = totalSTime;
3444             } else {
3445                 out.appCpuUid3 = out.appCpuUid2;
3446                 out.appCpuUTime3 = out.appCpuUTime2;
3447                 out.appCpuSTime3 = out.appCpuSTime2;
3448                 if (totalTime <= (out.appCpuUTime1+out.appCpuSTime1)) {
3449                     out.appCpuUid2 = uid.mUid;
3450                     out.appCpuUTime2 = totalUTime;
3451                     out.appCpuSTime2 = totalSTime;
3452                 } else {
3453                     out.appCpuUid2 = out.appCpuUid1;
3454                     out.appCpuUTime2 = out.appCpuUTime1;
3455                     out.appCpuSTime2 = out.appCpuSTime1;
3456                     out.appCpuUid1 = uid.mUid;
3457                     out.appCpuUTime1 = totalUTime;
3458                     out.appCpuSTime1 = totalSTime;
3459                 }
3460             }
3461         }
3462         mLastStepCpuUserTime = mCurStepCpuUserTime;
3463         mLastStepCpuSystemTime = mCurStepCpuSystemTime;
3464         mLastStepStatUserTime = mCurStepStatUserTime;
3465         mLastStepStatSystemTime = mCurStepStatSystemTime;
3466         mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
3467         mLastStepStatIrqTime = mCurStepStatIrqTime;
3468         mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
3469         mLastStepStatIdleTime = mCurStepStatIdleTime;
3470     }
3471 
readHistoryDelta(Parcel src, HistoryItem cur)3472     public void readHistoryDelta(Parcel src, HistoryItem cur) {
3473         int firstToken = src.readInt();
3474         int deltaTimeToken = firstToken&DELTA_TIME_MASK;
3475         cur.cmd = HistoryItem.CMD_UPDATE;
3476         cur.numReadInts = 1;
3477         if (DEBUG) Slog.i(TAG, "READ DELTA: firstToken=0x" + Integer.toHexString(firstToken)
3478                 + " deltaTimeToken=" + deltaTimeToken);
3479 
3480         if (deltaTimeToken < DELTA_TIME_ABS) {
3481             cur.time += deltaTimeToken;
3482         } else if (deltaTimeToken == DELTA_TIME_ABS) {
3483             cur.time = src.readLong();
3484             cur.numReadInts += 2;
3485             if (DEBUG) Slog.i(TAG, "READ DELTA: ABS time=" + cur.time);
3486             cur.readFromParcel(src);
3487             return;
3488         } else if (deltaTimeToken == DELTA_TIME_INT) {
3489             int delta = src.readInt();
3490             cur.time += delta;
3491             cur.numReadInts += 1;
3492             if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
3493         } else {
3494             long delta = src.readLong();
3495             if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
3496             cur.time += delta;
3497             cur.numReadInts += 2;
3498         }
3499 
3500         final int batteryLevelInt;
3501         if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
3502             batteryLevelInt = src.readInt();
3503             readBatteryLevelInt(batteryLevelInt, cur);
3504             cur.numReadInts += 1;
3505             if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x"
3506                     + Integer.toHexString(batteryLevelInt)
3507                     + " batteryLevel=" + cur.batteryLevel
3508                     + " batteryTemp=" + cur.batteryTemperature
3509                     + " batteryVolt=" + (int)cur.batteryVoltage);
3510         } else {
3511             batteryLevelInt = 0;
3512         }
3513 
3514         if ((firstToken&DELTA_STATE_FLAG) != 0) {
3515             int stateInt = src.readInt();
3516             cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~STATE_BATTERY_MASK));
3517             cur.batteryStatus = (byte)((stateInt>>STATE_BATTERY_STATUS_SHIFT)
3518                     & STATE_BATTERY_STATUS_MASK);
3519             cur.batteryHealth = (byte)((stateInt>>STATE_BATTERY_HEALTH_SHIFT)
3520                     & STATE_BATTERY_HEALTH_MASK);
3521             cur.batteryPlugType = (byte)((stateInt>>STATE_BATTERY_PLUG_SHIFT)
3522                     & STATE_BATTERY_PLUG_MASK);
3523             switch (cur.batteryPlugType) {
3524                 case 1:
3525                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_AC;
3526                     break;
3527                 case 2:
3528                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_USB;
3529                     break;
3530                 case 3:
3531                     cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
3532                     break;
3533             }
3534             cur.numReadInts += 1;
3535             if (DEBUG) Slog.i(TAG, "READ DELTA: stateToken=0x"
3536                     + Integer.toHexString(stateInt)
3537                     + " batteryStatus=" + cur.batteryStatus
3538                     + " batteryHealth=" + cur.batteryHealth
3539                     + " batteryPlugType=" + cur.batteryPlugType
3540                     + " states=0x" + Integer.toHexString(cur.states));
3541         } else {
3542             cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~STATE_BATTERY_MASK));
3543         }
3544 
3545         if ((firstToken&DELTA_STATE2_FLAG) != 0) {
3546             cur.states2 = src.readInt();
3547             if (DEBUG) Slog.i(TAG, "READ DELTA: states2=0x"
3548                     + Integer.toHexString(cur.states2));
3549         }
3550 
3551         if ((firstToken&DELTA_WAKELOCK_FLAG) != 0) {
3552             int indexes = src.readInt();
3553             int wakeLockIndex = indexes&0xffff;
3554             int wakeReasonIndex = (indexes>>16)&0xffff;
3555             if (wakeLockIndex != 0xffff) {
3556                 cur.wakelockTag = cur.localWakelockTag;
3557                 readHistoryTag(wakeLockIndex, cur.wakelockTag);
3558                 if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
3559                     + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
3560             } else {
3561                 cur.wakelockTag = null;
3562             }
3563             if (wakeReasonIndex != 0xffff) {
3564                 cur.wakeReasonTag = cur.localWakeReasonTag;
3565                 readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
3566                 if (DEBUG) Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
3567                     + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
3568             } else {
3569                 cur.wakeReasonTag = null;
3570             }
3571             cur.numReadInts += 1;
3572         } else {
3573             cur.wakelockTag = null;
3574             cur.wakeReasonTag = null;
3575         }
3576 
3577         if ((firstToken&DELTA_EVENT_FLAG) != 0) {
3578             cur.eventTag = cur.localEventTag;
3579             final int codeAndIndex = src.readInt();
3580             cur.eventCode = (codeAndIndex&0xffff);
3581             final int index = ((codeAndIndex>>16)&0xffff);
3582             readHistoryTag(index, cur.eventTag);
3583             cur.numReadInts += 1;
3584             if (DEBUG) Slog.i(TAG, "READ DELTA: event=" + cur.eventCode + " tag=#"
3585                     + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
3586                     + cur.eventTag.string);
3587         } else {
3588             cur.eventCode = HistoryItem.EVENT_NONE;
3589         }
3590 
3591         if ((batteryLevelInt&BATTERY_DELTA_LEVEL_FLAG) != 0) {
3592             cur.stepDetails = mReadHistoryStepDetails;
3593             cur.stepDetails.readFromParcel(src);
3594         } else {
3595             cur.stepDetails = null;
3596         }
3597 
3598         if ((firstToken&DELTA_BATTERY_CHARGE_FLAG) != 0) {
3599             cur.batteryChargeUAh = src.readInt();
3600         }
3601         cur.modemRailChargeMah = src.readDouble();
3602         cur.wifiRailChargeMah = src.readDouble();
3603     }
3604 
3605     @Override
commitCurrentHistoryBatchLocked()3606     public void commitCurrentHistoryBatchLocked() {
3607         mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
3608     }
3609 
createFakeHistoryEvents(long numEvents)3610     public void createFakeHistoryEvents(long numEvents) {
3611         for(long i = 0; i < numEvents; i++) {
3612             noteLongPartialWakelockStart("name1", "historyName1", 1000);
3613             noteLongPartialWakelockFinish("name1", "historyName1", 1000);
3614         }
3615     }
3616 
addHistoryBufferLocked(long elapsedRealtimeMs, HistoryItem cur)3617     void addHistoryBufferLocked(long elapsedRealtimeMs, HistoryItem cur) {
3618         if (!mHaveBatteryLevel || !mRecordingHistory) {
3619             return;
3620         }
3621 
3622         final long timeDiff = (mHistoryBaseTime+elapsedRealtimeMs) - mHistoryLastWritten.time;
3623         final int diffStates = mHistoryLastWritten.states^(cur.states&mActiveHistoryStates);
3624         final int diffStates2 = mHistoryLastWritten.states2^(cur.states2&mActiveHistoryStates2);
3625         final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
3626         final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
3627         if (DEBUG) Slog.i(TAG, "ADD: tdelta=" + timeDiff + " diff="
3628                 + Integer.toHexString(diffStates) + " lastDiff="
3629                 + Integer.toHexString(lastDiffStates) + " diff2="
3630                 + Integer.toHexString(diffStates2) + " lastDiff2="
3631                 + Integer.toHexString(lastDiffStates2));
3632         if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
3633                 && timeDiff < 1000 && (diffStates&lastDiffStates) == 0
3634                 && (diffStates2&lastDiffStates2) == 0
3635                 && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
3636                 && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
3637                 && mHistoryLastWritten.stepDetails == null
3638                 && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
3639                         || cur.eventCode == HistoryItem.EVENT_NONE)
3640                 && mHistoryLastWritten.batteryLevel == cur.batteryLevel
3641                 && mHistoryLastWritten.batteryStatus == cur.batteryStatus
3642                 && mHistoryLastWritten.batteryHealth == cur.batteryHealth
3643                 && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
3644                 && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
3645                 && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
3646             // We can merge this new change in with the last one.  Merging is
3647             // allowed as long as only the states have changed, and within those states
3648             // as long as no bit has changed both between now and the last entry, as
3649             // well as the last entry and the one before it (so we capture any toggles).
3650             if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
3651             mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
3652             mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
3653             mHistoryBufferLastPos = -1;
3654             elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTime;
3655             // If the last written history had a wakelock tag, we need to retain it.
3656             // Note that the condition above made sure that we aren't in a case where
3657             // both it and the current history item have a wakelock tag.
3658             if (mHistoryLastWritten.wakelockTag != null) {
3659                 cur.wakelockTag = cur.localWakelockTag;
3660                 cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
3661             }
3662             // If the last written history had a wake reason tag, we need to retain it.
3663             // Note that the condition above made sure that we aren't in a case where
3664             // both it and the current history item have a wakelock tag.
3665             if (mHistoryLastWritten.wakeReasonTag != null) {
3666                 cur.wakeReasonTag = cur.localWakeReasonTag;
3667                 cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
3668             }
3669             // If the last written history had an event, we need to retain it.
3670             // Note that the condition above made sure that we aren't in a case where
3671             // both it and the current history item have an event.
3672             if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
3673                 cur.eventCode = mHistoryLastWritten.eventCode;
3674                 cur.eventTag = cur.localEventTag;
3675                 cur.eventTag.setTo(mHistoryLastWritten.eventTag);
3676             }
3677             mHistoryLastWritten.setTo(mHistoryLastLastWritten);
3678         }
3679         final int dataSize = mHistoryBuffer.dataSize();
3680 
3681         if (dataSize >= mConstants.MAX_HISTORY_BUFFER) {
3682             //open a new history file.
3683             final long start = SystemClock.uptimeMillis();
3684             writeHistoryLocked(true);
3685             if (DEBUG) {
3686                 Slog.d(TAG, "addHistoryBufferLocked writeHistoryLocked takes ms:"
3687                         + (SystemClock.uptimeMillis() - start));
3688             }
3689             mBatteryStatsHistory.startNextFile();
3690             mHistoryBuffer.setDataSize(0);
3691             mHistoryBuffer.setDataPosition(0);
3692             mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
3693             mHistoryBufferLastPos = -1;
3694             final long elapsedRealtime = mClocks.elapsedRealtime();
3695             final long uptime = mClocks.uptimeMillis();
3696             HistoryItem newItem = new HistoryItem();
3697             newItem.setTo(cur);
3698             startRecordingHistory(elapsedRealtime, uptime, false);
3699             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, newItem);
3700             return;
3701         }
3702 
3703         if (dataSize == 0) {
3704             // The history is currently empty; we need it to start with a time stamp.
3705             cur.currentTime = System.currentTimeMillis();
3706             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
3707         }
3708         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3709     }
3710 
addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur)3711     private void addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur) {
3712         if (mIteratingHistory) {
3713             throw new IllegalStateException("Can't do this while iterating history!");
3714         }
3715         mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
3716         mHistoryLastLastWritten.setTo(mHistoryLastWritten);
3717         mHistoryLastWritten.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
3718         mHistoryLastWritten.states &= mActiveHistoryStates;
3719         mHistoryLastWritten.states2 &= mActiveHistoryStates2;
3720         writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
3721         mLastHistoryElapsedRealtime = elapsedRealtimeMs;
3722         cur.wakelockTag = null;
3723         cur.wakeReasonTag = null;
3724         cur.eventCode = HistoryItem.EVENT_NONE;
3725         cur.eventTag = null;
3726         if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
3727                 + " now " + mHistoryBuffer.dataPosition()
3728                 + " size is now " + mHistoryBuffer.dataSize());
3729     }
3730 
3731     int mChangedStates = 0;
3732     int mChangedStates2 = 0;
3733 
addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs)3734     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
3735         if (mTrackRunningHistoryElapsedRealtime != 0) {
3736             final long diffElapsed = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtime;
3737             final long diffUptime = uptimeMs - mTrackRunningHistoryUptime;
3738             if (diffUptime < (diffElapsed-20)) {
3739                 final long wakeElapsedTime = elapsedRealtimeMs - (diffElapsed - diffUptime);
3740                 mHistoryAddTmp.setTo(mHistoryLastWritten);
3741                 mHistoryAddTmp.wakelockTag = null;
3742                 mHistoryAddTmp.wakeReasonTag = null;
3743                 mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
3744                 mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
3745                 addHistoryRecordInnerLocked(wakeElapsedTime, mHistoryAddTmp);
3746             }
3747         }
3748         mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
3749         mTrackRunningHistoryElapsedRealtime = elapsedRealtimeMs;
3750         mTrackRunningHistoryUptime = uptimeMs;
3751         addHistoryRecordInnerLocked(elapsedRealtimeMs, mHistoryCur);
3752     }
3753 
addHistoryRecordInnerLocked(long elapsedRealtimeMs, HistoryItem cur)3754     void addHistoryRecordInnerLocked(long elapsedRealtimeMs, HistoryItem cur) {
3755         addHistoryBufferLocked(elapsedRealtimeMs, cur);
3756 
3757         if (!USE_OLD_HISTORY) {
3758             return;
3759         }
3760 
3761         if (!mHaveBatteryLevel || !mRecordingHistory) {
3762             return;
3763         }
3764 
3765         // If the current time is basically the same as the last time,
3766         // and no states have since the last recorded entry changed and
3767         // are now resetting back to their original value, then just collapse
3768         // into one record.
3769         if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE
3770                 && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+1000)
3771                 && ((mHistoryEnd.states^cur.states)&mChangedStates&mActiveHistoryStates) == 0
3772                 && ((mHistoryEnd.states2^cur.states2)&mChangedStates2&mActiveHistoryStates2) == 0) {
3773             // If the current is the same as the one before, then we no
3774             // longer need the entry.
3775             if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE
3776                     && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+500)
3777                     && mHistoryLastEnd.sameNonEvent(cur)) {
3778                 mHistoryLastEnd.next = null;
3779                 mHistoryEnd.next = mHistoryCache;
3780                 mHistoryCache = mHistoryEnd;
3781                 mHistoryEnd = mHistoryLastEnd;
3782                 mHistoryLastEnd = null;
3783             } else {
3784                 mChangedStates |= mHistoryEnd.states^(cur.states&mActiveHistoryStates);
3785                 mChangedStates2 |= mHistoryEnd.states^(cur.states2&mActiveHistoryStates2);
3786                 mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, cur);
3787             }
3788             return;
3789         }
3790 
3791         mChangedStates = 0;
3792         mChangedStates2 = 0;
3793         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3794     }
3795 
addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code, String name, int uid)3796     public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
3797             String name, int uid) {
3798         mHistoryCur.eventCode = code;
3799         mHistoryCur.eventTag = mHistoryCur.localEventTag;
3800         mHistoryCur.eventTag.string = name;
3801         mHistoryCur.eventTag.uid = uid;
3802         addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
3803     }
3804 
addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur)3805     void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) {
3806         HistoryItem rec = mHistoryCache;
3807         if (rec != null) {
3808             mHistoryCache = rec.next;
3809         } else {
3810             rec = new HistoryItem();
3811         }
3812         rec.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
3813 
3814         addHistoryRecordLocked(rec);
3815     }
3816 
addHistoryRecordLocked(HistoryItem rec)3817     void addHistoryRecordLocked(HistoryItem rec) {
3818         mNumHistoryItems++;
3819         rec.next = null;
3820         mHistoryLastEnd = mHistoryEnd;
3821         if (mHistoryEnd != null) {
3822             mHistoryEnd.next = rec;
3823             mHistoryEnd = rec;
3824         } else {
3825             mHistory = mHistoryEnd = rec;
3826         }
3827     }
3828 
clearHistoryLocked()3829     void clearHistoryLocked() {
3830         if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
3831         if (USE_OLD_HISTORY) {
3832             if (mHistory != null) {
3833                 mHistoryEnd.next = mHistoryCache;
3834                 mHistoryCache = mHistory;
3835                 mHistory = mHistoryLastEnd = mHistoryEnd = null;
3836             }
3837             mNumHistoryItems = 0;
3838         }
3839 
3840         mHistoryBaseTime = 0;
3841         mLastHistoryElapsedRealtime = 0;
3842         mTrackRunningHistoryElapsedRealtime = 0;
3843         mTrackRunningHistoryUptime = 0;
3844 
3845         mHistoryBuffer.setDataSize(0);
3846         mHistoryBuffer.setDataPosition(0);
3847         mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
3848         mHistoryLastLastWritten.clear();
3849         mHistoryLastWritten.clear();
3850         mHistoryTagPool.clear();
3851         mNextHistoryTagIdx = 0;
3852         mNumHistoryTagChars = 0;
3853         mHistoryBufferLastPos = -1;
3854         mActiveHistoryStates = 0xffffffff;
3855         mActiveHistoryStates2 = 0xffffffff;
3856     }
3857 
3858     @GuardedBy("this")
updateTimeBasesLocked(boolean unplugged, int screenState, long uptime, long realtime)3859     public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptime,
3860             long realtime) {
3861         final boolean screenOff = !isScreenOn(screenState);
3862         final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
3863         final boolean updateOnBatteryScreenOffTimeBase =
3864                 (unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
3865 
3866         if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) {
3867             if (updateOnBatteryScreenOffTimeBase) {
3868                 updateKernelWakelocksLocked();
3869                 updateBatteryPropertiesLocked();
3870             }
3871             // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
3872             // updateRpmStatsLocked is too slow to run each screen change. When the speed is
3873             // improved, remove the surrounding if{}.
3874             if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
3875                 updateRpmStatsLocked(); // if either OnBattery or OnBatteryScreenOff timebase changes.
3876             }
3877             if (DEBUG_ENERGY_CPU) {
3878                 Slog.d(TAG, "Updating cpu time because screen is now "
3879                         + Display.stateToString(screenState)
3880                         + " and battery is " + (unplugged ? "on" : "off"));
3881             }
3882 
3883             mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime);
3884             if (updateOnBatteryTimeBase) {
3885                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
3886                     mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptime, realtime);
3887                 }
3888             }
3889             if (updateOnBatteryScreenOffTimeBase) {
3890                 mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff, uptime, realtime);
3891                 for (int i = mUidStats.size() - 1; i >= 0; --i) {
3892                     mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptime, realtime);
3893                 }
3894             }
3895         }
3896     }
3897 
updateBatteryPropertiesLocked()3898     private void updateBatteryPropertiesLocked() {
3899         try {
3900             IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
3901                     ServiceManager.getService("batteryproperties"));
3902             if (registrar != null) {
3903                 registrar.scheduleUpdate();
3904             }
3905         } catch (RemoteException e) {
3906             // Ignore.
3907         }
3908     }
3909 
addIsolatedUidLocked(int isolatedUid, int appUid)3910     public void addIsolatedUidLocked(int isolatedUid, int appUid) {
3911         mIsolatedUids.put(isolatedUid, appUid);
3912         final Uid u = getUidStatsLocked(appUid);
3913         u.addIsolatedUid(isolatedUid);
3914     }
3915 
3916     /**
3917      * Schedules a read of the latest cpu times before removing the isolated UID.
3918      * @see #removeIsolatedUidLocked(int)
3919      */
scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid)3920     public void scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid) {
3921         int curUid = mIsolatedUids.get(isolatedUid, -1);
3922         if (curUid == appUid) {
3923             if (mExternalSync != null) {
3924                 mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
3925             }
3926         }
3927     }
3928 
3929     /**
3930      * This should only be called after the cpu times have been read.
3931      * @see #scheduleRemoveIsolatedUidLocked(int, int)
3932      */
3933     @GuardedBy("this")
removeIsolatedUidLocked(int isolatedUid)3934     public void removeIsolatedUidLocked(int isolatedUid) {
3935         final int idx = mIsolatedUids.indexOfKey(isolatedUid);
3936         if (idx >= 0) {
3937             final int ownerUid = mIsolatedUids.valueAt(idx);
3938             final Uid u = getUidStatsLocked(ownerUid);
3939             u.removeIsolatedUid(isolatedUid);
3940             mIsolatedUids.removeAt(idx);
3941         }
3942         mPendingRemovedUids.add(new UidToRemove(isolatedUid, mClocks.elapsedRealtime()));
3943     }
3944 
mapUid(int uid)3945     public int mapUid(int uid) {
3946         int isolated = mIsolatedUids.get(uid, -1);
3947         return isolated > 0 ? isolated : uid;
3948     }
3949 
noteEventLocked(int code, String name, int uid)3950     public void noteEventLocked(int code, String name, int uid) {
3951         uid = mapUid(uid);
3952         if (!mActiveEvents.updateState(code, name, uid, 0)) {
3953             return;
3954         }
3955         final long elapsedRealtime = mClocks.elapsedRealtime();
3956         final long uptime = mClocks.uptimeMillis();
3957         addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
3958     }
3959 
noteCurrentTimeChangedLocked()3960     public void noteCurrentTimeChangedLocked() {
3961         final long currentTime = System.currentTimeMillis();
3962         final long elapsedRealtime = mClocks.elapsedRealtime();
3963         final long uptime = mClocks.uptimeMillis();
3964         recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
3965     }
3966 
noteProcessStartLocked(String name, int uid)3967     public void noteProcessStartLocked(String name, int uid) {
3968         uid = mapUid(uid);
3969         if (isOnBattery()) {
3970             Uid u = getUidStatsLocked(uid);
3971             u.getProcessStatsLocked(name).incStartsLocked();
3972         }
3973         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
3974             return;
3975         }
3976         if (!mRecordAllHistory) {
3977             return;
3978         }
3979         final long elapsedRealtime = mClocks.elapsedRealtime();
3980         final long uptime = mClocks.uptimeMillis();
3981         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid);
3982     }
3983 
noteProcessCrashLocked(String name, int uid)3984     public void noteProcessCrashLocked(String name, int uid) {
3985         uid = mapUid(uid);
3986         if (isOnBattery()) {
3987             Uid u = getUidStatsLocked(uid);
3988             u.getProcessStatsLocked(name).incNumCrashesLocked();
3989         }
3990     }
3991 
noteProcessAnrLocked(String name, int uid)3992     public void noteProcessAnrLocked(String name, int uid) {
3993         uid = mapUid(uid);
3994         if (isOnBattery()) {
3995             Uid u = getUidStatsLocked(uid);
3996             u.getProcessStatsLocked(name).incNumAnrsLocked();
3997         }
3998     }
3999 
noteUidProcessStateLocked(int uid, int state)4000     public void noteUidProcessStateLocked(int uid, int state) {
4001         int parentUid = mapUid(uid);
4002         if (uid != parentUid) {
4003             // Isolated UIDs process state is already rolled up into parent, so no need to track
4004             // Otherwise the parent's process state will get downgraded incorrectly
4005             return;
4006         }
4007         getUidStatsLocked(uid).updateUidProcessStateLocked(state);
4008     }
4009 
noteProcessFinishLocked(String name, int uid)4010     public void noteProcessFinishLocked(String name, int uid) {
4011         uid = mapUid(uid);
4012         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
4013             return;
4014         }
4015         if (!mRecordAllHistory) {
4016             return;
4017         }
4018         final long elapsedRealtime = mClocks.elapsedRealtime();
4019         final long uptime = mClocks.uptimeMillis();
4020         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
4021     }
4022 
noteSyncStartLocked(String name, int uid)4023     public void noteSyncStartLocked(String name, int uid) {
4024         uid = mapUid(uid);
4025         final long elapsedRealtime = mClocks.elapsedRealtime();
4026         final long uptime = mClocks.uptimeMillis();
4027         getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime);
4028         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
4029             return;
4030         }
4031         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_START, name, uid);
4032     }
4033 
noteSyncFinishLocked(String name, int uid)4034     public void noteSyncFinishLocked(String name, int uid) {
4035         uid = mapUid(uid);
4036         final long elapsedRealtime = mClocks.elapsedRealtime();
4037         final long uptime = mClocks.uptimeMillis();
4038         getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime);
4039         if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
4040             return;
4041         }
4042         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_FINISH, name, uid);
4043     }
4044 
noteJobStartLocked(String name, int uid)4045     public void noteJobStartLocked(String name, int uid) {
4046         uid = mapUid(uid);
4047         final long elapsedRealtime = mClocks.elapsedRealtime();
4048         final long uptime = mClocks.uptimeMillis();
4049         getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime);
4050         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
4051             return;
4052         }
4053         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid);
4054     }
4055 
noteJobFinishLocked(String name, int uid, int stopReason)4056     public void noteJobFinishLocked(String name, int uid, int stopReason) {
4057         uid = mapUid(uid);
4058         final long elapsedRealtime = mClocks.elapsedRealtime();
4059         final long uptime = mClocks.uptimeMillis();
4060         getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime, stopReason);
4061         if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
4062             return;
4063         }
4064         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
4065     }
4066 
noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast)4067     public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast) {
4068         uid = mapUid(uid);
4069         getUidStatsLocked(uid).noteJobsDeferredLocked(numDeferred, sinceLast);
4070     }
4071 
noteAlarmStartLocked(String name, WorkSource workSource, int uid)4072     public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
4073         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid);
4074     }
4075 
noteAlarmFinishLocked(String name, WorkSource workSource, int uid)4076     public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
4077         noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid);
4078     }
4079 
noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, int uid)4080     private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
4081             int uid) {
4082         if (!mRecordAllHistory) {
4083             return;
4084         }
4085 
4086         final long elapsedRealtime = mClocks.elapsedRealtime();
4087         final long uptime = mClocks.uptimeMillis();
4088 
4089         if (workSource != null) {
4090             for (int i = 0; i < workSource.size(); ++i) {
4091                 uid = mapUid(workSource.get(i));
4092                 if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4093                     addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4094                 }
4095             }
4096 
4097             List<WorkChain> workChains = workSource.getWorkChains();
4098             if (workChains != null) {
4099                 for (int i = 0; i < workChains.size(); ++i) {
4100                     uid = mapUid(workChains.get(i).getAttributionUid());
4101                     if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4102                         addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4103                     }
4104                 }
4105             }
4106         } else {
4107             uid = mapUid(uid);
4108 
4109             if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4110                 addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4111             }
4112         }
4113     }
4114 
noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag)4115     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4116             String tag) {
4117         if (workSource != null) {
4118             for (int i = 0; i < workSource.size(); ++i) {
4119                 uid = workSource.get(i);
4120                 final String workSourceName = workSource.getName(i);
4121 
4122                 if (isOnBattery()) {
4123                     BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
4124                             workSourceName != null ? workSourceName : packageName);
4125                     pkg.noteWakeupAlarmLocked(tag);
4126                 }
4127             }
4128 
4129             ArrayList<WorkChain> workChains = workSource.getWorkChains();
4130             if (workChains != null) {
4131                 for (int i = 0; i < workChains.size(); ++i) {
4132                     final WorkChain wc = workChains.get(i);
4133                     uid = wc.getAttributionUid();
4134 
4135                     if (isOnBattery()) {
4136                         BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
4137                         pkg.noteWakeupAlarmLocked(tag);
4138                     }
4139                 }
4140             }
4141         } else {
4142             if (isOnBattery()) {
4143                 BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
4144                 pkg.noteWakeupAlarmLocked(tag);
4145             }
4146         }
4147     }
4148 
requestWakelockCpuUpdate()4149     private void requestWakelockCpuUpdate() {
4150         mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS);
4151     }
4152 
requestImmediateCpuUpdate()4153     private void requestImmediateCpuUpdate() {
4154         mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
4155     }
4156 
setRecordAllHistoryLocked(boolean enabled)4157     public void setRecordAllHistoryLocked(boolean enabled) {
4158         mRecordAllHistory = enabled;
4159         if (!enabled) {
4160             // Clear out any existing state.
4161             mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
4162             mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
4163             // Record the currently running processes as stopping, now that we are no
4164             // longer tracking them.
4165             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4166                     HistoryItem.EVENT_PROC);
4167             if (active != null) {
4168                 long mSecRealtime = mClocks.elapsedRealtime();
4169                 final long mSecUptime = mClocks.uptimeMillis();
4170                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4171                     SparseIntArray uids = ent.getValue();
4172                     for (int j=0; j<uids.size(); j++) {
4173                         addHistoryEventLocked(mSecRealtime, mSecUptime,
4174                                 HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
4175                     }
4176                 }
4177             }
4178         } else {
4179             // Record the currently running processes as starting, now that we are tracking them.
4180             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4181                     HistoryItem.EVENT_PROC);
4182             if (active != null) {
4183                 long mSecRealtime = mClocks.elapsedRealtime();
4184                 final long mSecUptime = mClocks.uptimeMillis();
4185                 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4186                     SparseIntArray uids = ent.getValue();
4187                     for (int j=0; j<uids.size(); j++) {
4188                         addHistoryEventLocked(mSecRealtime, mSecUptime,
4189                                 HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
4190                     }
4191                 }
4192             }
4193         }
4194     }
4195 
setNoAutoReset(boolean enabled)4196     public void setNoAutoReset(boolean enabled) {
4197         mNoAutoReset = enabled;
4198     }
4199 
setPretendScreenOff(boolean pretendScreenOff)4200     public void setPretendScreenOff(boolean pretendScreenOff) {
4201         if (mPretendScreenOff != pretendScreenOff) {
4202             mPretendScreenOff = pretendScreenOff;
4203             noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON);
4204         }
4205     }
4206 
4207     private String mInitialAcquireWakeName;
4208     private int mInitialAcquireWakeUid = -1;
4209 
noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtime, long uptime)4210     public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4211         int type, boolean unimportantForLogging, long elapsedRealtime, long uptime) {
4212         uid = mapUid(uid);
4213         if (type == WAKE_TYPE_PARTIAL) {
4214             // Only care about partial wake locks, since full wake locks
4215             // will be canceled when the user puts the screen to sleep.
4216             aggregateLastWakeupUptimeLocked(uptime);
4217             if (historyName == null) {
4218                 historyName = name;
4219             }
4220             if (mRecordAllHistory) {
4221                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
4222                         uid, 0)) {
4223                     addHistoryEventLocked(elapsedRealtime, uptime,
4224                             HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
4225                 }
4226             }
4227             if (mWakeLockNesting == 0) {
4228                 mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
4229                 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
4230                         + Integer.toHexString(mHistoryCur.states));
4231                 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
4232                 mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
4233                 mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
4234                 mWakeLockImportant = !unimportantForLogging;
4235                 addHistoryRecordLocked(elapsedRealtime, uptime);
4236             } else if (!mWakeLockImportant && !unimportantForLogging
4237                     && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
4238                 if (mHistoryLastWritten.wakelockTag != null) {
4239                     // We'll try to update the last tag.
4240                     mHistoryLastWritten.wakelockTag = null;
4241                     mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
4242                     mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
4243                     mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
4244                     addHistoryRecordLocked(elapsedRealtime, uptime);
4245                 }
4246                 mWakeLockImportant = true;
4247             }
4248             mWakeLockNesting++;
4249         }
4250         if (uid >= 0) {
4251             if (mOnBatteryScreenOffTimeBase.isRunning()) {
4252                 // We only update the cpu time when a wake lock is acquired if the screen is off.
4253                 // If the screen is on, we don't distribute the power amongst partial wakelocks.
4254                 if (DEBUG_ENERGY_CPU) {
4255                     Slog.d(TAG, "Updating cpu time because of +wake_lock");
4256                 }
4257                 requestWakelockCpuUpdate();
4258             }
4259 
4260             getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
4261 
4262             if (wc != null) {
4263                 StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(),
4264                         getPowerManagerWakeLockLevel(type), name,
4265                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
4266             } else {
4267                 StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null,
4268                         getPowerManagerWakeLockLevel(type), name,
4269                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
4270             }
4271         }
4272     }
4273 
noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, long elapsedRealtime, long uptime)4274     public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4275             int type, long elapsedRealtime, long uptime) {
4276         uid = mapUid(uid);
4277         if (type == WAKE_TYPE_PARTIAL) {
4278             mWakeLockNesting--;
4279             if (mRecordAllHistory) {
4280                 if (historyName == null) {
4281                     historyName = name;
4282                 }
4283                 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
4284                         uid, 0)) {
4285                     addHistoryEventLocked(elapsedRealtime, uptime,
4286                             HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
4287                 }
4288             }
4289             if (mWakeLockNesting == 0) {
4290                 mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
4291                 if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
4292                         + Integer.toHexString(mHistoryCur.states));
4293                 mInitialAcquireWakeName = null;
4294                 mInitialAcquireWakeUid = -1;
4295                 addHistoryRecordLocked(elapsedRealtime, uptime);
4296             }
4297         }
4298         if (uid >= 0) {
4299             if (mOnBatteryScreenOffTimeBase.isRunning()) {
4300                 if (DEBUG_ENERGY_CPU) {
4301                     Slog.d(TAG, "Updating cpu time because of -wake_lock");
4302                 }
4303                 requestWakelockCpuUpdate();
4304             }
4305 
4306             getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
4307             if (wc != null) {
4308                 StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(),
4309                         getPowerManagerWakeLockLevel(type), name,
4310                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
4311             } else {
4312                 StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null,
4313                         getPowerManagerWakeLockLevel(type), name,
4314                         StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
4315             }
4316         }
4317     }
4318 
4319     /**
4320      * Converts BatteryStats wakelock types back into PowerManager wakelock levels.
4321      * This is the inverse map of Notifier.getBatteryStatsWakeLockMonitorType().
4322      * These are estimations, since batterystats loses some of the original data.
4323      * TODO: Delete this. Instead, StatsLog.write should be called from PowerManager's Notifier.
4324      */
getPowerManagerWakeLockLevel(int battertStatsWakelockType)4325     private int getPowerManagerWakeLockLevel(int battertStatsWakelockType) {
4326         switch (battertStatsWakelockType) {
4327             // PowerManager.PARTIAL_WAKE_LOCK or PROXIMITY_SCREEN_OFF_WAKE_LOCK
4328             case BatteryStats.WAKE_TYPE_PARTIAL:
4329                 return PowerManager.PARTIAL_WAKE_LOCK;
4330 
4331             // PowerManager.SCREEN_DIM_WAKE_LOCK or SCREEN_BRIGHT_WAKE_LOCK
4332             case BatteryStats.WAKE_TYPE_FULL:
4333                 return PowerManager.FULL_WAKE_LOCK;
4334 
4335             case BatteryStats.WAKE_TYPE_DRAW:
4336                 return PowerManager.DRAW_WAKE_LOCK;
4337 
4338             // It appears that nothing can ever make a Window and PowerManager lacks an equivalent.
4339             case BatteryStats.WAKE_TYPE_WINDOW:
4340                 Slog.e(TAG, "Illegal window wakelock type observed in batterystats.");
4341                 return -1;
4342 
4343             default:
4344                 Slog.e(TAG, "Illegal wakelock type in batterystats: " + battertStatsWakelockType);
4345                 return -1;
4346         }
4347     }
4348 
noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging)4349     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
4350             String historyName, int type, boolean unimportantForLogging) {
4351         final long elapsedRealtime = mClocks.elapsedRealtime();
4352         final long uptime = mClocks.uptimeMillis();
4353         final int N = ws.size();
4354         for (int i=0; i<N; i++) {
4355             noteStartWakeLocked(ws.get(i), pid, null, name, historyName, type,
4356                     unimportantForLogging, elapsedRealtime, uptime);
4357         }
4358 
4359         List<WorkChain> wcs = ws.getWorkChains();
4360         if (wcs != null) {
4361             for (int i = 0; i < wcs.size(); ++i) {
4362                 final WorkChain wc = wcs.get(i);
4363                 noteStartWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4364                         unimportantForLogging, elapsedRealtime, uptime);
4365             }
4366         }
4367     }
4368 
noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, WorkSource newWs, int newPid, String newName, String newHistoryName, int newType, boolean newUnimportantForLogging)4369     public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
4370             String historyName, int type, WorkSource newWs, int newPid, String newName,
4371             String newHistoryName, int newType, boolean newUnimportantForLogging) {
4372         final long elapsedRealtime = mClocks.elapsedRealtime();
4373         final long uptime = mClocks.uptimeMillis();
4374 
4375         List<WorkChain>[] wcs = WorkSource.diffChains(ws, newWs);
4376 
4377         // For correct semantics, we start the need worksources first, so that we won't
4378         // make inappropriate history items as if all wake locks went away and new ones
4379         // appeared.  This is okay because tracking of wake locks allows nesting.
4380         //
4381         // First the starts :
4382         final int NN = newWs.size();
4383         for (int i=0; i<NN; i++) {
4384             noteStartWakeLocked(newWs.get(i), newPid, null, newName, newHistoryName, newType,
4385                     newUnimportantForLogging, elapsedRealtime, uptime);
4386         }
4387         if (wcs != null) {
4388             List<WorkChain> newChains = wcs[0];
4389             if (newChains != null) {
4390                 for (int i = 0; i < newChains.size(); ++i) {
4391                     final WorkChain newChain = newChains.get(i);
4392                     noteStartWakeLocked(newChain.getAttributionUid(), newPid, newChain, newName,
4393                         newHistoryName, newType, newUnimportantForLogging, elapsedRealtime,
4394                         uptime);
4395                 }
4396             }
4397         }
4398 
4399         // Then the stops :
4400         final int NO = ws.size();
4401         for (int i=0; i<NO; i++) {
4402             noteStopWakeLocked(ws.get(i), pid, null, name, historyName, type, elapsedRealtime,
4403                     uptime);
4404         }
4405         if (wcs != null) {
4406             List<WorkChain> goneChains = wcs[1];
4407             if (goneChains != null) {
4408                 for (int i = 0; i < goneChains.size(); ++i) {
4409                     final WorkChain goneChain = goneChains.get(i);
4410                     noteStopWakeLocked(goneChain.getAttributionUid(), pid, goneChain, name,
4411                             historyName, type, elapsedRealtime, uptime);
4412                 }
4413             }
4414         }
4415     }
4416 
noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type)4417     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
4418             String historyName, int type) {
4419         final long elapsedRealtime = mClocks.elapsedRealtime();
4420         final long uptime = mClocks.uptimeMillis();
4421         final int N = ws.size();
4422         for (int i=0; i<N; i++) {
4423             noteStopWakeLocked(ws.get(i), pid, null, name, historyName, type, elapsedRealtime,
4424                     uptime);
4425         }
4426 
4427         List<WorkChain> wcs = ws.getWorkChains();
4428         if (wcs != null) {
4429             for (int i = 0; i < wcs.size(); ++i) {
4430                 final WorkChain wc = wcs.get(i);
4431                 noteStopWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4432                         elapsedRealtime, uptime);
4433             }
4434         }
4435     }
4436 
noteLongPartialWakelockStart(String name, String historyName, int uid)4437     public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
4438         uid = mapUid(uid);
4439         noteLongPartialWakeLockStartInternal(name, historyName, uid);
4440     }
4441 
noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource)4442     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
4443             WorkSource workSource) {
4444         final int N = workSource.size();
4445         for (int i = 0; i < N; ++i) {
4446             final int uid = mapUid(workSource.get(i));
4447             noteLongPartialWakeLockStartInternal(name, historyName, uid);
4448         }
4449 
4450         final ArrayList<WorkChain> workChains = workSource.getWorkChains();
4451         if (workChains != null) {
4452             for (int i = 0; i < workChains.size(); ++i) {
4453                 final WorkChain workChain = workChains.get(i);
4454                 final int uid = workChain.getAttributionUid();
4455                 noteLongPartialWakeLockStartInternal(name, historyName, uid);
4456             }
4457         }
4458     }
4459 
noteLongPartialWakeLockStartInternal(String name, String historyName, int uid)4460     private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid) {
4461         final long elapsedRealtime = mClocks.elapsedRealtime();
4462         final long uptime = mClocks.uptimeMillis();
4463         if (historyName == null) {
4464             historyName = name;
4465         }
4466         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid,
4467                 0)) {
4468             return;
4469         }
4470         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
4471                 historyName, uid);
4472     }
4473 
noteLongPartialWakelockFinish(String name, String historyName, int uid)4474     public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
4475         uid = mapUid(uid);
4476         noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4477     }
4478 
noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource)4479     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
4480             WorkSource workSource) {
4481         final int N = workSource.size();
4482         for (int i = 0; i < N; ++i) {
4483             final int uid = mapUid(workSource.get(i));
4484             noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4485         }
4486 
4487         final ArrayList<WorkChain> workChains = workSource.getWorkChains();
4488         if (workChains != null) {
4489             for (int i = 0; i < workChains.size(); ++i) {
4490                 final WorkChain workChain = workChains.get(i);
4491                 final int uid = workChain.getAttributionUid();
4492                 noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4493             }
4494         }
4495     }
4496 
noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid)4497     private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid) {
4498         final long elapsedRealtime = mClocks.elapsedRealtime();
4499         final long uptime = mClocks.uptimeMillis();
4500         if (historyName == null) {
4501             historyName = name;
4502         }
4503         if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid,
4504                 0)) {
4505             return;
4506         }
4507         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
4508                 historyName, uid);
4509     }
4510 
aggregateLastWakeupUptimeLocked(long uptimeMs)4511     void aggregateLastWakeupUptimeLocked(long uptimeMs) {
4512         if (mLastWakeupReason != null) {
4513             long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
4514             SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
4515             timer.add(deltaUptime * 1000, 1); // time in in microseconds
4516             StatsLog.write(StatsLog.KERNEL_WAKEUP_REPORTED, mLastWakeupReason,
4517                     /* duration_usec */ deltaUptime * 1000);
4518             mLastWakeupReason = null;
4519         }
4520     }
4521 
noteWakeupReasonLocked(String reason)4522     public void noteWakeupReasonLocked(String reason) {
4523         final long elapsedRealtime = mClocks.elapsedRealtime();
4524         final long uptime = mClocks.uptimeMillis();
4525         if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
4526                 + Integer.toHexString(mHistoryCur.states));
4527         aggregateLastWakeupUptimeLocked(uptime);
4528         mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
4529         mHistoryCur.wakeReasonTag.string = reason;
4530         mHistoryCur.wakeReasonTag.uid = 0;
4531         mLastWakeupReason = reason;
4532         mLastWakeupUptimeMs = uptime;
4533         addHistoryRecordLocked(elapsedRealtime, uptime);
4534     }
4535 
startAddingCpuLocked()4536     public boolean startAddingCpuLocked() {
4537         mExternalSync.cancelCpuSyncDueToWakelockChange();
4538         return mOnBatteryInternal;
4539     }
4540 
finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime, int statSystemTime, int statIOWaitTime, int statIrqTime, int statSoftIrqTime, int statIdleTime)4541     public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime,
4542                                       int statSystemTime, int statIOWaitTime, int statIrqTime,
4543                                       int statSoftIrqTime, int statIdleTime) {
4544         if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
4545                 + " user=" + statUserTime + " sys=" + statSystemTime
4546                 + " io=" + statIOWaitTime + " irq=" + statIrqTime
4547                 + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime);
4548         mCurStepCpuUserTime += totalUTime;
4549         mCurStepCpuSystemTime += totalSTime;
4550         mCurStepStatUserTime += statUserTime;
4551         mCurStepStatSystemTime += statSystemTime;
4552         mCurStepStatIOWaitTime += statIOWaitTime;
4553         mCurStepStatIrqTime += statIrqTime;
4554         mCurStepStatSoftIrqTime += statSoftIrqTime;
4555         mCurStepStatIdleTime += statIdleTime;
4556     }
4557 
noteProcessDiedLocked(int uid, int pid)4558     public void noteProcessDiedLocked(int uid, int pid) {
4559         uid = mapUid(uid);
4560         Uid u = mUidStats.get(uid);
4561         if (u != null) {
4562             u.mPids.remove(pid);
4563         }
4564     }
4565 
getProcessWakeTime(int uid, int pid, long realtime)4566     public long getProcessWakeTime(int uid, int pid, long realtime) {
4567         uid = mapUid(uid);
4568         Uid u = mUidStats.get(uid);
4569         if (u != null) {
4570             Uid.Pid p = u.mPids.get(pid);
4571             if (p != null) {
4572                 return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0);
4573             }
4574         }
4575         return 0;
4576     }
4577 
reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime)4578     public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
4579         uid = mapUid(uid);
4580         Uid u = mUidStats.get(uid);
4581         if (u != null) {
4582             u.reportExcessiveCpuLocked(proc, overTime, usedTime);
4583         }
4584     }
4585 
4586     int mSensorNesting;
4587 
noteStartSensorLocked(int uid, int sensor)4588     public void noteStartSensorLocked(int uid, int sensor) {
4589         uid = mapUid(uid);
4590         final long elapsedRealtime = mClocks.elapsedRealtime();
4591         final long uptime = mClocks.uptimeMillis();
4592         if (mSensorNesting == 0) {
4593             mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
4594             if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
4595                     + Integer.toHexString(mHistoryCur.states));
4596             addHistoryRecordLocked(elapsedRealtime, uptime);
4597         }
4598         mSensorNesting++;
4599         getUidStatsLocked(uid).noteStartSensor(sensor, elapsedRealtime);
4600     }
4601 
noteStopSensorLocked(int uid, int sensor)4602     public void noteStopSensorLocked(int uid, int sensor) {
4603         uid = mapUid(uid);
4604         final long elapsedRealtime = mClocks.elapsedRealtime();
4605         final long uptime = mClocks.uptimeMillis();
4606         mSensorNesting--;
4607         if (mSensorNesting == 0) {
4608             mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
4609             if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
4610                     + Integer.toHexString(mHistoryCur.states));
4611             addHistoryRecordLocked(elapsedRealtime, uptime);
4612         }
4613         getUidStatsLocked(uid).noteStopSensor(sensor, elapsedRealtime);
4614     }
4615 
4616     int mGpsNesting;
4617 
noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs)4618     public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
4619         for (int i = 0; i < newWs.size(); ++i) {
4620             noteStartGpsLocked(newWs.get(i), null);
4621         }
4622 
4623         for (int i = 0; i < oldWs.size(); ++i) {
4624             noteStopGpsLocked((oldWs.get(i)), null);
4625         }
4626 
4627         List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
4628         if (wcs != null) {
4629             if (wcs[0] != null) {
4630                 final List<WorkChain> newChains = wcs[0];
4631                 for (int i = 0; i < newChains.size(); ++i) {
4632                     noteStartGpsLocked(-1, newChains.get(i));
4633                 }
4634             }
4635 
4636             if (wcs[1] != null) {
4637                 final List<WorkChain> goneChains = wcs[1];
4638                 for (int i = 0; i < goneChains.size(); ++i) {
4639                     noteStopGpsLocked(-1, goneChains.get(i));
4640                 }
4641             }
4642         }
4643     }
4644 
noteStartGpsLocked(int uid, WorkChain workChain)4645     private void noteStartGpsLocked(int uid, WorkChain workChain) {
4646         uid = getAttributionUid(uid, workChain);
4647         final long elapsedRealtime = mClocks.elapsedRealtime();
4648         final long uptime = mClocks.uptimeMillis();
4649         if (mGpsNesting == 0) {
4650             mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
4651             if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
4652                     + Integer.toHexString(mHistoryCur.states));
4653             addHistoryRecordLocked(elapsedRealtime, uptime);
4654         }
4655         mGpsNesting++;
4656 
4657         if (workChain == null) {
4658             StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
4659                     StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
4660         } else {
4661             StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED,
4662                     workChain.getUids(), workChain.getTags(),
4663                     StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
4664         }
4665 
4666         getUidStatsLocked(uid).noteStartGps(elapsedRealtime);
4667     }
4668 
noteStopGpsLocked(int uid, WorkChain workChain)4669     private void noteStopGpsLocked(int uid, WorkChain workChain) {
4670         uid = getAttributionUid(uid, workChain);
4671         final long elapsedRealtime = mClocks.elapsedRealtime();
4672         final long uptime = mClocks.uptimeMillis();
4673         mGpsNesting--;
4674         if (mGpsNesting == 0) {
4675             mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
4676             if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
4677                     + Integer.toHexString(mHistoryCur.states));
4678             addHistoryRecordLocked(elapsedRealtime, uptime);
4679             stopAllGpsSignalQualityTimersLocked(-1);
4680             mGpsSignalQualityBin = -1;
4681         }
4682 
4683         if (workChain == null) {
4684             StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
4685                     StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
4686         } else {
4687             StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(),
4688                     workChain.getTags(), StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
4689         }
4690 
4691         getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
4692     }
4693 
noteGpsSignalQualityLocked(int signalLevel)4694     public void noteGpsSignalQualityLocked(int signalLevel) {
4695         if (mGpsNesting == 0) {
4696             return;
4697         }
4698         if (signalLevel < 0 || signalLevel >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
4699             stopAllGpsSignalQualityTimersLocked(-1);
4700             return;
4701         }
4702         final long elapsedRealtime = mClocks.elapsedRealtime();
4703         final long uptime = mClocks.uptimeMillis();
4704         if (mGpsSignalQualityBin != signalLevel) {
4705             if (mGpsSignalQualityBin >= 0) {
4706                 mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtime);
4707             }
4708             if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
4709                 mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtime);
4710             }
4711             mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
4712                     | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
4713             addHistoryRecordLocked(elapsedRealtime, uptime);
4714             mGpsSignalQualityBin = signalLevel;
4715         }
4716         return;
4717     }
4718 
4719     @GuardedBy("this")
noteScreenStateLocked(int state)4720     public void noteScreenStateLocked(int state) {
4721         state = mPretendScreenOff ? Display.STATE_OFF : state;
4722 
4723         // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
4724         // original 4 are mapped to one of the originals.
4725         if (state > MAX_TRACKED_SCREEN_STATE) {
4726             switch (state) {
4727                 case Display.STATE_VR:
4728                     state = Display.STATE_ON;
4729                     break;
4730                 default:
4731                     Slog.wtf(TAG, "Unknown screen state (not mapped): " + state);
4732                     break;
4733             }
4734         }
4735 
4736         if (mScreenState != state) {
4737             recordDailyStatsIfNeededLocked(true);
4738             final int oldState = mScreenState;
4739             mScreenState = state;
4740             if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
4741                     + ", newState=" + Display.stateToString(state));
4742 
4743             if (state != Display.STATE_UNKNOWN) {
4744                 int stepState = state-1;
4745                 if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
4746                     mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
4747                     mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
4748                 } else {
4749                     Slog.wtf(TAG, "Unexpected screen state: " + state);
4750                 }
4751             }
4752 
4753             final long elapsedRealtime = mClocks.elapsedRealtime();
4754             final long uptime = mClocks.uptimeMillis();
4755 
4756             boolean updateHistory = false;
4757             if (isScreenDoze(state)) {
4758                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
4759                 mScreenDozeTimer.startRunningLocked(elapsedRealtime);
4760                 updateHistory = true;
4761             } else if (isScreenDoze(oldState)) {
4762                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG;
4763                 mScreenDozeTimer.stopRunningLocked(elapsedRealtime);
4764                 updateHistory = true;
4765             }
4766             if (isScreenOn(state)) {
4767                 mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
4768                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
4769                         + Integer.toHexString(mHistoryCur.states));
4770                 mScreenOnTimer.startRunningLocked(elapsedRealtime);
4771                 if (mScreenBrightnessBin >= 0) {
4772                     mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
4773                 }
4774                 updateHistory = true;
4775             } else if (isScreenOn(oldState)) {
4776                 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
4777                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
4778                         + Integer.toHexString(mHistoryCur.states));
4779                 mScreenOnTimer.stopRunningLocked(elapsedRealtime);
4780                 if (mScreenBrightnessBin >= 0) {
4781                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
4782                 }
4783                 updateHistory = true;
4784             }
4785             if (updateHistory) {
4786                 if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: "
4787                         + Display.stateToString(state));
4788                 addHistoryRecordLocked(elapsedRealtime, uptime);
4789             }
4790             mExternalSync.scheduleCpuSyncDueToScreenStateChange(
4791                     mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
4792             if (isScreenOn(state)) {
4793                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
4794                         mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
4795                 // Fake a wake lock, so we consider the device waked as long as the screen is on.
4796                 noteStartWakeLocked(-1, -1, null, "screen", null, WAKE_TYPE_PARTIAL, false,
4797                         elapsedRealtime, uptime);
4798             } else if (isScreenOn(oldState)) {
4799                 noteStopWakeLocked(-1, -1, null, "screen", "screen", WAKE_TYPE_PARTIAL,
4800                         elapsedRealtime, uptime);
4801                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
4802                         mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
4803             }
4804             // Update discharge amounts.
4805             if (mOnBatteryInternal) {
4806                 updateDischargeScreenLevelsLocked(oldState, state);
4807             }
4808         }
4809     }
4810 
4811     @UnsupportedAppUsage
noteScreenBrightnessLocked(int brightness)4812     public void noteScreenBrightnessLocked(int brightness) {
4813         // Bin the brightness.
4814         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
4815         if (bin < 0) bin = 0;
4816         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
4817         if (mScreenBrightnessBin != bin) {
4818             final long elapsedRealtime = mClocks.elapsedRealtime();
4819             final long uptime = mClocks.uptimeMillis();
4820             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
4821                     | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
4822             if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
4823                     + Integer.toHexString(mHistoryCur.states));
4824             addHistoryRecordLocked(elapsedRealtime, uptime);
4825             if (mScreenState == Display.STATE_ON) {
4826                 if (mScreenBrightnessBin >= 0) {
4827                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
4828                 }
4829                 mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime);
4830             }
4831             mScreenBrightnessBin = bin;
4832         }
4833     }
4834 
4835     @UnsupportedAppUsage
noteUserActivityLocked(int uid, int event)4836     public void noteUserActivityLocked(int uid, int event) {
4837         if (mOnBatteryInternal) {
4838             uid = mapUid(uid);
4839             getUidStatsLocked(uid).noteUserActivityLocked(event);
4840         }
4841     }
4842 
noteWakeUpLocked(String reason, int reasonUid)4843     public void noteWakeUpLocked(String reason, int reasonUid) {
4844         final long elapsedRealtime = mClocks.elapsedRealtime();
4845         final long uptime = mClocks.uptimeMillis();
4846         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SCREEN_WAKE_UP,
4847                 reason, reasonUid);
4848     }
4849 
noteInteractiveLocked(boolean interactive)4850     public void noteInteractiveLocked(boolean interactive) {
4851         if (mInteractive != interactive) {
4852             final long elapsedRealtime = mClocks.elapsedRealtime();
4853             mInteractive = interactive;
4854             if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
4855             if (interactive) {
4856                 mInteractiveTimer.startRunningLocked(elapsedRealtime);
4857             } else {
4858                 mInteractiveTimer.stopRunningLocked(elapsedRealtime);
4859             }
4860         }
4861     }
4862 
noteConnectivityChangedLocked(int type, String extra)4863     public void noteConnectivityChangedLocked(int type, String extra) {
4864         final long elapsedRealtime = mClocks.elapsedRealtime();
4865         final long uptime = mClocks.uptimeMillis();
4866         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
4867                 extra, type);
4868         mNumConnectivityChange++;
4869     }
4870 
noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)4871     private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
4872             final long uptimeMillis, int uid) {
4873         uid = mapUid(uid);
4874         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
4875                 uid);
4876         getUidStatsLocked(uid).noteMobileRadioApWakeupLocked();
4877     }
4878 
4879     /**
4880      * Updates the radio power state and returns true if an external stats collection should occur.
4881      */
noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid)4882     public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
4883         final long elapsedRealtime = mClocks.elapsedRealtime();
4884         final long uptime = mClocks.uptimeMillis();
4885         if (mMobileRadioPowerState != powerState) {
4886             long realElapsedRealtimeMs;
4887             final boolean active =
4888                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
4889                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
4890             if (active) {
4891                 if (uid > 0) {
4892                     noteMobileRadioApWakeupLocked(elapsedRealtime, uptime, uid);
4893                 }
4894 
4895                 mMobileRadioActiveStartTime = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
4896                 mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
4897             } else {
4898                 realElapsedRealtimeMs = timestampNs / (1000*1000);
4899                 long lastUpdateTimeMs = mMobileRadioActiveStartTime;
4900                 if (realElapsedRealtimeMs < lastUpdateTimeMs) {
4901                     Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
4902                             + " is before start time " + lastUpdateTimeMs);
4903                     realElapsedRealtimeMs = elapsedRealtime;
4904                 } else if (realElapsedRealtimeMs < elapsedRealtime) {
4905                     mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
4906                             - realElapsedRealtimeMs);
4907                 }
4908                 mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
4909             }
4910             if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
4911                     + Integer.toHexString(mHistoryCur.states));
4912             addHistoryRecordLocked(elapsedRealtime, uptime);
4913             mMobileRadioPowerState = powerState;
4914             if (active) {
4915                 mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
4916                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
4917             } else {
4918                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
4919                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
4920                 // Tell the caller to collect radio network/power stats.
4921                 return true;
4922             }
4923         }
4924         return false;
4925     }
4926 
notePowerSaveModeLocked(boolean enabled)4927     public void notePowerSaveModeLocked(boolean enabled) {
4928         if (mPowerSaveModeEnabled != enabled) {
4929             int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
4930             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
4931             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
4932             final long elapsedRealtime = mClocks.elapsedRealtime();
4933             final long uptime = mClocks.uptimeMillis();
4934             mPowerSaveModeEnabled = enabled;
4935             if (enabled) {
4936                 mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
4937                 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
4938                         + Integer.toHexString(mHistoryCur.states2));
4939                 mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtime);
4940             } else {
4941                 mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
4942                 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
4943                         + Integer.toHexString(mHistoryCur.states2));
4944                 mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtime);
4945             }
4946             addHistoryRecordLocked(elapsedRealtime, uptime);
4947             StatsLog.write(StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED, enabled ?
4948                     StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON :
4949                     StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
4950         }
4951     }
4952 
noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid)4953     public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid) {
4954         final long elapsedRealtime = mClocks.elapsedRealtime();
4955         final long uptime = mClocks.uptimeMillis();
4956         boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
4957         if (mDeviceIdling && !nowIdling && activeReason == null) {
4958             // We don't go out of general idling mode until explicitly taken out of
4959             // device idle through going active or significant motion.
4960             nowIdling = true;
4961         }
4962         boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
4963         if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
4964             // We don't go out of general light idling mode until explicitly taken out of
4965             // device idle through going active or significant motion.
4966             nowLightIdling = true;
4967         }
4968         if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
4969             addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
4970                     activeReason, activeUid);
4971         }
4972         if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
4973             int statsmode;
4974             if (nowIdling)           statsmode = DEVICE_IDLE_MODE_DEEP;
4975             else if (nowLightIdling) statsmode = DEVICE_IDLE_MODE_LIGHT;
4976             else                     statsmode = DEVICE_IDLE_MODE_OFF;
4977             StatsLog.write(StatsLog.DEVICE_IDLING_MODE_STATE_CHANGED, statsmode);
4978         }
4979         if (mDeviceIdling != nowIdling) {
4980             mDeviceIdling = nowIdling;
4981             int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
4982             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
4983             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
4984             if (nowIdling) {
4985                 mDeviceIdlingTimer.startRunningLocked(elapsedRealtime);
4986             } else {
4987                 mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime);
4988             }
4989         }
4990         if (mDeviceLightIdling != nowLightIdling) {
4991             mDeviceLightIdling = nowLightIdling;
4992             if (nowLightIdling) {
4993                 mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtime);
4994             } else {
4995                 mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtime);
4996             }
4997         }
4998         if (mDeviceIdleMode != mode) {
4999             mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
5000                     | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
5001             if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
5002                     + Integer.toHexString(mHistoryCur.states2));
5003             addHistoryRecordLocked(elapsedRealtime, uptime);
5004             long lastDuration = elapsedRealtime - mLastIdleTimeStart;
5005             mLastIdleTimeStart = elapsedRealtime;
5006             if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
5007                 if (lastDuration > mLongestLightIdleTime) {
5008                     mLongestLightIdleTime = lastDuration;
5009                 }
5010                 mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtime);
5011             } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
5012                 if (lastDuration > mLongestFullIdleTime) {
5013                     mLongestFullIdleTime = lastDuration;
5014                 }
5015                 mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtime);
5016             }
5017             if (mode == DEVICE_IDLE_MODE_LIGHT) {
5018                 mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtime);
5019             } else if (mode == DEVICE_IDLE_MODE_DEEP) {
5020                 mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtime);
5021             }
5022             mDeviceIdleMode = mode;
5023             StatsLog.write(StatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mode);
5024         }
5025     }
5026 
notePackageInstalledLocked(String pkgName, long versionCode)5027     public void notePackageInstalledLocked(String pkgName, long versionCode) {
5028         final long elapsedRealtime = mClocks.elapsedRealtime();
5029         final long uptime = mClocks.uptimeMillis();
5030         // XXX need to figure out what to do with long version codes.
5031         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED,
5032                 pkgName, (int)versionCode);
5033         PackageChange pc = new PackageChange();
5034         pc.mPackageName = pkgName;
5035         pc.mUpdate = true;
5036         pc.mVersionCode = versionCode;
5037         addPackageChange(pc);
5038     }
5039 
notePackageUninstalledLocked(String pkgName)5040     public void notePackageUninstalledLocked(String pkgName) {
5041         final long elapsedRealtime = mClocks.elapsedRealtime();
5042         final long uptime = mClocks.uptimeMillis();
5043         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
5044                 pkgName, 0);
5045         PackageChange pc = new PackageChange();
5046         pc.mPackageName = pkgName;
5047         pc.mUpdate = true;
5048         addPackageChange(pc);
5049     }
5050 
addPackageChange(PackageChange pc)5051     private void addPackageChange(PackageChange pc) {
5052         if (mDailyPackageChanges == null) {
5053             mDailyPackageChanges = new ArrayList<>();
5054         }
5055         mDailyPackageChanges.add(pc);
5056     }
5057 
stopAllGpsSignalQualityTimersLocked(int except)5058     void stopAllGpsSignalQualityTimersLocked(int except) {
5059         final long elapsedRealtime = mClocks.elapsedRealtime();
5060         for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
5061             if (i == except) {
5062                 continue;
5063             }
5064             while (mGpsSignalQualityTimer[i].isRunningLocked()) {
5065                 mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtime);
5066             }
5067         }
5068     }
5069 
5070     @UnsupportedAppUsage
notePhoneOnLocked()5071     public void notePhoneOnLocked() {
5072         if (!mPhoneOn) {
5073             final long elapsedRealtime = mClocks.elapsedRealtime();
5074             final long uptime = mClocks.uptimeMillis();
5075             mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
5076             if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
5077                     + Integer.toHexString(mHistoryCur.states));
5078             addHistoryRecordLocked(elapsedRealtime, uptime);
5079             mPhoneOn = true;
5080             mPhoneOnTimer.startRunningLocked(elapsedRealtime);
5081         }
5082     }
5083 
5084     @UnsupportedAppUsage
notePhoneOffLocked()5085     public void notePhoneOffLocked() {
5086         if (mPhoneOn) {
5087             final long elapsedRealtime = mClocks.elapsedRealtime();
5088             final long uptime = mClocks.uptimeMillis();
5089             mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
5090             if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
5091                     + Integer.toHexString(mHistoryCur.states));
5092             addHistoryRecordLocked(elapsedRealtime, uptime);
5093             mPhoneOn = false;
5094             mPhoneOnTimer.stopRunningLocked(elapsedRealtime);
5095         }
5096     }
5097 
registerUsbStateReceiver(Context context)5098     private void registerUsbStateReceiver(Context context) {
5099         final IntentFilter usbStateFilter = new IntentFilter();
5100         usbStateFilter.addAction(UsbManager.ACTION_USB_STATE);
5101         context.registerReceiver(new BroadcastReceiver() {
5102             @Override
5103             public void onReceive(Context context, Intent intent) {
5104                 final boolean state = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
5105                 synchronized (BatteryStatsImpl.this) {
5106                     noteUsbConnectionStateLocked(state);
5107                 }
5108             }
5109         }, usbStateFilter);
5110         synchronized (this) {
5111             if (mUsbDataState == USB_DATA_UNKNOWN) {
5112                 final Intent usbState = context.registerReceiver(null, usbStateFilter);
5113                 final boolean initState = usbState != null && usbState.getBooleanExtra(
5114                         UsbManager.USB_CONNECTED, false);
5115                 noteUsbConnectionStateLocked(initState);
5116             }
5117         }
5118     }
5119 
noteUsbConnectionStateLocked(boolean connected)5120     private void noteUsbConnectionStateLocked(boolean connected) {
5121         int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED;
5122         if (mUsbDataState != newState) {
5123             mUsbDataState = newState;
5124             if (connected) {
5125                 mHistoryCur.states2 |= HistoryItem.STATE2_USB_DATA_LINK_FLAG;
5126             } else {
5127                 mHistoryCur.states2 &= ~HistoryItem.STATE2_USB_DATA_LINK_FLAG;
5128             }
5129             addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5130         }
5131     }
5132 
stopAllPhoneSignalStrengthTimersLocked(int except)5133     void stopAllPhoneSignalStrengthTimersLocked(int except) {
5134         final long elapsedRealtime = mClocks.elapsedRealtime();
5135         for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
5136             if (i == except) {
5137                 continue;
5138             }
5139             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
5140                 mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
5141             }
5142         }
5143     }
5144 
fixPhoneServiceState(int state, int signalBin)5145     private int fixPhoneServiceState(int state, int signalBin) {
5146         if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
5147             // In this case we will always be STATE_OUT_OF_SERVICE, so need
5148             // to infer that we are scanning from other data.
5149             if (state == ServiceState.STATE_OUT_OF_SERVICE
5150                     && signalBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5151                 state = ServiceState.STATE_IN_SERVICE;
5152             }
5153         }
5154 
5155         return state;
5156     }
5157 
updateAllPhoneStateLocked(int state, int simState, int strengthBin)5158     private void updateAllPhoneStateLocked(int state, int simState, int strengthBin) {
5159         boolean scanning = false;
5160         boolean newHistory = false;
5161 
5162         mPhoneServiceStateRaw = state;
5163         mPhoneSimStateRaw = simState;
5164         mPhoneSignalStrengthBinRaw = strengthBin;
5165 
5166         final long elapsedRealtime = mClocks.elapsedRealtime();
5167         final long uptime = mClocks.uptimeMillis();
5168 
5169         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
5170             // In this case we will always be STATE_OUT_OF_SERVICE, so need
5171             // to infer that we are scanning from other data.
5172             if (state == ServiceState.STATE_OUT_OF_SERVICE
5173                     && strengthBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5174                 state = ServiceState.STATE_IN_SERVICE;
5175             }
5176         }
5177 
5178         // If the phone is powered off, stop all timers.
5179         if (state == ServiceState.STATE_POWER_OFF) {
5180             strengthBin = -1;
5181 
5182         // If we are in service, make sure the correct signal string timer is running.
5183         } else if (state == ServiceState.STATE_IN_SERVICE) {
5184             // Bin will be changed below.
5185 
5186         // If we're out of service, we are in the lowest signal strength
5187         // bin and have the scanning bit set.
5188         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
5189             scanning = true;
5190             strengthBin = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
5191             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
5192                 mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
5193                 newHistory = true;
5194                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
5195                         + Integer.toHexString(mHistoryCur.states));
5196                 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
5197                 StatsLog.write(StatsLog.PHONE_SERVICE_STATE_CHANGED, state, simState, strengthBin);
5198             }
5199         }
5200 
5201         if (!scanning) {
5202             // If we are no longer scanning, then stop the scanning timer.
5203             if (mPhoneSignalScanningTimer.isRunningLocked()) {
5204                 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
5205                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
5206                         + Integer.toHexString(mHistoryCur.states));
5207                 newHistory = true;
5208                 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
5209                 StatsLog.write(StatsLog.PHONE_SERVICE_STATE_CHANGED, state, simState, strengthBin);
5210             }
5211         }
5212 
5213         if (mPhoneServiceState != state) {
5214             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
5215                     | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
5216             if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
5217                     + Integer.toHexString(mHistoryCur.states));
5218             newHistory = true;
5219             mPhoneServiceState = state;
5220         }
5221 
5222         if (mPhoneSignalStrengthBin != strengthBin) {
5223             if (mPhoneSignalStrengthBin >= 0) {
5224                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
5225                         elapsedRealtime);
5226             }
5227             if (strengthBin >= 0) {
5228                 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
5229                     mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
5230                 }
5231                 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
5232                         | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
5233                 if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
5234                         + Integer.toHexString(mHistoryCur.states));
5235                 newHistory = true;
5236                 StatsLog.write(StatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
5237             } else {
5238                 stopAllPhoneSignalStrengthTimersLocked(-1);
5239             }
5240             mPhoneSignalStrengthBin = strengthBin;
5241         }
5242 
5243         if (newHistory) {
5244             addHistoryRecordLocked(elapsedRealtime, uptime);
5245         }
5246     }
5247 
5248     /**
5249      * Telephony stack updates the phone state.
5250      * @param state phone state from ServiceState.getState()
5251      */
notePhoneStateLocked(int state, int simState)5252     public void notePhoneStateLocked(int state, int simState) {
5253         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
5254     }
5255 
5256     @UnsupportedAppUsage
notePhoneSignalStrengthLocked(SignalStrength signalStrength)5257     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
5258         // Bin the strength.
5259         int bin = signalStrength.getLevel();
5260         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
5261     }
5262 
5263     @UnsupportedAppUsage
notePhoneDataConnectionStateLocked(int dataType, boolean hasData)5264     public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
5265         // BatteryStats uses 0 to represent no network type.
5266         // Telephony does not have a concept of no network type, and uses 0 to represent unknown.
5267         // Unknown is included in DATA_CONNECTION_OTHER.
5268         int bin = DATA_CONNECTION_NONE;
5269         if (hasData) {
5270             if (dataType > 0 && dataType <= TelephonyManager.MAX_NETWORK_TYPE) {
5271                 bin = dataType;
5272             } else {
5273                 bin = DATA_CONNECTION_OTHER;
5274             }
5275         }
5276         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
5277         if (mPhoneDataConnectionType != bin) {
5278             final long elapsedRealtime = mClocks.elapsedRealtime();
5279             final long uptime = mClocks.uptimeMillis();
5280             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
5281                     | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
5282             if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
5283                     + Integer.toHexString(mHistoryCur.states));
5284             addHistoryRecordLocked(elapsedRealtime, uptime);
5285             if (mPhoneDataConnectionType >= 0) {
5286                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
5287                         elapsedRealtime);
5288             }
5289             mPhoneDataConnectionType = bin;
5290             mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime);
5291         }
5292     }
5293 
noteWifiOnLocked()5294     public void noteWifiOnLocked() {
5295         if (!mWifiOn) {
5296             final long elapsedRealtime = mClocks.elapsedRealtime();
5297             final long uptime = mClocks.uptimeMillis();
5298             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
5299             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
5300                     + Integer.toHexString(mHistoryCur.states));
5301             addHistoryRecordLocked(elapsedRealtime, uptime);
5302             mWifiOn = true;
5303             mWifiOnTimer.startRunningLocked(elapsedRealtime);
5304             scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
5305         }
5306     }
5307 
noteWifiOffLocked()5308     public void noteWifiOffLocked() {
5309         final long elapsedRealtime = mClocks.elapsedRealtime();
5310         final long uptime = mClocks.uptimeMillis();
5311         if (mWifiOn) {
5312             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
5313             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
5314                     + Integer.toHexString(mHistoryCur.states));
5315             addHistoryRecordLocked(elapsedRealtime, uptime);
5316             mWifiOn = false;
5317             mWifiOnTimer.stopRunningLocked(elapsedRealtime);
5318             scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
5319         }
5320     }
5321 
5322     @UnsupportedAppUsage
noteAudioOnLocked(int uid)5323     public void noteAudioOnLocked(int uid) {
5324         uid = mapUid(uid);
5325         final long elapsedRealtime = mClocks.elapsedRealtime();
5326         final long uptime = mClocks.uptimeMillis();
5327         if (mAudioOnNesting == 0) {
5328             mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
5329             if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
5330                     + Integer.toHexString(mHistoryCur.states));
5331             addHistoryRecordLocked(elapsedRealtime, uptime);
5332             mAudioOnTimer.startRunningLocked(elapsedRealtime);
5333         }
5334         mAudioOnNesting++;
5335         getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
5336     }
5337 
5338     @UnsupportedAppUsage
noteAudioOffLocked(int uid)5339     public void noteAudioOffLocked(int uid) {
5340         if (mAudioOnNesting == 0) {
5341             return;
5342         }
5343         uid = mapUid(uid);
5344         final long elapsedRealtime = mClocks.elapsedRealtime();
5345         final long uptime = mClocks.uptimeMillis();
5346         if (--mAudioOnNesting == 0) {
5347             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
5348             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
5349                     + Integer.toHexString(mHistoryCur.states));
5350             addHistoryRecordLocked(elapsedRealtime, uptime);
5351             mAudioOnTimer.stopRunningLocked(elapsedRealtime);
5352         }
5353         getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
5354     }
5355 
5356     @UnsupportedAppUsage
noteVideoOnLocked(int uid)5357     public void noteVideoOnLocked(int uid) {
5358         uid = mapUid(uid);
5359         final long elapsedRealtime = mClocks.elapsedRealtime();
5360         final long uptime = mClocks.uptimeMillis();
5361         if (mVideoOnNesting == 0) {
5362             mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
5363             if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
5364                     + Integer.toHexString(mHistoryCur.states));
5365             addHistoryRecordLocked(elapsedRealtime, uptime);
5366             mVideoOnTimer.startRunningLocked(elapsedRealtime);
5367         }
5368         mVideoOnNesting++;
5369         getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
5370     }
5371 
5372     @UnsupportedAppUsage
noteVideoOffLocked(int uid)5373     public void noteVideoOffLocked(int uid) {
5374         if (mVideoOnNesting == 0) {
5375             return;
5376         }
5377         uid = mapUid(uid);
5378         final long elapsedRealtime = mClocks.elapsedRealtime();
5379         final long uptime = mClocks.uptimeMillis();
5380         if (--mVideoOnNesting == 0) {
5381             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
5382             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
5383                     + Integer.toHexString(mHistoryCur.states));
5384             addHistoryRecordLocked(elapsedRealtime, uptime);
5385             mVideoOnTimer.stopRunningLocked(elapsedRealtime);
5386         }
5387         getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime);
5388     }
5389 
noteResetAudioLocked()5390     public void noteResetAudioLocked() {
5391         if (mAudioOnNesting > 0) {
5392             final long elapsedRealtime = mClocks.elapsedRealtime();
5393             final long uptime = mClocks.uptimeMillis();
5394             mAudioOnNesting = 0;
5395             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
5396             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
5397                     + Integer.toHexString(mHistoryCur.states));
5398             addHistoryRecordLocked(elapsedRealtime, uptime);
5399             mAudioOnTimer.stopAllRunningLocked(elapsedRealtime);
5400             for (int i=0; i<mUidStats.size(); i++) {
5401                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5402                 uid.noteResetAudioLocked(elapsedRealtime);
5403             }
5404         }
5405     }
5406 
noteResetVideoLocked()5407     public void noteResetVideoLocked() {
5408         if (mVideoOnNesting > 0) {
5409             final long elapsedRealtime = mClocks.elapsedRealtime();
5410             final long uptime = mClocks.uptimeMillis();
5411             mAudioOnNesting = 0;
5412             mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
5413             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
5414                     + Integer.toHexString(mHistoryCur.states));
5415             addHistoryRecordLocked(elapsedRealtime, uptime);
5416             mVideoOnTimer.stopAllRunningLocked(elapsedRealtime);
5417             for (int i=0; i<mUidStats.size(); i++) {
5418                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5419                 uid.noteResetVideoLocked(elapsedRealtime);
5420             }
5421         }
5422     }
5423 
noteActivityResumedLocked(int uid)5424     public void noteActivityResumedLocked(int uid) {
5425         uid = mapUid(uid);
5426         getUidStatsLocked(uid).noteActivityResumedLocked(mClocks.elapsedRealtime());
5427     }
5428 
noteActivityPausedLocked(int uid)5429     public void noteActivityPausedLocked(int uid) {
5430         uid = mapUid(uid);
5431         getUidStatsLocked(uid).noteActivityPausedLocked(mClocks.elapsedRealtime());
5432     }
5433 
noteVibratorOnLocked(int uid, long durationMillis)5434     public void noteVibratorOnLocked(int uid, long durationMillis) {
5435         uid = mapUid(uid);
5436         getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis);
5437     }
5438 
noteVibratorOffLocked(int uid)5439     public void noteVibratorOffLocked(int uid) {
5440         uid = mapUid(uid);
5441         getUidStatsLocked(uid).noteVibratorOffLocked();
5442     }
5443 
noteFlashlightOnLocked(int uid)5444     public void noteFlashlightOnLocked(int uid) {
5445         uid = mapUid(uid);
5446         final long elapsedRealtime = mClocks.elapsedRealtime();
5447         final long uptime = mClocks.uptimeMillis();
5448         if (mFlashlightOnNesting++ == 0) {
5449             mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
5450             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
5451                     + Integer.toHexString(mHistoryCur.states2));
5452             addHistoryRecordLocked(elapsedRealtime, uptime);
5453             mFlashlightOnTimer.startRunningLocked(elapsedRealtime);
5454         }
5455         getUidStatsLocked(uid).noteFlashlightTurnedOnLocked(elapsedRealtime);
5456     }
5457 
noteFlashlightOffLocked(int uid)5458     public void noteFlashlightOffLocked(int uid) {
5459         if (mFlashlightOnNesting == 0) {
5460             return;
5461         }
5462         uid = mapUid(uid);
5463         final long elapsedRealtime = mClocks.elapsedRealtime();
5464         final long uptime = mClocks.uptimeMillis();
5465         if (--mFlashlightOnNesting == 0) {
5466             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
5467             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
5468                     + Integer.toHexString(mHistoryCur.states2));
5469             addHistoryRecordLocked(elapsedRealtime, uptime);
5470             mFlashlightOnTimer.stopRunningLocked(elapsedRealtime);
5471         }
5472         getUidStatsLocked(uid).noteFlashlightTurnedOffLocked(elapsedRealtime);
5473     }
5474 
noteCameraOnLocked(int uid)5475     public void noteCameraOnLocked(int uid) {
5476         uid = mapUid(uid);
5477         final long elapsedRealtime = mClocks.elapsedRealtime();
5478         final long uptime = mClocks.uptimeMillis();
5479         if (mCameraOnNesting++ == 0) {
5480             mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
5481             if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
5482                     + Integer.toHexString(mHistoryCur.states2));
5483             addHistoryRecordLocked(elapsedRealtime, uptime);
5484             mCameraOnTimer.startRunningLocked(elapsedRealtime);
5485         }
5486         getUidStatsLocked(uid).noteCameraTurnedOnLocked(elapsedRealtime);
5487     }
5488 
noteCameraOffLocked(int uid)5489     public void noteCameraOffLocked(int uid) {
5490         if (mCameraOnNesting == 0) {
5491             return;
5492         }
5493         uid = mapUid(uid);
5494         final long elapsedRealtime = mClocks.elapsedRealtime();
5495         final long uptime = mClocks.uptimeMillis();
5496         if (--mCameraOnNesting == 0) {
5497             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
5498             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
5499                     + Integer.toHexString(mHistoryCur.states2));
5500             addHistoryRecordLocked(elapsedRealtime, uptime);
5501             mCameraOnTimer.stopRunningLocked(elapsedRealtime);
5502         }
5503         getUidStatsLocked(uid).noteCameraTurnedOffLocked(elapsedRealtime);
5504     }
5505 
noteResetCameraLocked()5506     public void noteResetCameraLocked() {
5507         if (mCameraOnNesting > 0) {
5508             final long elapsedRealtime = mClocks.elapsedRealtime();
5509             final long uptime = mClocks.uptimeMillis();
5510             mCameraOnNesting = 0;
5511             mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
5512             if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
5513                     + Integer.toHexString(mHistoryCur.states2));
5514             addHistoryRecordLocked(elapsedRealtime, uptime);
5515             mCameraOnTimer.stopAllRunningLocked(elapsedRealtime);
5516             for (int i=0; i<mUidStats.size(); i++) {
5517                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5518                 uid.noteResetCameraLocked(elapsedRealtime);
5519             }
5520         }
5521     }
5522 
noteResetFlashlightLocked()5523     public void noteResetFlashlightLocked() {
5524         if (mFlashlightOnNesting > 0) {
5525             final long elapsedRealtime = mClocks.elapsedRealtime();
5526             final long uptime = mClocks.uptimeMillis();
5527             mFlashlightOnNesting = 0;
5528             mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
5529             if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
5530                     + Integer.toHexString(mHistoryCur.states2));
5531             addHistoryRecordLocked(elapsedRealtime, uptime);
5532             mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtime);
5533             for (int i=0; i<mUidStats.size(); i++) {
5534                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5535                 uid.noteResetFlashlightLocked(elapsedRealtime);
5536             }
5537         }
5538     }
5539 
noteBluetoothScanStartedLocked(WorkChain workChain, int uid, boolean isUnoptimized)5540     private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
5541             boolean isUnoptimized) {
5542         uid = getAttributionUid(uid, workChain);
5543         final long elapsedRealtime = mClocks.elapsedRealtime();
5544         final long uptime = mClocks.uptimeMillis();
5545         if (mBluetoothScanNesting == 0) {
5546             mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5547             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
5548                     + Integer.toHexString(mHistoryCur.states2));
5549             addHistoryRecordLocked(elapsedRealtime, uptime);
5550             mBluetoothScanTimer.startRunningLocked(elapsedRealtime);
5551         }
5552         mBluetoothScanNesting++;
5553         getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime, isUnoptimized);
5554     }
5555 
noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized)5556     public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
5557         final int N = ws.size();
5558         for (int i = 0; i < N; i++) {
5559             noteBluetoothScanStartedLocked(null, ws.get(i), isUnoptimized);
5560         }
5561 
5562         final List<WorkChain> workChains = ws.getWorkChains();
5563         if (workChains != null) {
5564             for (int i = 0; i < workChains.size(); ++i) {
5565                 noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized);
5566             }
5567         }
5568     }
5569 
noteBluetoothScanStoppedLocked(WorkChain workChain, int uid, boolean isUnoptimized)5570     private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
5571             boolean isUnoptimized) {
5572         uid = getAttributionUid(uid, workChain);
5573         final long elapsedRealtime = mClocks.elapsedRealtime();
5574         final long uptime = mClocks.uptimeMillis();
5575         mBluetoothScanNesting--;
5576         if (mBluetoothScanNesting == 0) {
5577             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5578             if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
5579                     + Integer.toHexString(mHistoryCur.states2));
5580             addHistoryRecordLocked(elapsedRealtime, uptime);
5581             mBluetoothScanTimer.stopRunningLocked(elapsedRealtime);
5582         }
5583         getUidStatsLocked(uid).noteBluetoothScanStoppedLocked(elapsedRealtime, isUnoptimized);
5584     }
5585 
getAttributionUid(int uid, WorkChain workChain)5586     private int getAttributionUid(int uid, WorkChain workChain) {
5587         if (workChain != null) {
5588             return mapUid(workChain.getAttributionUid());
5589         }
5590 
5591         return mapUid(uid);
5592     }
5593 
noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized)5594     public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
5595         final int N = ws.size();
5596         for (int i = 0; i < N; i++) {
5597             noteBluetoothScanStoppedLocked(null, ws.get(i), isUnoptimized);
5598         }
5599 
5600         final List<WorkChain> workChains = ws.getWorkChains();
5601         if (workChains != null) {
5602             for (int i = 0; i < workChains.size(); ++i) {
5603                 noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized);
5604             }
5605         }
5606     }
5607 
noteResetBluetoothScanLocked()5608     public void noteResetBluetoothScanLocked() {
5609         if (mBluetoothScanNesting > 0) {
5610             final long elapsedRealtime = mClocks.elapsedRealtime();
5611             final long uptime = mClocks.uptimeMillis();
5612             mBluetoothScanNesting = 0;
5613             mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5614             if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
5615                     + Integer.toHexString(mHistoryCur.states2));
5616             addHistoryRecordLocked(elapsedRealtime, uptime);
5617             mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtime);
5618             for (int i=0; i<mUidStats.size(); i++) {
5619                 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5620                 uid.noteResetBluetoothScanLocked(elapsedRealtime);
5621             }
5622         }
5623     }
5624 
noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults)5625     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
5626         final int N = ws.size();
5627         for (int i = 0; i < N; i++) {
5628             int uid = mapUid(ws.get(i));
5629             getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
5630         }
5631 
5632         final List<WorkChain> workChains = ws.getWorkChains();
5633         if (workChains != null) {
5634             for (int i = 0; i < workChains.size(); ++i) {
5635                 final WorkChain wc = workChains.get(i);
5636                 int uid = mapUid(wc.getAttributionUid());
5637                 getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
5638             }
5639         }
5640     }
5641 
noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid)5642     private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
5643             final long uptimeMillis, int uid) {
5644         uid = mapUid(uid);
5645         addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
5646                 uid);
5647         getUidStatsLocked(uid).noteWifiRadioApWakeupLocked();
5648     }
5649 
noteWifiRadioPowerState(int powerState, long timestampNs, int uid)5650     public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) {
5651         final long elapsedRealtime = mClocks.elapsedRealtime();
5652         final long uptime = mClocks.uptimeMillis();
5653         if (mWifiRadioPowerState != powerState) {
5654             final boolean active =
5655                     powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
5656                             || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
5657             if (active) {
5658                 if (uid > 0) {
5659                     noteWifiRadioApWakeupLocked(elapsedRealtime, uptime, uid);
5660                 }
5661                 mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
5662                 mWifiActiveTimer.startRunningLocked(elapsedRealtime);
5663             } else {
5664                 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
5665                 mWifiActiveTimer.stopRunningLocked(
5666                     timestampNs / (1000 * 1000));
5667             }
5668             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
5669                     + Integer.toHexString(mHistoryCur.states));
5670             addHistoryRecordLocked(elapsedRealtime, uptime);
5671             mWifiRadioPowerState = powerState;
5672         }
5673     }
5674 
noteWifiRunningLocked(WorkSource ws)5675     public void noteWifiRunningLocked(WorkSource ws) {
5676         if (!mGlobalWifiRunning) {
5677             final long elapsedRealtime = mClocks.elapsedRealtime();
5678             final long uptime = mClocks.uptimeMillis();
5679             mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
5680             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
5681                     + Integer.toHexString(mHistoryCur.states));
5682             addHistoryRecordLocked(elapsedRealtime, uptime);
5683             mGlobalWifiRunning = true;
5684             mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
5685             int N = ws.size();
5686             for (int i=0; i<N; i++) {
5687                 int uid = mapUid(ws.get(i));
5688                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5689             }
5690 
5691             List<WorkChain> workChains = ws.getWorkChains();
5692             if (workChains != null) {
5693                 for (int i = 0; i < workChains.size(); ++i) {
5694                     int uid = mapUid(workChains.get(i).getAttributionUid());
5695                     getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5696                 }
5697             }
5698 
5699             scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
5700         } else {
5701             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
5702         }
5703     }
5704 
noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs)5705     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
5706         if (mGlobalWifiRunning) {
5707             final long elapsedRealtime = mClocks.elapsedRealtime();
5708             int N = oldWs.size();
5709             for (int i=0; i<N; i++) {
5710                 int uid = mapUid(oldWs.get(i));
5711                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5712             }
5713 
5714             List<WorkChain> workChains = oldWs.getWorkChains();
5715             if (workChains != null) {
5716                 for (int i = 0; i < workChains.size(); ++i) {
5717                     int uid = mapUid(workChains.get(i).getAttributionUid());
5718                     getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5719                 }
5720             }
5721 
5722             N = newWs.size();
5723             for (int i=0; i<N; i++) {
5724                 int uid = mapUid(newWs.get(i));
5725                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5726             }
5727 
5728             workChains = newWs.getWorkChains();
5729             if (workChains != null) {
5730                 for (int i = 0; i < workChains.size(); ++i) {
5731                     int uid = mapUid(workChains.get(i).getAttributionUid());
5732                     getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5733                 }
5734             }
5735         } else {
5736             Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
5737         }
5738     }
5739 
noteWifiStoppedLocked(WorkSource ws)5740     public void noteWifiStoppedLocked(WorkSource ws) {
5741         if (mGlobalWifiRunning) {
5742             final long elapsedRealtime = mClocks.elapsedRealtime();
5743             final long uptime = mClocks.uptimeMillis();
5744             mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
5745             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
5746                     + Integer.toHexString(mHistoryCur.states));
5747             addHistoryRecordLocked(elapsedRealtime, uptime);
5748             mGlobalWifiRunning = false;
5749             mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
5750             int N = ws.size();
5751             for (int i=0; i<N; i++) {
5752                 int uid = mapUid(ws.get(i));
5753                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5754             }
5755 
5756             List<WorkChain> workChains = ws.getWorkChains();
5757             if (workChains != null) {
5758                 for (int i = 0; i < workChains.size(); ++i) {
5759                     int uid = mapUid(workChains.get(i).getAttributionUid());
5760                     getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5761                 }
5762             }
5763 
5764             scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
5765         } else {
5766             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
5767         }
5768     }
5769 
noteWifiStateLocked(int wifiState, String accessPoint)5770     public void noteWifiStateLocked(int wifiState, String accessPoint) {
5771         if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
5772         if (mWifiState != wifiState) {
5773             final long elapsedRealtime = mClocks.elapsedRealtime();
5774             if (mWifiState >= 0) {
5775                 mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
5776             }
5777             mWifiState = wifiState;
5778             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
5779             scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
5780         }
5781     }
5782 
noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth)5783     public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
5784         if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
5785         if (mWifiSupplState != supplState) {
5786             final long elapsedRealtime = mClocks.elapsedRealtime();
5787             final long uptime = mClocks.uptimeMillis();
5788             if (mWifiSupplState >= 0) {
5789                 mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime);
5790             }
5791             mWifiSupplState = supplState;
5792             mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtime);
5793             mHistoryCur.states2 =
5794                     (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
5795                     | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
5796             if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
5797                     + Integer.toHexString(mHistoryCur.states2));
5798             addHistoryRecordLocked(elapsedRealtime, uptime);
5799         }
5800     }
5801 
stopAllWifiSignalStrengthTimersLocked(int except)5802     void stopAllWifiSignalStrengthTimersLocked(int except) {
5803         final long elapsedRealtime = mClocks.elapsedRealtime();
5804         for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
5805             if (i == except) {
5806                 continue;
5807             }
5808             while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
5809                 mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
5810             }
5811         }
5812     }
5813 
noteWifiRssiChangedLocked(int newRssi)5814     public void noteWifiRssiChangedLocked(int newRssi) {
5815         int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
5816         if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
5817         if (mWifiSignalStrengthBin != strengthBin) {
5818             final long elapsedRealtime = mClocks.elapsedRealtime();
5819             final long uptime = mClocks.uptimeMillis();
5820             if (mWifiSignalStrengthBin >= 0) {
5821                 mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
5822                         elapsedRealtime);
5823             }
5824             if (strengthBin >= 0) {
5825                 if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
5826                     mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
5827                 }
5828                 mHistoryCur.states2 =
5829                         (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
5830                         | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
5831                 if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
5832                         + Integer.toHexString(mHistoryCur.states2));
5833                 addHistoryRecordLocked(elapsedRealtime, uptime);
5834             } else {
5835                 stopAllWifiSignalStrengthTimersLocked(-1);
5836             }
5837             mWifiSignalStrengthBin = strengthBin;
5838         }
5839     }
5840 
5841     int mWifiFullLockNesting = 0;
5842 
5843     @UnsupportedAppUsage
noteFullWifiLockAcquiredLocked(int uid)5844     public void noteFullWifiLockAcquiredLocked(int uid) {
5845         final long elapsedRealtime = mClocks.elapsedRealtime();
5846         final long uptime = mClocks.uptimeMillis();
5847         if (mWifiFullLockNesting == 0) {
5848             mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
5849             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
5850                     + Integer.toHexString(mHistoryCur.states));
5851             addHistoryRecordLocked(elapsedRealtime, uptime);
5852         }
5853         mWifiFullLockNesting++;
5854         getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
5855     }
5856 
5857     @UnsupportedAppUsage
noteFullWifiLockReleasedLocked(int uid)5858     public void noteFullWifiLockReleasedLocked(int uid) {
5859         final long elapsedRealtime = mClocks.elapsedRealtime();
5860         final long uptime = mClocks.uptimeMillis();
5861         mWifiFullLockNesting--;
5862         if (mWifiFullLockNesting == 0) {
5863             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
5864             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
5865                     + Integer.toHexString(mHistoryCur.states));
5866             addHistoryRecordLocked(elapsedRealtime, uptime);
5867         }
5868         getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime);
5869     }
5870 
5871     int mWifiScanNesting = 0;
5872 
noteWifiScanStartedLocked(int uid)5873     public void noteWifiScanStartedLocked(int uid) {
5874         final long elapsedRealtime = mClocks.elapsedRealtime();
5875         final long uptime = mClocks.uptimeMillis();
5876         if (mWifiScanNesting == 0) {
5877             mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
5878             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
5879                     + Integer.toHexString(mHistoryCur.states));
5880             addHistoryRecordLocked(elapsedRealtime, uptime);
5881         }
5882         mWifiScanNesting++;
5883         getUidStatsLocked(uid).noteWifiScanStartedLocked(elapsedRealtime);
5884     }
5885 
noteWifiScanStoppedLocked(int uid)5886     public void noteWifiScanStoppedLocked(int uid) {
5887         final long elapsedRealtime = mClocks.elapsedRealtime();
5888         final long uptime = mClocks.uptimeMillis();
5889         mWifiScanNesting--;
5890         if (mWifiScanNesting == 0) {
5891             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
5892             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
5893                     + Integer.toHexString(mHistoryCur.states));
5894             addHistoryRecordLocked(elapsedRealtime, uptime);
5895         }
5896         getUidStatsLocked(uid).noteWifiScanStoppedLocked(elapsedRealtime);
5897     }
5898 
noteWifiBatchedScanStartedLocked(int uid, int csph)5899     public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
5900         uid = mapUid(uid);
5901         final long elapsedRealtime = mClocks.elapsedRealtime();
5902         getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime);
5903     }
5904 
noteWifiBatchedScanStoppedLocked(int uid)5905     public void noteWifiBatchedScanStoppedLocked(int uid) {
5906         uid = mapUid(uid);
5907         final long elapsedRealtime = mClocks.elapsedRealtime();
5908         getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime);
5909     }
5910 
5911     int mWifiMulticastNesting = 0;
5912 
5913     @UnsupportedAppUsage
noteWifiMulticastEnabledLocked(int uid)5914     public void noteWifiMulticastEnabledLocked(int uid) {
5915         uid = mapUid(uid);
5916         final long elapsedRealtime = mClocks.elapsedRealtime();
5917         final long uptime = mClocks.uptimeMillis();
5918         if (mWifiMulticastNesting == 0) {
5919             mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
5920             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
5921                     + Integer.toHexString(mHistoryCur.states));
5922             addHistoryRecordLocked(elapsedRealtime, uptime);
5923 
5924             // Start Wifi Multicast overall timer
5925             if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
5926                 if (DEBUG_HISTORY) Slog.v(TAG, "WiFi Multicast Overall Timer Started");
5927                 mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtime);
5928             }
5929         }
5930         mWifiMulticastNesting++;
5931         getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
5932     }
5933 
5934     @UnsupportedAppUsage
noteWifiMulticastDisabledLocked(int uid)5935     public void noteWifiMulticastDisabledLocked(int uid) {
5936         uid = mapUid(uid);
5937         final long elapsedRealtime = mClocks.elapsedRealtime();
5938         final long uptime = mClocks.uptimeMillis();
5939         mWifiMulticastNesting--;
5940         if (mWifiMulticastNesting == 0) {
5941             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
5942             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
5943                     + Integer.toHexString(mHistoryCur.states));
5944             addHistoryRecordLocked(elapsedRealtime, uptime);
5945 
5946             // Stop Wifi Multicast overall timer
5947             if (mWifiMulticastWakelockTimer.isRunningLocked()) {
5948                 if (DEBUG_HISTORY) Slog.v(TAG, "Multicast Overall Timer Stopped");
5949                 mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtime);
5950             }
5951         }
5952         getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime);
5953     }
5954 
noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws)5955     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
5956         int N = ws.size();
5957         for (int i=0; i<N; i++) {
5958             final int uid = mapUid(ws.get(i));
5959             noteFullWifiLockAcquiredLocked(uid);
5960         }
5961 
5962         final List<WorkChain> workChains = ws.getWorkChains();
5963         if (workChains != null) {
5964             for (int i = 0; i < workChains.size(); ++i) {
5965                 final WorkChain workChain = workChains.get(i);
5966                 final int uid = mapUid(workChain.getAttributionUid());
5967                 noteFullWifiLockAcquiredLocked(uid);
5968             }
5969         }
5970     }
5971 
noteFullWifiLockReleasedFromSourceLocked(WorkSource ws)5972     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
5973         int N = ws.size();
5974         for (int i=0; i<N; i++) {
5975             final int uid = mapUid(ws.get(i));
5976             noteFullWifiLockReleasedLocked(uid);
5977         }
5978 
5979         final List<WorkChain> workChains = ws.getWorkChains();
5980         if (workChains != null) {
5981             for (int i = 0; i < workChains.size(); ++i) {
5982                 final WorkChain workChain = workChains.get(i);
5983                 final int uid = mapUid(workChain.getAttributionUid());
5984                 noteFullWifiLockReleasedLocked(uid);
5985             }
5986         }
5987     }
5988 
noteWifiScanStartedFromSourceLocked(WorkSource ws)5989     public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
5990         int N = ws.size();
5991         for (int i=0; i<N; i++) {
5992             final int uid = mapUid(ws.get(i));
5993             noteWifiScanStartedLocked(uid);
5994         }
5995 
5996         final List<WorkChain> workChains = ws.getWorkChains();
5997         if (workChains != null) {
5998             for (int i = 0; i < workChains.size(); ++i) {
5999                 final WorkChain workChain = workChains.get(i);
6000                 final int uid = mapUid(workChain.getAttributionUid());
6001                 noteWifiScanStartedLocked(uid);
6002             }
6003         }
6004     }
6005 
noteWifiScanStoppedFromSourceLocked(WorkSource ws)6006     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
6007         int N = ws.size();
6008         for (int i=0; i<N; i++) {
6009             final int uid = mapUid(ws.get(i));
6010             noteWifiScanStoppedLocked(uid);
6011         }
6012 
6013         final List<WorkChain> workChains = ws.getWorkChains();
6014         if (workChains != null) {
6015             for (int i = 0; i < workChains.size(); ++i) {
6016                 final WorkChain workChain = workChains.get(i);
6017                 final int uid = mapUid(workChain.getAttributionUid());
6018                 noteWifiScanStoppedLocked(uid);
6019             }
6020         }
6021     }
6022 
noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph)6023     public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
6024         int N = ws.size();
6025         for (int i=0; i<N; i++) {
6026             noteWifiBatchedScanStartedLocked(ws.get(i), csph);
6027         }
6028 
6029         final List<WorkChain> workChains = ws.getWorkChains();
6030         if (workChains != null) {
6031             for (int i = 0; i < workChains.size(); ++i) {
6032                 noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph);
6033             }
6034         }
6035     }
6036 
noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws)6037     public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
6038         int N = ws.size();
6039         for (int i=0; i<N; i++) {
6040             noteWifiBatchedScanStoppedLocked(ws.get(i));
6041         }
6042 
6043         final List<WorkChain> workChains = ws.getWorkChains();
6044         if (workChains != null) {
6045             for (int i = 0; i < workChains.size(); ++i) {
6046                 noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid());
6047             }
6048         }
6049     }
6050 
includeInStringArray(String[] array, String str)6051     private static String[] includeInStringArray(String[] array, String str) {
6052         if (ArrayUtils.indexOf(array, str) >= 0) {
6053             return array;
6054         }
6055         String[] newArray = new String[array.length+1];
6056         System.arraycopy(array, 0, newArray, 0, array.length);
6057         newArray[array.length] = str;
6058         return newArray;
6059     }
6060 
excludeFromStringArray(String[] array, String str)6061     private static String[] excludeFromStringArray(String[] array, String str) {
6062         int index = ArrayUtils.indexOf(array, str);
6063         if (index >= 0) {
6064             String[] newArray = new String[array.length-1];
6065             if (index > 0) {
6066                 System.arraycopy(array, 0, newArray, 0, index);
6067             }
6068             if (index < array.length-1) {
6069                 System.arraycopy(array, index+1, newArray, index, array.length-index-1);
6070             }
6071             return newArray;
6072         }
6073         return array;
6074     }
6075 
noteNetworkInterfaceTypeLocked(String iface, int networkType)6076     public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
6077         if (TextUtils.isEmpty(iface)) return;
6078 
6079         synchronized (mModemNetworkLock) {
6080             if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
6081                 mModemIfaces = includeInStringArray(mModemIfaces, iface);
6082                 if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mModemIfaces);
6083             } else {
6084                 mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
6085                 if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mModemIfaces);
6086             }
6087         }
6088 
6089         synchronized (mWifiNetworkLock) {
6090             if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
6091                 mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
6092                 if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
6093             } else {
6094                 mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
6095                 if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
6096             }
6097         }
6098     }
6099 
getWifiIfaces()6100     public String[] getWifiIfaces() {
6101         synchronized (mWifiNetworkLock) {
6102             return mWifiIfaces;
6103         }
6104     }
6105 
getMobileIfaces()6106     public String[] getMobileIfaces() {
6107         synchronized (mModemNetworkLock) {
6108             return mModemIfaces;
6109         }
6110     }
6111 
6112     @UnsupportedAppUsage
getScreenOnTime(long elapsedRealtimeUs, int which)6113     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
6114         return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6115     }
6116 
getScreenOnCount(int which)6117     @Override public int getScreenOnCount(int which) {
6118         return mScreenOnTimer.getCountLocked(which);
6119     }
6120 
getScreenDozeTime(long elapsedRealtimeUs, int which)6121     @Override public long getScreenDozeTime(long elapsedRealtimeUs, int which) {
6122         return mScreenDozeTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6123     }
6124 
getScreenDozeCount(int which)6125     @Override public int getScreenDozeCount(int which) {
6126         return mScreenDozeTimer.getCountLocked(which);
6127     }
6128 
6129     @UnsupportedAppUsage
getScreenBrightnessTime(int brightnessBin, long elapsedRealtimeUs, int which)6130     @Override public long getScreenBrightnessTime(int brightnessBin,
6131             long elapsedRealtimeUs, int which) {
6132         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
6133                 elapsedRealtimeUs, which);
6134     }
6135 
getScreenBrightnessTimer(int brightnessBin)6136     @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
6137         return mScreenBrightnessTimer[brightnessBin];
6138     }
6139 
getInteractiveTime(long elapsedRealtimeUs, int which)6140     @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
6141         return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6142     }
6143 
getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which)6144     @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
6145         return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6146     }
6147 
getPowerSaveModeEnabledCount(int which)6148     @Override public int getPowerSaveModeEnabledCount(int which) {
6149         return mPowerSaveModeEnabledTimer.getCountLocked(which);
6150     }
6151 
getDeviceIdleModeTime(int mode, long elapsedRealtimeUs, int which)6152     @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
6153             int which) {
6154         switch (mode) {
6155             case DEVICE_IDLE_MODE_LIGHT:
6156                 return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6157             case DEVICE_IDLE_MODE_DEEP:
6158                 return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6159         }
6160         return 0;
6161     }
6162 
getDeviceIdleModeCount(int mode, int which)6163     @Override public int getDeviceIdleModeCount(int mode, int which) {
6164         switch (mode) {
6165             case DEVICE_IDLE_MODE_LIGHT:
6166                 return mDeviceIdleModeLightTimer.getCountLocked(which);
6167             case DEVICE_IDLE_MODE_DEEP:
6168                 return mDeviceIdleModeFullTimer.getCountLocked(which);
6169         }
6170         return 0;
6171     }
6172 
getLongestDeviceIdleModeTime(int mode)6173     @Override public long getLongestDeviceIdleModeTime(int mode) {
6174         switch (mode) {
6175             case DEVICE_IDLE_MODE_LIGHT:
6176                 return mLongestLightIdleTime;
6177             case DEVICE_IDLE_MODE_DEEP:
6178                 return mLongestFullIdleTime;
6179         }
6180         return 0;
6181     }
6182 
getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which)6183     @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
6184         switch (mode) {
6185             case DEVICE_IDLE_MODE_LIGHT:
6186                 return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6187             case DEVICE_IDLE_MODE_DEEP:
6188                 return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6189         }
6190         return 0;
6191     }
6192 
getDeviceIdlingCount(int mode, int which)6193     @Override public int getDeviceIdlingCount(int mode, int which) {
6194         switch (mode) {
6195             case DEVICE_IDLE_MODE_LIGHT:
6196                 return mDeviceLightIdlingTimer.getCountLocked(which);
6197             case DEVICE_IDLE_MODE_DEEP:
6198                 return mDeviceIdlingTimer.getCountLocked(which);
6199         }
6200         return 0;
6201     }
6202 
getNumConnectivityChange(int which)6203     @Override public int getNumConnectivityChange(int which) {
6204         return mNumConnectivityChange;
6205     }
6206 
getGpsSignalQualityTime(int strengthBin, long elapsedRealtimeUs, int which)6207     @Override public long getGpsSignalQualityTime(int strengthBin,
6208         long elapsedRealtimeUs, int which) {
6209         if (strengthBin < 0 || strengthBin >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
6210             return 0;
6211         }
6212         return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
6213             elapsedRealtimeUs, which);
6214     }
6215 
getGpsBatteryDrainMaMs()6216     @Override public long getGpsBatteryDrainMaMs() {
6217         final double opVolt = mPowerProfile.getAveragePower(
6218             PowerProfile.POWER_GPS_OPERATING_VOLTAGE) / 1000.0;
6219         if (opVolt == 0) {
6220             return 0;
6221         }
6222         double energyUsedMaMs = 0.0;
6223         final int which = STATS_SINCE_CHARGED;
6224         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
6225         for(int i=0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
6226             energyUsedMaMs
6227                 += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
6228                 * (getGpsSignalQualityTime(i, rawRealtime, which) / 1000);
6229         }
6230         return (long) energyUsedMaMs;
6231     }
6232 
6233     @UnsupportedAppUsage
getPhoneOnTime(long elapsedRealtimeUs, int which)6234     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
6235         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6236     }
6237 
getPhoneOnCount(int which)6238     @Override public int getPhoneOnCount(int which) {
6239         return mPhoneOnTimer.getCountLocked(which);
6240     }
6241 
6242     @UnsupportedAppUsage
getPhoneSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)6243     @Override public long getPhoneSignalStrengthTime(int strengthBin,
6244             long elapsedRealtimeUs, int which) {
6245         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
6246                 elapsedRealtimeUs, which);
6247     }
6248 
6249     @UnsupportedAppUsage
getPhoneSignalScanningTime( long elapsedRealtimeUs, int which)6250     @Override public long getPhoneSignalScanningTime(
6251             long elapsedRealtimeUs, int which) {
6252         return mPhoneSignalScanningTimer.getTotalTimeLocked(
6253                 elapsedRealtimeUs, which);
6254     }
6255 
getPhoneSignalScanningTimer()6256     @Override public Timer getPhoneSignalScanningTimer() {
6257         return mPhoneSignalScanningTimer;
6258     }
6259 
6260     @UnsupportedAppUsage
getPhoneSignalStrengthCount(int strengthBin, int which)6261     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
6262         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
6263     }
6264 
getPhoneSignalStrengthTimer(int strengthBin)6265     @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
6266         return mPhoneSignalStrengthsTimer[strengthBin];
6267     }
6268 
6269     @UnsupportedAppUsage
getPhoneDataConnectionTime(int dataType, long elapsedRealtimeUs, int which)6270     @Override public long getPhoneDataConnectionTime(int dataType,
6271             long elapsedRealtimeUs, int which) {
6272         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
6273                 elapsedRealtimeUs, which);
6274     }
6275 
6276     @UnsupportedAppUsage
getPhoneDataConnectionCount(int dataType, int which)6277     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
6278         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
6279     }
6280 
getPhoneDataConnectionTimer(int dataType)6281     @Override public Timer getPhoneDataConnectionTimer(int dataType) {
6282         return mPhoneDataConnectionsTimer[dataType];
6283     }
6284 
6285     @UnsupportedAppUsage
getMobileRadioActiveTime(long elapsedRealtimeUs, int which)6286     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
6287         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6288     }
6289 
getMobileRadioActiveCount(int which)6290     @Override public int getMobileRadioActiveCount(int which) {
6291         return mMobileRadioActiveTimer.getCountLocked(which);
6292     }
6293 
getMobileRadioActiveAdjustedTime(int which)6294     @Override public long getMobileRadioActiveAdjustedTime(int which) {
6295         return mMobileRadioActiveAdjustedTime.getCountLocked(which);
6296     }
6297 
getMobileRadioActiveUnknownTime(int which)6298     @Override public long getMobileRadioActiveUnknownTime(int which) {
6299         return mMobileRadioActiveUnknownTime.getCountLocked(which);
6300     }
6301 
getMobileRadioActiveUnknownCount(int which)6302     @Override public int getMobileRadioActiveUnknownCount(int which) {
6303         return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
6304     }
6305 
getWifiMulticastWakelockTime( long elapsedRealtimeUs, int which)6306     @Override public long getWifiMulticastWakelockTime(
6307             long elapsedRealtimeUs, int which) {
6308         return mWifiMulticastWakelockTimer.getTotalTimeLocked(
6309                 elapsedRealtimeUs, which);
6310     }
6311 
getWifiMulticastWakelockCount(int which)6312     @Override public int getWifiMulticastWakelockCount(int which) {
6313         return mWifiMulticastWakelockTimer.getCountLocked(which);
6314     }
6315 
6316     @UnsupportedAppUsage
getWifiOnTime(long elapsedRealtimeUs, int which)6317     @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
6318         return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6319     }
6320 
getWifiActiveTime(long elapsedRealtimeUs, int which)6321     @Override public long getWifiActiveTime(long elapsedRealtimeUs, int which) {
6322         return mWifiActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6323     }
6324 
6325     @UnsupportedAppUsage
getGlobalWifiRunningTime(long elapsedRealtimeUs, int which)6326     @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
6327         return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6328     }
6329 
getWifiStateTime(int wifiState, long elapsedRealtimeUs, int which)6330     @Override public long getWifiStateTime(int wifiState,
6331             long elapsedRealtimeUs, int which) {
6332         return mWifiStateTimer[wifiState].getTotalTimeLocked(
6333                 elapsedRealtimeUs, which);
6334     }
6335 
getWifiStateCount(int wifiState, int which)6336     @Override public int getWifiStateCount(int wifiState, int which) {
6337         return mWifiStateTimer[wifiState].getCountLocked(which);
6338     }
6339 
getWifiStateTimer(int wifiState)6340     @Override public Timer getWifiStateTimer(int wifiState) {
6341         return mWifiStateTimer[wifiState];
6342     }
6343 
getWifiSupplStateTime(int state, long elapsedRealtimeUs, int which)6344     @Override public long getWifiSupplStateTime(int state,
6345             long elapsedRealtimeUs, int which) {
6346         return mWifiSupplStateTimer[state].getTotalTimeLocked(
6347                 elapsedRealtimeUs, which);
6348     }
6349 
getWifiSupplStateCount(int state, int which)6350     @Override public int getWifiSupplStateCount(int state, int which) {
6351         return mWifiSupplStateTimer[state].getCountLocked(which);
6352     }
6353 
getWifiSupplStateTimer(int state)6354     @Override public Timer getWifiSupplStateTimer(int state) {
6355         return mWifiSupplStateTimer[state];
6356     }
6357 
getWifiSignalStrengthTime(int strengthBin, long elapsedRealtimeUs, int which)6358     @Override public long getWifiSignalStrengthTime(int strengthBin,
6359             long elapsedRealtimeUs, int which) {
6360         return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
6361                 elapsedRealtimeUs, which);
6362     }
6363 
getWifiSignalStrengthCount(int strengthBin, int which)6364     @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
6365         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
6366     }
6367 
getWifiSignalStrengthTimer(int strengthBin)6368     @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
6369         return mWifiSignalStrengthsTimer[strengthBin];
6370     }
6371 
6372     @Override
getBluetoothControllerActivity()6373     public ControllerActivityCounter getBluetoothControllerActivity() {
6374         return mBluetoothActivity;
6375     }
6376 
6377     @Override
getWifiControllerActivity()6378     public ControllerActivityCounter getWifiControllerActivity() {
6379         return mWifiActivity;
6380     }
6381 
6382     @Override
getModemControllerActivity()6383     public ControllerActivityCounter getModemControllerActivity() {
6384         return mModemActivity;
6385     }
6386 
6387     @Override
hasBluetoothActivityReporting()6388     public boolean hasBluetoothActivityReporting() {
6389         return mHasBluetoothReporting;
6390     }
6391 
6392     @Override
hasWifiActivityReporting()6393     public boolean hasWifiActivityReporting() {
6394         return mHasWifiReporting;
6395     }
6396 
6397     @Override
hasModemActivityReporting()6398     public boolean hasModemActivityReporting() {
6399         return mHasModemReporting;
6400     }
6401 
6402     @Override
getFlashlightOnTime(long elapsedRealtimeUs, int which)6403     public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
6404         return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6405     }
6406 
6407     @Override
getFlashlightOnCount(int which)6408     public long getFlashlightOnCount(int which) {
6409         return mFlashlightOnTimer.getCountLocked(which);
6410     }
6411 
6412     @Override
getCameraOnTime(long elapsedRealtimeUs, int which)6413     public long getCameraOnTime(long elapsedRealtimeUs, int which) {
6414         return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6415     }
6416 
6417     @Override
getBluetoothScanTime(long elapsedRealtimeUs, int which)6418     public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
6419         return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6420     }
6421 
6422     @Override
6423     @UnsupportedAppUsage
getNetworkActivityBytes(int type, int which)6424     public long getNetworkActivityBytes(int type, int which) {
6425         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
6426             return mNetworkByteActivityCounters[type].getCountLocked(which);
6427         } else {
6428             return 0;
6429         }
6430     }
6431 
6432     @Override
getNetworkActivityPackets(int type, int which)6433     public long getNetworkActivityPackets(int type, int which) {
6434         if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
6435             return mNetworkPacketActivityCounters[type].getCountLocked(which);
6436         } else {
6437             return 0;
6438         }
6439     }
6440 
getStartClockTime()6441     @Override public long getStartClockTime() {
6442         final long currentTime = System.currentTimeMillis();
6443         if ((currentTime > MILLISECONDS_IN_YEAR
6444                 && mStartClockTime < (currentTime - MILLISECONDS_IN_YEAR))
6445                 || (mStartClockTime > currentTime)) {
6446             // If the start clock time has changed by more than a year, then presumably
6447             // the previous time was completely bogus.  So we are going to figure out a
6448             // new time based on how much time has elapsed since we started counting.
6449             recordCurrentTimeChangeLocked(currentTime, mClocks.elapsedRealtime(),
6450                     mClocks.uptimeMillis());
6451             return currentTime - (mClocks.elapsedRealtime() - (mRealtimeStart / 1000));
6452         }
6453         return mStartClockTime;
6454     }
6455 
getStartPlatformVersion()6456     @Override public String getStartPlatformVersion() {
6457         return mStartPlatformVersion;
6458     }
6459 
getEndPlatformVersion()6460     @Override public String getEndPlatformVersion() {
6461         return mEndPlatformVersion;
6462     }
6463 
getParcelVersion()6464     @Override public int getParcelVersion() {
6465         return VERSION;
6466     }
6467 
getIsOnBattery()6468     @Override public boolean getIsOnBattery() {
6469         return mOnBattery;
6470     }
6471 
6472     @UnsupportedAppUsage
getUidStats()6473     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
6474         return mUidStats;
6475     }
6476 
resetIfNotNull(T t, boolean detachIfReset)6477     private static <T extends TimeBaseObs> boolean resetIfNotNull(T t, boolean detachIfReset) {
6478         if (t != null) {
6479             return t.reset(detachIfReset);
6480         }
6481         return true;
6482     }
6483 
resetIfNotNull(T[] t, boolean detachIfReset)6484     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[] t, boolean detachIfReset) {
6485         if (t != null) {
6486             boolean ret = true;
6487             for (int i = 0; i < t.length; i++) {
6488                 ret &= resetIfNotNull(t[i], detachIfReset);
6489             }
6490             return ret;
6491         }
6492         return true;
6493     }
6494 
resetIfNotNull(T[][] t, boolean detachIfReset)6495     private static <T extends TimeBaseObs> boolean resetIfNotNull(T[][] t, boolean detachIfReset) {
6496         if (t != null) {
6497             boolean ret = true;
6498             for (int i = 0; i < t.length; i++) {
6499                 ret &= resetIfNotNull(t[i], detachIfReset);
6500             }
6501             return ret;
6502         }
6503         return true;
6504     }
6505 
resetIfNotNull(ControllerActivityCounterImpl counter, boolean detachIfReset)6506     private static boolean resetIfNotNull(ControllerActivityCounterImpl counter,
6507             boolean detachIfReset) {
6508         if (counter != null) {
6509             counter.reset(detachIfReset);
6510         }
6511         return true;
6512     }
6513 
detachIfNotNull(T t)6514     private static <T extends TimeBaseObs> void detachIfNotNull(T t) {
6515         if (t != null) {
6516             t.detach();
6517         }
6518     }
6519 
detachIfNotNull(T[] t)6520     private static <T extends TimeBaseObs> void detachIfNotNull(T[] t) {
6521         if (t != null) {
6522             for (int i = 0; i < t.length; i++) {
6523                 detachIfNotNull(t[i]);
6524             }
6525         }
6526     }
6527 
detachIfNotNull(T[][] t)6528     private static <T extends TimeBaseObs> void detachIfNotNull(T[][] t) {
6529         if (t != null) {
6530             for (int i = 0; i < t.length; i++) {
6531                 detachIfNotNull(t[i]);
6532             }
6533         }
6534     }
6535 
detachIfNotNull(ControllerActivityCounterImpl counter)6536     private static void detachIfNotNull(ControllerActivityCounterImpl counter) {
6537         if (counter != null) {
6538             counter.detach();
6539         }
6540     }
6541 
6542     /**
6543      * The statistics associated with a particular uid.
6544      */
6545     public static class Uid extends BatteryStats.Uid {
6546         /**
6547          * BatteryStatsImpl that we are associated with.
6548          */
6549         protected BatteryStatsImpl mBsi;
6550 
6551         final int mUid;
6552 
6553         /** TimeBase for when uid is in background and device is on battery. */
6554         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
6555         public final TimeBase mOnBatteryBackgroundTimeBase;
6556         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
6557         public final TimeBase mOnBatteryScreenOffBackgroundTimeBase;
6558 
6559         boolean mWifiRunning;
6560         StopwatchTimer mWifiRunningTimer;
6561 
6562         boolean mFullWifiLockOut;
6563         StopwatchTimer mFullWifiLockTimer;
6564 
6565         boolean mWifiScanStarted;
6566         DualTimer mWifiScanTimer;
6567 
6568         static final int NO_BATCHED_SCAN_STARTED = -1;
6569         int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
6570         StopwatchTimer[] mWifiBatchedScanTimer;
6571 
6572         int mWifiMulticastWakelockCount;
6573         StopwatchTimer mWifiMulticastTimer;
6574 
6575         StopwatchTimer mAudioTurnedOnTimer;
6576         StopwatchTimer mVideoTurnedOnTimer;
6577         StopwatchTimer mFlashlightTurnedOnTimer;
6578         StopwatchTimer mCameraTurnedOnTimer;
6579         StopwatchTimer mForegroundActivityTimer;
6580         StopwatchTimer mForegroundServiceTimer;
6581         /** Total time spent by the uid holding any partial wakelocks. */
6582         DualTimer mAggregatedPartialWakelockTimer;
6583         DualTimer mBluetoothScanTimer;
6584         DualTimer mBluetoothUnoptimizedScanTimer;
6585         Counter mBluetoothScanResultCounter;
6586         Counter mBluetoothScanResultBgCounter;
6587 
6588         int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
6589         StopwatchTimer[] mProcessStateTimer;
6590 
6591         boolean mInForegroundService = false;
6592 
6593         BatchTimer mVibratorOnTimer;
6594 
6595         Counter[] mUserActivityCounters;
6596 
6597         LongSamplingCounter[] mNetworkByteActivityCounters;
6598         LongSamplingCounter[] mNetworkPacketActivityCounters;
6599         LongSamplingCounter mMobileRadioActiveTime;
6600         LongSamplingCounter mMobileRadioActiveCount;
6601 
6602         /**
6603          * How many times this UID woke up the Application Processor due to a Mobile radio packet.
6604          */
6605         private LongSamplingCounter mMobileRadioApWakeupCount;
6606 
6607         /**
6608          * How many times this UID woke up the Application Processor due to a Wifi packet.
6609          */
6610         private LongSamplingCounter mWifiRadioApWakeupCount;
6611 
6612         /**
6613          * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
6614          * Can be null if the UID has had no such activity.
6615          */
6616         private ControllerActivityCounterImpl mWifiControllerActivity;
6617 
6618         /**
6619          * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
6620          * Can be null if the UID has had no such activity.
6621          */
6622         private ControllerActivityCounterImpl mBluetoothControllerActivity;
6623 
6624         /**
6625          * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
6626          * Can be null if the UID has had no such activity.
6627          */
6628         private ControllerActivityCounterImpl mModemControllerActivity;
6629 
6630         /**
6631          * The CPU times we had at the last history details update.
6632          */
6633         long mLastStepUserTime;
6634         long mLastStepSystemTime;
6635         long mCurStepUserTime;
6636         long mCurStepSystemTime;
6637 
6638         LongSamplingCounter mUserCpuTime;
6639         LongSamplingCounter mSystemCpuTime;
6640         LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
6641         LongSamplingCounter mCpuActiveTimeMs;
6642 
6643         LongSamplingCounterArray mCpuFreqTimeMs;
6644         LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
6645         LongSamplingCounterArray mCpuClusterTimesMs;
6646 
6647         LongSamplingCounterArray[] mProcStateTimeMs;
6648         LongSamplingCounterArray[] mProcStateScreenOffTimeMs;
6649 
6650         IntArray mChildUids;
6651 
6652         /**
6653          * The statistics we have collected for this uid's wake locks.
6654          */
6655         final OverflowArrayMap<Wakelock> mWakelockStats;
6656 
6657         /**
6658          * The statistics we have collected for this uid's syncs.
6659          */
6660         final OverflowArrayMap<DualTimer> mSyncStats;
6661 
6662         /**
6663          * The statistics we have collected for this uid's jobs.
6664          */
6665         final OverflowArrayMap<DualTimer> mJobStats;
6666 
6667         /**
6668          * Count of the jobs that have completed and the reasons why they completed.
6669          */
6670         final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
6671 
6672         /**
6673          * Count of app launch events that had associated deferred job counts or info about
6674          * last time a job was run.
6675          */
6676         Counter mJobsDeferredEventCount;
6677 
6678         /**
6679          * Count of deferred jobs that were pending when the app was launched or brought to
6680          * the foreground through a user interaction.
6681          */
6682         Counter mJobsDeferredCount;
6683 
6684         /**
6685          * Sum of time since the last time a job was run for this app before it was launched.
6686          */
6687         LongSamplingCounter mJobsFreshnessTimeMs;
6688 
6689         /**
6690          * Array of counts of instances where the time since the last job was run for the app
6691          * fell within one of the thresholds in {@link #JOB_FRESHNESS_BUCKETS}.
6692          */
6693         final Counter[] mJobsFreshnessBuckets;
6694 
6695         /**
6696          * The statistics we have collected for this uid's sensor activations.
6697          */
6698         final SparseArray<Sensor> mSensorStats = new SparseArray<>();
6699 
6700         /**
6701          * The statistics we have collected for this uid's processes.
6702          */
6703         final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
6704 
6705         /**
6706          * The statistics we have collected for this uid's processes.
6707          */
6708         final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
6709 
6710         /**
6711          * The transient wake stats we have collected for this uid's pids.
6712          */
6713         final SparseArray<Pid> mPids = new SparseArray<>();
6714 
Uid(BatteryStatsImpl bsi, int uid)6715         public Uid(BatteryStatsImpl bsi, int uid) {
6716             mBsi = bsi;
6717             mUid = uid;
6718 
6719             /* Observer list of TimeBase object in Uid is short */
6720             mOnBatteryBackgroundTimeBase = new TimeBase(false);
6721             mOnBatteryBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
6722                     mBsi.mClocks.elapsedRealtime() * 1000);
6723             /* Observer list of TimeBase object in Uid is short */
6724             mOnBatteryScreenOffBackgroundTimeBase = new TimeBase(false);
6725             mOnBatteryScreenOffBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
6726                     mBsi.mClocks.elapsedRealtime() * 1000);
6727 
6728             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6729             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6730             mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6731             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase);
6732 
6733             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
6734                 @Override public Wakelock instantiateObject() {
6735                     return new Wakelock(mBsi, Uid.this);
6736                 }
6737             };
6738             mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
6739                 @Override public DualTimer instantiateObject() {
6740                     return new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
6741                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6742                 }
6743             };
6744             mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
6745                 @Override public DualTimer instantiateObject() {
6746                     return new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
6747                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6748                 }
6749             };
6750 
6751             mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_RUNNING,
6752                     mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
6753             mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, this, FULL_WIFI_LOCK,
6754                     mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
6755             mWifiScanTimer = new DualTimer(mBsi.mClocks, this, WIFI_SCAN,
6756                     mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6757             mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
6758             mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_MULTICAST_ENABLED,
6759                     mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
6760             mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
6761             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase);
6762             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase);
6763             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6764             mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length];
6765         }
6766 
6767         @VisibleForTesting
setProcessStateForTest(int procState)6768         public void setProcessStateForTest(int procState) {
6769             mProcessState = procState;
6770         }
6771 
6772         @Override
getCpuFreqTimes(int which)6773         public long[] getCpuFreqTimes(int which) {
6774             return nullIfAllZeros(mCpuFreqTimeMs, which);
6775         }
6776 
6777         @Override
getScreenOffCpuFreqTimes(int which)6778         public long[] getScreenOffCpuFreqTimes(int which) {
6779             return nullIfAllZeros(mScreenOffCpuFreqTimeMs, which);
6780         }
6781 
6782         @Override
getCpuActiveTime()6783         public long getCpuActiveTime() {
6784             return mCpuActiveTimeMs.getCountLocked(STATS_SINCE_CHARGED);
6785         }
6786 
6787         @Override
getCpuClusterTimes()6788         public long[] getCpuClusterTimes() {
6789             return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
6790         }
6791 
6792 
6793         @Override
getCpuFreqTimes(int which, int procState)6794         public long[] getCpuFreqTimes(int which, int procState) {
6795             if (which < 0 || which >= NUM_PROCESS_STATE) {
6796                 return null;
6797             }
6798             if (mProcStateTimeMs == null) {
6799                 return null;
6800             }
6801             if (!mBsi.mPerProcStateCpuTimesAvailable) {
6802                 mProcStateTimeMs = null;
6803                 return null;
6804             }
6805             return nullIfAllZeros(mProcStateTimeMs[procState], which);
6806         }
6807 
6808         @Override
getScreenOffCpuFreqTimes(int which, int procState)6809         public long[] getScreenOffCpuFreqTimes(int which, int procState) {
6810             if (which < 0 || which >= NUM_PROCESS_STATE) {
6811                 return null;
6812             }
6813             if (mProcStateScreenOffTimeMs == null) {
6814                 return null;
6815             }
6816             if (!mBsi.mPerProcStateCpuTimesAvailable) {
6817                 mProcStateScreenOffTimeMs = null;
6818                 return null;
6819             }
6820             return nullIfAllZeros(mProcStateScreenOffTimeMs[procState], which);
6821         }
6822 
addIsolatedUid(int isolatedUid)6823         public void addIsolatedUid(int isolatedUid) {
6824             if (mChildUids == null) {
6825                 mChildUids = new IntArray();
6826             } else if (mChildUids.indexOf(isolatedUid) >= 0) {
6827                 return;
6828             }
6829             mChildUids.add(isolatedUid);
6830         }
6831 
removeIsolatedUid(int isolatedUid)6832         public void removeIsolatedUid(int isolatedUid) {
6833             final int idx = mChildUids == null ? -1 : mChildUids.indexOf(isolatedUid);
6834             if (idx < 0) {
6835                 return;
6836             }
6837             mChildUids.remove(idx);
6838         }
6839 
nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which)6840         private long[] nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which) {
6841             if (cpuTimesMs == null) {
6842                 return null;
6843             }
6844             final long[] counts = cpuTimesMs.getCountsLocked(which);
6845             if (counts == null) {
6846                 return null;
6847             }
6848             // Return counts only if at least one of the elements is non-zero.
6849             for (int i = counts.length - 1; i >= 0; --i) {
6850                 if (counts[i] != 0) {
6851                     return counts;
6852                 }
6853             }
6854             return null;
6855         }
6856 
addProcStateTimesMs(int procState, long[] cpuTimesMs, boolean onBattery)6857         private void addProcStateTimesMs(int procState, long[] cpuTimesMs, boolean onBattery) {
6858             if (mProcStateTimeMs == null) {
6859                 mProcStateTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
6860             }
6861             if (mProcStateTimeMs[procState] == null
6862                     || mProcStateTimeMs[procState].getSize() != cpuTimesMs.length) {
6863                 detachIfNotNull(mProcStateTimeMs[procState]);
6864                 mProcStateTimeMs[procState] = new LongSamplingCounterArray(
6865                         mBsi.mOnBatteryTimeBase);
6866             }
6867             mProcStateTimeMs[procState].addCountLocked(cpuTimesMs, onBattery);
6868         }
6869 
addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs, boolean onBatteryScreenOff)6870         private void addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs,
6871                 boolean onBatteryScreenOff) {
6872             if (mProcStateScreenOffTimeMs == null) {
6873                 mProcStateScreenOffTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
6874             }
6875             if (mProcStateScreenOffTimeMs[procState] == null
6876                     || mProcStateScreenOffTimeMs[procState].getSize() != cpuTimesMs.length) {
6877                 detachIfNotNull(mProcStateScreenOffTimeMs[procState]);
6878                 mProcStateScreenOffTimeMs[procState] = new LongSamplingCounterArray(
6879                         mBsi.mOnBatteryScreenOffTimeBase);
6880             }
6881             mProcStateScreenOffTimeMs[procState].addCountLocked(cpuTimesMs, onBatteryScreenOff);
6882         }
6883 
6884         @Override
getAggregatedPartialWakelockTimer()6885         public Timer getAggregatedPartialWakelockTimer() {
6886             return mAggregatedPartialWakelockTimer;
6887         }
6888 
6889         @Override
6890         @UnsupportedAppUsage
getWakelockStats()6891         public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
6892             return mWakelockStats.getMap();
6893         }
6894 
6895         @Override
getMulticastWakelockStats()6896         public Timer getMulticastWakelockStats() {
6897             return mWifiMulticastTimer;
6898         }
6899 
6900         @Override
getSyncStats()6901         public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
6902             return mSyncStats.getMap();
6903         }
6904 
6905         @Override
getJobStats()6906         public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
6907             return mJobStats.getMap();
6908         }
6909 
6910         @Override
getJobCompletionStats()6911         public ArrayMap<String, SparseIntArray> getJobCompletionStats() {
6912             return mJobCompletions;
6913         }
6914 
6915         @Override
6916         @UnsupportedAppUsage
getSensorStats()6917         public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
6918             return mSensorStats;
6919         }
6920 
6921         @Override
6922         @UnsupportedAppUsage
getProcessStats()6923         public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
6924             return mProcessStats;
6925         }
6926 
6927         @Override
getPackageStats()6928         public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
6929             return mPackageStats;
6930         }
6931 
6932         @Override
6933         @UnsupportedAppUsage
getUid()6934         public int getUid() {
6935             return mUid;
6936         }
6937 
6938         @Override
noteWifiRunningLocked(long elapsedRealtimeMs)6939         public void noteWifiRunningLocked(long elapsedRealtimeMs) {
6940             if (!mWifiRunning) {
6941                 mWifiRunning = true;
6942                 if (mWifiRunningTimer == null) {
6943                     mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
6944                             mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
6945                 }
6946                 mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
6947             }
6948         }
6949 
6950         @Override
noteWifiStoppedLocked(long elapsedRealtimeMs)6951         public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
6952             if (mWifiRunning) {
6953                 mWifiRunning = false;
6954                 mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
6955             }
6956         }
6957 
6958         @Override
noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs)6959         public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
6960             if (!mFullWifiLockOut) {
6961                 mFullWifiLockOut = true;
6962                 if (mFullWifiLockTimer == null) {
6963                     mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
6964                             mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
6965                 }
6966                 mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
6967             }
6968         }
6969 
6970         @Override
noteFullWifiLockReleasedLocked(long elapsedRealtimeMs)6971         public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
6972             if (mFullWifiLockOut) {
6973                 mFullWifiLockOut = false;
6974                 mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
6975             }
6976         }
6977 
6978         @Override
noteWifiScanStartedLocked(long elapsedRealtimeMs)6979         public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
6980             if (!mWifiScanStarted) {
6981                 mWifiScanStarted = true;
6982                 if (mWifiScanTimer == null) {
6983                     mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
6984                             mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase,
6985                             mOnBatteryBackgroundTimeBase);
6986                 }
6987                 mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
6988             }
6989         }
6990 
6991         @Override
noteWifiScanStoppedLocked(long elapsedRealtimeMs)6992         public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
6993             if (mWifiScanStarted) {
6994                 mWifiScanStarted = false;
6995                 mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
6996             }
6997         }
6998 
6999         @Override
noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs)7000         public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
7001             int bin = 0;
7002             while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
7003                 csph = csph >> 3;
7004                 bin++;
7005             }
7006 
7007             if (mWifiBatchedScanBinStarted == bin) return;
7008 
7009             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
7010                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
7011                         stopRunningLocked(elapsedRealtimeMs);
7012             }
7013             mWifiBatchedScanBinStarted = bin;
7014             if (mWifiBatchedScanTimer[bin] == null) {
7015                 makeWifiBatchedScanBin(bin, null);
7016             }
7017             mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
7018         }
7019 
7020         @Override
noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs)7021         public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
7022             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
7023                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
7024                         stopRunningLocked(elapsedRealtimeMs);
7025                 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
7026             }
7027         }
7028 
7029         @Override
noteWifiMulticastEnabledLocked(long elapsedRealtimeMs)7030         public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
7031             if (mWifiMulticastWakelockCount == 0) {
7032                 if (mWifiMulticastTimer == null) {
7033                     mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7034                             WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
7035                 }
7036                 mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
7037             }
7038             mWifiMulticastWakelockCount++;
7039         }
7040 
7041         @Override
noteWifiMulticastDisabledLocked(long elapsedRealtimeMs)7042         public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
7043             if (mWifiMulticastWakelockCount == 0) {
7044                 return;
7045             }
7046 
7047             mWifiMulticastWakelockCount--;
7048             if (mWifiMulticastWakelockCount == 0) {
7049                 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
7050             }
7051         }
7052 
7053         @Override
getWifiControllerActivity()7054         public ControllerActivityCounter getWifiControllerActivity() {
7055             return mWifiControllerActivity;
7056         }
7057 
7058         @Override
getBluetoothControllerActivity()7059         public ControllerActivityCounter getBluetoothControllerActivity() {
7060             return mBluetoothControllerActivity;
7061         }
7062 
7063         @Override
getModemControllerActivity()7064         public ControllerActivityCounter getModemControllerActivity() {
7065             return mModemControllerActivity;
7066         }
7067 
getOrCreateWifiControllerActivityLocked()7068         public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
7069             if (mWifiControllerActivity == null) {
7070                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7071                         NUM_BT_TX_LEVELS);
7072             }
7073             return mWifiControllerActivity;
7074         }
7075 
getOrCreateBluetoothControllerActivityLocked()7076         public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
7077             if (mBluetoothControllerActivity == null) {
7078                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7079                         NUM_BT_TX_LEVELS);
7080             }
7081             return mBluetoothControllerActivity;
7082         }
7083 
getOrCreateModemControllerActivityLocked()7084         public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
7085             if (mModemControllerActivity == null) {
7086                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7087                         ModemActivityInfo.TX_POWER_LEVELS);
7088             }
7089             return mModemControllerActivity;
7090         }
7091 
createAudioTurnedOnTimerLocked()7092         public StopwatchTimer createAudioTurnedOnTimerLocked() {
7093             if (mAudioTurnedOnTimer == null) {
7094                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
7095                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7096             }
7097             return mAudioTurnedOnTimer;
7098         }
7099 
noteAudioTurnedOnLocked(long elapsedRealtimeMs)7100         public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
7101             createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7102         }
7103 
noteAudioTurnedOffLocked(long elapsedRealtimeMs)7104         public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
7105             if (mAudioTurnedOnTimer != null) {
7106                 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7107             }
7108         }
7109 
noteResetAudioLocked(long elapsedRealtimeMs)7110         public void noteResetAudioLocked(long elapsedRealtimeMs) {
7111             if (mAudioTurnedOnTimer != null) {
7112                 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7113             }
7114         }
7115 
createVideoTurnedOnTimerLocked()7116         public StopwatchTimer createVideoTurnedOnTimerLocked() {
7117             if (mVideoTurnedOnTimer == null) {
7118                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
7119                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7120             }
7121             return mVideoTurnedOnTimer;
7122         }
7123 
noteVideoTurnedOnLocked(long elapsedRealtimeMs)7124         public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
7125             createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7126         }
7127 
noteVideoTurnedOffLocked(long elapsedRealtimeMs)7128         public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
7129             if (mVideoTurnedOnTimer != null) {
7130                 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7131             }
7132         }
7133 
noteResetVideoLocked(long elapsedRealtimeMs)7134         public void noteResetVideoLocked(long elapsedRealtimeMs) {
7135             if (mVideoTurnedOnTimer != null) {
7136                 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7137             }
7138         }
7139 
createFlashlightTurnedOnTimerLocked()7140         public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
7141             if (mFlashlightTurnedOnTimer == null) {
7142                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7143                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7144             }
7145             return mFlashlightTurnedOnTimer;
7146         }
7147 
noteFlashlightTurnedOnLocked(long elapsedRealtimeMs)7148         public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
7149             createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7150         }
7151 
noteFlashlightTurnedOffLocked(long elapsedRealtimeMs)7152         public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
7153             if (mFlashlightTurnedOnTimer != null) {
7154                 mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7155             }
7156         }
7157 
noteResetFlashlightLocked(long elapsedRealtimeMs)7158         public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
7159             if (mFlashlightTurnedOnTimer != null) {
7160                 mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7161             }
7162         }
7163 
createCameraTurnedOnTimerLocked()7164         public StopwatchTimer createCameraTurnedOnTimerLocked() {
7165             if (mCameraTurnedOnTimer == null) {
7166                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
7167                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7168             }
7169             return mCameraTurnedOnTimer;
7170         }
7171 
noteCameraTurnedOnLocked(long elapsedRealtimeMs)7172         public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
7173             createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7174         }
7175 
noteCameraTurnedOffLocked(long elapsedRealtimeMs)7176         public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
7177             if (mCameraTurnedOnTimer != null) {
7178                 mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7179             }
7180         }
7181 
noteResetCameraLocked(long elapsedRealtimeMs)7182         public void noteResetCameraLocked(long elapsedRealtimeMs) {
7183             if (mCameraTurnedOnTimer != null) {
7184                 mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7185             }
7186         }
7187 
createForegroundActivityTimerLocked()7188         public StopwatchTimer createForegroundActivityTimerLocked() {
7189             if (mForegroundActivityTimer == null) {
7190                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7191                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
7192             }
7193             return mForegroundActivityTimer;
7194         }
7195 
createForegroundServiceTimerLocked()7196         public StopwatchTimer createForegroundServiceTimerLocked() {
7197             if (mForegroundServiceTimer == null) {
7198                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7199                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase);
7200             }
7201             return mForegroundServiceTimer;
7202         }
7203 
createAggregatedPartialWakelockTimerLocked()7204         public DualTimer createAggregatedPartialWakelockTimerLocked() {
7205             if (mAggregatedPartialWakelockTimer == null) {
7206                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
7207                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
7208                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase);
7209             }
7210             return mAggregatedPartialWakelockTimer;
7211         }
7212 
createBluetoothScanTimerLocked()7213         public DualTimer createBluetoothScanTimerLocked() {
7214             if (mBluetoothScanTimer == null) {
7215                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
7216                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
7217                         mOnBatteryBackgroundTimeBase);
7218             }
7219             return mBluetoothScanTimer;
7220         }
7221 
createBluetoothUnoptimizedScanTimerLocked()7222         public DualTimer createBluetoothUnoptimizedScanTimerLocked() {
7223             if (mBluetoothUnoptimizedScanTimer == null) {
7224                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
7225                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
7226                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
7227             }
7228             return mBluetoothUnoptimizedScanTimer;
7229         }
7230 
noteBluetoothScanStartedLocked(long elapsedRealtimeMs, boolean isUnoptimized)7231         public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs,
7232                 boolean isUnoptimized) {
7233             createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
7234             if (isUnoptimized) {
7235                 createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
7236             }
7237         }
7238 
noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized)7239         public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
7240             if (mBluetoothScanTimer != null) {
7241                 mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
7242             }
7243             if (isUnoptimized && mBluetoothUnoptimizedScanTimer != null) {
7244                 mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs);
7245             }
7246         }
7247 
noteResetBluetoothScanLocked(long elapsedRealtimeMs)7248         public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
7249             if (mBluetoothScanTimer != null) {
7250                 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
7251             }
7252             if (mBluetoothUnoptimizedScanTimer != null) {
7253                 mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
7254             }
7255         }
7256 
createBluetoothScanResultCounterLocked()7257         public Counter createBluetoothScanResultCounterLocked() {
7258             if (mBluetoothScanResultCounter == null) {
7259                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase);
7260             }
7261             return mBluetoothScanResultCounter;
7262         }
7263 
createBluetoothScanResultBgCounterLocked()7264         public Counter createBluetoothScanResultBgCounterLocked() {
7265             if (mBluetoothScanResultBgCounter == null) {
7266                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase);
7267             }
7268             return mBluetoothScanResultBgCounter;
7269         }
7270 
noteBluetoothScanResultsLocked(int numNewResults)7271         public void noteBluetoothScanResultsLocked(int numNewResults) {
7272             createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
7273             // Uses background timebase, so the count will only be incremented if uid in background.
7274             createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults);
7275         }
7276 
7277         @Override
noteActivityResumedLocked(long elapsedRealtimeMs)7278         public void noteActivityResumedLocked(long elapsedRealtimeMs) {
7279             // We always start, since we want multiple foreground PIDs to nest
7280             createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
7281         }
7282 
7283         @Override
noteActivityPausedLocked(long elapsedRealtimeMs)7284         public void noteActivityPausedLocked(long elapsedRealtimeMs) {
7285             if (mForegroundActivityTimer != null) {
7286                 mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
7287             }
7288         }
7289 
noteForegroundServiceResumedLocked(long elapsedRealtimeMs)7290         public void noteForegroundServiceResumedLocked(long elapsedRealtimeMs) {
7291             createForegroundServiceTimerLocked().startRunningLocked(elapsedRealtimeMs);
7292         }
7293 
noteForegroundServicePausedLocked(long elapsedRealtimeMs)7294         public void noteForegroundServicePausedLocked(long elapsedRealtimeMs) {
7295             if (mForegroundServiceTimer != null) {
7296                 mForegroundServiceTimer.stopRunningLocked(elapsedRealtimeMs);
7297             }
7298         }
7299 
createVibratorOnTimerLocked()7300         public BatchTimer createVibratorOnTimerLocked() {
7301             if (mVibratorOnTimer == null) {
7302                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
7303                         mBsi.mOnBatteryTimeBase);
7304             }
7305             return mVibratorOnTimer;
7306         }
7307 
noteVibratorOnLocked(long durationMillis)7308         public void noteVibratorOnLocked(long durationMillis) {
7309             createVibratorOnTimerLocked().addDuration(mBsi, durationMillis);
7310         }
7311 
noteVibratorOffLocked()7312         public void noteVibratorOffLocked() {
7313             if (mVibratorOnTimer != null) {
7314                 mVibratorOnTimer.abortLastDuration(mBsi);
7315             }
7316         }
7317 
7318         @Override
7319         @UnsupportedAppUsage
getWifiRunningTime(long elapsedRealtimeUs, int which)7320         public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
7321             if (mWifiRunningTimer == null) {
7322                 return 0;
7323             }
7324             return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7325         }
7326 
7327         @Override
getFullWifiLockTime(long elapsedRealtimeUs, int which)7328         public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
7329             if (mFullWifiLockTimer == null) {
7330                 return 0;
7331             }
7332             return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7333         }
7334 
7335         @Override
7336         @UnsupportedAppUsage
getWifiScanTime(long elapsedRealtimeUs, int which)7337         public long getWifiScanTime(long elapsedRealtimeUs, int which) {
7338             if (mWifiScanTimer == null) {
7339                 return 0;
7340             }
7341             return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7342         }
7343 
7344         @Override
getWifiScanCount(int which)7345         public int getWifiScanCount(int which) {
7346             if (mWifiScanTimer == null) {
7347                 return 0;
7348             }
7349             return mWifiScanTimer.getCountLocked(which);
7350         }
7351 
7352         @Override
getWifiScanTimer()7353         public Timer getWifiScanTimer() {
7354             return mWifiScanTimer;
7355         }
7356 
7357         @Override
getWifiScanBackgroundCount(int which)7358         public int getWifiScanBackgroundCount(int which) {
7359             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
7360                 return 0;
7361             }
7362             return mWifiScanTimer.getSubTimer().getCountLocked(which);
7363         }
7364 
7365         @Override
getWifiScanActualTime(final long elapsedRealtimeUs)7366         public long getWifiScanActualTime(final long elapsedRealtimeUs) {
7367             if (mWifiScanTimer == null) {
7368                 return 0;
7369             }
7370             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
7371             return mWifiScanTimer.getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
7372         }
7373 
7374         @Override
getWifiScanBackgroundTime(final long elapsedRealtimeUs)7375         public long getWifiScanBackgroundTime(final long elapsedRealtimeUs) {
7376             if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
7377                 return 0;
7378             }
7379             final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
7380             return mWifiScanTimer.getSubTimer().getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
7381         }
7382 
7383         @Override
getWifiScanBackgroundTimer()7384         public Timer getWifiScanBackgroundTimer() {
7385             if (mWifiScanTimer == null) {
7386                 return null;
7387             }
7388             return mWifiScanTimer.getSubTimer();
7389         }
7390 
7391         @Override
getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which)7392         public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
7393             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
7394             if (mWifiBatchedScanTimer[csphBin] == null) {
7395                 return 0;
7396             }
7397             return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
7398         }
7399 
7400         @Override
getWifiBatchedScanCount(int csphBin, int which)7401         public int getWifiBatchedScanCount(int csphBin, int which) {
7402             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
7403             if (mWifiBatchedScanTimer[csphBin] == null) {
7404                 return 0;
7405             }
7406             return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
7407         }
7408 
7409         @Override
getWifiMulticastTime(long elapsedRealtimeUs, int which)7410         public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
7411             if (mWifiMulticastTimer == null) {
7412                 return 0;
7413             }
7414             return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7415         }
7416 
7417         @Override
getAudioTurnedOnTimer()7418         public Timer getAudioTurnedOnTimer() {
7419             return mAudioTurnedOnTimer;
7420         }
7421 
7422         @Override
getVideoTurnedOnTimer()7423         public Timer getVideoTurnedOnTimer() {
7424             return mVideoTurnedOnTimer;
7425         }
7426 
7427         @Override
getFlashlightTurnedOnTimer()7428         public Timer getFlashlightTurnedOnTimer() {
7429             return mFlashlightTurnedOnTimer;
7430         }
7431 
7432         @Override
getCameraTurnedOnTimer()7433         public Timer getCameraTurnedOnTimer() {
7434             return mCameraTurnedOnTimer;
7435         }
7436 
7437         @Override
getForegroundActivityTimer()7438         public Timer getForegroundActivityTimer() {
7439             return mForegroundActivityTimer;
7440         }
7441 
7442         @Override
getForegroundServiceTimer()7443         public Timer getForegroundServiceTimer() {
7444             return mForegroundServiceTimer;
7445         }
7446 
7447         @Override
getBluetoothScanTimer()7448         public Timer getBluetoothScanTimer() {
7449             return mBluetoothScanTimer;
7450         }
7451 
7452         @Override
getBluetoothScanBackgroundTimer()7453         public Timer getBluetoothScanBackgroundTimer() {
7454             if (mBluetoothScanTimer == null) {
7455                 return null;
7456             }
7457             return mBluetoothScanTimer.getSubTimer();
7458         }
7459 
7460         @Override
getBluetoothUnoptimizedScanTimer()7461         public Timer getBluetoothUnoptimizedScanTimer() {
7462             return mBluetoothUnoptimizedScanTimer;
7463         }
7464 
7465         @Override
getBluetoothUnoptimizedScanBackgroundTimer()7466         public Timer getBluetoothUnoptimizedScanBackgroundTimer() {
7467             if (mBluetoothUnoptimizedScanTimer == null) {
7468                 return null;
7469             }
7470             return mBluetoothUnoptimizedScanTimer.getSubTimer();
7471         }
7472 
7473         @Override
getBluetoothScanResultCounter()7474         public Counter getBluetoothScanResultCounter() {
7475             return mBluetoothScanResultCounter;
7476         }
7477 
7478         @Override
getBluetoothScanResultBgCounter()7479         public Counter getBluetoothScanResultBgCounter() {
7480             return mBluetoothScanResultBgCounter;
7481         }
7482 
makeProcessState(int i, Parcel in)7483         void makeProcessState(int i, Parcel in) {
7484             if (i < 0 || i >= NUM_PROCESS_STATE) return;
7485 
7486             detachIfNotNull(mProcessStateTimer[i]);
7487             if (in == null) {
7488                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
7489                         mBsi.mOnBatteryTimeBase);
7490             } else {
7491                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
7492                         mBsi.mOnBatteryTimeBase, in);
7493             }
7494         }
7495 
7496         @Override
getProcessStateTime(int state, long elapsedRealtimeUs, int which)7497         public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
7498             if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
7499             if (mProcessStateTimer[state] == null) {
7500                 return 0;
7501             }
7502             return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
7503         }
7504 
7505         @Override
getProcessStateTimer(int state)7506         public Timer getProcessStateTimer(int state) {
7507             if (state < 0 || state >= NUM_PROCESS_STATE) return null;
7508             return mProcessStateTimer[state];
7509         }
7510 
7511         @Override
getVibratorOnTimer()7512         public Timer getVibratorOnTimer() {
7513             return mVibratorOnTimer;
7514         }
7515 
7516         @Override
noteUserActivityLocked(int type)7517         public void noteUserActivityLocked(int type) {
7518             if (mUserActivityCounters == null) {
7519                 initUserActivityLocked();
7520             }
7521             if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
7522                 mUserActivityCounters[type].stepAtomic();
7523             } else {
7524                 Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
7525                         new Throwable());
7526             }
7527         }
7528 
7529         @Override
hasUserActivity()7530         public boolean hasUserActivity() {
7531             return mUserActivityCounters != null;
7532         }
7533 
7534         @Override
getUserActivityCount(int type, int which)7535         public int getUserActivityCount(int type, int which) {
7536             if (mUserActivityCounters == null) {
7537                 return 0;
7538             }
7539             return mUserActivityCounters[type].getCountLocked(which);
7540         }
7541 
makeWifiBatchedScanBin(int i, Parcel in)7542         void makeWifiBatchedScanBin(int i, Parcel in) {
7543             if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
7544 
7545             ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
7546             if (collected == null) {
7547                 collected = new ArrayList<StopwatchTimer>();
7548                 mBsi.mWifiBatchedScanTimers.put(i, collected);
7549             }
7550             detachIfNotNull(mWifiBatchedScanTimer[i]);
7551             if (in == null) {
7552                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
7553                         collected, mBsi.mOnBatteryTimeBase);
7554             } else {
7555                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
7556                         collected, mBsi.mOnBatteryTimeBase, in);
7557             }
7558         }
7559 
7560 
initUserActivityLocked()7561         void initUserActivityLocked() {
7562             detachIfNotNull(mUserActivityCounters);
7563             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
7564             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
7565                 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
7566             }
7567         }
7568 
noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets)7569         void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
7570             if (mNetworkByteActivityCounters == null) {
7571                 initNetworkActivityLocked();
7572             }
7573             if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
7574                 mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
7575                 mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
7576             } else {
7577                 Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
7578                         new Throwable());
7579             }
7580         }
7581 
noteMobileRadioActiveTimeLocked(long batteryUptime)7582         void noteMobileRadioActiveTimeLocked(long batteryUptime) {
7583             if (mNetworkByteActivityCounters == null) {
7584                 initNetworkActivityLocked();
7585             }
7586             mMobileRadioActiveTime.addCountLocked(batteryUptime);
7587             mMobileRadioActiveCount.addCountLocked(1);
7588         }
7589 
7590         @Override
hasNetworkActivity()7591         public boolean hasNetworkActivity() {
7592             return mNetworkByteActivityCounters != null;
7593         }
7594 
7595         @Override
getNetworkActivityBytes(int type, int which)7596         public long getNetworkActivityBytes(int type, int which) {
7597             if (mNetworkByteActivityCounters != null && type >= 0
7598                     && type < mNetworkByteActivityCounters.length) {
7599                 return mNetworkByteActivityCounters[type].getCountLocked(which);
7600             } else {
7601                 return 0;
7602             }
7603         }
7604 
7605         @Override
getNetworkActivityPackets(int type, int which)7606         public long getNetworkActivityPackets(int type, int which) {
7607             if (mNetworkPacketActivityCounters != null && type >= 0
7608                     && type < mNetworkPacketActivityCounters.length) {
7609                 return mNetworkPacketActivityCounters[type].getCountLocked(which);
7610             } else {
7611                 return 0;
7612             }
7613         }
7614 
7615         @Override
getMobileRadioActiveTime(int which)7616         public long getMobileRadioActiveTime(int which) {
7617             return mMobileRadioActiveTime != null
7618                     ? mMobileRadioActiveTime.getCountLocked(which) : 0;
7619         }
7620 
7621         @Override
getMobileRadioActiveCount(int which)7622         public int getMobileRadioActiveCount(int which) {
7623             return mMobileRadioActiveCount != null
7624                     ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
7625         }
7626 
7627         @Override
getUserCpuTimeUs(int which)7628         public long getUserCpuTimeUs(int which) {
7629             return mUserCpuTime.getCountLocked(which);
7630         }
7631 
7632         @Override
getSystemCpuTimeUs(int which)7633         public long getSystemCpuTimeUs(int which) {
7634             return mSystemCpuTime.getCountLocked(which);
7635         }
7636 
7637         @Override
getTimeAtCpuSpeed(int cluster, int step, int which)7638         public long getTimeAtCpuSpeed(int cluster, int step, int which) {
7639             if (mCpuClusterSpeedTimesUs != null) {
7640                 if (cluster >= 0 && cluster < mCpuClusterSpeedTimesUs.length) {
7641                     final LongSamplingCounter[] cpuSpeedTimesUs = mCpuClusterSpeedTimesUs[cluster];
7642                     if (cpuSpeedTimesUs != null) {
7643                         if (step >= 0 && step < cpuSpeedTimesUs.length) {
7644                             final LongSamplingCounter c = cpuSpeedTimesUs[step];
7645                             if (c != null) {
7646                                 return c.getCountLocked(which);
7647                             }
7648                         }
7649                     }
7650                 }
7651             }
7652             return 0;
7653         }
7654 
noteMobileRadioApWakeupLocked()7655         public void noteMobileRadioApWakeupLocked() {
7656             if (mMobileRadioApWakeupCount == null) {
7657                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7658             }
7659             mMobileRadioApWakeupCount.addCountLocked(1);
7660         }
7661 
7662         @Override
getMobileRadioApWakeupCount(int which)7663         public long getMobileRadioApWakeupCount(int which) {
7664             if (mMobileRadioApWakeupCount != null) {
7665                 return mMobileRadioApWakeupCount.getCountLocked(which);
7666             }
7667             return 0;
7668         }
7669 
noteWifiRadioApWakeupLocked()7670         public void noteWifiRadioApWakeupLocked() {
7671             if (mWifiRadioApWakeupCount == null) {
7672                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7673             }
7674             mWifiRadioApWakeupCount.addCountLocked(1);
7675         }
7676 
7677         @Override
getWifiRadioApWakeupCount(int which)7678         public long getWifiRadioApWakeupCount(int which) {
7679             if (mWifiRadioApWakeupCount != null) {
7680                 return mWifiRadioApWakeupCount.getCountLocked(which);
7681             }
7682             return 0;
7683         }
7684 
7685         @Override
getDeferredJobsCheckinLineLocked(StringBuilder sb, int which)7686         public void getDeferredJobsCheckinLineLocked(StringBuilder sb, int which) {
7687             sb.setLength(0);
7688             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
7689             if (deferredEventCount == 0) {
7690                 return;
7691             }
7692             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
7693             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
7694             sb.append(deferredEventCount); sb.append(',');
7695             sb.append(deferredCount); sb.append(',');
7696             sb.append(totalLatency);
7697             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
7698                 if (mJobsFreshnessBuckets[i] == null) {
7699                     sb.append(",0");
7700                 } else {
7701                     sb.append(",");
7702                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
7703                 }
7704             }
7705         }
7706 
7707         @Override
getDeferredJobsLineLocked(StringBuilder sb, int which)7708         public void getDeferredJobsLineLocked(StringBuilder sb, int which) {
7709             sb.setLength(0);
7710             final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
7711             if (deferredEventCount == 0) {
7712                 return;
7713             }
7714             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
7715             final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
7716             sb.append("times="); sb.append(deferredEventCount); sb.append(", ");
7717             sb.append("count="); sb.append(deferredCount); sb.append(", ");
7718             sb.append("totalLatencyMs="); sb.append(totalLatency); sb.append(", ");
7719             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
7720                 sb.append("<"); sb.append(JOB_FRESHNESS_BUCKETS[i]); sb.append("ms=");
7721                 if (mJobsFreshnessBuckets[i] == null) {
7722                     sb.append("0");
7723                 } else {
7724                     sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
7725                 }
7726                 sb.append(" ");
7727             }
7728         }
7729 
initNetworkActivityLocked()7730         void initNetworkActivityLocked() {
7731             detachIfNotNull(mNetworkByteActivityCounters);
7732             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
7733             detachIfNotNull(mNetworkPacketActivityCounters);
7734             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
7735             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7736                 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7737                 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7738             }
7739             detachIfNotNull(mMobileRadioActiveTime);
7740             mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7741             detachIfNotNull(mMobileRadioActiveCount);
7742             mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7743         }
7744 
7745         /**
7746          * Clear all stats for this uid.  Returns true if the uid is completely
7747          * inactive so can be dropped.
7748          */
7749         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
reset(long uptime, long realtime)7750         public boolean reset(long uptime, long realtime) {
7751             boolean active = false;
7752 
7753             mOnBatteryBackgroundTimeBase.init(uptime, realtime);
7754             mOnBatteryScreenOffBackgroundTimeBase.init(uptime, realtime);
7755 
7756             if (mWifiRunningTimer != null) {
7757                 active |= !mWifiRunningTimer.reset(false);
7758                 active |= mWifiRunning;
7759             }
7760             if (mFullWifiLockTimer != null) {
7761                 active |= !mFullWifiLockTimer.reset(false);
7762                 active |= mFullWifiLockOut;
7763             }
7764             if (mWifiScanTimer != null) {
7765                 active |= !mWifiScanTimer.reset(false);
7766                 active |= mWifiScanStarted;
7767             }
7768             if (mWifiBatchedScanTimer != null) {
7769                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
7770                     if (mWifiBatchedScanTimer[i] != null) {
7771                         active |= !mWifiBatchedScanTimer[i].reset(false);
7772                     }
7773                 }
7774                 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
7775             }
7776             if (mWifiMulticastTimer != null) {
7777                 active |= !mWifiMulticastTimer.reset(false);
7778                 active |= (mWifiMulticastWakelockCount > 0);
7779             }
7780 
7781             active |= !resetIfNotNull(mAudioTurnedOnTimer, false);
7782             active |= !resetIfNotNull(mVideoTurnedOnTimer, false);
7783             active |= !resetIfNotNull(mFlashlightTurnedOnTimer, false);
7784             active |= !resetIfNotNull(mCameraTurnedOnTimer, false);
7785             active |= !resetIfNotNull(mForegroundActivityTimer, false);
7786             active |= !resetIfNotNull(mForegroundServiceTimer, false);
7787             active |= !resetIfNotNull(mAggregatedPartialWakelockTimer, false);
7788             active |= !resetIfNotNull(mBluetoothScanTimer, false);
7789             active |= !resetIfNotNull(mBluetoothUnoptimizedScanTimer, false);
7790 
7791             resetIfNotNull(mBluetoothScanResultCounter, false);
7792             resetIfNotNull(mBluetoothScanResultBgCounter, false);
7793 
7794             if (mProcessStateTimer != null) {
7795                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
7796                     active |= !resetIfNotNull(mProcessStateTimer[i], false);
7797                 }
7798                 active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
7799             }
7800             if (mVibratorOnTimer != null) {
7801                 if (mVibratorOnTimer.reset(false)) {
7802                     mVibratorOnTimer.detach();
7803                     mVibratorOnTimer = null;
7804                 } else {
7805                     active = true;
7806                 }
7807             }
7808 
7809             resetIfNotNull(mUserActivityCounters, false);
7810 
7811             resetIfNotNull(mNetworkByteActivityCounters, false);
7812             resetIfNotNull(mNetworkPacketActivityCounters, false);
7813             resetIfNotNull(mMobileRadioActiveTime, false);
7814             resetIfNotNull(mMobileRadioActiveCount, false);
7815 
7816             resetIfNotNull(mWifiControllerActivity, false);
7817             resetIfNotNull(mBluetoothControllerActivity, false);
7818             resetIfNotNull(mModemControllerActivity, false);
7819 
7820             resetIfNotNull(mUserCpuTime, false);
7821             resetIfNotNull(mSystemCpuTime, false);
7822 
7823             resetIfNotNull(mCpuClusterSpeedTimesUs, false);
7824 
7825             resetIfNotNull(mCpuFreqTimeMs, false);
7826             resetIfNotNull(mScreenOffCpuFreqTimeMs, false);
7827 
7828 
7829             resetIfNotNull(mCpuActiveTimeMs, false);
7830             resetIfNotNull(mCpuClusterTimesMs, false);
7831 
7832             resetIfNotNull(mProcStateTimeMs, false);
7833 
7834             resetIfNotNull(mProcStateScreenOffTimeMs, false);
7835 
7836             resetIfNotNull(mMobileRadioApWakeupCount, false);
7837 
7838             resetIfNotNull(mWifiRadioApWakeupCount, false);
7839 
7840 
7841             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
7842             for (int iw=wakeStats.size()-1; iw>=0; iw--) {
7843                 Wakelock wl = wakeStats.valueAt(iw);
7844                 if (wl.reset()) {
7845                     wakeStats.removeAt(iw);
7846                 } else {
7847                     active = true;
7848                 }
7849             }
7850             mWakelockStats.cleanup();
7851             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
7852             for (int is=syncStats.size()-1; is>=0; is--) {
7853                 DualTimer timer = syncStats.valueAt(is);
7854                 if (timer.reset(false)) {
7855                     syncStats.removeAt(is);
7856                     timer.detach();
7857                 } else {
7858                     active = true;
7859                 }
7860             }
7861             mSyncStats.cleanup();
7862             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
7863             for (int ij=jobStats.size()-1; ij>=0; ij--) {
7864                 DualTimer timer = jobStats.valueAt(ij);
7865                 if (timer.reset(false)) {
7866                     jobStats.removeAt(ij);
7867                     timer.detach();
7868                 } else {
7869                     active = true;
7870                 }
7871             }
7872             mJobStats.cleanup();
7873             mJobCompletions.clear();
7874 
7875             resetIfNotNull(mJobsDeferredEventCount, false);
7876             resetIfNotNull(mJobsDeferredCount, false);
7877             resetIfNotNull(mJobsFreshnessTimeMs, false);
7878             resetIfNotNull(mJobsFreshnessBuckets, false);
7879 
7880             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
7881                 Sensor s = mSensorStats.valueAt(ise);
7882                 if (s.reset()) {
7883                     mSensorStats.removeAt(ise);
7884                 } else {
7885                     active = true;
7886                 }
7887             }
7888 
7889             for (int ip = mProcessStats.size() - 1; ip >= 0; ip--) {
7890                 Proc proc = mProcessStats.valueAt(ip);
7891                 proc.detach();
7892             }
7893             mProcessStats.clear();
7894 
7895             for (int i = mPids.size() - 1; i >= 0; i--) {
7896                 Pid pid = mPids.valueAt(i);
7897                 if (pid.mWakeNesting > 0) {
7898                     active = true;
7899                 } else {
7900                     mPids.removeAt(i);
7901                 }
7902             }
7903 
7904 
7905             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
7906                 Pkg p = mPackageStats.valueAt(i);
7907                 p.detach();
7908             }
7909             mPackageStats.clear();
7910 
7911             mLastStepUserTime = mLastStepSystemTime = 0;
7912             mCurStepUserTime = mCurStepSystemTime = 0;
7913 
7914             return !active;
7915         }
7916 
7917         /**
7918          * This method MUST be called whenever the Uid object is destructed, otherwise it is a
7919          * memory leak in {@link TimeBase#mObservers} list.
7920          * Typically the Uid object is destructed when it is removed from
7921          * {@link BatteryStatsImpl#mUidStats}
7922          */
detachFromTimeBase()7923         void detachFromTimeBase() {
7924             detachIfNotNull(mWifiRunningTimer);
7925             detachIfNotNull(mFullWifiLockTimer);
7926             detachIfNotNull(mWifiScanTimer);
7927             detachIfNotNull(mWifiBatchedScanTimer);
7928             detachIfNotNull(mWifiMulticastTimer);
7929             detachIfNotNull(mAudioTurnedOnTimer);
7930             detachIfNotNull(mVideoTurnedOnTimer);
7931             detachIfNotNull(mFlashlightTurnedOnTimer);
7932 
7933             detachIfNotNull(mCameraTurnedOnTimer);
7934             detachIfNotNull(mForegroundActivityTimer);
7935             detachIfNotNull(mForegroundServiceTimer);
7936 
7937             detachIfNotNull(mAggregatedPartialWakelockTimer);
7938 
7939             detachIfNotNull(mBluetoothScanTimer);
7940             detachIfNotNull(mBluetoothUnoptimizedScanTimer);
7941             detachIfNotNull(mBluetoothScanResultCounter);
7942             detachIfNotNull(mBluetoothScanResultBgCounter);
7943 
7944             detachIfNotNull(mProcessStateTimer);
7945 
7946             detachIfNotNull(mVibratorOnTimer);
7947 
7948             detachIfNotNull(mUserActivityCounters);
7949 
7950             detachIfNotNull(mNetworkByteActivityCounters);
7951             detachIfNotNull(mNetworkPacketActivityCounters);
7952 
7953             detachIfNotNull(mMobileRadioActiveTime);
7954             detachIfNotNull(mMobileRadioActiveCount);
7955             detachIfNotNull(mMobileRadioApWakeupCount);
7956             detachIfNotNull(mWifiRadioApWakeupCount);
7957 
7958             detachIfNotNull(mWifiControllerActivity);
7959             detachIfNotNull(mBluetoothControllerActivity);
7960             detachIfNotNull(mModemControllerActivity);
7961 
7962             mPids.clear();
7963 
7964             detachIfNotNull(mUserCpuTime);
7965             detachIfNotNull(mSystemCpuTime);
7966 
7967             detachIfNotNull(mCpuClusterSpeedTimesUs);
7968 
7969             detachIfNotNull(mCpuActiveTimeMs);
7970             detachIfNotNull(mCpuFreqTimeMs);
7971 
7972             detachIfNotNull(mScreenOffCpuFreqTimeMs);
7973 
7974             detachIfNotNull(mCpuClusterTimesMs);
7975 
7976             detachIfNotNull(mProcStateTimeMs);
7977 
7978             detachIfNotNull(mProcStateScreenOffTimeMs);
7979 
7980             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
7981             for (int iw = wakeStats.size() - 1; iw >= 0; iw--) {
7982                 Wakelock wl = wakeStats.valueAt(iw);
7983                 wl.detachFromTimeBase();
7984             }
7985             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
7986             for (int is = syncStats.size() - 1; is >= 0; is--) {
7987                 DualTimer timer = syncStats.valueAt(is);
7988                 detachIfNotNull(timer);
7989             }
7990             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
7991             for (int ij = jobStats.size() - 1; ij >= 0; ij--) {
7992                 DualTimer timer = jobStats.valueAt(ij);
7993                 detachIfNotNull(timer);
7994             }
7995 
7996             detachIfNotNull(mJobsDeferredEventCount);
7997             detachIfNotNull(mJobsDeferredCount);
7998             detachIfNotNull(mJobsFreshnessTimeMs);
7999             detachIfNotNull(mJobsFreshnessBuckets);
8000 
8001 
8002             for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
8003                 Sensor s = mSensorStats.valueAt(ise);
8004                 s.detachFromTimeBase();
8005             }
8006 
8007             for (int ip= mProcessStats.size() - 1; ip >= 0; ip--) {
8008                 Proc proc = mProcessStats.valueAt(ip);
8009                 proc.detach();
8010             }
8011             mProcessStats.clear();
8012 
8013             for(int i = mPackageStats.size() - 1; i >= 0; i--) {
8014                 Pkg p = mPackageStats.valueAt(i);
8015                 p.detach();
8016             }
8017             mPackageStats.clear();
8018         }
8019 
writeJobCompletionsToParcelLocked(Parcel out)8020         void writeJobCompletionsToParcelLocked(Parcel out) {
8021             int NJC = mJobCompletions.size();
8022             out.writeInt(NJC);
8023             for (int ijc=0; ijc<NJC; ijc++) {
8024                 out.writeString(mJobCompletions.keyAt(ijc));
8025                 SparseIntArray types = mJobCompletions.valueAt(ijc);
8026                 int NT = types.size();
8027                 out.writeInt(NT);
8028                 for (int it=0; it<NT; it++) {
8029                     out.writeInt(types.keyAt(it));
8030                     out.writeInt(types.valueAt(it));
8031                 }
8032             }
8033         }
8034 
writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs)8035         void writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
8036             mOnBatteryBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
8037             mOnBatteryScreenOffBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
8038 
8039             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
8040             int NW = wakeStats.size();
8041             out.writeInt(NW);
8042             for (int iw=0; iw<NW; iw++) {
8043                 out.writeString(wakeStats.keyAt(iw));
8044                 Uid.Wakelock wakelock = wakeStats.valueAt(iw);
8045                 wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
8046             }
8047 
8048             final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
8049             int NS = syncStats.size();
8050             out.writeInt(NS);
8051             for (int is=0; is<NS; is++) {
8052                 out.writeString(syncStats.keyAt(is));
8053                 DualTimer timer = syncStats.valueAt(is);
8054                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
8055             }
8056 
8057             final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
8058             int NJ = jobStats.size();
8059             out.writeInt(NJ);
8060             for (int ij=0; ij<NJ; ij++) {
8061                 out.writeString(jobStats.keyAt(ij));
8062                 DualTimer timer = jobStats.valueAt(ij);
8063                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
8064             }
8065 
8066             writeJobCompletionsToParcelLocked(out);
8067 
8068             mJobsDeferredEventCount.writeToParcel(out);
8069             mJobsDeferredCount.writeToParcel(out);
8070             mJobsFreshnessTimeMs.writeToParcel(out);
8071             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8072                 Counter.writeCounterToParcel(out, mJobsFreshnessBuckets[i]);
8073             }
8074 
8075             int NSE = mSensorStats.size();
8076             out.writeInt(NSE);
8077             for (int ise=0; ise<NSE; ise++) {
8078                 out.writeInt(mSensorStats.keyAt(ise));
8079                 Uid.Sensor sensor = mSensorStats.valueAt(ise);
8080                 sensor.writeToParcelLocked(out, elapsedRealtimeUs);
8081             }
8082 
8083             int NP = mProcessStats.size();
8084             out.writeInt(NP);
8085             for (int ip=0; ip<NP; ip++) {
8086                 out.writeString(mProcessStats.keyAt(ip));
8087                 Uid.Proc proc = mProcessStats.valueAt(ip);
8088                 proc.writeToParcelLocked(out);
8089             }
8090 
8091             out.writeInt(mPackageStats.size());
8092             for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
8093                 out.writeString(pkgEntry.getKey());
8094                 Uid.Pkg pkg = pkgEntry.getValue();
8095                 pkg.writeToParcelLocked(out);
8096             }
8097 
8098             if (mWifiRunningTimer != null) {
8099                 out.writeInt(1);
8100                 mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
8101             } else {
8102                 out.writeInt(0);
8103             }
8104             if (mFullWifiLockTimer != null) {
8105                 out.writeInt(1);
8106                 mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
8107             } else {
8108                 out.writeInt(0);
8109             }
8110             if (mWifiScanTimer != null) {
8111                 out.writeInt(1);
8112                 mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
8113             } else {
8114                 out.writeInt(0);
8115             }
8116             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8117                 if (mWifiBatchedScanTimer[i] != null) {
8118                     out.writeInt(1);
8119                     mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
8120                 } else {
8121                     out.writeInt(0);
8122                 }
8123             }
8124             if (mWifiMulticastTimer != null) {
8125                 out.writeInt(1);
8126                 mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
8127             } else {
8128                 out.writeInt(0);
8129             }
8130 
8131             if (mAudioTurnedOnTimer != null) {
8132                 out.writeInt(1);
8133                 mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8134             } else {
8135                 out.writeInt(0);
8136             }
8137             if (mVideoTurnedOnTimer != null) {
8138                 out.writeInt(1);
8139                 mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8140             } else {
8141                 out.writeInt(0);
8142             }
8143             if (mFlashlightTurnedOnTimer != null) {
8144                 out.writeInt(1);
8145                 mFlashlightTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8146             } else {
8147                 out.writeInt(0);
8148             }
8149             if (mCameraTurnedOnTimer != null) {
8150                 out.writeInt(1);
8151                 mCameraTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8152             } else {
8153                 out.writeInt(0);
8154             }
8155             if (mForegroundActivityTimer != null) {
8156                 out.writeInt(1);
8157                 mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
8158             } else {
8159                 out.writeInt(0);
8160             }
8161             if (mForegroundServiceTimer != null) {
8162                 out.writeInt(1);
8163                 mForegroundServiceTimer.writeToParcel(out, elapsedRealtimeUs);
8164             } else {
8165                 out.writeInt(0);
8166             }
8167             if (mAggregatedPartialWakelockTimer != null) {
8168                 out.writeInt(1);
8169                 mAggregatedPartialWakelockTimer.writeToParcel(out, elapsedRealtimeUs);
8170             } else {
8171                 out.writeInt(0);
8172             }
8173             if (mBluetoothScanTimer != null) {
8174                 out.writeInt(1);
8175                 mBluetoothScanTimer.writeToParcel(out, elapsedRealtimeUs);
8176             } else {
8177                 out.writeInt(0);
8178             }
8179             if (mBluetoothUnoptimizedScanTimer != null) {
8180                 out.writeInt(1);
8181                 mBluetoothUnoptimizedScanTimer.writeToParcel(out, elapsedRealtimeUs);
8182             } else {
8183                 out.writeInt(0);
8184             }
8185             if (mBluetoothScanResultCounter != null) {
8186                 out.writeInt(1);
8187                 mBluetoothScanResultCounter.writeToParcel(out);
8188             } else {
8189                 out.writeInt(0);
8190             }
8191             if (mBluetoothScanResultBgCounter != null) {
8192                 out.writeInt(1);
8193                 mBluetoothScanResultBgCounter.writeToParcel(out);
8194             } else {
8195                 out.writeInt(0);
8196             }
8197             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
8198                 if (mProcessStateTimer[i] != null) {
8199                     out.writeInt(1);
8200                     mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
8201                 } else {
8202                     out.writeInt(0);
8203                 }
8204             }
8205             if (mVibratorOnTimer != null) {
8206                 out.writeInt(1);
8207                 mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
8208             } else {
8209                 out.writeInt(0);
8210             }
8211             if (mUserActivityCounters != null) {
8212                 out.writeInt(1);
8213                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8214                     mUserActivityCounters[i].writeToParcel(out);
8215                 }
8216             } else {
8217                 out.writeInt(0);
8218             }
8219             if (mNetworkByteActivityCounters != null) {
8220                 out.writeInt(1);
8221                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8222                     mNetworkByteActivityCounters[i].writeToParcel(out);
8223                     mNetworkPacketActivityCounters[i].writeToParcel(out);
8224                 }
8225                 mMobileRadioActiveTime.writeToParcel(out);
8226                 mMobileRadioActiveCount.writeToParcel(out);
8227             } else {
8228                 out.writeInt(0);
8229             }
8230 
8231             if (mWifiControllerActivity != null) {
8232                 out.writeInt(1);
8233                 mWifiControllerActivity.writeToParcel(out, 0);
8234             } else {
8235                 out.writeInt(0);
8236             }
8237 
8238             if (mBluetoothControllerActivity != null) {
8239                 out.writeInt(1);
8240                 mBluetoothControllerActivity.writeToParcel(out, 0);
8241             } else {
8242                 out.writeInt(0);
8243             }
8244 
8245             if (mModemControllerActivity != null) {
8246                 out.writeInt(1);
8247                 mModemControllerActivity.writeToParcel(out, 0);
8248             } else {
8249                 out.writeInt(0);
8250             }
8251 
8252             mUserCpuTime.writeToParcel(out);
8253             mSystemCpuTime.writeToParcel(out);
8254 
8255             if (mCpuClusterSpeedTimesUs != null) {
8256                 out.writeInt(1);
8257                 out.writeInt(mCpuClusterSpeedTimesUs.length);
8258                 for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) {
8259                     if (cpuSpeeds != null) {
8260                         out.writeInt(1);
8261                         out.writeInt(cpuSpeeds.length);
8262                         for (LongSamplingCounter c : cpuSpeeds) {
8263                             if (c != null) {
8264                                 out.writeInt(1);
8265                                 c.writeToParcel(out);
8266                             } else {
8267                                 out.writeInt(0);
8268                             }
8269                         }
8270                     } else {
8271                         out.writeInt(0);
8272                     }
8273                 }
8274             } else {
8275                 out.writeInt(0);
8276             }
8277 
8278             LongSamplingCounterArray.writeToParcel(out, mCpuFreqTimeMs);
8279             LongSamplingCounterArray.writeToParcel(out, mScreenOffCpuFreqTimeMs);
8280 
8281             mCpuActiveTimeMs.writeToParcel(out);
8282             mCpuClusterTimesMs.writeToParcel(out);
8283 
8284             if (mProcStateTimeMs != null) {
8285                 out.writeInt(mProcStateTimeMs.length);
8286                 for (LongSamplingCounterArray counters : mProcStateTimeMs) {
8287                     LongSamplingCounterArray.writeToParcel(out, counters);
8288                 }
8289             } else {
8290                 out.writeInt(0);
8291             }
8292             if (mProcStateScreenOffTimeMs != null) {
8293                 out.writeInt(mProcStateScreenOffTimeMs.length);
8294                 for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
8295                     LongSamplingCounterArray.writeToParcel(out, counters);
8296                 }
8297             } else {
8298                 out.writeInt(0);
8299             }
8300 
8301             if (mMobileRadioApWakeupCount != null) {
8302                 out.writeInt(1);
8303                 mMobileRadioApWakeupCount.writeToParcel(out);
8304             } else {
8305                 out.writeInt(0);
8306             }
8307 
8308             if (mWifiRadioApWakeupCount != null) {
8309                 out.writeInt(1);
8310                 mWifiRadioApWakeupCount.writeToParcel(out);
8311             } else {
8312                 out.writeInt(0);
8313             }
8314         }
8315 
readJobCompletionsFromParcelLocked(Parcel in)8316         void readJobCompletionsFromParcelLocked(Parcel in) {
8317             int numJobCompletions = in.readInt();
8318             mJobCompletions.clear();
8319             for (int j = 0; j < numJobCompletions; j++) {
8320                 String jobName = in.readString();
8321                 int numTypes = in.readInt();
8322                 if (numTypes > 0) {
8323                     SparseIntArray types = new SparseIntArray();
8324                     for (int k = 0; k < numTypes; k++) {
8325                         int type = in.readInt();
8326                         int count = in.readInt();
8327                         types.put(type, count);
8328                     }
8329                     mJobCompletions.put(jobName, types);
8330                 }
8331             }
8332         }
8333 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in)8334         void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
8335             mOnBatteryBackgroundTimeBase.readFromParcel(in);
8336             mOnBatteryScreenOffBackgroundTimeBase.readFromParcel(in);
8337 
8338             int numWakelocks = in.readInt();
8339             mWakelockStats.clear();
8340             for (int j = 0; j < numWakelocks; j++) {
8341                 String wakelockName = in.readString();
8342                 Uid.Wakelock wakelock = new Wakelock(mBsi, this);
8343                 wakelock.readFromParcelLocked(
8344                         timeBase, screenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase, in);
8345                 mWakelockStats.add(wakelockName, wakelock);
8346             }
8347 
8348             int numSyncs = in.readInt();
8349             mSyncStats.clear();
8350             for (int j = 0; j < numSyncs; j++) {
8351                 String syncName = in.readString();
8352                 if (in.readInt() != 0) {
8353                     mSyncStats.add(syncName, new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
8354                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
8355                 }
8356             }
8357 
8358             int numJobs = in.readInt();
8359             mJobStats.clear();
8360             for (int j = 0; j < numJobs; j++) {
8361                 String jobName = in.readString();
8362                 if (in.readInt() != 0) {
8363                     mJobStats.add(jobName, new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
8364                             mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
8365                 }
8366             }
8367 
8368             readJobCompletionsFromParcelLocked(in);
8369 
8370             mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase, in);
8371             mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase, in);
8372             mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8373             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8374                 mJobsFreshnessBuckets[i] = Counter.readCounterFromParcel(mBsi.mOnBatteryTimeBase,
8375                         in);
8376             }
8377 
8378             int numSensors = in.readInt();
8379             mSensorStats.clear();
8380             for (int k = 0; k < numSensors; k++) {
8381                 int sensorNumber = in.readInt();
8382                 Uid.Sensor sensor = new Sensor(mBsi, this, sensorNumber);
8383                 sensor.readFromParcelLocked(mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
8384                         in);
8385                 mSensorStats.put(sensorNumber, sensor);
8386             }
8387 
8388             int numProcs = in.readInt();
8389             mProcessStats.clear();
8390             for (int k = 0; k < numProcs; k++) {
8391                 String processName = in.readString();
8392                 Uid.Proc proc = new Proc(mBsi, processName);
8393                 proc.readFromParcelLocked(in);
8394                 mProcessStats.put(processName, proc);
8395             }
8396 
8397             int numPkgs = in.readInt();
8398             mPackageStats.clear();
8399             for (int l = 0; l < numPkgs; l++) {
8400                 String packageName = in.readString();
8401                 Uid.Pkg pkg = new Pkg(mBsi);
8402                 pkg.readFromParcelLocked(in);
8403                 mPackageStats.put(packageName, pkg);
8404             }
8405 
8406             mWifiRunning = false;
8407             if (in.readInt() != 0) {
8408                 mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
8409                         mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase, in);
8410             } else {
8411                 mWifiRunningTimer = null;
8412             }
8413             mFullWifiLockOut = false;
8414             if (in.readInt() != 0) {
8415                 mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
8416                         mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase, in);
8417             } else {
8418                 mFullWifiLockTimer = null;
8419             }
8420             mWifiScanStarted = false;
8421             if (in.readInt() != 0) {
8422                 mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
8423                         mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
8424                         in);
8425             } else {
8426                 mWifiScanTimer = null;
8427             }
8428             mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
8429             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8430                 if (in.readInt() != 0) {
8431                     makeWifiBatchedScanBin(i, in);
8432                 } else {
8433                     mWifiBatchedScanTimer[i] = null;
8434                 }
8435             }
8436             mWifiMulticastWakelockCount = 0;
8437             if (in.readInt() != 0) {
8438                 mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_MULTICAST_ENABLED,
8439                         mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase, in);
8440             } else {
8441                 mWifiMulticastTimer = null;
8442             }
8443             if (in.readInt() != 0) {
8444                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
8445                         mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8446             } else {
8447                 mAudioTurnedOnTimer = null;
8448             }
8449             if (in.readInt() != 0) {
8450                 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
8451                         mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8452             } else {
8453                 mVideoTurnedOnTimer = null;
8454             }
8455             if (in.readInt() != 0) {
8456                 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8457                         FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8458             } else {
8459                 mFlashlightTurnedOnTimer = null;
8460             }
8461             if (in.readInt() != 0) {
8462                 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
8463                         mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8464             } else {
8465                 mCameraTurnedOnTimer = null;
8466             }
8467             if (in.readInt() != 0) {
8468                 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8469                         FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase, in);
8470             } else {
8471                 mForegroundActivityTimer = null;
8472             }
8473             if (in.readInt() != 0) {
8474                 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8475                         FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase, in);
8476             } else {
8477                 mForegroundServiceTimer = null;
8478             }
8479             if (in.readInt() != 0) {
8480                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
8481                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
8482                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase,
8483                         in);
8484             } else {
8485                 mAggregatedPartialWakelockTimer = null;
8486             }
8487             if (in.readInt() != 0) {
8488                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
8489                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
8490                         mOnBatteryBackgroundTimeBase, in);
8491             } else {
8492                 mBluetoothScanTimer = null;
8493             }
8494             if (in.readInt() != 0) {
8495                 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
8496                         BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
8497                         mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in);
8498             } else {
8499                 mBluetoothUnoptimizedScanTimer = null;
8500             }
8501             if (in.readInt() != 0) {
8502                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase, in);
8503             } else {
8504                 mBluetoothScanResultCounter = null;
8505             }
8506             if (in.readInt() != 0) {
8507                 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase, in);
8508             } else {
8509                 mBluetoothScanResultBgCounter = null;
8510             }
8511             mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
8512             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
8513                 if (in.readInt() != 0) {
8514                     makeProcessState(i, in);
8515                 } else {
8516                     mProcessStateTimer[i] = null;
8517                 }
8518             }
8519             if (in.readInt() != 0) {
8520                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
8521                         mBsi.mOnBatteryTimeBase, in);
8522             } else {
8523                 mVibratorOnTimer = null;
8524             }
8525             if (in.readInt() != 0) {
8526                 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
8527                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8528                     mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase, in);
8529                 }
8530             } else {
8531                 mUserActivityCounters = null;
8532             }
8533             if (in.readInt() != 0) {
8534                 mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
8535                 mNetworkPacketActivityCounters
8536                         = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
8537                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8538                     mNetworkByteActivityCounters[i]
8539                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8540                     mNetworkPacketActivityCounters[i]
8541                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8542                 }
8543                 mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8544                 mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8545             } else {
8546                 mNetworkByteActivityCounters = null;
8547                 mNetworkPacketActivityCounters = null;
8548             }
8549 
8550             if (in.readInt() != 0) {
8551                 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8552                         NUM_WIFI_TX_LEVELS, in);
8553             } else {
8554                 mWifiControllerActivity = null;
8555             }
8556 
8557             if (in.readInt() != 0) {
8558                 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8559                         NUM_BT_TX_LEVELS, in);
8560             } else {
8561                 mBluetoothControllerActivity = null;
8562             }
8563 
8564             if (in.readInt() != 0) {
8565                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8566                         ModemActivityInfo.TX_POWER_LEVELS, in);
8567             } else {
8568                 mModemControllerActivity = null;
8569             }
8570 
8571             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8572             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8573 
8574             if (in.readInt() != 0) {
8575                 int numCpuClusters = in.readInt();
8576                 if (mBsi.mPowerProfile != null && mBsi.mPowerProfile.getNumCpuClusters() != numCpuClusters) {
8577                     throw new ParcelFormatException("Incompatible number of cpu clusters");
8578                 }
8579 
8580                 mCpuClusterSpeedTimesUs = new LongSamplingCounter[numCpuClusters][];
8581                 for (int cluster = 0; cluster < numCpuClusters; cluster++) {
8582                     if (in.readInt() != 0) {
8583                         int numSpeeds = in.readInt();
8584                         if (mBsi.mPowerProfile != null &&
8585                                 mBsi.mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
8586                             throw new ParcelFormatException("Incompatible number of cpu speeds");
8587                         }
8588 
8589                         final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
8590                         mCpuClusterSpeedTimesUs[cluster] = cpuSpeeds;
8591                         for (int speed = 0; speed < numSpeeds; speed++) {
8592                             if (in.readInt() != 0) {
8593                                 cpuSpeeds[speed] = new LongSamplingCounter(
8594                                         mBsi.mOnBatteryTimeBase, in);
8595                             }
8596                         }
8597                     } else {
8598                         mCpuClusterSpeedTimesUs[cluster] = null;
8599                     }
8600                 }
8601             } else {
8602                 mCpuClusterSpeedTimesUs = null;
8603             }
8604 
8605             mCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(in, mBsi.mOnBatteryTimeBase);
8606             mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(
8607                     in, mBsi.mOnBatteryScreenOffTimeBase);
8608 
8609             mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8610             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
8611 
8612             int length = in.readInt();
8613             if (length == NUM_PROCESS_STATE) {
8614                 mProcStateTimeMs = new LongSamplingCounterArray[length];
8615                 for (int procState = 0; procState < length; ++procState) {
8616                     mProcStateTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
8617                             in, mBsi.mOnBatteryTimeBase);
8618                 }
8619             } else {
8620                 mProcStateTimeMs = null;
8621             }
8622             length = in.readInt();
8623             if (length == NUM_PROCESS_STATE) {
8624                 mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
8625                 for (int procState = 0; procState < length; ++procState) {
8626                     mProcStateScreenOffTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
8627                             in, mBsi.mOnBatteryScreenOffTimeBase);
8628                 }
8629             } else {
8630                 mProcStateScreenOffTimeMs = null;
8631             }
8632 
8633             if (in.readInt() != 0) {
8634                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8635             } else {
8636                 mMobileRadioApWakeupCount = null;
8637             }
8638 
8639             if (in.readInt() != 0) {
8640                 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8641             } else {
8642                 mWifiRadioApWakeupCount = null;
8643             }
8644         }
8645 
noteJobsDeferredLocked(int numDeferred, long sinceLast)8646         public void noteJobsDeferredLocked(int numDeferred, long sinceLast) {
8647             mJobsDeferredEventCount.addAtomic(1);
8648             mJobsDeferredCount.addAtomic(numDeferred);
8649             if (sinceLast != 0) {
8650                 // Add the total time, which can be divided by the event count to get an average
8651                 mJobsFreshnessTimeMs.addCountLocked(sinceLast);
8652                 // Also keep track of how many times there were in these different buckets.
8653                 for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8654                     if (sinceLast < JOB_FRESHNESS_BUCKETS[i]) {
8655                         if (mJobsFreshnessBuckets[i] == null) {
8656                             mJobsFreshnessBuckets[i] = new Counter(
8657                                     mBsi.mOnBatteryTimeBase);
8658                         }
8659                         mJobsFreshnessBuckets[i].addAtomic(1);
8660                         break;
8661                     }
8662                 }
8663             }
8664         }
8665 
8666         /**
8667          * The statistics associated with a particular wake lock.
8668          */
8669         public static class Wakelock extends BatteryStats.Uid.Wakelock {
8670             /**
8671              * BatteryStatsImpl that we are associated with.
8672              */
8673             protected BatteryStatsImpl mBsi;
8674 
8675             /**
8676              * BatteryStatsImpl that we are associated with.
8677              */
8678             protected Uid mUid;
8679 
8680             /**
8681              * How long (in ms) this uid has been keeping the device partially awake.
8682              * Tracks both the total time and the time while the app was in the background.
8683              */
8684             DualTimer mTimerPartial;
8685 
8686             /**
8687              * How long (in ms) this uid has been keeping the device fully awake.
8688              */
8689             StopwatchTimer mTimerFull;
8690 
8691             /**
8692              * How long (in ms) this uid has had a window keeping the device awake.
8693              */
8694             StopwatchTimer mTimerWindow;
8695 
8696             /**
8697              * How long (in ms) this uid has had a draw wake lock.
8698              */
8699             StopwatchTimer mTimerDraw;
8700 
Wakelock(BatteryStatsImpl bsi, Uid uid)8701             public Wakelock(BatteryStatsImpl bsi, Uid uid) {
8702                 mBsi = bsi;
8703                 mUid = uid;
8704             }
8705 
8706             /**
8707              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
8708              * proper timer pool from the given BatteryStatsImpl object.
8709              *
8710              * @param in the Parcel to be read from.
8711              * return a new Timer, or null.
8712              */
readStopwatchTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in)8713             private StopwatchTimer readStopwatchTimerFromParcel(int type,
8714                     ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
8715                 if (in.readInt() == 0) {
8716                     return null;
8717                 }
8718 
8719                 return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
8720             }
8721 
8722             /**
8723              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
8724              * proper timer pool from the given BatteryStatsImpl object.
8725              *
8726              * @param in the Parcel to be read from.
8727              * return a new Timer, or null.
8728              */
readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, TimeBase timeBase, TimeBase bgTimeBase, Parcel in)8729             private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
8730                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
8731                 if (in.readInt() == 0) {
8732                     return null;
8733                 }
8734 
8735                 return new DualTimer(mBsi.mClocks, mUid, type, pool, timeBase, bgTimeBase, in);
8736             }
8737 
reset()8738             boolean reset() {
8739                 boolean wlactive = false;
8740 
8741                 wlactive |= !resetIfNotNull(mTimerFull,false);
8742                 wlactive |= !resetIfNotNull(mTimerPartial,false);
8743                 wlactive |= !resetIfNotNull(mTimerWindow,false);
8744                 wlactive |= !resetIfNotNull(mTimerDraw,false);
8745 
8746                 if (!wlactive) {
8747                     detachIfNotNull(mTimerFull);
8748                     mTimerFull = null;
8749 
8750                     detachIfNotNull(mTimerPartial);
8751                     mTimerPartial = null;
8752 
8753                     detachIfNotNull(mTimerWindow);
8754                     mTimerWindow = null;
8755 
8756                     detachIfNotNull(mTimerDraw);
8757                     mTimerDraw = null;
8758                 }
8759                 return !wlactive;
8760             }
8761 
readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, TimeBase screenOffBgTimeBase, Parcel in)8762             void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase,
8763                     TimeBase screenOffBgTimeBase, Parcel in) {
8764                 mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL,
8765                         mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in);
8766                 mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
8767                         mBsi.mFullTimers, timeBase, in);
8768                 mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
8769                         mBsi.mWindowTimers, timeBase, in);
8770                 mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
8771                         mBsi.mDrawTimers, timeBase, in);
8772             }
8773 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)8774             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
8775                 Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
8776                 Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
8777                 Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
8778                 Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
8779             }
8780 
8781             @Override
8782             @UnsupportedAppUsage
getWakeTime(int type)8783             public Timer getWakeTime(int type) {
8784                 switch (type) {
8785                 case WAKE_TYPE_FULL: return mTimerFull;
8786                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
8787                 case WAKE_TYPE_WINDOW: return mTimerWindow;
8788                 case WAKE_TYPE_DRAW: return mTimerDraw;
8789                 default: throw new IllegalArgumentException("type = " + type);
8790                 }
8791             }
8792 
detachFromTimeBase()8793             public void detachFromTimeBase() {
8794                 detachIfNotNull(mTimerPartial);
8795                 detachIfNotNull(mTimerFull);
8796                 detachIfNotNull(mTimerWindow);
8797                 detachIfNotNull(mTimerDraw);
8798             }
8799         }
8800 
8801         public static class Sensor extends BatteryStats.Uid.Sensor {
8802             /**
8803              * BatteryStatsImpl that we are associated with.
8804              */
8805             protected BatteryStatsImpl mBsi;
8806 
8807             /**
8808              * Uid that we are associated with.
8809              */
8810             protected Uid mUid;
8811 
8812             final int mHandle;
8813             DualTimer mTimer;
8814 
Sensor(BatteryStatsImpl bsi, Uid uid, int handle)8815             public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
8816                 mBsi = bsi;
8817                 mUid = uid;
8818                 mHandle = handle;
8819             }
8820 
readTimersFromParcel( TimeBase timeBase, TimeBase bgTimeBase, Parcel in)8821             private DualTimer readTimersFromParcel(
8822                     TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
8823                 if (in.readInt() == 0) {
8824                     return null;
8825                 }
8826 
8827                 ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
8828                 if (pool == null) {
8829                     pool = new ArrayList<StopwatchTimer>();
8830                     mBsi.mSensorTimers.put(mHandle, pool);
8831                 }
8832                 return new DualTimer(mBsi.mClocks, mUid, 0, pool, timeBase, bgTimeBase, in);
8833             }
8834 
reset()8835             boolean reset() {
8836                 if (mTimer.reset(true)) {
8837                     mTimer = null;
8838                     return true;
8839                 }
8840                 return false;
8841             }
8842 
readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in)8843             void readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
8844                 mTimer = readTimersFromParcel(timeBase, bgTimeBase, in);
8845             }
8846 
writeToParcelLocked(Parcel out, long elapsedRealtimeUs)8847             void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
8848                 Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
8849             }
8850 
8851             @Override
8852             @UnsupportedAppUsage
getSensorTime()8853             public Timer getSensorTime() {
8854                 return mTimer;
8855             }
8856 
8857             @Override
getSensorBackgroundTime()8858             public Timer getSensorBackgroundTime() {
8859                 if (mTimer == null) {
8860                     return null;
8861                 }
8862                 return mTimer.getSubTimer();
8863             }
8864 
8865             @Override
8866             @UnsupportedAppUsage
getHandle()8867             public int getHandle() {
8868                 return mHandle;
8869             }
8870 
detachFromTimeBase()8871             public void  detachFromTimeBase() {
8872                 detachIfNotNull(mTimer);
8873             }
8874         }
8875 
8876         /**
8877          * The statistics associated with a particular process.
8878          */
8879         public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
8880             /**
8881              * BatteryStatsImpl that we are associated with.
8882              */
8883             protected BatteryStatsImpl mBsi;
8884 
8885             /**
8886              * The name of this process.
8887              */
8888             final String mName;
8889 
8890             /**
8891              * Remains true until removed from the stats.
8892              */
8893             boolean mActive = true;
8894 
8895             /**
8896              * Total time (in ms) spent executing in user code.
8897              */
8898             long mUserTime;
8899 
8900             /**
8901              * Total time (in ms) spent executing in kernel code.
8902              */
8903             long mSystemTime;
8904 
8905             /**
8906              * Amount of time (in ms) the process was running in the foreground.
8907              */
8908             long mForegroundTime;
8909 
8910             /**
8911              * Number of times the process has been started.
8912              */
8913             int mStarts;
8914 
8915             /**
8916              * Number of times the process has crashed.
8917              */
8918             int mNumCrashes;
8919 
8920             /**
8921              * Number of times the process has had an ANR.
8922              */
8923             int mNumAnrs;
8924 
8925             ArrayList<ExcessivePower> mExcessivePower;
8926 
Proc(BatteryStatsImpl bsi, String name)8927             public Proc(BatteryStatsImpl bsi, String name) {
8928                 mBsi = bsi;
8929                 mName = name;
8930                 mBsi.mOnBatteryTimeBase.add(this);
8931             }
8932 
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)8933             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
8934             }
8935 
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)8936             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
8937             }
8938 
8939             @Override
reset(boolean detachIfReset)8940             public boolean reset(boolean detachIfReset) {
8941                 if (detachIfReset) {
8942                     this.detach();
8943                 }
8944                 return true;
8945             }
8946 
8947             @Override
detach()8948             public void detach() {
8949                 mActive = false;
8950                 mBsi.mOnBatteryTimeBase.remove(this);
8951             }
8952 
countExcessivePowers()8953             public int countExcessivePowers() {
8954                 return mExcessivePower != null ? mExcessivePower.size() : 0;
8955             }
8956 
getExcessivePower(int i)8957             public ExcessivePower getExcessivePower(int i) {
8958                 if (mExcessivePower != null) {
8959                     return mExcessivePower.get(i);
8960                 }
8961                 return null;
8962             }
8963 
addExcessiveCpu(long overTime, long usedTime)8964             public void addExcessiveCpu(long overTime, long usedTime) {
8965                 if (mExcessivePower == null) {
8966                     mExcessivePower = new ArrayList<ExcessivePower>();
8967                 }
8968                 ExcessivePower ew = new ExcessivePower();
8969                 ew.type = ExcessivePower.TYPE_CPU;
8970                 ew.overTime = overTime;
8971                 ew.usedTime = usedTime;
8972                 mExcessivePower.add(ew);
8973             }
8974 
writeExcessivePowerToParcelLocked(Parcel out)8975             void writeExcessivePowerToParcelLocked(Parcel out) {
8976                 if (mExcessivePower == null) {
8977                     out.writeInt(0);
8978                     return;
8979                 }
8980 
8981                 final int N = mExcessivePower.size();
8982                 out.writeInt(N);
8983                 for (int i=0; i<N; i++) {
8984                     ExcessivePower ew = mExcessivePower.get(i);
8985                     out.writeInt(ew.type);
8986                     out.writeLong(ew.overTime);
8987                     out.writeLong(ew.usedTime);
8988                 }
8989             }
8990 
readExcessivePowerFromParcelLocked(Parcel in)8991             void readExcessivePowerFromParcelLocked(Parcel in) {
8992                 final int N = in.readInt();
8993                 if (N == 0) {
8994                     mExcessivePower = null;
8995                     return;
8996                 }
8997 
8998                 if (N > 10000) {
8999                     throw new ParcelFormatException(
9000                             "File corrupt: too many excessive power entries " + N);
9001                 }
9002 
9003                 mExcessivePower = new ArrayList<>();
9004                 for (int i=0; i<N; i++) {
9005                     ExcessivePower ew = new ExcessivePower();
9006                     ew.type = in.readInt();
9007                     ew.overTime = in.readLong();
9008                     ew.usedTime = in.readLong();
9009                     mExcessivePower.add(ew);
9010                 }
9011             }
9012 
writeToParcelLocked(Parcel out)9013             void writeToParcelLocked(Parcel out) {
9014                 out.writeLong(mUserTime);
9015                 out.writeLong(mSystemTime);
9016                 out.writeLong(mForegroundTime);
9017                 out.writeInt(mStarts);
9018                 out.writeInt(mNumCrashes);
9019                 out.writeInt(mNumAnrs);
9020                 writeExcessivePowerToParcelLocked(out);
9021             }
9022 
readFromParcelLocked(Parcel in)9023             void readFromParcelLocked(Parcel in) {
9024                 mUserTime = in.readLong();
9025                 mSystemTime = in.readLong();
9026                 mForegroundTime = in.readLong();
9027                 mStarts = in.readInt();
9028                 mNumCrashes = in.readInt();
9029                 mNumAnrs = in.readInt();
9030                 readExcessivePowerFromParcelLocked(in);
9031             }
9032 
9033             @UnsupportedAppUsage
addCpuTimeLocked(int utime, int stime)9034             public void addCpuTimeLocked(int utime, int stime) {
9035                 addCpuTimeLocked(utime, stime, mBsi.mOnBatteryTimeBase.isRunning());
9036             }
9037 
addCpuTimeLocked(int utime, int stime, boolean isRunning)9038             public void addCpuTimeLocked(int utime, int stime, boolean isRunning) {
9039                 if (isRunning) {
9040                     mUserTime += utime;
9041                     mSystemTime += stime;
9042                 }
9043             }
9044 
9045             @UnsupportedAppUsage
addForegroundTimeLocked(long ttime)9046             public void addForegroundTimeLocked(long ttime) {
9047                 mForegroundTime += ttime;
9048             }
9049 
9050             @UnsupportedAppUsage
incStartsLocked()9051             public void incStartsLocked() {
9052                 mStarts++;
9053             }
9054 
incNumCrashesLocked()9055             public void incNumCrashesLocked() {
9056                 mNumCrashes++;
9057             }
9058 
incNumAnrsLocked()9059             public void incNumAnrsLocked() {
9060                 mNumAnrs++;
9061             }
9062 
9063             @Override
isActive()9064             public boolean isActive() {
9065                 return mActive;
9066             }
9067 
9068             @Override
9069             @UnsupportedAppUsage
getUserTime(int which)9070             public long getUserTime(int which) {
9071                 return mUserTime;
9072             }
9073 
9074             @Override
9075             @UnsupportedAppUsage
getSystemTime(int which)9076             public long getSystemTime(int which) {
9077                 return mSystemTime;
9078             }
9079 
9080             @Override
9081             @UnsupportedAppUsage
getForegroundTime(int which)9082             public long getForegroundTime(int which) {
9083                 return mForegroundTime;
9084             }
9085 
9086             @Override
9087             @UnsupportedAppUsage
getStarts(int which)9088             public int getStarts(int which) {
9089                 return mStarts;
9090             }
9091 
9092             @Override
getNumCrashes(int which)9093             public int getNumCrashes(int which) {
9094                 return mNumCrashes;
9095             }
9096 
9097             @Override
getNumAnrs(int which)9098             public int getNumAnrs(int which) {
9099                 return mNumAnrs;
9100             }
9101         }
9102 
9103         /**
9104          * The statistics associated with a particular package.
9105          */
9106         public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
9107             /**
9108              * BatteryStatsImpl that we are associated with.
9109              */
9110             protected BatteryStatsImpl mBsi;
9111 
9112             /**
9113              * Number of times wakeup alarms have occurred for this app.
9114              * On screen-off timebase starting in report v25.
9115              */
9116             ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
9117 
9118             /**
9119              * The statics we have collected for this package's services.
9120              */
9121             final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
9122 
Pkg(BatteryStatsImpl bsi)9123             public Pkg(BatteryStatsImpl bsi) {
9124                 mBsi = bsi;
9125                 mBsi.mOnBatteryScreenOffTimeBase.add(this);
9126             }
9127 
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)9128             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
9129             }
9130 
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)9131             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
9132             }
9133 
9134             @Override
reset(boolean detachIfReset)9135             public boolean reset(boolean detachIfReset) {
9136                 if (detachIfReset) {
9137                     this.detach();
9138                 }
9139                 return true;
9140             }
9141 
9142             @Override
detach()9143             public void detach() {
9144                 mBsi.mOnBatteryScreenOffTimeBase.remove(this);
9145                 for (int j = mWakeupAlarms.size() - 1; j >= 0; j--) {
9146                     detachIfNotNull(mWakeupAlarms.valueAt(j));
9147                 }
9148                 for (int j = mServiceStats.size() - 1; j >= 0; j--) {
9149                     detachIfNotNull(mServiceStats.valueAt(j));
9150                 }
9151             }
9152 
readFromParcelLocked(Parcel in)9153             void readFromParcelLocked(Parcel in) {
9154                 int numWA = in.readInt();
9155                 mWakeupAlarms.clear();
9156                 for (int i=0; i<numWA; i++) {
9157                     String tag = in.readString();
9158                     mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryScreenOffTimeBase, in));
9159                 }
9160 
9161                 int numServs = in.readInt();
9162                 mServiceStats.clear();
9163                 for (int m = 0; m < numServs; m++) {
9164                     String serviceName = in.readString();
9165                     Uid.Pkg.Serv serv = new Serv(mBsi);
9166                     mServiceStats.put(serviceName, serv);
9167 
9168                     serv.readFromParcelLocked(in);
9169                 }
9170             }
9171 
writeToParcelLocked(Parcel out)9172             void writeToParcelLocked(Parcel out) {
9173                 int numWA = mWakeupAlarms.size();
9174                 out.writeInt(numWA);
9175                 for (int i=0; i<numWA; i++) {
9176                     out.writeString(mWakeupAlarms.keyAt(i));
9177                     mWakeupAlarms.valueAt(i).writeToParcel(out);
9178                 }
9179 
9180                 final int NS = mServiceStats.size();
9181                 out.writeInt(NS);
9182                 for (int i=0; i<NS; i++) {
9183                     out.writeString(mServiceStats.keyAt(i));
9184                     Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
9185                     serv.writeToParcelLocked(out);
9186                 }
9187             }
9188 
9189             @Override
getWakeupAlarmStats()9190             public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
9191                 return mWakeupAlarms;
9192             }
9193 
noteWakeupAlarmLocked(String tag)9194             public void noteWakeupAlarmLocked(String tag) {
9195                 Counter c = mWakeupAlarms.get(tag);
9196                 if (c == null) {
9197                     c = new Counter(mBsi.mOnBatteryScreenOffTimeBase);
9198                     mWakeupAlarms.put(tag, c);
9199                 }
9200                 c.stepAtomic();
9201             }
9202 
9203             @Override
getServiceStats()9204             public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
9205                 return mServiceStats;
9206             }
9207 
9208             /**
9209              * The statistics associated with a particular service.
9210              */
9211             public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
9212                 /**
9213                  * BatteryStatsImpl that we are associated with.
9214                  */
9215                 protected BatteryStatsImpl mBsi;
9216 
9217                 /**
9218                  * The android package in which this service resides.
9219                  */
9220                 protected Pkg mPkg;
9221 
9222                 /**
9223                  * Total time (ms in battery uptime) the service has been left started.
9224                  */
9225                 protected long mStartTime;
9226 
9227                 /**
9228                  * If service has been started and not yet stopped, this is
9229                  * when it was started.
9230                  */
9231                 protected long mRunningSince;
9232 
9233                 /**
9234                  * True if we are currently running.
9235                  */
9236                 protected boolean mRunning;
9237 
9238                 /**
9239                  * Total number of times startService() has been called.
9240                  */
9241                 protected int mStarts;
9242 
9243                 /**
9244                  * Total time (ms in battery uptime) the service has been left launched.
9245                  */
9246                 protected long mLaunchedTime;
9247 
9248                 /**
9249                  * If service has been launched and not yet exited, this is
9250                  * when it was launched (ms in battery uptime).
9251                  */
9252                 protected long mLaunchedSince;
9253 
9254                 /**
9255                  * True if we are currently launched.
9256                  */
9257                 protected boolean mLaunched;
9258 
9259                 /**
9260                  * Total number times the service has been launched.
9261                  */
9262                 protected int mLaunches;
9263 
9264                 /**
9265                  * Construct a Serv. Also adds it to the on-battery time base as a listener.
9266                  */
Serv(BatteryStatsImpl bsi)9267                 public Serv(BatteryStatsImpl bsi) {
9268                     mBsi = bsi;
9269                     mBsi.mOnBatteryTimeBase.add(this);
9270                 }
9271 
onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime)9272                 public void onTimeStarted(long elapsedRealtime, long baseUptime,
9273                         long baseRealtime) {
9274                 }
9275 
onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime)9276                 public void onTimeStopped(long elapsedRealtime, long baseUptime,
9277                         long baseRealtime) {
9278                 }
9279 
9280                 @Override
reset(boolean detachIfReset)9281                 public boolean reset(boolean detachIfReset) {
9282                     if (detachIfReset) {
9283                         this.detach();
9284                     }
9285                     return true;
9286                 }
9287 
9288                 /**
9289                  * Remove this Serv as a listener from the time base.
9290                  */
9291                 @Override
detach()9292                 public void detach() {
9293                     mBsi.mOnBatteryTimeBase.remove(this);
9294                 }
9295 
readFromParcelLocked(Parcel in)9296                 public void readFromParcelLocked(Parcel in) {
9297                     mStartTime = in.readLong();
9298                     mRunningSince = in.readLong();
9299                     mRunning = in.readInt() != 0;
9300                     mStarts = in.readInt();
9301                     mLaunchedTime = in.readLong();
9302                     mLaunchedSince = in.readLong();
9303                     mLaunched = in.readInt() != 0;
9304                     mLaunches = in.readInt();
9305                 }
9306 
writeToParcelLocked(Parcel out)9307                 public void writeToParcelLocked(Parcel out) {
9308                     out.writeLong(mStartTime);
9309                     out.writeLong(mRunningSince);
9310                     out.writeInt(mRunning ? 1 : 0);
9311                     out.writeInt(mStarts);
9312                     out.writeLong(mLaunchedTime);
9313                     out.writeLong(mLaunchedSince);
9314                     out.writeInt(mLaunched ? 1 : 0);
9315                     out.writeInt(mLaunches);
9316                 }
9317 
getLaunchTimeToNowLocked(long batteryUptime)9318                 public long getLaunchTimeToNowLocked(long batteryUptime) {
9319                     if (!mLaunched) return mLaunchedTime;
9320                     return mLaunchedTime + batteryUptime - mLaunchedSince;
9321                 }
9322 
getStartTimeToNowLocked(long batteryUptime)9323                 public long getStartTimeToNowLocked(long batteryUptime) {
9324                     if (!mRunning) return mStartTime;
9325                     return mStartTime + batteryUptime - mRunningSince;
9326                 }
9327 
9328                 @UnsupportedAppUsage
startLaunchedLocked()9329                 public void startLaunchedLocked() {
9330                     if (!mLaunched) {
9331                         mLaunches++;
9332                         mLaunchedSince = mBsi.getBatteryUptimeLocked();
9333                         mLaunched = true;
9334                     }
9335                 }
9336 
9337                 @UnsupportedAppUsage
stopLaunchedLocked()9338                 public void stopLaunchedLocked() {
9339                     if (mLaunched) {
9340                         long time = mBsi.getBatteryUptimeLocked() - mLaunchedSince;
9341                         if (time > 0) {
9342                             mLaunchedTime += time;
9343                         } else {
9344                             mLaunches--;
9345                         }
9346                         mLaunched = false;
9347                     }
9348                 }
9349 
9350                 @UnsupportedAppUsage
startRunningLocked()9351                 public void startRunningLocked() {
9352                     if (!mRunning) {
9353                         mStarts++;
9354                         mRunningSince = mBsi.getBatteryUptimeLocked();
9355                         mRunning = true;
9356                     }
9357                 }
9358 
9359                 @UnsupportedAppUsage
stopRunningLocked()9360                 public void stopRunningLocked() {
9361                     if (mRunning) {
9362                         long time = mBsi.getBatteryUptimeLocked() - mRunningSince;
9363                         if (time > 0) {
9364                             mStartTime += time;
9365                         } else {
9366                             mStarts--;
9367                         }
9368                         mRunning = false;
9369                     }
9370                 }
9371 
9372                 @UnsupportedAppUsage
getBatteryStats()9373                 public BatteryStatsImpl getBatteryStats() {
9374                     return mBsi;
9375                 }
9376 
9377                 @Override
getLaunches(int which)9378                 public int getLaunches(int which) {
9379                     return mLaunches;
9380                 }
9381 
9382                 @Override
getStartTime(long now, int which)9383                 public long getStartTime(long now, int which) {
9384                     return getStartTimeToNowLocked(now);
9385                 }
9386 
9387                 @Override
getStarts(int which)9388                 public int getStarts(int which) {
9389                     return mStarts;
9390                 }
9391             }
9392 
newServiceStatsLocked()9393             final Serv newServiceStatsLocked() {
9394                 return new Serv(mBsi);
9395             }
9396         }
9397 
9398         /**
9399          * Retrieve the statistics object for a particular process, creating
9400          * if needed.
9401          */
getProcessStatsLocked(String name)9402         public Proc getProcessStatsLocked(String name) {
9403             Proc ps = mProcessStats.get(name);
9404             if (ps == null) {
9405                 ps = new Proc(mBsi, name);
9406                 mProcessStats.put(name, ps);
9407             }
9408 
9409             return ps;
9410         }
9411 
9412         @GuardedBy("mBsi")
updateUidProcessStateLocked(int procState)9413         public void updateUidProcessStateLocked(int procState) {
9414             int uidRunningState;
9415             // Make special note of Foreground Services
9416             final boolean userAwareService =
9417                     (ActivityManager.isForegroundService(procState));
9418             uidRunningState = BatteryStats.mapToInternalProcessState(procState);
9419 
9420             if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
9421                 return;
9422             }
9423 
9424             final long elapsedRealtimeMs = mBsi.mClocks.elapsedRealtime();
9425             if (mProcessState != uidRunningState) {
9426                 final long uptimeMs = mBsi.mClocks.uptimeMillis();
9427 
9428                 if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
9429                     mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
9430 
9431                     if (mBsi.trackPerProcStateCpuTimes()) {
9432                         if (mBsi.mPendingUids.size() == 0) {
9433                             mBsi.mExternalSync.scheduleReadProcStateCpuTimes(
9434                                     mBsi.mOnBatteryTimeBase.isRunning(),
9435                                     mBsi.mOnBatteryScreenOffTimeBase.isRunning(),
9436                                     mBsi.mConstants.PROC_STATE_CPU_TIMES_READ_DELAY_MS);
9437                             mBsi.mNumSingleUidCpuTimeReads++;
9438                         } else {
9439                             mBsi.mNumBatchedSingleUidCpuTimeReads++;
9440                         }
9441                         if (mBsi.mPendingUids.indexOfKey(mUid) < 0
9442                                 || ArrayUtils.contains(CRITICAL_PROC_STATES, mProcessState)) {
9443                             mBsi.mPendingUids.put(mUid, mProcessState);
9444                         }
9445                     } else {
9446                         mBsi.mPendingUids.clear();
9447                     }
9448                 }
9449                 mProcessState = uidRunningState;
9450                 if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
9451                     if (mProcessStateTimer[uidRunningState] == null) {
9452                         makeProcessState(uidRunningState, null);
9453                     }
9454                     mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
9455                 }
9456 
9457                 updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
9458                 updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
9459             }
9460 
9461             if (userAwareService != mInForegroundService) {
9462                 if (userAwareService) {
9463                     noteForegroundServiceResumedLocked(elapsedRealtimeMs);
9464                 } else {
9465                     noteForegroundServicePausedLocked(elapsedRealtimeMs);
9466                 }
9467                 mInForegroundService = userAwareService;
9468             }
9469         }
9470 
9471         /** Whether to consider Uid to be in the background for background timebase purposes. */
isInBackground()9472         public boolean isInBackground() {
9473             // Note that PROCESS_STATE_CACHED and ActivityManager.PROCESS_STATE_NONEXISTENT is
9474             // also considered to be 'background' for our purposes, because it's not foreground.
9475             return mProcessState >= PROCESS_STATE_BACKGROUND;
9476         }
9477 
updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs)9478         public boolean updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs) {
9479             boolean on = mBsi.mOnBatteryTimeBase.isRunning() && isInBackground();
9480             return mOnBatteryBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
9481         }
9482 
updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs)9483         public boolean updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs) {
9484             boolean on = mBsi.mOnBatteryScreenOffTimeBase.isRunning() && isInBackground();
9485             return mOnBatteryScreenOffBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
9486         }
9487 
getPidStats()9488         public SparseArray<? extends Pid> getPidStats() {
9489             return mPids;
9490         }
9491 
getPidStatsLocked(int pid)9492         public Pid getPidStatsLocked(int pid) {
9493             Pid p = mPids.get(pid);
9494             if (p == null) {
9495                 p = new Pid();
9496                 mPids.put(pid, p);
9497             }
9498             return p;
9499         }
9500 
9501         /**
9502          * Retrieve the statistics object for a particular service, creating
9503          * if needed.
9504          */
getPackageStatsLocked(String name)9505         public Pkg getPackageStatsLocked(String name) {
9506             Pkg ps = mPackageStats.get(name);
9507             if (ps == null) {
9508                 ps = new Pkg(mBsi);
9509                 mPackageStats.put(name, ps);
9510             }
9511 
9512             return ps;
9513         }
9514 
9515         /**
9516          * Retrieve the statistics object for a particular service, creating
9517          * if needed.
9518          */
getServiceStatsLocked(String pkg, String serv)9519         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
9520             Pkg ps = getPackageStatsLocked(pkg);
9521             Pkg.Serv ss = ps.mServiceStats.get(serv);
9522             if (ss == null) {
9523                 ss = ps.newServiceStatsLocked();
9524                 ps.mServiceStats.put(serv, ss);
9525             }
9526 
9527             return ss;
9528         }
9529 
readSyncSummaryFromParcelLocked(String name, Parcel in)9530         public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
9531             DualTimer timer = mSyncStats.instantiateObject();
9532             timer.readSummaryFromParcelLocked(in);
9533             mSyncStats.add(name, timer);
9534         }
9535 
readJobSummaryFromParcelLocked(String name, Parcel in)9536         public void readJobSummaryFromParcelLocked(String name, Parcel in) {
9537             DualTimer timer = mJobStats.instantiateObject();
9538             timer.readSummaryFromParcelLocked(in);
9539             mJobStats.add(name, timer);
9540         }
9541 
readWakeSummaryFromParcelLocked(String wlName, Parcel in)9542         public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
9543             Wakelock wl = new Wakelock(mBsi, this);
9544             mWakelockStats.add(wlName, wl);
9545             if (in.readInt() != 0) {
9546                 getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
9547             }
9548             if (in.readInt() != 0) {
9549                 getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
9550             }
9551             if (in.readInt() != 0) {
9552                 getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
9553             }
9554             if (in.readInt() != 0) {
9555                 getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
9556             }
9557         }
9558 
getSensorTimerLocked(int sensor, boolean create)9559         public DualTimer getSensorTimerLocked(int sensor, boolean create) {
9560             Sensor se = mSensorStats.get(sensor);
9561             if (se == null) {
9562                 if (!create) {
9563                     return null;
9564                 }
9565                 se = new Sensor(mBsi, this, sensor);
9566                 mSensorStats.put(sensor, se);
9567             }
9568             DualTimer t = se.mTimer;
9569             if (t != null) {
9570                 return t;
9571             }
9572             ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
9573             if (timers == null) {
9574                 timers = new ArrayList<StopwatchTimer>();
9575                 mBsi.mSensorTimers.put(sensor, timers);
9576             }
9577             t = new DualTimer(mBsi.mClocks, this, BatteryStats.SENSOR, timers,
9578                     mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
9579             se.mTimer = t;
9580             return t;
9581         }
9582 
noteStartSyncLocked(String name, long elapsedRealtimeMs)9583         public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
9584             DualTimer t = mSyncStats.startObject(name);
9585             if (t != null) {
9586                 t.startRunningLocked(elapsedRealtimeMs);
9587             }
9588         }
9589 
noteStopSyncLocked(String name, long elapsedRealtimeMs)9590         public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
9591             DualTimer t = mSyncStats.stopObject(name);
9592             if (t != null) {
9593                 t.stopRunningLocked(elapsedRealtimeMs);
9594             }
9595         }
9596 
noteStartJobLocked(String name, long elapsedRealtimeMs)9597         public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
9598             DualTimer t = mJobStats.startObject(name);
9599             if (t != null) {
9600                 t.startRunningLocked(elapsedRealtimeMs);
9601             }
9602         }
9603 
noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason)9604         public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
9605             DualTimer t = mJobStats.stopObject(name);
9606             if (t != null) {
9607                 t.stopRunningLocked(elapsedRealtimeMs);
9608             }
9609             if (mBsi.mOnBatteryTimeBase.isRunning()) {
9610                 SparseIntArray types = mJobCompletions.get(name);
9611                 if (types == null) {
9612                     types = new SparseIntArray();
9613                     mJobCompletions.put(name, types);
9614                 }
9615                 int last = types.get(stopReason, 0);
9616                 types.put(stopReason, last + 1);
9617             }
9618         }
9619 
getWakelockTimerLocked(Wakelock wl, int type)9620         public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
9621             if (wl == null) {
9622                 return null;
9623             }
9624             switch (type) {
9625                 case WAKE_TYPE_PARTIAL: {
9626                     DualTimer t = wl.mTimerPartial;
9627                     if (t == null) {
9628                         t = new DualTimer(mBsi.mClocks, this, WAKE_TYPE_PARTIAL,
9629                                 mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase,
9630                                 mOnBatteryScreenOffBackgroundTimeBase);
9631                         wl.mTimerPartial = t;
9632                     }
9633                     return t;
9634                 }
9635                 case WAKE_TYPE_FULL: {
9636                     StopwatchTimer t = wl.mTimerFull;
9637                     if (t == null) {
9638                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_FULL,
9639                                 mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
9640                         wl.mTimerFull = t;
9641                     }
9642                     return t;
9643                 }
9644                 case WAKE_TYPE_WINDOW: {
9645                     StopwatchTimer t = wl.mTimerWindow;
9646                     if (t == null) {
9647                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_WINDOW,
9648                                 mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
9649                         wl.mTimerWindow = t;
9650                     }
9651                     return t;
9652                 }
9653                 case WAKE_TYPE_DRAW: {
9654                     StopwatchTimer t = wl.mTimerDraw;
9655                     if (t == null) {
9656                         t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_DRAW,
9657                                 mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
9658                         wl.mTimerDraw = t;
9659                     }
9660                     return t;
9661                 }
9662                 default:
9663                     throw new IllegalArgumentException("type=" + type);
9664             }
9665         }
9666 
noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)9667         public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
9668             Wakelock wl = mWakelockStats.startObject(name);
9669             if (wl != null) {
9670                 getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
9671             }
9672             if (type == WAKE_TYPE_PARTIAL) {
9673                 createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
9674                 if (pid >= 0) {
9675                     Pid p = getPidStatsLocked(pid);
9676                     if (p.mWakeNesting++ == 0) {
9677                         p.mWakeStartMs = elapsedRealtimeMs;
9678                     }
9679                 }
9680             }
9681         }
9682 
noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs)9683         public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
9684             Wakelock wl = mWakelockStats.stopObject(name);
9685             if (wl != null) {
9686                 StopwatchTimer wlt = getWakelockTimerLocked(wl, type);
9687                 wlt.stopRunningLocked(elapsedRealtimeMs);
9688             }
9689             if (type == WAKE_TYPE_PARTIAL) {
9690                 if (mAggregatedPartialWakelockTimer != null) {
9691                     mAggregatedPartialWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
9692                 }
9693                 if (pid >= 0) {
9694                     Pid p = mPids.get(pid);
9695                     if (p != null && p.mWakeNesting > 0) {
9696                         if (p.mWakeNesting-- == 1) {
9697                             p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
9698                             p.mWakeStartMs = 0;
9699                         }
9700                     }
9701                 }
9702             }
9703         }
9704 
reportExcessiveCpuLocked(String proc, long overTime, long usedTime)9705         public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
9706             Proc p = getProcessStatsLocked(proc);
9707             if (p != null) {
9708                 p.addExcessiveCpu(overTime, usedTime);
9709             }
9710         }
9711 
noteStartSensor(int sensor, long elapsedRealtimeMs)9712         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
9713             DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
9714             t.startRunningLocked(elapsedRealtimeMs);
9715         }
9716 
noteStopSensor(int sensor, long elapsedRealtimeMs)9717         public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
9718             // Don't create a timer if one doesn't already exist
9719             DualTimer t = getSensorTimerLocked(sensor, false);
9720             if (t != null) {
9721                 t.stopRunningLocked(elapsedRealtimeMs);
9722             }
9723         }
9724 
noteStartGps(long elapsedRealtimeMs)9725         public void noteStartGps(long elapsedRealtimeMs) {
9726             noteStartSensor(Sensor.GPS, elapsedRealtimeMs);
9727         }
9728 
noteStopGps(long elapsedRealtimeMs)9729         public void noteStopGps(long elapsedRealtimeMs) {
9730             noteStopSensor(Sensor.GPS, elapsedRealtimeMs);
9731         }
9732 
getBatteryStats()9733         public BatteryStatsImpl getBatteryStats() {
9734             return mBsi;
9735         }
9736     }
9737 
getCpuFreqs()9738     public long[] getCpuFreqs() {
9739         return mCpuFreqs;
9740     }
9741 
BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb, RailEnergyDataCallback railStatsCb, UserInfoProvider userInfoProvider)9742     public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
9743             RailEnergyDataCallback railStatsCb, UserInfoProvider userInfoProvider) {
9744         this(new SystemClocks(), systemDir, handler, cb, railStatsCb, userInfoProvider);
9745     }
9746 
BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler, PlatformIdleStateCallback cb, RailEnergyDataCallback railStatsCb, UserInfoProvider userInfoProvider)9747     private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
9748             PlatformIdleStateCallback cb, RailEnergyDataCallback railStatsCb,
9749             UserInfoProvider userInfoProvider) {
9750         init(clocks);
9751 
9752 
9753         if (systemDir == null) {
9754             mStatsFile = null;
9755             mBatteryStatsHistory = new BatteryStatsHistory(this, mHistoryBuffer);
9756         } else {
9757             mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
9758             mBatteryStatsHistory = new BatteryStatsHistory(this, systemDir, mHistoryBuffer);
9759         }
9760         mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
9761         mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
9762         mHandler = new MyHandler(handler.getLooper());
9763         mConstants = new Constants(mHandler);
9764         mStartCount++;
9765         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
9766         mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
9767         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
9768             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
9769                     mOnBatteryTimeBase);
9770         }
9771         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase);
9772         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
9773                 mOnBatteryTimeBase);
9774         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -11, null,
9775                 mOnBatteryTimeBase);
9776         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
9777         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null, mOnBatteryTimeBase);
9778         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase);
9779         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase);
9780         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
9781             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i, null,
9782                     mOnBatteryTimeBase);
9783         }
9784         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
9785                 mOnBatteryTimeBase);
9786         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
9787             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i, null,
9788                     mOnBatteryTimeBase);
9789         }
9790         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9791             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
9792             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
9793         }
9794         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
9795         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
9796                 NUM_BT_TX_LEVELS);
9797         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
9798                 ModemActivityInfo.TX_POWER_LEVELS);
9799         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase);
9800         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
9801                 mOnBatteryTimeBase);
9802         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
9803         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
9804         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
9805         mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null,
9806                 WIFI_AGGREGATE_MULTICAST_ENABLED, null, mOnBatteryTimeBase);
9807         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase);
9808         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null, mOnBatteryTimeBase);
9809         for (int i=0; i<NUM_WIFI_STATES; i++) {
9810             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i, null,
9811                     mOnBatteryTimeBase);
9812         }
9813         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
9814             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i, null,
9815                     mOnBatteryTimeBase);
9816         }
9817         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
9818             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
9819                     mOnBatteryTimeBase);
9820         }
9821         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null, mOnBatteryTimeBase);
9822         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
9823             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i, null,
9824                 mOnBatteryTimeBase);
9825         }
9826         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
9827         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
9828         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
9829         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase);
9830         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
9831         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
9832         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
9833         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
9834         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
9835         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
9836         mOnBattery = mOnBatteryInternal = false;
9837         long uptime = mClocks.uptimeMillis() * 1000;
9838         long realtime = mClocks.elapsedRealtime() * 1000;
9839         initTimes(uptime, realtime);
9840         mStartPlatformVersion = mEndPlatformVersion = Build.ID;
9841         mDischargeStartLevel = 0;
9842         mDischargeUnplugLevel = 0;
9843         mDischargePlugLevel = -1;
9844         mDischargeCurrentLevel = 0;
9845         mCurrentBatteryLevel = 0;
9846         initDischarge();
9847         clearHistoryLocked();
9848         updateDailyDeadlineLocked();
9849         mPlatformIdleStateCallback = cb;
9850         mRailEnergyDataCallback = railStatsCb;
9851         mUserInfoProvider = userInfoProvider;
9852     }
9853 
9854     @UnsupportedAppUsage
BatteryStatsImpl(Parcel p)9855     public BatteryStatsImpl(Parcel p) {
9856         this(new SystemClocks(), p);
9857     }
9858 
BatteryStatsImpl(Clocks clocks, Parcel p)9859     public BatteryStatsImpl(Clocks clocks, Parcel p) {
9860         init(clocks);
9861         mStatsFile = null;
9862         mCheckinFile = null;
9863         mDailyFile = null;
9864         mHandler = null;
9865         mExternalSync = null;
9866         mConstants = new Constants(mHandler);
9867         clearHistoryLocked();
9868         mBatteryStatsHistory = new BatteryStatsHistory(this, mHistoryBuffer);
9869         readFromParcel(p);
9870         mPlatformIdleStateCallback = null;
9871         mRailEnergyDataCallback = null;
9872     }
9873 
setPowerProfileLocked(PowerProfile profile)9874     public void setPowerProfileLocked(PowerProfile profile) {
9875         mPowerProfile = profile;
9876 
9877         // We need to initialize the KernelCpuSpeedReaders to read from
9878         // the first cpu of each core. Once we have the PowerProfile, we have access to this
9879         // information.
9880         final int numClusters = mPowerProfile.getNumCpuClusters();
9881         mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
9882         int firstCpuOfCluster = 0;
9883         for (int i = 0; i < numClusters; i++) {
9884             final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
9885             mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
9886                     numSpeedSteps);
9887             firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
9888         }
9889 
9890         if (mEstimatedBatteryCapacity == -1) {
9891             // Initialize the estimated battery capacity to a known preset one.
9892             mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
9893         }
9894     }
9895 
setCallback(BatteryCallback cb)9896     public void setCallback(BatteryCallback cb) {
9897         mCallback = cb;
9898     }
9899 
setRadioScanningTimeoutLocked(long timeout)9900     public void setRadioScanningTimeoutLocked(long timeout) {
9901         if (mPhoneSignalScanningTimer != null) {
9902             mPhoneSignalScanningTimer.setTimeout(timeout);
9903         }
9904     }
9905 
setExternalStatsSyncLocked(ExternalStatsSync sync)9906     public void setExternalStatsSyncLocked(ExternalStatsSync sync) {
9907         mExternalSync = sync;
9908     }
9909 
updateDailyDeadlineLocked()9910     public void updateDailyDeadlineLocked() {
9911         // Get the current time.
9912         long currentTime = mDailyStartTime = System.currentTimeMillis();
9913         Calendar calDeadline = Calendar.getInstance();
9914         calDeadline.setTimeInMillis(currentTime);
9915 
9916         // Move time up to the next day, ranging from 1am to 3pm.
9917         calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
9918         calDeadline.set(Calendar.MILLISECOND, 0);
9919         calDeadline.set(Calendar.SECOND, 0);
9920         calDeadline.set(Calendar.MINUTE, 0);
9921         calDeadline.set(Calendar.HOUR_OF_DAY, 1);
9922         mNextMinDailyDeadline = calDeadline.getTimeInMillis();
9923         calDeadline.set(Calendar.HOUR_OF_DAY, 3);
9924         mNextMaxDailyDeadline = calDeadline.getTimeInMillis();
9925     }
9926 
recordDailyStatsIfNeededLocked(boolean settled)9927     public void recordDailyStatsIfNeededLocked(boolean settled) {
9928         long currentTime = System.currentTimeMillis();
9929         if (currentTime >= mNextMaxDailyDeadline) {
9930             recordDailyStatsLocked();
9931         } else if (settled && currentTime >= mNextMinDailyDeadline) {
9932             recordDailyStatsLocked();
9933         } else if (currentTime < (mDailyStartTime-(1000*60*60*24))) {
9934             recordDailyStatsLocked();
9935         }
9936     }
9937 
recordDailyStatsLocked()9938     public void recordDailyStatsLocked() {
9939         DailyItem item = new DailyItem();
9940         item.mStartTime = mDailyStartTime;
9941         item.mEndTime = System.currentTimeMillis();
9942         boolean hasData = false;
9943         if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
9944             hasData = true;
9945             item.mDischargeSteps = new LevelStepTracker(
9946                     mDailyDischargeStepTracker.mNumStepDurations,
9947                     mDailyDischargeStepTracker.mStepDurations);
9948         }
9949         if (mDailyChargeStepTracker.mNumStepDurations > 0) {
9950             hasData = true;
9951             item.mChargeSteps = new LevelStepTracker(
9952                     mDailyChargeStepTracker.mNumStepDurations,
9953                     mDailyChargeStepTracker.mStepDurations);
9954         }
9955         if (mDailyPackageChanges != null) {
9956             hasData = true;
9957             item.mPackageChanges = mDailyPackageChanges;
9958             mDailyPackageChanges = null;
9959         }
9960         mDailyDischargeStepTracker.init();
9961         mDailyChargeStepTracker.init();
9962         updateDailyDeadlineLocked();
9963 
9964         if (hasData) {
9965             final long startTime = SystemClock.uptimeMillis();
9966             mDailyItems.add(item);
9967             while (mDailyItems.size() > MAX_DAILY_ITEMS) {
9968                 mDailyItems.remove(0);
9969             }
9970             final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
9971             try {
9972                 XmlSerializer out = new FastXmlSerializer();
9973                 out.setOutput(memStream, StandardCharsets.UTF_8.name());
9974                 writeDailyItemsLocked(out);
9975                 final long initialTime = SystemClock.uptimeMillis() - startTime;
9976                 BackgroundThread.getHandler().post(new Runnable() {
9977                     @Override
9978                     public void run() {
9979                         synchronized (mCheckinFile) {
9980                             final long startTime2 = SystemClock.uptimeMillis();
9981                             FileOutputStream stream = null;
9982                             try {
9983                                 stream = mDailyFile.startWrite();
9984                                 memStream.writeTo(stream);
9985                                 stream.flush();
9986                                 mDailyFile.finishWrite(stream);
9987                                 com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
9988                                         "batterystats-daily",
9989                                         initialTime + SystemClock.uptimeMillis() - startTime2);
9990                             } catch (IOException e) {
9991                                 Slog.w("BatteryStats",
9992                                         "Error writing battery daily items", e);
9993                                 mDailyFile.failWrite(stream);
9994                             }
9995                         }
9996                     }
9997                 });
9998             } catch (IOException e) {
9999             }
10000         }
10001     }
10002 
writeDailyItemsLocked(XmlSerializer out)10003     private void writeDailyItemsLocked(XmlSerializer out) throws IOException {
10004         StringBuilder sb = new StringBuilder(64);
10005         out.startDocument(null, true);
10006         out.startTag(null, "daily-items");
10007         for (int i=0; i<mDailyItems.size(); i++) {
10008             final DailyItem dit = mDailyItems.get(i);
10009             out.startTag(null, "item");
10010             out.attribute(null, "start", Long.toString(dit.mStartTime));
10011             out.attribute(null, "end", Long.toString(dit.mEndTime));
10012             writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
10013             writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
10014             if (dit.mPackageChanges != null) {
10015                 for (int j=0; j<dit.mPackageChanges.size(); j++) {
10016                     PackageChange pc = dit.mPackageChanges.get(j);
10017                     if (pc.mUpdate) {
10018                         out.startTag(null, "upd");
10019                         out.attribute(null, "pkg", pc.mPackageName);
10020                         out.attribute(null, "ver", Long.toString(pc.mVersionCode));
10021                         out.endTag(null, "upd");
10022                     } else {
10023                         out.startTag(null, "rem");
10024                         out.attribute(null, "pkg", pc.mPackageName);
10025                         out.endTag(null, "rem");
10026                     }
10027                 }
10028             }
10029             out.endTag(null, "item");
10030         }
10031         out.endTag(null, "daily-items");
10032         out.endDocument();
10033     }
10034 
writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps, StringBuilder tmpBuilder)10035     private void writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps,
10036             StringBuilder tmpBuilder) throws IOException {
10037         if (steps != null) {
10038             out.startTag(null, tag);
10039             out.attribute(null, "n", Integer.toString(steps.mNumStepDurations));
10040             for (int i=0; i<steps.mNumStepDurations; i++) {
10041                 out.startTag(null, "s");
10042                 tmpBuilder.setLength(0);
10043                 steps.encodeEntryAt(i, tmpBuilder);
10044                 out.attribute(null, "v", tmpBuilder.toString());
10045                 out.endTag(null, "s");
10046             }
10047             out.endTag(null, tag);
10048         }
10049     }
10050 
readDailyStatsLocked()10051     public void readDailyStatsLocked() {
10052         Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
10053         mDailyItems.clear();
10054         FileInputStream stream;
10055         try {
10056             stream = mDailyFile.openRead();
10057         } catch (FileNotFoundException e) {
10058             return;
10059         }
10060         try {
10061             XmlPullParser parser = Xml.newPullParser();
10062             parser.setInput(stream, StandardCharsets.UTF_8.name());
10063             readDailyItemsLocked(parser);
10064         } catch (XmlPullParserException e) {
10065         } finally {
10066             try {
10067                 stream.close();
10068             } catch (IOException e) {
10069             }
10070         }
10071     }
10072 
readDailyItemsLocked(XmlPullParser parser)10073     private void readDailyItemsLocked(XmlPullParser parser) {
10074         try {
10075             int type;
10076             while ((type = parser.next()) != XmlPullParser.START_TAG
10077                     && type != XmlPullParser.END_DOCUMENT) {
10078                 ;
10079             }
10080 
10081             if (type != XmlPullParser.START_TAG) {
10082                 throw new IllegalStateException("no start tag found");
10083             }
10084 
10085             int outerDepth = parser.getDepth();
10086             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10087                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10088                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10089                     continue;
10090                 }
10091 
10092                 String tagName = parser.getName();
10093                 if (tagName.equals("item")) {
10094                     readDailyItemTagLocked(parser);
10095                 } else {
10096                     Slog.w(TAG, "Unknown element under <daily-items>: "
10097                             + parser.getName());
10098                     XmlUtils.skipCurrentTag(parser);
10099                 }
10100             }
10101 
10102         } catch (IllegalStateException e) {
10103             Slog.w(TAG, "Failed parsing daily " + e);
10104         } catch (NullPointerException e) {
10105             Slog.w(TAG, "Failed parsing daily " + e);
10106         } catch (NumberFormatException e) {
10107             Slog.w(TAG, "Failed parsing daily " + e);
10108         } catch (XmlPullParserException e) {
10109             Slog.w(TAG, "Failed parsing daily " + e);
10110         } catch (IOException e) {
10111             Slog.w(TAG, "Failed parsing daily " + e);
10112         } catch (IndexOutOfBoundsException e) {
10113             Slog.w(TAG, "Failed parsing daily " + e);
10114         }
10115     }
10116 
readDailyItemTagLocked(XmlPullParser parser)10117     void readDailyItemTagLocked(XmlPullParser parser) throws NumberFormatException,
10118             XmlPullParserException, IOException {
10119         DailyItem dit = new DailyItem();
10120         String attr = parser.getAttributeValue(null, "start");
10121         if (attr != null) {
10122             dit.mStartTime = Long.parseLong(attr);
10123         }
10124         attr = parser.getAttributeValue(null, "end");
10125         if (attr != null) {
10126             dit.mEndTime = Long.parseLong(attr);
10127         }
10128         int outerDepth = parser.getDepth();
10129         int type;
10130         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10131                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10132             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10133                 continue;
10134             }
10135 
10136             String tagName = parser.getName();
10137             if (tagName.equals("dis")) {
10138                 readDailyItemTagDetailsLocked(parser, dit, false, "dis");
10139             } else if (tagName.equals("chg")) {
10140                 readDailyItemTagDetailsLocked(parser, dit, true, "chg");
10141             } else if (tagName.equals("upd")) {
10142                 if (dit.mPackageChanges == null) {
10143                     dit.mPackageChanges = new ArrayList<>();
10144                 }
10145                 PackageChange pc = new PackageChange();
10146                 pc.mUpdate = true;
10147                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
10148                 String verStr = parser.getAttributeValue(null, "ver");
10149                 pc.mVersionCode = verStr != null ? Long.parseLong(verStr) : 0;
10150                 dit.mPackageChanges.add(pc);
10151                 XmlUtils.skipCurrentTag(parser);
10152             } else if (tagName.equals("rem")) {
10153                 if (dit.mPackageChanges == null) {
10154                     dit.mPackageChanges = new ArrayList<>();
10155                 }
10156                 PackageChange pc = new PackageChange();
10157                 pc.mUpdate = false;
10158                 pc.mPackageName = parser.getAttributeValue(null, "pkg");
10159                 dit.mPackageChanges.add(pc);
10160                 XmlUtils.skipCurrentTag(parser);
10161             } else {
10162                 Slog.w(TAG, "Unknown element under <item>: "
10163                         + parser.getName());
10164                 XmlUtils.skipCurrentTag(parser);
10165             }
10166         }
10167         mDailyItems.add(dit);
10168     }
10169 
readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge, String tag)10170     void readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge,
10171             String tag)
10172             throws NumberFormatException, XmlPullParserException, IOException {
10173         final String numAttr = parser.getAttributeValue(null, "n");
10174         if (numAttr == null) {
10175             Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
10176             XmlUtils.skipCurrentTag(parser);
10177             return;
10178         }
10179         final int num = Integer.parseInt(numAttr);
10180         LevelStepTracker steps = new LevelStepTracker(num);
10181         if (isCharge) {
10182             dit.mChargeSteps = steps;
10183         } else {
10184             dit.mDischargeSteps = steps;
10185         }
10186         int i = 0;
10187         int outerDepth = parser.getDepth();
10188         int type;
10189         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10190                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10191             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10192                 continue;
10193             }
10194 
10195             String tagName = parser.getName();
10196             if ("s".equals(tagName)) {
10197                 if (i < num) {
10198                     String valueAttr = parser.getAttributeValue(null, "v");
10199                     if (valueAttr != null) {
10200                         steps.decodeEntryAt(i, valueAttr);
10201                         i++;
10202                     }
10203                 }
10204             } else {
10205                 Slog.w(TAG, "Unknown element under <" + tag + ">: "
10206                         + parser.getName());
10207                 XmlUtils.skipCurrentTag(parser);
10208             }
10209         }
10210         steps.mNumStepDurations = i;
10211     }
10212 
10213     @Override
getDailyItemLocked(int daysAgo)10214     public DailyItem getDailyItemLocked(int daysAgo) {
10215         int index = mDailyItems.size()-1-daysAgo;
10216         return index >= 0 ? mDailyItems.get(index) : null;
10217     }
10218 
10219     @Override
getCurrentDailyStartTime()10220     public long getCurrentDailyStartTime() {
10221         return mDailyStartTime;
10222     }
10223 
10224     @Override
getNextMinDailyDeadline()10225     public long getNextMinDailyDeadline() {
10226         return mNextMinDailyDeadline;
10227     }
10228 
10229     @Override
getNextMaxDailyDeadline()10230     public long getNextMaxDailyDeadline() {
10231         return mNextMaxDailyDeadline;
10232     }
10233 
10234     @Override
startIteratingOldHistoryLocked()10235     public boolean startIteratingOldHistoryLocked() {
10236         if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
10237                 + " pos=" + mHistoryBuffer.dataPosition());
10238         if ((mHistoryIterator = mHistory) == null) {
10239             return false;
10240         }
10241         mHistoryBuffer.setDataPosition(0);
10242         mHistoryReadTmp.clear();
10243         mReadOverflow = false;
10244         mIteratingHistory = true;
10245         return true;
10246     }
10247 
10248     @Override
getNextOldHistoryLocked(HistoryItem out)10249     public boolean getNextOldHistoryLocked(HistoryItem out) {
10250         boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
10251         if (!end) {
10252             readHistoryDelta(mHistoryBuffer, mHistoryReadTmp);
10253             mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
10254         }
10255         HistoryItem cur = mHistoryIterator;
10256         if (cur == null) {
10257             if (!mReadOverflow && !end) {
10258                 Slog.w(TAG, "Old history ends before new history!");
10259             }
10260             return false;
10261         }
10262         out.setTo(cur);
10263         mHistoryIterator = cur.next;
10264         if (!mReadOverflow) {
10265             if (end) {
10266                 Slog.w(TAG, "New history ends before old history!");
10267             } else if (!out.same(mHistoryReadTmp)) {
10268                 PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
10269                 pw.println("Histories differ!");
10270                 pw.println("Old history:");
10271                 (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
10272                 pw.println("New history:");
10273                 (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
10274                         true);
10275                 pw.flush();
10276             }
10277         }
10278         return true;
10279     }
10280 
10281     @Override
finishIteratingOldHistoryLocked()10282     public void finishIteratingOldHistoryLocked() {
10283         mIteratingHistory = false;
10284         mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
10285         mHistoryIterator = null;
10286     }
10287 
getHistoryTotalSize()10288     public int getHistoryTotalSize() {
10289         return mConstants.MAX_HISTORY_BUFFER * mConstants.MAX_HISTORY_FILES;
10290     }
10291 
getHistoryUsedSize()10292     public int getHistoryUsedSize() {
10293         return mBatteryStatsHistory.getHistoryUsedSize();
10294     }
10295 
10296     @Override
10297     @UnsupportedAppUsage
startIteratingHistoryLocked()10298     public boolean startIteratingHistoryLocked() {
10299         mBatteryStatsHistory.startIteratingHistory();
10300         mReadOverflow = false;
10301         mIteratingHistory = true;
10302         mReadHistoryStrings = new String[mHistoryTagPool.size()];
10303         mReadHistoryUids = new int[mHistoryTagPool.size()];
10304         mReadHistoryChars = 0;
10305         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
10306             final HistoryTag tag = ent.getKey();
10307             final int idx = ent.getValue();
10308             mReadHistoryStrings[idx] = tag.string;
10309             mReadHistoryUids[idx] = tag.uid;
10310             mReadHistoryChars += tag.string.length() + 1;
10311         }
10312         return true;
10313     }
10314 
10315     @Override
getHistoryStringPoolSize()10316     public int getHistoryStringPoolSize() {
10317         return mReadHistoryStrings.length;
10318     }
10319 
10320     @Override
getHistoryStringPoolBytes()10321     public int getHistoryStringPoolBytes() {
10322         // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
10323         // Each string character is 2 bytes.
10324         return (mReadHistoryStrings.length * 12) + (mReadHistoryChars * 2);
10325     }
10326 
10327     @Override
getHistoryTagPoolString(int index)10328     public String getHistoryTagPoolString(int index) {
10329         return mReadHistoryStrings[index];
10330     }
10331 
10332     @Override
getHistoryTagPoolUid(int index)10333     public int getHistoryTagPoolUid(int index) {
10334         return mReadHistoryUids[index];
10335     }
10336 
10337     @Override
10338     @UnsupportedAppUsage
getNextHistoryLocked(HistoryItem out)10339     public boolean getNextHistoryLocked(HistoryItem out) {
10340         Parcel p = mBatteryStatsHistory.getNextParcel(out);
10341         if (p == null) {
10342             return false;
10343         }
10344         final long lastRealtime = out.time;
10345         final long lastWalltime = out.currentTime;
10346         readHistoryDelta(p, out);
10347         if (out.cmd != HistoryItem.CMD_CURRENT_TIME
10348                 && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
10349             out.currentTime = lastWalltime + (out.time - lastRealtime);
10350         }
10351         return true;
10352     }
10353 
10354     @Override
finishIteratingHistoryLocked()10355     public void finishIteratingHistoryLocked() {
10356         mBatteryStatsHistory.finishIteratingHistory();
10357         mIteratingHistory = false;
10358         mReadHistoryStrings = null;
10359         mReadHistoryUids = null;
10360     }
10361 
10362     @Override
getHistoryBaseTime()10363     public long getHistoryBaseTime() {
10364         return mHistoryBaseTime;
10365     }
10366 
10367     @Override
getStartCount()10368     public int getStartCount() {
10369         return mStartCount;
10370     }
10371 
10372     @UnsupportedAppUsage
isOnBattery()10373     public boolean isOnBattery() {
10374         return mOnBattery;
10375     }
10376 
isCharging()10377     public boolean isCharging() {
10378         return mCharging;
10379     }
10380 
isScreenOn(int state)10381     public boolean isScreenOn(int state) {
10382         return state == Display.STATE_ON || state == Display.STATE_VR
10383             || state == Display.STATE_ON_SUSPEND;
10384     }
10385 
isScreenOff(int state)10386     public boolean isScreenOff(int state) {
10387         return state == Display.STATE_OFF;
10388     }
10389 
isScreenDoze(int state)10390     public boolean isScreenDoze(int state) {
10391         return state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND;
10392     }
10393 
initTimes(long uptime, long realtime)10394     void initTimes(long uptime, long realtime) {
10395         mStartClockTime = System.currentTimeMillis();
10396         mOnBatteryTimeBase.init(uptime, realtime);
10397         mOnBatteryScreenOffTimeBase.init(uptime, realtime);
10398         mRealtime = 0;
10399         mUptime = 0;
10400         mRealtimeStart = realtime;
10401         mUptimeStart = uptime;
10402     }
10403 
initDischarge()10404     void initDischarge() {
10405         mLowDischargeAmountSinceCharge = 0;
10406         mHighDischargeAmountSinceCharge = 0;
10407         mDischargeAmountScreenOn = 0;
10408         mDischargeAmountScreenOnSinceCharge = 0;
10409         mDischargeAmountScreenOff = 0;
10410         mDischargeAmountScreenOffSinceCharge = 0;
10411         mDischargeAmountScreenDoze = 0;
10412         mDischargeAmountScreenDozeSinceCharge = 0;
10413         mDischargeStepTracker.init();
10414         mChargeStepTracker.init();
10415         mDischargeScreenOffCounter.reset(false);
10416         mDischargeScreenDozeCounter.reset(false);
10417         mDischargeLightDozeCounter.reset(false);
10418         mDischargeDeepDozeCounter.reset(false);
10419         mDischargeCounter.reset(false);
10420     }
10421 
resetAllStatsCmdLocked()10422     public void resetAllStatsCmdLocked() {
10423         resetAllStatsLocked();
10424         final long mSecUptime = mClocks.uptimeMillis();
10425         long uptime = mSecUptime * 1000;
10426         long mSecRealtime = mClocks.elapsedRealtime();
10427         long realtime = mSecRealtime * 1000;
10428         mDischargeStartLevel = mHistoryCur.batteryLevel;
10429         pullPendingStateUpdatesLocked();
10430         addHistoryRecordLocked(mSecRealtime, mSecUptime);
10431         mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
10432                 = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
10433         mOnBatteryTimeBase.reset(uptime, realtime);
10434         mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
10435         if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
10436             if (isScreenOn(mScreenState)) {
10437                 mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
10438                 mDischargeScreenDozeUnplugLevel = 0;
10439                 mDischargeScreenOffUnplugLevel = 0;
10440             } else if (isScreenDoze(mScreenState)) {
10441                 mDischargeScreenOnUnplugLevel = 0;
10442                 mDischargeScreenDozeUnplugLevel = mHistoryCur.batteryLevel;
10443                 mDischargeScreenOffUnplugLevel = 0;
10444             } else {
10445                 mDischargeScreenOnUnplugLevel = 0;
10446                 mDischargeScreenDozeUnplugLevel = 0;
10447                 mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
10448             }
10449             mDischargeAmountScreenOn = 0;
10450             mDischargeAmountScreenOff = 0;
10451             mDischargeAmountScreenDoze = 0;
10452         }
10453         initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
10454     }
10455 
resetAllStatsLocked()10456     private void resetAllStatsLocked() {
10457         final long uptimeMillis = mClocks.uptimeMillis();
10458         final long elapsedRealtimeMillis = mClocks.elapsedRealtime();
10459         mStartCount = 0;
10460         initTimes(uptimeMillis * 1000, elapsedRealtimeMillis * 1000);
10461         mScreenOnTimer.reset(false);
10462         mScreenDozeTimer.reset(false);
10463         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10464             mScreenBrightnessTimer[i].reset(false);
10465         }
10466 
10467         if (mPowerProfile != null) {
10468             mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
10469         } else {
10470             mEstimatedBatteryCapacity = -1;
10471         }
10472         mMinLearnedBatteryCapacity = -1;
10473         mMaxLearnedBatteryCapacity = -1;
10474         mInteractiveTimer.reset(false);
10475         mPowerSaveModeEnabledTimer.reset(false);
10476         mLastIdleTimeStart = elapsedRealtimeMillis;
10477         mLongestLightIdleTime = 0;
10478         mLongestFullIdleTime = 0;
10479         mDeviceIdleModeLightTimer.reset(false);
10480         mDeviceIdleModeFullTimer.reset(false);
10481         mDeviceLightIdlingTimer.reset(false);
10482         mDeviceIdlingTimer.reset(false);
10483         mPhoneOnTimer.reset(false);
10484         mAudioOnTimer.reset(false);
10485         mVideoOnTimer.reset(false);
10486         mFlashlightOnTimer.reset(false);
10487         mCameraOnTimer.reset(false);
10488         mBluetoothScanTimer.reset(false);
10489         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
10490             mPhoneSignalStrengthsTimer[i].reset(false);
10491         }
10492         mPhoneSignalScanningTimer.reset(false);
10493         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10494             mPhoneDataConnectionsTimer[i].reset(false);
10495         }
10496         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10497             mNetworkByteActivityCounters[i].reset(false);
10498             mNetworkPacketActivityCounters[i].reset(false);
10499         }
10500         mMobileRadioActiveTimer.reset(false);
10501         mMobileRadioActivePerAppTimer.reset(false);
10502         mMobileRadioActiveAdjustedTime.reset(false);
10503         mMobileRadioActiveUnknownTime.reset(false);
10504         mMobileRadioActiveUnknownCount.reset(false);
10505         mWifiOnTimer.reset(false);
10506         mGlobalWifiRunningTimer.reset(false);
10507         for (int i=0; i<NUM_WIFI_STATES; i++) {
10508             mWifiStateTimer[i].reset(false);
10509         }
10510         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10511             mWifiSupplStateTimer[i].reset(false);
10512         }
10513         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10514             mWifiSignalStrengthsTimer[i].reset(false);
10515         }
10516         mWifiMulticastWakelockTimer.reset(false);
10517         mWifiActiveTimer.reset(false);
10518         mWifiActivity.reset(false);
10519         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
10520             mGpsSignalQualityTimer[i].reset(false);
10521         }
10522         mBluetoothActivity.reset(false);
10523         mModemActivity.reset(false);
10524         mNumConnectivityChange = 0;
10525 
10526         for (int i=0; i<mUidStats.size(); i++) {
10527             if (mUidStats.valueAt(i).reset(uptimeMillis * 1000, elapsedRealtimeMillis * 1000)) {
10528                 mUidStats.valueAt(i).detachFromTimeBase();
10529                 mUidStats.remove(mUidStats.keyAt(i));
10530                 i--;
10531             }
10532         }
10533 
10534         if (mRpmStats.size() > 0) {
10535             for (SamplingTimer timer : mRpmStats.values()) {
10536                 mOnBatteryTimeBase.remove(timer);
10537             }
10538             mRpmStats.clear();
10539         }
10540         if (mScreenOffRpmStats.size() > 0) {
10541             for (SamplingTimer timer : mScreenOffRpmStats.values()) {
10542                 mOnBatteryScreenOffTimeBase.remove(timer);
10543             }
10544             mScreenOffRpmStats.clear();
10545         }
10546 
10547         if (mKernelWakelockStats.size() > 0) {
10548             for (SamplingTimer timer : mKernelWakelockStats.values()) {
10549                 mOnBatteryScreenOffTimeBase.remove(timer);
10550             }
10551             mKernelWakelockStats.clear();
10552         }
10553 
10554         if (mKernelMemoryStats.size() > 0) {
10555             for (int i = 0; i < mKernelMemoryStats.size(); i++) {
10556                 mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i));
10557             }
10558             mKernelMemoryStats.clear();
10559         }
10560 
10561         if (mWakeupReasonStats.size() > 0) {
10562             for (SamplingTimer timer : mWakeupReasonStats.values()) {
10563                 mOnBatteryTimeBase.remove(timer);
10564             }
10565             mWakeupReasonStats.clear();
10566         }
10567 
10568         mTmpRailStats.reset();
10569 
10570         mLastHistoryStepDetails = null;
10571         mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
10572         mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
10573         mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
10574         mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
10575         mLastStepStatUserTime = mCurStepStatUserTime = 0;
10576         mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
10577         mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
10578         mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
10579         mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
10580         mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
10581 
10582         mNumAllUidCpuTimeReads = 0;
10583         mNumUidsRemoved = 0;
10584 
10585         initDischarge();
10586 
10587         clearHistoryLocked();
10588         mBatteryStatsHistory.resetAllFiles();
10589 
10590         mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
10591     }
10592 
initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs)10593     private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
10594         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
10595             if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
10596                 // Not recording process starts/stops.
10597                 continue;
10598             }
10599             HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
10600             if (active == null) {
10601                 continue;
10602             }
10603             for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
10604                 SparseIntArray uids = ent.getValue();
10605                 for (int j=0; j<uids.size(); j++) {
10606                     addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
10607                             uids.keyAt(j));
10608                 }
10609             }
10610         }
10611     }
10612 
updateDischargeScreenLevelsLocked(int oldState, int newState)10613     void updateDischargeScreenLevelsLocked(int oldState, int newState) {
10614         updateOldDischargeScreenLevelLocked(oldState);
10615         updateNewDischargeScreenLevelLocked(newState);
10616     }
10617 
updateOldDischargeScreenLevelLocked(int state)10618     private void updateOldDischargeScreenLevelLocked(int state) {
10619         if (isScreenOn(state)) {
10620             int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
10621             if (diff > 0) {
10622                 mDischargeAmountScreenOn += diff;
10623                 mDischargeAmountScreenOnSinceCharge += diff;
10624             }
10625         } else if (isScreenDoze(state)) {
10626             int diff = mDischargeScreenDozeUnplugLevel - mDischargeCurrentLevel;
10627             if (diff > 0) {
10628                 mDischargeAmountScreenDoze += diff;
10629                 mDischargeAmountScreenDozeSinceCharge += diff;
10630             }
10631         } else if (isScreenOff(state)){
10632             int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
10633             if (diff > 0) {
10634                 mDischargeAmountScreenOff += diff;
10635                 mDischargeAmountScreenOffSinceCharge += diff;
10636             }
10637         }
10638     }
10639 
updateNewDischargeScreenLevelLocked(int state)10640     private void updateNewDischargeScreenLevelLocked(int state) {
10641         if (isScreenOn(state)) {
10642             mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
10643             mDischargeScreenOffUnplugLevel = 0;
10644             mDischargeScreenDozeUnplugLevel = 0;
10645         } else if (isScreenDoze(state)){
10646             mDischargeScreenOnUnplugLevel = 0;
10647             mDischargeScreenDozeUnplugLevel = mDischargeCurrentLevel;
10648             mDischargeScreenOffUnplugLevel = 0;
10649         } else if (isScreenOff(state)) {
10650             mDischargeScreenOnUnplugLevel = 0;
10651             mDischargeScreenDozeUnplugLevel = 0;
10652             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
10653         }
10654     }
10655 
pullPendingStateUpdatesLocked()10656     public void pullPendingStateUpdatesLocked() {
10657         if (mOnBatteryInternal) {
10658             updateDischargeScreenLevelsLocked(mScreenState, mScreenState);
10659         }
10660     }
10661 
10662     private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6);
10663 
10664     private final Object mWifiNetworkLock = new Object();
10665 
10666     @GuardedBy("mWifiNetworkLock")
10667     private String[] mWifiIfaces = EmptyArray.STRING;
10668 
10669     @GuardedBy("mWifiNetworkLock")
10670     private NetworkStats mLastWifiNetworkStats = new NetworkStats(0, -1);
10671 
10672     private final Object mModemNetworkLock = new Object();
10673 
10674     @GuardedBy("mModemNetworkLock")
10675     private String[] mModemIfaces = EmptyArray.STRING;
10676 
10677     @GuardedBy("mModemNetworkLock")
10678     private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
10679 
readNetworkStatsLocked(String[] ifaces)10680     private NetworkStats readNetworkStatsLocked(String[] ifaces) {
10681         try {
10682             if (!ArrayUtils.isEmpty(ifaces)) {
10683                 INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
10684                         ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
10685                 if (statsService != null) {
10686                     return statsService.getDetailedUidStats(ifaces);
10687                 } else {
10688                     Slog.e(TAG, "Failed to get networkStatsService ");
10689                 }
10690             }
10691         } catch (RemoteException e) {
10692             Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces) + e);
10693         }
10694         return null;
10695     }
10696 
10697    /**
10698      * Distribute WiFi energy info and network traffic to apps.
10699      * @param info The energy information from the WiFi controller.
10700      */
updateWifiState(@ullable final WifiActivityEnergyInfo info)10701     public void updateWifiState(@Nullable final WifiActivityEnergyInfo info) {
10702         if (DEBUG_ENERGY) {
10703             Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
10704         }
10705 
10706         // Grab a separate lock to acquire the network stats, which may do I/O.
10707         NetworkStats delta = null;
10708         synchronized (mWifiNetworkLock) {
10709             final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces);
10710             if (latestStats != null) {
10711                 delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null,
10712                         mNetworkStatsPool.acquire());
10713                 mNetworkStatsPool.release(mLastWifiNetworkStats);
10714                 mLastWifiNetworkStats = latestStats;
10715             }
10716         }
10717 
10718         synchronized (this) {
10719             if (!mOnBatteryInternal) {
10720                 if (delta != null) {
10721                     mNetworkStatsPool.release(delta);
10722                 }
10723                 return;
10724             }
10725 
10726             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
10727             SparseLongArray rxPackets = new SparseLongArray();
10728             SparseLongArray txPackets = new SparseLongArray();
10729             long totalTxPackets = 0;
10730             long totalRxPackets = 0;
10731             if (delta != null) {
10732                 NetworkStats.Entry entry = new NetworkStats.Entry();
10733                 final int size = delta.size();
10734                 for (int i = 0; i < size; i++) {
10735                     entry = delta.getValues(i, entry);
10736 
10737                     if (DEBUG_ENERGY) {
10738                         Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
10739                                 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
10740                                 + " txPackets=" + entry.txPackets);
10741                     }
10742 
10743                     if (entry.rxBytes == 0 && entry.txBytes == 0) {
10744                         // Skip the lookup below since there is no work to do.
10745                         continue;
10746                     }
10747 
10748                     final Uid u = getUidStatsLocked(mapUid(entry.uid));
10749                     if (entry.rxBytes != 0) {
10750                         u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
10751                                 entry.rxPackets);
10752                         if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
10753                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
10754                                     entry.rxPackets);
10755                         }
10756                         mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
10757                                 entry.rxBytes);
10758                         mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
10759                                 entry.rxPackets);
10760 
10761                         rxPackets.put(u.getUid(), entry.rxPackets);
10762 
10763                         // Sum the total number of packets so that the Rx Power can
10764                         // be evenly distributed amongst the apps.
10765                         totalRxPackets += entry.rxPackets;
10766                     }
10767 
10768                     if (entry.txBytes != 0) {
10769                         u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
10770                                 entry.txPackets);
10771                         if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
10772                             u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
10773                                     entry.txPackets);
10774                         }
10775                         mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
10776                                 entry.txBytes);
10777                         mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
10778                                 entry.txPackets);
10779 
10780                         txPackets.put(u.getUid(), entry.txPackets);
10781 
10782                         // Sum the total number of packets so that the Tx Power can
10783                         // be evenly distributed amongst the apps.
10784                         totalTxPackets += entry.txPackets;
10785                     }
10786                 }
10787                 mNetworkStatsPool.release(delta);
10788                 delta = null;
10789             }
10790 
10791             if (info != null) {
10792                 mHasWifiReporting = true;
10793 
10794                 // Measured in mAms
10795                 final long txTimeMs = info.getControllerTxTimeMillis();
10796                 final long rxTimeMs = info.getControllerRxTimeMillis();
10797                 final long scanTimeMs = info.getControllerScanTimeMillis();
10798                 final long idleTimeMs = info.getControllerIdleTimeMillis();
10799                 final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
10800 
10801                 long leftOverRxTimeMs = rxTimeMs;
10802                 long leftOverTxTimeMs = txTimeMs;
10803 
10804                 if (DEBUG_ENERGY) {
10805                     Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
10806                     Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
10807                     Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
10808                     Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
10809                     Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
10810                     Slog.d(TAG, "  Scan Time:  " + scanTimeMs + " ms");
10811                 }
10812 
10813                 long totalWifiLockTimeMs = 0;
10814                 long totalScanTimeMs = 0;
10815 
10816                 // On the first pass, collect some totals so that we can normalize power
10817                 // calculations if we need to.
10818                 final int uidStatsSize = mUidStats.size();
10819                 for (int i = 0; i < uidStatsSize; i++) {
10820                     final Uid uid = mUidStats.valueAt(i);
10821 
10822                     // Sum the total scan power for all apps.
10823                     totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
10824                             elapsedRealtimeMs * 1000) / 1000;
10825 
10826                     // Sum the total time holding wifi lock for all apps.
10827                     totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
10828                             elapsedRealtimeMs * 1000) / 1000;
10829                 }
10830 
10831                 if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
10832                     Slog.d(TAG,
10833                             "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
10834                                     + rxTimeMs + " ms). Normalizing scan time.");
10835                 }
10836                 if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
10837                     Slog.d(TAG,
10838                             "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
10839                                     + txTimeMs + " ms). Normalizing scan time.");
10840                 }
10841 
10842                 // Actually assign and distribute power usage to apps.
10843                 for (int i = 0; i < uidStatsSize; i++) {
10844                     final Uid uid = mUidStats.valueAt(i);
10845 
10846                     long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
10847                             elapsedRealtimeMs * 1000) / 1000;
10848                     if (scanTimeSinceMarkMs > 0) {
10849                         // Set the new mark so that next time we get new data since this point.
10850                         uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
10851 
10852                         long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
10853                         long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
10854 
10855                         // Our total scan time is more than the reported Tx/Rx time.
10856                         // This is possible because the cost of a scan is approximate.
10857                         // Let's normalize the result so that we evenly blame each app
10858                         // scanning.
10859                         //
10860                         // This means that we may have apps that transmitted/received packets not be
10861                         // blamed for this, but this is fine as scans are relatively more expensive.
10862                         if (totalScanTimeMs > rxTimeMs) {
10863                             scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
10864                                     totalScanTimeMs;
10865                         }
10866                         if (totalScanTimeMs > txTimeMs) {
10867                             scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
10868                                     totalScanTimeMs;
10869                         }
10870 
10871                         if (DEBUG_ENERGY) {
10872                             Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
10873                                     + scanRxTimeSinceMarkMs + " ms  Tx:"
10874                                     + scanTxTimeSinceMarkMs + " ms)");
10875                         }
10876 
10877                         ControllerActivityCounterImpl activityCounter =
10878                                 uid.getOrCreateWifiControllerActivityLocked();
10879                         activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
10880                         activityCounter.getTxTimeCounters()[0].addCountLocked(
10881                                 scanTxTimeSinceMarkMs);
10882                         leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
10883                         leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
10884                     }
10885 
10886                     // Distribute evenly the power consumed while Idle to each app holding a WiFi
10887                     // lock.
10888                     final long wifiLockTimeSinceMarkMs =
10889                             uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
10890                                     elapsedRealtimeMs * 1000) / 1000;
10891                     if (wifiLockTimeSinceMarkMs > 0) {
10892                         // Set the new mark so that next time we get new data since this point.
10893                         uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
10894 
10895                         final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
10896                                 / totalWifiLockTimeMs;
10897                         if (DEBUG_ENERGY) {
10898                             Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
10899                                     + myIdleTimeMs + " ms");
10900                         }
10901                         uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
10902                                 .addCountLocked(myIdleTimeMs);
10903                     }
10904                 }
10905 
10906                 if (DEBUG_ENERGY) {
10907                     Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
10908                     Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
10909                 }
10910 
10911                 // Distribute the remaining Tx power appropriately between all apps that transmitted
10912                 // packets.
10913                 for (int i = 0; i < txPackets.size(); i++) {
10914                     final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
10915                     final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
10916                             / totalTxPackets;
10917                     if (DEBUG_ENERGY) {
10918                         Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
10919                     }
10920                     uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
10921                             .addCountLocked(myTxTimeMs);
10922                 }
10923 
10924                 // Distribute the remaining Rx power appropriately between all apps that received
10925                 // packets.
10926                 for (int i = 0; i < rxPackets.size(); i++) {
10927                     final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
10928                     final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
10929                             / totalRxPackets;
10930                     if (DEBUG_ENERGY) {
10931                         Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
10932                     }
10933                     uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
10934                             .addCountLocked(myRxTimeMs);
10935                 }
10936 
10937                 // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
10938 
10939 
10940                 // Update WiFi controller stats.
10941                 mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
10942                 mWifiActivity.getTxTimeCounters()[0].addCountLocked(
10943                         info.getControllerTxTimeMillis());
10944                 mWifiActivity.getScanTimeCounter().addCountLocked(
10945                     info.getControllerScanTimeMillis());
10946                 mWifiActivity.getIdleTimeCounter().addCountLocked(
10947                         info.getControllerIdleTimeMillis());
10948 
10949                 // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
10950                 final double opVolt = mPowerProfile.getAveragePower(
10951                         PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
10952                 if (opVolt != 0) {
10953                     // We store the power drain as mAms.
10954                     mWifiActivity.getPowerCounter().addCountLocked(
10955                             (long) (info.getControllerEnergyUsed() / opVolt));
10956                 }
10957                 // Converting uWs to mAms.
10958                 // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
10959                 long monitoredRailChargeConsumedMaMs =
10960                         (long) (mTmpRailStats.getWifiTotalEnergyUseduWs() / opVolt);
10961                 mWifiActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
10962                         monitoredRailChargeConsumedMaMs);
10963                 mHistoryCur.wifiRailChargeMah +=
10964                         (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
10965                 addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
10966                 mTmpRailStats.resetWifiTotalEnergyUsed();
10967             }
10968         }
10969     }
10970 
10971     private ModemActivityInfo mLastModemActivityInfo =
10972             new ModemActivityInfo(0, 0, 0, new int[0], 0, 0);
10973 
getDeltaModemActivityInfo(ModemActivityInfo activityInfo)10974     private ModemActivityInfo getDeltaModemActivityInfo(ModemActivityInfo activityInfo) {
10975         if (activityInfo == null) {
10976             return null;
10977         }
10978         int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
10979         for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) {
10980             txTimeMs[i] = activityInfo.getTxTimeMillis()[i]
10981                     - mLastModemActivityInfo.getTxTimeMillis()[i];
10982         }
10983         ModemActivityInfo deltaInfo = new ModemActivityInfo(activityInfo.getTimestamp(),
10984                 activityInfo.getSleepTimeMillis() - mLastModemActivityInfo.getSleepTimeMillis(),
10985                 activityInfo.getIdleTimeMillis() - mLastModemActivityInfo.getIdleTimeMillis(),
10986                 txTimeMs,
10987                 activityInfo.getRxTimeMillis() - mLastModemActivityInfo.getRxTimeMillis(),
10988                 activityInfo.getEnergyUsed() - mLastModemActivityInfo.getEnergyUsed());
10989         mLastModemActivityInfo = activityInfo;
10990         return deltaInfo;
10991     }
10992 
10993     /**
10994      * Distribute Cell radio energy info and network traffic to apps.
10995      */
updateMobileRadioState(@ullable final ModemActivityInfo activityInfo)10996     public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo) {
10997         if (DEBUG_ENERGY) {
10998             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
10999         }
11000         ModemActivityInfo deltaInfo = getDeltaModemActivityInfo(activityInfo);
11001 
11002         // Add modem tx power to history.
11003         addModemTxPowerToHistory(deltaInfo);
11004 
11005         // Grab a separate lock to acquire the network stats, which may do I/O.
11006         NetworkStats delta = null;
11007         synchronized (mModemNetworkLock) {
11008             final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces);
11009             if (latestStats != null) {
11010                 delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null,
11011                         mNetworkStatsPool.acquire());
11012                 mNetworkStatsPool.release(mLastModemNetworkStats);
11013                 mLastModemNetworkStats = latestStats;
11014             }
11015         }
11016 
11017         synchronized (this) {
11018             if (!mOnBatteryInternal) {
11019                 if (delta != null) {
11020                     mNetworkStatsPool.release(delta);
11021                 }
11022                 return;
11023             }
11024 
11025             if (deltaInfo != null) {
11026                 mHasModemReporting = true;
11027                 mModemActivity.getIdleTimeCounter().addCountLocked(
11028                         deltaInfo.getIdleTimeMillis());
11029                 mModemActivity.getSleepTimeCounter().addCountLocked(
11030                         deltaInfo.getSleepTimeMillis());
11031                 mModemActivity.getRxTimeCounter().addCountLocked(deltaInfo.getRxTimeMillis());
11032                 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
11033                     mModemActivity.getTxTimeCounters()[lvl]
11034                         .addCountLocked(deltaInfo.getTxTimeMillis()[lvl]);
11035                 }
11036 
11037                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11038                 final double opVolt = mPowerProfile.getAveragePower(
11039                     PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11040                 if (opVolt != 0) {
11041                     double energyUsed =
11042                             deltaInfo.getSleepTimeMillis() *
11043                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
11044                             + deltaInfo.getIdleTimeMillis() *
11045                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
11046                             + deltaInfo.getRxTimeMillis() *
11047                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
11048                     int[] txTimeMs = deltaInfo.getTxTimeMillis();
11049                     for (int i = 0; i < Math.min(txTimeMs.length,
11050                             SignalStrength.NUM_SIGNAL_STRENGTH_BINS); i++) {
11051                         energyUsed += txTimeMs[i] * mPowerProfile.getAveragePower(
11052                                 PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
11053                     }
11054 
11055                     // We store the power drain as mAms.
11056                     mModemActivity.getPowerCounter().addCountLocked((long) energyUsed);
11057                     // Converting uWs to mAms.
11058                     // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
11059                     long monitoredRailChargeConsumedMaMs =
11060                             (long) (mTmpRailStats.getCellularTotalEnergyUseduWs() / opVolt);
11061                     mModemActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
11062                             monitoredRailChargeConsumedMaMs);
11063                     mHistoryCur.modemRailChargeMah +=
11064                             (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
11065                     addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
11066                     mTmpRailStats.resetCellularTotalEnergyUsed();
11067                 }
11068             }
11069             final long elapsedRealtimeMs = mClocks.elapsedRealtime();
11070             long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
11071                     elapsedRealtimeMs * 1000);
11072             mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
11073 
11074             long totalRxPackets = 0;
11075             long totalTxPackets = 0;
11076             if (delta != null) {
11077                 NetworkStats.Entry entry = new NetworkStats.Entry();
11078                 final int size = delta.size();
11079                 for (int i = 0; i < size; i++) {
11080                     entry = delta.getValues(i, entry);
11081                     if (entry.rxPackets == 0 && entry.txPackets == 0) {
11082                         continue;
11083                     }
11084 
11085                     if (DEBUG_ENERGY) {
11086                         Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
11087                                 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
11088                                 + " txPackets=" + entry.txPackets);
11089                     }
11090 
11091                     totalRxPackets += entry.rxPackets;
11092                     totalTxPackets += entry.txPackets;
11093 
11094                     final Uid u = getUidStatsLocked(mapUid(entry.uid));
11095                     u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
11096                             entry.rxPackets);
11097                     u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
11098                             entry.txPackets);
11099                     if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11100                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
11101                                 entry.rxBytes, entry.rxPackets);
11102                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
11103                                 entry.txBytes, entry.txPackets);
11104                     }
11105 
11106                     mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
11107                             entry.rxBytes);
11108                     mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
11109                             entry.txBytes);
11110                     mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
11111                             entry.rxPackets);
11112                     mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
11113                             entry.txPackets);
11114                 }
11115 
11116                 // Now distribute proportional blame to the apps that did networking.
11117                 long totalPackets = totalRxPackets + totalTxPackets;
11118                 if (totalPackets > 0) {
11119                     for (int i = 0; i < size; i++) {
11120                         entry = delta.getValues(i, entry);
11121                         if (entry.rxPackets == 0 && entry.txPackets == 0) {
11122                             continue;
11123                         }
11124 
11125                         final Uid u = getUidStatsLocked(mapUid(entry.uid));
11126 
11127                         // Distribute total radio active time in to this app.
11128                         final long appPackets = entry.rxPackets + entry.txPackets;
11129                         final long appRadioTime = (radioTime * appPackets) / totalPackets;
11130                         u.noteMobileRadioActiveTimeLocked(appRadioTime);
11131 
11132                         // Remove this app from the totals, so that we don't lose any time
11133                         // due to rounding.
11134                         radioTime -= appRadioTime;
11135                         totalPackets -= appPackets;
11136 
11137                         if (deltaInfo != null) {
11138                             ControllerActivityCounterImpl activityCounter =
11139                                     u.getOrCreateModemControllerActivityLocked();
11140                             if (totalRxPackets > 0 && entry.rxPackets > 0) {
11141                                 final long rxMs = (entry.rxPackets * deltaInfo.getRxTimeMillis())
11142                                         / totalRxPackets;
11143                                 activityCounter.getRxTimeCounter().addCountLocked(rxMs);
11144                             }
11145 
11146                             if (totalTxPackets > 0 && entry.txPackets > 0) {
11147                                 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
11148                                     long txMs =
11149                                             entry.txPackets * deltaInfo.getTxTimeMillis()[lvl];
11150                                     txMs /= totalTxPackets;
11151                                     activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
11152                                 }
11153                             }
11154                         }
11155                     }
11156                 }
11157 
11158                 if (radioTime > 0) {
11159                     // Whoops, there is some radio time we can't blame on an app!
11160                     mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
11161                     mMobileRadioActiveUnknownCount.addCountLocked(1);
11162                 }
11163 
11164                 mNetworkStatsPool.release(delta);
11165                 delta = null;
11166             }
11167         }
11168     }
11169 
11170     /**
11171      * Add modem tx power to history
11172      * Device is said to be in high cellular transmit power when it has spent most of the transmit
11173      * time at the highest power level.
11174      * @param activityInfo
11175      */
addModemTxPowerToHistory(final ModemActivityInfo activityInfo)11176     private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo) {
11177         if (activityInfo == null) {
11178             return;
11179         }
11180         int[] txTimeMs = activityInfo.getTxTimeMillis();
11181         if (txTimeMs == null || txTimeMs.length != ModemActivityInfo.TX_POWER_LEVELS) {
11182             return;
11183         }
11184         final long elapsedRealtime = mClocks.elapsedRealtime();
11185         final long uptime = mClocks.uptimeMillis();
11186         int levelMaxTimeSpent = 0;
11187         for (int i = 1; i < txTimeMs.length; i++) {
11188             if (txTimeMs[i] > txTimeMs[levelMaxTimeSpent]) {
11189                 levelMaxTimeSpent = i;
11190             }
11191         }
11192         if (levelMaxTimeSpent == ModemActivityInfo.TX_POWER_LEVELS - 1) {
11193             if (!mIsCellularTxPowerHigh) {
11194                 mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
11195                 addHistoryRecordLocked(elapsedRealtime, uptime);
11196                 mIsCellularTxPowerHigh = true;
11197             }
11198             return;
11199         }
11200         if (mIsCellularTxPowerHigh) {
11201             mHistoryCur.states2 &= ~HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
11202             addHistoryRecordLocked(elapsedRealtime, uptime);
11203             mIsCellularTxPowerHigh = false;
11204         }
11205         return;
11206     }
11207 
11208     private final class BluetoothActivityInfoCache {
11209         long idleTimeMs;
11210         long rxTimeMs;
11211         long txTimeMs;
11212         long energy;
11213 
11214         SparseLongArray uidRxBytes = new SparseLongArray();
11215         SparseLongArray uidTxBytes = new SparseLongArray();
11216 
set(BluetoothActivityEnergyInfo info)11217         void set(BluetoothActivityEnergyInfo info) {
11218             idleTimeMs = info.getControllerIdleTimeMillis();
11219             rxTimeMs = info.getControllerRxTimeMillis();
11220             txTimeMs = info.getControllerTxTimeMillis();
11221             energy = info.getControllerEnergyUsed();
11222             if (info.getUidTraffic() != null) {
11223                 for (UidTraffic traffic : info.getUidTraffic()) {
11224                     uidRxBytes.put(traffic.getUid(), traffic.getRxBytes());
11225                     uidTxBytes.put(traffic.getUid(), traffic.getTxBytes());
11226                 }
11227             }
11228         }
11229     }
11230 
11231     private final BluetoothActivityInfoCache mLastBluetoothActivityInfo
11232             = new BluetoothActivityInfoCache();
11233 
11234     /**
11235      * Distribute Bluetooth energy info and network traffic to apps.
11236      *
11237      * @param info The energy information from the bluetooth controller.
11238      */
updateBluetoothStateLocked(@ullable final BluetoothActivityEnergyInfo info)11239     public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
11240         if (DEBUG_ENERGY) {
11241             Slog.d(TAG, "Updating bluetooth stats: " + info);
11242         }
11243 
11244         if (info == null || !mOnBatteryInternal) {
11245             return;
11246         }
11247 
11248         mHasBluetoothReporting = true;
11249 
11250         final long elapsedRealtimeMs = mClocks.elapsedRealtime();
11251         final long rxTimeMs =
11252                 info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs;
11253         final long txTimeMs =
11254                 info.getControllerTxTimeMillis() - mLastBluetoothActivityInfo.txTimeMs;
11255         final long idleTimeMs =
11256                 info.getControllerIdleTimeMillis() - mLastBluetoothActivityInfo.idleTimeMs;
11257 
11258         if (DEBUG_ENERGY) {
11259             Slog.d(TAG, "------ BEGIN BLE power blaming ------");
11260             Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
11261             Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
11262             Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
11263         }
11264 
11265         long totalScanTimeMs = 0;
11266 
11267         final int uidCount = mUidStats.size();
11268         for (int i = 0; i < uidCount; i++) {
11269             final Uid u = mUidStats.valueAt(i);
11270             if (u.mBluetoothScanTimer == null) {
11271                 continue;
11272             }
11273 
11274             totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
11275                     elapsedRealtimeMs * 1000) / 1000;
11276         }
11277 
11278         final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
11279         final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
11280 
11281         if (DEBUG_ENERGY) {
11282             Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
11283                     + " TX=" + normalizeScanTxTime);
11284         }
11285 
11286         long leftOverRxTimeMs = rxTimeMs;
11287         long leftOverTxTimeMs = txTimeMs;
11288 
11289         for (int i = 0; i < uidCount; i++) {
11290             final Uid u = mUidStats.valueAt(i);
11291             if (u.mBluetoothScanTimer == null) {
11292                 continue;
11293             }
11294 
11295             long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
11296                     elapsedRealtimeMs * 1000) / 1000;
11297             if (scanTimeSinceMarkMs > 0) {
11298                 // Set the new mark so that next time we get new data since this point.
11299                 u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
11300 
11301                 long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
11302                 long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
11303 
11304                 if (normalizeScanRxTime) {
11305                     // Scan time is longer than the total rx time in the controller,
11306                     // so distribute the scan time proportionately. This means regular traffic
11307                     // will not blamed, but scans are more expensive anyways.
11308                     scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
11309                 }
11310 
11311                 if (normalizeScanTxTime) {
11312                     // Scan time is longer than the total tx time in the controller,
11313                     // so distribute the scan time proportionately. This means regular traffic
11314                     // will not blamed, but scans are more expensive anyways.
11315                     scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
11316                 }
11317 
11318                 final ControllerActivityCounterImpl counter =
11319                         u.getOrCreateBluetoothControllerActivityLocked();
11320                 counter.getRxTimeCounter().addCountLocked(scanTimeRxSinceMarkMs);
11321                 counter.getTxTimeCounters()[0].addCountLocked(scanTimeTxSinceMarkMs);
11322 
11323                 leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
11324                 leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
11325             }
11326         }
11327 
11328         if (DEBUG_ENERGY) {
11329             Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX="
11330                     + leftOverTxTimeMs);
11331         }
11332 
11333         //
11334         // Now distribute blame to apps that did bluetooth traffic.
11335         //
11336 
11337         long totalTxBytes = 0;
11338         long totalRxBytes = 0;
11339 
11340         final UidTraffic[] uidTraffic = info.getUidTraffic();
11341         final int numUids = uidTraffic != null ? uidTraffic.length : 0;
11342         for (int i = 0; i < numUids; i++) {
11343             final UidTraffic traffic = uidTraffic[i];
11344             final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(
11345                     traffic.getUid());
11346             final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(
11347                     traffic.getUid());
11348 
11349             // Add to the global counters.
11350             mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(rxBytes);
11351             mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes);
11352 
11353             // Add to the UID counters.
11354             final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
11355             u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0);
11356             u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0);
11357 
11358             // Calculate the total traffic.
11359             totalRxBytes += rxBytes;
11360             totalTxBytes += txBytes;
11361         }
11362 
11363         if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0
11364                 || leftOverTxTimeMs != 0)) {
11365             for (int i = 0; i < numUids; i++) {
11366                 final UidTraffic traffic = uidTraffic[i];
11367                 final int uid = traffic.getUid();
11368                 final long rxBytes =
11369                         traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid);
11370                 final long txBytes =
11371                         traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid);
11372 
11373                 final Uid u = getUidStatsLocked(mapUid(uid));
11374                 final ControllerActivityCounterImpl counter =
11375                         u.getOrCreateBluetoothControllerActivityLocked();
11376 
11377                 if (totalRxBytes > 0 && rxBytes > 0) {
11378                     final long timeRxMs = (leftOverRxTimeMs * rxBytes) / totalRxBytes;
11379                     if (DEBUG_ENERGY) {
11380                         Slog.d(TAG, "UID=" + uid + " rx_bytes=" + rxBytes + " rx_time=" + timeRxMs);
11381                     }
11382                     counter.getRxTimeCounter().addCountLocked(timeRxMs);
11383                 }
11384 
11385                 if (totalTxBytes > 0 && txBytes > 0) {
11386                     final long timeTxMs = (leftOverTxTimeMs * txBytes) / totalTxBytes;
11387                     if (DEBUG_ENERGY) {
11388                         Slog.d(TAG, "UID=" + uid + " tx_bytes=" + txBytes + " tx_time=" + timeTxMs);
11389                     }
11390                     counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
11391                 }
11392             }
11393         }
11394 
11395         mBluetoothActivity.getRxTimeCounter().addCountLocked(rxTimeMs);
11396         mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(txTimeMs);
11397         mBluetoothActivity.getIdleTimeCounter().addCountLocked(idleTimeMs);
11398 
11399         // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11400         final double opVolt = mPowerProfile.getAveragePower(
11401                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11402         if (opVolt != 0) {
11403             // We store the power drain as mAms.
11404             mBluetoothActivity.getPowerCounter().addCountLocked(
11405                     (long) ((info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
11406                             / opVolt));
11407         }
11408         mLastBluetoothActivityInfo.set(info);
11409     }
11410 
11411     /**
11412      * Read and record Resource Power Manager (RPM) state and voter times.
11413      * If RPM stats were fetched more recently than RPM_STATS_UPDATE_FREQ_MS ago, uses the old data
11414      * instead of fetching it anew.
11415      */
updateRpmStatsLocked()11416     public void updateRpmStatsLocked() {
11417         if (mPlatformIdleStateCallback == null) return;
11418         long now = SystemClock.elapsedRealtime();
11419         if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
11420             mPlatformIdleStateCallback.fillLowPowerStats(mTmpRpmStats);
11421             mLastRpmStatsUpdateTimeMs = now;
11422         }
11423 
11424         for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate
11425                 : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) {
11426 
11427             // Update values for this platform state.
11428             final String pName = pstate.getKey();
11429             final long pTimeUs = pstate.getValue().mTimeMs * 1000;
11430             final int pCount = pstate.getValue().mCount;
11431             getRpmTimerLocked(pName).update(pTimeUs, pCount);
11432             if (SCREEN_OFF_RPM_STATS_ENABLED) {
11433                 getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount);
11434             }
11435 
11436             // Update values for each voter of this platform state.
11437             for (Map.Entry<String, RpmStats.PowerStateElement> voter
11438                     : pstate.getValue().mVoters.entrySet()) {
11439                 final String vName = pName + "." + voter.getKey();
11440                 final long vTimeUs = voter.getValue().mTimeMs * 1000;
11441                 final int vCount = voter.getValue().mCount;
11442                 getRpmTimerLocked(vName).update(vTimeUs, vCount);
11443                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
11444                     getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount);
11445                 }
11446             }
11447         }
11448 
11449         for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys
11450                 : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) {
11451 
11452             final String subsysName = subsys.getKey();
11453             for (Map.Entry<String, RpmStats.PowerStateElement> sstate
11454                     : subsys.getValue().mStates.entrySet()) {
11455                 final String name = subsysName + "." + sstate.getKey();
11456                 final long timeUs = sstate.getValue().mTimeMs * 1000;
11457                 final int count = sstate.getValue().mCount;
11458                 getRpmTimerLocked(name).update(timeUs, count);
11459                 if (SCREEN_OFF_RPM_STATS_ENABLED) {
11460                     getScreenOffRpmTimerLocked(name).update(timeUs, count);
11461                 }
11462             }
11463         }
11464     }
11465 
11466     /**
11467      * Read and record Rail Energy data.
11468      */
updateRailStatsLocked()11469     public void updateRailStatsLocked() {
11470         if (mRailEnergyDataCallback == null || !mTmpRailStats.isRailStatsAvailable()) {
11471             return;
11472         }
11473         mRailEnergyDataCallback.fillRailDataStats(mTmpRailStats);
11474     }
11475 
11476     /**
11477      * Read and distribute kernel wake lock use across apps.
11478      */
updateKernelWakelocksLocked()11479     public void updateKernelWakelocksLocked() {
11480         final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
11481                 mTmpWakelockStats);
11482         if (wakelockStats == null) {
11483             // Not crashing might make board bringup easier.
11484             Slog.w(TAG, "Couldn't get kernel wake lock stats");
11485             return;
11486         }
11487 
11488         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
11489             String name = ent.getKey();
11490             KernelWakelockStats.Entry kws = ent.getValue();
11491 
11492             SamplingTimer kwlt = mKernelWakelockStats.get(name);
11493             if (kwlt == null) {
11494                 kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
11495                 mKernelWakelockStats.put(name, kwlt);
11496             }
11497 
11498             kwlt.update(kws.mTotalTime, kws.mCount);
11499             kwlt.setUpdateVersion(kws.mVersion);
11500         }
11501 
11502         int numWakelocksSetStale = 0;
11503         // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
11504         // this time.
11505         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
11506             SamplingTimer st = ent.getValue();
11507             if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
11508                 st.endSample();
11509                 numWakelocksSetStale++;
11510             }
11511         }
11512 
11513         // Record whether we've seen a non-zero time (for debugging b/22716723).
11514         if (wakelockStats.isEmpty()) {
11515             Slog.wtf(TAG, "All kernel wakelocks had time of zero");
11516         }
11517 
11518         if (numWakelocksSetStale == mKernelWakelockStats.size()) {
11519             Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
11520                     wakelockStats.kernelWakelockVersion);
11521         }
11522     }
11523 
11524     // We use an anonymous class to access these variables,
11525     // so they can't live on the stack or they'd have to be
11526     // final MutableLong objects (more allocations).
11527     // Used in updateCpuTimeLocked().
11528     long mTempTotalCpuUserTimeUs;
11529     long mTempTotalCpuSystemTimeUs;
11530     long[][] mWakeLockAllocationsUs;
11531 
11532     /**
11533      * Reads the newest memory stats from the kernel.
11534      */
updateKernelMemoryBandwidthLocked()11535     public void updateKernelMemoryBandwidthLocked() {
11536         mKernelMemoryBandwidthStats.updateStats();
11537         LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
11538         final int bandwidthEntryCount = bandwidthEntries.size();
11539         int index;
11540         for (int i = 0; i < bandwidthEntryCount; i++) {
11541             SamplingTimer timer;
11542             if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) {
11543                 timer = mKernelMemoryStats.valueAt(index);
11544             } else {
11545                 timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
11546                 mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
11547             }
11548             timer.update(bandwidthEntries.valueAt(i), 1);
11549             if (DEBUG_MEMORY) {
11550                 Slog.d(TAG, String.format("Added entry %d and updated timer to: "
11551                         + "mUnpluggedReportedTotalTime %d size %d", bandwidthEntries.keyAt(i),
11552                         mKernelMemoryStats.get(
11553                                 bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTime,
11554                         mKernelMemoryStats.size()));
11555             }
11556         }
11557     }
11558 
isOnBatteryLocked()11559     public boolean isOnBatteryLocked() {
11560         return mOnBatteryTimeBase.isRunning();
11561     }
11562 
isOnBatteryScreenOffLocked()11563     public boolean isOnBatteryScreenOffLocked() {
11564         return mOnBatteryScreenOffTimeBase.isRunning();
11565     }
11566 
11567     /**
11568      * Read and distribute CPU usage across apps. If their are partial wakelocks being held
11569      * and we are on battery with screen off, we give more of the cpu time to those apps holding
11570      * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
11571      * It's possible this will be invoked after the internal battery/screen states are updated, so
11572      * passing the appropriate battery/screen states to try attribute the cpu times to correct
11573      * buckets.
11574      */
11575     @GuardedBy("this")
updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff)11576     public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff) {
11577         if (mPowerProfile == null) {
11578             return;
11579         }
11580 
11581         if (DEBUG_ENERGY_CPU) {
11582             Slog.d(TAG, "!Cpu updating!");
11583         }
11584 
11585         if (mCpuFreqs == null) {
11586             mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
11587         }
11588 
11589         // Calculate the wakelocks we have to distribute amongst. The system is excluded as it is
11590         // usually holding the wakelock on behalf of an app.
11591         // And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
11592         ArrayList<StopwatchTimer> partialTimersToConsider = null;
11593         if (onBatteryScreenOff) {
11594             partialTimersToConsider = new ArrayList<>();
11595             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
11596                 final StopwatchTimer timer = mPartialTimers.get(i);
11597                 // Since the collection and blaming of wakelocks can be scheduled to run after
11598                 // some delay, the mPartialTimers list may have new entries. We can't blame
11599                 // the newly added timer for past cpu time, so we only consider timers that
11600                 // were present for one round of collection. Once a timer has gone through
11601                 // a round of collection, its mInList field is set to true.
11602                 if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
11603                     partialTimersToConsider.add(timer);
11604                 }
11605             }
11606         }
11607         markPartialTimersAsEligible();
11608 
11609         // When the battery is not on, we don't attribute the cpu times to any timers but we still
11610         // need to take the snapshots.
11611         if (!onBattery) {
11612             mCpuUidUserSysTimeReader.readDelta(null);
11613             mCpuUidFreqTimeReader.readDelta(null);
11614             mNumAllUidCpuTimeReads += 2;
11615             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
11616                 mCpuUidActiveTimeReader.readDelta(null);
11617                 mCpuUidClusterTimeReader.readDelta(null);
11618                 mNumAllUidCpuTimeReads += 2;
11619             }
11620             for (int cluster = mKernelCpuSpeedReaders.length - 1; cluster >= 0; --cluster) {
11621                 mKernelCpuSpeedReaders[cluster].readDelta();
11622             }
11623             return;
11624         }
11625 
11626         mUserInfoProvider.refreshUserIds();
11627         final SparseLongArray updatedUids = mCpuUidFreqTimeReader.perClusterTimesAvailable()
11628                 ? null : new SparseLongArray();
11629         readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
11630         // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
11631         // freqs, so no need to approximate these values.
11632         if (updatedUids != null) {
11633             updateClusterSpeedTimes(updatedUids, onBattery);
11634         }
11635         readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff);
11636         mNumAllUidCpuTimeReads += 2;
11637         if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
11638             readKernelUidCpuActiveTimesLocked(onBattery);
11639             readKernelUidCpuClusterTimesLocked(onBattery);
11640             mNumAllUidCpuTimeReads += 2;
11641         }
11642     }
11643 
11644     /**
11645      * Mark the current partial timers as gone through a collection so that they will be
11646      * considered in the next cpu times distribution to wakelock holders.
11647      */
11648     @VisibleForTesting
markPartialTimersAsEligible()11649     public void markPartialTimersAsEligible() {
11650         if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
11651             // No difference, so each timer is now considered for the next collection.
11652             for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
11653                 mPartialTimers.get(i).mInList = true;
11654             }
11655         } else {
11656             // The lists are different, meaning we added (or removed a timer) since the last
11657             // collection.
11658             for (int i = mLastPartialTimers.size() - 1; i >= 0; --i) {
11659                 mLastPartialTimers.get(i).mInList = false;
11660             }
11661             mLastPartialTimers.clear();
11662 
11663             // Mark the current timers as gone through a collection.
11664             final int numPartialTimers = mPartialTimers.size();
11665             for (int i = 0; i < numPartialTimers; ++i) {
11666                 final StopwatchTimer timer = mPartialTimers.get(i);
11667                 timer.mInList = true;
11668                 mLastPartialTimers.add(timer);
11669             }
11670         }
11671     }
11672 
11673     /**
11674      * Take snapshot of cpu times (aggregated over all uids) at different frequencies and
11675      * calculate cpu times spent by each uid at different frequencies.
11676      *
11677      * @param updatedUids The uids for which times spent at different frequencies are calculated.
11678      */
11679     @VisibleForTesting
updateClusterSpeedTimes(@onNull SparseLongArray updatedUids, boolean onBattery)11680     public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery) {
11681         long totalCpuClustersTimeMs = 0;
11682         // Read the time spent for each cluster at various cpu frequencies.
11683         final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
11684         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
11685             clusterSpeedTimesMs[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
11686             if (clusterSpeedTimesMs[cluster] != null) {
11687                 for (int speed = clusterSpeedTimesMs[cluster].length - 1; speed >= 0; --speed) {
11688                     totalCpuClustersTimeMs += clusterSpeedTimesMs[cluster][speed];
11689                 }
11690             }
11691         }
11692         if (totalCpuClustersTimeMs != 0) {
11693             // We have cpu times per freq aggregated over all uids but we need the times per uid.
11694             // So, we distribute total time spent by an uid to different cpu freqs based on the
11695             // amount of time cpu was running at that freq.
11696             final int updatedUidsCount = updatedUids.size();
11697             for (int i = 0; i < updatedUidsCount; ++i) {
11698                 final Uid u = getUidStatsLocked(updatedUids.keyAt(i));
11699                 final long appCpuTimeUs = updatedUids.valueAt(i);
11700                 // Add the cpu speeds to this UID.
11701                 final int numClusters = mPowerProfile.getNumCpuClusters();
11702                 if (u.mCpuClusterSpeedTimesUs == null ||
11703                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
11704                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
11705                 }
11706 
11707                 for (int cluster = 0; cluster < clusterSpeedTimesMs.length; cluster++) {
11708                     final int speedsInCluster = clusterSpeedTimesMs[cluster].length;
11709                     if (u.mCpuClusterSpeedTimesUs[cluster] == null || speedsInCluster !=
11710                             u.mCpuClusterSpeedTimesUs[cluster].length) {
11711                         u.mCpuClusterSpeedTimesUs[cluster]
11712                                 = new LongSamplingCounter[speedsInCluster];
11713                     }
11714 
11715                     final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeedTimesUs[cluster];
11716                     for (int speed = 0; speed < speedsInCluster; speed++) {
11717                         if (cpuSpeeds[speed] == null) {
11718                             cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
11719                         }
11720                         cpuSpeeds[speed].addCountLocked(appCpuTimeUs
11721                                 * clusterSpeedTimesMs[cluster][speed]
11722                                 / totalCpuClustersTimeMs, onBattery);
11723                     }
11724                 }
11725             }
11726         }
11727     }
11728 
11729     /**
11730      * Take a snapshot of the cpu times spent by each uid and update the corresponding counters.
11731      * If {@param partialTimers} is not null and empty, then we assign a portion of cpu times to
11732      * wakelock holders.
11733      *
11734      * @param partialTimers The wakelock holders among which the cpu times will be distributed.
11735      * @param updatedUids If not null, then the uids found in the snapshot will be added to this.
11736      */
11737     @VisibleForTesting
readKernelUidCpuTimesLocked(@ullable ArrayList<StopwatchTimer> partialTimers, @Nullable SparseLongArray updatedUids, boolean onBattery)11738     public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
11739             @Nullable SparseLongArray updatedUids, boolean onBattery) {
11740         mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
11741         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
11742         final long startTimeMs = mClocks.uptimeMillis();
11743 
11744         mCpuUidUserSysTimeReader.readDelta((uid, timesUs) -> {
11745             long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
11746 
11747             uid = mapUid(uid);
11748             if (Process.isIsolated(uid)) {
11749                 // This could happen if the isolated uid mapping was removed before that process
11750                 // was actually killed.
11751                 mCpuUidUserSysTimeReader.removeUid(uid);
11752                 Slog.d(TAG, "Got readings for an isolated uid with no mapping: " + uid);
11753                 return;
11754             }
11755             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
11756                 Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
11757                 mCpuUidUserSysTimeReader.removeUid(uid);
11758                 return;
11759             }
11760             final Uid u = getUidStatsLocked(uid);
11761 
11762             // Accumulate the total system and user time.
11763             mTempTotalCpuUserTimeUs += userTimeUs;
11764             mTempTotalCpuSystemTimeUs += systemTimeUs;
11765 
11766             StringBuilder sb = null;
11767             if (DEBUG_ENERGY_CPU) {
11768                 sb = new StringBuilder();
11769                 sb.append("  got time for uid=").append(u.mUid).append(": u=");
11770                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
11771                 sb.append(" s=");
11772                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
11773                 sb.append("\n");
11774             }
11775 
11776             if (numWakelocks > 0) {
11777                 // We have wakelocks being held, so only give a portion of the
11778                 // time to the process. The rest will be distributed among wakelock
11779                 // holders.
11780                 userTimeUs = (userTimeUs * WAKE_LOCK_WEIGHT) / 100;
11781                 systemTimeUs = (systemTimeUs * WAKE_LOCK_WEIGHT) / 100;
11782             }
11783 
11784             if (sb != null) {
11785                 sb.append("  adding to uid=").append(u.mUid).append(": u=");
11786                 TimeUtils.formatDuration(userTimeUs / 1000, sb);
11787                 sb.append(" s=");
11788                 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
11789                 Slog.d(TAG, sb.toString());
11790             }
11791 
11792             u.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
11793             u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
11794             if (updatedUids != null) {
11795                 updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
11796             }
11797         });
11798 
11799         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
11800         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
11801             Slog.d(TAG, "Reading cpu stats took " + elapsedTimeMs + "ms");
11802         }
11803 
11804         if (numWakelocks > 0) {
11805             // Distribute a portion of the total cpu time to wakelock holders.
11806             mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
11807             mTempTotalCpuSystemTimeUs =
11808                     (mTempTotalCpuSystemTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
11809 
11810             for (int i = 0; i < numWakelocks; ++i) {
11811                 final StopwatchTimer timer = partialTimers.get(i);
11812                 final int userTimeUs = (int) (mTempTotalCpuUserTimeUs / (numWakelocks - i));
11813                 final int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / (numWakelocks - i));
11814 
11815                 if (DEBUG_ENERGY_CPU) {
11816                     final StringBuilder sb = new StringBuilder();
11817                     sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
11818                             .append(": u=");
11819                     TimeUtils.formatDuration(userTimeUs / 1000, sb);
11820                     sb.append(" s=");
11821                     TimeUtils.formatDuration(systemTimeUs / 1000, sb);
11822                     Slog.d(TAG, sb.toString());
11823                 }
11824 
11825                 timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
11826                 timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
11827                 if (updatedUids != null) {
11828                     final int uid = timer.mUid.getUid();
11829                     updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
11830                 }
11831 
11832                 final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
11833                 proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery);
11834 
11835                 mTempTotalCpuUserTimeUs -= userTimeUs;
11836                 mTempTotalCpuSystemTimeUs -= systemTimeUs;
11837             }
11838         }
11839     }
11840 
11841     /**
11842      * Take a snapshot of the cpu times spent by each uid in each freq and update the
11843      * corresponding counters.
11844      *
11845      * @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
11846      */
11847     @VisibleForTesting
readKernelUidCpuFreqTimesLocked(@ullable ArrayList<StopwatchTimer> partialTimers, boolean onBattery, boolean onBatteryScreenOff)11848     public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
11849             boolean onBattery, boolean onBatteryScreenOff) {
11850         final boolean perClusterTimesAvailable =
11851                 mCpuUidFreqTimeReader.perClusterTimesAvailable();
11852         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
11853         final int numClusters = mPowerProfile.getNumCpuClusters();
11854         mWakeLockAllocationsUs = null;
11855         final long startTimeMs = mClocks.uptimeMillis();
11856         mCpuUidFreqTimeReader.readDelta((uid, cpuFreqTimeMs) -> {
11857             uid = mapUid(uid);
11858             if (Process.isIsolated(uid)) {
11859                 mCpuUidFreqTimeReader.removeUid(uid);
11860                 Slog.d(TAG, "Got freq readings for an isolated uid with no mapping: " + uid);
11861                 return;
11862             }
11863             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
11864                 Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
11865                 mCpuUidFreqTimeReader.removeUid(uid);
11866                 return;
11867             }
11868             final Uid u = getUidStatsLocked(uid);
11869             if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
11870                 detachIfNotNull(u.mCpuFreqTimeMs);
11871                 u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
11872             }
11873             u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
11874             if (u.mScreenOffCpuFreqTimeMs == null ||
11875                     u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
11876                 detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
11877                 u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
11878                         mOnBatteryScreenOffTimeBase);
11879             }
11880             u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff);
11881 
11882             if (perClusterTimesAvailable) {
11883                 if (u.mCpuClusterSpeedTimesUs == null ||
11884                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
11885                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
11886                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
11887                 }
11888                 if (numWakelocks > 0 && mWakeLockAllocationsUs == null) {
11889                     mWakeLockAllocationsUs = new long[numClusters][];
11890                 }
11891 
11892                 int freqIndex = 0;
11893                 for (int cluster = 0; cluster < numClusters; ++cluster) {
11894                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
11895                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
11896                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
11897                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
11898                         u.mCpuClusterSpeedTimesUs[cluster]
11899                                 = new LongSamplingCounter[speedsInCluster];
11900                     }
11901                     if (numWakelocks > 0 && mWakeLockAllocationsUs[cluster] == null) {
11902                         mWakeLockAllocationsUs[cluster] = new long[speedsInCluster];
11903                     }
11904                     final LongSamplingCounter[] cpuTimesUs = u.mCpuClusterSpeedTimesUs[cluster];
11905                     for (int speed = 0; speed < speedsInCluster; ++speed) {
11906                         if (cpuTimesUs[speed] == null) {
11907                             cpuTimesUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
11908                         }
11909                         final long appAllocationUs;
11910                         if (mWakeLockAllocationsUs != null) {
11911                             appAllocationUs =
11912                                     (cpuFreqTimeMs[freqIndex] * 1000 * WAKE_LOCK_WEIGHT) / 100;
11913                             mWakeLockAllocationsUs[cluster][speed] +=
11914                                     (cpuFreqTimeMs[freqIndex] * 1000 - appAllocationUs);
11915                         } else {
11916                             appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
11917                         }
11918                         cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
11919                         freqIndex++;
11920                     }
11921                 }
11922             }
11923         });
11924 
11925         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
11926         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
11927             Slog.d(TAG, "Reading cpu freq times took " + elapsedTimeMs + "ms");
11928         }
11929 
11930         if (mWakeLockAllocationsUs != null) {
11931             for (int i = 0; i < numWakelocks; ++i) {
11932                 final Uid u = partialTimers.get(i).mUid;
11933                 if (u.mCpuClusterSpeedTimesUs == null ||
11934                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
11935                     detachIfNotNull(u.mCpuClusterSpeedTimesUs);
11936                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
11937                 }
11938 
11939                 for (int cluster = 0; cluster < numClusters; ++cluster) {
11940                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
11941                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
11942                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
11943                         detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
11944                         u.mCpuClusterSpeedTimesUs[cluster]
11945                                 = new LongSamplingCounter[speedsInCluster];
11946                     }
11947                     final LongSamplingCounter[] cpuTimeUs = u.mCpuClusterSpeedTimesUs[cluster];
11948                     for (int speed = 0; speed < speedsInCluster; ++speed) {
11949                         if (cpuTimeUs[speed] == null) {
11950                             cpuTimeUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
11951                         }
11952                         final long allocationUs =
11953                                 mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
11954                         cpuTimeUs[speed].addCountLocked(allocationUs, onBattery);
11955                         mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
11956                     }
11957                 }
11958             }
11959         }
11960     }
11961 
11962     /**
11963      * Take a snapshot of the cpu active times spent by each uid and update the corresponding
11964      * counters.
11965      */
11966     @VisibleForTesting
readKernelUidCpuActiveTimesLocked(boolean onBattery)11967     public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
11968         final long startTimeMs = mClocks.uptimeMillis();
11969         mCpuUidActiveTimeReader.readDelta((uid, cpuActiveTimesMs) -> {
11970             uid = mapUid(uid);
11971             if (Process.isIsolated(uid)) {
11972                 mCpuUidActiveTimeReader.removeUid(uid);
11973                 Slog.w(TAG, "Got active times for an isolated uid with no mapping: " + uid);
11974                 return;
11975             }
11976             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
11977                 Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
11978                 mCpuUidActiveTimeReader.removeUid(uid);
11979                 return;
11980             }
11981             final Uid u = getUidStatsLocked(uid);
11982             u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesMs, onBattery);
11983         });
11984 
11985         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
11986         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
11987             Slog.d(TAG, "Reading cpu active times took " + elapsedTimeMs + "ms");
11988         }
11989     }
11990 
11991     /**
11992      * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding
11993      * counters.
11994      */
11995     @VisibleForTesting
readKernelUidCpuClusterTimesLocked(boolean onBattery)11996     public void readKernelUidCpuClusterTimesLocked(boolean onBattery) {
11997         final long startTimeMs = mClocks.uptimeMillis();
11998         mCpuUidClusterTimeReader.readDelta((uid, cpuClusterTimesMs) -> {
11999             uid = mapUid(uid);
12000             if (Process.isIsolated(uid)) {
12001                 mCpuUidClusterTimeReader.removeUid(uid);
12002                 Slog.w(TAG, "Got cluster times for an isolated uid with no mapping: " + uid);
12003                 return;
12004             }
12005             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
12006                 Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
12007                 mCpuUidClusterTimeReader.removeUid(uid);
12008                 return;
12009             }
12010             final Uid u = getUidStatsLocked(uid);
12011             u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesMs, onBattery);
12012         });
12013 
12014         final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
12015         if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
12016             Slog.d(TAG, "Reading cpu cluster times took " + elapsedTimeMs + "ms");
12017         }
12018     }
12019 
setChargingLocked(boolean charging)12020     boolean setChargingLocked(boolean charging) {
12021         // if the device is no longer charging, remove the callback
12022         // if the device is now charging, it means that this is either called
12023         // 1. directly when level >= 90
12024         // 2. or from within the runnable that we deferred
12025         // For 1. if we have an existing callback, remove it, since we will immediately send a
12026         // ACTION_CHARGING
12027         // For 2. we remove existing callback so we don't send multiple ACTION_CHARGING
12028         mHandler.removeCallbacks(mDeferSetCharging);
12029         if (mCharging != charging) {
12030             mCharging = charging;
12031             if (charging) {
12032                 mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
12033             } else {
12034                 mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
12035             }
12036             mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
12037             return true;
12038         }
12039         return false;
12040     }
12041 
12042     @GuardedBy("this")
setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery, final int oldStatus, final int level, final int chargeUAh)12043     protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
12044             final boolean onBattery, final int oldStatus, final int level, final int chargeUAh) {
12045         boolean doWrite = false;
12046         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
12047         m.arg1 = onBattery ? 1 : 0;
12048         mHandler.sendMessage(m);
12049 
12050         final long uptime = mSecUptime * 1000;
12051         final long realtime = mSecRealtime * 1000;
12052         final int screenState = mScreenState;
12053         if (onBattery) {
12054             // We will reset our status if we are unplugging after the
12055             // battery was last full, or the level is at 100, or
12056             // we have gone through a significant charge (from a very low
12057             // level to a now very high level).
12058             boolean reset = false;
12059             if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
12060                     || level >= 90
12061                     || (mDischargeCurrentLevel < 20 && level >= 80))) {
12062                 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
12063                         + " dischargeLevel=" + mDischargeCurrentLevel
12064                         + " lowAmount=" + getLowDischargeAmountSinceCharge()
12065                         + " highAmount=" + getHighDischargeAmountSinceCharge());
12066                 // Before we write, collect a snapshot of the final aggregated
12067                 // stats to be reported in the next checkin.  Only do this if we have
12068                 // a sufficient amount of data to make it interesting.
12069                 if (getLowDischargeAmountSinceCharge() >= 20) {
12070                     final long startTime = SystemClock.uptimeMillis();
12071                     final Parcel parcel = Parcel.obtain();
12072                     writeSummaryToParcel(parcel, true);
12073                     final long initialTime = SystemClock.uptimeMillis() - startTime;
12074                     BackgroundThread.getHandler().post(new Runnable() {
12075                         @Override public void run() {
12076                             synchronized (mCheckinFile) {
12077                                 final long startTime2 = SystemClock.uptimeMillis();
12078                                 FileOutputStream stream = null;
12079                                 try {
12080                                     stream = mCheckinFile.startWrite();
12081                                     stream.write(parcel.marshall());
12082                                     stream.flush();
12083                                     mCheckinFile.finishWrite(stream);
12084                                     com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
12085                                             "batterystats-checkin",
12086                                             initialTime + SystemClock.uptimeMillis() - startTime2);
12087                                 } catch (IOException e) {
12088                                     Slog.w("BatteryStats",
12089                                             "Error writing checkin battery statistics", e);
12090                                     mCheckinFile.failWrite(stream);
12091                                 } finally {
12092                                     parcel.recycle();
12093                                 }
12094                             }
12095                         }
12096                     });
12097                 }
12098                 doWrite = true;
12099                 resetAllStatsLocked();
12100                 if (chargeUAh > 0 && level > 0) {
12101                     // Only use the reported coulomb charge value if it is supported and reported.
12102                     mEstimatedBatteryCapacity = (int) ((chargeUAh / 1000) / (level / 100.0));
12103                 }
12104                 mDischargeStartLevel = level;
12105                 reset = true;
12106                 mDischargeStepTracker.init();
12107             }
12108             if (mCharging) {
12109                 setChargingLocked(false);
12110             }
12111             mLastChargingStateLevel = level;
12112             mOnBattery = mOnBatteryInternal = true;
12113             mLastDischargeStepLevel = level;
12114             mMinDischargeStepLevel = level;
12115             mDischargeStepTracker.clearTime();
12116             mDailyDischargeStepTracker.clearTime();
12117             mInitStepMode = mCurStepMode;
12118             mModStepMode = 0;
12119             pullPendingStateUpdatesLocked();
12120             mHistoryCur.batteryLevel = (byte)level;
12121             mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12122             if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
12123                     + Integer.toHexString(mHistoryCur.states));
12124             if (reset) {
12125                 mRecordingHistory = true;
12126                 startRecordingHistory(mSecRealtime, mSecUptime, reset);
12127             }
12128             addHistoryRecordLocked(mSecRealtime, mSecUptime);
12129             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
12130             if (isScreenOn(screenState)) {
12131                 mDischargeScreenOnUnplugLevel = level;
12132                 mDischargeScreenDozeUnplugLevel = 0;
12133                 mDischargeScreenOffUnplugLevel = 0;
12134             } else if (isScreenDoze(screenState)) {
12135                 mDischargeScreenOnUnplugLevel = 0;
12136                 mDischargeScreenDozeUnplugLevel = level;
12137                 mDischargeScreenOffUnplugLevel = 0;
12138             } else {
12139                 mDischargeScreenOnUnplugLevel = 0;
12140                 mDischargeScreenDozeUnplugLevel = 0;
12141                 mDischargeScreenOffUnplugLevel = level;
12142             }
12143             mDischargeAmountScreenOn = 0;
12144             mDischargeAmountScreenDoze = 0;
12145             mDischargeAmountScreenOff = 0;
12146             updateTimeBasesLocked(true, screenState, uptime, realtime);
12147         } else {
12148             mLastChargingStateLevel = level;
12149             mOnBattery = mOnBatteryInternal = false;
12150             pullPendingStateUpdatesLocked();
12151             mHistoryCur.batteryLevel = (byte)level;
12152             mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12153             if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
12154                     + Integer.toHexString(mHistoryCur.states));
12155             addHistoryRecordLocked(mSecRealtime, mSecUptime);
12156             mDischargeCurrentLevel = mDischargePlugLevel = level;
12157             if (level < mDischargeUnplugLevel) {
12158                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
12159                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
12160             }
12161             updateDischargeScreenLevelsLocked(screenState, screenState);
12162             updateTimeBasesLocked(false, screenState, uptime, realtime);
12163             mChargeStepTracker.init();
12164             mLastChargeStepLevel = level;
12165             mMaxChargeStepLevel = level;
12166             mInitStepMode = mCurStepMode;
12167             mModStepMode = 0;
12168         }
12169         if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
12170             if (mStatsFile != null && mBatteryStatsHistory.getActiveFile() != null) {
12171                 writeAsyncLocked();
12172             }
12173         }
12174     }
12175 
startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs, boolean reset)12176     private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
12177             boolean reset) {
12178         mRecordingHistory = true;
12179         mHistoryCur.currentTime = System.currentTimeMillis();
12180         addHistoryBufferLocked(elapsedRealtimeMs,
12181                 reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
12182                 mHistoryCur);
12183         mHistoryCur.currentTime = 0;
12184         if (reset) {
12185             initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
12186         }
12187     }
12188 
recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs, final long uptimeMs)12189     private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
12190             final long uptimeMs) {
12191         if (mRecordingHistory) {
12192             mHistoryCur.currentTime = currentTime;
12193             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_CURRENT_TIME, mHistoryCur);
12194             mHistoryCur.currentTime = 0;
12195         }
12196     }
12197 
recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs)12198     private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
12199         if (mRecordingHistory) {
12200             mHistoryCur.currentTime = System.currentTimeMillis();
12201             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_SHUTDOWN, mHistoryCur);
12202             mHistoryCur.currentTime = 0;
12203         }
12204     }
12205 
scheduleSyncExternalStatsLocked(String reason, int updateFlags)12206     private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
12207         if (mExternalSync != null) {
12208             mExternalSync.scheduleSync(reason, updateFlags);
12209         }
12210     }
12211 
12212     // This should probably be exposed in the API, though it's not critical
12213     public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
12214 
12215     @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)12216     public void setBatteryStateLocked(final int status, final int health, final int plugType,
12217             final int level, /* not final */ int temp, final int volt, final int chargeUAh,
12218             final int chargeFullUAh) {
12219         // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
12220         temp = Math.max(0, temp);
12221 
12222         reportChangesToStatsLog(mHaveBatteryLevel ? mHistoryCur : null,
12223                 status, plugType, level);
12224 
12225         final boolean onBattery = isOnBattery(plugType, status);
12226         final long uptime = mClocks.uptimeMillis();
12227         final long elapsedRealtime = mClocks.elapsedRealtime();
12228         if (!mHaveBatteryLevel) {
12229             mHaveBatteryLevel = true;
12230             // We start out assuming that the device is plugged in (not
12231             // on battery).  If our first report is now that we are indeed
12232             // plugged in, then twiddle our state to correctly reflect that
12233             // since we won't be going through the full setOnBattery().
12234             if (onBattery == mOnBattery) {
12235                 if (onBattery) {
12236                     mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12237                 } else {
12238                     mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12239                 }
12240             }
12241             // Always start out assuming charging, that will be updated later.
12242             mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
12243             mHistoryCur.batteryStatus = (byte)status;
12244             mHistoryCur.batteryLevel = (byte)level;
12245             mHistoryCur.batteryChargeUAh = chargeUAh;
12246             mMaxChargeStepLevel = mMinDischargeStepLevel =
12247                     mLastChargeStepLevel = mLastDischargeStepLevel = level;
12248             mLastChargingStateLevel = level;
12249         } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
12250             recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
12251         }
12252         int oldStatus = mHistoryCur.batteryStatus;
12253         if (onBattery) {
12254             mDischargeCurrentLevel = level;
12255             if (!mRecordingHistory) {
12256                 mRecordingHistory = true;
12257                 startRecordingHistory(elapsedRealtime, uptime, true);
12258             }
12259         } else if (level < 96 &&
12260                 status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
12261             if (!mRecordingHistory) {
12262                 mRecordingHistory = true;
12263                 startRecordingHistory(elapsedRealtime, uptime, true);
12264             }
12265         }
12266         mCurrentBatteryLevel = level;
12267         if (mDischargePlugLevel < 0) {
12268             mDischargePlugLevel = level;
12269         }
12270 
12271         if (onBattery != mOnBattery) {
12272             mHistoryCur.batteryLevel = (byte)level;
12273             mHistoryCur.batteryStatus = (byte)status;
12274             mHistoryCur.batteryHealth = (byte)health;
12275             mHistoryCur.batteryPlugType = (byte)plugType;
12276             mHistoryCur.batteryTemperature = (short)temp;
12277             mHistoryCur.batteryVoltage = (char)volt;
12278             if (chargeUAh < mHistoryCur.batteryChargeUAh) {
12279                 // Only record discharges
12280                 final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
12281                 mDischargeCounter.addCountLocked(chargeDiff);
12282                 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
12283                 if (isScreenDoze(mScreenState)) {
12284                     mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
12285                 }
12286                 if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
12287                     mDischargeLightDozeCounter.addCountLocked(chargeDiff);
12288                 } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
12289                     mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
12290                 }
12291             }
12292             mHistoryCur.batteryChargeUAh = chargeUAh;
12293             setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level, chargeUAh);
12294         } else {
12295             boolean changed = false;
12296             if (mHistoryCur.batteryLevel != level) {
12297                 mHistoryCur.batteryLevel = (byte)level;
12298                 changed = true;
12299 
12300                 // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
12301                 // which will pull external stats.
12302                 mExternalSync.scheduleSyncDueToBatteryLevelChange(
12303                         mConstants.BATTERY_LEVEL_COLLECTION_DELAY_MS);
12304             }
12305             if (mHistoryCur.batteryStatus != status) {
12306                 mHistoryCur.batteryStatus = (byte)status;
12307                 changed = true;
12308             }
12309             if (mHistoryCur.batteryHealth != health) {
12310                 mHistoryCur.batteryHealth = (byte)health;
12311                 changed = true;
12312             }
12313             if (mHistoryCur.batteryPlugType != plugType) {
12314                 mHistoryCur.batteryPlugType = (byte)plugType;
12315                 changed = true;
12316             }
12317             if (temp >= (mHistoryCur.batteryTemperature+10)
12318                     || temp <= (mHistoryCur.batteryTemperature-10)) {
12319                 mHistoryCur.batteryTemperature = (short)temp;
12320                 changed = true;
12321             }
12322             if (volt > (mHistoryCur.batteryVoltage+20)
12323                     || volt < (mHistoryCur.batteryVoltage-20)) {
12324                 mHistoryCur.batteryVoltage = (char)volt;
12325                 changed = true;
12326             }
12327             if (chargeUAh >= (mHistoryCur.batteryChargeUAh+10)
12328                     || chargeUAh <= (mHistoryCur.batteryChargeUAh-10)) {
12329                 if (chargeUAh < mHistoryCur.batteryChargeUAh) {
12330                     // Only record discharges
12331                     final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
12332                     mDischargeCounter.addCountLocked(chargeDiff);
12333                     mDischargeScreenOffCounter.addCountLocked(chargeDiff);
12334                     if (isScreenDoze(mScreenState)) {
12335                         mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
12336                     }
12337                     if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
12338                         mDischargeLightDozeCounter.addCountLocked(chargeDiff);
12339                     } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
12340                         mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
12341                     }
12342                 }
12343                 mHistoryCur.batteryChargeUAh = chargeUAh;
12344                 changed = true;
12345             }
12346             long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
12347                     | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
12348                     | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
12349             if (onBattery) {
12350                 changed |= setChargingLocked(false);
12351                 if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
12352                     mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
12353                             modeBits, elapsedRealtime);
12354                     mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
12355                             modeBits, elapsedRealtime);
12356                     mLastDischargeStepLevel = level;
12357                     mMinDischargeStepLevel = level;
12358                     mInitStepMode = mCurStepMode;
12359                     mModStepMode = 0;
12360                 }
12361             } else {
12362                 if (level >= 90) {
12363                     // If the battery level is at least 90%, always consider the device to be
12364                     // charging even if it happens to go down a level.
12365                     changed |= setChargingLocked(true);
12366                 } else if (!mCharging) {
12367                     if (mLastChargeStepLevel < level) {
12368                         // We have not reported that we are charging, but the level has gone up,
12369                         // but we would like to not have tons of activity from charging-constraint
12370                         // jobs, so instead of reporting ACTION_CHARGING immediately, we defer it.
12371                         if (!mHandler.hasCallbacks(mDeferSetCharging)) {
12372                             mHandler.postDelayed(
12373                                     mDeferSetCharging,
12374                                     mConstants.BATTERY_CHARGED_DELAY_MS);
12375                         }
12376                     } else if (mLastChargeStepLevel > level) {
12377                         // if we had deferred a runnable due to charge level increasing, but then
12378                         // later the charge level drops (could be due to thermal issues), we don't
12379                         // want to trigger the deferred runnable, so remove it here
12380                         mHandler.removeCallbacks(mDeferSetCharging);
12381                     }
12382                 } else {
12383                     if (mLastChargeStepLevel > level) {
12384                         // We had reported that the device was charging, but here we are with
12385                         // power connected and the level going down.  Looks like the current
12386                         // power supplied isn't enough, so consider the device to now be
12387                         // discharging.
12388                         changed |= setChargingLocked(false);
12389                     }
12390                 }
12391                 if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
12392                     mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
12393                             modeBits, elapsedRealtime);
12394                     mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
12395                             modeBits, elapsedRealtime);
12396                     mMaxChargeStepLevel = level;
12397                     mInitStepMode = mCurStepMode;
12398                     mModStepMode = 0;
12399                 }
12400                 mLastChargeStepLevel = level;
12401             }
12402             if (changed) {
12403                 addHistoryRecordLocked(elapsedRealtime, uptime);
12404             }
12405         }
12406         if (!onBattery &&
12407                 (status == BatteryManager.BATTERY_STATUS_FULL ||
12408                         status == BatteryManager.BATTERY_STATUS_UNKNOWN)) {
12409             // We don't record history while we are plugged in and fully charged
12410             // (or when battery is not present).  The next time we are
12411             // unplugged, history will be cleared.
12412             mRecordingHistory = DEBUG;
12413         }
12414 
12415         if (mMinLearnedBatteryCapacity == -1) {
12416             mMinLearnedBatteryCapacity = chargeFullUAh;
12417         } else {
12418             mMinLearnedBatteryCapacity = Math.min(mMinLearnedBatteryCapacity, chargeFullUAh);
12419         }
12420         mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh);
12421     }
12422 
isOnBattery(int plugType, int status)12423     public static boolean isOnBattery(int plugType, int status) {
12424         return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN;
12425     }
12426 
12427     // Inform StatsLog of setBatteryState changes.
12428     // If this is the first reporting, pass in recentPast == null.
reportChangesToStatsLog(HistoryItem recentPast, final int status, final int plugType, final int level)12429     private void reportChangesToStatsLog(HistoryItem recentPast,
12430             final int status, final int plugType, final int level) {
12431 
12432         if (recentPast == null || recentPast.batteryStatus != status) {
12433             StatsLog.write(StatsLog.CHARGING_STATE_CHANGED, status);
12434         }
12435         if (recentPast == null || recentPast.batteryPlugType != plugType) {
12436             StatsLog.write(StatsLog.PLUGGED_STATE_CHANGED, plugType);
12437         }
12438         if (recentPast == null || recentPast.batteryLevel != level) {
12439             StatsLog.write(StatsLog.BATTERY_LEVEL_CHANGED, level);
12440         }
12441     }
12442 
12443     @UnsupportedAppUsage
getAwakeTimeBattery()12444     public long getAwakeTimeBattery() {
12445         // This previously evaluated to mOnBatteryTimeBase.getUptime(getBatteryUptimeLocked());
12446         // for over a decade, but surely that was a mistake.
12447         return getBatteryUptimeLocked();
12448     }
12449 
12450     @UnsupportedAppUsage
getAwakeTimePlugged()12451     public long getAwakeTimePlugged() {
12452         return (mClocks.uptimeMillis() * 1000) - getAwakeTimeBattery();
12453     }
12454 
12455     @Override
computeUptime(long curTime, int which)12456     public long computeUptime(long curTime, int which) {
12457         return mUptime + (curTime - mUptimeStart);
12458     }
12459 
12460     @Override
computeRealtime(long curTime, int which)12461     public long computeRealtime(long curTime, int which) {
12462         return mRealtime + (curTime - mRealtimeStart);
12463     }
12464 
12465     @Override
12466     @UnsupportedAppUsage
computeBatteryUptime(long curTime, int which)12467     public long computeBatteryUptime(long curTime, int which) {
12468         return mOnBatteryTimeBase.computeUptime(curTime, which);
12469     }
12470 
12471     @Override
12472     @UnsupportedAppUsage
computeBatteryRealtime(long curTime, int which)12473     public long computeBatteryRealtime(long curTime, int which) {
12474         return mOnBatteryTimeBase.computeRealtime(curTime, which);
12475     }
12476 
12477     @Override
computeBatteryScreenOffUptime(long curTime, int which)12478     public long computeBatteryScreenOffUptime(long curTime, int which) {
12479         return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
12480     }
12481 
12482     @Override
computeBatteryScreenOffRealtime(long curTime, int which)12483     public long computeBatteryScreenOffRealtime(long curTime, int which) {
12484         return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
12485     }
12486 
computeTimePerLevel(long[] steps, int numSteps)12487     private long computeTimePerLevel(long[] steps, int numSteps) {
12488         // For now we'll do a simple average across all steps.
12489         if (numSteps <= 0) {
12490             return -1;
12491         }
12492         long total = 0;
12493         for (int i=0; i<numSteps; i++) {
12494             total += steps[i] & STEP_LEVEL_TIME_MASK;
12495         }
12496         return total / numSteps;
12497         /*
12498         long[] buckets = new long[numSteps];
12499         int numBuckets = 0;
12500         int numToAverage = 4;
12501         int i = 0;
12502         while (i < numSteps) {
12503             long totalTime = 0;
12504             int num = 0;
12505             for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
12506                 totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
12507                 num++;
12508             }
12509             buckets[numBuckets] = totalTime / num;
12510             numBuckets++;
12511             numToAverage *= 2;
12512             i += num;
12513         }
12514         if (numBuckets < 1) {
12515             return -1;
12516         }
12517         long averageTime = buckets[numBuckets-1];
12518         for (i=numBuckets-2; i>=0; i--) {
12519             averageTime = (averageTime + buckets[i]) / 2;
12520         }
12521         return averageTime;
12522         */
12523     }
12524 
12525     @Override
12526     @UnsupportedAppUsage
computeBatteryTimeRemaining(long curTime)12527     public long computeBatteryTimeRemaining(long curTime) {
12528         if (!mOnBattery) {
12529             return -1;
12530         }
12531         /* Simple implementation just looks at the average discharge per level across the
12532            entire sample period.
12533         int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
12534         if (discharge < 2) {
12535             return -1;
12536         }
12537         long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
12538         if (duration < 1000*1000) {
12539             return -1;
12540         }
12541         long usPerLevel = duration/discharge;
12542         return usPerLevel * mCurrentBatteryLevel;
12543         */
12544         if (mDischargeStepTracker.mNumStepDurations < 1) {
12545             return -1;
12546         }
12547         long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
12548         if (msPerLevel <= 0) {
12549             return -1;
12550         }
12551         return (msPerLevel * mCurrentBatteryLevel) * 1000;
12552     }
12553 
12554     @Override
getDischargeLevelStepTracker()12555     public LevelStepTracker getDischargeLevelStepTracker() {
12556         return mDischargeStepTracker;
12557     }
12558 
12559     @Override
getDailyDischargeLevelStepTracker()12560     public LevelStepTracker getDailyDischargeLevelStepTracker() {
12561         return mDailyDischargeStepTracker;
12562     }
12563 
12564     @Override
computeChargeTimeRemaining(long curTime)12565     public long computeChargeTimeRemaining(long curTime) {
12566         if (mOnBattery) {
12567             // Not yet working.
12568             return -1;
12569         }
12570         /* Broken
12571         int curLevel = mCurrentBatteryLevel;
12572         int plugLevel = mDischargePlugLevel;
12573         if (plugLevel < 0 || curLevel < (plugLevel+1)) {
12574             return -1;
12575         }
12576         long duration = computeBatteryRealtime(curTime, STATS_SINCE_UNPLUGGED);
12577         if (duration < 1000*1000) {
12578             return -1;
12579         }
12580         long usPerLevel = duration/(curLevel-plugLevel);
12581         return usPerLevel * (100-curLevel);
12582         */
12583         if (mChargeStepTracker.mNumStepDurations < 1) {
12584             return -1;
12585         }
12586         long msPerLevel = mChargeStepTracker.computeTimePerLevel();
12587         if (msPerLevel <= 0) {
12588             return -1;
12589         }
12590         return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
12591     }
12592 
12593     /*@hide */
getCellularBatteryStats()12594     public CellularBatteryStats getCellularBatteryStats() {
12595         CellularBatteryStats s = new CellularBatteryStats();
12596         final int which = STATS_SINCE_CHARGED;
12597         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
12598         final ControllerActivityCounter counter = getModemControllerActivity();
12599         final long sleepTimeMs = counter.getSleepTimeCounter().getCountLocked(which);
12600         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
12601         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
12602         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
12603         final long monitoredRailChargeConsumedMaMs =
12604                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
12605         long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
12606         for (int i = 0; i < timeInRatMs.length; i++) {
12607            timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTime, which) / 1000;
12608         }
12609         long[] timeInRxSignalStrengthLevelMs = new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
12610         for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
12611            timeInRxSignalStrengthLevelMs[i]
12612                = getPhoneSignalStrengthTime(i, rawRealTime, which) / 1000;
12613         }
12614         long[] txTimeMs = new long[Math.min(ModemActivityInfo.TX_POWER_LEVELS,
12615             counter.getTxTimeCounters().length)];
12616         long totalTxTimeMs = 0;
12617         for (int i = 0; i < txTimeMs.length; i++) {
12618             txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
12619             totalTxTimeMs += txTimeMs[i];
12620         }
12621         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
12622         s.setKernelActiveTimeMs(getMobileRadioActiveTime(rawRealTime, which) / 1000);
12623         s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which));
12624         s.setNumBytesTx(getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which));
12625         s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which));
12626         s.setNumBytesRx(getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which));
12627         s.setSleepTimeMs(sleepTimeMs);
12628         s.setIdleTimeMs(idleTimeMs);
12629         s.setRxTimeMs(rxTimeMs);
12630         s.setEnergyConsumedMaMs(energyConsumedMaMs);
12631         s.setTimeInRatMs(timeInRatMs);
12632         s.setTimeInRxSignalStrengthLevelMs(timeInRxSignalStrengthLevelMs);
12633         s.setTxTimeMs(txTimeMs);
12634         s.setMonitoredRailChargeConsumedMaMs(monitoredRailChargeConsumedMaMs);
12635         return s;
12636     }
12637 
12638     /*@hide */
getWifiBatteryStats()12639     public WifiBatteryStats getWifiBatteryStats() {
12640         WifiBatteryStats s = new WifiBatteryStats();
12641         final int which = STATS_SINCE_CHARGED;
12642         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
12643         final ControllerActivityCounter counter = getWifiControllerActivity();
12644         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
12645         final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which);
12646         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
12647         final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which);
12648         final long totalControllerActivityTimeMs
12649                 = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000;
12650         final long sleepTimeMs
12651                 = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs);
12652         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
12653         final long monitoredRailChargeConsumedMaMs =
12654                 counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which);
12655         long numAppScanRequest = 0;
12656         for (int i = 0; i < mUidStats.size(); i++) {
12657             numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which);
12658         }
12659         long[] timeInStateMs = new long[NUM_WIFI_STATES];
12660         for (int i=0; i<NUM_WIFI_STATES; i++) {
12661             timeInStateMs[i] = getWifiStateTime(i, rawRealTime, which) / 1000;
12662         }
12663         long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES];
12664         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
12665             timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTime, which) / 1000;
12666         }
12667         long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS];
12668         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
12669             timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTime, which) / 1000;
12670         }
12671         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
12672         s.setKernelActiveTimeMs(getWifiActiveTime(rawRealTime, which) / 1000);
12673         s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which));
12674         s.setNumBytesTx(getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which));
12675         s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which));
12676         s.setNumBytesRx(getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which));
12677         s.setSleepTimeMs(sleepTimeMs);
12678         s.setIdleTimeMs(idleTimeMs);
12679         s.setRxTimeMs(rxTimeMs);
12680         s.setTxTimeMs(txTimeMs);
12681         s.setScanTimeMs(scanTimeMs);
12682         s.setEnergyConsumedMaMs(energyConsumedMaMs);
12683         s.setNumAppScanRequest(numAppScanRequest);
12684         s.setTimeInStateMs(timeInStateMs);
12685         s.setTimeInSupplicantStateMs(timeInSupplStateMs);
12686         s.setTimeInRxSignalStrengthLevelMs(timeSignalStrengthTimeMs);
12687         s.setMonitoredRailChargeConsumedMaMs(monitoredRailChargeConsumedMaMs);
12688         return s;
12689     }
12690 
12691     /*@hide */
getGpsBatteryStats()12692     public GpsBatteryStats getGpsBatteryStats() {
12693         GpsBatteryStats s = new GpsBatteryStats();
12694         final int which = STATS_SINCE_CHARGED;
12695         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
12696         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
12697         s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
12698         long[] time = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
12699         for (int i=0; i<time.length; i++) {
12700             time[i] = getGpsSignalQualityTime(i, rawRealTime, which) / 1000;
12701         }
12702         s.setTimeInGpsSignalQualityLevel(time);
12703         return s;
12704     }
12705 
12706     @Override
getChargeLevelStepTracker()12707     public LevelStepTracker getChargeLevelStepTracker() {
12708         return mChargeStepTracker;
12709     }
12710 
12711     @Override
getDailyChargeLevelStepTracker()12712     public LevelStepTracker getDailyChargeLevelStepTracker() {
12713         return mDailyChargeStepTracker;
12714     }
12715 
12716     @Override
getDailyPackageChanges()12717     public ArrayList<PackageChange> getDailyPackageChanges() {
12718         return mDailyPackageChanges;
12719     }
12720 
getBatteryUptimeLocked()12721     protected long getBatteryUptimeLocked() {
12722         return mOnBatteryTimeBase.getUptime(mClocks.uptimeMillis() * 1000);
12723     }
12724 
12725     @Override
getBatteryUptime(long curTime)12726     public long getBatteryUptime(long curTime) {
12727         return mOnBatteryTimeBase.getUptime(curTime);
12728     }
12729 
12730     @Override
12731     @UnsupportedAppUsage
getBatteryRealtime(long curTime)12732     public long getBatteryRealtime(long curTime) {
12733         return mOnBatteryTimeBase.getRealtime(curTime);
12734     }
12735 
12736     @Override
12737     @UnsupportedAppUsage
getDischargeStartLevel()12738     public int getDischargeStartLevel() {
12739         synchronized(this) {
12740             return getDischargeStartLevelLocked();
12741         }
12742     }
12743 
getDischargeStartLevelLocked()12744     public int getDischargeStartLevelLocked() {
12745             return mDischargeUnplugLevel;
12746     }
12747 
12748     @Override
12749     @UnsupportedAppUsage
getDischargeCurrentLevel()12750     public int getDischargeCurrentLevel() {
12751         synchronized(this) {
12752             return getDischargeCurrentLevelLocked();
12753         }
12754     }
12755 
getDischargeCurrentLevelLocked()12756     public int getDischargeCurrentLevelLocked() {
12757         return mDischargeCurrentLevel;
12758     }
12759 
12760     @Override
getLowDischargeAmountSinceCharge()12761     public int getLowDischargeAmountSinceCharge() {
12762         synchronized(this) {
12763             int val = mLowDischargeAmountSinceCharge;
12764             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
12765                 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
12766             }
12767             return val;
12768         }
12769     }
12770 
12771     @Override
getHighDischargeAmountSinceCharge()12772     public int getHighDischargeAmountSinceCharge() {
12773         synchronized(this) {
12774             int val = mHighDischargeAmountSinceCharge;
12775             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
12776                 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
12777             }
12778             return val;
12779         }
12780     }
12781 
12782     @Override
12783     @UnsupportedAppUsage
getDischargeAmount(int which)12784     public int getDischargeAmount(int which) {
12785         int dischargeAmount = which == STATS_SINCE_CHARGED
12786                 ? getHighDischargeAmountSinceCharge()
12787                 : (getDischargeStartLevel() - getDischargeCurrentLevel());
12788         if (dischargeAmount < 0) {
12789             dischargeAmount = 0;
12790         }
12791         return dischargeAmount;
12792     }
12793 
12794     @Override
12795     @UnsupportedAppUsage
getDischargeAmountScreenOn()12796     public int getDischargeAmountScreenOn() {
12797         synchronized(this) {
12798             int val = mDischargeAmountScreenOn;
12799             if (mOnBattery && isScreenOn(mScreenState)
12800                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
12801                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
12802             }
12803             return val;
12804         }
12805     }
12806 
12807     @Override
getDischargeAmountScreenOnSinceCharge()12808     public int getDischargeAmountScreenOnSinceCharge() {
12809         synchronized(this) {
12810             int val = mDischargeAmountScreenOnSinceCharge;
12811             if (mOnBattery && isScreenOn(mScreenState)
12812                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
12813                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
12814             }
12815             return val;
12816         }
12817     }
12818 
12819     @Override
12820     @UnsupportedAppUsage
getDischargeAmountScreenOff()12821     public int getDischargeAmountScreenOff() {
12822         synchronized(this) {
12823             int val = mDischargeAmountScreenOff;
12824             if (mOnBattery && isScreenOff(mScreenState)
12825                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
12826                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
12827             }
12828             // For backward compatibility, doze discharge is counted into screen off.
12829             return val + getDischargeAmountScreenDoze();
12830         }
12831     }
12832 
12833     @Override
getDischargeAmountScreenOffSinceCharge()12834     public int getDischargeAmountScreenOffSinceCharge() {
12835         synchronized(this) {
12836             int val = mDischargeAmountScreenOffSinceCharge;
12837             if (mOnBattery && isScreenOff(mScreenState)
12838                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
12839                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
12840             }
12841             // For backward compatibility, doze discharge is counted into screen off.
12842             return val + getDischargeAmountScreenDozeSinceCharge();
12843         }
12844     }
12845 
12846     @Override
getDischargeAmountScreenDoze()12847     public int getDischargeAmountScreenDoze() {
12848         synchronized(this) {
12849             int val = mDischargeAmountScreenDoze;
12850             if (mOnBattery && isScreenDoze(mScreenState)
12851                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
12852                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
12853             }
12854             return val;
12855         }
12856     }
12857 
12858     @Override
getDischargeAmountScreenDozeSinceCharge()12859     public int getDischargeAmountScreenDozeSinceCharge() {
12860         synchronized(this) {
12861             int val = mDischargeAmountScreenDozeSinceCharge;
12862             if (mOnBattery && isScreenDoze(mScreenState)
12863                     && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
12864                 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
12865             }
12866             return val;
12867         }
12868     }
12869 
12870     /**
12871      * Retrieve the statistics object for a particular uid, creating if needed.
12872      */
12873     @UnsupportedAppUsage
getUidStatsLocked(int uid)12874     public Uid getUidStatsLocked(int uid) {
12875         Uid u = mUidStats.get(uid);
12876         if (u == null) {
12877             u = new Uid(this, uid);
12878             mUidStats.put(uid, u);
12879         }
12880         return u;
12881     }
12882 
12883     /**
12884      * Retrieve the statistics object for a particular uid. Returns null if the object is not
12885      * available.
12886      */
getAvailableUidStatsLocked(int uid)12887     public Uid getAvailableUidStatsLocked(int uid) {
12888         Uid u = mUidStats.get(uid);
12889         return u;
12890     }
12891 
onCleanupUserLocked(int userId)12892     public void onCleanupUserLocked(int userId) {
12893         final int firstUidForUser = UserHandle.getUid(userId, 0);
12894         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
12895         mPendingRemovedUids.add(
12896                 new UidToRemove(firstUidForUser, lastUidForUser, mClocks.elapsedRealtime()));
12897     }
12898 
onUserRemovedLocked(int userId)12899     public void onUserRemovedLocked(int userId) {
12900         final int firstUidForUser = UserHandle.getUid(userId, 0);
12901         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
12902         mUidStats.put(firstUidForUser, null);
12903         mUidStats.put(lastUidForUser, null);
12904         final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
12905         final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
12906         for (int i = firstIndex; i <= lastIndex; i++) {
12907             final Uid uid = mUidStats.valueAt(i);
12908             if (uid != null) {
12909                 uid.detachFromTimeBase();
12910             }
12911         }
12912         mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
12913     }
12914 
12915     /**
12916      * Remove the statistics object for a particular uid.
12917      */
12918     @UnsupportedAppUsage
removeUidStatsLocked(int uid)12919     public void removeUidStatsLocked(int uid) {
12920         final Uid u = mUidStats.get(uid);
12921         if (u != null) {
12922             u.detachFromTimeBase();
12923         }
12924         mUidStats.remove(uid);
12925         mPendingRemovedUids.add(new UidToRemove(uid, mClocks.elapsedRealtime()));
12926     }
12927 
12928     /**
12929      * Retrieve the statistics object for a particular process, creating
12930      * if needed.
12931      */
12932     @UnsupportedAppUsage
getProcessStatsLocked(int uid, String name)12933     public Uid.Proc getProcessStatsLocked(int uid, String name) {
12934         uid = mapUid(uid);
12935         Uid u = getUidStatsLocked(uid);
12936         return u.getProcessStatsLocked(name);
12937     }
12938 
12939     /**
12940      * Retrieve the statistics object for a particular process, creating
12941      * if needed.
12942      */
12943     @UnsupportedAppUsage
getPackageStatsLocked(int uid, String pkg)12944     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
12945         uid = mapUid(uid);
12946         Uid u = getUidStatsLocked(uid);
12947         return u.getPackageStatsLocked(pkg);
12948     }
12949 
12950     /**
12951      * Retrieve the statistics object for a particular service, creating
12952      * if needed.
12953      */
12954     @UnsupportedAppUsage
getServiceStatsLocked(int uid, String pkg, String name)12955     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
12956         uid = mapUid(uid);
12957         Uid u = getUidStatsLocked(uid);
12958         return u.getServiceStatsLocked(pkg, name);
12959     }
12960 
shutdownLocked()12961     public void shutdownLocked() {
12962         recordShutdownLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
12963         writeSyncLocked();
12964         mShuttingDown = true;
12965     }
12966 
trackPerProcStateCpuTimes()12967     public boolean trackPerProcStateCpuTimes() {
12968         return mConstants.TRACK_CPU_TIMES_BY_PROC_STATE && mPerProcStateCpuTimesAvailable;
12969     }
12970 
systemServicesReady(Context context)12971     public void systemServicesReady(Context context) {
12972         mConstants.startObserving(context.getContentResolver());
12973         registerUsbStateReceiver(context);
12974     }
12975 
12976     @VisibleForTesting
12977     public final class Constants extends ContentObserver {
12978         public static final String KEY_TRACK_CPU_TIMES_BY_PROC_STATE
12979                 = "track_cpu_times_by_proc_state";
12980         public static final String KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME
12981                 = "track_cpu_active_cluster_time";
12982         public static final String KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS
12983                 = "proc_state_cpu_times_read_delay_ms";
12984         public static final String KEY_KERNEL_UID_READERS_THROTTLE_TIME
12985                 = "kernel_uid_readers_throttle_time";
12986         public static final String KEY_UID_REMOVE_DELAY_MS
12987                 = "uid_remove_delay_ms";
12988         public static final String KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
12989                 = "external_stats_collection_rate_limit_ms";
12990         public static final String KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS
12991                 = "battery_level_collection_delay_ms";
12992         public static final String KEY_MAX_HISTORY_FILES = "max_history_files";
12993         public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
12994         public static final String KEY_BATTERY_CHARGED_DELAY_MS =
12995                 "battery_charged_delay_ms";
12996 
12997         private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = false;
12998         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
12999         private static final long DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS = 5_000;
13000         private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000;
13001         private static final long DEFAULT_UID_REMOVE_DELAY_MS = 5L * 60L * 1000L;
13002         private static final long DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = 600_000;
13003         private static final long DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS = 300_000;
13004         private static final int DEFAULT_MAX_HISTORY_FILES = 32;
13005         private static final int DEFAULT_MAX_HISTORY_BUFFER_KB = 128; /*Kilo Bytes*/
13006         private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64;
13007         private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
13008         private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
13009 
13010         public boolean TRACK_CPU_TIMES_BY_PROC_STATE = DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE;
13011         public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
13012         public long PROC_STATE_CPU_TIMES_READ_DELAY_MS = DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS;
13013         /* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
13014          * update when startObserving. */
13015         public long KERNEL_UID_READERS_THROTTLE_TIME;
13016         public long UID_REMOVE_DELAY_MS = DEFAULT_UID_REMOVE_DELAY_MS;
13017         public long EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
13018                 = DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
13019         public long BATTERY_LEVEL_COLLECTION_DELAY_MS
13020                 = DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS;
13021         public int MAX_HISTORY_FILES;
13022         public int MAX_HISTORY_BUFFER; /*Bytes*/
13023         public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
13024 
13025         private ContentResolver mResolver;
13026         private final KeyValueListParser mParser = new KeyValueListParser(',');
13027 
Constants(Handler handler)13028         public Constants(Handler handler) {
13029             super(handler);
13030             if (ActivityManager.isLowRamDeviceStatic()) {
13031                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE;
13032                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB * 1024;
13033             } else {
13034                 MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES;
13035                 MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_KB * 1024;
13036             }
13037         }
13038 
startObserving(ContentResolver resolver)13039         public void startObserving(ContentResolver resolver) {
13040             mResolver = resolver;
13041             mResolver.registerContentObserver(
13042                     Settings.Global.getUriFor(Settings.Global.BATTERY_STATS_CONSTANTS),
13043                     false /* notifyForDescendants */, this);
13044             mResolver.registerContentObserver(
13045                     Settings.Global.getUriFor(Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY),
13046                     false /* notifyForDescendants */, this);
13047             updateConstants();
13048         }
13049 
13050         @Override
onChange(boolean selfChange, Uri uri)13051         public void onChange(boolean selfChange, Uri uri) {
13052             if (uri.equals(
13053                     Settings.Global.getUriFor(
13054                             Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY))) {
13055                 synchronized (BatteryStatsImpl.this) {
13056                     updateBatteryChargedDelayMsLocked();
13057                 }
13058                 return;
13059             }
13060             updateConstants();
13061         }
13062 
updateConstants()13063         private void updateConstants() {
13064             synchronized (BatteryStatsImpl.this) {
13065                 try {
13066                     mParser.setString(Settings.Global.getString(mResolver,
13067                             Settings.Global.BATTERY_STATS_CONSTANTS));
13068                 } catch (IllegalArgumentException e) {
13069                     // Failed to parse the settings string, log this and move on
13070                     // with defaults.
13071                     Slog.e(TAG, "Bad batterystats settings", e);
13072                 }
13073 
13074                 updateTrackCpuTimesByProcStateLocked(TRACK_CPU_TIMES_BY_PROC_STATE,
13075                         mParser.getBoolean(KEY_TRACK_CPU_TIMES_BY_PROC_STATE,
13076                                 DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE));
13077                 TRACK_CPU_ACTIVE_CLUSTER_TIME = mParser.getBoolean(
13078                         KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME, DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME);
13079                 updateProcStateCpuTimesReadDelayMs(PROC_STATE_CPU_TIMES_READ_DELAY_MS,
13080                         mParser.getLong(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS,
13081                                 DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS));
13082                 updateKernelUidReadersThrottleTime(KERNEL_UID_READERS_THROTTLE_TIME,
13083                         mParser.getLong(KEY_KERNEL_UID_READERS_THROTTLE_TIME,
13084                                 DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME));
13085                 updateUidRemoveDelay(
13086                         mParser.getLong(KEY_UID_REMOVE_DELAY_MS, DEFAULT_UID_REMOVE_DELAY_MS));
13087                 EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = mParser.getLong(
13088                         KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS,
13089                         DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
13090                 BATTERY_LEVEL_COLLECTION_DELAY_MS = mParser.getLong(
13091                         KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS,
13092                         DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS);
13093 
13094                 MAX_HISTORY_FILES = mParser.getInt(KEY_MAX_HISTORY_FILES,
13095                         ActivityManager.isLowRamDeviceStatic() ?
13096                                 DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE
13097                         : DEFAULT_MAX_HISTORY_FILES);
13098                 MAX_HISTORY_BUFFER = mParser.getInt(KEY_MAX_HISTORY_BUFFER_KB,
13099                         ActivityManager.isLowRamDeviceStatic() ?
13100                                 DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB
13101                                 : DEFAULT_MAX_HISTORY_BUFFER_KB)
13102                         * 1024;
13103                 updateBatteryChargedDelayMsLocked();
13104             }
13105         }
13106 
updateBatteryChargedDelayMsLocked()13107         private void updateBatteryChargedDelayMsLocked() {
13108             // a negative value indicates that we should ignore this override
13109             final int delay = Settings.Global.getInt(mResolver,
13110                     Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
13111                     -1);
13112 
13113             BATTERY_CHARGED_DELAY_MS = delay >= 0 ? delay : mParser.getInt(
13114                     KEY_BATTERY_CHARGED_DELAY_MS,
13115                     DEFAULT_BATTERY_CHARGED_DELAY_MS);
13116         }
13117 
updateTrackCpuTimesByProcStateLocked(boolean wasEnabled, boolean isEnabled)13118         private void updateTrackCpuTimesByProcStateLocked(boolean wasEnabled, boolean isEnabled) {
13119             TRACK_CPU_TIMES_BY_PROC_STATE = isEnabled;
13120             if (isEnabled && !wasEnabled) {
13121                 mIsPerProcessStateCpuDataStale = true;
13122                 mExternalSync.scheduleCpuSyncDueToSettingChange();
13123 
13124                 mNumSingleUidCpuTimeReads = 0;
13125                 mNumBatchedSingleUidCpuTimeReads = 0;
13126                 mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
13127             }
13128         }
13129 
updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis)13130         private void updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis) {
13131             PROC_STATE_CPU_TIMES_READ_DELAY_MS = newDelayMillis;
13132             if (oldDelayMillis != newDelayMillis) {
13133                 mNumSingleUidCpuTimeReads = 0;
13134                 mNumBatchedSingleUidCpuTimeReads = 0;
13135                 mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
13136             }
13137         }
13138 
updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs)13139         private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
13140             KERNEL_UID_READERS_THROTTLE_TIME = newTimeMs;
13141             if (oldTimeMs != newTimeMs) {
13142                 mCpuUidUserSysTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
13143                 mCpuUidFreqTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
13144                 mCpuUidActiveTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
13145                 mCpuUidClusterTimeReader
13146                         .setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
13147             }
13148         }
13149 
updateUidRemoveDelay(long newTimeMs)13150         private void updateUidRemoveDelay(long newTimeMs) {
13151             UID_REMOVE_DELAY_MS = newTimeMs;
13152             clearPendingRemovedUids();
13153         }
13154 
dumpLocked(PrintWriter pw)13155         public void dumpLocked(PrintWriter pw) {
13156             pw.print(KEY_TRACK_CPU_TIMES_BY_PROC_STATE); pw.print("=");
13157             pw.println(TRACK_CPU_TIMES_BY_PROC_STATE);
13158             pw.print(KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME); pw.print("=");
13159             pw.println(TRACK_CPU_ACTIVE_CLUSTER_TIME);
13160             pw.print(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS); pw.print("=");
13161             pw.println(PROC_STATE_CPU_TIMES_READ_DELAY_MS);
13162             pw.print(KEY_KERNEL_UID_READERS_THROTTLE_TIME); pw.print("=");
13163             pw.println(KERNEL_UID_READERS_THROTTLE_TIME);
13164             pw.print(KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS); pw.print("=");
13165             pw.println(EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
13166             pw.print(KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS); pw.print("=");
13167             pw.println(BATTERY_LEVEL_COLLECTION_DELAY_MS);
13168             pw.print(KEY_MAX_HISTORY_FILES); pw.print("=");
13169             pw.println(MAX_HISTORY_FILES);
13170             pw.print(KEY_MAX_HISTORY_BUFFER_KB); pw.print("=");
13171             pw.println(MAX_HISTORY_BUFFER/1024);
13172             pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("=");
13173             pw.println(BATTERY_CHARGED_DELAY_MS);
13174         }
13175     }
13176 
getExternalStatsCollectionRateLimitMs()13177     public long getExternalStatsCollectionRateLimitMs() {
13178         synchronized (this) {
13179             return mConstants.EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
13180         }
13181     }
13182 
13183     @GuardedBy("this")
dumpConstantsLocked(PrintWriter pw)13184     public void dumpConstantsLocked(PrintWriter pw) {
13185         mConstants.dumpLocked(pw);
13186     }
13187 
13188     @GuardedBy("this")
dumpCpuStatsLocked(PrintWriter pw)13189     public void dumpCpuStatsLocked(PrintWriter pw) {
13190         int size = mUidStats.size();
13191         pw.println("Per UID CPU user & system time in ms:");
13192         for (int i = 0; i < size; i++) {
13193             int u = mUidStats.keyAt(i);
13194             Uid uid = mUidStats.get(u);
13195             pw.print("  "); pw.print(u); pw.print(": ");
13196             pw.print(uid.getUserCpuTimeUs(STATS_SINCE_CHARGED) / 1000); pw.print(" ");
13197             pw.println(uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED) / 1000);
13198         }
13199         pw.println("Per UID CPU active time in ms:");
13200         for (int i = 0; i < size; i++) {
13201             int u = mUidStats.keyAt(i);
13202             Uid uid = mUidStats.get(u);
13203             if (uid.getCpuActiveTime() > 0) {
13204                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(uid.getCpuActiveTime());
13205             }
13206         }
13207         pw.println("Per UID CPU cluster time in ms:");
13208         for (int i = 0; i < size; i++) {
13209             int u = mUidStats.keyAt(i);
13210             long[] times = mUidStats.get(u).getCpuClusterTimes();
13211             if (times != null) {
13212                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
13213             }
13214         }
13215         pw.println("Per UID CPU frequency time in ms:");
13216         for (int i = 0; i < size; i++) {
13217             int u = mUidStats.keyAt(i);
13218             long[] times = mUidStats.get(u).getCpuFreqTimes(STATS_SINCE_CHARGED);
13219             if (times != null) {
13220                 pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
13221             }
13222         }
13223     }
13224 
13225     final ReentrantLock mWriteLock = new ReentrantLock();
13226 
writeAsyncLocked()13227     public void writeAsyncLocked() {
13228         writeStatsLocked(false);
13229         writeHistoryLocked(false);
13230     }
13231 
writeSyncLocked()13232     public void writeSyncLocked() {
13233         writeStatsLocked(true);
13234         writeHistoryLocked(true);
13235     }
13236 
writeStatsLocked(boolean sync)13237     void writeStatsLocked(boolean sync) {
13238         if (mStatsFile == null) {
13239             Slog.w(TAG,
13240                     "writeStatsLocked: no file associated with this instance");
13241             return;
13242         }
13243 
13244         if (mShuttingDown) {
13245             return;
13246         }
13247 
13248         final Parcel p = Parcel.obtain();
13249         final long start = SystemClock.uptimeMillis();
13250         writeSummaryToParcel(p, false/*history is in separate file*/);
13251         if (DEBUG) {
13252             Slog.d(TAG, "writeSummaryToParcel duration ms:"
13253                     + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
13254         }
13255         mLastWriteTime = mClocks.elapsedRealtime();
13256         writeParcelToFileLocked(p, mStatsFile, sync);
13257     }
13258 
writeHistoryLocked(boolean sync)13259     void writeHistoryLocked(boolean sync) {
13260         if (mBatteryStatsHistory.getActiveFile() == null) {
13261             Slog.w(TAG,
13262                     "writeHistoryLocked: no history file associated with this instance");
13263             return;
13264         }
13265 
13266         if (mShuttingDown) {
13267             return;
13268         }
13269 
13270         Parcel p = Parcel.obtain();
13271         final long start = SystemClock.uptimeMillis();
13272         writeHistoryBuffer(p, true, true);
13273         if (DEBUG) {
13274             Slog.d(TAG, "writeHistoryBuffer duration ms:"
13275                     + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
13276         }
13277         writeParcelToFileLocked(p, mBatteryStatsHistory.getActiveFile(), sync);
13278     }
13279 
writeParcelToFileLocked(Parcel p, AtomicFile file, boolean sync)13280     void writeParcelToFileLocked(Parcel p, AtomicFile file, boolean sync) {
13281         if (sync) {
13282             commitPendingDataToDisk(p, file);
13283         } else {
13284             BackgroundThread.getHandler().post(new Runnable() {
13285                 @Override public void run() {
13286                     commitPendingDataToDisk(p, file);
13287                 }
13288             });
13289         }
13290     }
13291 
commitPendingDataToDisk(Parcel p, AtomicFile file)13292     private void commitPendingDataToDisk(Parcel p, AtomicFile file) {
13293         mWriteLock.lock();
13294         FileOutputStream fos = null;
13295         try {
13296             final long startTime = SystemClock.uptimeMillis();
13297             fos = file.startWrite();
13298             fos.write(p.marshall());
13299             fos.flush();
13300             file.finishWrite(fos);
13301             if (DEBUG) {
13302                 Slog.d(TAG, "commitPendingDataToDisk file:" + file.getBaseFile().getPath()
13303                         + " duration ms:" + (SystemClock.uptimeMillis() - startTime)
13304                         + " bytes:" + p.dataSize());
13305             }
13306             com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
13307                     "batterystats", SystemClock.uptimeMillis() - startTime);
13308         } catch (IOException e) {
13309             Slog.w(TAG, "Error writing battery statistics", e);
13310             file.failWrite(fos);
13311         } finally {
13312             p.recycle();
13313             mWriteLock.unlock();
13314         }
13315     }
13316 
13317     @UnsupportedAppUsage
readLocked()13318     public void readLocked() {
13319         if (mDailyFile != null) {
13320             readDailyStatsLocked();
13321         }
13322 
13323         if (mStatsFile == null) {
13324             Slog.w(TAG, "readLocked: no file associated with this instance");
13325             return;
13326         }
13327 
13328         if (mBatteryStatsHistory.getActiveFile() == null) {
13329             Slog.w(TAG,
13330                     "readLocked: no history file associated with this instance");
13331             return;
13332         }
13333 
13334         mUidStats.clear();
13335 
13336         Parcel stats = Parcel.obtain();
13337         try {
13338             final long start = SystemClock.uptimeMillis();
13339             byte[] raw = mStatsFile.readFully();
13340             stats.unmarshall(raw, 0, raw.length);
13341             stats.setDataPosition(0);
13342             readSummaryFromParcel(stats);
13343             if (DEBUG) {
13344                 Slog.d(TAG, "readLocked stats file:" + mStatsFile.getBaseFile().getPath()
13345                         + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
13346                         - start));
13347             }
13348         } catch (Exception e) {
13349             Slog.e(TAG, "Error reading battery statistics", e);
13350             resetAllStatsLocked();
13351         } finally {
13352             stats.recycle();
13353         }
13354 
13355         Parcel history = Parcel.obtain();
13356         try {
13357             final long start = SystemClock.uptimeMillis();
13358             byte[] raw = mBatteryStatsHistory.getActiveFile().readFully();
13359             if (raw.length > 0) {
13360                 history.unmarshall(raw, 0, raw.length);
13361                 history.setDataPosition(0);
13362                 readHistoryBuffer(history, true);
13363             }
13364             if (DEBUG) {
13365                 Slog.d(TAG, "readLocked history file::"
13366                         + mBatteryStatsHistory.getActiveFile().getBaseFile().getPath()
13367                         + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
13368                         - start));
13369             }
13370         } catch (Exception e) {
13371             Slog.e(TAG, "Error reading battery history", e);
13372             clearHistoryLocked();
13373             mBatteryStatsHistory.resetAllFiles();
13374         } finally {
13375             history.recycle();
13376         }
13377 
13378         mEndPlatformVersion = Build.ID;
13379 
13380         if (mHistoryBuffer.dataPosition() > 0
13381                 || mBatteryStatsHistory.getFilesNumbers().size() > 1) {
13382             mRecordingHistory = true;
13383             final long elapsedRealtime = mClocks.elapsedRealtime();
13384             final long uptime = mClocks.uptimeMillis();
13385             if (USE_OLD_HISTORY) {
13386                 addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
13387             }
13388             addHistoryBufferLocked(elapsedRealtime, HistoryItem.CMD_START, mHistoryCur);
13389             startRecordingHistory(elapsedRealtime, uptime, false);
13390         }
13391 
13392         recordDailyStatsIfNeededLocked(false);
13393     }
13394 
describeContents()13395     public int describeContents() {
13396         return 0;
13397     }
13398 
readHistoryBuffer(Parcel in, boolean andOldHistory)13399     void  readHistoryBuffer(Parcel in, boolean andOldHistory) throws ParcelFormatException {
13400         final int version = in.readInt();
13401         if (version != VERSION) {
13402             Slog.w("BatteryStats", "readHistoryBuffer: version got " + version
13403                     + ", expected " + VERSION + "; erasing old stats");
13404             return;
13405         }
13406 
13407         final long historyBaseTime = in.readLong();
13408 
13409         mHistoryBuffer.setDataSize(0);
13410         mHistoryBuffer.setDataPosition(0);
13411 
13412         int bufSize = in.readInt();
13413         int curPos = in.dataPosition();
13414         if (bufSize >= (mConstants.MAX_HISTORY_BUFFER*100)) {
13415             throw new ParcelFormatException("File corrupt: history data buffer too large " +
13416                     bufSize);
13417         } else if ((bufSize&~3) != bufSize) {
13418             throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
13419                     bufSize);
13420         } else {
13421             if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
13422                     + " bytes at " + curPos);
13423             mHistoryBuffer.appendFrom(in, curPos, bufSize);
13424             in.setDataPosition(curPos + bufSize);
13425         }
13426 
13427         if (andOldHistory) {
13428             readOldHistory(in);
13429         }
13430 
13431         if (DEBUG_HISTORY) {
13432             StringBuilder sb = new StringBuilder(128);
13433             sb.append("****************** OLD mHistoryBaseTime: ");
13434             TimeUtils.formatDuration(mHistoryBaseTime, sb);
13435             Slog.i(TAG, sb.toString());
13436         }
13437         mHistoryBaseTime = historyBaseTime;
13438         if (DEBUG_HISTORY) {
13439             StringBuilder sb = new StringBuilder(128);
13440             sb.append("****************** NEW mHistoryBaseTime: ");
13441             TimeUtils.formatDuration(mHistoryBaseTime, sb);
13442             Slog.i(TAG, sb.toString());
13443         }
13444 
13445         // We are just arbitrarily going to insert 1 minute from the sample of
13446         // the last run until samples in this run.
13447         if (mHistoryBaseTime > 0) {
13448             long oldnow = mClocks.elapsedRealtime();
13449             mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
13450             if (DEBUG_HISTORY) {
13451                 StringBuilder sb = new StringBuilder(128);
13452                 sb.append("****************** ADJUSTED mHistoryBaseTime: ");
13453                 TimeUtils.formatDuration(mHistoryBaseTime, sb);
13454                 Slog.i(TAG, sb.toString());
13455             }
13456         }
13457     }
13458 
readOldHistory(Parcel in)13459     void readOldHistory(Parcel in) {
13460         if (!USE_OLD_HISTORY) {
13461             return;
13462         }
13463         mHistory = mHistoryEnd = mHistoryCache = null;
13464         long time;
13465         while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
13466             HistoryItem rec = new HistoryItem(time, in);
13467             addHistoryRecordLocked(rec);
13468         }
13469     }
13470 
writeHistoryBuffer(Parcel out, boolean inclData, boolean andOldHistory)13471     void writeHistoryBuffer(Parcel out, boolean inclData, boolean andOldHistory) {
13472         if (DEBUG_HISTORY) {
13473             StringBuilder sb = new StringBuilder(128);
13474             sb.append("****************** WRITING mHistoryBaseTime: ");
13475             TimeUtils.formatDuration(mHistoryBaseTime, sb);
13476             sb.append(" mLastHistoryElapsedRealtime: ");
13477             TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
13478             Slog.i(TAG, sb.toString());
13479         }
13480         out.writeInt(VERSION);
13481         out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
13482         if (!inclData) {
13483             out.writeInt(0);
13484             out.writeInt(0);
13485             return;
13486         }
13487 
13488         out.writeInt(mHistoryBuffer.dataSize());
13489         if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
13490                 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
13491         out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
13492 
13493         if (andOldHistory) {
13494             writeOldHistory(out);
13495         }
13496     }
13497 
writeOldHistory(Parcel out)13498     void writeOldHistory(Parcel out) {
13499         if (!USE_OLD_HISTORY) {
13500             return;
13501         }
13502         HistoryItem rec = mHistory;
13503         while (rec != null) {
13504             if (rec.time >= 0) rec.writeToParcel(out, 0);
13505             rec = rec.next;
13506         }
13507         out.writeLong(-1);
13508     }
13509 
readSummaryFromParcel(Parcel in)13510     public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
13511         final int version = in.readInt();
13512         if (version != VERSION) {
13513             Slog.w("BatteryStats", "readFromParcel: version got " + version
13514                 + ", expected " + VERSION + "; erasing old stats");
13515             return;
13516         }
13517 
13518         boolean inclHistory = in.readBoolean();
13519         if (inclHistory) {
13520             readHistoryBuffer(in, true);
13521             mBatteryStatsHistory.readFromParcel(in);
13522         }
13523 
13524         mHistoryTagPool.clear();
13525         mNextHistoryTagIdx = 0;
13526         mNumHistoryTagChars = 0;
13527 
13528         int numTags = in.readInt();
13529         for (int i=0; i<numTags; i++) {
13530             int idx = in.readInt();
13531             String str = in.readString();
13532             if (str == null) {
13533                 throw new ParcelFormatException("null history tag string");
13534             }
13535             int uid = in.readInt();
13536             HistoryTag tag = new HistoryTag();
13537             tag.string = str;
13538             tag.uid = uid;
13539             tag.poolIdx = idx;
13540             mHistoryTagPool.put(tag, idx);
13541             if (idx >= mNextHistoryTagIdx) {
13542                 mNextHistoryTagIdx = idx+1;
13543             }
13544             mNumHistoryTagChars += tag.string.length() + 1;
13545         }
13546 
13547         mStartCount = in.readInt();
13548         mUptime = in.readLong();
13549         mRealtime = in.readLong();
13550         mStartClockTime = in.readLong();
13551         mStartPlatformVersion = in.readString();
13552         mEndPlatformVersion = in.readString();
13553         mOnBatteryTimeBase.readSummaryFromParcel(in);
13554         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
13555         mDischargeUnplugLevel = in.readInt();
13556         mDischargePlugLevel = in.readInt();
13557         mDischargeCurrentLevel = in.readInt();
13558         mCurrentBatteryLevel = in.readInt();
13559         mEstimatedBatteryCapacity = in.readInt();
13560         mMinLearnedBatteryCapacity = in.readInt();
13561         mMaxLearnedBatteryCapacity = in.readInt();
13562         mLowDischargeAmountSinceCharge = in.readInt();
13563         mHighDischargeAmountSinceCharge = in.readInt();
13564         mDischargeAmountScreenOnSinceCharge = in.readInt();
13565         mDischargeAmountScreenOffSinceCharge = in.readInt();
13566         mDischargeAmountScreenDozeSinceCharge = in.readInt();
13567         mDischargeStepTracker.readFromParcel(in);
13568         mChargeStepTracker.readFromParcel(in);
13569         mDailyDischargeStepTracker.readFromParcel(in);
13570         mDailyChargeStepTracker.readFromParcel(in);
13571         mDischargeCounter.readSummaryFromParcelLocked(in);
13572         mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
13573         mDischargeScreenDozeCounter.readSummaryFromParcelLocked(in);
13574         mDischargeLightDozeCounter.readSummaryFromParcelLocked(in);
13575         mDischargeDeepDozeCounter.readSummaryFromParcelLocked(in);
13576         int NPKG = in.readInt();
13577         if (NPKG > 0) {
13578             mDailyPackageChanges = new ArrayList<>(NPKG);
13579             while (NPKG > 0) {
13580                 NPKG--;
13581                 PackageChange pc = new PackageChange();
13582                 pc.mPackageName = in.readString();
13583                 pc.mUpdate = in.readInt() != 0;
13584                 pc.mVersionCode = in.readLong();
13585                 mDailyPackageChanges.add(pc);
13586             }
13587         } else {
13588             mDailyPackageChanges = null;
13589         }
13590         mDailyStartTime = in.readLong();
13591         mNextMinDailyDeadline = in.readLong();
13592         mNextMaxDailyDeadline = in.readLong();
13593 
13594         mStartCount++;
13595 
13596         mScreenState = Display.STATE_UNKNOWN;
13597         mScreenOnTimer.readSummaryFromParcelLocked(in);
13598         mScreenDozeTimer.readSummaryFromParcelLocked(in);
13599         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
13600             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
13601         }
13602         mInteractive = false;
13603         mInteractiveTimer.readSummaryFromParcelLocked(in);
13604         mPhoneOn = false;
13605         mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
13606         mLongestLightIdleTime = in.readLong();
13607         mLongestFullIdleTime = in.readLong();
13608         mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
13609         mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
13610         mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
13611         mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
13612         mPhoneOnTimer.readSummaryFromParcelLocked(in);
13613         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
13614             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
13615         }
13616         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
13617         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
13618             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
13619         }
13620         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
13621             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
13622             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
13623         }
13624         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
13625         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
13626         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
13627         mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
13628         mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
13629         mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
13630         mWifiMulticastWakelockTimer.readSummaryFromParcelLocked(in);
13631         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
13632         mWifiOn = false;
13633         mWifiOnTimer.readSummaryFromParcelLocked(in);
13634         mGlobalWifiRunning = false;
13635         mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
13636         for (int i=0; i<NUM_WIFI_STATES; i++) {
13637             mWifiStateTimer[i].readSummaryFromParcelLocked(in);
13638         }
13639         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
13640             mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
13641         }
13642         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
13643             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
13644         }
13645         mWifiActiveTimer.readSummaryFromParcelLocked(in);
13646         mWifiActivity.readSummaryFromParcel(in);
13647         for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
13648             mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
13649         }
13650         mBluetoothActivity.readSummaryFromParcel(in);
13651         mModemActivity.readSummaryFromParcel(in);
13652         mHasWifiReporting = in.readInt() != 0;
13653         mHasBluetoothReporting = in.readInt() != 0;
13654         mHasModemReporting = in.readInt() != 0;
13655 
13656         mNumConnectivityChange = in.readInt();
13657         mFlashlightOnNesting = 0;
13658         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
13659         mCameraOnNesting = 0;
13660         mCameraOnTimer.readSummaryFromParcelLocked(in);
13661         mBluetoothScanNesting = 0;
13662         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
13663         mIsCellularTxPowerHigh = false;
13664 
13665         int NRPMS = in.readInt();
13666         if (NRPMS > 10000) {
13667             throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS);
13668         }
13669         for (int irpm = 0; irpm < NRPMS; irpm++) {
13670             if (in.readInt() != 0) {
13671                 String rpmName = in.readString();
13672                 getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
13673             }
13674         }
13675         int NSORPMS = in.readInt();
13676         if (NSORPMS > 10000) {
13677             throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS);
13678         }
13679         for (int irpm = 0; irpm < NSORPMS; irpm++) {
13680             if (in.readInt() != 0) {
13681                 String rpmName = in.readString();
13682                 getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
13683             }
13684         }
13685 
13686         int NKW = in.readInt();
13687         if (NKW > 10000) {
13688             throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
13689         }
13690         for (int ikw = 0; ikw < NKW; ikw++) {
13691             if (in.readInt() != 0) {
13692                 String kwltName = in.readString();
13693                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
13694             }
13695         }
13696 
13697         int NWR = in.readInt();
13698         if (NWR > 10000) {
13699             throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
13700         }
13701         for (int iwr = 0; iwr < NWR; iwr++) {
13702             if (in.readInt() != 0) {
13703                 String reasonName = in.readString();
13704                 getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
13705             }
13706         }
13707 
13708         int NMS = in.readInt();
13709         for (int ims = 0; ims < NMS; ims++) {
13710             if (in.readInt() != 0) {
13711                 long kmstName = in.readLong();
13712                 getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
13713             }
13714         }
13715 
13716         final int NU = in.readInt();
13717         if (NU > 10000) {
13718             throw new ParcelFormatException("File corrupt: too many uids " + NU);
13719         }
13720         for (int iu = 0; iu < NU; iu++) {
13721             int uid = in.readInt();
13722             Uid u = new Uid(this, uid);
13723             mUidStats.put(uid, u);
13724 
13725             u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
13726             u.mOnBatteryScreenOffBackgroundTimeBase.readSummaryFromParcel(in);
13727 
13728             u.mWifiRunning = false;
13729             if (in.readInt() != 0) {
13730                 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
13731             }
13732             u.mFullWifiLockOut = false;
13733             if (in.readInt() != 0) {
13734                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
13735             }
13736             u.mWifiScanStarted = false;
13737             if (in.readInt() != 0) {
13738                 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
13739             }
13740             u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
13741             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
13742                 if (in.readInt() != 0) {
13743                     u.makeWifiBatchedScanBin(i, null);
13744                     u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
13745                 }
13746             }
13747             u.mWifiMulticastWakelockCount = 0;
13748             if (in.readInt() != 0) {
13749                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
13750             }
13751             if (in.readInt() != 0) {
13752                 u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13753             }
13754             if (in.readInt() != 0) {
13755                 u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13756             }
13757             if (in.readInt() != 0) {
13758                 u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13759             }
13760             if (in.readInt() != 0) {
13761                 u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13762             }
13763             if (in.readInt() != 0) {
13764                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
13765             }
13766             if (in.readInt() != 0) {
13767                 u.createForegroundServiceTimerLocked().readSummaryFromParcelLocked(in);
13768             }
13769             if (in.readInt() != 0) {
13770                 u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
13771             }
13772             if (in.readInt() != 0) {
13773                 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
13774             }
13775             if (in.readInt() != 0) {
13776                 u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in);
13777             }
13778             if (in.readInt() != 0) {
13779                 u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
13780             }
13781             if (in.readInt() != 0) {
13782                 u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in);
13783             }
13784             u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
13785             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
13786                 if (in.readInt() != 0) {
13787                     u.makeProcessState(i, null);
13788                     u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
13789                 }
13790             }
13791             if (in.readInt() != 0) {
13792                 u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
13793             }
13794 
13795             if (in.readInt() != 0) {
13796                 if (u.mUserActivityCounters == null) {
13797                     u.initUserActivityLocked();
13798                 }
13799                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
13800                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
13801                 }
13802             }
13803 
13804             if (in.readInt() != 0) {
13805                 if (u.mNetworkByteActivityCounters == null) {
13806                     u.initNetworkActivityLocked();
13807                 }
13808                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
13809                     u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
13810                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
13811                 }
13812                 u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
13813                 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
13814             }
13815 
13816             u.mUserCpuTime.readSummaryFromParcelLocked(in);
13817             u.mSystemCpuTime.readSummaryFromParcelLocked(in);
13818 
13819             if (in.readInt() != 0) {
13820                 final int numClusters = in.readInt();
13821                 if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
13822                     throw new ParcelFormatException("Incompatible cpu cluster arrangement");
13823                 }
13824                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
13825                 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
13826                 for (int cluster = 0; cluster < numClusters; cluster++) {
13827                     if (in.readInt() != 0) {
13828                         final int NSB = in.readInt();
13829                         if (mPowerProfile != null &&
13830                                 mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
13831                             throw new ParcelFormatException("File corrupt: too many speed bins " +
13832                                     NSB);
13833                         }
13834 
13835                         u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[NSB];
13836                         for (int speed = 0; speed < NSB; speed++) {
13837                             if (in.readInt() != 0) {
13838                                 u.mCpuClusterSpeedTimesUs[cluster][speed] = new LongSamplingCounter(
13839                                         mOnBatteryTimeBase);
13840                                 u.mCpuClusterSpeedTimesUs[cluster][speed].readSummaryFromParcelLocked(in);
13841                             }
13842                         }
13843                     } else {
13844                         u.mCpuClusterSpeedTimesUs[cluster] = null;
13845                     }
13846                 }
13847             } else {
13848                 detachIfNotNull(u.mCpuClusterSpeedTimesUs);
13849                 u.mCpuClusterSpeedTimesUs = null;
13850             }
13851 
13852             detachIfNotNull(u.mCpuFreqTimeMs);
13853             u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
13854                     in, mOnBatteryTimeBase);
13855             detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
13856             u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
13857                     in, mOnBatteryScreenOffTimeBase);
13858 
13859             u.mCpuActiveTimeMs.readSummaryFromParcelLocked(in);
13860             u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
13861 
13862             int length = in.readInt();
13863             if (length == Uid.NUM_PROCESS_STATE) {
13864                 detachIfNotNull(u.mProcStateTimeMs);
13865                 u.mProcStateTimeMs = new LongSamplingCounterArray[length];
13866                 for (int procState = 0; procState < length; ++procState) {
13867                     u.mProcStateTimeMs[procState]
13868                             = LongSamplingCounterArray.readSummaryFromParcelLocked(
13869                                     in, mOnBatteryTimeBase);
13870                 }
13871             } else {
13872                 detachIfNotNull(u.mProcStateTimeMs);
13873                 u.mProcStateTimeMs = null;
13874             }
13875             length = in.readInt();
13876             if (length == Uid.NUM_PROCESS_STATE) {
13877                 detachIfNotNull(u.mProcStateScreenOffTimeMs);
13878                 u.mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
13879                 for (int procState = 0; procState < length; ++procState) {
13880                     u.mProcStateScreenOffTimeMs[procState]
13881                             = LongSamplingCounterArray.readSummaryFromParcelLocked(
13882                                     in, mOnBatteryScreenOffTimeBase);
13883                 }
13884             } else {
13885                 detachIfNotNull(u.mProcStateScreenOffTimeMs);
13886                 u.mProcStateScreenOffTimeMs = null;
13887             }
13888 
13889             if (in.readInt() != 0) {
13890                 detachIfNotNull(u.mMobileRadioApWakeupCount);
13891                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
13892                 u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
13893             } else {
13894                 detachIfNotNull(u.mMobileRadioApWakeupCount);
13895                 u.mMobileRadioApWakeupCount = null;
13896             }
13897 
13898             if (in.readInt() != 0) {
13899                 detachIfNotNull(u.mWifiRadioApWakeupCount);
13900                 u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
13901                 u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
13902             } else {
13903                 detachIfNotNull(u.mWifiRadioApWakeupCount);
13904                 u.mWifiRadioApWakeupCount = null;
13905             }
13906 
13907             int NW = in.readInt();
13908             if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
13909                 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
13910             }
13911             for (int iw = 0; iw < NW; iw++) {
13912                 String wlName = in.readString();
13913                 u.readWakeSummaryFromParcelLocked(wlName, in);
13914             }
13915 
13916             int NS = in.readInt();
13917             if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
13918                 throw new ParcelFormatException("File corrupt: too many syncs " + NS);
13919             }
13920             for (int is = 0; is < NS; is++) {
13921                 String name = in.readString();
13922                 u.readSyncSummaryFromParcelLocked(name, in);
13923             }
13924 
13925             int NJ = in.readInt();
13926             if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
13927                 throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
13928             }
13929             for (int ij = 0; ij < NJ; ij++) {
13930                 String name = in.readString();
13931                 u.readJobSummaryFromParcelLocked(name, in);
13932             }
13933 
13934             u.readJobCompletionsFromParcelLocked(in);
13935 
13936             u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in);
13937             u.mJobsDeferredCount.readSummaryFromParcelLocked(in);
13938             u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in);
13939             detachIfNotNull(u.mJobsFreshnessBuckets);
13940             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
13941                 if (in.readInt() != 0) {
13942                     u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase);
13943                     u.mJobsFreshnessBuckets[i].readSummaryFromParcelLocked(in);
13944                 }
13945             }
13946 
13947             int NP = in.readInt();
13948             if (NP > 1000) {
13949                 throw new ParcelFormatException("File corrupt: too many sensors " + NP);
13950             }
13951             for (int is = 0; is < NP; is++) {
13952                 int seNumber = in.readInt();
13953                 if (in.readInt() != 0) {
13954                     u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
13955                 }
13956             }
13957 
13958             NP = in.readInt();
13959             if (NP > 1000) {
13960                 throw new ParcelFormatException("File corrupt: too many processes " + NP);
13961             }
13962             for (int ip = 0; ip < NP; ip++) {
13963                 String procName = in.readString();
13964                 Uid.Proc p = u.getProcessStatsLocked(procName);
13965                 p.mUserTime = in.readLong();
13966                 p.mSystemTime = in.readLong();
13967                 p.mForegroundTime = in.readLong();
13968                 p.mStarts = in.readInt();
13969                 p.mNumCrashes = in.readInt();
13970                 p.mNumAnrs = in.readInt();
13971                 p.readExcessivePowerFromParcelLocked(in);
13972             }
13973 
13974             NP = in.readInt();
13975             if (NP > 10000) {
13976                 throw new ParcelFormatException("File corrupt: too many packages " + NP);
13977             }
13978             for (int ip = 0; ip < NP; ip++) {
13979                 String pkgName = in.readString();
13980                 detachIfNotNull(u.mPackageStats.get(pkgName));
13981                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
13982                 final int NWA = in.readInt();
13983                 if (NWA > 10000) {
13984                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
13985                 }
13986                 p.mWakeupAlarms.clear();
13987                 for (int iwa = 0; iwa < NWA; iwa++) {
13988                     String tag = in.readString();
13989                     Counter c = new Counter(mOnBatteryScreenOffTimeBase);
13990                     c.readSummaryFromParcelLocked(in);
13991                     p.mWakeupAlarms.put(tag, c);
13992                 }
13993                 NS = in.readInt();
13994                 if (NS > 10000) {
13995                     throw new ParcelFormatException("File corrupt: too many services " + NS);
13996                 }
13997                 for (int is = 0; is < NS; is++) {
13998                     String servName = in.readString();
13999                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
14000                     s.mStartTime = in.readLong();
14001                     s.mStarts = in.readInt();
14002                     s.mLaunches = in.readInt();
14003                 }
14004             }
14005         }
14006     }
14007 
14008     /**
14009      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
14010      * disk.  This format does not allow a lossless round-trip.
14011      *
14012      * @param out the Parcel to be written to.
14013      */
writeSummaryToParcel(Parcel out, boolean inclHistory)14014     public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
14015         pullPendingStateUpdatesLocked();
14016 
14017         // Pull the clock time.  This may update the time and make a new history entry
14018         // if we had originally pulled a time before the RTC was set.
14019         getStartClockTime();
14020 
14021         final long NOW_SYS = mClocks.uptimeMillis() * 1000;
14022         final long NOWREAL_SYS = mClocks.elapsedRealtime() * 1000;
14023 
14024         out.writeInt(VERSION);
14025 
14026         out.writeBoolean(inclHistory);
14027         if (inclHistory) {
14028             writeHistoryBuffer(out, true, true);
14029             mBatteryStatsHistory.writeToParcel(out);
14030         }
14031 
14032         out.writeInt(mHistoryTagPool.size());
14033         for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
14034             HistoryTag tag = ent.getKey();
14035             out.writeInt(ent.getValue());
14036             out.writeString(tag.string);
14037             out.writeInt(tag.uid);
14038         }
14039 
14040         out.writeInt(mStartCount);
14041         out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
14042         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
14043         out.writeLong(mStartClockTime);
14044         out.writeString(mStartPlatformVersion);
14045         out.writeString(mEndPlatformVersion);
14046         mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14047         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14048         out.writeInt(mDischargeUnplugLevel);
14049         out.writeInt(mDischargePlugLevel);
14050         out.writeInt(mDischargeCurrentLevel);
14051         out.writeInt(mCurrentBatteryLevel);
14052         out.writeInt(mEstimatedBatteryCapacity);
14053         out.writeInt(mMinLearnedBatteryCapacity);
14054         out.writeInt(mMaxLearnedBatteryCapacity);
14055         out.writeInt(getLowDischargeAmountSinceCharge());
14056         out.writeInt(getHighDischargeAmountSinceCharge());
14057         out.writeInt(getDischargeAmountScreenOnSinceCharge());
14058         out.writeInt(getDischargeAmountScreenOffSinceCharge());
14059         out.writeInt(getDischargeAmountScreenDozeSinceCharge());
14060         mDischargeStepTracker.writeToParcel(out);
14061         mChargeStepTracker.writeToParcel(out);
14062         mDailyDischargeStepTracker.writeToParcel(out);
14063         mDailyChargeStepTracker.writeToParcel(out);
14064         mDischargeCounter.writeSummaryFromParcelLocked(out);
14065         mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
14066         mDischargeScreenDozeCounter.writeSummaryFromParcelLocked(out);
14067         mDischargeLightDozeCounter.writeSummaryFromParcelLocked(out);
14068         mDischargeDeepDozeCounter.writeSummaryFromParcelLocked(out);
14069         if (mDailyPackageChanges != null) {
14070             final int NPKG = mDailyPackageChanges.size();
14071             out.writeInt(NPKG);
14072             for (int i=0; i<NPKG; i++) {
14073                 PackageChange pc = mDailyPackageChanges.get(i);
14074                 out.writeString(pc.mPackageName);
14075                 out.writeInt(pc.mUpdate ? 1 : 0);
14076                 out.writeLong(pc.mVersionCode);
14077             }
14078         } else {
14079             out.writeInt(0);
14080         }
14081         out.writeLong(mDailyStartTime);
14082         out.writeLong(mNextMinDailyDeadline);
14083         out.writeLong(mNextMaxDailyDeadline);
14084 
14085         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14086         mScreenDozeTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14087         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14088             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14089         }
14090         mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14091         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14092         out.writeLong(mLongestLightIdleTime);
14093         out.writeLong(mLongestFullIdleTime);
14094         mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14095         mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14096         mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14097         mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14098         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14099         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
14100             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14101         }
14102         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14103         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14104             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14105         }
14106         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14107             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
14108             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
14109         }
14110         mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14111         mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14112         mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
14113         mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
14114         mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
14115         mWifiMulticastWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14116         mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14117         mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14118         for (int i=0; i<NUM_WIFI_STATES; i++) {
14119             mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14120         }
14121         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14122             mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14123         }
14124         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14125             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14126         }
14127         mWifiActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14128         mWifiActivity.writeSummaryToParcel(out);
14129         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14130             mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14131         }
14132         mBluetoothActivity.writeSummaryToParcel(out);
14133         mModemActivity.writeSummaryToParcel(out);
14134         out.writeInt(mHasWifiReporting ? 1 : 0);
14135         out.writeInt(mHasBluetoothReporting ? 1 : 0);
14136         out.writeInt(mHasModemReporting ? 1 : 0);
14137 
14138         out.writeInt(mNumConnectivityChange);
14139         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14140         mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14141         mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14142 
14143         out.writeInt(mRpmStats.size());
14144         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
14145             Timer rpmt = ent.getValue();
14146             if (rpmt != null) {
14147                 out.writeInt(1);
14148                 out.writeString(ent.getKey());
14149                 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14150             } else {
14151                 out.writeInt(0);
14152             }
14153         }
14154         out.writeInt(mScreenOffRpmStats.size());
14155         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
14156             Timer rpmt = ent.getValue();
14157             if (rpmt != null) {
14158                 out.writeInt(1);
14159                 out.writeString(ent.getKey());
14160                 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14161             } else {
14162                 out.writeInt(0);
14163             }
14164         }
14165 
14166         out.writeInt(mKernelWakelockStats.size());
14167         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
14168             Timer kwlt = ent.getValue();
14169             if (kwlt != null) {
14170                 out.writeInt(1);
14171                 out.writeString(ent.getKey());
14172                 kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14173             } else {
14174                 out.writeInt(0);
14175             }
14176         }
14177 
14178         out.writeInt(mWakeupReasonStats.size());
14179         for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
14180             SamplingTimer timer = ent.getValue();
14181             if (timer != null) {
14182                 out.writeInt(1);
14183                 out.writeString(ent.getKey());
14184                 timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14185             } else {
14186                 out.writeInt(0);
14187             }
14188         }
14189 
14190         out.writeInt(mKernelMemoryStats.size());
14191         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
14192             Timer kmt = mKernelMemoryStats.valueAt(i);
14193             if (kmt != null) {
14194                 out.writeInt(1);
14195                 out.writeLong(mKernelMemoryStats.keyAt(i));
14196                 kmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14197             } else {
14198                 out.writeInt(0);
14199             }
14200         }
14201 
14202         final int NU = mUidStats.size();
14203         out.writeInt(NU);
14204         for (int iu = 0; iu < NU; iu++) {
14205             out.writeInt(mUidStats.keyAt(iu));
14206             Uid u = mUidStats.valueAt(iu);
14207 
14208             u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14209             u.mOnBatteryScreenOffBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14210 
14211             if (u.mWifiRunningTimer != null) {
14212                 out.writeInt(1);
14213                 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14214             } else {
14215                 out.writeInt(0);
14216             }
14217             if (u.mFullWifiLockTimer != null) {
14218                 out.writeInt(1);
14219                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14220             } else {
14221                 out.writeInt(0);
14222             }
14223             if (u.mWifiScanTimer != null) {
14224                 out.writeInt(1);
14225                 u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14226             } else {
14227                 out.writeInt(0);
14228             }
14229             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
14230                 if (u.mWifiBatchedScanTimer[i] != null) {
14231                     out.writeInt(1);
14232                     u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14233                 } else {
14234                     out.writeInt(0);
14235                 }
14236             }
14237             if (u.mWifiMulticastTimer != null) {
14238                 out.writeInt(1);
14239                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14240             } else {
14241                 out.writeInt(0);
14242             }
14243             if (u.mAudioTurnedOnTimer != null) {
14244                 out.writeInt(1);
14245                 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14246             } else {
14247                 out.writeInt(0);
14248             }
14249             if (u.mVideoTurnedOnTimer != null) {
14250                 out.writeInt(1);
14251                 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14252             } else {
14253                 out.writeInt(0);
14254             }
14255             if (u.mFlashlightTurnedOnTimer != null) {
14256                 out.writeInt(1);
14257                 u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14258             } else {
14259                 out.writeInt(0);
14260             }
14261             if (u.mCameraTurnedOnTimer != null) {
14262                 out.writeInt(1);
14263                 u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14264             } else {
14265                 out.writeInt(0);
14266             }
14267             if (u.mForegroundActivityTimer != null) {
14268                 out.writeInt(1);
14269                 u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14270             } else {
14271                 out.writeInt(0);
14272             }
14273             if (u.mForegroundServiceTimer != null) {
14274                 out.writeInt(1);
14275                 u.mForegroundServiceTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14276             } else {
14277                 out.writeInt(0);
14278             }
14279             if (u.mAggregatedPartialWakelockTimer != null) {
14280                 out.writeInt(1);
14281                 u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14282             } else {
14283                 out.writeInt(0);
14284             }
14285             if (u.mBluetoothScanTimer != null) {
14286                 out.writeInt(1);
14287                 u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14288             } else {
14289                 out.writeInt(0);
14290             }
14291             if (u.mBluetoothUnoptimizedScanTimer != null) {
14292                 out.writeInt(1);
14293                 u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14294             } else {
14295                 out.writeInt(0);
14296             }
14297             if (u.mBluetoothScanResultCounter != null) {
14298                 out.writeInt(1);
14299                 u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
14300             } else {
14301                 out.writeInt(0);
14302             }
14303             if (u.mBluetoothScanResultBgCounter != null) {
14304                 out.writeInt(1);
14305                 u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out);
14306             } else {
14307                 out.writeInt(0);
14308             }
14309             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
14310                 if (u.mProcessStateTimer[i] != null) {
14311                     out.writeInt(1);
14312                     u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14313                 } else {
14314                     out.writeInt(0);
14315                 }
14316             }
14317             if (u.mVibratorOnTimer != null) {
14318                 out.writeInt(1);
14319                 u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14320             } else {
14321                 out.writeInt(0);
14322             }
14323 
14324             if (u.mUserActivityCounters == null) {
14325                 out.writeInt(0);
14326             } else {
14327                 out.writeInt(1);
14328                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
14329                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
14330                 }
14331             }
14332 
14333             if (u.mNetworkByteActivityCounters == null) {
14334                 out.writeInt(0);
14335             } else {
14336                 out.writeInt(1);
14337                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14338                     u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
14339                     u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
14340                 }
14341                 u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
14342                 u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
14343             }
14344 
14345             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
14346             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
14347 
14348             if (u.mCpuClusterSpeedTimesUs != null) {
14349                 out.writeInt(1);
14350                 out.writeInt(u.mCpuClusterSpeedTimesUs.length);
14351                 for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeedTimesUs) {
14352                     if (cpuSpeeds != null) {
14353                         out.writeInt(1);
14354                         out.writeInt(cpuSpeeds.length);
14355                         for (LongSamplingCounter c : cpuSpeeds) {
14356                             if (c != null) {
14357                                 out.writeInt(1);
14358                                 c.writeSummaryFromParcelLocked(out);
14359                             } else {
14360                                 out.writeInt(0);
14361                             }
14362                         }
14363                     } else {
14364                         out.writeInt(0);
14365                     }
14366                 }
14367             } else {
14368                 out.writeInt(0);
14369             }
14370 
14371             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
14372             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
14373 
14374             u.mCpuActiveTimeMs.writeSummaryFromParcelLocked(out);
14375             u.mCpuClusterTimesMs.writeSummaryToParcelLocked(out);
14376 
14377             if (u.mProcStateTimeMs != null) {
14378                 out.writeInt(u.mProcStateTimeMs.length);
14379                 for (LongSamplingCounterArray counters : u.mProcStateTimeMs) {
14380                     LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
14381                 }
14382             } else {
14383                 out.writeInt(0);
14384             }
14385             if (u.mProcStateScreenOffTimeMs != null) {
14386                 out.writeInt(u.mProcStateScreenOffTimeMs.length);
14387                 for (LongSamplingCounterArray counters : u.mProcStateScreenOffTimeMs) {
14388                     LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
14389                 }
14390             } else {
14391                 out.writeInt(0);
14392             }
14393 
14394             if (u.mMobileRadioApWakeupCount != null) {
14395                 out.writeInt(1);
14396                 u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
14397             } else {
14398                 out.writeInt(0);
14399             }
14400 
14401             if (u.mWifiRadioApWakeupCount != null) {
14402                 out.writeInt(1);
14403                 u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
14404             } else {
14405                 out.writeInt(0);
14406             }
14407 
14408             final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
14409             int NW = wakeStats.size();
14410             out.writeInt(NW);
14411             for (int iw=0; iw<NW; iw++) {
14412                 out.writeString(wakeStats.keyAt(iw));
14413                 Uid.Wakelock wl = wakeStats.valueAt(iw);
14414                 if (wl.mTimerFull != null) {
14415                     out.writeInt(1);
14416                     wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14417                 } else {
14418                     out.writeInt(0);
14419                 }
14420                 if (wl.mTimerPartial != null) {
14421                     out.writeInt(1);
14422                     wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14423                 } else {
14424                     out.writeInt(0);
14425                 }
14426                 if (wl.mTimerWindow != null) {
14427                     out.writeInt(1);
14428                     wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14429                 } else {
14430                     out.writeInt(0);
14431                 }
14432                 if (wl.mTimerDraw != null) {
14433                     out.writeInt(1);
14434                     wl.mTimerDraw.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14435                 } else {
14436                     out.writeInt(0);
14437                 }
14438             }
14439 
14440             final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
14441             int NS = syncStats.size();
14442             out.writeInt(NS);
14443             for (int is=0; is<NS; is++) {
14444                 out.writeString(syncStats.keyAt(is));
14445                 syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14446             }
14447 
14448             final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
14449             int NJ = jobStats.size();
14450             out.writeInt(NJ);
14451             for (int ij=0; ij<NJ; ij++) {
14452                 out.writeString(jobStats.keyAt(ij));
14453                 jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14454             }
14455 
14456             u.writeJobCompletionsToParcelLocked(out);
14457 
14458             u.mJobsDeferredEventCount.writeSummaryFromParcelLocked(out);
14459             u.mJobsDeferredCount.writeSummaryFromParcelLocked(out);
14460             u.mJobsFreshnessTimeMs.writeSummaryFromParcelLocked(out);
14461             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
14462                 if (u.mJobsFreshnessBuckets[i] != null) {
14463                     out.writeInt(1);
14464                     u.mJobsFreshnessBuckets[i].writeSummaryFromParcelLocked(out);
14465                 } else {
14466                     out.writeInt(0);
14467                 }
14468             }
14469 
14470             int NSE = u.mSensorStats.size();
14471             out.writeInt(NSE);
14472             for (int ise=0; ise<NSE; ise++) {
14473                 out.writeInt(u.mSensorStats.keyAt(ise));
14474                 Uid.Sensor se = u.mSensorStats.valueAt(ise);
14475                 if (se.mTimer != null) {
14476                     out.writeInt(1);
14477                     se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14478                 } else {
14479                     out.writeInt(0);
14480                 }
14481             }
14482 
14483             int NP = u.mProcessStats.size();
14484             out.writeInt(NP);
14485             for (int ip=0; ip<NP; ip++) {
14486                 out.writeString(u.mProcessStats.keyAt(ip));
14487                 Uid.Proc ps = u.mProcessStats.valueAt(ip);
14488                 out.writeLong(ps.mUserTime);
14489                 out.writeLong(ps.mSystemTime);
14490                 out.writeLong(ps.mForegroundTime);
14491                 out.writeInt(ps.mStarts);
14492                 out.writeInt(ps.mNumCrashes);
14493                 out.writeInt(ps.mNumAnrs);
14494                 ps.writeExcessivePowerToParcelLocked(out);
14495             }
14496 
14497             NP = u.mPackageStats.size();
14498             out.writeInt(NP);
14499             if (NP > 0) {
14500                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
14501                     : u.mPackageStats.entrySet()) {
14502                     out.writeString(ent.getKey());
14503                     Uid.Pkg ps = ent.getValue();
14504                     final int NWA = ps.mWakeupAlarms.size();
14505                     out.writeInt(NWA);
14506                     for (int iwa=0; iwa<NWA; iwa++) {
14507                         out.writeString(ps.mWakeupAlarms.keyAt(iwa));
14508                         ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
14509                     }
14510                     NS = ps.mServiceStats.size();
14511                     out.writeInt(NS);
14512                     for (int is=0; is<NS; is++) {
14513                         out.writeString(ps.mServiceStats.keyAt(is));
14514                         BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
14515                         long time = ss.getStartTimeToNowLocked(
14516                                 mOnBatteryTimeBase.getUptime(NOW_SYS));
14517                         out.writeLong(time);
14518                         out.writeInt(ss.mStarts);
14519                         out.writeInt(ss.mLaunches);
14520                     }
14521                 }
14522             }
14523         }
14524     }
14525 
readFromParcel(Parcel in)14526     public void readFromParcel(Parcel in) {
14527         readFromParcelLocked(in);
14528     }
14529 
readFromParcelLocked(Parcel in)14530     void readFromParcelLocked(Parcel in) {
14531         int magic = in.readInt();
14532         if (magic != MAGIC) {
14533             throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
14534         }
14535 
14536         readHistoryBuffer(in, false);
14537         mBatteryStatsHistory.readFromParcel(in);
14538 
14539         mStartCount = in.readInt();
14540         mStartClockTime = in.readLong();
14541         mStartPlatformVersion = in.readString();
14542         mEndPlatformVersion = in.readString();
14543         mUptime = in.readLong();
14544         mUptimeStart = in.readLong();
14545         mRealtime = in.readLong();
14546         mRealtimeStart = in.readLong();
14547         mOnBattery = in.readInt() != 0;
14548         mEstimatedBatteryCapacity = in.readInt();
14549         mMinLearnedBatteryCapacity = in.readInt();
14550         mMaxLearnedBatteryCapacity = in.readInt();
14551         mOnBatteryInternal = false; // we are no longer really running.
14552         mOnBatteryTimeBase.readFromParcel(in);
14553         mOnBatteryScreenOffTimeBase.readFromParcel(in);
14554 
14555         mScreenState = Display.STATE_UNKNOWN;
14556         mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
14557         mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
14558         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14559             mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
14560                     mOnBatteryTimeBase, in);
14561         }
14562         mInteractive = false;
14563         mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase, in);
14564         mPhoneOn = false;
14565         mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
14566                 mOnBatteryTimeBase, in);
14567         mLongestLightIdleTime = in.readLong();
14568         mLongestFullIdleTime = in.readLong();
14569         mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null,
14570                 mOnBatteryTimeBase, in);
14571         mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null,
14572                 mOnBatteryTimeBase, in);
14573         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null,
14574                 mOnBatteryTimeBase, in);
14575         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase, in);
14576         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase, in);
14577         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
14578             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i,
14579                     null, mOnBatteryTimeBase, in);
14580         }
14581         mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
14582                 mOnBatteryTimeBase, in);
14583         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14584             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i,
14585                     null, mOnBatteryTimeBase, in);
14586         }
14587         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14588             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
14589             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
14590         }
14591         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
14592         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
14593                 mOnBatteryTimeBase, in);
14594         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
14595                 mOnBatteryTimeBase, in);
14596         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
14597         mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
14598         mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
14599         mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null, -4, null,
14600                 mOnBatteryTimeBase, in);
14601         mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
14602         mWifiOn = false;
14603         mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase, in);
14604         mGlobalWifiRunning = false;
14605         mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null,
14606                 mOnBatteryTimeBase, in);
14607         for (int i=0; i<NUM_WIFI_STATES; i++) {
14608             mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i,
14609                     null, mOnBatteryTimeBase, in);
14610         }
14611         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14612             mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i,
14613                     null, mOnBatteryTimeBase, in);
14614         }
14615         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14616             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
14617                     null, mOnBatteryTimeBase, in);
14618         }
14619         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null,
14620             mOnBatteryTimeBase, in);
14621         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14622                 NUM_WIFI_TX_LEVELS, in);
14623         for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14624             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i,
14625                 null, mOnBatteryTimeBase, in);
14626         }
14627         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14628                 NUM_BT_TX_LEVELS, in);
14629         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14630                 ModemActivityInfo.TX_POWER_LEVELS, in);
14631         mHasWifiReporting = in.readInt() != 0;
14632         mHasBluetoothReporting = in.readInt() != 0;
14633         mHasModemReporting = in.readInt() != 0;
14634 
14635         mNumConnectivityChange = in.readInt();
14636         mAudioOnNesting = 0;
14637         // TODO: It's likely a mistake that mAudioOnTimer/mVideoOnTimer don't write/read to parcel!
14638         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
14639         mVideoOnNesting = 0;
14640         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
14641         mFlashlightOnNesting = 0;
14642         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase, in);
14643         mCameraOnNesting = 0;
14644         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
14645         mBluetoothScanNesting = 0;
14646         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
14647         mIsCellularTxPowerHigh = false;
14648         mDischargeUnplugLevel = in.readInt();
14649         mDischargePlugLevel = in.readInt();
14650         mDischargeCurrentLevel = in.readInt();
14651         mCurrentBatteryLevel = in.readInt();
14652         mLowDischargeAmountSinceCharge = in.readInt();
14653         mHighDischargeAmountSinceCharge = in.readInt();
14654         mDischargeAmountScreenOn = in.readInt();
14655         mDischargeAmountScreenOnSinceCharge = in.readInt();
14656         mDischargeAmountScreenOff = in.readInt();
14657         mDischargeAmountScreenOffSinceCharge = in.readInt();
14658         mDischargeAmountScreenDoze = in.readInt();
14659         mDischargeAmountScreenDozeSinceCharge = in.readInt();
14660         mDischargeStepTracker.readFromParcel(in);
14661         mChargeStepTracker.readFromParcel(in);
14662         mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14663         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase, in);
14664         mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14665         mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14666         mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14667         mLastWriteTime = in.readLong();
14668 
14669         mRpmStats.clear();
14670         int NRPMS = in.readInt();
14671         for (int irpm = 0; irpm < NRPMS; irpm++) {
14672             if (in.readInt() != 0) {
14673                 String rpmName = in.readString();
14674                 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14675                 mRpmStats.put(rpmName, rpmt);
14676             }
14677         }
14678         mScreenOffRpmStats.clear();
14679         int NSORPMS = in.readInt();
14680         for (int irpm = 0; irpm < NSORPMS; irpm++) {
14681             if (in.readInt() != 0) {
14682                 String rpmName = in.readString();
14683                 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
14684                 mScreenOffRpmStats.put(rpmName, rpmt);
14685             }
14686         }
14687 
14688         mKernelWakelockStats.clear();
14689         int NKW = in.readInt();
14690         for (int ikw = 0; ikw < NKW; ikw++) {
14691             if (in.readInt() != 0) {
14692                 String wakelockName = in.readString();
14693                 SamplingTimer kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
14694                 mKernelWakelockStats.put(wakelockName, kwlt);
14695             }
14696         }
14697 
14698         mWakeupReasonStats.clear();
14699         int NWR = in.readInt();
14700         for (int iwr = 0; iwr < NWR; iwr++) {
14701             if (in.readInt() != 0) {
14702                 String reasonName = in.readString();
14703                 SamplingTimer timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14704                 mWakeupReasonStats.put(reasonName, timer);
14705             }
14706         }
14707 
14708         mKernelMemoryStats.clear();
14709         int nmt = in.readInt();
14710         for (int imt = 0; imt < nmt; imt++) {
14711             if (in.readInt() != 0) {
14712                 Long bucket = in.readLong();
14713                 SamplingTimer kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14714                 mKernelMemoryStats.put(bucket, kmt);
14715             }
14716         }
14717 
14718         mPartialTimers.clear();
14719         mFullTimers.clear();
14720         mWindowTimers.clear();
14721         mWifiRunningTimers.clear();
14722         mFullWifiLockTimers.clear();
14723         mWifiScanTimers.clear();
14724         mWifiBatchedScanTimers.clear();
14725         mWifiMulticastTimers.clear();
14726         mAudioTurnedOnTimers.clear();
14727         mVideoTurnedOnTimers.clear();
14728         mFlashlightTurnedOnTimers.clear();
14729         mCameraTurnedOnTimers.clear();
14730 
14731         int numUids = in.readInt();
14732         mUidStats.clear();
14733         for (int i = 0; i < numUids; i++) {
14734             int uid = in.readInt();
14735             Uid u = new Uid(this, uid);
14736             u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
14737             mUidStats.append(uid, u);
14738         }
14739     }
14740 
writeToParcel(Parcel out, int flags)14741     public void writeToParcel(Parcel out, int flags) {
14742         writeToParcelLocked(out, true, flags);
14743     }
14744 
writeToParcelWithoutUids(Parcel out, int flags)14745     public void writeToParcelWithoutUids(Parcel out, int flags) {
14746         writeToParcelLocked(out, false, flags);
14747     }
14748 
14749     @SuppressWarnings("unused")
writeToParcelLocked(Parcel out, boolean inclUids, int flags)14750     void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
14751         // Need to update with current kernel wake lock counts.
14752         pullPendingStateUpdatesLocked();
14753 
14754         // Pull the clock time.  This may update the time and make a new history entry
14755         // if we had originally pulled a time before the RTC was set.
14756         getStartClockTime();
14757 
14758         final long uSecUptime = mClocks.uptimeMillis() * 1000;
14759         final long uSecRealtime = mClocks.elapsedRealtime() * 1000;
14760         final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
14761         final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
14762 
14763         out.writeInt(MAGIC);
14764 
14765         writeHistoryBuffer(out, true, false);
14766         mBatteryStatsHistory.writeToParcel(out);
14767 
14768         out.writeInt(mStartCount);
14769         out.writeLong(mStartClockTime);
14770         out.writeString(mStartPlatformVersion);
14771         out.writeString(mEndPlatformVersion);
14772         out.writeLong(mUptime);
14773         out.writeLong(mUptimeStart);
14774         out.writeLong(mRealtime);
14775         out.writeLong(mRealtimeStart);
14776         out.writeInt(mOnBattery ? 1 : 0);
14777         out.writeInt(mEstimatedBatteryCapacity);
14778         out.writeInt(mMinLearnedBatteryCapacity);
14779         out.writeInt(mMaxLearnedBatteryCapacity);
14780         mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
14781         mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
14782 
14783         mScreenOnTimer.writeToParcel(out, uSecRealtime);
14784         mScreenDozeTimer.writeToParcel(out, uSecRealtime);
14785         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14786             mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
14787         }
14788         mInteractiveTimer.writeToParcel(out, uSecRealtime);
14789         mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
14790         out.writeLong(mLongestLightIdleTime);
14791         out.writeLong(mLongestFullIdleTime);
14792         mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
14793         mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
14794         mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
14795         mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
14796         mPhoneOnTimer.writeToParcel(out, uSecRealtime);
14797         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
14798             mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
14799         }
14800         mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
14801         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14802             mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
14803         }
14804         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14805             mNetworkByteActivityCounters[i].writeToParcel(out);
14806             mNetworkPacketActivityCounters[i].writeToParcel(out);
14807         }
14808         mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
14809         mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
14810         mMobileRadioActiveAdjustedTime.writeToParcel(out);
14811         mMobileRadioActiveUnknownTime.writeToParcel(out);
14812         mMobileRadioActiveUnknownCount.writeToParcel(out);
14813         mWifiMulticastWakelockTimer.writeToParcel(out, uSecRealtime);
14814         mWifiOnTimer.writeToParcel(out, uSecRealtime);
14815         mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
14816         for (int i=0; i<NUM_WIFI_STATES; i++) {
14817             mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
14818         }
14819         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14820             mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
14821         }
14822         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14823             mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
14824         }
14825         mWifiActiveTimer.writeToParcel(out, uSecRealtime);
14826         mWifiActivity.writeToParcel(out, 0);
14827         for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14828             mGpsSignalQualityTimer[i].writeToParcel(out, uSecRealtime);
14829         }
14830         mBluetoothActivity.writeToParcel(out, 0);
14831         mModemActivity.writeToParcel(out, 0);
14832         out.writeInt(mHasWifiReporting ? 1 : 0);
14833         out.writeInt(mHasBluetoothReporting ? 1 : 0);
14834         out.writeInt(mHasModemReporting ? 1 : 0);
14835 
14836         out.writeInt(mNumConnectivityChange);
14837         mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
14838         mCameraOnTimer.writeToParcel(out, uSecRealtime);
14839         mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
14840         out.writeInt(mDischargeUnplugLevel);
14841         out.writeInt(mDischargePlugLevel);
14842         out.writeInt(mDischargeCurrentLevel);
14843         out.writeInt(mCurrentBatteryLevel);
14844         out.writeInt(mLowDischargeAmountSinceCharge);
14845         out.writeInt(mHighDischargeAmountSinceCharge);
14846         out.writeInt(mDischargeAmountScreenOn);
14847         out.writeInt(mDischargeAmountScreenOnSinceCharge);
14848         out.writeInt(mDischargeAmountScreenOff);
14849         out.writeInt(mDischargeAmountScreenOffSinceCharge);
14850         out.writeInt(mDischargeAmountScreenDoze);
14851         out.writeInt(mDischargeAmountScreenDozeSinceCharge);
14852         mDischargeStepTracker.writeToParcel(out);
14853         mChargeStepTracker.writeToParcel(out);
14854         mDischargeCounter.writeToParcel(out);
14855         mDischargeScreenOffCounter.writeToParcel(out);
14856         mDischargeScreenDozeCounter.writeToParcel(out);
14857         mDischargeLightDozeCounter.writeToParcel(out);
14858         mDischargeDeepDozeCounter.writeToParcel(out);
14859         out.writeLong(mLastWriteTime);
14860 
14861         out.writeInt(mRpmStats.size());
14862         for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
14863             SamplingTimer rpmt = ent.getValue();
14864             if (rpmt != null) {
14865                 out.writeInt(1);
14866                 out.writeString(ent.getKey());
14867                 rpmt.writeToParcel(out, uSecRealtime);
14868             } else {
14869                 out.writeInt(0);
14870             }
14871         }
14872         out.writeInt(mScreenOffRpmStats.size());
14873         for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
14874             SamplingTimer rpmt = ent.getValue();
14875             if (rpmt != null) {
14876                 out.writeInt(1);
14877                 out.writeString(ent.getKey());
14878                 rpmt.writeToParcel(out, uSecRealtime);
14879             } else {
14880                 out.writeInt(0);
14881             }
14882         }
14883 
14884         if (inclUids) {
14885             out.writeInt(mKernelWakelockStats.size());
14886             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
14887                 SamplingTimer kwlt = ent.getValue();
14888                 if (kwlt != null) {
14889                     out.writeInt(1);
14890                     out.writeString(ent.getKey());
14891                     kwlt.writeToParcel(out, uSecRealtime);
14892                 } else {
14893                     out.writeInt(0);
14894                 }
14895             }
14896             out.writeInt(mWakeupReasonStats.size());
14897             for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
14898                 SamplingTimer timer = ent.getValue();
14899                 if (timer != null) {
14900                     out.writeInt(1);
14901                     out.writeString(ent.getKey());
14902                     timer.writeToParcel(out, uSecRealtime);
14903                 } else {
14904                     out.writeInt(0);
14905                 }
14906             }
14907         } else {
14908             out.writeInt(0);
14909             out.writeInt(0);
14910         }
14911 
14912         out.writeInt(mKernelMemoryStats.size());
14913         for (int i = 0; i < mKernelMemoryStats.size(); i++) {
14914             SamplingTimer kmt = mKernelMemoryStats.valueAt(i);
14915             if (kmt != null) {
14916                 out.writeInt(1);
14917                 out.writeLong(mKernelMemoryStats.keyAt(i));
14918                 kmt.writeToParcel(out, uSecRealtime);
14919             } else {
14920                 out.writeInt(0);
14921             }
14922         }
14923 
14924         if (inclUids) {
14925             int size = mUidStats.size();
14926             out.writeInt(size);
14927             for (int i = 0; i < size; i++) {
14928                 out.writeInt(mUidStats.keyAt(i));
14929                 Uid uid = mUidStats.valueAt(i);
14930 
14931                 uid.writeToParcelLocked(out, uSecUptime, uSecRealtime);
14932             }
14933         } else {
14934             out.writeInt(0);
14935         }
14936     }
14937 
14938     @UnsupportedAppUsage
14939     public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
14940         new Parcelable.Creator<BatteryStatsImpl>() {
14941         public BatteryStatsImpl createFromParcel(Parcel in) {
14942             return new BatteryStatsImpl(in);
14943         }
14944 
14945         public BatteryStatsImpl[] newArray(int size) {
14946             return new BatteryStatsImpl[size];
14947         }
14948     };
14949 
prepareForDumpLocked()14950     public void prepareForDumpLocked() {
14951         // Need to retrieve current kernel wake lock stats before printing.
14952         pullPendingStateUpdatesLocked();
14953 
14954         // Pull the clock time.  This may update the time and make a new history entry
14955         // if we had originally pulled a time before the RTC was set.
14956         getStartClockTime();
14957     }
14958 
dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart)14959     public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
14960         if (DEBUG) {
14961             pw.println("mOnBatteryTimeBase:");
14962             mOnBatteryTimeBase.dump(pw, "  ");
14963             pw.println("mOnBatteryScreenOffTimeBase:");
14964             mOnBatteryScreenOffTimeBase.dump(pw, "  ");
14965             Printer pr = new PrintWriterPrinter(pw);
14966             pr.println("*** Screen on timer:");
14967             mScreenOnTimer.logState(pr, "  ");
14968             pr.println("*** Screen doze timer:");
14969             mScreenDozeTimer.logState(pr, "  ");
14970             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14971                 pr.println("*** Screen brightness #" + i + ":");
14972                 mScreenBrightnessTimer[i].logState(pr, "  ");
14973             }
14974             pr.println("*** Interactive timer:");
14975             mInteractiveTimer.logState(pr, "  ");
14976             pr.println("*** Power save mode timer:");
14977             mPowerSaveModeEnabledTimer.logState(pr, "  ");
14978             pr.println("*** Device idle mode light timer:");
14979             mDeviceIdleModeLightTimer.logState(pr, "  ");
14980             pr.println("*** Device idle mode full timer:");
14981             mDeviceIdleModeFullTimer.logState(pr, "  ");
14982             pr.println("*** Device light idling timer:");
14983             mDeviceLightIdlingTimer.logState(pr, "  ");
14984             pr.println("*** Device idling timer:");
14985             mDeviceIdlingTimer.logState(pr, "  ");
14986             pr.println("*** Phone timer:");
14987             mPhoneOnTimer.logState(pr, "  ");
14988             for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
14989                 pr.println("*** Phone signal strength #" + i + ":");
14990                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
14991             }
14992             pr.println("*** Signal scanning :");
14993             mPhoneSignalScanningTimer.logState(pr, "  ");
14994             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14995                 pr.println("*** Data connection type #" + i + ":");
14996                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
14997             }
14998             pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
14999             pr.println("*** Mobile network active timer:");
15000             mMobileRadioActiveTimer.logState(pr, "  ");
15001             pr.println("*** Mobile network active adjusted timer:");
15002             mMobileRadioActiveAdjustedTime.logState(pr, "  ");
15003             pr.println("*** Wifi Multicast WakeLock Timer:");
15004             mWifiMulticastWakelockTimer.logState(pr, "  ");
15005             pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
15006             pr.println("*** Wifi timer:");
15007             mWifiOnTimer.logState(pr, "  ");
15008             pr.println("*** WifiRunning timer:");
15009             mGlobalWifiRunningTimer.logState(pr, "  ");
15010             for (int i=0; i<NUM_WIFI_STATES; i++) {
15011                 pr.println("*** Wifi state #" + i + ":");
15012                 mWifiStateTimer[i].logState(pr, "  ");
15013             }
15014             for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
15015                 pr.println("*** Wifi suppl state #" + i + ":");
15016                 mWifiSupplStateTimer[i].logState(pr, "  ");
15017             }
15018             for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
15019                 pr.println("*** Wifi signal strength #" + i + ":");
15020                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
15021             }
15022             for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
15023                 pr.println("*** GPS signal quality #" + i + ":");
15024                 mGpsSignalQualityTimer[i].logState(pr, "  ");
15025             }
15026             pr.println("*** Flashlight timer:");
15027             mFlashlightOnTimer.logState(pr, "  ");
15028             pr.println("*** Camera timer:");
15029             mCameraOnTimer.logState(pr, "  ");
15030         }
15031         super.dumpLocked(context, pw, flags, reqUid, histStart);
15032         pw.print("Total cpu time reads: ");
15033         pw.println(mNumSingleUidCpuTimeReads);
15034         pw.print("Batched cpu time reads: ");
15035         pw.println(mNumBatchedSingleUidCpuTimeReads);
15036         pw.print("Batching Duration (min): ");
15037         pw.println((mClocks.uptimeMillis() - mCpuTimeReadsTrackingStartTime) / (60 * 1000));
15038         pw.print("All UID cpu time reads since the later of device start or stats reset: ");
15039         pw.println(mNumAllUidCpuTimeReads);
15040         pw.print("UIDs removed since the later of device start or stats reset: ");
15041         pw.println(mNumUidsRemoved);
15042     }
15043 }
15044