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