• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006-2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.os;
18 
19 import static android.net.NetworkStats.IFACE_ALL;
20 import static android.net.NetworkStats.UID_ALL;
21 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
22 
23 import android.bluetooth.BluetoothDevice;
24 import android.bluetooth.BluetoothHeadset;
25 import android.content.res.Resources;
26 import android.net.ConnectivityManager;
27 import android.net.NetworkStats;
28 import android.os.BatteryManager;
29 import android.os.BatteryStats;
30 import android.os.FileUtils;
31 import android.os.Handler;
32 import android.os.Message;
33 import android.os.Parcel;
34 import android.os.ParcelFormatException;
35 import android.os.Parcelable;
36 import android.os.Process;
37 import android.os.SystemClock;
38 import android.os.WorkSource;
39 import android.telephony.ServiceState;
40 import android.telephony.SignalStrength;
41 import android.telephony.TelephonyManager;
42 import android.util.Log;
43 import android.util.LogWriter;
44 import android.util.PrintWriterPrinter;
45 import android.util.Printer;
46 import android.util.Slog;
47 import android.util.SparseArray;
48 import android.util.TimeUtils;
49 
50 import com.android.internal.R;
51 import com.android.internal.net.NetworkStatsFactory;
52 import com.android.internal.util.JournaledFile;
53 import com.google.android.collect.Sets;
54 
55 import java.io.BufferedReader;
56 import java.io.File;
57 import java.io.FileInputStream;
58 import java.io.FileOutputStream;
59 import java.io.FileReader;
60 import java.io.IOException;
61 import java.io.PrintWriter;
62 import java.util.ArrayList;
63 import java.util.HashMap;
64 import java.util.HashSet;
65 import java.util.Iterator;
66 import java.util.List;
67 import java.util.Map;
68 import java.util.concurrent.atomic.AtomicInteger;
69 import java.util.concurrent.locks.ReentrantLock;
70 
71 /**
72  * All information we are collecting about things that can happen that impact
73  * battery life.  All times are represented in microseconds except where indicated
74  * otherwise.
75  */
76 public final class BatteryStatsImpl extends BatteryStats {
77     private static final String TAG = "BatteryStatsImpl";
78     private static final boolean DEBUG = false;
79     private static final boolean DEBUG_HISTORY = false;
80     private static final boolean USE_OLD_HISTORY = false;   // for debugging.
81 
82     // TODO: remove "tcp" from network methods, since we measure total stats.
83 
84     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
85     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
86 
87     // Current on-disk Parcel version
88     private static final int VERSION = 61 + (USE_OLD_HISTORY ? 1000 : 0);
89 
90     // Maximum number of items we will record in the history.
91     private static final int MAX_HISTORY_ITEMS = 2000;
92 
93     // No, really, THIS is the maximum number of items we will record in the history.
94     private static final int MAX_MAX_HISTORY_ITEMS = 3000;
95 
96     // The maximum number of names wakelocks we will keep track of
97     // per uid; once the limit is reached, we batch the remaining wakelocks
98     // in to one common name.
99     private static final int MAX_WAKELOCKS_PER_UID = 30;
100 
101     // The system process gets more.  It is special.  Oh so special.
102     // With, you know, special needs.  Like this.
103     private static final int MAX_WAKELOCKS_PER_UID_IN_SYSTEM = 50;
104 
105     private static final String BATCHED_WAKELOCK_NAME = "*overflow*";
106 
107     private static int sNumSpeedSteps;
108 
109     private final JournaledFile mFile;
110 
111     static final int MSG_UPDATE_WAKELOCKS = 1;
112     static final int MSG_REPORT_POWER_CHANGE = 2;
113     static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
114 
115     public interface BatteryCallback {
batteryNeedsCpuUpdate()116         public void batteryNeedsCpuUpdate();
batteryPowerChanged(boolean onBattery)117         public void batteryPowerChanged(boolean onBattery);
118     }
119 
120     final class MyHandler extends Handler {
121         @Override
handleMessage(Message msg)122         public void handleMessage(Message msg) {
123             BatteryCallback cb = mCallback;
124             switch (msg.what) {
125                 case MSG_UPDATE_WAKELOCKS:
126                     if (cb != null) {
127                         cb.batteryNeedsCpuUpdate();
128                     }
129                     break;
130                 case MSG_REPORT_POWER_CHANGE:
131                     if (cb != null) {
132                         cb.batteryPowerChanged(msg.arg1 != 0);
133                     }
134                     break;
135             }
136         }
137     }
138 
139     private final MyHandler mHandler;
140 
141     private BatteryCallback mCallback;
142 
143     /**
144      * The statistics we have collected organized by uids.
145      */
146     final SparseArray<BatteryStatsImpl.Uid> mUidStats =
147         new SparseArray<BatteryStatsImpl.Uid>();
148 
149     // A set of pools of currently active timers.  When a timer is queried, we will divide the
150     // elapsed time by the number of active timers to arrive at that timer's share of the time.
151     // In order to do this, we must refresh each timer whenever the number of active timers
152     // changes.
153     final ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<StopwatchTimer>();
154     final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<StopwatchTimer>();
155     final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<StopwatchTimer>();
156     final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers
157             = new SparseArray<ArrayList<StopwatchTimer>>();
158     final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<StopwatchTimer>();
159     final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<StopwatchTimer>();
160     final ArrayList<StopwatchTimer> mScanWifiLockTimers = new ArrayList<StopwatchTimer>();
161     final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<StopwatchTimer>();
162 
163     // Last partial timers we use for distributing CPU usage.
164     final ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<StopwatchTimer>();
165 
166     // These are the objects that will want to do something when the device
167     // is unplugged from power.
168     final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>();
169 
170     boolean mShuttingDown;
171 
172     long mHistoryBaseTime;
173     boolean mHaveBatteryLevel = false;
174     boolean mRecordingHistory = true;
175     int mNumHistoryItems;
176 
177     static final int MAX_HISTORY_BUFFER = 128*1024; // 128KB
178     static final int MAX_MAX_HISTORY_BUFFER = 144*1024; // 144KB
179     final Parcel mHistoryBuffer = Parcel.obtain();
180     final HistoryItem mHistoryLastWritten = new HistoryItem();
181     final HistoryItem mHistoryLastLastWritten = new HistoryItem();
182     final HistoryItem mHistoryReadTmp = new HistoryItem();
183     int mHistoryBufferLastPos = -1;
184     boolean mHistoryOverflow = false;
185     long mLastHistoryTime = 0;
186 
187     final HistoryItem mHistoryCur = new HistoryItem();
188 
189     HistoryItem mHistory;
190     HistoryItem mHistoryEnd;
191     HistoryItem mHistoryLastEnd;
192     HistoryItem mHistoryCache;
193 
194     private HistoryItem mHistoryIterator;
195     private boolean mReadOverflow;
196     private boolean mIteratingHistory;
197 
198     int mStartCount;
199 
200     long mBatteryUptime;
201     long mBatteryLastUptime;
202     long mBatteryRealtime;
203     long mBatteryLastRealtime;
204 
205     long mUptime;
206     long mUptimeStart;
207     long mLastUptime;
208     long mRealtime;
209     long mRealtimeStart;
210     long mLastRealtime;
211 
212     boolean mScreenOn;
213     StopwatchTimer mScreenOnTimer;
214 
215     int mScreenBrightnessBin = -1;
216     final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
217 
218     Counter mInputEventCounter;
219 
220     boolean mPhoneOn;
221     StopwatchTimer mPhoneOnTimer;
222 
223     boolean mAudioOn;
224     StopwatchTimer mAudioOnTimer;
225 
226     boolean mVideoOn;
227     StopwatchTimer mVideoOnTimer;
228 
229     int mPhoneSignalStrengthBin = -1;
230     int mPhoneSignalStrengthBinRaw = -1;
231     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
232             new StopwatchTimer[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
233 
234     StopwatchTimer mPhoneSignalScanningTimer;
235 
236     int mPhoneDataConnectionType = -1;
237     final StopwatchTimer[] mPhoneDataConnectionsTimer =
238             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
239 
240     boolean mWifiOn;
241     StopwatchTimer mWifiOnTimer;
242     int mWifiOnUid = -1;
243 
244     boolean mGlobalWifiRunning;
245     StopwatchTimer mGlobalWifiRunningTimer;
246 
247     boolean mBluetoothOn;
248     StopwatchTimer mBluetoothOnTimer;
249 
250     /** Bluetooth headset object */
251     BluetoothHeadset mBtHeadset;
252 
253     /**
254      * These provide time bases that discount the time the device is plugged
255      * in to power.
256      */
257     boolean mOnBattery;
258     boolean mOnBatteryInternal;
259     long mTrackBatteryPastUptime;
260     long mTrackBatteryUptimeStart;
261     long mTrackBatteryPastRealtime;
262     long mTrackBatteryRealtimeStart;
263 
264     long mUnpluggedBatteryUptime;
265     long mUnpluggedBatteryRealtime;
266 
267     /*
268      * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
269      */
270     int mDischargeStartLevel;
271     int mDischargeUnplugLevel;
272     int mDischargeCurrentLevel;
273     int mLowDischargeAmountSinceCharge;
274     int mHighDischargeAmountSinceCharge;
275     int mDischargeScreenOnUnplugLevel;
276     int mDischargeScreenOffUnplugLevel;
277     int mDischargeAmountScreenOn;
278     int mDischargeAmountScreenOnSinceCharge;
279     int mDischargeAmountScreenOff;
280     int mDischargeAmountScreenOffSinceCharge;
281 
282     long mLastWriteTime = 0; // Milliseconds
283 
284     // Mobile data transferred while on battery
285     private long[] mMobileDataTx = new long[4];
286     private long[] mMobileDataRx = new long[4];
287     private long[] mTotalDataTx = new long[4];
288     private long[] mTotalDataRx = new long[4];
289 
290     private long mRadioDataUptime;
291     private long mRadioDataStart;
292 
293     private int mBluetoothPingCount;
294     private int mBluetoothPingStart = -1;
295 
296     private int mPhoneServiceState = -1;
297     private int mPhoneServiceStateRaw = -1;
298     private int mPhoneSimStateRaw = -1;
299 
300     /*
301      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
302      */
303     private final HashMap<String, SamplingTimer> mKernelWakelockStats =
304             new HashMap<String, SamplingTimer>();
305 
getKernelWakelockStats()306     public Map<String, ? extends SamplingTimer> getKernelWakelockStats() {
307         return mKernelWakelockStats;
308     }
309 
310     private static int sKernelWakelockUpdateVersion = 0;
311 
312     private static final int[] PROC_WAKELOCKS_FORMAT = new int[] {
313         Process.PROC_TAB_TERM|Process.PROC_OUT_STRING,                // 0: name
314         Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 1: count
315         Process.PROC_TAB_TERM,
316         Process.PROC_TAB_TERM,
317         Process.PROC_TAB_TERM,
318         Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 5: totalTime
319     };
320 
321     private final String[] mProcWakelocksName = new String[3];
322     private final long[] mProcWakelocksData = new long[3];
323 
324     /*
325      * Used as a buffer for reading in data from /proc/wakelocks before it is processed and added
326      * to mKernelWakelockStats.
327      */
328     private final Map<String, KernelWakelockStats> mProcWakelockFileStats =
329             new HashMap<String, KernelWakelockStats>();
330 
331     private HashMap<String, Integer> mUidCache = new HashMap<String, Integer>();
332 
333     private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
334 
335     /** Network ifaces that {@link ConnectivityManager} has claimed as mobile. */
336     private HashSet<String> mMobileIfaces = Sets.newHashSet();
337 
338     // For debugging
BatteryStatsImpl()339     public BatteryStatsImpl() {
340         mFile = null;
341         mHandler = null;
342     }
343 
344     public static interface Unpluggable {
unplug(long batteryUptime, long batteryRealtime)345         void unplug(long batteryUptime, long batteryRealtime);
plug(long batteryUptime, long batteryRealtime)346         void plug(long batteryUptime, long batteryRealtime);
347     }
348 
349     /**
350      * State for keeping track of counting information.
351      */
352     public static class Counter extends BatteryStats.Counter implements Unpluggable {
353         final AtomicInteger mCount = new AtomicInteger();
354         final ArrayList<Unpluggable> mUnpluggables;
355         int mLoadedCount;
356         int mLastCount;
357         int mUnpluggedCount;
358         int mPluggedCount;
359 
Counter(ArrayList<Unpluggable> unpluggables, Parcel in)360         Counter(ArrayList<Unpluggable> unpluggables, Parcel in) {
361             mUnpluggables = unpluggables;
362             mPluggedCount = in.readInt();
363             mCount.set(mPluggedCount);
364             mLoadedCount = in.readInt();
365             mLastCount = 0;
366             mUnpluggedCount = in.readInt();
367             unpluggables.add(this);
368         }
369 
Counter(ArrayList<Unpluggable> unpluggables)370         Counter(ArrayList<Unpluggable> unpluggables) {
371             mUnpluggables = unpluggables;
372             unpluggables.add(this);
373         }
374 
writeToParcel(Parcel out)375         public void writeToParcel(Parcel out) {
376             out.writeInt(mCount.get());
377             out.writeInt(mLoadedCount);
378             out.writeInt(mUnpluggedCount);
379         }
380 
unplug(long batteryUptime, long batteryRealtime)381         public void unplug(long batteryUptime, long batteryRealtime) {
382             mUnpluggedCount = mPluggedCount;
383             mCount.set(mPluggedCount);
384         }
385 
plug(long batteryUptime, long batteryRealtime)386         public void plug(long batteryUptime, long batteryRealtime) {
387             mPluggedCount = mCount.get();
388         }
389 
390         /**
391          * Writes a possibly null Counter to a Parcel.
392          *
393          * @param out the Parcel to be written to.
394          * @param counter a Counter, or null.
395          */
writeCounterToParcel(Parcel out, Counter counter)396         public static void writeCounterToParcel(Parcel out, Counter counter) {
397             if (counter == null) {
398                 out.writeInt(0); // indicates null
399                 return;
400             }
401             out.writeInt(1); // indicates non-null
402 
403             counter.writeToParcel(out);
404         }
405 
406         @Override
getCountLocked(int which)407         public int getCountLocked(int which) {
408             int val;
409             if (which == STATS_LAST) {
410                 val = mLastCount;
411             } else {
412                 val = mCount.get();
413                 if (which == STATS_SINCE_UNPLUGGED) {
414                     val -= mUnpluggedCount;
415                 } else if (which != STATS_SINCE_CHARGED) {
416                     val -= mLoadedCount;
417                 }
418             }
419 
420             return val;
421         }
422 
logState(Printer pw, String prefix)423         public void logState(Printer pw, String prefix) {
424             pw.println(prefix + "mCount=" + mCount.get()
425                     + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
426                     + " mUnpluggedCount=" + mUnpluggedCount
427                     + " mPluggedCount=" + mPluggedCount);
428         }
429 
stepAtomic()430         void stepAtomic() {
431             mCount.incrementAndGet();
432         }
433 
434         /**
435          * Clear state of this counter.
436          */
reset(boolean detachIfReset)437         void reset(boolean detachIfReset) {
438             mCount.set(0);
439             mLoadedCount = mLastCount = mPluggedCount = mUnpluggedCount = 0;
440             if (detachIfReset) {
441                 detach();
442             }
443         }
444 
detach()445         void detach() {
446             mUnpluggables.remove(this);
447         }
448 
writeSummaryFromParcelLocked(Parcel out)449         void writeSummaryFromParcelLocked(Parcel out) {
450             int count = mCount.get();
451             out.writeInt(count);
452         }
453 
readSummaryFromParcelLocked(Parcel in)454         void readSummaryFromParcelLocked(Parcel in) {
455             mLoadedCount = in.readInt();
456             mCount.set(mLoadedCount);
457             mLastCount = 0;
458             mUnpluggedCount = mPluggedCount = mLoadedCount;
459         }
460     }
461 
462     public static class SamplingCounter extends Counter {
463 
SamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in)464         SamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in) {
465             super(unpluggables, in);
466         }
467 
SamplingCounter(ArrayList<Unpluggable> unpluggables)468         SamplingCounter(ArrayList<Unpluggable> unpluggables) {
469             super(unpluggables);
470         }
471 
addCountAtomic(long count)472         public void addCountAtomic(long count) {
473             mCount.addAndGet((int)count);
474         }
475     }
476 
477     /**
478      * State for keeping track of timing information.
479      */
480     public static abstract class Timer extends BatteryStats.Timer implements Unpluggable {
481         final int mType;
482         final ArrayList<Unpluggable> mUnpluggables;
483 
484         int mCount;
485         int mLoadedCount;
486         int mLastCount;
487         int mUnpluggedCount;
488 
489         // Times are in microseconds for better accuracy when dividing by the
490         // lock count, and are in "battery realtime" units.
491 
492         /**
493          * The total time we have accumulated since the start of the original
494          * boot, to the last time something interesting happened in the
495          * current run.
496          */
497         long mTotalTime;
498 
499         /**
500          * The total time we loaded for the previous runs.  Subtract this from
501          * mTotalTime to find the time for the current run of the system.
502          */
503         long mLoadedTime;
504 
505         /**
506          * The run time of the last run of the system, as loaded from the
507          * saved data.
508          */
509         long mLastTime;
510 
511         /**
512          * The value of mTotalTime when unplug() was last called.  Subtract
513          * this from mTotalTime to find the time since the last unplug from
514          * power.
515          */
516         long mUnpluggedTime;
517 
518         /**
519          * Constructs from a parcel.
520          * @param type
521          * @param unpluggables
522          * @param powerType
523          * @param in
524          */
Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in)525         Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in) {
526             mType = type;
527             mUnpluggables = unpluggables;
528 
529             mCount = in.readInt();
530             mLoadedCount = in.readInt();
531             mLastCount = 0;
532             mUnpluggedCount = in.readInt();
533             mTotalTime = in.readLong();
534             mLoadedTime = in.readLong();
535             mLastTime = 0;
536             mUnpluggedTime = in.readLong();
537             unpluggables.add(this);
538         }
539 
Timer(int type, ArrayList<Unpluggable> unpluggables)540         Timer(int type, ArrayList<Unpluggable> unpluggables) {
541             mType = type;
542             mUnpluggables = unpluggables;
543             unpluggables.add(this);
544         }
545 
computeRunTimeLocked(long curBatteryRealtime)546         protected abstract long computeRunTimeLocked(long curBatteryRealtime);
547 
computeCurrentCountLocked()548         protected abstract int computeCurrentCountLocked();
549 
550         /**
551          * Clear state of this timer.  Returns true if the timer is inactive
552          * so can be completely dropped.
553          */
reset(BatteryStatsImpl stats, boolean detachIfReset)554         boolean reset(BatteryStatsImpl stats, boolean detachIfReset) {
555             mTotalTime = mLoadedTime = mLastTime = 0;
556             mCount = mLoadedCount = mLastCount = 0;
557             if (detachIfReset) {
558                 detach();
559             }
560             return true;
561         }
562 
detach()563         void detach() {
564             mUnpluggables.remove(this);
565         }
566 
writeToParcel(Parcel out, long batteryRealtime)567         public void writeToParcel(Parcel out, long batteryRealtime) {
568             out.writeInt(mCount);
569             out.writeInt(mLoadedCount);
570             out.writeInt(mUnpluggedCount);
571             out.writeLong(computeRunTimeLocked(batteryRealtime));
572             out.writeLong(mLoadedTime);
573             out.writeLong(mUnpluggedTime);
574         }
575 
unplug(long batteryUptime, long batteryRealtime)576         public void unplug(long batteryUptime, long batteryRealtime) {
577             if (DEBUG && mType < 0) {
578                 Log.v(TAG, "unplug #" + mType + ": realtime=" + batteryRealtime
579                         + " old mUnpluggedTime=" + mUnpluggedTime
580                         + " old mUnpluggedCount=" + mUnpluggedCount);
581             }
582             mUnpluggedTime = computeRunTimeLocked(batteryRealtime);
583             mUnpluggedCount = mCount;
584             if (DEBUG && mType < 0) {
585                 Log.v(TAG, "unplug #" + mType
586                         + ": new mUnpluggedTime=" + mUnpluggedTime
587                         + " new mUnpluggedCount=" + mUnpluggedCount);
588             }
589         }
590 
plug(long batteryUptime, long batteryRealtime)591         public void plug(long batteryUptime, long batteryRealtime) {
592             if (DEBUG && mType < 0) {
593                 Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime
594                         + " old mTotalTime=" + mTotalTime);
595             }
596             mTotalTime = computeRunTimeLocked(batteryRealtime);
597             mCount = computeCurrentCountLocked();
598             if (DEBUG && mType < 0) {
599                 Log.v(TAG, "plug #" + mType
600                         + ": new mTotalTime=" + mTotalTime);
601             }
602         }
603 
604         /**
605          * Writes a possibly null Timer to a Parcel.
606          *
607          * @param out the Parcel to be written to.
608          * @param timer a Timer, or null.
609          */
writeTimerToParcel(Parcel out, Timer timer, long batteryRealtime)610         public static void writeTimerToParcel(Parcel out, Timer timer,
611                 long batteryRealtime) {
612             if (timer == null) {
613                 out.writeInt(0); // indicates null
614                 return;
615             }
616             out.writeInt(1); // indicates non-null
617 
618             timer.writeToParcel(out, batteryRealtime);
619         }
620 
621         @Override
getTotalTimeLocked(long batteryRealtime, int which)622         public long getTotalTimeLocked(long batteryRealtime, int which) {
623             long val;
624             if (which == STATS_LAST) {
625                 val = mLastTime;
626             } else {
627                 val = computeRunTimeLocked(batteryRealtime);
628                 if (which == STATS_SINCE_UNPLUGGED) {
629                     val -= mUnpluggedTime;
630                 } else if (which != STATS_SINCE_CHARGED) {
631                     val -= mLoadedTime;
632                 }
633             }
634 
635             return val;
636         }
637 
638         @Override
getCountLocked(int which)639         public int getCountLocked(int which) {
640             int val;
641             if (which == STATS_LAST) {
642                 val = mLastCount;
643             } else {
644                 val = computeCurrentCountLocked();
645                 if (which == STATS_SINCE_UNPLUGGED) {
646                     val -= mUnpluggedCount;
647                 } else if (which != STATS_SINCE_CHARGED) {
648                     val -= mLoadedCount;
649                 }
650             }
651 
652             return val;
653         }
654 
logState(Printer pw, String prefix)655         public void logState(Printer pw, String prefix) {
656             pw.println(prefix + " mCount=" + mCount
657                     + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
658                     + " mUnpluggedCount=" + mUnpluggedCount);
659             pw.println(prefix + "mTotalTime=" + mTotalTime
660                     + " mLoadedTime=" + mLoadedTime);
661             pw.println(prefix + "mLastTime=" + mLastTime
662                     + " mUnpluggedTime=" + mUnpluggedTime);
663         }
664 
665 
writeSummaryFromParcelLocked(Parcel out, long batteryRealtime)666         void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
667             long runTime = computeRunTimeLocked(batteryRealtime);
668             // Divide by 1000 for backwards compatibility
669             out.writeLong((runTime + 500) / 1000);
670             out.writeInt(mCount);
671         }
672 
readSummaryFromParcelLocked(Parcel in)673         void readSummaryFromParcelLocked(Parcel in) {
674             // Multiply by 1000 for backwards compatibility
675             mTotalTime = mLoadedTime = in.readLong() * 1000;
676             mLastTime = 0;
677             mUnpluggedTime = mTotalTime;
678             mCount = mLoadedCount = in.readInt();
679             mLastCount = 0;
680             mUnpluggedCount = mCount;
681         }
682     }
683 
684     public static final class SamplingTimer extends Timer {
685 
686         /**
687          * The most recent reported count from /proc/wakelocks.
688          */
689         int mCurrentReportedCount;
690 
691         /**
692          * The reported count from /proc/wakelocks when unplug() was last
693          * called.
694          */
695         int mUnpluggedReportedCount;
696 
697         /**
698          * The most recent reported total_time from /proc/wakelocks.
699          */
700         long mCurrentReportedTotalTime;
701 
702 
703         /**
704          * The reported total_time from /proc/wakelocks when unplug() was last
705          * called.
706          */
707         long mUnpluggedReportedTotalTime;
708 
709         /**
710          * Whether we are currently in a discharge cycle.
711          */
712         boolean mInDischarge;
713 
714         /**
715          * Whether we are currently recording reported values.
716          */
717         boolean mTrackingReportedValues;
718 
719         /*
720          * A sequnce counter, incremented once for each update of the stats.
721          */
722         int mUpdateVersion;
723 
SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, Parcel in)724         SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, Parcel in) {
725             super(0, unpluggables, in);
726             mCurrentReportedCount = in.readInt();
727             mUnpluggedReportedCount = in.readInt();
728             mCurrentReportedTotalTime = in.readLong();
729             mUnpluggedReportedTotalTime = in.readLong();
730             mTrackingReportedValues = in.readInt() == 1;
731             mInDischarge = inDischarge;
732         }
733 
SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, boolean trackReportedValues)734         SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge,
735                 boolean trackReportedValues) {
736             super(0, unpluggables);
737             mTrackingReportedValues = trackReportedValues;
738             mInDischarge = inDischarge;
739         }
740 
setStale()741         public void setStale() {
742             mTrackingReportedValues = false;
743             mUnpluggedReportedTotalTime = 0;
744             mUnpluggedReportedCount = 0;
745         }
746 
setUpdateVersion(int version)747         public void setUpdateVersion(int version) {
748             mUpdateVersion = version;
749         }
750 
getUpdateVersion()751         public int getUpdateVersion() {
752             return mUpdateVersion;
753         }
754 
updateCurrentReportedCount(int count)755         public void updateCurrentReportedCount(int count) {
756             if (mInDischarge && mUnpluggedReportedCount == 0) {
757                 // Updating the reported value for the first time.
758                 mUnpluggedReportedCount = count;
759                 // If we are receiving an update update mTrackingReportedValues;
760                 mTrackingReportedValues = true;
761             }
762             mCurrentReportedCount = count;
763         }
764 
updateCurrentReportedTotalTime(long totalTime)765         public void updateCurrentReportedTotalTime(long totalTime) {
766             if (mInDischarge && mUnpluggedReportedTotalTime == 0) {
767                 // Updating the reported value for the first time.
768                 mUnpluggedReportedTotalTime = totalTime;
769                 // If we are receiving an update update mTrackingReportedValues;
770                 mTrackingReportedValues = true;
771             }
772             mCurrentReportedTotalTime = totalTime;
773         }
774 
unplug(long batteryUptime, long batteryRealtime)775         public void unplug(long batteryUptime, long batteryRealtime) {
776             super.unplug(batteryUptime, batteryRealtime);
777             if (mTrackingReportedValues) {
778                 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
779                 mUnpluggedReportedCount = mCurrentReportedCount;
780             }
781             mInDischarge = true;
782         }
783 
plug(long batteryUptime, long batteryRealtime)784         public void plug(long batteryUptime, long batteryRealtime) {
785             super.plug(batteryUptime, batteryRealtime);
786             mInDischarge = false;
787         }
788 
logState(Printer pw, String prefix)789         public void logState(Printer pw, String prefix) {
790             super.logState(pw, prefix);
791             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
792                     + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
793                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
794                     + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
795         }
796 
computeRunTimeLocked(long curBatteryRealtime)797         protected long computeRunTimeLocked(long curBatteryRealtime) {
798             return mTotalTime + (mInDischarge && mTrackingReportedValues
799                     ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
800         }
801 
computeCurrentCountLocked()802         protected int computeCurrentCountLocked() {
803             return mCount + (mInDischarge && mTrackingReportedValues
804                     ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
805         }
806 
writeToParcel(Parcel out, long batteryRealtime)807         public void writeToParcel(Parcel out, long batteryRealtime) {
808             super.writeToParcel(out, batteryRealtime);
809             out.writeInt(mCurrentReportedCount);
810             out.writeInt(mUnpluggedReportedCount);
811             out.writeLong(mCurrentReportedTotalTime);
812             out.writeLong(mUnpluggedReportedTotalTime);
813             out.writeInt(mTrackingReportedValues ? 1 : 0);
814         }
815 
reset(BatteryStatsImpl stats, boolean detachIfReset)816         boolean reset(BatteryStatsImpl stats, boolean detachIfReset) {
817             super.reset(stats, detachIfReset);
818             setStale();
819             return true;
820         }
821 
writeSummaryFromParcelLocked(Parcel out, long batteryRealtime)822         void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
823             super.writeSummaryFromParcelLocked(out, batteryRealtime);
824             out.writeLong(mCurrentReportedTotalTime);
825             out.writeInt(mCurrentReportedCount);
826             out.writeInt(mTrackingReportedValues ? 1 : 0);
827         }
828 
readSummaryFromParcelLocked(Parcel in)829         void readSummaryFromParcelLocked(Parcel in) {
830             super.readSummaryFromParcelLocked(in);
831             mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong();
832             mUnpluggedReportedCount = mCurrentReportedCount = in.readInt();
833             mTrackingReportedValues = in.readInt() == 1;
834         }
835     }
836 
837     /**
838      * State for keeping track of timing information.
839      */
840     public static final class StopwatchTimer extends Timer {
841         final Uid mUid;
842         final ArrayList<StopwatchTimer> mTimerPool;
843 
844         int mNesting;
845 
846         /**
847          * The last time at which we updated the timer.  If mNesting is > 0,
848          * subtract this from the current battery time to find the amount of
849          * time we have been running since we last computed an update.
850          */
851         long mUpdateTime;
852 
853         /**
854          * The total time at which the timer was acquired, to determine if it
855          * was actually held for an interesting duration.
856          */
857         long mAcquireTime;
858 
859         long mTimeout;
860 
861         /**
862          * For partial wake locks, keep track of whether we are in the list
863          * to consume CPU cycles.
864          */
865         boolean mInList;
866 
StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool, ArrayList<Unpluggable> unpluggables, Parcel in)867         StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
868                 ArrayList<Unpluggable> unpluggables, Parcel in) {
869             super(type, unpluggables, in);
870             mUid = uid;
871             mTimerPool = timerPool;
872             mUpdateTime = in.readLong();
873         }
874 
StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool, ArrayList<Unpluggable> unpluggables)875         StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
876                 ArrayList<Unpluggable> unpluggables) {
877             super(type, unpluggables);
878             mUid = uid;
879             mTimerPool = timerPool;
880         }
881 
setTimeout(long timeout)882         void setTimeout(long timeout) {
883             mTimeout = timeout;
884         }
885 
writeToParcel(Parcel out, long batteryRealtime)886         public void writeToParcel(Parcel out, long batteryRealtime) {
887             super.writeToParcel(out, batteryRealtime);
888             out.writeLong(mUpdateTime);
889         }
890 
plug(long batteryUptime, long batteryRealtime)891         public void plug(long batteryUptime, long batteryRealtime) {
892             if (mNesting > 0) {
893                 if (DEBUG && mType < 0) {
894                     Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
895                 }
896                 super.plug(batteryUptime, batteryRealtime);
897                 mUpdateTime = batteryRealtime;
898                 if (DEBUG && mType < 0) {
899                     Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
900                 }
901             }
902         }
903 
logState(Printer pw, String prefix)904         public void logState(Printer pw, String prefix) {
905             super.logState(pw, prefix);
906             pw.println(prefix + "mNesting=" + mNesting + "mUpdateTime=" + mUpdateTime
907                     + " mAcquireTime=" + mAcquireTime);
908         }
909 
startRunningLocked(BatteryStatsImpl stats)910         void startRunningLocked(BatteryStatsImpl stats) {
911             if (mNesting++ == 0) {
912                 mUpdateTime = stats.getBatteryRealtimeLocked(
913                         SystemClock.elapsedRealtime() * 1000);
914                 if (mTimerPool != null) {
915                     // Accumulate time to all currently active timers before adding
916                     // this new one to the pool.
917                     refreshTimersLocked(stats, mTimerPool);
918                     // Add this timer to the active pool
919                     mTimerPool.add(this);
920                 }
921                 // Increment the count
922                 mCount++;
923                 mAcquireTime = mTotalTime;
924                 if (DEBUG && mType < 0) {
925                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
926                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
927                             + " mAcquireTime=" + mAcquireTime);
928                 }
929             }
930         }
931 
isRunningLocked()932         boolean isRunningLocked() {
933             return mNesting > 0;
934         }
935 
stopRunningLocked(BatteryStatsImpl stats)936         void stopRunningLocked(BatteryStatsImpl stats) {
937             // Ignore attempt to stop a timer that isn't running
938             if (mNesting == 0) {
939                 return;
940             }
941             if (--mNesting == 0) {
942                 if (mTimerPool != null) {
943                     // Accumulate time to all active counters, scaled by the total
944                     // active in the pool, before taking this one out of the pool.
945                     refreshTimersLocked(stats, mTimerPool);
946                     // Remove this timer from the active pool
947                     mTimerPool.remove(this);
948                 } else {
949                     final long realtime = SystemClock.elapsedRealtime() * 1000;
950                     final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
951                     mNesting = 1;
952                     mTotalTime = computeRunTimeLocked(batteryRealtime);
953                     mNesting = 0;
954                 }
955 
956                 if (DEBUG && mType < 0) {
957                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
958                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
959                             + " mAcquireTime=" + mAcquireTime);
960                 }
961 
962                 if (mTotalTime == mAcquireTime) {
963                     // If there was no change in the time, then discard this
964                     // count.  A somewhat cheezy strategy, but hey.
965                     mCount--;
966                 }
967             }
968         }
969 
970         // Update the total time for all other running Timers with the same type as this Timer
971         // due to a change in timer count
refreshTimersLocked(final BatteryStatsImpl stats, final ArrayList<StopwatchTimer> pool)972         private static void refreshTimersLocked(final BatteryStatsImpl stats,
973                 final ArrayList<StopwatchTimer> pool) {
974             final long realtime = SystemClock.elapsedRealtime() * 1000;
975             final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
976             final int N = pool.size();
977             for (int i=N-1; i>= 0; i--) {
978                 final StopwatchTimer t = pool.get(i);
979                 long heldTime = batteryRealtime - t.mUpdateTime;
980                 if (heldTime > 0) {
981                     t.mTotalTime += heldTime / N;
982                 }
983                 t.mUpdateTime = batteryRealtime;
984             }
985         }
986 
987         @Override
computeRunTimeLocked(long curBatteryRealtime)988         protected long computeRunTimeLocked(long curBatteryRealtime) {
989             if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) {
990                 curBatteryRealtime = mUpdateTime + mTimeout;
991             }
992             return mTotalTime + (mNesting > 0
993                     ? (curBatteryRealtime - mUpdateTime)
994                             / (mTimerPool != null ? mTimerPool.size() : 1)
995                     : 0);
996         }
997 
998         @Override
computeCurrentCountLocked()999         protected int computeCurrentCountLocked() {
1000             return mCount;
1001         }
1002 
reset(BatteryStatsImpl stats, boolean detachIfReset)1003         boolean reset(BatteryStatsImpl stats, boolean detachIfReset) {
1004             boolean canDetach = mNesting <= 0;
1005             super.reset(stats, canDetach && detachIfReset);
1006             if (mNesting > 0) {
1007                 mUpdateTime = stats.getBatteryRealtimeLocked(
1008                         SystemClock.elapsedRealtime() * 1000);
1009             }
1010             mAcquireTime = mTotalTime;
1011             return canDetach;
1012         }
1013 
detach()1014         void detach() {
1015             super.detach();
1016             if (mTimerPool != null) {
1017                 mTimerPool.remove(this);
1018             }
1019         }
1020 
readSummaryFromParcelLocked(Parcel in)1021         void readSummaryFromParcelLocked(Parcel in) {
1022             super.readSummaryFromParcelLocked(in);
1023             mNesting = 0;
1024         }
1025     }
1026 
readKernelWakelockStats()1027     private final Map<String, KernelWakelockStats> readKernelWakelockStats() {
1028 
1029         byte[] buffer = new byte[8192];
1030         int len;
1031 
1032         try {
1033             FileInputStream is = new FileInputStream("/proc/wakelocks");
1034             len = is.read(buffer);
1035             is.close();
1036 
1037             if (len > 0) {
1038                 int i;
1039                 for (i=0; i<len; i++) {
1040                     if (buffer[i] == '\0') {
1041                         len = i;
1042                         break;
1043                     }
1044                 }
1045             }
1046         } catch (java.io.FileNotFoundException e) {
1047             return null;
1048         } catch (java.io.IOException e) {
1049             return null;
1050         }
1051 
1052         return parseProcWakelocks(buffer, len);
1053     }
1054 
parseProcWakelocks( byte[] wlBuffer, int len)1055     private final Map<String, KernelWakelockStats> parseProcWakelocks(
1056             byte[] wlBuffer, int len) {
1057         String name;
1058         int count;
1059         long totalTime;
1060         int startIndex;
1061         int endIndex;
1062         int numUpdatedWlNames = 0;
1063 
1064         // Advance past the first line.
1065         int i;
1066         for (i = 0; i < len && wlBuffer[i] != '\n' && wlBuffer[i] != '\0'; i++);
1067         startIndex = endIndex = i + 1;
1068 
1069         synchronized(this) {
1070             Map<String, KernelWakelockStats> m = mProcWakelockFileStats;
1071 
1072             sKernelWakelockUpdateVersion++;
1073             while (endIndex < len) {
1074                 for (endIndex=startIndex;
1075                         endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0';
1076                         endIndex++);
1077                 endIndex++; // endIndex is an exclusive upper bound.
1078                 // Don't go over the end of the buffer, Process.parseProcLine might
1079                 // write to wlBuffer[endIndex]
1080                 if (endIndex >= (len - 1) ) {
1081                     return m;
1082                 }
1083 
1084                 String[] nameStringArray = mProcWakelocksName;
1085                 long[] wlData = mProcWakelocksData;
1086                 // Stomp out any bad characters since this is from a circular buffer
1087                 // A corruption is seen sometimes that results in the vm crashing
1088                 // This should prevent crashes and the line will probably fail to parse
1089                 for (int j = startIndex; j < endIndex; j++) {
1090                     if ((wlBuffer[j] & 0x80) != 0) wlBuffer[j] = (byte) '?';
1091                 }
1092                 boolean parsed = Process.parseProcLine(wlBuffer, startIndex, endIndex,
1093                         PROC_WAKELOCKS_FORMAT, nameStringArray, wlData, null);
1094 
1095                 name = nameStringArray[0];
1096                 count = (int) wlData[1];
1097                 // convert nanoseconds to microseconds with rounding.
1098                 totalTime = (wlData[2] + 500) / 1000;
1099 
1100                 if (parsed && name.length() > 0) {
1101                     if (!m.containsKey(name)) {
1102                         m.put(name, new KernelWakelockStats(count, totalTime,
1103                                 sKernelWakelockUpdateVersion));
1104                         numUpdatedWlNames++;
1105                     } else {
1106                         KernelWakelockStats kwlStats = m.get(name);
1107                         if (kwlStats.mVersion == sKernelWakelockUpdateVersion) {
1108                             kwlStats.mCount += count;
1109                             kwlStats.mTotalTime += totalTime;
1110                         } else {
1111                             kwlStats.mCount = count;
1112                             kwlStats.mTotalTime = totalTime;
1113                             kwlStats.mVersion = sKernelWakelockUpdateVersion;
1114                             numUpdatedWlNames++;
1115                         }
1116                     }
1117                 }
1118                 startIndex = endIndex;
1119             }
1120 
1121             if (m.size() != numUpdatedWlNames) {
1122                 // Don't report old data.
1123                 Iterator<KernelWakelockStats> itr = m.values().iterator();
1124                 while (itr.hasNext()) {
1125                     if (itr.next().mVersion != sKernelWakelockUpdateVersion) {
1126                         itr.remove();
1127                     }
1128                 }
1129             }
1130             return m;
1131         }
1132     }
1133 
1134     private class KernelWakelockStats {
1135         public int mCount;
1136         public long mTotalTime;
1137         public int mVersion;
1138 
KernelWakelockStats(int count, long totalTime, int version)1139         KernelWakelockStats(int count, long totalTime, int version) {
1140             mCount = count;
1141             mTotalTime = totalTime;
1142             mVersion = version;
1143         }
1144     }
1145 
1146     /*
1147      * Get the KernelWakelockTimer associated with name, and create a new one if one
1148      * doesn't already exist.
1149      */
getKernelWakelockTimerLocked(String name)1150     public SamplingTimer getKernelWakelockTimerLocked(String name) {
1151         SamplingTimer kwlt = mKernelWakelockStats.get(name);
1152         if (kwlt == null) {
1153             kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal,
1154                     true /* track reported values */);
1155             mKernelWakelockStats.put(name, kwlt);
1156         }
1157         return kwlt;
1158     }
1159 
doDataPlug(long[] dataTransfer, long currentBytes)1160     private void doDataPlug(long[] dataTransfer, long currentBytes) {
1161         dataTransfer[STATS_LAST] = dataTransfer[STATS_SINCE_UNPLUGGED];
1162         dataTransfer[STATS_SINCE_UNPLUGGED] = -1;
1163     }
1164 
doDataUnplug(long[] dataTransfer, long currentBytes)1165     private void doDataUnplug(long[] dataTransfer, long currentBytes) {
1166         dataTransfer[STATS_SINCE_UNPLUGGED] = currentBytes;
1167     }
1168 
1169     /**
1170      * Radio uptime in microseconds when transferring data. This value is very approximate.
1171      * @return
1172      */
getCurrentRadioDataUptime()1173     private long getCurrentRadioDataUptime() {
1174         try {
1175             File awakeTimeFile = new File("/sys/devices/virtual/net/rmnet0/awake_time_ms");
1176             if (!awakeTimeFile.exists()) return 0;
1177             BufferedReader br = new BufferedReader(new FileReader(awakeTimeFile));
1178             String line = br.readLine();
1179             br.close();
1180             return Long.parseLong(line) * 1000;
1181         } catch (NumberFormatException nfe) {
1182             // Nothing
1183         } catch (IOException ioe) {
1184             // Nothing
1185         }
1186         return 0;
1187     }
1188 
1189     /**
1190      * @deprecated use getRadioDataUptime
1191      */
getRadioDataUptimeMs()1192     public long getRadioDataUptimeMs() {
1193         return getRadioDataUptime() / 1000;
1194     }
1195 
1196     /**
1197      * Returns the duration that the cell radio was up for data transfers.
1198      */
getRadioDataUptime()1199     public long getRadioDataUptime() {
1200         if (mRadioDataStart == -1) {
1201             return mRadioDataUptime;
1202         } else {
1203             return getCurrentRadioDataUptime() - mRadioDataStart;
1204         }
1205     }
1206 
getCurrentBluetoothPingCount()1207     private int getCurrentBluetoothPingCount() {
1208         if (mBtHeadset != null) {
1209             List<BluetoothDevice> deviceList = mBtHeadset.getConnectedDevices();
1210             if (deviceList.size() > 0) {
1211                 return mBtHeadset.getBatteryUsageHint(deviceList.get(0));
1212             }
1213         }
1214         return -1;
1215     }
1216 
getBluetoothPingCount()1217     public int getBluetoothPingCount() {
1218         if (mBluetoothPingStart == -1) {
1219             return mBluetoothPingCount;
1220         } else if (mBtHeadset != null) {
1221             return getCurrentBluetoothPingCount() - mBluetoothPingStart;
1222         }
1223         return 0;
1224     }
1225 
setBtHeadset(BluetoothHeadset headset)1226     public void setBtHeadset(BluetoothHeadset headset) {
1227         if (headset != null && mBtHeadset == null && isOnBattery() && mBluetoothPingStart == -1) {
1228             mBluetoothPingStart = getCurrentBluetoothPingCount();
1229         }
1230         mBtHeadset = headset;
1231     }
1232 
1233     int mChangedBufferStates = 0;
1234 
addHistoryBufferLocked(long curTime)1235     void addHistoryBufferLocked(long curTime) {
1236         if (!mHaveBatteryLevel || !mRecordingHistory) {
1237             return;
1238         }
1239 
1240         final long timeDiff = (mHistoryBaseTime+curTime) - mHistoryLastWritten.time;
1241         if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
1242                 && timeDiff < 2000
1243                 && ((mHistoryLastWritten.states^mHistoryCur.states)&mChangedBufferStates) == 0) {
1244             // If the current is the same as the one before, then we no
1245             // longer need the entry.
1246             mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
1247             mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
1248             mHistoryBufferLastPos = -1;
1249             if (mHistoryLastLastWritten.cmd == HistoryItem.CMD_UPDATE
1250                     && timeDiff < 500 && mHistoryLastLastWritten.same(mHistoryCur)) {
1251                 // If this results in us returning to the state written
1252                 // prior to the last one, then we can just delete the last
1253                 // written one and drop the new one.  Nothing more to do.
1254                 mHistoryLastWritten.setTo(mHistoryLastLastWritten);
1255                 mHistoryLastLastWritten.cmd = HistoryItem.CMD_NULL;
1256                 return;
1257             }
1258             mChangedBufferStates |= mHistoryLastWritten.states^mHistoryCur.states;
1259             curTime = mHistoryLastWritten.time - mHistoryBaseTime;
1260             mHistoryLastWritten.setTo(mHistoryLastLastWritten);
1261         } else {
1262             mChangedBufferStates = 0;
1263         }
1264 
1265         final int dataSize = mHistoryBuffer.dataSize();
1266         if (dataSize >= MAX_HISTORY_BUFFER) {
1267             if (!mHistoryOverflow) {
1268                 mHistoryOverflow = true;
1269                 addHistoryBufferLocked(curTime, HistoryItem.CMD_OVERFLOW);
1270             }
1271 
1272             // Once we've reached the maximum number of items, we only
1273             // record changes to the battery level and the most interesting states.
1274             // Once we've reached the maximum maximum number of items, we only
1275             // record changes to the battery level.
1276             if (mHistoryLastWritten.batteryLevel == mHistoryCur.batteryLevel &&
1277                     (dataSize >= MAX_MAX_HISTORY_BUFFER
1278                             || ((mHistoryEnd.states^mHistoryCur.states)
1279                                     & HistoryItem.MOST_INTERESTING_STATES) == 0)) {
1280                 return;
1281             }
1282         }
1283 
1284         addHistoryBufferLocked(curTime, HistoryItem.CMD_UPDATE);
1285     }
1286 
addHistoryBufferLocked(long curTime, byte cmd)1287     void addHistoryBufferLocked(long curTime, byte cmd) {
1288         int origPos = 0;
1289         if (mIteratingHistory) {
1290             origPos = mHistoryBuffer.dataPosition();
1291             mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
1292         }
1293         mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
1294         mHistoryLastLastWritten.setTo(mHistoryLastWritten);
1295         mHistoryLastWritten.setTo(mHistoryBaseTime + curTime, cmd, mHistoryCur);
1296         mHistoryLastWritten.writeDelta(mHistoryBuffer, mHistoryLastLastWritten);
1297         mLastHistoryTime = curTime;
1298         if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
1299                 + " now " + mHistoryBuffer.dataPosition()
1300                 + " size is now " + mHistoryBuffer.dataSize());
1301         if (mIteratingHistory) {
1302             mHistoryBuffer.setDataPosition(origPos);
1303         }
1304     }
1305 
1306     int mChangedStates = 0;
1307 
addHistoryRecordLocked(long curTime)1308     void addHistoryRecordLocked(long curTime) {
1309         addHistoryBufferLocked(curTime);
1310 
1311         if (!USE_OLD_HISTORY) {
1312             return;
1313         }
1314 
1315         if (!mHaveBatteryLevel || !mRecordingHistory) {
1316             return;
1317         }
1318 
1319         // If the current time is basically the same as the last time,
1320         // and no states have since the last recorded entry changed and
1321         // are now resetting back to their original value, then just collapse
1322         // into one record.
1323         if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE
1324                 && (mHistoryBaseTime+curTime) < (mHistoryEnd.time+2000)
1325                 && ((mHistoryEnd.states^mHistoryCur.states)&mChangedStates) == 0) {
1326             // If the current is the same as the one before, then we no
1327             // longer need the entry.
1328             if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE
1329                     && (mHistoryBaseTime+curTime) < (mHistoryEnd.time+500)
1330                     && mHistoryLastEnd.same(mHistoryCur)) {
1331                 mHistoryLastEnd.next = null;
1332                 mHistoryEnd.next = mHistoryCache;
1333                 mHistoryCache = mHistoryEnd;
1334                 mHistoryEnd = mHistoryLastEnd;
1335                 mHistoryLastEnd = null;
1336             } else {
1337                 mChangedStates |= mHistoryEnd.states^mHistoryCur.states;
1338                 mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, mHistoryCur);
1339             }
1340             return;
1341         }
1342 
1343         mChangedStates = 0;
1344 
1345         if (mNumHistoryItems == MAX_HISTORY_ITEMS
1346                 || mNumHistoryItems == MAX_MAX_HISTORY_ITEMS) {
1347             addHistoryRecordLocked(curTime, HistoryItem.CMD_OVERFLOW);
1348         }
1349 
1350         if (mNumHistoryItems >= MAX_HISTORY_ITEMS) {
1351             // Once we've reached the maximum number of items, we only
1352             // record changes to the battery level and the most interesting states.
1353             // Once we've reached the maximum maximum number of items, we only
1354             // record changes to the battery level.
1355             if (mHistoryEnd != null && mHistoryEnd.batteryLevel
1356                     == mHistoryCur.batteryLevel &&
1357                     (mNumHistoryItems >= MAX_MAX_HISTORY_ITEMS
1358                             || ((mHistoryEnd.states^mHistoryCur.states)
1359                                     & HistoryItem.MOST_INTERESTING_STATES) == 0)) {
1360                 return;
1361             }
1362         }
1363 
1364         addHistoryRecordLocked(curTime, HistoryItem.CMD_UPDATE);
1365     }
1366 
addHistoryRecordLocked(long curTime, byte cmd)1367     void addHistoryRecordLocked(long curTime, byte cmd) {
1368         HistoryItem rec = mHistoryCache;
1369         if (rec != null) {
1370             mHistoryCache = rec.next;
1371         } else {
1372             rec = new HistoryItem();
1373         }
1374         rec.setTo(mHistoryBaseTime + curTime, cmd, mHistoryCur);
1375 
1376         addHistoryRecordLocked(rec);
1377     }
1378 
addHistoryRecordLocked(HistoryItem rec)1379     void addHistoryRecordLocked(HistoryItem rec) {
1380         mNumHistoryItems++;
1381         rec.next = null;
1382         mHistoryLastEnd = mHistoryEnd;
1383         if (mHistoryEnd != null) {
1384             mHistoryEnd.next = rec;
1385             mHistoryEnd = rec;
1386         } else {
1387             mHistory = mHistoryEnd = rec;
1388         }
1389     }
1390 
clearHistoryLocked()1391     void clearHistoryLocked() {
1392         if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
1393         if (USE_OLD_HISTORY) {
1394             if (mHistory != null) {
1395                 mHistoryEnd.next = mHistoryCache;
1396                 mHistoryCache = mHistory;
1397                 mHistory = mHistoryLastEnd = mHistoryEnd = null;
1398             }
1399             mNumHistoryItems = 0;
1400         }
1401 
1402         mHistoryBaseTime = 0;
1403         mLastHistoryTime = 0;
1404 
1405         mHistoryBuffer.setDataSize(0);
1406         mHistoryBuffer.setDataPosition(0);
1407         mHistoryBuffer.setDataCapacity(MAX_HISTORY_BUFFER/2);
1408         mHistoryLastLastWritten.cmd = HistoryItem.CMD_NULL;
1409         mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
1410         mHistoryBufferLastPos = -1;
1411         mHistoryOverflow = false;
1412     }
1413 
doUnplugLocked(long batteryUptime, long batteryRealtime)1414     public void doUnplugLocked(long batteryUptime, long batteryRealtime) {
1415         NetworkStats.Entry entry = null;
1416 
1417         // Track UID data usage
1418         final NetworkStats uidStats = getNetworkStatsDetailGroupedByUid();
1419         final int size = uidStats.size();
1420         for (int i = 0; i < size; i++) {
1421             entry = uidStats.getValues(i, entry);
1422 
1423             final Uid u = mUidStats.get(entry.uid);
1424             if (u == null) continue;
1425 
1426             u.mStartedTcpBytesReceived = entry.rxBytes;
1427             u.mStartedTcpBytesSent = entry.txBytes;
1428             u.mTcpBytesReceivedAtLastUnplug = u.mCurrentTcpBytesReceived;
1429             u.mTcpBytesSentAtLastUnplug = u.mCurrentTcpBytesSent;
1430         }
1431 
1432         for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
1433             mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime);
1434         }
1435 
1436         // Track both mobile and total overall data
1437         final NetworkStats ifaceStats = getNetworkStatsSummary();
1438         entry = ifaceStats.getTotal(entry, mMobileIfaces);
1439         doDataUnplug(mMobileDataRx, entry.rxBytes);
1440         doDataUnplug(mMobileDataTx, entry.txBytes);
1441         entry = ifaceStats.getTotal(entry);
1442         doDataUnplug(mTotalDataRx, entry.rxBytes);
1443         doDataUnplug(mTotalDataTx, entry.txBytes);
1444 
1445         // Track radio awake time
1446         mRadioDataStart = getCurrentRadioDataUptime();
1447         mRadioDataUptime = 0;
1448 
1449         // Track bt headset ping count
1450         mBluetoothPingStart = getCurrentBluetoothPingCount();
1451         mBluetoothPingCount = 0;
1452     }
1453 
doPlugLocked(long batteryUptime, long batteryRealtime)1454     public void doPlugLocked(long batteryUptime, long batteryRealtime) {
1455         NetworkStats.Entry entry = null;
1456 
1457         for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
1458             Uid u = mUidStats.valueAt(iu);
1459             if (u.mStartedTcpBytesReceived >= 0) {
1460                 u.mCurrentTcpBytesReceived = u.computeCurrentTcpBytesReceived();
1461                 u.mStartedTcpBytesReceived = -1;
1462             }
1463             if (u.mStartedTcpBytesSent >= 0) {
1464                 u.mCurrentTcpBytesSent = u.computeCurrentTcpBytesSent();
1465                 u.mStartedTcpBytesSent = -1;
1466             }
1467         }
1468         for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
1469             mUnpluggables.get(i).plug(batteryUptime, batteryRealtime);
1470         }
1471 
1472         // Track both mobile and total overall data
1473         final NetworkStats ifaceStats = getNetworkStatsSummary();
1474         entry = ifaceStats.getTotal(entry, mMobileIfaces);
1475         doDataPlug(mMobileDataRx, entry.rxBytes);
1476         doDataPlug(mMobileDataTx, entry.txBytes);
1477         entry = ifaceStats.getTotal(entry);
1478         doDataPlug(mTotalDataRx, entry.rxBytes);
1479         doDataPlug(mTotalDataTx, entry.txBytes);
1480 
1481         // Track radio awake time
1482         mRadioDataUptime = getRadioDataUptime();
1483         mRadioDataStart = -1;
1484 
1485         // Track bt headset ping count
1486         mBluetoothPingCount = getBluetoothPingCount();
1487         mBluetoothPingStart = -1;
1488     }
1489 
1490     int mWakeLockNesting;
1491 
noteStartWakeLocked(int uid, int pid, String name, int type)1492     public void noteStartWakeLocked(int uid, int pid, String name, int type) {
1493         if (type == WAKE_TYPE_PARTIAL) {
1494             // Only care about partial wake locks, since full wake locks
1495             // will be canceled when the user puts the screen to sleep.
1496             if (mWakeLockNesting == 0) {
1497                 mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
1498                 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
1499                         + Integer.toHexString(mHistoryCur.states));
1500                 addHistoryRecordLocked(SystemClock.elapsedRealtime());
1501             }
1502             mWakeLockNesting++;
1503         }
1504         if (uid >= 0) {
1505             if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
1506                 Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
1507                 mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
1508             }
1509             getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type);
1510         }
1511     }
1512 
noteStopWakeLocked(int uid, int pid, String name, int type)1513     public void noteStopWakeLocked(int uid, int pid, String name, int type) {
1514         if (type == WAKE_TYPE_PARTIAL) {
1515             mWakeLockNesting--;
1516             if (mWakeLockNesting == 0) {
1517                 mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
1518                 if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
1519                         + Integer.toHexString(mHistoryCur.states));
1520                 addHistoryRecordLocked(SystemClock.elapsedRealtime());
1521             }
1522         }
1523         if (uid >= 0) {
1524             if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
1525                 Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
1526                 mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
1527             }
1528             getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type);
1529         }
1530     }
1531 
noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, int type)1532     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, int type) {
1533         int N = ws.size();
1534         for (int i=0; i<N; i++) {
1535             noteStartWakeLocked(ws.get(i), pid, name, type);
1536         }
1537     }
1538 
noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, int type)1539     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, int type) {
1540         int N = ws.size();
1541         for (int i=0; i<N; i++) {
1542             noteStopWakeLocked(ws.get(i), pid, name, type);
1543         }
1544     }
1545 
startAddingCpuLocked()1546     public int startAddingCpuLocked() {
1547         mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
1548 
1549         if (mScreenOn) {
1550             return 0;
1551         }
1552 
1553         final int N = mPartialTimers.size();
1554         if (N == 0) {
1555             mLastPartialTimers.clear();
1556             return 0;
1557         }
1558 
1559         // How many timers should consume CPU?  Only want to include ones
1560         // that have already been in the list.
1561         for (int i=0; i<N; i++) {
1562             StopwatchTimer st = mPartialTimers.get(i);
1563             if (st.mInList) {
1564                 Uid uid = st.mUid;
1565                 // We don't include the system UID, because it so often
1566                 // holds wake locks at one request or another of an app.
1567                 if (uid != null && uid.mUid != Process.SYSTEM_UID) {
1568                     return 50;
1569                 }
1570             }
1571         }
1572 
1573         return 0;
1574     }
1575 
finishAddingCpuLocked(int perc, int utime, int stime, long[] cpuSpeedTimes)1576     public void finishAddingCpuLocked(int perc, int utime, int stime, long[] cpuSpeedTimes) {
1577         final int N = mPartialTimers.size();
1578         if (perc != 0) {
1579             int num = 0;
1580             for (int i=0; i<N; i++) {
1581                 StopwatchTimer st = mPartialTimers.get(i);
1582                 if (st.mInList) {
1583                     Uid uid = st.mUid;
1584                     // We don't include the system UID, because it so often
1585                     // holds wake locks at one request or another of an app.
1586                     if (uid != null && uid.mUid != Process.SYSTEM_UID) {
1587                         num++;
1588                     }
1589                 }
1590             }
1591             if (num != 0) {
1592                 for (int i=0; i<N; i++) {
1593                     StopwatchTimer st = mPartialTimers.get(i);
1594                     if (st.mInList) {
1595                         Uid uid = st.mUid;
1596                         if (uid != null && uid.mUid != Process.SYSTEM_UID) {
1597                             int myUTime = utime/num;
1598                             int mySTime = stime/num;
1599                             utime -= myUTime;
1600                             stime -= mySTime;
1601                             num--;
1602                             Uid.Proc proc = uid.getProcessStatsLocked("*wakelock*");
1603                             proc.addCpuTimeLocked(myUTime, mySTime);
1604                             proc.addSpeedStepTimes(cpuSpeedTimes);
1605                         }
1606                     }
1607                 }
1608             }
1609 
1610             // Just in case, collect any lost CPU time.
1611             if (utime != 0 || stime != 0) {
1612                 Uid uid = getUidStatsLocked(Process.SYSTEM_UID);
1613                 if (uid != null) {
1614                     Uid.Proc proc = uid.getProcessStatsLocked("*lost*");
1615                     proc.addCpuTimeLocked(utime, stime);
1616                     proc.addSpeedStepTimes(cpuSpeedTimes);
1617                 }
1618             }
1619         }
1620 
1621         final int NL = mLastPartialTimers.size();
1622         boolean diff = N != NL;
1623         for (int i=0; i<NL && !diff; i++) {
1624             diff |= mPartialTimers.get(i) != mLastPartialTimers.get(i);
1625         }
1626         if (!diff) {
1627             for (int i=0; i<NL; i++) {
1628                 mPartialTimers.get(i).mInList = true;
1629             }
1630             return;
1631         }
1632 
1633         for (int i=0; i<NL; i++) {
1634             mLastPartialTimers.get(i).mInList = false;
1635         }
1636         mLastPartialTimers.clear();
1637         for (int i=0; i<N; i++) {
1638             StopwatchTimer st = mPartialTimers.get(i);
1639             st.mInList = true;
1640             mLastPartialTimers.add(st);
1641         }
1642     }
1643 
noteProcessDiedLocked(int uid, int pid)1644     public void noteProcessDiedLocked(int uid, int pid) {
1645         Uid u = mUidStats.get(uid);
1646         if (u != null) {
1647             u.mPids.remove(pid);
1648         }
1649     }
1650 
getProcessWakeTime(int uid, int pid, long realtime)1651     public long getProcessWakeTime(int uid, int pid, long realtime) {
1652         Uid u = mUidStats.get(uid);
1653         if (u != null) {
1654             Uid.Pid p = u.mPids.get(pid);
1655             if (p != null) {
1656                 return p.mWakeSum + (p.mWakeStart != 0 ? (realtime - p.mWakeStart) : 0);
1657             }
1658         }
1659         return 0;
1660     }
1661 
reportExcessiveWakeLocked(int uid, String proc, long overTime, long usedTime)1662     public void reportExcessiveWakeLocked(int uid, String proc, long overTime, long usedTime) {
1663         Uid u = mUidStats.get(uid);
1664         if (u != null) {
1665             u.reportExcessiveWakeLocked(proc, overTime, usedTime);
1666         }
1667     }
1668 
reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime)1669     public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
1670         Uid u = mUidStats.get(uid);
1671         if (u != null) {
1672             u.reportExcessiveCpuLocked(proc, overTime, usedTime);
1673         }
1674     }
1675 
1676     int mSensorNesting;
1677 
noteStartSensorLocked(int uid, int sensor)1678     public void noteStartSensorLocked(int uid, int sensor) {
1679         if (mSensorNesting == 0) {
1680             mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
1681             if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
1682                     + Integer.toHexString(mHistoryCur.states));
1683             addHistoryRecordLocked(SystemClock.elapsedRealtime());
1684         }
1685         mSensorNesting++;
1686         getUidStatsLocked(uid).noteStartSensor(sensor);
1687     }
1688 
noteStopSensorLocked(int uid, int sensor)1689     public void noteStopSensorLocked(int uid, int sensor) {
1690         mSensorNesting--;
1691         if (mSensorNesting == 0) {
1692             mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
1693             if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
1694                     + Integer.toHexString(mHistoryCur.states));
1695             addHistoryRecordLocked(SystemClock.elapsedRealtime());
1696         }
1697         getUidStatsLocked(uid).noteStopSensor(sensor);
1698     }
1699 
1700     int mGpsNesting;
1701 
noteStartGpsLocked(int uid)1702     public void noteStartGpsLocked(int uid) {
1703         if (mGpsNesting == 0) {
1704             mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
1705             if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
1706                     + Integer.toHexString(mHistoryCur.states));
1707             addHistoryRecordLocked(SystemClock.elapsedRealtime());
1708         }
1709         mGpsNesting++;
1710         getUidStatsLocked(uid).noteStartGps();
1711     }
1712 
noteStopGpsLocked(int uid)1713     public void noteStopGpsLocked(int uid) {
1714         mGpsNesting--;
1715         if (mGpsNesting == 0) {
1716             mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
1717             if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
1718                     + Integer.toHexString(mHistoryCur.states));
1719             addHistoryRecordLocked(SystemClock.elapsedRealtime());
1720         }
1721         getUidStatsLocked(uid).noteStopGps();
1722     }
1723 
noteScreenOnLocked()1724     public void noteScreenOnLocked() {
1725         if (!mScreenOn) {
1726             mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
1727             if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
1728                     + Integer.toHexString(mHistoryCur.states));
1729             addHistoryRecordLocked(SystemClock.elapsedRealtime());
1730             mScreenOn = true;
1731             mScreenOnTimer.startRunningLocked(this);
1732             if (mScreenBrightnessBin >= 0) {
1733                 mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(this);
1734             }
1735 
1736             // Fake a wake lock, so we consider the device waked as long
1737             // as the screen is on.
1738             noteStartWakeLocked(-1, -1, "dummy", WAKE_TYPE_PARTIAL);
1739 
1740             // Update discharge amounts.
1741             if (mOnBatteryInternal) {
1742                 updateDischargeScreenLevelsLocked(false, true);
1743             }
1744         }
1745     }
1746 
noteScreenOffLocked()1747     public void noteScreenOffLocked() {
1748         if (mScreenOn) {
1749             mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
1750             if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
1751                     + Integer.toHexString(mHistoryCur.states));
1752             addHistoryRecordLocked(SystemClock.elapsedRealtime());
1753             mScreenOn = false;
1754             mScreenOnTimer.stopRunningLocked(this);
1755             if (mScreenBrightnessBin >= 0) {
1756                 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this);
1757             }
1758 
1759             noteStopWakeLocked(-1, -1, "dummy", WAKE_TYPE_PARTIAL);
1760 
1761             // Update discharge amounts.
1762             if (mOnBatteryInternal) {
1763                 updateDischargeScreenLevelsLocked(true, false);
1764             }
1765         }
1766     }
1767 
noteScreenBrightnessLocked(int brightness)1768     public void noteScreenBrightnessLocked(int brightness) {
1769         // Bin the brightness.
1770         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
1771         if (bin < 0) bin = 0;
1772         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
1773         if (mScreenBrightnessBin != bin) {
1774             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
1775                     | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
1776             if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
1777                     + Integer.toHexString(mHistoryCur.states));
1778             addHistoryRecordLocked(SystemClock.elapsedRealtime());
1779             if (mScreenOn) {
1780                 if (mScreenBrightnessBin >= 0) {
1781                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this);
1782                 }
1783                 mScreenBrightnessTimer[bin].startRunningLocked(this);
1784             }
1785             mScreenBrightnessBin = bin;
1786         }
1787     }
1788 
noteInputEventAtomic()1789     public void noteInputEventAtomic() {
1790         mInputEventCounter.stepAtomic();
1791     }
1792 
noteUserActivityLocked(int uid, int event)1793     public void noteUserActivityLocked(int uid, int event) {
1794         getUidStatsLocked(uid).noteUserActivityLocked(event);
1795     }
1796 
notePhoneOnLocked()1797     public void notePhoneOnLocked() {
1798         if (!mPhoneOn) {
1799             mHistoryCur.states |= HistoryItem.STATE_PHONE_IN_CALL_FLAG;
1800             if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
1801                     + Integer.toHexString(mHistoryCur.states));
1802             addHistoryRecordLocked(SystemClock.elapsedRealtime());
1803             mPhoneOn = true;
1804             mPhoneOnTimer.startRunningLocked(this);
1805         }
1806     }
1807 
notePhoneOffLocked()1808     public void notePhoneOffLocked() {
1809         if (mPhoneOn) {
1810             mHistoryCur.states &= ~HistoryItem.STATE_PHONE_IN_CALL_FLAG;
1811             if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
1812                     + Integer.toHexString(mHistoryCur.states));
1813             addHistoryRecordLocked(SystemClock.elapsedRealtime());
1814             mPhoneOn = false;
1815             mPhoneOnTimer.stopRunningLocked(this);
1816         }
1817     }
1818 
stopAllSignalStrengthTimersLocked(int except)1819     void stopAllSignalStrengthTimersLocked(int except) {
1820         for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1821             if (i == except) {
1822                 continue;
1823             }
1824             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
1825                 mPhoneSignalStrengthsTimer[i].stopRunningLocked(this);
1826             }
1827         }
1828     }
1829 
fixPhoneServiceState(int state, int signalBin)1830     private int fixPhoneServiceState(int state, int signalBin) {
1831         if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
1832             // In this case we will always be STATE_OUT_OF_SERVICE, so need
1833             // to infer that we are scanning from other data.
1834             if (state == ServiceState.STATE_OUT_OF_SERVICE
1835                     && signalBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
1836                 state = ServiceState.STATE_IN_SERVICE;
1837             }
1838         }
1839 
1840         return state;
1841     }
1842 
updateAllPhoneStateLocked(int state, int simState, int bin)1843     private void updateAllPhoneStateLocked(int state, int simState, int bin) {
1844         boolean scanning = false;
1845         boolean newHistory = false;
1846 
1847         mPhoneServiceStateRaw = state;
1848         mPhoneSimStateRaw = simState;
1849         mPhoneSignalStrengthBinRaw = bin;
1850 
1851         if (simState == TelephonyManager.SIM_STATE_ABSENT) {
1852             // In this case we will always be STATE_OUT_OF_SERVICE, so need
1853             // to infer that we are scanning from other data.
1854             if (state == ServiceState.STATE_OUT_OF_SERVICE
1855                     && bin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
1856                 state = ServiceState.STATE_IN_SERVICE;
1857             }
1858         }
1859 
1860         // If the phone is powered off, stop all timers.
1861         if (state == ServiceState.STATE_POWER_OFF) {
1862             bin = -1;
1863 
1864         // If we are in service, make sure the correct signal string timer is running.
1865         } else if (state == ServiceState.STATE_IN_SERVICE) {
1866             // Bin will be changed below.
1867 
1868         // If we're out of service, we are in the lowest signal strength
1869         // bin and have the scanning bit set.
1870         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
1871             scanning = true;
1872             bin = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
1873             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
1874                 mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
1875                 newHistory = true;
1876                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
1877                         + Integer.toHexString(mHistoryCur.states));
1878                 mPhoneSignalScanningTimer.startRunningLocked(this);
1879             }
1880         }
1881 
1882         if (!scanning) {
1883             // If we are no longer scanning, then stop the scanning timer.
1884             if (mPhoneSignalScanningTimer.isRunningLocked()) {
1885                 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
1886                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
1887                         + Integer.toHexString(mHistoryCur.states));
1888                 newHistory = true;
1889                 mPhoneSignalScanningTimer.stopRunningLocked(this);
1890             }
1891         }
1892 
1893         if (mPhoneServiceState != state) {
1894             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
1895                     | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
1896             if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
1897                     + Integer.toHexString(mHistoryCur.states));
1898             newHistory = true;
1899             mPhoneServiceState = state;
1900         }
1901 
1902         if (mPhoneSignalStrengthBin != bin) {
1903             if (mPhoneSignalStrengthBin >= 0) {
1904                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(this);
1905             }
1906             if (bin >= 0) {
1907                 if (!mPhoneSignalStrengthsTimer[bin].isRunningLocked()) {
1908                     mPhoneSignalStrengthsTimer[bin].startRunningLocked(this);
1909                 }
1910                 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_SIGNAL_STRENGTH_MASK)
1911                         | (bin << HistoryItem.STATE_SIGNAL_STRENGTH_SHIFT);
1912                 if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + bin + " to: "
1913                         + Integer.toHexString(mHistoryCur.states));
1914                 newHistory = true;
1915             } else {
1916                 stopAllSignalStrengthTimersLocked(-1);
1917             }
1918             mPhoneSignalStrengthBin = bin;
1919         }
1920 
1921         if (newHistory) {
1922             addHistoryRecordLocked(SystemClock.elapsedRealtime());
1923         }
1924     }
1925 
1926     /**
1927      * Telephony stack updates the phone state.
1928      * @param state phone state from ServiceState.getState()
1929      */
notePhoneStateLocked(int state, int simState)1930     public void notePhoneStateLocked(int state, int simState) {
1931         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
1932     }
1933 
notePhoneSignalStrengthLocked(SignalStrength signalStrength)1934     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
1935         // Bin the strength.
1936         int bin = signalStrength.getLevel();
1937         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
1938     }
1939 
notePhoneDataConnectionStateLocked(int dataType, boolean hasData)1940     public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
1941         int bin = DATA_CONNECTION_NONE;
1942         if (hasData) {
1943             switch (dataType) {
1944                 case TelephonyManager.NETWORK_TYPE_EDGE:
1945                     bin = DATA_CONNECTION_EDGE;
1946                     break;
1947                 case TelephonyManager.NETWORK_TYPE_GPRS:
1948                     bin = DATA_CONNECTION_GPRS;
1949                     break;
1950                 case TelephonyManager.NETWORK_TYPE_UMTS:
1951                     bin = DATA_CONNECTION_UMTS;
1952                     break;
1953                 case TelephonyManager.NETWORK_TYPE_CDMA:
1954                     bin = DATA_CONNECTION_CDMA;
1955                     break;
1956                 case TelephonyManager.NETWORK_TYPE_EVDO_0:
1957                     bin = DATA_CONNECTION_EVDO_0;
1958                     break;
1959                 case TelephonyManager.NETWORK_TYPE_EVDO_A:
1960                     bin = DATA_CONNECTION_EVDO_A;
1961                     break;
1962                 case TelephonyManager.NETWORK_TYPE_1xRTT:
1963                     bin = DATA_CONNECTION_1xRTT;
1964                     break;
1965                 case TelephonyManager.NETWORK_TYPE_HSDPA:
1966                     bin = DATA_CONNECTION_HSDPA;
1967                     break;
1968                 case TelephonyManager.NETWORK_TYPE_HSUPA:
1969                     bin = DATA_CONNECTION_HSUPA;
1970                     break;
1971                 case TelephonyManager.NETWORK_TYPE_HSPA:
1972                     bin = DATA_CONNECTION_HSPA;
1973                     break;
1974                 case TelephonyManager.NETWORK_TYPE_IDEN:
1975                     bin = DATA_CONNECTION_IDEN;
1976                     break;
1977                 case TelephonyManager.NETWORK_TYPE_EVDO_B:
1978                     bin = DATA_CONNECTION_EVDO_B;
1979                     break;
1980                 case TelephonyManager.NETWORK_TYPE_LTE:
1981                     bin = DATA_CONNECTION_LTE;
1982                     break;
1983                 case TelephonyManager.NETWORK_TYPE_EHRPD:
1984                     bin = DATA_CONNECTION_EHRPD;
1985                     break;
1986                 default:
1987                     bin = DATA_CONNECTION_OTHER;
1988                     break;
1989             }
1990         }
1991         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
1992         if (mPhoneDataConnectionType != bin) {
1993             mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
1994                     | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
1995             if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
1996                     + Integer.toHexString(mHistoryCur.states));
1997             addHistoryRecordLocked(SystemClock.elapsedRealtime());
1998             if (mPhoneDataConnectionType >= 0) {
1999                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this);
2000             }
2001             mPhoneDataConnectionType = bin;
2002             mPhoneDataConnectionsTimer[bin].startRunningLocked(this);
2003         }
2004     }
2005 
noteWifiOnLocked()2006     public void noteWifiOnLocked() {
2007         if (!mWifiOn) {
2008             mHistoryCur.states |= HistoryItem.STATE_WIFI_ON_FLAG;
2009             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
2010                     + Integer.toHexString(mHistoryCur.states));
2011             addHistoryRecordLocked(SystemClock.elapsedRealtime());
2012             mWifiOn = true;
2013             mWifiOnTimer.startRunningLocked(this);
2014         }
2015     }
2016 
noteWifiOffLocked()2017     public void noteWifiOffLocked() {
2018         if (mWifiOn) {
2019             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_ON_FLAG;
2020             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
2021                     + Integer.toHexString(mHistoryCur.states));
2022             addHistoryRecordLocked(SystemClock.elapsedRealtime());
2023             mWifiOn = false;
2024             mWifiOnTimer.stopRunningLocked(this);
2025         }
2026         if (mWifiOnUid >= 0) {
2027             getUidStatsLocked(mWifiOnUid).noteWifiStoppedLocked();
2028             mWifiOnUid = -1;
2029         }
2030     }
2031 
noteAudioOnLocked(int uid)2032     public void noteAudioOnLocked(int uid) {
2033         if (!mAudioOn) {
2034             mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
2035             if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
2036                     + Integer.toHexString(mHistoryCur.states));
2037             addHistoryRecordLocked(SystemClock.elapsedRealtime());
2038             mAudioOn = true;
2039             mAudioOnTimer.startRunningLocked(this);
2040         }
2041         getUidStatsLocked(uid).noteAudioTurnedOnLocked();
2042     }
2043 
noteAudioOffLocked(int uid)2044     public void noteAudioOffLocked(int uid) {
2045         if (mAudioOn) {
2046             mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
2047             if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
2048                     + Integer.toHexString(mHistoryCur.states));
2049             addHistoryRecordLocked(SystemClock.elapsedRealtime());
2050             mAudioOn = false;
2051             mAudioOnTimer.stopRunningLocked(this);
2052         }
2053         getUidStatsLocked(uid).noteAudioTurnedOffLocked();
2054     }
2055 
noteVideoOnLocked(int uid)2056     public void noteVideoOnLocked(int uid) {
2057         if (!mVideoOn) {
2058             mHistoryCur.states |= HistoryItem.STATE_VIDEO_ON_FLAG;
2059             if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
2060                     + Integer.toHexString(mHistoryCur.states));
2061             addHistoryRecordLocked(SystemClock.elapsedRealtime());
2062             mVideoOn = true;
2063             mVideoOnTimer.startRunningLocked(this);
2064         }
2065         getUidStatsLocked(uid).noteVideoTurnedOnLocked();
2066     }
2067 
noteVideoOffLocked(int uid)2068     public void noteVideoOffLocked(int uid) {
2069         if (mVideoOn) {
2070             mHistoryCur.states &= ~HistoryItem.STATE_VIDEO_ON_FLAG;
2071             if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
2072                     + Integer.toHexString(mHistoryCur.states));
2073             addHistoryRecordLocked(SystemClock.elapsedRealtime());
2074             mVideoOn = false;
2075             mVideoOnTimer.stopRunningLocked(this);
2076         }
2077         getUidStatsLocked(uid).noteVideoTurnedOffLocked();
2078     }
2079 
noteWifiRunningLocked(WorkSource ws)2080     public void noteWifiRunningLocked(WorkSource ws) {
2081         if (!mGlobalWifiRunning) {
2082             mHistoryCur.states |= HistoryItem.STATE_WIFI_RUNNING_FLAG;
2083             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
2084                     + Integer.toHexString(mHistoryCur.states));
2085             addHistoryRecordLocked(SystemClock.elapsedRealtime());
2086             mGlobalWifiRunning = true;
2087             mGlobalWifiRunningTimer.startRunningLocked(this);
2088             int N = ws.size();
2089             for (int i=0; i<N; i++) {
2090                 getUidStatsLocked(ws.get(i)).noteWifiRunningLocked();
2091             }
2092         } else {
2093             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
2094         }
2095     }
2096 
noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs)2097     public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
2098         if (mGlobalWifiRunning) {
2099             int N = oldWs.size();
2100             for (int i=0; i<N; i++) {
2101                 getUidStatsLocked(oldWs.get(i)).noteWifiStoppedLocked();
2102             }
2103             N = newWs.size();
2104             for (int i=0; i<N; i++) {
2105                 getUidStatsLocked(newWs.get(i)).noteWifiRunningLocked();
2106             }
2107         } else {
2108             Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
2109         }
2110     }
2111 
noteWifiStoppedLocked(WorkSource ws)2112     public void noteWifiStoppedLocked(WorkSource ws) {
2113         if (mGlobalWifiRunning) {
2114             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RUNNING_FLAG;
2115             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
2116                     + Integer.toHexString(mHistoryCur.states));
2117             addHistoryRecordLocked(SystemClock.elapsedRealtime());
2118             mGlobalWifiRunning = false;
2119             mGlobalWifiRunningTimer.stopRunningLocked(this);
2120             int N = ws.size();
2121             for (int i=0; i<N; i++) {
2122                 getUidStatsLocked(ws.get(i)).noteWifiStoppedLocked();
2123             }
2124         } else {
2125             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
2126         }
2127     }
2128 
noteBluetoothOnLocked()2129     public void noteBluetoothOnLocked() {
2130         if (!mBluetoothOn) {
2131             mHistoryCur.states |= HistoryItem.STATE_BLUETOOTH_ON_FLAG;
2132             if (DEBUG_HISTORY) Slog.v(TAG, "Bluetooth on to: "
2133                     + Integer.toHexString(mHistoryCur.states));
2134             addHistoryRecordLocked(SystemClock.elapsedRealtime());
2135             mBluetoothOn = true;
2136             mBluetoothOnTimer.startRunningLocked(this);
2137         }
2138     }
2139 
noteBluetoothOffLocked()2140     public void noteBluetoothOffLocked() {
2141         if (mBluetoothOn) {
2142             mHistoryCur.states &= ~HistoryItem.STATE_BLUETOOTH_ON_FLAG;
2143             if (DEBUG_HISTORY) Slog.v(TAG, "Bluetooth off to: "
2144                     + Integer.toHexString(mHistoryCur.states));
2145             addHistoryRecordLocked(SystemClock.elapsedRealtime());
2146             mBluetoothOn = false;
2147             mBluetoothOnTimer.stopRunningLocked(this);
2148         }
2149     }
2150 
2151     int mWifiFullLockNesting = 0;
2152 
noteFullWifiLockAcquiredLocked(int uid)2153     public void noteFullWifiLockAcquiredLocked(int uid) {
2154         if (mWifiFullLockNesting == 0) {
2155             mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
2156             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
2157                     + Integer.toHexString(mHistoryCur.states));
2158             addHistoryRecordLocked(SystemClock.elapsedRealtime());
2159         }
2160         mWifiFullLockNesting++;
2161         getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked();
2162     }
2163 
noteFullWifiLockReleasedLocked(int uid)2164     public void noteFullWifiLockReleasedLocked(int uid) {
2165         mWifiFullLockNesting--;
2166         if (mWifiFullLockNesting == 0) {
2167             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
2168             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
2169                     + Integer.toHexString(mHistoryCur.states));
2170             addHistoryRecordLocked(SystemClock.elapsedRealtime());
2171         }
2172         getUidStatsLocked(uid).noteFullWifiLockReleasedLocked();
2173     }
2174 
2175     int mWifiScanLockNesting = 0;
2176 
noteScanWifiLockAcquiredLocked(int uid)2177     public void noteScanWifiLockAcquiredLocked(int uid) {
2178         if (mWifiScanLockNesting == 0) {
2179             mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG;
2180             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan lock on to: "
2181                     + Integer.toHexString(mHistoryCur.states));
2182             addHistoryRecordLocked(SystemClock.elapsedRealtime());
2183         }
2184         mWifiScanLockNesting++;
2185         getUidStatsLocked(uid).noteScanWifiLockAcquiredLocked();
2186     }
2187 
noteScanWifiLockReleasedLocked(int uid)2188     public void noteScanWifiLockReleasedLocked(int uid) {
2189         mWifiScanLockNesting--;
2190         if (mWifiScanLockNesting == 0) {
2191             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG;
2192             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan lock off to: "
2193                     + Integer.toHexString(mHistoryCur.states));
2194             addHistoryRecordLocked(SystemClock.elapsedRealtime());
2195         }
2196         getUidStatsLocked(uid).noteScanWifiLockReleasedLocked();
2197     }
2198 
2199     int mWifiMulticastNesting = 0;
2200 
noteWifiMulticastEnabledLocked(int uid)2201     public void noteWifiMulticastEnabledLocked(int uid) {
2202         if (mWifiMulticastNesting == 0) {
2203             mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
2204             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
2205                     + Integer.toHexString(mHistoryCur.states));
2206             addHistoryRecordLocked(SystemClock.elapsedRealtime());
2207         }
2208         mWifiMulticastNesting++;
2209         getUidStatsLocked(uid).noteWifiMulticastEnabledLocked();
2210     }
2211 
noteWifiMulticastDisabledLocked(int uid)2212     public void noteWifiMulticastDisabledLocked(int uid) {
2213         mWifiMulticastNesting--;
2214         if (mWifiMulticastNesting == 0) {
2215             mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
2216             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
2217                     + Integer.toHexString(mHistoryCur.states));
2218             addHistoryRecordLocked(SystemClock.elapsedRealtime());
2219         }
2220         getUidStatsLocked(uid).noteWifiMulticastDisabledLocked();
2221     }
2222 
noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws)2223     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
2224         int N = ws.size();
2225         for (int i=0; i<N; i++) {
2226             noteFullWifiLockAcquiredLocked(ws.get(i));
2227         }
2228     }
2229 
noteFullWifiLockReleasedFromSourceLocked(WorkSource ws)2230     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
2231         int N = ws.size();
2232         for (int i=0; i<N; i++) {
2233             noteFullWifiLockReleasedLocked(ws.get(i));
2234         }
2235     }
2236 
noteScanWifiLockAcquiredFromSourceLocked(WorkSource ws)2237     public void noteScanWifiLockAcquiredFromSourceLocked(WorkSource ws) {
2238         int N = ws.size();
2239         for (int i=0; i<N; i++) {
2240             noteScanWifiLockAcquiredLocked(ws.get(i));
2241         }
2242     }
2243 
noteScanWifiLockReleasedFromSourceLocked(WorkSource ws)2244     public void noteScanWifiLockReleasedFromSourceLocked(WorkSource ws) {
2245         int N = ws.size();
2246         for (int i=0; i<N; i++) {
2247             noteScanWifiLockReleasedLocked(ws.get(i));
2248         }
2249     }
2250 
noteWifiMulticastEnabledFromSourceLocked(WorkSource ws)2251     public void noteWifiMulticastEnabledFromSourceLocked(WorkSource ws) {
2252         int N = ws.size();
2253         for (int i=0; i<N; i++) {
2254             noteWifiMulticastEnabledLocked(ws.get(i));
2255         }
2256     }
2257 
noteWifiMulticastDisabledFromSourceLocked(WorkSource ws)2258     public void noteWifiMulticastDisabledFromSourceLocked(WorkSource ws) {
2259         int N = ws.size();
2260         for (int i=0; i<N; i++) {
2261             noteWifiMulticastDisabledLocked(ws.get(i));
2262         }
2263     }
2264 
noteNetworkInterfaceTypeLocked(String iface, int networkType)2265     public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
2266         if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
2267             mMobileIfaces.add(iface);
2268         } else {
2269             mMobileIfaces.remove(iface);
2270         }
2271     }
2272 
getScreenOnTime(long batteryRealtime, int which)2273     @Override public long getScreenOnTime(long batteryRealtime, int which) {
2274         return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which);
2275     }
2276 
getScreenBrightnessTime(int brightnessBin, long batteryRealtime, int which)2277     @Override public long getScreenBrightnessTime(int brightnessBin,
2278             long batteryRealtime, int which) {
2279         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
2280                 batteryRealtime, which);
2281     }
2282 
getInputEventCount(int which)2283     @Override public int getInputEventCount(int which) {
2284         return mInputEventCounter.getCountLocked(which);
2285     }
2286 
getPhoneOnTime(long batteryRealtime, int which)2287     @Override public long getPhoneOnTime(long batteryRealtime, int which) {
2288         return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which);
2289     }
2290 
getPhoneSignalStrengthTime(int strengthBin, long batteryRealtime, int which)2291     @Override public long getPhoneSignalStrengthTime(int strengthBin,
2292             long batteryRealtime, int which) {
2293         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
2294                 batteryRealtime, which);
2295     }
2296 
getPhoneSignalScanningTime( long batteryRealtime, int which)2297     @Override public long getPhoneSignalScanningTime(
2298             long batteryRealtime, int which) {
2299         return mPhoneSignalScanningTimer.getTotalTimeLocked(
2300                 batteryRealtime, which);
2301     }
2302 
getPhoneSignalStrengthCount(int dataType, int which)2303     @Override public int getPhoneSignalStrengthCount(int dataType, int which) {
2304         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
2305     }
2306 
getPhoneDataConnectionTime(int dataType, long batteryRealtime, int which)2307     @Override public long getPhoneDataConnectionTime(int dataType,
2308             long batteryRealtime, int which) {
2309         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
2310                 batteryRealtime, which);
2311     }
2312 
getPhoneDataConnectionCount(int dataType, int which)2313     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
2314         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
2315     }
2316 
getWifiOnTime(long batteryRealtime, int which)2317     @Override public long getWifiOnTime(long batteryRealtime, int which) {
2318         return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which);
2319     }
2320 
getGlobalWifiRunningTime(long batteryRealtime, int which)2321     @Override public long getGlobalWifiRunningTime(long batteryRealtime, int which) {
2322         return mGlobalWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which);
2323     }
2324 
getBluetoothOnTime(long batteryRealtime, int which)2325     @Override public long getBluetoothOnTime(long batteryRealtime, int which) {
2326         return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which);
2327     }
2328 
getIsOnBattery()2329     @Override public boolean getIsOnBattery() {
2330         return mOnBattery;
2331     }
2332 
getUidStats()2333     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
2334         return mUidStats;
2335     }
2336 
2337     /**
2338      * The statistics associated with a particular uid.
2339      */
2340     public final class Uid extends BatteryStats.Uid {
2341 
2342         final int mUid;
2343         long mLoadedTcpBytesReceived;
2344         long mLoadedTcpBytesSent;
2345         long mCurrentTcpBytesReceived;
2346         long mCurrentTcpBytesSent;
2347         long mTcpBytesReceivedAtLastUnplug;
2348         long mTcpBytesSentAtLastUnplug;
2349 
2350         // These are not saved/restored when parcelling, since we want
2351         // to return from the parcel with a snapshot of the state.
2352         long mStartedTcpBytesReceived = -1;
2353         long mStartedTcpBytesSent = -1;
2354 
2355         boolean mWifiRunning;
2356         StopwatchTimer mWifiRunningTimer;
2357 
2358         boolean mFullWifiLockOut;
2359         StopwatchTimer mFullWifiLockTimer;
2360 
2361         boolean mScanWifiLockOut;
2362         StopwatchTimer mScanWifiLockTimer;
2363 
2364         boolean mWifiMulticastEnabled;
2365         StopwatchTimer mWifiMulticastTimer;
2366 
2367         boolean mAudioTurnedOn;
2368         StopwatchTimer mAudioTurnedOnTimer;
2369 
2370         boolean mVideoTurnedOn;
2371         StopwatchTimer mVideoTurnedOnTimer;
2372 
2373         Counter[] mUserActivityCounters;
2374 
2375         /**
2376          * The statistics we have collected for this uid's wake locks.
2377          */
2378         final HashMap<String, Wakelock> mWakelockStats = new HashMap<String, Wakelock>();
2379 
2380         /**
2381          * The statistics we have collected for this uid's sensor activations.
2382          */
2383         final HashMap<Integer, Sensor> mSensorStats = new HashMap<Integer, Sensor>();
2384 
2385         /**
2386          * The statistics we have collected for this uid's processes.
2387          */
2388         final HashMap<String, Proc> mProcessStats = new HashMap<String, Proc>();
2389 
2390         /**
2391          * The statistics we have collected for this uid's processes.
2392          */
2393         final HashMap<String, Pkg> mPackageStats = new HashMap<String, Pkg>();
2394 
2395         /**
2396          * The transient wake stats we have collected for this uid's pids.
2397          */
2398         final SparseArray<Pid> mPids = new SparseArray<Pid>();
2399 
Uid(int uid)2400         public Uid(int uid) {
2401             mUid = uid;
2402             mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
2403                     mWifiRunningTimers, mUnpluggables);
2404             mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
2405                     mFullWifiLockTimers, mUnpluggables);
2406             mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
2407                     mScanWifiLockTimers, mUnpluggables);
2408             mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
2409                     mWifiMulticastTimers, mUnpluggables);
2410             mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
2411                     null, mUnpluggables);
2412             mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
2413                     null, mUnpluggables);
2414         }
2415 
2416         @Override
getWakelockStats()2417         public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
2418             return mWakelockStats;
2419         }
2420 
2421         @Override
getSensorStats()2422         public Map<Integer, ? extends BatteryStats.Uid.Sensor> getSensorStats() {
2423             return mSensorStats;
2424         }
2425 
2426         @Override
getProcessStats()2427         public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
2428             return mProcessStats;
2429         }
2430 
2431         @Override
getPackageStats()2432         public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
2433             return mPackageStats;
2434         }
2435 
2436         @Override
getUid()2437         public int getUid() {
2438             return mUid;
2439         }
2440 
2441         @Override
getTcpBytesReceived(int which)2442         public long getTcpBytesReceived(int which) {
2443             if (which == STATS_LAST) {
2444                 return mLoadedTcpBytesReceived;
2445             } else {
2446                 long current = computeCurrentTcpBytesReceived();
2447                 if (which == STATS_SINCE_UNPLUGGED) {
2448                     current -= mTcpBytesReceivedAtLastUnplug;
2449                 } else if (which == STATS_SINCE_CHARGED) {
2450                     current += mLoadedTcpBytesReceived;
2451                 }
2452                 return current;
2453             }
2454         }
2455 
computeCurrentTcpBytesReceived()2456         public long computeCurrentTcpBytesReceived() {
2457             final long uidRxBytes = getNetworkStatsDetailGroupedByUid().getTotal(
2458                     null, mUid).rxBytes;
2459             return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0
2460                     ? (uidRxBytes - mStartedTcpBytesReceived) : 0);
2461         }
2462 
2463         @Override
getTcpBytesSent(int which)2464         public long getTcpBytesSent(int which) {
2465             if (which == STATS_LAST) {
2466                 return mLoadedTcpBytesSent;
2467             } else {
2468                 long current = computeCurrentTcpBytesSent();
2469                 if (which == STATS_SINCE_UNPLUGGED) {
2470                     current -= mTcpBytesSentAtLastUnplug;
2471                 } else if (which == STATS_SINCE_CHARGED) {
2472                     current += mLoadedTcpBytesSent;
2473                 }
2474                 return current;
2475             }
2476         }
2477 
2478         @Override
noteWifiRunningLocked()2479         public void noteWifiRunningLocked() {
2480             if (!mWifiRunning) {
2481                 mWifiRunning = true;
2482                 if (mWifiRunningTimer == null) {
2483                     mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
2484                             mWifiRunningTimers, mUnpluggables);
2485                 }
2486                 mWifiRunningTimer.startRunningLocked(BatteryStatsImpl.this);
2487             }
2488         }
2489 
2490         @Override
noteWifiStoppedLocked()2491         public void noteWifiStoppedLocked() {
2492             if (mWifiRunning) {
2493                 mWifiRunning = false;
2494                 mWifiRunningTimer.stopRunningLocked(BatteryStatsImpl.this);
2495             }
2496         }
2497 
2498         @Override
noteFullWifiLockAcquiredLocked()2499         public void noteFullWifiLockAcquiredLocked() {
2500             if (!mFullWifiLockOut) {
2501                 mFullWifiLockOut = true;
2502                 if (mFullWifiLockTimer == null) {
2503                     mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
2504                             mFullWifiLockTimers, mUnpluggables);
2505                 }
2506                 mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
2507             }
2508         }
2509 
2510         @Override
noteFullWifiLockReleasedLocked()2511         public void noteFullWifiLockReleasedLocked() {
2512             if (mFullWifiLockOut) {
2513                 mFullWifiLockOut = false;
2514                 mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
2515             }
2516         }
2517 
2518         @Override
noteScanWifiLockAcquiredLocked()2519         public void noteScanWifiLockAcquiredLocked() {
2520             if (!mScanWifiLockOut) {
2521                 mScanWifiLockOut = true;
2522                 if (mScanWifiLockTimer == null) {
2523                     mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
2524                             mScanWifiLockTimers, mUnpluggables);
2525                 }
2526                 mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
2527             }
2528         }
2529 
2530         @Override
noteScanWifiLockReleasedLocked()2531         public void noteScanWifiLockReleasedLocked() {
2532             if (mScanWifiLockOut) {
2533                 mScanWifiLockOut = false;
2534                 mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
2535             }
2536         }
2537 
2538         @Override
noteWifiMulticastEnabledLocked()2539         public void noteWifiMulticastEnabledLocked() {
2540             if (!mWifiMulticastEnabled) {
2541                 mWifiMulticastEnabled = true;
2542                 if (mWifiMulticastTimer == null) {
2543                     mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
2544                             mWifiMulticastTimers, mUnpluggables);
2545                 }
2546                 mWifiMulticastTimer.startRunningLocked(BatteryStatsImpl.this);
2547             }
2548         }
2549 
2550         @Override
noteWifiMulticastDisabledLocked()2551         public void noteWifiMulticastDisabledLocked() {
2552             if (mWifiMulticastEnabled) {
2553                 mWifiMulticastEnabled = false;
2554                 mWifiMulticastTimer.stopRunningLocked(BatteryStatsImpl.this);
2555             }
2556         }
2557 
2558         @Override
noteAudioTurnedOnLocked()2559         public void noteAudioTurnedOnLocked() {
2560             if (!mAudioTurnedOn) {
2561                 mAudioTurnedOn = true;
2562                 if (mAudioTurnedOnTimer == null) {
2563                     mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
2564                             null, mUnpluggables);
2565                 }
2566                 mAudioTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
2567             }
2568         }
2569 
2570         @Override
noteAudioTurnedOffLocked()2571         public void noteAudioTurnedOffLocked() {
2572             if (mAudioTurnedOn) {
2573                 mAudioTurnedOn = false;
2574                 mAudioTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
2575             }
2576         }
2577 
2578         @Override
noteVideoTurnedOnLocked()2579         public void noteVideoTurnedOnLocked() {
2580             if (!mVideoTurnedOn) {
2581                 mVideoTurnedOn = true;
2582                 if (mVideoTurnedOnTimer == null) {
2583                     mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
2584                             null, mUnpluggables);
2585                 }
2586                 mVideoTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
2587             }
2588         }
2589 
2590         @Override
noteVideoTurnedOffLocked()2591         public void noteVideoTurnedOffLocked() {
2592             if (mVideoTurnedOn) {
2593                 mVideoTurnedOn = false;
2594                 mVideoTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
2595             }
2596         }
2597 
2598         @Override
getWifiRunningTime(long batteryRealtime, int which)2599         public long getWifiRunningTime(long batteryRealtime, int which) {
2600             if (mWifiRunningTimer == null) {
2601                 return 0;
2602             }
2603             return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which);
2604         }
2605 
2606         @Override
getFullWifiLockTime(long batteryRealtime, int which)2607         public long getFullWifiLockTime(long batteryRealtime, int which) {
2608             if (mFullWifiLockTimer == null) {
2609                 return 0;
2610             }
2611             return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
2612         }
2613 
2614         @Override
getScanWifiLockTime(long batteryRealtime, int which)2615         public long getScanWifiLockTime(long batteryRealtime, int which) {
2616             if (mScanWifiLockTimer == null) {
2617                 return 0;
2618             }
2619             return mScanWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
2620         }
2621 
2622         @Override
getWifiMulticastTime(long batteryRealtime, int which)2623         public long getWifiMulticastTime(long batteryRealtime, int which) {
2624             if (mWifiMulticastTimer == null) {
2625                 return 0;
2626             }
2627             return mWifiMulticastTimer.getTotalTimeLocked(batteryRealtime,
2628                                                           which);
2629         }
2630 
2631         @Override
getAudioTurnedOnTime(long batteryRealtime, int which)2632         public long getAudioTurnedOnTime(long batteryRealtime, int which) {
2633             if (mAudioTurnedOnTimer == null) {
2634                 return 0;
2635             }
2636             return mAudioTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
2637         }
2638 
2639         @Override
getVideoTurnedOnTime(long batteryRealtime, int which)2640         public long getVideoTurnedOnTime(long batteryRealtime, int which) {
2641             if (mVideoTurnedOnTimer == null) {
2642                 return 0;
2643             }
2644             return mVideoTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
2645         }
2646 
2647         @Override
noteUserActivityLocked(int type)2648         public void noteUserActivityLocked(int type) {
2649             if (mUserActivityCounters == null) {
2650                 initUserActivityLocked();
2651             }
2652             if (type < 0) type = 0;
2653             else if (type >= NUM_USER_ACTIVITY_TYPES) type = NUM_USER_ACTIVITY_TYPES-1;
2654             mUserActivityCounters[type].stepAtomic();
2655         }
2656 
2657         @Override
hasUserActivity()2658         public boolean hasUserActivity() {
2659             return mUserActivityCounters != null;
2660         }
2661 
2662         @Override
getUserActivityCount(int type, int which)2663         public int getUserActivityCount(int type, int which) {
2664             if (mUserActivityCounters == null) {
2665                 return 0;
2666             }
2667             return mUserActivityCounters[type].getCountLocked(which);
2668         }
2669 
initUserActivityLocked()2670         void initUserActivityLocked() {
2671             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
2672             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
2673                 mUserActivityCounters[i] = new Counter(mUnpluggables);
2674             }
2675         }
2676 
computeCurrentTcpBytesSent()2677         public long computeCurrentTcpBytesSent() {
2678             final long uidTxBytes = getNetworkStatsDetailGroupedByUid().getTotal(
2679                     null, mUid).txBytes;
2680             return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0
2681                     ? (uidTxBytes - mStartedTcpBytesSent) : 0);
2682         }
2683 
2684         /**
2685          * Clear all stats for this uid.  Returns true if the uid is completely
2686          * inactive so can be dropped.
2687          */
reset()2688         boolean reset() {
2689             boolean active = false;
2690 
2691             if (mWifiRunningTimer != null) {
2692                 active |= !mWifiRunningTimer.reset(BatteryStatsImpl.this, false);
2693                 active |= mWifiRunning;
2694             }
2695             if (mFullWifiLockTimer != null) {
2696                 active |= !mFullWifiLockTimer.reset(BatteryStatsImpl.this, false);
2697                 active |= mFullWifiLockOut;
2698             }
2699             if (mScanWifiLockTimer != null) {
2700                 active |= !mScanWifiLockTimer.reset(BatteryStatsImpl.this, false);
2701                 active |= mScanWifiLockOut;
2702             }
2703             if (mWifiMulticastTimer != null) {
2704                 active |= !mWifiMulticastTimer.reset(BatteryStatsImpl.this, false);
2705                 active |= mWifiMulticastEnabled;
2706             }
2707             if (mAudioTurnedOnTimer != null) {
2708                 active |= !mAudioTurnedOnTimer.reset(BatteryStatsImpl.this, false);
2709                 active |= mAudioTurnedOn;
2710             }
2711             if (mVideoTurnedOnTimer != null) {
2712                 active |= !mVideoTurnedOnTimer.reset(BatteryStatsImpl.this, false);
2713                 active |= mVideoTurnedOn;
2714             }
2715 
2716             mLoadedTcpBytesReceived = mLoadedTcpBytesSent = 0;
2717             mCurrentTcpBytesReceived = mCurrentTcpBytesSent = 0;
2718 
2719             if (mUserActivityCounters != null) {
2720                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
2721                     mUserActivityCounters[i].reset(false);
2722                 }
2723             }
2724 
2725             if (mWakelockStats.size() > 0) {
2726                 Iterator<Map.Entry<String, Wakelock>> it = mWakelockStats.entrySet().iterator();
2727                 while (it.hasNext()) {
2728                     Map.Entry<String, Wakelock> wakelockEntry = it.next();
2729                     Wakelock wl = wakelockEntry.getValue();
2730                     if (wl.reset()) {
2731                         it.remove();
2732                     } else {
2733                         active = true;
2734                     }
2735                 }
2736             }
2737             if (mSensorStats.size() > 0) {
2738                 Iterator<Map.Entry<Integer, Sensor>> it = mSensorStats.entrySet().iterator();
2739                 while (it.hasNext()) {
2740                     Map.Entry<Integer, Sensor> sensorEntry = it.next();
2741                     Sensor s = sensorEntry.getValue();
2742                     if (s.reset()) {
2743                         it.remove();
2744                     } else {
2745                         active = true;
2746                     }
2747                 }
2748             }
2749             if (mProcessStats.size() > 0) {
2750                 Iterator<Map.Entry<String, Proc>> it = mProcessStats.entrySet().iterator();
2751                 while (it.hasNext()) {
2752                     Map.Entry<String, Proc> procEntry = it.next();
2753                     procEntry.getValue().detach();
2754                 }
2755                 mProcessStats.clear();
2756             }
2757             if (mPids.size() > 0) {
2758                 for (int i=0; !active && i<mPids.size(); i++) {
2759                     Pid pid = mPids.valueAt(i);
2760                     if (pid.mWakeStart != 0) {
2761                         active = true;
2762                     }
2763                 }
2764             }
2765             if (mPackageStats.size() > 0) {
2766                 Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator();
2767                 while (it.hasNext()) {
2768                     Map.Entry<String, Pkg> pkgEntry = it.next();
2769                     Pkg p = pkgEntry.getValue();
2770                     p.detach();
2771                     if (p.mServiceStats.size() > 0) {
2772                         Iterator<Map.Entry<String, Pkg.Serv>> it2
2773                                 = p.mServiceStats.entrySet().iterator();
2774                         while (it2.hasNext()) {
2775                             Map.Entry<String, Pkg.Serv> servEntry = it2.next();
2776                             servEntry.getValue().detach();
2777                         }
2778                     }
2779                 }
2780                 mPackageStats.clear();
2781             }
2782 
2783             mPids.clear();
2784 
2785             if (!active) {
2786                 if (mWifiRunningTimer != null) {
2787                     mWifiRunningTimer.detach();
2788                 }
2789                 if (mFullWifiLockTimer != null) {
2790                     mFullWifiLockTimer.detach();
2791                 }
2792                 if (mScanWifiLockTimer != null) {
2793                     mScanWifiLockTimer.detach();
2794                 }
2795                 if (mWifiMulticastTimer != null) {
2796                     mWifiMulticastTimer.detach();
2797                 }
2798                 if (mAudioTurnedOnTimer != null) {
2799                     mAudioTurnedOnTimer.detach();
2800                 }
2801                 if (mVideoTurnedOnTimer != null) {
2802                     mVideoTurnedOnTimer.detach();
2803                 }
2804                 if (mUserActivityCounters != null) {
2805                     for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
2806                         mUserActivityCounters[i].detach();
2807                     }
2808                 }
2809             }
2810 
2811             return !active;
2812         }
2813 
writeToParcelLocked(Parcel out, long batteryRealtime)2814         void writeToParcelLocked(Parcel out, long batteryRealtime) {
2815             out.writeInt(mWakelockStats.size());
2816             for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) {
2817                 out.writeString(wakelockEntry.getKey());
2818                 Uid.Wakelock wakelock = wakelockEntry.getValue();
2819                 wakelock.writeToParcelLocked(out, batteryRealtime);
2820             }
2821 
2822             out.writeInt(mSensorStats.size());
2823             for (Map.Entry<Integer, Uid.Sensor> sensorEntry : mSensorStats.entrySet()) {
2824                 out.writeInt(sensorEntry.getKey());
2825                 Uid.Sensor sensor = sensorEntry.getValue();
2826                 sensor.writeToParcelLocked(out, batteryRealtime);
2827             }
2828 
2829             out.writeInt(mProcessStats.size());
2830             for (Map.Entry<String, Uid.Proc> procEntry : mProcessStats.entrySet()) {
2831                 out.writeString(procEntry.getKey());
2832                 Uid.Proc proc = procEntry.getValue();
2833                 proc.writeToParcelLocked(out);
2834             }
2835 
2836             out.writeInt(mPackageStats.size());
2837             for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
2838                 out.writeString(pkgEntry.getKey());
2839                 Uid.Pkg pkg = pkgEntry.getValue();
2840                 pkg.writeToParcelLocked(out);
2841             }
2842 
2843             out.writeLong(mLoadedTcpBytesReceived);
2844             out.writeLong(mLoadedTcpBytesSent);
2845             out.writeLong(computeCurrentTcpBytesReceived());
2846             out.writeLong(computeCurrentTcpBytesSent());
2847             out.writeLong(mTcpBytesReceivedAtLastUnplug);
2848             out.writeLong(mTcpBytesSentAtLastUnplug);
2849             if (mWifiRunningTimer != null) {
2850                 out.writeInt(1);
2851                 mWifiRunningTimer.writeToParcel(out, batteryRealtime);
2852             } else {
2853                 out.writeInt(0);
2854             }
2855             if (mFullWifiLockTimer != null) {
2856                 out.writeInt(1);
2857                 mFullWifiLockTimer.writeToParcel(out, batteryRealtime);
2858             } else {
2859                 out.writeInt(0);
2860             }
2861             if (mScanWifiLockTimer != null) {
2862                 out.writeInt(1);
2863                 mScanWifiLockTimer.writeToParcel(out, batteryRealtime);
2864             } else {
2865                 out.writeInt(0);
2866             }
2867             if (mWifiMulticastTimer != null) {
2868                 out.writeInt(1);
2869                 mWifiMulticastTimer.writeToParcel(out, batteryRealtime);
2870             } else {
2871                 out.writeInt(0);
2872             }
2873             if (mAudioTurnedOnTimer != null) {
2874                 out.writeInt(1);
2875                 mAudioTurnedOnTimer.writeToParcel(out, batteryRealtime);
2876             } else {
2877                 out.writeInt(0);
2878             }
2879             if (mVideoTurnedOnTimer != null) {
2880                 out.writeInt(1);
2881                 mVideoTurnedOnTimer.writeToParcel(out, batteryRealtime);
2882             } else {
2883                 out.writeInt(0);
2884             }
2885             if (mUserActivityCounters != null) {
2886                 out.writeInt(1);
2887                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
2888                     mUserActivityCounters[i].writeToParcel(out);
2889                 }
2890             } else {
2891                 out.writeInt(0);
2892             }
2893         }
2894 
readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in)2895         void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
2896             int numWakelocks = in.readInt();
2897             mWakelockStats.clear();
2898             for (int j = 0; j < numWakelocks; j++) {
2899                 String wakelockName = in.readString();
2900                 Uid.Wakelock wakelock = new Wakelock();
2901                 wakelock.readFromParcelLocked(unpluggables, in);
2902                 // We will just drop some random set of wakelocks if
2903                 // the previous run of the system was an older version
2904                 // that didn't impose a limit.
2905                 mWakelockStats.put(wakelockName, wakelock);
2906             }
2907 
2908             int numSensors = in.readInt();
2909             mSensorStats.clear();
2910             for (int k = 0; k < numSensors; k++) {
2911                 int sensorNumber = in.readInt();
2912                 Uid.Sensor sensor = new Sensor(sensorNumber);
2913                 sensor.readFromParcelLocked(mUnpluggables, in);
2914                 mSensorStats.put(sensorNumber, sensor);
2915             }
2916 
2917             int numProcs = in.readInt();
2918             mProcessStats.clear();
2919             for (int k = 0; k < numProcs; k++) {
2920                 String processName = in.readString();
2921                 Uid.Proc proc = new Proc();
2922                 proc.readFromParcelLocked(in);
2923                 mProcessStats.put(processName, proc);
2924             }
2925 
2926             int numPkgs = in.readInt();
2927             mPackageStats.clear();
2928             for (int l = 0; l < numPkgs; l++) {
2929                 String packageName = in.readString();
2930                 Uid.Pkg pkg = new Pkg();
2931                 pkg.readFromParcelLocked(in);
2932                 mPackageStats.put(packageName, pkg);
2933             }
2934 
2935             mLoadedTcpBytesReceived = in.readLong();
2936             mLoadedTcpBytesSent = in.readLong();
2937             mCurrentTcpBytesReceived = in.readLong();
2938             mCurrentTcpBytesSent = in.readLong();
2939             mTcpBytesReceivedAtLastUnplug = in.readLong();
2940             mTcpBytesSentAtLastUnplug = in.readLong();
2941             mWifiRunning = false;
2942             if (in.readInt() != 0) {
2943                 mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
2944                         mWifiRunningTimers, mUnpluggables, in);
2945             } else {
2946                 mWifiRunningTimer = null;
2947             }
2948             mFullWifiLockOut = false;
2949             if (in.readInt() != 0) {
2950                 mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
2951                         mFullWifiLockTimers, mUnpluggables, in);
2952             } else {
2953                 mFullWifiLockTimer = null;
2954             }
2955             mScanWifiLockOut = false;
2956             if (in.readInt() != 0) {
2957                 mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
2958                         mScanWifiLockTimers, mUnpluggables, in);
2959             } else {
2960                 mScanWifiLockTimer = null;
2961             }
2962             mWifiMulticastEnabled = false;
2963             if (in.readInt() != 0) {
2964                 mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
2965                         mWifiMulticastTimers, mUnpluggables, in);
2966             } else {
2967                 mWifiMulticastTimer = null;
2968             }
2969             mAudioTurnedOn = false;
2970             if (in.readInt() != 0) {
2971                 mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
2972                         null, mUnpluggables, in);
2973             } else {
2974                 mAudioTurnedOnTimer = null;
2975             }
2976             mVideoTurnedOn = false;
2977             if (in.readInt() != 0) {
2978                 mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
2979                         null, mUnpluggables, in);
2980             } else {
2981                 mVideoTurnedOnTimer = null;
2982             }
2983             if (in.readInt() != 0) {
2984                 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
2985                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
2986                     mUserActivityCounters[i] = new Counter(mUnpluggables, in);
2987                 }
2988             } else {
2989                 mUserActivityCounters = null;
2990             }
2991         }
2992 
2993         /**
2994          * The statistics associated with a particular wake lock.
2995          */
2996         public final class Wakelock extends BatteryStats.Uid.Wakelock {
2997             /**
2998              * How long (in ms) this uid has been keeping the device partially awake.
2999              */
3000             StopwatchTimer mTimerPartial;
3001 
3002             /**
3003              * How long (in ms) this uid has been keeping the device fully awake.
3004              */
3005             StopwatchTimer mTimerFull;
3006 
3007             /**
3008              * How long (in ms) this uid has had a window keeping the device awake.
3009              */
3010             StopwatchTimer mTimerWindow;
3011 
3012             /**
3013              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
3014              * proper timer pool from the given BatteryStatsImpl object.
3015              *
3016              * @param in the Parcel to be read from.
3017              * return a new Timer, or null.
3018              */
readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, ArrayList<Unpluggable> unpluggables, Parcel in)3019             private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
3020                     ArrayList<Unpluggable> unpluggables, Parcel in) {
3021                 if (in.readInt() == 0) {
3022                     return null;
3023                 }
3024 
3025                 return new StopwatchTimer(Uid.this, type, pool, unpluggables, in);
3026             }
3027 
reset()3028             boolean reset() {
3029                 boolean wlactive = false;
3030                 if (mTimerFull != null) {
3031                     wlactive |= !mTimerFull.reset(BatteryStatsImpl.this, false);
3032                 }
3033                 if (mTimerPartial != null) {
3034                     wlactive |= !mTimerPartial.reset(BatteryStatsImpl.this, false);
3035                 }
3036                 if (mTimerWindow != null) {
3037                     wlactive |= !mTimerWindow.reset(BatteryStatsImpl.this, false);
3038                 }
3039                 if (!wlactive) {
3040                     if (mTimerFull != null) {
3041                         mTimerFull.detach();
3042                         mTimerFull = null;
3043                     }
3044                     if (mTimerPartial != null) {
3045                         mTimerPartial.detach();
3046                         mTimerPartial = null;
3047                     }
3048                     if (mTimerWindow != null) {
3049                         mTimerWindow.detach();
3050                         mTimerWindow = null;
3051                     }
3052                 }
3053                 return !wlactive;
3054             }
3055 
readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in)3056             void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
3057                 mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL,
3058                         mPartialTimers, unpluggables, in);
3059                 mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL,
3060                         mFullTimers, unpluggables, in);
3061                 mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW,
3062                         mWindowTimers, unpluggables, in);
3063             }
3064 
writeToParcelLocked(Parcel out, long batteryRealtime)3065             void writeToParcelLocked(Parcel out, long batteryRealtime) {
3066                 Timer.writeTimerToParcel(out, mTimerPartial, batteryRealtime);
3067                 Timer.writeTimerToParcel(out, mTimerFull, batteryRealtime);
3068                 Timer.writeTimerToParcel(out, mTimerWindow, batteryRealtime);
3069             }
3070 
3071             @Override
getWakeTime(int type)3072             public Timer getWakeTime(int type) {
3073                 switch (type) {
3074                 case WAKE_TYPE_FULL: return mTimerFull;
3075                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
3076                 case WAKE_TYPE_WINDOW: return mTimerWindow;
3077                 default: throw new IllegalArgumentException("type = " + type);
3078                 }
3079             }
3080         }
3081 
3082         public final class Sensor extends BatteryStats.Uid.Sensor {
3083             final int mHandle;
3084             StopwatchTimer mTimer;
3085 
Sensor(int handle)3086             public Sensor(int handle) {
3087                 mHandle = handle;
3088             }
3089 
readTimerFromParcel(ArrayList<Unpluggable> unpluggables, Parcel in)3090             private StopwatchTimer readTimerFromParcel(ArrayList<Unpluggable> unpluggables,
3091                     Parcel in) {
3092                 if (in.readInt() == 0) {
3093                     return null;
3094                 }
3095 
3096                 ArrayList<StopwatchTimer> pool = mSensorTimers.get(mHandle);
3097                 if (pool == null) {
3098                     pool = new ArrayList<StopwatchTimer>();
3099                     mSensorTimers.put(mHandle, pool);
3100                 }
3101                 return new StopwatchTimer(Uid.this, 0, pool, unpluggables, in);
3102             }
3103 
reset()3104             boolean reset() {
3105                 if (mTimer.reset(BatteryStatsImpl.this, true)) {
3106                     mTimer = null;
3107                     return true;
3108                 }
3109                 return false;
3110             }
3111 
readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in)3112             void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
3113                 mTimer = readTimerFromParcel(unpluggables, in);
3114             }
3115 
writeToParcelLocked(Parcel out, long batteryRealtime)3116             void writeToParcelLocked(Parcel out, long batteryRealtime) {
3117                 Timer.writeTimerToParcel(out, mTimer, batteryRealtime);
3118             }
3119 
3120             @Override
getSensorTime()3121             public Timer getSensorTime() {
3122                 return mTimer;
3123             }
3124 
3125             @Override
getHandle()3126             public int getHandle() {
3127                 return mHandle;
3128             }
3129         }
3130 
3131         /**
3132          * The statistics associated with a particular process.
3133          */
3134         public final class Proc extends BatteryStats.Uid.Proc implements Unpluggable {
3135             /**
3136              * Total time (in 1/100 sec) spent executing in user code.
3137              */
3138             long mUserTime;
3139 
3140             /**
3141              * Total time (in 1/100 sec) spent executing in kernel code.
3142              */
3143             long mSystemTime;
3144 
3145             /**
3146              * Number of times the process has been started.
3147              */
3148             int mStarts;
3149 
3150             /**
3151              * Amount of time the process was running in the foreground.
3152              */
3153             long mForegroundTime;
3154 
3155             /**
3156              * The amount of user time loaded from a previous save.
3157              */
3158             long mLoadedUserTime;
3159 
3160             /**
3161              * The amount of system time loaded from a previous save.
3162              */
3163             long mLoadedSystemTime;
3164 
3165             /**
3166              * The number of times the process has started from a previous save.
3167              */
3168             int mLoadedStarts;
3169 
3170             /**
3171              * The amount of foreground time loaded from a previous save.
3172              */
3173             long mLoadedForegroundTime;
3174 
3175             /**
3176              * The amount of user time loaded from the previous run.
3177              */
3178             long mLastUserTime;
3179 
3180             /**
3181              * The amount of system time loaded from the previous run.
3182              */
3183             long mLastSystemTime;
3184 
3185             /**
3186              * The number of times the process has started from the previous run.
3187              */
3188             int mLastStarts;
3189 
3190             /**
3191              * The amount of foreground time loaded from the previous run
3192              */
3193             long mLastForegroundTime;
3194 
3195             /**
3196              * The amount of user time when last unplugged.
3197              */
3198             long mUnpluggedUserTime;
3199 
3200             /**
3201              * The amount of system time when last unplugged.
3202              */
3203             long mUnpluggedSystemTime;
3204 
3205             /**
3206              * The number of times the process has started before unplugged.
3207              */
3208             int mUnpluggedStarts;
3209 
3210             /**
3211              * The amount of foreground time since unplugged.
3212              */
3213             long mUnpluggedForegroundTime;
3214 
3215             SamplingCounter[] mSpeedBins;
3216 
3217             ArrayList<ExcessivePower> mExcessivePower;
3218 
Proc()3219             Proc() {
3220                 mUnpluggables.add(this);
3221                 mSpeedBins = new SamplingCounter[getCpuSpeedSteps()];
3222             }
3223 
unplug(long batteryUptime, long batteryRealtime)3224             public void unplug(long batteryUptime, long batteryRealtime) {
3225                 mUnpluggedUserTime = mUserTime;
3226                 mUnpluggedSystemTime = mSystemTime;
3227                 mUnpluggedStarts = mStarts;
3228                 mUnpluggedForegroundTime = mForegroundTime;
3229             }
3230 
plug(long batteryUptime, long batteryRealtime)3231             public void plug(long batteryUptime, long batteryRealtime) {
3232             }
3233 
detach()3234             void detach() {
3235                 mUnpluggables.remove(this);
3236                 for (int i = 0; i < mSpeedBins.length; i++) {
3237                     SamplingCounter c = mSpeedBins[i];
3238                     if (c != null) {
3239                         mUnpluggables.remove(c);
3240                         mSpeedBins[i] = null;
3241                     }
3242                 }
3243             }
3244 
countExcessivePowers()3245             public int countExcessivePowers() {
3246                 return mExcessivePower != null ? mExcessivePower.size() : 0;
3247             }
3248 
getExcessivePower(int i)3249             public ExcessivePower getExcessivePower(int i) {
3250                 if (mExcessivePower != null) {
3251                     return mExcessivePower.get(i);
3252                 }
3253                 return null;
3254             }
3255 
addExcessiveWake(long overTime, long usedTime)3256             public void addExcessiveWake(long overTime, long usedTime) {
3257                 if (mExcessivePower == null) {
3258                     mExcessivePower = new ArrayList<ExcessivePower>();
3259                 }
3260                 ExcessivePower ew = new ExcessivePower();
3261                 ew.type = ExcessivePower.TYPE_WAKE;
3262                 ew.overTime = overTime;
3263                 ew.usedTime = usedTime;
3264                 mExcessivePower.add(ew);
3265             }
3266 
addExcessiveCpu(long overTime, long usedTime)3267             public void addExcessiveCpu(long overTime, long usedTime) {
3268                 if (mExcessivePower == null) {
3269                     mExcessivePower = new ArrayList<ExcessivePower>();
3270                 }
3271                 ExcessivePower ew = new ExcessivePower();
3272                 ew.type = ExcessivePower.TYPE_CPU;
3273                 ew.overTime = overTime;
3274                 ew.usedTime = usedTime;
3275                 mExcessivePower.add(ew);
3276             }
3277 
writeExcessivePowerToParcelLocked(Parcel out)3278             void writeExcessivePowerToParcelLocked(Parcel out) {
3279                 if (mExcessivePower == null) {
3280                     out.writeInt(0);
3281                     return;
3282                 }
3283 
3284                 final int N = mExcessivePower.size();
3285                 out.writeInt(N);
3286                 for (int i=0; i<N; i++) {
3287                     ExcessivePower ew = mExcessivePower.get(i);
3288                     out.writeInt(ew.type);
3289                     out.writeLong(ew.overTime);
3290                     out.writeLong(ew.usedTime);
3291                 }
3292             }
3293 
readExcessivePowerFromParcelLocked(Parcel in)3294             boolean readExcessivePowerFromParcelLocked(Parcel in) {
3295                 final int N = in.readInt();
3296                 if (N == 0) {
3297                     mExcessivePower = null;
3298                     return true;
3299                 }
3300 
3301                 if (N > 10000) {
3302                     Slog.w(TAG, "File corrupt: too many excessive power entries " + N);
3303                     return false;
3304                 }
3305 
3306                 mExcessivePower = new ArrayList<ExcessivePower>();
3307                 for (int i=0; i<N; i++) {
3308                     ExcessivePower ew = new ExcessivePower();
3309                     ew.type = in.readInt();
3310                     ew.overTime = in.readLong();
3311                     ew.usedTime = in.readLong();
3312                     mExcessivePower.add(ew);
3313                 }
3314                 return true;
3315             }
3316 
writeToParcelLocked(Parcel out)3317             void writeToParcelLocked(Parcel out) {
3318                 out.writeLong(mUserTime);
3319                 out.writeLong(mSystemTime);
3320                 out.writeLong(mForegroundTime);
3321                 out.writeInt(mStarts);
3322                 out.writeLong(mLoadedUserTime);
3323                 out.writeLong(mLoadedSystemTime);
3324                 out.writeLong(mLoadedForegroundTime);
3325                 out.writeInt(mLoadedStarts);
3326                 out.writeLong(mUnpluggedUserTime);
3327                 out.writeLong(mUnpluggedSystemTime);
3328                 out.writeLong(mUnpluggedForegroundTime);
3329                 out.writeInt(mUnpluggedStarts);
3330 
3331                 out.writeInt(mSpeedBins.length);
3332                 for (int i = 0; i < mSpeedBins.length; i++) {
3333                     SamplingCounter c = mSpeedBins[i];
3334                     if (c != null) {
3335                         out.writeInt(1);
3336                         c.writeToParcel(out);
3337                     } else {
3338                         out.writeInt(0);
3339                     }
3340                 }
3341 
3342                 writeExcessivePowerToParcelLocked(out);
3343             }
3344 
readFromParcelLocked(Parcel in)3345             void readFromParcelLocked(Parcel in) {
3346                 mUserTime = in.readLong();
3347                 mSystemTime = in.readLong();
3348                 mForegroundTime = in.readLong();
3349                 mStarts = in.readInt();
3350                 mLoadedUserTime = in.readLong();
3351                 mLoadedSystemTime = in.readLong();
3352                 mLoadedForegroundTime = in.readLong();
3353                 mLoadedStarts = in.readInt();
3354                 mLastUserTime = 0;
3355                 mLastSystemTime = 0;
3356                 mLastForegroundTime = 0;
3357                 mLastStarts = 0;
3358                 mUnpluggedUserTime = in.readLong();
3359                 mUnpluggedSystemTime = in.readLong();
3360                 mUnpluggedForegroundTime = in.readLong();
3361                 mUnpluggedStarts = in.readInt();
3362 
3363                 int bins = in.readInt();
3364                 int steps = getCpuSpeedSteps();
3365                 mSpeedBins = new SamplingCounter[bins >= steps ? bins : steps];
3366                 for (int i = 0; i < bins; i++) {
3367                     if (in.readInt() != 0) {
3368                         mSpeedBins[i] = new SamplingCounter(mUnpluggables, in);
3369                     }
3370                 }
3371 
3372                 readExcessivePowerFromParcelLocked(in);
3373             }
3374 
getBatteryStats()3375             public BatteryStatsImpl getBatteryStats() {
3376                 return BatteryStatsImpl.this;
3377             }
3378 
addCpuTimeLocked(int utime, int stime)3379             public void addCpuTimeLocked(int utime, int stime) {
3380                 mUserTime += utime;
3381                 mSystemTime += stime;
3382             }
3383 
addForegroundTimeLocked(long ttime)3384             public void addForegroundTimeLocked(long ttime) {
3385                 mForegroundTime += ttime;
3386             }
3387 
incStartsLocked()3388             public void incStartsLocked() {
3389                 mStarts++;
3390             }
3391 
3392             @Override
getUserTime(int which)3393             public long getUserTime(int which) {
3394                 long val;
3395                 if (which == STATS_LAST) {
3396                     val = mLastUserTime;
3397                 } else {
3398                     val = mUserTime;
3399                     if (which == STATS_CURRENT) {
3400                         val -= mLoadedUserTime;
3401                     } else if (which == STATS_SINCE_UNPLUGGED) {
3402                         val -= mUnpluggedUserTime;
3403                     }
3404                 }
3405                 return val;
3406             }
3407 
3408             @Override
getSystemTime(int which)3409             public long getSystemTime(int which) {
3410                 long val;
3411                 if (which == STATS_LAST) {
3412                     val = mLastSystemTime;
3413                 } else {
3414                     val = mSystemTime;
3415                     if (which == STATS_CURRENT) {
3416                         val -= mLoadedSystemTime;
3417                     } else if (which == STATS_SINCE_UNPLUGGED) {
3418                         val -= mUnpluggedSystemTime;
3419                     }
3420                 }
3421                 return val;
3422             }
3423 
3424             @Override
getForegroundTime(int which)3425             public long getForegroundTime(int which) {
3426                 long val;
3427                 if (which == STATS_LAST) {
3428                     val = mLastForegroundTime;
3429                 } else {
3430                     val = mForegroundTime;
3431                     if (which == STATS_CURRENT) {
3432                         val -= mLoadedForegroundTime;
3433                     } else if (which == STATS_SINCE_UNPLUGGED) {
3434                         val -= mUnpluggedForegroundTime;
3435                     }
3436                 }
3437                 return val;
3438             }
3439 
3440             @Override
getStarts(int which)3441             public int getStarts(int which) {
3442                 int val;
3443                 if (which == STATS_LAST) {
3444                     val = mLastStarts;
3445                 } else {
3446                     val = mStarts;
3447                     if (which == STATS_CURRENT) {
3448                         val -= mLoadedStarts;
3449                     } else if (which == STATS_SINCE_UNPLUGGED) {
3450                         val -= mUnpluggedStarts;
3451                     }
3452                 }
3453                 return val;
3454             }
3455 
3456             /* Called by ActivityManagerService when CPU times are updated. */
addSpeedStepTimes(long[] values)3457             public void addSpeedStepTimes(long[] values) {
3458                 for (int i = 0; i < mSpeedBins.length && i < values.length; i++) {
3459                     long amt = values[i];
3460                     if (amt != 0) {
3461                         SamplingCounter c = mSpeedBins[i];
3462                         if (c == null) {
3463                             mSpeedBins[i] = c = new SamplingCounter(mUnpluggables);
3464                         }
3465                         c.addCountAtomic(values[i]);
3466                     }
3467                 }
3468             }
3469 
3470             @Override
getTimeAtCpuSpeedStep(int speedStep, int which)3471             public long getTimeAtCpuSpeedStep(int speedStep, int which) {
3472                 if (speedStep < mSpeedBins.length) {
3473                     SamplingCounter c = mSpeedBins[speedStep];
3474                     return c != null ? c.getCountLocked(which) : 0;
3475                 } else {
3476                     return 0;
3477                 }
3478             }
3479         }
3480 
3481         /**
3482          * The statistics associated with a particular package.
3483          */
3484         public final class Pkg extends BatteryStats.Uid.Pkg implements Unpluggable {
3485             /**
3486              * Number of times this package has done something that could wake up the
3487              * device from sleep.
3488              */
3489             int mWakeups;
3490 
3491             /**
3492              * Number of things that could wake up the device loaded from a
3493              * previous save.
3494              */
3495             int mLoadedWakeups;
3496 
3497             /**
3498              * Number of things that could wake up the device as of the
3499              * last run.
3500              */
3501             int mLastWakeups;
3502 
3503             /**
3504              * Number of things that could wake up the device as of the
3505              * last run.
3506              */
3507             int mUnpluggedWakeups;
3508 
3509             /**
3510              * The statics we have collected for this package's services.
3511              */
3512             final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>();
3513 
Pkg()3514             Pkg() {
3515                 mUnpluggables.add(this);
3516             }
3517 
unplug(long batteryUptime, long batteryRealtime)3518             public void unplug(long batteryUptime, long batteryRealtime) {
3519                 mUnpluggedWakeups = mWakeups;
3520             }
3521 
plug(long batteryUptime, long batteryRealtime)3522             public void plug(long batteryUptime, long batteryRealtime) {
3523             }
3524 
detach()3525             void detach() {
3526                 mUnpluggables.remove(this);
3527             }
3528 
readFromParcelLocked(Parcel in)3529             void readFromParcelLocked(Parcel in) {
3530                 mWakeups = in.readInt();
3531                 mLoadedWakeups = in.readInt();
3532                 mLastWakeups = 0;
3533                 mUnpluggedWakeups = in.readInt();
3534 
3535                 int numServs = in.readInt();
3536                 mServiceStats.clear();
3537                 for (int m = 0; m < numServs; m++) {
3538                     String serviceName = in.readString();
3539                     Uid.Pkg.Serv serv = new Serv();
3540                     mServiceStats.put(serviceName, serv);
3541 
3542                     serv.readFromParcelLocked(in);
3543                 }
3544             }
3545 
writeToParcelLocked(Parcel out)3546             void writeToParcelLocked(Parcel out) {
3547                 out.writeInt(mWakeups);
3548                 out.writeInt(mLoadedWakeups);
3549                 out.writeInt(mUnpluggedWakeups);
3550 
3551                 out.writeInt(mServiceStats.size());
3552                 for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) {
3553                     out.writeString(servEntry.getKey());
3554                     Uid.Pkg.Serv serv = servEntry.getValue();
3555 
3556                     serv.writeToParcelLocked(out);
3557                 }
3558             }
3559 
3560             @Override
getServiceStats()3561             public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
3562                 return mServiceStats;
3563             }
3564 
3565             @Override
getWakeups(int which)3566             public int getWakeups(int which) {
3567                 int val;
3568                 if (which == STATS_LAST) {
3569                     val = mLastWakeups;
3570                 } else {
3571                     val = mWakeups;
3572                     if (which == STATS_CURRENT) {
3573                         val -= mLoadedWakeups;
3574                     } else if (which == STATS_SINCE_UNPLUGGED) {
3575                         val -= mUnpluggedWakeups;
3576                     }
3577                 }
3578 
3579                 return val;
3580             }
3581 
3582             /**
3583              * The statistics associated with a particular service.
3584              */
3585             public final class Serv extends BatteryStats.Uid.Pkg.Serv implements Unpluggable {
3586                 /**
3587                  * Total time (ms in battery uptime) the service has been left started.
3588                  */
3589                 long mStartTime;
3590 
3591                 /**
3592                  * If service has been started and not yet stopped, this is
3593                  * when it was started.
3594                  */
3595                 long mRunningSince;
3596 
3597                 /**
3598                  * True if we are currently running.
3599                  */
3600                 boolean mRunning;
3601 
3602                 /**
3603                  * Total number of times startService() has been called.
3604                  */
3605                 int mStarts;
3606 
3607                 /**
3608                  * Total time (ms in battery uptime) the service has been left launched.
3609                  */
3610                 long mLaunchedTime;
3611 
3612                 /**
3613                  * If service has been launched and not yet exited, this is
3614                  * when it was launched (ms in battery uptime).
3615                  */
3616                 long mLaunchedSince;
3617 
3618                 /**
3619                  * True if we are currently launched.
3620                  */
3621                 boolean mLaunched;
3622 
3623                 /**
3624                  * Total number times the service has been launched.
3625                  */
3626                 int mLaunches;
3627 
3628                 /**
3629                  * The amount of time spent started loaded from a previous save
3630                  * (ms in battery uptime).
3631                  */
3632                 long mLoadedStartTime;
3633 
3634                 /**
3635                  * The number of starts loaded from a previous save.
3636                  */
3637                 int mLoadedStarts;
3638 
3639                 /**
3640                  * The number of launches loaded from a previous save.
3641                  */
3642                 int mLoadedLaunches;
3643 
3644                 /**
3645                  * The amount of time spent started as of the last run (ms
3646                  * in battery uptime).
3647                  */
3648                 long mLastStartTime;
3649 
3650                 /**
3651                  * The number of starts as of the last run.
3652                  */
3653                 int mLastStarts;
3654 
3655                 /**
3656                  * The number of launches as of the last run.
3657                  */
3658                 int mLastLaunches;
3659 
3660                 /**
3661                  * The amount of time spent started when last unplugged (ms
3662                  * in battery uptime).
3663                  */
3664                 long mUnpluggedStartTime;
3665 
3666                 /**
3667                  * The number of starts when last unplugged.
3668                  */
3669                 int mUnpluggedStarts;
3670 
3671                 /**
3672                  * The number of launches when last unplugged.
3673                  */
3674                 int mUnpluggedLaunches;
3675 
Serv()3676                 Serv() {
3677                     mUnpluggables.add(this);
3678                 }
3679 
unplug(long batteryUptime, long batteryRealtime)3680                 public void unplug(long batteryUptime, long batteryRealtime) {
3681                     mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime);
3682                     mUnpluggedStarts = mStarts;
3683                     mUnpluggedLaunches = mLaunches;
3684                 }
3685 
plug(long batteryUptime, long batteryRealtime)3686                 public void plug(long batteryUptime, long batteryRealtime) {
3687                 }
3688 
detach()3689                 void detach() {
3690                     mUnpluggables.remove(this);
3691                 }
3692 
readFromParcelLocked(Parcel in)3693                 void readFromParcelLocked(Parcel in) {
3694                     mStartTime = in.readLong();
3695                     mRunningSince = in.readLong();
3696                     mRunning = in.readInt() != 0;
3697                     mStarts = in.readInt();
3698                     mLaunchedTime = in.readLong();
3699                     mLaunchedSince = in.readLong();
3700                     mLaunched = in.readInt() != 0;
3701                     mLaunches = in.readInt();
3702                     mLoadedStartTime = in.readLong();
3703                     mLoadedStarts = in.readInt();
3704                     mLoadedLaunches = in.readInt();
3705                     mLastStartTime = 0;
3706                     mLastStarts = 0;
3707                     mLastLaunches = 0;
3708                     mUnpluggedStartTime = in.readLong();
3709                     mUnpluggedStarts = in.readInt();
3710                     mUnpluggedLaunches = in.readInt();
3711                 }
3712 
writeToParcelLocked(Parcel out)3713                 void writeToParcelLocked(Parcel out) {
3714                     out.writeLong(mStartTime);
3715                     out.writeLong(mRunningSince);
3716                     out.writeInt(mRunning ? 1 : 0);
3717                     out.writeInt(mStarts);
3718                     out.writeLong(mLaunchedTime);
3719                     out.writeLong(mLaunchedSince);
3720                     out.writeInt(mLaunched ? 1 : 0);
3721                     out.writeInt(mLaunches);
3722                     out.writeLong(mLoadedStartTime);
3723                     out.writeInt(mLoadedStarts);
3724                     out.writeInt(mLoadedLaunches);
3725                     out.writeLong(mUnpluggedStartTime);
3726                     out.writeInt(mUnpluggedStarts);
3727                     out.writeInt(mUnpluggedLaunches);
3728                 }
3729 
getLaunchTimeToNowLocked(long batteryUptime)3730                 long getLaunchTimeToNowLocked(long batteryUptime) {
3731                     if (!mLaunched) return mLaunchedTime;
3732                     return mLaunchedTime + batteryUptime - mLaunchedSince;
3733                 }
3734 
getStartTimeToNowLocked(long batteryUptime)3735                 long getStartTimeToNowLocked(long batteryUptime) {
3736                     if (!mRunning) return mStartTime;
3737                     return mStartTime + batteryUptime - mRunningSince;
3738                 }
3739 
startLaunchedLocked()3740                 public void startLaunchedLocked() {
3741                     if (!mLaunched) {
3742                         mLaunches++;
3743                         mLaunchedSince = getBatteryUptimeLocked();
3744                         mLaunched = true;
3745                     }
3746                 }
3747 
stopLaunchedLocked()3748                 public void stopLaunchedLocked() {
3749                     if (mLaunched) {
3750                         long time = getBatteryUptimeLocked() - mLaunchedSince;
3751                         if (time > 0) {
3752                             mLaunchedTime += time;
3753                         } else {
3754                             mLaunches--;
3755                         }
3756                         mLaunched = false;
3757                     }
3758                 }
3759 
startRunningLocked()3760                 public void startRunningLocked() {
3761                     if (!mRunning) {
3762                         mStarts++;
3763                         mRunningSince = getBatteryUptimeLocked();
3764                         mRunning = true;
3765                     }
3766                 }
3767 
stopRunningLocked()3768                 public void stopRunningLocked() {
3769                     if (mRunning) {
3770                         long time = getBatteryUptimeLocked() - mRunningSince;
3771                         if (time > 0) {
3772                             mStartTime += time;
3773                         } else {
3774                             mStarts--;
3775                         }
3776                         mRunning = false;
3777                     }
3778                 }
3779 
getBatteryStats()3780                 public BatteryStatsImpl getBatteryStats() {
3781                     return BatteryStatsImpl.this;
3782                 }
3783 
3784                 @Override
getLaunches(int which)3785                 public int getLaunches(int which) {
3786                     int val;
3787 
3788                     if (which == STATS_LAST) {
3789                         val = mLastLaunches;
3790                     } else {
3791                         val = mLaunches;
3792                         if (which == STATS_CURRENT) {
3793                             val -= mLoadedLaunches;
3794                         } else if (which == STATS_SINCE_UNPLUGGED) {
3795                             val -= mUnpluggedLaunches;
3796                         }
3797                     }
3798 
3799                     return val;
3800                 }
3801 
3802                 @Override
getStartTime(long now, int which)3803                 public long getStartTime(long now, int which) {
3804                     long val;
3805                     if (which == STATS_LAST) {
3806                         val = mLastStartTime;
3807                     } else {
3808                         val = getStartTimeToNowLocked(now);
3809                         if (which == STATS_CURRENT) {
3810                             val -= mLoadedStartTime;
3811                         } else if (which == STATS_SINCE_UNPLUGGED) {
3812                             val -= mUnpluggedStartTime;
3813                         }
3814                     }
3815 
3816                     return val;
3817                 }
3818 
3819                 @Override
getStarts(int which)3820                 public int getStarts(int which) {
3821                     int val;
3822                     if (which == STATS_LAST) {
3823                         val = mLastStarts;
3824                     } else {
3825                         val = mStarts;
3826                         if (which == STATS_CURRENT) {
3827                             val -= mLoadedStarts;
3828                         } else if (which == STATS_SINCE_UNPLUGGED) {
3829                             val -= mUnpluggedStarts;
3830                         }
3831                     }
3832 
3833                     return val;
3834                 }
3835             }
3836 
getBatteryStats()3837             public BatteryStatsImpl getBatteryStats() {
3838                 return BatteryStatsImpl.this;
3839             }
3840 
incWakeupsLocked()3841             public void incWakeupsLocked() {
3842                 mWakeups++;
3843             }
3844 
newServiceStatsLocked()3845             final Serv newServiceStatsLocked() {
3846                 return new Serv();
3847             }
3848         }
3849 
3850         /**
3851          * Retrieve the statistics object for a particular process, creating
3852          * if needed.
3853          */
getProcessStatsLocked(String name)3854         public Proc getProcessStatsLocked(String name) {
3855             Proc ps = mProcessStats.get(name);
3856             if (ps == null) {
3857                 ps = new Proc();
3858                 mProcessStats.put(name, ps);
3859             }
3860 
3861             return ps;
3862         }
3863 
getPidStats()3864         public SparseArray<? extends Pid> getPidStats() {
3865             return mPids;
3866         }
3867 
getPidStatsLocked(int pid)3868         public Pid getPidStatsLocked(int pid) {
3869             Pid p = mPids.get(pid);
3870             if (p == null) {
3871                 p = new Pid();
3872                 mPids.put(pid, p);
3873             }
3874             return p;
3875         }
3876 
3877         /**
3878          * Retrieve the statistics object for a particular service, creating
3879          * if needed.
3880          */
getPackageStatsLocked(String name)3881         public Pkg getPackageStatsLocked(String name) {
3882             Pkg ps = mPackageStats.get(name);
3883             if (ps == null) {
3884                 ps = new Pkg();
3885                 mPackageStats.put(name, ps);
3886             }
3887 
3888             return ps;
3889         }
3890 
3891         /**
3892          * Retrieve the statistics object for a particular service, creating
3893          * if needed.
3894          */
getServiceStatsLocked(String pkg, String serv)3895         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
3896             Pkg ps = getPackageStatsLocked(pkg);
3897             Pkg.Serv ss = ps.mServiceStats.get(serv);
3898             if (ss == null) {
3899                 ss = ps.newServiceStatsLocked();
3900                 ps.mServiceStats.put(serv, ss);
3901             }
3902 
3903             return ss;
3904         }
3905 
getWakeTimerLocked(String name, int type)3906         public StopwatchTimer getWakeTimerLocked(String name, int type) {
3907             Wakelock wl = mWakelockStats.get(name);
3908             if (wl == null) {
3909                 final int N = mWakelockStats.size();
3910                 if (N > MAX_WAKELOCKS_PER_UID && (mUid != Process.SYSTEM_UID
3911                         || N > MAX_WAKELOCKS_PER_UID_IN_SYSTEM)) {
3912                     name = BATCHED_WAKELOCK_NAME;
3913                     wl = mWakelockStats.get(name);
3914                 }
3915                 if (wl == null) {
3916                     wl = new Wakelock();
3917                     mWakelockStats.put(name, wl);
3918                 }
3919             }
3920             StopwatchTimer t = null;
3921             switch (type) {
3922                 case WAKE_TYPE_PARTIAL:
3923                     t = wl.mTimerPartial;
3924                     if (t == null) {
3925                         t = new StopwatchTimer(Uid.this, WAKE_TYPE_PARTIAL,
3926                                 mPartialTimers, mUnpluggables);
3927                         wl.mTimerPartial = t;
3928                     }
3929                     return t;
3930                 case WAKE_TYPE_FULL:
3931                     t = wl.mTimerFull;
3932                     if (t == null) {
3933                         t = new StopwatchTimer(Uid.this, WAKE_TYPE_FULL,
3934                                 mFullTimers, mUnpluggables);
3935                         wl.mTimerFull = t;
3936                     }
3937                     return t;
3938                 case WAKE_TYPE_WINDOW:
3939                     t = wl.mTimerWindow;
3940                     if (t == null) {
3941                         t = new StopwatchTimer(Uid.this, WAKE_TYPE_WINDOW,
3942                                 mWindowTimers, mUnpluggables);
3943                         wl.mTimerWindow = t;
3944                     }
3945                     return t;
3946                 default:
3947                     throw new IllegalArgumentException("type=" + type);
3948             }
3949         }
3950 
getSensorTimerLocked(int sensor, boolean create)3951         public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) {
3952             Sensor se = mSensorStats.get(sensor);
3953             if (se == null) {
3954                 if (!create) {
3955                     return null;
3956                 }
3957                 se = new Sensor(sensor);
3958                 mSensorStats.put(sensor, se);
3959             }
3960             StopwatchTimer t = se.mTimer;
3961             if (t != null) {
3962                 return t;
3963             }
3964             ArrayList<StopwatchTimer> timers = mSensorTimers.get(sensor);
3965             if (timers == null) {
3966                 timers = new ArrayList<StopwatchTimer>();
3967                 mSensorTimers.put(sensor, timers);
3968             }
3969             t = new StopwatchTimer(Uid.this, BatteryStats.SENSOR, timers, mUnpluggables);
3970             se.mTimer = t;
3971             return t;
3972         }
3973 
noteStartWakeLocked(int pid, String name, int type)3974         public void noteStartWakeLocked(int pid, String name, int type) {
3975             StopwatchTimer t = getWakeTimerLocked(name, type);
3976             if (t != null) {
3977                 t.startRunningLocked(BatteryStatsImpl.this);
3978             }
3979             if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
3980                 Pid p = getPidStatsLocked(pid);
3981                 if (p.mWakeStart == 0) {
3982                     p.mWakeStart = SystemClock.elapsedRealtime();
3983                 }
3984             }
3985         }
3986 
noteStopWakeLocked(int pid, String name, int type)3987         public void noteStopWakeLocked(int pid, String name, int type) {
3988             StopwatchTimer t = getWakeTimerLocked(name, type);
3989             if (t != null) {
3990                 t.stopRunningLocked(BatteryStatsImpl.this);
3991             }
3992             if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
3993                 Pid p = mPids.get(pid);
3994                 if (p != null && p.mWakeStart != 0) {
3995                     p.mWakeSum += SystemClock.elapsedRealtime() - p.mWakeStart;
3996                     p.mWakeStart = 0;
3997                 }
3998             }
3999         }
4000 
reportExcessiveWakeLocked(String proc, long overTime, long usedTime)4001         public void reportExcessiveWakeLocked(String proc, long overTime, long usedTime) {
4002             Proc p = getProcessStatsLocked(proc);
4003             if (p != null) {
4004                 p.addExcessiveWake(overTime, usedTime);
4005             }
4006         }
4007 
reportExcessiveCpuLocked(String proc, long overTime, long usedTime)4008         public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
4009             Proc p = getProcessStatsLocked(proc);
4010             if (p != null) {
4011                 p.addExcessiveCpu(overTime, usedTime);
4012             }
4013         }
4014 
noteStartSensor(int sensor)4015         public void noteStartSensor(int sensor) {
4016             StopwatchTimer t = getSensorTimerLocked(sensor, true);
4017             if (t != null) {
4018                 t.startRunningLocked(BatteryStatsImpl.this);
4019             }
4020         }
4021 
noteStopSensor(int sensor)4022         public void noteStopSensor(int sensor) {
4023             // Don't create a timer if one doesn't already exist
4024             StopwatchTimer t = getSensorTimerLocked(sensor, false);
4025             if (t != null) {
4026                 t.stopRunningLocked(BatteryStatsImpl.this);
4027             }
4028         }
4029 
noteStartGps()4030         public void noteStartGps() {
4031             StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true);
4032             if (t != null) {
4033                 t.startRunningLocked(BatteryStatsImpl.this);
4034             }
4035         }
4036 
noteStopGps()4037         public void noteStopGps() {
4038             StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false);
4039             if (t != null) {
4040                 t.stopRunningLocked(BatteryStatsImpl.this);
4041             }
4042         }
4043 
getBatteryStats()4044         public BatteryStatsImpl getBatteryStats() {
4045             return BatteryStatsImpl.this;
4046         }
4047     }
4048 
BatteryStatsImpl(String filename)4049     public BatteryStatsImpl(String filename) {
4050         mFile = new JournaledFile(new File(filename), new File(filename + ".tmp"));
4051         mHandler = new MyHandler();
4052         mStartCount++;
4053         mScreenOnTimer = new StopwatchTimer(null, -1, null, mUnpluggables);
4054         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
4055             mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mUnpluggables);
4056         }
4057         mInputEventCounter = new Counter(mUnpluggables);
4058         mPhoneOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables);
4059         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
4060             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null, mUnpluggables);
4061         }
4062         mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mUnpluggables);
4063         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
4064             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, null, mUnpluggables);
4065         }
4066         mWifiOnTimer = new StopwatchTimer(null, -3, null, mUnpluggables);
4067         mGlobalWifiRunningTimer = new StopwatchTimer(null, -4, null, mUnpluggables);
4068         mBluetoothOnTimer = new StopwatchTimer(null, -5, null, mUnpluggables);
4069         mAudioOnTimer = new StopwatchTimer(null, -6, null, mUnpluggables);
4070         mVideoOnTimer = new StopwatchTimer(null, -7, null, mUnpluggables);
4071         mOnBattery = mOnBatteryInternal = false;
4072         initTimes();
4073         mTrackBatteryPastUptime = 0;
4074         mTrackBatteryPastRealtime = 0;
4075         mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000;
4076         mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000;
4077         mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart);
4078         mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart);
4079         mDischargeStartLevel = 0;
4080         mDischargeUnplugLevel = 0;
4081         mDischargeCurrentLevel = 0;
4082         initDischarge();
4083         clearHistoryLocked();
4084     }
4085 
BatteryStatsImpl(Parcel p)4086     public BatteryStatsImpl(Parcel p) {
4087         mFile = null;
4088         mHandler = null;
4089         clearHistoryLocked();
4090         readFromParcel(p);
4091     }
4092 
setCallback(BatteryCallback cb)4093     public void setCallback(BatteryCallback cb) {
4094         mCallback = cb;
4095     }
4096 
setNumSpeedSteps(int steps)4097     public void setNumSpeedSteps(int steps) {
4098         if (sNumSpeedSteps == 0) sNumSpeedSteps = steps;
4099     }
4100 
setRadioScanningTimeout(long timeout)4101     public void setRadioScanningTimeout(long timeout) {
4102         if (mPhoneSignalScanningTimer != null) {
4103             mPhoneSignalScanningTimer.setTimeout(timeout);
4104         }
4105     }
4106 
4107     @Override
startIteratingOldHistoryLocked()4108     public boolean startIteratingOldHistoryLocked() {
4109         if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
4110                 + " pos=" + mHistoryBuffer.dataPosition());
4111         mHistoryBuffer.setDataPosition(0);
4112         mHistoryReadTmp.clear();
4113         mReadOverflow = false;
4114         mIteratingHistory = true;
4115         return (mHistoryIterator = mHistory) != null;
4116     }
4117 
4118     @Override
getNextOldHistoryLocked(HistoryItem out)4119     public boolean getNextOldHistoryLocked(HistoryItem out) {
4120         boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
4121         if (!end) {
4122             mHistoryReadTmp.readDelta(mHistoryBuffer);
4123             mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
4124         }
4125         HistoryItem cur = mHistoryIterator;
4126         if (cur == null) {
4127             if (!mReadOverflow && !end) {
4128                 Slog.w(TAG, "Old history ends before new history!");
4129             }
4130             return false;
4131         }
4132         out.setTo(cur);
4133         mHistoryIterator = cur.next;
4134         if (!mReadOverflow) {
4135             if (end) {
4136                 Slog.w(TAG, "New history ends before old history!");
4137             } else if (!out.same(mHistoryReadTmp)) {
4138                 long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
4139                 PrintWriter pw = new PrintWriter(new LogWriter(android.util.Log.WARN, TAG));
4140                 pw.println("Histories differ!");
4141                 pw.println("Old history:");
4142                 (new HistoryPrinter()).printNextItem(pw, out, now);
4143                 pw.println("New history:");
4144                 (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, now);
4145             }
4146         }
4147         return true;
4148     }
4149 
4150     @Override
finishIteratingOldHistoryLocked()4151     public void finishIteratingOldHistoryLocked() {
4152         mIteratingHistory = false;
4153         mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
4154     }
4155 
4156     @Override
startIteratingHistoryLocked()4157     public boolean startIteratingHistoryLocked() {
4158         if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
4159                 + " pos=" + mHistoryBuffer.dataPosition());
4160         mHistoryBuffer.setDataPosition(0);
4161         mReadOverflow = false;
4162         mIteratingHistory = true;
4163         return mHistoryBuffer.dataSize() > 0;
4164     }
4165 
4166     @Override
getNextHistoryLocked(HistoryItem out)4167     public boolean getNextHistoryLocked(HistoryItem out) {
4168         final int pos = mHistoryBuffer.dataPosition();
4169         if (pos == 0) {
4170             out.clear();
4171         }
4172         boolean end = pos >= mHistoryBuffer.dataSize();
4173         if (end) {
4174             return false;
4175         }
4176 
4177         out.readDelta(mHistoryBuffer);
4178         return true;
4179     }
4180 
4181     @Override
finishIteratingHistoryLocked()4182     public void finishIteratingHistoryLocked() {
4183         mIteratingHistory = false;
4184         mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
4185     }
4186 
4187     @Override
getHistoryBaseTime()4188     public long getHistoryBaseTime() {
4189         return mHistoryBaseTime;
4190     }
4191 
4192     @Override
getStartCount()4193     public int getStartCount() {
4194         return mStartCount;
4195     }
4196 
isOnBattery()4197     public boolean isOnBattery() {
4198         return mOnBattery;
4199     }
4200 
isScreenOn()4201     public boolean isScreenOn() {
4202         return mScreenOn;
4203     }
4204 
initTimes()4205     void initTimes() {
4206         mBatteryRealtime = mTrackBatteryPastUptime = 0;
4207         mBatteryUptime = mTrackBatteryPastRealtime = 0;
4208         mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000;
4209         mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000;
4210         mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart);
4211         mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart);
4212     }
4213 
initDischarge()4214     void initDischarge() {
4215         mLowDischargeAmountSinceCharge = 0;
4216         mHighDischargeAmountSinceCharge = 0;
4217         mDischargeAmountScreenOn = 0;
4218         mDischargeAmountScreenOnSinceCharge = 0;
4219         mDischargeAmountScreenOff = 0;
4220         mDischargeAmountScreenOffSinceCharge = 0;
4221     }
4222 
resetAllStatsLocked()4223     public void resetAllStatsLocked() {
4224         mStartCount = 0;
4225         initTimes();
4226         mScreenOnTimer.reset(this, false);
4227         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
4228             mScreenBrightnessTimer[i].reset(this, false);
4229         }
4230         mInputEventCounter.reset(false);
4231         mPhoneOnTimer.reset(this, false);
4232         mAudioOnTimer.reset(this, false);
4233         mVideoOnTimer.reset(this, false);
4234         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
4235             mPhoneSignalStrengthsTimer[i].reset(this, false);
4236         }
4237         mPhoneSignalScanningTimer.reset(this, false);
4238         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
4239             mPhoneDataConnectionsTimer[i].reset(this, false);
4240         }
4241         mWifiOnTimer.reset(this, false);
4242         mGlobalWifiRunningTimer.reset(this, false);
4243         mBluetoothOnTimer.reset(this, false);
4244 
4245         for (int i=0; i<mUidStats.size(); i++) {
4246             if (mUidStats.valueAt(i).reset()) {
4247                 mUidStats.remove(mUidStats.keyAt(i));
4248                 i--;
4249             }
4250         }
4251 
4252         if (mKernelWakelockStats.size() > 0) {
4253             for (SamplingTimer timer : mKernelWakelockStats.values()) {
4254                 mUnpluggables.remove(timer);
4255             }
4256             mKernelWakelockStats.clear();
4257         }
4258 
4259         initDischarge();
4260 
4261         clearHistoryLocked();
4262     }
4263 
updateDischargeScreenLevelsLocked(boolean oldScreenOn, boolean newScreenOn)4264     void updateDischargeScreenLevelsLocked(boolean oldScreenOn, boolean newScreenOn) {
4265         if (oldScreenOn) {
4266             int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
4267             if (diff > 0) {
4268                 mDischargeAmountScreenOn += diff;
4269                 mDischargeAmountScreenOnSinceCharge += diff;
4270             }
4271         } else {
4272             int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
4273             if (diff > 0) {
4274                 mDischargeAmountScreenOff += diff;
4275                 mDischargeAmountScreenOffSinceCharge += diff;
4276             }
4277         }
4278         if (newScreenOn) {
4279             mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
4280             mDischargeScreenOffUnplugLevel = 0;
4281         } else {
4282             mDischargeScreenOnUnplugLevel = 0;
4283             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
4284         }
4285     }
4286 
setOnBattery(boolean onBattery, int oldStatus, int level)4287     void setOnBattery(boolean onBattery, int oldStatus, int level) {
4288         synchronized(this) {
4289             setOnBatteryLocked(onBattery, oldStatus, level);
4290         }
4291     }
4292 
setOnBatteryLocked(boolean onBattery, int oldStatus, int level)4293     void setOnBatteryLocked(boolean onBattery, int oldStatus, int level) {
4294         boolean doWrite = false;
4295         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
4296         m.arg1 = onBattery ? 1 : 0;
4297         mHandler.sendMessage(m);
4298         mOnBattery = mOnBatteryInternal = onBattery;
4299 
4300         long uptime = SystemClock.uptimeMillis() * 1000;
4301         long mSecRealtime = SystemClock.elapsedRealtime();
4302         long realtime = mSecRealtime * 1000;
4303         if (onBattery) {
4304             // We will reset our status if we are unplugging after the
4305             // battery was last full, or the level is at 100, or
4306             // we have gone through a significant charge (from a very low
4307             // level to a now very high level).
4308             if (oldStatus == BatteryManager.BATTERY_STATUS_FULL
4309                     || level >= 90
4310                     || (mDischargeCurrentLevel < 20 && level >= 80)) {
4311                 doWrite = true;
4312                 resetAllStatsLocked();
4313                 mDischargeStartLevel = level;
4314             }
4315             updateKernelWakelocksLocked();
4316             mHistoryCur.batteryLevel = (byte)level;
4317             mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
4318             if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
4319                     + Integer.toHexString(mHistoryCur.states));
4320             addHistoryRecordLocked(mSecRealtime);
4321             mTrackBatteryUptimeStart = uptime;
4322             mTrackBatteryRealtimeStart = realtime;
4323             mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime);
4324             mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime);
4325             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
4326             if (mScreenOn) {
4327                 mDischargeScreenOnUnplugLevel = level;
4328                 mDischargeScreenOffUnplugLevel = 0;
4329             } else {
4330                 mDischargeScreenOnUnplugLevel = 0;
4331                 mDischargeScreenOffUnplugLevel = level;
4332             }
4333             mDischargeAmountScreenOn = 0;
4334             mDischargeAmountScreenOff = 0;
4335             doUnplugLocked(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
4336         } else {
4337             updateKernelWakelocksLocked();
4338             mHistoryCur.batteryLevel = (byte)level;
4339             mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
4340             if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
4341                     + Integer.toHexString(mHistoryCur.states));
4342             addHistoryRecordLocked(mSecRealtime);
4343             mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart;
4344             mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart;
4345             mDischargeCurrentLevel = level;
4346             if (level < mDischargeUnplugLevel) {
4347                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
4348                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
4349             }
4350             updateDischargeScreenLevelsLocked(mScreenOn, mScreenOn);
4351             doPlugLocked(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime));
4352         }
4353         if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
4354             if (mFile != null) {
4355                 writeAsyncLocked();
4356             }
4357         }
4358     }
4359 
4360     // This should probably be exposed in the API, though it's not critical
4361     private static final int BATTERY_PLUGGED_NONE = 0;
4362 
setBatteryState(int status, int health, int plugType, int level, int temp, int volt)4363     public void setBatteryState(int status, int health, int plugType, int level,
4364             int temp, int volt) {
4365         synchronized(this) {
4366             boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
4367             int oldStatus = mHistoryCur.batteryStatus;
4368             if (!mHaveBatteryLevel) {
4369                 mHaveBatteryLevel = true;
4370                 // We start out assuming that the device is plugged in (not
4371                 // on battery).  If our first report is now that we are indeed
4372                 // plugged in, then twiddle our state to correctly reflect that
4373                 // since we won't be going through the full setOnBattery().
4374                 if (onBattery == mOnBattery) {
4375                     if (onBattery) {
4376                         mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
4377                     } else {
4378                         mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
4379                     }
4380                 }
4381                 oldStatus = status;
4382             }
4383             if (onBattery) {
4384                 mDischargeCurrentLevel = level;
4385                 mRecordingHistory = true;
4386             }
4387             if (onBattery != mOnBattery) {
4388                 mHistoryCur.batteryLevel = (byte)level;
4389                 mHistoryCur.batteryStatus = (byte)status;
4390                 mHistoryCur.batteryHealth = (byte)health;
4391                 mHistoryCur.batteryPlugType = (byte)plugType;
4392                 mHistoryCur.batteryTemperature = (char)temp;
4393                 mHistoryCur.batteryVoltage = (char)volt;
4394                 setOnBatteryLocked(onBattery, oldStatus, level);
4395             } else {
4396                 boolean changed = false;
4397                 if (mHistoryCur.batteryLevel != level) {
4398                     mHistoryCur.batteryLevel = (byte)level;
4399                     changed = true;
4400                 }
4401                 if (mHistoryCur.batteryStatus != status) {
4402                     mHistoryCur.batteryStatus = (byte)status;
4403                     changed = true;
4404                 }
4405                 if (mHistoryCur.batteryHealth != health) {
4406                     mHistoryCur.batteryHealth = (byte)health;
4407                     changed = true;
4408                 }
4409                 if (mHistoryCur.batteryPlugType != plugType) {
4410                     mHistoryCur.batteryPlugType = (byte)plugType;
4411                     changed = true;
4412                 }
4413                 if (temp >= (mHistoryCur.batteryTemperature+10)
4414                         || temp <= (mHistoryCur.batteryTemperature-10)) {
4415                     mHistoryCur.batteryTemperature = (char)temp;
4416                     changed = true;
4417                 }
4418                 if (volt > (mHistoryCur.batteryVoltage+20)
4419                         || volt < (mHistoryCur.batteryVoltage-20)) {
4420                     mHistoryCur.batteryVoltage = (char)volt;
4421                     changed = true;
4422                 }
4423                 if (changed) {
4424                     addHistoryRecordLocked(SystemClock.elapsedRealtime());
4425                 }
4426             }
4427             if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) {
4428                 // We don't record history while we are plugged in and fully charged.
4429                 // The next time we are unplugged, history will be cleared.
4430                 mRecordingHistory = false;
4431             }
4432         }
4433     }
4434 
updateKernelWakelocksLocked()4435     public void updateKernelWakelocksLocked() {
4436         Map<String, KernelWakelockStats> m = readKernelWakelockStats();
4437 
4438         if (m == null) {
4439             // Not crashing might make board bringup easier.
4440             Slog.w(TAG, "Couldn't get kernel wake lock stats");
4441             return;
4442         }
4443 
4444         for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) {
4445             String name = ent.getKey();
4446             KernelWakelockStats kws = ent.getValue();
4447 
4448             SamplingTimer kwlt = mKernelWakelockStats.get(name);
4449             if (kwlt == null) {
4450                 kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal,
4451                         true /* track reported values */);
4452                 mKernelWakelockStats.put(name, kwlt);
4453             }
4454             kwlt.updateCurrentReportedCount(kws.mCount);
4455             kwlt.updateCurrentReportedTotalTime(kws.mTotalTime);
4456             kwlt.setUpdateVersion(sKernelWakelockUpdateVersion);
4457         }
4458 
4459         if (m.size() != mKernelWakelockStats.size()) {
4460             // Set timers to stale if they didn't appear in /proc/wakelocks this time.
4461             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
4462                 SamplingTimer st = ent.getValue();
4463                 if (st.getUpdateVersion() != sKernelWakelockUpdateVersion) {
4464                     st.setStale();
4465                 }
4466             }
4467         }
4468     }
4469 
getAwakeTimeBattery()4470     public long getAwakeTimeBattery() {
4471         return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
4472     }
4473 
getAwakeTimePlugged()4474     public long getAwakeTimePlugged() {
4475         return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery();
4476     }
4477 
4478     @Override
computeUptime(long curTime, int which)4479     public long computeUptime(long curTime, int which) {
4480         switch (which) {
4481             case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart);
4482             case STATS_LAST: return mLastUptime;
4483             case STATS_CURRENT: return (curTime-mUptimeStart);
4484             case STATS_SINCE_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart);
4485         }
4486         return 0;
4487     }
4488 
4489     @Override
computeRealtime(long curTime, int which)4490     public long computeRealtime(long curTime, int which) {
4491         switch (which) {
4492             case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart);
4493             case STATS_LAST: return mLastRealtime;
4494             case STATS_CURRENT: return (curTime-mRealtimeStart);
4495             case STATS_SINCE_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart);
4496         }
4497         return 0;
4498     }
4499 
4500     @Override
computeBatteryUptime(long curTime, int which)4501     public long computeBatteryUptime(long curTime, int which) {
4502         switch (which) {
4503             case STATS_SINCE_CHARGED:
4504                 return mBatteryUptime + getBatteryUptime(curTime);
4505             case STATS_LAST:
4506                 return mBatteryLastUptime;
4507             case STATS_CURRENT:
4508                 return getBatteryUptime(curTime);
4509             case STATS_SINCE_UNPLUGGED:
4510                 return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime;
4511         }
4512         return 0;
4513     }
4514 
4515     @Override
computeBatteryRealtime(long curTime, int which)4516     public long computeBatteryRealtime(long curTime, int which) {
4517         switch (which) {
4518             case STATS_SINCE_CHARGED:
4519                 return mBatteryRealtime + getBatteryRealtimeLocked(curTime);
4520             case STATS_LAST:
4521                 return mBatteryLastRealtime;
4522             case STATS_CURRENT:
4523                 return getBatteryRealtimeLocked(curTime);
4524             case STATS_SINCE_UNPLUGGED:
4525                 return getBatteryRealtimeLocked(curTime) - mUnpluggedBatteryRealtime;
4526         }
4527         return 0;
4528     }
4529 
getBatteryUptimeLocked(long curTime)4530     long getBatteryUptimeLocked(long curTime) {
4531         long time = mTrackBatteryPastUptime;
4532         if (mOnBatteryInternal) {
4533             time += curTime - mTrackBatteryUptimeStart;
4534         }
4535         return time;
4536     }
4537 
getBatteryUptimeLocked()4538     long getBatteryUptimeLocked() {
4539         return getBatteryUptime(SystemClock.uptimeMillis() * 1000);
4540     }
4541 
4542     @Override
getBatteryUptime(long curTime)4543     public long getBatteryUptime(long curTime) {
4544         return getBatteryUptimeLocked(curTime);
4545     }
4546 
getBatteryRealtimeLocked(long curTime)4547     long getBatteryRealtimeLocked(long curTime) {
4548         long time = mTrackBatteryPastRealtime;
4549         if (mOnBatteryInternal) {
4550             time += curTime - mTrackBatteryRealtimeStart;
4551         }
4552         return time;
4553     }
4554 
4555     @Override
getBatteryRealtime(long curTime)4556     public long getBatteryRealtime(long curTime) {
4557         return getBatteryRealtimeLocked(curTime);
4558     }
4559 
getTcpBytes(long current, long[] dataBytes, int which)4560     private long getTcpBytes(long current, long[] dataBytes, int which) {
4561         if (which == STATS_LAST) {
4562             return dataBytes[STATS_LAST];
4563         } else {
4564             if (which == STATS_SINCE_UNPLUGGED) {
4565                 if (dataBytes[STATS_SINCE_UNPLUGGED] < 0) {
4566                     return dataBytes[STATS_LAST];
4567                 } else {
4568                     return current - dataBytes[STATS_SINCE_UNPLUGGED];
4569                 }
4570             } else if (which == STATS_SINCE_CHARGED) {
4571                 return (current - dataBytes[STATS_CURRENT]) + dataBytes[STATS_SINCE_CHARGED];
4572             }
4573             return current - dataBytes[STATS_CURRENT];
4574         }
4575     }
4576 
4577     /** Only STATS_UNPLUGGED works properly */
getMobileTcpBytesSent(int which)4578     public long getMobileTcpBytesSent(int which) {
4579         final long mobileTxBytes = getNetworkStatsSummary().getTotal(null, mMobileIfaces).txBytes;
4580         return getTcpBytes(mobileTxBytes, mMobileDataTx, which);
4581     }
4582 
4583     /** Only STATS_UNPLUGGED works properly */
getMobileTcpBytesReceived(int which)4584     public long getMobileTcpBytesReceived(int which) {
4585         final long mobileRxBytes = getNetworkStatsSummary().getTotal(null, mMobileIfaces).rxBytes;
4586         return getTcpBytes(mobileRxBytes, mMobileDataRx, which);
4587     }
4588 
4589     /** Only STATS_UNPLUGGED works properly */
getTotalTcpBytesSent(int which)4590     public long getTotalTcpBytesSent(int which) {
4591         final long totalTxBytes = getNetworkStatsSummary().getTotal(null).txBytes;
4592         return getTcpBytes(totalTxBytes, mTotalDataTx, which);
4593     }
4594 
4595     /** Only STATS_UNPLUGGED works properly */
getTotalTcpBytesReceived(int which)4596     public long getTotalTcpBytesReceived(int which) {
4597         final long totalRxBytes = getNetworkStatsSummary().getTotal(null).rxBytes;
4598         return getTcpBytes(totalRxBytes, mTotalDataRx, which);
4599     }
4600 
4601     @Override
getDischargeStartLevel()4602     public int getDischargeStartLevel() {
4603         synchronized(this) {
4604             return getDischargeStartLevelLocked();
4605         }
4606     }
4607 
getDischargeStartLevelLocked()4608     public int getDischargeStartLevelLocked() {
4609             return mDischargeUnplugLevel;
4610     }
4611 
4612     @Override
getDischargeCurrentLevel()4613     public int getDischargeCurrentLevel() {
4614         synchronized(this) {
4615             return getDischargeCurrentLevelLocked();
4616         }
4617     }
4618 
getDischargeCurrentLevelLocked()4619     public int getDischargeCurrentLevelLocked() {
4620         return mDischargeCurrentLevel;
4621     }
4622 
4623     @Override
getLowDischargeAmountSinceCharge()4624     public int getLowDischargeAmountSinceCharge() {
4625         synchronized(this) {
4626             int val = mLowDischargeAmountSinceCharge;
4627             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
4628                 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
4629             }
4630             return val;
4631         }
4632     }
4633 
4634     @Override
getHighDischargeAmountSinceCharge()4635     public int getHighDischargeAmountSinceCharge() {
4636         synchronized(this) {
4637             int val = mHighDischargeAmountSinceCharge;
4638             if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
4639                 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
4640             }
4641             return val;
4642         }
4643     }
4644 
getDischargeAmountScreenOn()4645     public int getDischargeAmountScreenOn() {
4646         synchronized(this) {
4647             int val = mDischargeAmountScreenOn;
4648             if (mOnBattery && mScreenOn
4649                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
4650                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
4651             }
4652             return val;
4653         }
4654     }
4655 
getDischargeAmountScreenOnSinceCharge()4656     public int getDischargeAmountScreenOnSinceCharge() {
4657         synchronized(this) {
4658             int val = mDischargeAmountScreenOnSinceCharge;
4659             if (mOnBattery && mScreenOn
4660                     && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
4661                 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
4662             }
4663             return val;
4664         }
4665     }
4666 
getDischargeAmountScreenOff()4667     public int getDischargeAmountScreenOff() {
4668         synchronized(this) {
4669             int val = mDischargeAmountScreenOff;
4670             if (mOnBattery && !mScreenOn
4671                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
4672                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
4673             }
4674             return val;
4675         }
4676     }
4677 
getDischargeAmountScreenOffSinceCharge()4678     public int getDischargeAmountScreenOffSinceCharge() {
4679         synchronized(this) {
4680             int val = mDischargeAmountScreenOffSinceCharge;
4681             if (mOnBattery && !mScreenOn
4682                     && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
4683                 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
4684             }
4685             return val;
4686         }
4687     }
4688 
4689     @Override
getCpuSpeedSteps()4690     public int getCpuSpeedSteps() {
4691         return sNumSpeedSteps;
4692     }
4693 
4694     /**
4695      * Retrieve the statistics object for a particular uid, creating if needed.
4696      */
getUidStatsLocked(int uid)4697     public Uid getUidStatsLocked(int uid) {
4698         Uid u = mUidStats.get(uid);
4699         if (u == null) {
4700             u = new Uid(uid);
4701             mUidStats.put(uid, u);
4702         }
4703         return u;
4704     }
4705 
4706     /**
4707      * Remove the statistics object for a particular uid.
4708      */
removeUidStatsLocked(int uid)4709     public void removeUidStatsLocked(int uid) {
4710         mUidStats.remove(uid);
4711     }
4712 
4713     /**
4714      * Retrieve the statistics object for a particular process, creating
4715      * if needed.
4716      */
getProcessStatsLocked(int uid, String name)4717     public Uid.Proc getProcessStatsLocked(int uid, String name) {
4718         Uid u = getUidStatsLocked(uid);
4719         return u.getProcessStatsLocked(name);
4720     }
4721 
4722     /**
4723      * Retrieve the statistics object for a particular process, given
4724      * the name of the process.
4725      * @param name process name
4726      * @return the statistics object for the process
4727      */
getProcessStatsLocked(String name, int pid)4728     public Uid.Proc getProcessStatsLocked(String name, int pid) {
4729         int uid;
4730         if (mUidCache.containsKey(name)) {
4731             uid = mUidCache.get(name);
4732         } else {
4733             uid = Process.getUidForPid(pid);
4734             mUidCache.put(name, uid);
4735         }
4736         Uid u = getUidStatsLocked(uid);
4737         return u.getProcessStatsLocked(name);
4738     }
4739 
4740     /**
4741      * Retrieve the statistics object for a particular process, creating
4742      * if needed.
4743      */
getPackageStatsLocked(int uid, String pkg)4744     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
4745         Uid u = getUidStatsLocked(uid);
4746         return u.getPackageStatsLocked(pkg);
4747     }
4748 
4749     /**
4750      * Retrieve the statistics object for a particular service, creating
4751      * if needed.
4752      */
getServiceStatsLocked(int uid, String pkg, String name)4753     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
4754         Uid u = getUidStatsLocked(uid);
4755         return u.getServiceStatsLocked(pkg, name);
4756     }
4757 
4758     /**
4759      * Massage data to distribute any reasonable work down to more specific
4760      * owners.  Must only be called on a dead BatteryStats object!
4761      */
distributeWorkLocked(int which)4762     public void distributeWorkLocked(int which) {
4763         // Aggregate all CPU time associated with WIFI.
4764         Uid wifiUid = mUidStats.get(Process.WIFI_UID);
4765         if (wifiUid != null) {
4766             long uSecTime = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which);
4767             for (Uid.Proc proc : wifiUid.mProcessStats.values()) {
4768                 long totalRunningTime = getGlobalWifiRunningTime(uSecTime, which);
4769                 for (int i=0; i<mUidStats.size(); i++) {
4770                     Uid uid = mUidStats.valueAt(i);
4771                     if (uid.mUid != Process.WIFI_UID) {
4772                         long uidRunningTime = uid.getWifiRunningTime(uSecTime, which);
4773                         if (uidRunningTime > 0) {
4774                             Uid.Proc uidProc = uid.getProcessStatsLocked("*wifi*");
4775                             long time = proc.getUserTime(which);
4776                             time = (time*uidRunningTime)/totalRunningTime;
4777                             uidProc.mUserTime += time;
4778                             proc.mUserTime -= time;
4779                             time = proc.getSystemTime(which);
4780                             time = (time*uidRunningTime)/totalRunningTime;
4781                             uidProc.mSystemTime += time;
4782                             proc.mSystemTime -= time;
4783                             time = proc.getForegroundTime(which);
4784                             time = (time*uidRunningTime)/totalRunningTime;
4785                             uidProc.mForegroundTime += time;
4786                             proc.mForegroundTime -= time;
4787                             for (int sb=0; sb<proc.mSpeedBins.length; sb++) {
4788                                 SamplingCounter sc = proc.mSpeedBins[sb];
4789                                 if (sc != null) {
4790                                     time = sc.getCountLocked(which);
4791                                     time = (time*uidRunningTime)/totalRunningTime;
4792                                     SamplingCounter uidSc = uidProc.mSpeedBins[sb];
4793                                     if (uidSc == null) {
4794                                         uidSc = new SamplingCounter(mUnpluggables);
4795                                         uidProc.mSpeedBins[sb] = uidSc;
4796                                     }
4797                                     uidSc.mCount.addAndGet((int)time);
4798                                     sc.mCount.addAndGet((int)-time);
4799                                 }
4800                             }
4801                             totalRunningTime -= uidRunningTime;
4802                         }
4803                     }
4804                 }
4805             }
4806         }
4807     }
4808 
shutdownLocked()4809     public void shutdownLocked() {
4810         writeSyncLocked();
4811         mShuttingDown = true;
4812     }
4813 
4814     Parcel mPendingWrite = null;
4815     final ReentrantLock mWriteLock = new ReentrantLock();
4816 
writeAsyncLocked()4817     public void writeAsyncLocked() {
4818         writeLocked(false);
4819     }
4820 
writeSyncLocked()4821     public void writeSyncLocked() {
4822         writeLocked(true);
4823     }
4824 
writeLocked(boolean sync)4825     void writeLocked(boolean sync) {
4826         if (mFile == null) {
4827             Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
4828             return;
4829         }
4830 
4831         if (mShuttingDown) {
4832             return;
4833         }
4834 
4835         Parcel out = Parcel.obtain();
4836         writeSummaryToParcel(out);
4837         mLastWriteTime = SystemClock.elapsedRealtime();
4838 
4839         if (mPendingWrite != null) {
4840             mPendingWrite.recycle();
4841         }
4842         mPendingWrite = out;
4843 
4844         if (sync) {
4845             commitPendingDataToDisk();
4846         } else {
4847             Thread thr = new Thread("BatteryStats-Write") {
4848                 @Override
4849                 public void run() {
4850                     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
4851                     commitPendingDataToDisk();
4852                 }
4853             };
4854             thr.start();
4855         }
4856     }
4857 
commitPendingDataToDisk()4858     public void commitPendingDataToDisk() {
4859         final Parcel next;
4860         synchronized (this) {
4861             next = mPendingWrite;
4862             mPendingWrite = null;
4863             if (next == null) {
4864                 return;
4865             }
4866 
4867             mWriteLock.lock();
4868         }
4869 
4870         try {
4871             FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
4872             stream.write(next.marshall());
4873             stream.flush();
4874             FileUtils.sync(stream);
4875             stream.close();
4876             mFile.commit();
4877         } catch (IOException e) {
4878             Slog.w("BatteryStats", "Error writing battery statistics", e);
4879             mFile.rollback();
4880         } finally {
4881             next.recycle();
4882             mWriteLock.unlock();
4883         }
4884     }
4885 
readFully(FileInputStream stream)4886     static byte[] readFully(FileInputStream stream) throws java.io.IOException {
4887         int pos = 0;
4888         int avail = stream.available();
4889         byte[] data = new byte[avail];
4890         while (true) {
4891             int amt = stream.read(data, pos, data.length-pos);
4892             //Log.i("foo", "Read " + amt + " bytes at " + pos
4893             //        + " of avail " + data.length);
4894             if (amt <= 0) {
4895                 //Log.i("foo", "**** FINISHED READING: pos=" + pos
4896                 //        + " len=" + data.length);
4897                 return data;
4898             }
4899             pos += amt;
4900             avail = stream.available();
4901             if (avail > data.length-pos) {
4902                 byte[] newData = new byte[pos+avail];
4903                 System.arraycopy(data, 0, newData, 0, pos);
4904                 data = newData;
4905             }
4906         }
4907     }
4908 
readLocked()4909     public void readLocked() {
4910         if (mFile == null) {
4911             Slog.w("BatteryStats", "readLocked: no file associated with this instance");
4912             return;
4913         }
4914 
4915         mUidStats.clear();
4916 
4917         try {
4918             File file = mFile.chooseForRead();
4919             if (!file.exists()) {
4920                 return;
4921             }
4922             FileInputStream stream = new FileInputStream(file);
4923 
4924             byte[] raw = readFully(stream);
4925             Parcel in = Parcel.obtain();
4926             in.unmarshall(raw, 0, raw.length);
4927             in.setDataPosition(0);
4928             stream.close();
4929 
4930             readSummaryFromParcel(in);
4931         } catch(java.io.IOException e) {
4932             Slog.e("BatteryStats", "Error reading battery statistics", e);
4933         }
4934 
4935         long now = SystemClock.elapsedRealtime();
4936         if (USE_OLD_HISTORY) {
4937             addHistoryRecordLocked(now, HistoryItem.CMD_START);
4938         }
4939         addHistoryBufferLocked(now, HistoryItem.CMD_START);
4940     }
4941 
describeContents()4942     public int describeContents() {
4943         return 0;
4944     }
4945 
readHistory(Parcel in, boolean andOldHistory)4946     void readHistory(Parcel in, boolean andOldHistory) {
4947         final long historyBaseTime = in.readLong();
4948 
4949         mHistoryBuffer.setDataSize(0);
4950         mHistoryBuffer.setDataPosition(0);
4951 
4952         int bufSize = in.readInt();
4953         int curPos = in.dataPosition();
4954         if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) {
4955             Slog.w(TAG, "File corrupt: history data buffer too large " + bufSize);
4956         } else if ((bufSize&~3) != bufSize) {
4957             Slog.w(TAG, "File corrupt: history data buffer not aligned " + bufSize);
4958         } else {
4959             if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
4960                     + " bytes at " + curPos);
4961             mHistoryBuffer.appendFrom(in, curPos, bufSize);
4962             in.setDataPosition(curPos + bufSize);
4963         }
4964 
4965         if (andOldHistory) {
4966             readOldHistory(in);
4967         }
4968 
4969         if (DEBUG_HISTORY) {
4970             StringBuilder sb = new StringBuilder(128);
4971             sb.append("****************** OLD mHistoryBaseTime: ");
4972             TimeUtils.formatDuration(mHistoryBaseTime, sb);
4973             Slog.i(TAG, sb.toString());
4974         }
4975         mHistoryBaseTime = historyBaseTime;
4976         if (DEBUG_HISTORY) {
4977             StringBuilder sb = new StringBuilder(128);
4978             sb.append("****************** NEW mHistoryBaseTime: ");
4979             TimeUtils.formatDuration(mHistoryBaseTime, sb);
4980             Slog.i(TAG, sb.toString());
4981         }
4982 
4983         // We are just arbitrarily going to insert 1 minute from the sample of
4984         // the last run until samples in this run.
4985         if (mHistoryBaseTime > 0) {
4986             long oldnow = SystemClock.elapsedRealtime();
4987             mHistoryBaseTime = (mHistoryBaseTime - oldnow) + 60*1000;
4988             if (DEBUG_HISTORY) {
4989                 StringBuilder sb = new StringBuilder(128);
4990                 sb.append("****************** ADJUSTED mHistoryBaseTime: ");
4991                 TimeUtils.formatDuration(mHistoryBaseTime, sb);
4992                 Slog.i(TAG, sb.toString());
4993             }
4994         }
4995     }
4996 
readOldHistory(Parcel in)4997     void readOldHistory(Parcel in) {
4998         if (!USE_OLD_HISTORY) {
4999             return;
5000         }
5001         mHistory = mHistoryEnd = mHistoryCache = null;
5002         long time;
5003         while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
5004             HistoryItem rec = new HistoryItem(time, in);
5005             addHistoryRecordLocked(rec);
5006         }
5007     }
5008 
writeHistory(Parcel out, boolean andOldHistory)5009     void writeHistory(Parcel out, boolean andOldHistory) {
5010         if (DEBUG_HISTORY) {
5011             StringBuilder sb = new StringBuilder(128);
5012             sb.append("****************** WRITING mHistoryBaseTime: ");
5013             TimeUtils.formatDuration(mHistoryBaseTime, sb);
5014             sb.append(" mLastHistoryTime: ");
5015             TimeUtils.formatDuration(mLastHistoryTime, sb);
5016             Slog.i(TAG, sb.toString());
5017         }
5018         out.writeLong(mHistoryBaseTime + mLastHistoryTime);
5019         out.writeInt(mHistoryBuffer.dataSize());
5020         if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
5021                 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
5022         out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
5023 
5024         if (andOldHistory) {
5025             writeOldHistory(out);
5026         }
5027     }
5028 
writeOldHistory(Parcel out)5029     void writeOldHistory(Parcel out) {
5030         if (!USE_OLD_HISTORY) {
5031             return;
5032         }
5033         HistoryItem rec = mHistory;
5034         while (rec != null) {
5035             if (rec.time >= 0) rec.writeToParcel(out, 0);
5036             rec = rec.next;
5037         }
5038         out.writeLong(-1);
5039     }
5040 
readSummaryFromParcel(Parcel in)5041     private void readSummaryFromParcel(Parcel in) {
5042         final int version = in.readInt();
5043         if (version != VERSION) {
5044             Slog.w("BatteryStats", "readFromParcel: version got " + version
5045                 + ", expected " + VERSION + "; erasing old stats");
5046             return;
5047         }
5048 
5049         readHistory(in, true);
5050 
5051         mStartCount = in.readInt();
5052         mBatteryUptime = in.readLong();
5053         mBatteryRealtime = in.readLong();
5054         mUptime = in.readLong();
5055         mRealtime = in.readLong();
5056         mDischargeUnplugLevel = in.readInt();
5057         mDischargeCurrentLevel = in.readInt();
5058         mLowDischargeAmountSinceCharge = in.readInt();
5059         mHighDischargeAmountSinceCharge = in.readInt();
5060         mDischargeAmountScreenOnSinceCharge = in.readInt();
5061         mDischargeAmountScreenOffSinceCharge = in.readInt();
5062 
5063         mStartCount++;
5064 
5065         mScreenOn = false;
5066         mScreenOnTimer.readSummaryFromParcelLocked(in);
5067         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
5068             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
5069         }
5070         mInputEventCounter.readSummaryFromParcelLocked(in);
5071         mPhoneOn = false;
5072         mPhoneOnTimer.readSummaryFromParcelLocked(in);
5073         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
5074             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
5075         }
5076         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
5077         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
5078             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
5079         }
5080         mWifiOn = false;
5081         mWifiOnTimer.readSummaryFromParcelLocked(in);
5082         mGlobalWifiRunning = false;
5083         mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
5084         mBluetoothOn = false;
5085         mBluetoothOnTimer.readSummaryFromParcelLocked(in);
5086 
5087         int NKW = in.readInt();
5088         if (NKW > 10000) {
5089             Slog.w(TAG, "File corrupt: too many kernel wake locks " + NKW);
5090             return;
5091         }
5092         for (int ikw = 0; ikw < NKW; ikw++) {
5093             if (in.readInt() != 0) {
5094                 String kwltName = in.readString();
5095                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
5096             }
5097         }
5098 
5099         sNumSpeedSteps = in.readInt();
5100 
5101         final int NU = in.readInt();
5102         if (NU > 10000) {
5103             Slog.w(TAG, "File corrupt: too many uids " + NU);
5104             return;
5105         }
5106         for (int iu = 0; iu < NU; iu++) {
5107             int uid = in.readInt();
5108             Uid u = new Uid(uid);
5109             mUidStats.put(uid, u);
5110 
5111             u.mWifiRunning = false;
5112             if (in.readInt() != 0) {
5113                 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
5114             }
5115             u.mFullWifiLockOut = false;
5116             if (in.readInt() != 0) {
5117                 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
5118             }
5119             u.mScanWifiLockOut = false;
5120             if (in.readInt() != 0) {
5121                 u.mScanWifiLockTimer.readSummaryFromParcelLocked(in);
5122             }
5123             u.mWifiMulticastEnabled = false;
5124             if (in.readInt() != 0) {
5125                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
5126             }
5127             u.mAudioTurnedOn = false;
5128             if (in.readInt() != 0) {
5129                 u.mAudioTurnedOnTimer.readSummaryFromParcelLocked(in);
5130             }
5131             u.mVideoTurnedOn = false;
5132             if (in.readInt() != 0) {
5133                 u.mVideoTurnedOnTimer.readSummaryFromParcelLocked(in);
5134             }
5135 
5136             if (in.readInt() != 0) {
5137                 if (u.mUserActivityCounters == null) {
5138                     u.initUserActivityLocked();
5139                 }
5140                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
5141                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
5142                 }
5143             }
5144 
5145             int NW = in.readInt();
5146             if (NW > 100) {
5147                 Slog.w(TAG, "File corrupt: too many wake locks " + NW);
5148                 return;
5149             }
5150             for (int iw = 0; iw < NW; iw++) {
5151                 String wlName = in.readString();
5152                 if (in.readInt() != 0) {
5153                     u.getWakeTimerLocked(wlName, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
5154                 }
5155                 if (in.readInt() != 0) {
5156                     u.getWakeTimerLocked(wlName, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
5157                 }
5158                 if (in.readInt() != 0) {
5159                     u.getWakeTimerLocked(wlName, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
5160                 }
5161             }
5162 
5163             int NP = in.readInt();
5164             if (NP > 1000) {
5165                 Slog.w(TAG, "File corrupt: too many sensors " + NP);
5166                 return;
5167             }
5168             for (int is = 0; is < NP; is++) {
5169                 int seNumber = in.readInt();
5170                 if (in.readInt() != 0) {
5171                     u.getSensorTimerLocked(seNumber, true)
5172                             .readSummaryFromParcelLocked(in);
5173                 }
5174             }
5175 
5176             NP = in.readInt();
5177             if (NP > 1000) {
5178                 Slog.w(TAG, "File corrupt: too many processes " + NP);
5179                 return;
5180             }
5181             for (int ip = 0; ip < NP; ip++) {
5182                 String procName = in.readString();
5183                 Uid.Proc p = u.getProcessStatsLocked(procName);
5184                 p.mUserTime = p.mLoadedUserTime = in.readLong();
5185                 p.mSystemTime = p.mLoadedSystemTime = in.readLong();
5186                 p.mStarts = p.mLoadedStarts = in.readInt();
5187                 int NSB = in.readInt();
5188                 if (NSB > 100) {
5189                     Slog.w(TAG, "File corrupt: too many speed bins " + NSB);
5190                     return;
5191                 }
5192                 p.mSpeedBins = new SamplingCounter[NSB];
5193                 for (int i=0; i<NSB; i++) {
5194                     if (in.readInt() != 0) {
5195                         p.mSpeedBins[i] = new SamplingCounter(mUnpluggables);
5196                         p.mSpeedBins[i].readSummaryFromParcelLocked(in);
5197                     }
5198                 }
5199                 if (!p.readExcessivePowerFromParcelLocked(in)) {
5200                     return;
5201                 }
5202             }
5203 
5204             NP = in.readInt();
5205             if (NP > 10000) {
5206                 Slog.w(TAG, "File corrupt: too many packages " + NP);
5207                 return;
5208             }
5209             for (int ip = 0; ip < NP; ip++) {
5210                 String pkgName = in.readString();
5211                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
5212                 p.mWakeups = p.mLoadedWakeups = in.readInt();
5213                 final int NS = in.readInt();
5214                 if (NS > 1000) {
5215                     Slog.w(TAG, "File corrupt: too many services " + NS);
5216                     return;
5217                 }
5218                 for (int is = 0; is < NS; is++) {
5219                     String servName = in.readString();
5220                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
5221                     s.mStartTime = s.mLoadedStartTime = in.readLong();
5222                     s.mStarts = s.mLoadedStarts = in.readInt();
5223                     s.mLaunches = s.mLoadedLaunches = in.readInt();
5224                 }
5225             }
5226 
5227             u.mLoadedTcpBytesReceived = in.readLong();
5228             u.mLoadedTcpBytesSent = in.readLong();
5229         }
5230     }
5231 
5232     /**
5233      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
5234      * disk.  This format does not allow a lossless round-trip.
5235      *
5236      * @param out the Parcel to be written to.
5237      */
writeSummaryToParcel(Parcel out)5238     public void writeSummaryToParcel(Parcel out) {
5239         // Need to update with current kernel wake lock counts.
5240         updateKernelWakelocksLocked();
5241 
5242         final long NOW_SYS = SystemClock.uptimeMillis() * 1000;
5243         final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000;
5244         final long NOW = getBatteryUptimeLocked(NOW_SYS);
5245         final long NOWREAL = getBatteryRealtimeLocked(NOWREAL_SYS);
5246 
5247         out.writeInt(VERSION);
5248 
5249         writeHistory(out, true);
5250 
5251         out.writeInt(mStartCount);
5252         out.writeLong(computeBatteryUptime(NOW_SYS, STATS_SINCE_CHARGED));
5253         out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
5254         out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
5255         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
5256         out.writeInt(mDischargeUnplugLevel);
5257         out.writeInt(mDischargeCurrentLevel);
5258         out.writeInt(getLowDischargeAmountSinceCharge());
5259         out.writeInt(getHighDischargeAmountSinceCharge());
5260         out.writeInt(getDischargeAmountScreenOnSinceCharge());
5261         out.writeInt(getDischargeAmountScreenOffSinceCharge());
5262 
5263         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
5264         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
5265             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
5266         }
5267         mInputEventCounter.writeSummaryFromParcelLocked(out);
5268         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
5269         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
5270             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
5271         }
5272         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
5273         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
5274             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
5275         }
5276         mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
5277         mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
5278         mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
5279 
5280         out.writeInt(mKernelWakelockStats.size());
5281         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
5282             Timer kwlt = ent.getValue();
5283             if (kwlt != null) {
5284                 out.writeInt(1);
5285                 out.writeString(ent.getKey());
5286                 ent.getValue().writeSummaryFromParcelLocked(out, NOWREAL);
5287             } else {
5288                 out.writeInt(0);
5289             }
5290         }
5291 
5292         out.writeInt(sNumSpeedSteps);
5293         final int NU = mUidStats.size();
5294         out.writeInt(NU);
5295         for (int iu = 0; iu < NU; iu++) {
5296             out.writeInt(mUidStats.keyAt(iu));
5297             Uid u = mUidStats.valueAt(iu);
5298 
5299             if (u.mWifiRunningTimer != null) {
5300                 out.writeInt(1);
5301                 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
5302             } else {
5303                 out.writeInt(0);
5304             }
5305             if (u.mFullWifiLockTimer != null) {
5306                 out.writeInt(1);
5307                 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
5308             } else {
5309                 out.writeInt(0);
5310             }
5311             if (u.mScanWifiLockTimer != null) {
5312                 out.writeInt(1);
5313                 u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
5314             } else {
5315                 out.writeInt(0);
5316             }
5317             if (u.mWifiMulticastTimer != null) {
5318                 out.writeInt(1);
5319                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL);
5320             } else {
5321                 out.writeInt(0);
5322             }
5323             if (u.mAudioTurnedOnTimer != null) {
5324                 out.writeInt(1);
5325                 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
5326             } else {
5327                 out.writeInt(0);
5328             }
5329             if (u.mVideoTurnedOnTimer != null) {
5330                 out.writeInt(1);
5331                 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
5332             } else {
5333                 out.writeInt(0);
5334             }
5335 
5336             if (u.mUserActivityCounters == null) {
5337                 out.writeInt(0);
5338             } else {
5339                 out.writeInt(1);
5340                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
5341                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
5342                 }
5343             }
5344 
5345             int NW = u.mWakelockStats.size();
5346             out.writeInt(NW);
5347             if (NW > 0) {
5348                 for (Map.Entry<String, BatteryStatsImpl.Uid.Wakelock> ent
5349                         : u.mWakelockStats.entrySet()) {
5350                     out.writeString(ent.getKey());
5351                     Uid.Wakelock wl = ent.getValue();
5352                     if (wl.mTimerFull != null) {
5353                         out.writeInt(1);
5354                         wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL);
5355                     } else {
5356                         out.writeInt(0);
5357                     }
5358                     if (wl.mTimerPartial != null) {
5359                         out.writeInt(1);
5360                         wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL);
5361                     } else {
5362                         out.writeInt(0);
5363                     }
5364                     if (wl.mTimerWindow != null) {
5365                         out.writeInt(1);
5366                         wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL);
5367                     } else {
5368                         out.writeInt(0);
5369                     }
5370                 }
5371             }
5372 
5373             int NSE = u.mSensorStats.size();
5374             out.writeInt(NSE);
5375             if (NSE > 0) {
5376                 for (Map.Entry<Integer, BatteryStatsImpl.Uid.Sensor> ent
5377                         : u.mSensorStats.entrySet()) {
5378                     out.writeInt(ent.getKey());
5379                     Uid.Sensor se = ent.getValue();
5380                     if (se.mTimer != null) {
5381                         out.writeInt(1);
5382                         se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL);
5383                     } else {
5384                         out.writeInt(0);
5385                     }
5386                 }
5387             }
5388 
5389             int NP = u.mProcessStats.size();
5390             out.writeInt(NP);
5391             if (NP > 0) {
5392                 for (Map.Entry<String, BatteryStatsImpl.Uid.Proc> ent
5393                     : u.mProcessStats.entrySet()) {
5394                     out.writeString(ent.getKey());
5395                     Uid.Proc ps = ent.getValue();
5396                     out.writeLong(ps.mUserTime);
5397                     out.writeLong(ps.mSystemTime);
5398                     out.writeInt(ps.mStarts);
5399                     final int N = ps.mSpeedBins.length;
5400                     out.writeInt(N);
5401                     for (int i=0; i<N; i++) {
5402                         if (ps.mSpeedBins[i] != null) {
5403                             out.writeInt(1);
5404                             ps.mSpeedBins[i].writeSummaryFromParcelLocked(out);
5405                         } else {
5406                             out.writeInt(0);
5407                         }
5408                     }
5409                     ps.writeExcessivePowerToParcelLocked(out);
5410                 }
5411             }
5412 
5413             NP = u.mPackageStats.size();
5414             out.writeInt(NP);
5415             if (NP > 0) {
5416                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
5417                     : u.mPackageStats.entrySet()) {
5418                     out.writeString(ent.getKey());
5419                     Uid.Pkg ps = ent.getValue();
5420                     out.writeInt(ps.mWakeups);
5421                     final int NS = ps.mServiceStats.size();
5422                     out.writeInt(NS);
5423                     if (NS > 0) {
5424                         for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent
5425                                 : ps.mServiceStats.entrySet()) {
5426                             out.writeString(sent.getKey());
5427                             BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue();
5428                             long time = ss.getStartTimeToNowLocked(NOW);
5429                             out.writeLong(time);
5430                             out.writeInt(ss.mStarts);
5431                             out.writeInt(ss.mLaunches);
5432                         }
5433                     }
5434                 }
5435             }
5436 
5437             out.writeLong(u.getTcpBytesReceived(STATS_SINCE_CHARGED));
5438             out.writeLong(u.getTcpBytesSent(STATS_SINCE_CHARGED));
5439         }
5440     }
5441 
readFromParcel(Parcel in)5442     public void readFromParcel(Parcel in) {
5443         readFromParcelLocked(in);
5444     }
5445 
readFromParcelLocked(Parcel in)5446     void readFromParcelLocked(Parcel in) {
5447         int magic = in.readInt();
5448         if (magic != MAGIC) {
5449             throw new ParcelFormatException("Bad magic number");
5450         }
5451 
5452         readHistory(in, false);
5453 
5454         mStartCount = in.readInt();
5455         mBatteryUptime = in.readLong();
5456         mBatteryLastUptime = 0;
5457         mBatteryRealtime = in.readLong();
5458         mBatteryLastRealtime = 0;
5459         mScreenOn = false;
5460         mScreenOnTimer = new StopwatchTimer(null, -1, null, mUnpluggables, in);
5461         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
5462             mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i,
5463                     null, mUnpluggables, in);
5464         }
5465         mInputEventCounter = new Counter(mUnpluggables, in);
5466         mPhoneOn = false;
5467         mPhoneOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
5468         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
5469             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i,
5470                     null, mUnpluggables, in);
5471         }
5472         mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mUnpluggables, in);
5473         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
5474             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i,
5475                     null, mUnpluggables, in);
5476         }
5477         mWifiOn = false;
5478         mWifiOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
5479         mGlobalWifiRunning = false;
5480         mGlobalWifiRunningTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
5481         mBluetoothOn = false;
5482         mBluetoothOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
5483         mUptime = in.readLong();
5484         mUptimeStart = in.readLong();
5485         mLastUptime = 0;
5486         mRealtime = in.readLong();
5487         mRealtimeStart = in.readLong();
5488         mLastRealtime = 0;
5489         mOnBattery = in.readInt() != 0;
5490         mOnBatteryInternal = false; // we are no longer really running.
5491         mTrackBatteryPastUptime = in.readLong();
5492         mTrackBatteryUptimeStart = in.readLong();
5493         mTrackBatteryPastRealtime = in.readLong();
5494         mTrackBatteryRealtimeStart = in.readLong();
5495         mUnpluggedBatteryUptime = in.readLong();
5496         mUnpluggedBatteryRealtime = in.readLong();
5497         mDischargeUnplugLevel = in.readInt();
5498         mDischargeCurrentLevel = in.readInt();
5499         mLowDischargeAmountSinceCharge = in.readInt();
5500         mHighDischargeAmountSinceCharge = in.readInt();
5501         mDischargeAmountScreenOn = in.readInt();
5502         mDischargeAmountScreenOnSinceCharge = in.readInt();
5503         mDischargeAmountScreenOff = in.readInt();
5504         mDischargeAmountScreenOffSinceCharge = in.readInt();
5505         mLastWriteTime = in.readLong();
5506 
5507         mMobileDataRx[STATS_LAST] = in.readLong();
5508         mMobileDataRx[STATS_SINCE_UNPLUGGED] = -1;
5509         mMobileDataTx[STATS_LAST] = in.readLong();
5510         mMobileDataTx[STATS_SINCE_UNPLUGGED] = -1;
5511         mTotalDataRx[STATS_LAST] = in.readLong();
5512         mTotalDataRx[STATS_SINCE_UNPLUGGED] = -1;
5513         mTotalDataTx[STATS_LAST] = in.readLong();
5514         mTotalDataTx[STATS_SINCE_UNPLUGGED] = -1;
5515 
5516         mRadioDataUptime = in.readLong();
5517         mRadioDataStart = -1;
5518 
5519         mBluetoothPingCount = in.readInt();
5520         mBluetoothPingStart = -1;
5521 
5522         mKernelWakelockStats.clear();
5523         int NKW = in.readInt();
5524         for (int ikw = 0; ikw < NKW; ikw++) {
5525             if (in.readInt() != 0) {
5526                 String wakelockName = in.readString();
5527                 in.readInt(); // Extra 0/1 written by Timer.writeTimerToParcel
5528                 SamplingTimer kwlt = new SamplingTimer(mUnpluggables, mOnBattery, in);
5529                 mKernelWakelockStats.put(wakelockName, kwlt);
5530             }
5531         }
5532 
5533         mPartialTimers.clear();
5534         mFullTimers.clear();
5535         mWindowTimers.clear();
5536         mWifiRunningTimers.clear();
5537         mFullWifiLockTimers.clear();
5538         mScanWifiLockTimers.clear();
5539         mWifiMulticastTimers.clear();
5540 
5541         sNumSpeedSteps = in.readInt();
5542 
5543         int numUids = in.readInt();
5544         mUidStats.clear();
5545         for (int i = 0; i < numUids; i++) {
5546             int uid = in.readInt();
5547             Uid u = new Uid(uid);
5548             u.readFromParcelLocked(mUnpluggables, in);
5549             mUidStats.append(uid, u);
5550         }
5551     }
5552 
writeToParcel(Parcel out, int flags)5553     public void writeToParcel(Parcel out, int flags) {
5554         writeToParcelLocked(out, true, flags);
5555     }
5556 
writeToParcelWithoutUids(Parcel out, int flags)5557     public void writeToParcelWithoutUids(Parcel out, int flags) {
5558         writeToParcelLocked(out, false, flags);
5559     }
5560 
5561     @SuppressWarnings("unused")
writeToParcelLocked(Parcel out, boolean inclUids, int flags)5562     void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
5563         // Need to update with current kernel wake lock counts.
5564         updateKernelWakelocksLocked();
5565 
5566         final long uSecUptime = SystemClock.uptimeMillis() * 1000;
5567         final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
5568         final long batteryUptime = getBatteryUptimeLocked(uSecUptime);
5569         final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime);
5570 
5571         out.writeInt(MAGIC);
5572 
5573         writeHistory(out, false);
5574 
5575         out.writeInt(mStartCount);
5576         out.writeLong(mBatteryUptime);
5577         out.writeLong(mBatteryRealtime);
5578         mScreenOnTimer.writeToParcel(out, batteryRealtime);
5579         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
5580             mScreenBrightnessTimer[i].writeToParcel(out, batteryRealtime);
5581         }
5582         mInputEventCounter.writeToParcel(out);
5583         mPhoneOnTimer.writeToParcel(out, batteryRealtime);
5584         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
5585             mPhoneSignalStrengthsTimer[i].writeToParcel(out, batteryRealtime);
5586         }
5587         mPhoneSignalScanningTimer.writeToParcel(out, batteryRealtime);
5588         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
5589             mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime);
5590         }
5591         mWifiOnTimer.writeToParcel(out, batteryRealtime);
5592         mGlobalWifiRunningTimer.writeToParcel(out, batteryRealtime);
5593         mBluetoothOnTimer.writeToParcel(out, batteryRealtime);
5594         out.writeLong(mUptime);
5595         out.writeLong(mUptimeStart);
5596         out.writeLong(mRealtime);
5597         out.writeLong(mRealtimeStart);
5598         out.writeInt(mOnBattery ? 1 : 0);
5599         out.writeLong(batteryUptime);
5600         out.writeLong(mTrackBatteryUptimeStart);
5601         out.writeLong(batteryRealtime);
5602         out.writeLong(mTrackBatteryRealtimeStart);
5603         out.writeLong(mUnpluggedBatteryUptime);
5604         out.writeLong(mUnpluggedBatteryRealtime);
5605         out.writeInt(mDischargeUnplugLevel);
5606         out.writeInt(mDischargeCurrentLevel);
5607         out.writeInt(mLowDischargeAmountSinceCharge);
5608         out.writeInt(mHighDischargeAmountSinceCharge);
5609         out.writeInt(mDischargeAmountScreenOn);
5610         out.writeInt(mDischargeAmountScreenOnSinceCharge);
5611         out.writeInt(mDischargeAmountScreenOff);
5612         out.writeInt(mDischargeAmountScreenOffSinceCharge);
5613         out.writeLong(mLastWriteTime);
5614 
5615         out.writeLong(getMobileTcpBytesReceived(STATS_SINCE_UNPLUGGED));
5616         out.writeLong(getMobileTcpBytesSent(STATS_SINCE_UNPLUGGED));
5617         out.writeLong(getTotalTcpBytesReceived(STATS_SINCE_UNPLUGGED));
5618         out.writeLong(getTotalTcpBytesSent(STATS_SINCE_UNPLUGGED));
5619 
5620         // Write radio uptime for data
5621         out.writeLong(getRadioDataUptime());
5622 
5623         out.writeInt(getBluetoothPingCount());
5624 
5625         if (inclUids) {
5626             out.writeInt(mKernelWakelockStats.size());
5627             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
5628                 SamplingTimer kwlt = ent.getValue();
5629                 if (kwlt != null) {
5630                     out.writeInt(1);
5631                     out.writeString(ent.getKey());
5632                     Timer.writeTimerToParcel(out, kwlt, batteryRealtime);
5633                 } else {
5634                     out.writeInt(0);
5635                 }
5636             }
5637         } else {
5638             out.writeInt(0);
5639         }
5640 
5641         out.writeInt(sNumSpeedSteps);
5642 
5643         if (inclUids) {
5644             int size = mUidStats.size();
5645             out.writeInt(size);
5646             for (int i = 0; i < size; i++) {
5647                 out.writeInt(mUidStats.keyAt(i));
5648                 Uid uid = mUidStats.valueAt(i);
5649 
5650                 uid.writeToParcelLocked(out, batteryRealtime);
5651             }
5652         } else {
5653             out.writeInt(0);
5654         }
5655     }
5656 
5657     public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
5658         new Parcelable.Creator<BatteryStatsImpl>() {
5659         public BatteryStatsImpl createFromParcel(Parcel in) {
5660             return new BatteryStatsImpl(in);
5661         }
5662 
5663         public BatteryStatsImpl[] newArray(int size) {
5664             return new BatteryStatsImpl[size];
5665         }
5666     };
5667 
prepareForDumpLocked()5668     public void prepareForDumpLocked() {
5669         // Need to retrieve current kernel wake lock stats before printing.
5670         updateKernelWakelocksLocked();
5671     }
5672 
dumpLocked(PrintWriter pw)5673     public void dumpLocked(PrintWriter pw) {
5674         if (DEBUG) {
5675             Printer pr = new PrintWriterPrinter(pw);
5676             pr.println("*** Screen timer:");
5677             mScreenOnTimer.logState(pr, "  ");
5678             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
5679                 pr.println("*** Screen brightness #" + i + ":");
5680                 mScreenBrightnessTimer[i].logState(pr, "  ");
5681             }
5682             pr.println("*** Input event counter:");
5683             mInputEventCounter.logState(pr, "  ");
5684             pr.println("*** Phone timer:");
5685             mPhoneOnTimer.logState(pr, "  ");
5686             for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
5687                 pr.println("*** Signal strength #" + i + ":");
5688                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
5689             }
5690             pr.println("*** Signal scanning :");
5691             mPhoneSignalScanningTimer.logState(pr, "  ");
5692             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
5693                 pr.println("*** Data connection type #" + i + ":");
5694                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
5695             }
5696             pr.println("*** Wifi timer:");
5697             mWifiOnTimer.logState(pr, "  ");
5698             pr.println("*** WifiRunning timer:");
5699             mGlobalWifiRunningTimer.logState(pr, "  ");
5700             pr.println("*** Bluetooth timer:");
5701             mBluetoothOnTimer.logState(pr, "  ");
5702             pr.println("*** Mobile ifaces:");
5703             pr.println(mMobileIfaces.toString());
5704         }
5705         super.dumpLocked(pw);
5706     }
5707 
5708     private NetworkStats mNetworkSummaryCache;
5709     private NetworkStats mNetworkDetailCache;
5710 
getNetworkStatsSummary()5711     private NetworkStats getNetworkStatsSummary() {
5712         // NOTE: calls from BatteryStatsService already hold this lock
5713         synchronized (this) {
5714             if (mNetworkSummaryCache == null
5715                     || mNetworkSummaryCache.getElapsedRealtimeAge() > SECOND_IN_MILLIS) {
5716                 try {
5717                     mNetworkSummaryCache = mNetworkStatsFactory.readNetworkStatsSummary();
5718                 } catch (IllegalStateException e) {
5719                     // log problem and return empty object
5720                     Log.wtf(TAG, "problem reading network stats", e);
5721                     mNetworkSummaryCache = new NetworkStats(SystemClock.elapsedRealtime(), 0);
5722                 }
5723             }
5724             return mNetworkSummaryCache;
5725         }
5726     }
5727 
getNetworkStatsDetailGroupedByUid()5728     private NetworkStats getNetworkStatsDetailGroupedByUid() {
5729         // NOTE: calls from BatteryStatsService already hold this lock
5730         synchronized (this) {
5731             if (mNetworkDetailCache == null
5732                     || mNetworkDetailCache.getElapsedRealtimeAge() > SECOND_IN_MILLIS) {
5733                 try {
5734                     mNetworkDetailCache = mNetworkStatsFactory
5735                             .readNetworkStatsDetail().groupedByUid();
5736                 } catch (IllegalStateException e) {
5737                     // log problem and return empty object
5738                     Log.wtf(TAG, "problem reading network stats", e);
5739                     mNetworkDetailCache = new NetworkStats(SystemClock.elapsedRealtime(), 0);
5740                 }
5741             }
5742             return mNetworkDetailCache;
5743         }
5744     }
5745 }
5746