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