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
17package com.android.internal.os;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.app.ActivityManager;
22import android.bluetooth.BluetoothActivityEnergyInfo;
23import android.bluetooth.UidTraffic;
24import android.content.BroadcastReceiver;
25import android.content.ContentResolver;
26import android.content.Context;
27import android.content.Intent;
28import android.content.IntentFilter;
29import android.database.ContentObserver;
30import android.hardware.usb.UsbManager;
31import android.net.ConnectivityManager;
32import android.net.NetworkStats;
33import android.net.Uri;
34import android.net.wifi.WifiActivityEnergyInfo;
35import android.net.wifi.WifiManager;
36import android.os.BatteryManager;
37import android.os.BatteryStats;
38import android.os.Build;
39import android.os.FileUtils;
40import android.os.Handler;
41import android.os.IBatteryPropertiesRegistrar;
42import android.os.Looper;
43import android.os.Message;
44import android.os.OsProtoEnums;
45import android.os.Parcel;
46import android.os.ParcelFormatException;
47import android.os.Parcelable;
48import android.os.PowerManager;
49import android.os.Process;
50import android.os.RemoteException;
51import android.os.ServiceManager;
52import android.os.SystemClock;
53import android.os.UserHandle;
54import android.os.WorkSource;
55import android.os.WorkSource.WorkChain;
56import android.os.connectivity.CellularBatteryStats;
57import android.os.connectivity.GpsBatteryStats;
58import android.os.connectivity.WifiBatteryStats;
59import android.provider.Settings;
60import android.telephony.DataConnectionRealTimeInfo;
61import android.telephony.ModemActivityInfo;
62import android.telephony.ServiceState;
63import android.telephony.SignalStrength;
64import android.telephony.TelephonyManager;
65import android.text.TextUtils;
66import android.util.ArrayMap;
67import android.util.IntArray;
68import android.util.KeyValueListParser;
69import android.util.Log;
70import android.util.LogWriter;
71import android.util.LongSparseArray;
72import android.util.LongSparseLongArray;
73import android.util.MutableInt;
74import android.util.Pools;
75import android.util.PrintWriterPrinter;
76import android.util.Printer;
77import android.util.Slog;
78import android.util.SparseArray;
79import android.util.SparseIntArray;
80import android.util.SparseLongArray;
81import android.util.StatsLog;
82import android.util.TimeUtils;
83import android.util.Xml;
84import android.view.Display;
85
86import com.android.internal.annotations.GuardedBy;
87import com.android.internal.annotations.VisibleForTesting;
88import com.android.internal.location.gnssmetrics.GnssMetrics;
89import com.android.internal.net.NetworkStatsFactory;
90import com.android.internal.util.ArrayUtils;
91import com.android.internal.util.FastPrintWriter;
92import com.android.internal.util.FastXmlSerializer;
93import com.android.internal.util.JournaledFile;
94import com.android.internal.util.XmlUtils;
95
96import libcore.util.EmptyArray;
97
98import org.xmlpull.v1.XmlPullParser;
99import org.xmlpull.v1.XmlPullParserException;
100import org.xmlpull.v1.XmlSerializer;
101
102import java.io.ByteArrayOutputStream;
103import java.io.File;
104import java.io.FileInputStream;
105import java.io.FileNotFoundException;
106import java.io.FileOutputStream;
107import java.io.IOException;
108import java.io.PrintWriter;
109import java.nio.charset.StandardCharsets;
110import java.util.ArrayList;
111import java.util.Arrays;
112import java.util.Calendar;
113import java.util.HashMap;
114import java.util.Iterator;
115import java.util.LinkedList;
116import java.util.List;
117import java.util.Map;
118import java.util.Queue;
119import java.util.concurrent.Future;
120import java.util.concurrent.atomic.AtomicInteger;
121import java.util.concurrent.locks.ReentrantLock;
122
123/**
124 * All information we are collecting about things that can happen that impact
125 * battery life.  All times are represented in microseconds except where indicated
126 * otherwise.
127 */
128public class BatteryStatsImpl extends BatteryStats {
129    private static final String TAG = "BatteryStatsImpl";
130    private static final boolean DEBUG = false;
131    public static final boolean DEBUG_ENERGY = false;
132    private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
133    private static final boolean DEBUG_MEMORY = false;
134    private static final boolean DEBUG_HISTORY = false;
135    private static final boolean USE_OLD_HISTORY = false;   // for debugging.
136
137    // TODO: remove "tcp" from network methods, since we measure total stats.
138
139    // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
140    private static final int MAGIC = 0xBA757475; // 'BATSTATS'
141
142    // Current on-disk Parcel version
143    private static final int VERSION = 177 + (USE_OLD_HISTORY ? 1000 : 0);
144
145    // Maximum number of items we will record in the history.
146    private static final int MAX_HISTORY_ITEMS;
147
148    // No, really, THIS is the maximum number of items we will record in the history.
149    private static final int MAX_MAX_HISTORY_ITEMS;
150
151    // The maximum number of names wakelocks we will keep track of
152    // per uid; once the limit is reached, we batch the remaining wakelocks
153    // in to one common name.
154    private static final int MAX_WAKELOCKS_PER_UID;
155
156    static final int MAX_HISTORY_BUFFER; // 256KB
157    static final int MAX_MAX_HISTORY_BUFFER; // 320KB
158
159    static {
160        if (ActivityManager.isLowRamDeviceStatic()) {
161            MAX_HISTORY_ITEMS = 800;
162            MAX_MAX_HISTORY_ITEMS = 1200;
163            MAX_WAKELOCKS_PER_UID = 40;
164            MAX_HISTORY_BUFFER = 96*1024;  // 96KB
165            MAX_MAX_HISTORY_BUFFER = 128*1024; // 128KB
166        } else {
167            MAX_HISTORY_ITEMS = 4000;
168            MAX_MAX_HISTORY_ITEMS = 6000;
169            MAX_WAKELOCKS_PER_UID = 200;
170            MAX_HISTORY_BUFFER = 512*1024;  // 512KB
171            MAX_MAX_HISTORY_BUFFER = 640*1024;  // 640KB
172        }
173    }
174
175    // Number of transmit power states the Wifi controller can be in.
176    private static final int NUM_WIFI_TX_LEVELS = 1;
177
178    // Number of transmit power states the Bluetooth controller can be in.
179    private static final int NUM_BT_TX_LEVELS = 1;
180
181    /**
182     * Holding a wakelock costs more than just using the cpu.
183     * Currently, we assign only half the cpu time to an app that is running but
184     * not holding a wakelock. The apps holding wakelocks get the rest of the blame.
185     * If no app is holding a wakelock, then the distribution is normal.
186     */
187    @VisibleForTesting
188    public static final int WAKE_LOCK_WEIGHT = 50;
189
190    protected Clocks mClocks;
191
192    private final JournaledFile mFile;
193    public final AtomicFile mCheckinFile;
194    public final AtomicFile mDailyFile;
195
196    static final int MSG_REPORT_CPU_UPDATE_NEEDED = 1;
197    static final int MSG_REPORT_POWER_CHANGE = 2;
198    static final int MSG_REPORT_CHARGING = 3;
199    static final int MSG_REPORT_RESET_STATS = 4;
200    static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
201
202    private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
203    private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
204
205    @VisibleForTesting
206    protected KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader();
207    @VisibleForTesting
208    protected KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
209    @VisibleForTesting
210    protected KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader =
211            new KernelUidCpuFreqTimeReader();
212    @VisibleForTesting
213    protected KernelUidCpuActiveTimeReader mKernelUidCpuActiveTimeReader =
214            new KernelUidCpuActiveTimeReader();
215    @VisibleForTesting
216    protected KernelUidCpuClusterTimeReader mKernelUidCpuClusterTimeReader =
217            new KernelUidCpuClusterTimeReader();
218    @VisibleForTesting
219    protected KernelSingleUidTimeReader mKernelSingleUidTimeReader;
220
221    private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats
222            = new KernelMemoryBandwidthStats();
223    private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>();
224    public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
225        return mKernelMemoryStats;
226    }
227
228    @GuardedBy("this")
229    public boolean mPerProcStateCpuTimesAvailable = true;
230
231    /**
232     * Uids for which per-procstate cpu times need to be updated.
233     *
234     * Contains uid -> procState mappings.
235     */
236    @GuardedBy("this")
237    @VisibleForTesting
238    protected final SparseIntArray mPendingUids = new SparseIntArray();
239
240    @GuardedBy("this")
241    private long mNumSingleUidCpuTimeReads;
242    @GuardedBy("this")
243    private long mNumBatchedSingleUidCpuTimeReads;
244    @GuardedBy("this")
245    private long mCpuTimeReadsTrackingStartTime = SystemClock.uptimeMillis();
246    @GuardedBy("this")
247    private int mNumUidsRemoved;
248    @GuardedBy("this")
249    private int mNumAllUidCpuTimeReads;
250
251    /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
252    private final RpmStats mTmpRpmStats = new RpmStats();
253    /** The soonest the RPM stats can be updated after it was last updated. */
254    private static final long RPM_STATS_UPDATE_FREQ_MS = 1000;
255    /** Last time that RPM stats were updated by updateRpmStatsLocked. */
256    private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
257    /**
258     * Use a queue to delay removing UIDs from {@link KernelUidCpuTimeReader},
259     * {@link KernelUidCpuActiveTimeReader}, {@link KernelUidCpuClusterTimeReader},
260     * {@link KernelUidCpuFreqTimeReader} and from the Kernel.
261     *
262     * Isolated and invalid UID info must be removed to conserve memory. However, STATSD and
263     * Batterystats both need to access UID cpu time. To resolve this race condition, only
264     * Batterystats shall remove UIDs, and a delay {@link Constants#UID_REMOVE_DELAY_MS} is
265     * implemented so that STATSD can capture those UID times before they are deleted.
266     */
267    @GuardedBy("this")
268    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
269    protected Queue<UidToRemove> mPendingRemovedUids = new LinkedList<>();
270
271    @VisibleForTesting
272    public final class UidToRemove {
273        int startUid;
274        int endUid;
275        long timeAddedInQueue;
276
277        /** Remove just one UID */
278        public UidToRemove(int uid, long timestamp) {
279            this(uid, uid, timestamp);
280        }
281
282        /** Remove a range of UIDs, startUid must be smaller than endUid. */
283        public UidToRemove(int startUid, int endUid, long timestamp) {
284            this.startUid = startUid;
285            this.endUid = endUid;
286            timeAddedInQueue = timestamp;
287        }
288
289        void remove() {
290            if (startUid == endUid) {
291                mKernelUidCpuTimeReader.removeUid(startUid);
292                mKernelUidCpuFreqTimeReader.removeUid(startUid);
293                if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
294                    mKernelUidCpuActiveTimeReader.removeUid(startUid);
295                    mKernelUidCpuClusterTimeReader.removeUid(startUid);
296                }
297                if (mKernelSingleUidTimeReader != null) {
298                    mKernelSingleUidTimeReader.removeUid(startUid);
299                }
300                mNumUidsRemoved++;
301            } else if (startUid < endUid) {
302                mKernelUidCpuFreqTimeReader.removeUidsInRange(startUid, endUid);
303                mKernelUidCpuTimeReader.removeUidsInRange(startUid, endUid);
304                if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
305                    mKernelUidCpuActiveTimeReader.removeUidsInRange(startUid, endUid);
306                    mKernelUidCpuClusterTimeReader.removeUidsInRange(startUid, endUid);
307                }
308                if (mKernelSingleUidTimeReader != null) {
309                    mKernelSingleUidTimeReader.removeUidsInRange(startUid, endUid);
310                }
311                // Treat as one. We don't know how many uids there are in between.
312                mNumUidsRemoved++;
313            } else {
314                Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
315            }
316        }
317    }
318
319    public interface BatteryCallback {
320        public void batteryNeedsCpuUpdate();
321        public void batteryPowerChanged(boolean onBattery);
322        public void batterySendBroadcast(Intent intent);
323        public void batteryStatsReset();
324    }
325
326    public interface PlatformIdleStateCallback {
327        public void fillLowPowerStats(RpmStats rpmStats);
328        public String getPlatformLowPowerStats();
329        public String getSubsystemLowPowerStats();
330    }
331
332    public static abstract class UserInfoProvider {
333        private int[] userIds;
334        protected abstract @Nullable int[] getUserIds();
335        @VisibleForTesting
336        public final void refreshUserIds() {
337            userIds = getUserIds();
338        }
339        @VisibleForTesting
340        public boolean exists(int userId) {
341            return userIds != null ? ArrayUtils.contains(userIds, userId) : true;
342        }
343    }
344
345    private final PlatformIdleStateCallback mPlatformIdleStateCallback;
346
347    final class MyHandler extends Handler {
348        public MyHandler(Looper looper) {
349            super(looper, null, true);
350        }
351
352        @Override
353        public void handleMessage(Message msg) {
354            BatteryCallback cb = mCallback;
355            switch (msg.what) {
356                case MSG_REPORT_CPU_UPDATE_NEEDED:
357                    if (cb != null) {
358                        cb.batteryNeedsCpuUpdate();
359                    }
360                    break;
361                case MSG_REPORT_POWER_CHANGE:
362                    if (cb != null) {
363                        cb.batteryPowerChanged(msg.arg1 != 0);
364                    }
365                    break;
366                case MSG_REPORT_CHARGING:
367                    if (cb != null) {
368                        final String action;
369                        synchronized (BatteryStatsImpl.this) {
370                            action = mCharging ? BatteryManager.ACTION_CHARGING
371                                    : BatteryManager.ACTION_DISCHARGING;
372                        }
373                        Intent intent = new Intent(action);
374                        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
375                        cb.batterySendBroadcast(intent);
376                    }
377                    break;
378                case MSG_REPORT_RESET_STATS:
379                    if (cb != null) {
380                        cb.batteryStatsReset();
381                    }
382                }
383        }
384    }
385
386    public void postBatteryNeedsCpuUpdateMsg() {
387        mHandler.sendEmptyMessage(MSG_REPORT_CPU_UPDATE_NEEDED);
388    }
389
390    /**
391     * Update per-freq cpu times for all the uids in {@link #mPendingUids}.
392     */
393    public void updateProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
394        final SparseIntArray uidStates;
395        synchronized (BatteryStatsImpl.this) {
396            if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
397                return;
398            }
399            if(!initKernelSingleUidTimeReaderLocked()) {
400                return;
401            }
402            // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
403            // compute deltas since it might result in mis-attributing cpu times to wrong states.
404            if (mKernelSingleUidTimeReader.hasStaleData()) {
405                mPendingUids.clear();
406                return;
407            }
408
409            if (mPendingUids.size() == 0) {
410                return;
411            }
412            uidStates = mPendingUids.clone();
413            mPendingUids.clear();
414        }
415        for (int i = uidStates.size() - 1; i >= 0; --i) {
416            final int uid = uidStates.keyAt(i);
417            final int procState = uidStates.valueAt(i);
418            final int[] isolatedUids;
419            final Uid u;
420            synchronized (BatteryStatsImpl.this) {
421                // It's possible that uid no longer exists and any internal references have
422                // already been deleted, so using {@link #getAvailableUidStatsLocked} to avoid
423                // creating an UidStats object if it doesn't already exist.
424                u = getAvailableUidStatsLocked(uid);
425                if (u == null) {
426                    continue;
427                }
428                if (u.mChildUids == null) {
429                    isolatedUids = null;
430                } else {
431                    isolatedUids = u.mChildUids.toArray();
432                    for (int j = isolatedUids.length - 1; j >= 0; --j) {
433                        isolatedUids[j] = u.mChildUids.get(j);
434                    }
435                }
436            }
437            long[] cpuTimesMs = mKernelSingleUidTimeReader.readDeltaMs(uid);
438            if (isolatedUids != null) {
439                for (int j = isolatedUids.length - 1; j >= 0; --j) {
440                    cpuTimesMs = addCpuTimes(cpuTimesMs,
441                            mKernelSingleUidTimeReader.readDeltaMs(isolatedUids[j]));
442                }
443            }
444            if (onBattery && cpuTimesMs != null) {
445                synchronized (BatteryStatsImpl.this) {
446                    u.addProcStateTimesMs(procState, cpuTimesMs, onBattery);
447                    u.addProcStateScreenOffTimesMs(procState, cpuTimesMs, onBatteryScreenOff);
448                }
449            }
450        }
451    }
452
453    public void clearPendingRemovedUids() {
454        long cutOffTime = mClocks.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS;
455        while (!mPendingRemovedUids.isEmpty()
456                && mPendingRemovedUids.peek().timeAddedInQueue < cutOffTime) {
457            mPendingRemovedUids.poll().remove();
458        }
459    }
460
461    public void copyFromAllUidsCpuTimes() {
462        synchronized (BatteryStatsImpl.this) {
463            copyFromAllUidsCpuTimes(
464                    mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
465        }
466    }
467
468    /**
469     * When the battery/screen state changes, we don't attribute the cpu times to any process
470     * but we still need to snapshots of all uids to get correct deltas later on. Since we
471     * already read this data for updating per-freq cpu times, we can use the same data for
472     * per-procstate cpu times.
473     */
474    public void copyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff) {
475        synchronized (BatteryStatsImpl.this) {
476            if (!mConstants.TRACK_CPU_TIMES_BY_PROC_STATE) {
477                return;
478            }
479            if(!initKernelSingleUidTimeReaderLocked()) {
480                return;
481            }
482
483            final SparseArray<long[]> allUidCpuFreqTimesMs =
484                    mKernelUidCpuFreqTimeReader.getAllUidCpuFreqTimeMs();
485            // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
486            // compute deltas since it might result in mis-attributing cpu times to wrong states.
487            if (mKernelSingleUidTimeReader.hasStaleData()) {
488                mKernelSingleUidTimeReader.setAllUidsCpuTimesMs(allUidCpuFreqTimesMs);
489                mKernelSingleUidTimeReader.markDataAsStale(false);
490                mPendingUids.clear();
491                return;
492            }
493            for (int i = allUidCpuFreqTimesMs.size() - 1; i >= 0; --i) {
494                final int uid = allUidCpuFreqTimesMs.keyAt(i);
495                final Uid u = getAvailableUidStatsLocked(mapUid(uid));
496                if (u == null) {
497                    continue;
498                }
499                final long[] cpuTimesMs = allUidCpuFreqTimesMs.valueAt(i);
500                if (cpuTimesMs == null) {
501                    continue;
502                }
503                final long[] deltaTimesMs = mKernelSingleUidTimeReader.computeDelta(
504                        uid, cpuTimesMs.clone());
505                if (onBattery && deltaTimesMs != null) {
506                    final int procState;
507                    final int idx = mPendingUids.indexOfKey(uid);
508                    if (idx >= 0) {
509                        procState = mPendingUids.valueAt(idx);
510                        mPendingUids.removeAt(idx);
511                    } else {
512                        procState = u.mProcessState;
513                    }
514                    if (procState >= 0 && procState < Uid.NUM_PROCESS_STATE) {
515                        u.addProcStateTimesMs(procState, deltaTimesMs, onBattery);
516                        u.addProcStateScreenOffTimesMs(procState, deltaTimesMs, onBatteryScreenOff);
517                    }
518                }
519            }
520        }
521    }
522
523    @VisibleForTesting
524    public long[] addCpuTimes(long[] timesA, long[] timesB) {
525        if (timesA != null && timesB != null) {
526            for (int i = timesA.length - 1; i >= 0; --i) {
527                timesA[i] += timesB[i];
528            }
529            return timesA;
530        }
531        return timesA == null ? (timesB == null ? null : timesB) : timesA;
532    }
533
534    @GuardedBy("this")
535    private boolean initKernelSingleUidTimeReaderLocked() {
536        if (mKernelSingleUidTimeReader == null) {
537            if (mPowerProfile == null) {
538                return false;
539            }
540            if (mCpuFreqs == null) {
541                mCpuFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile);
542            }
543            if (mCpuFreqs != null) {
544                mKernelSingleUidTimeReader = new KernelSingleUidTimeReader(mCpuFreqs.length);
545            } else {
546                mPerProcStateCpuTimesAvailable = mKernelUidCpuFreqTimeReader.allUidTimesAvailable();
547                return false;
548            }
549        }
550        mPerProcStateCpuTimesAvailable = mKernelUidCpuFreqTimeReader.allUidTimesAvailable()
551                && mKernelSingleUidTimeReader.singleUidCpuTimesAvailable();
552        return true;
553    }
554
555    public interface Clocks {
556        public long elapsedRealtime();
557        public long uptimeMillis();
558    }
559
560    public static class SystemClocks implements Clocks {
561        public long elapsedRealtime() {
562            return SystemClock.elapsedRealtime();
563        }
564
565        public long uptimeMillis() {
566            return SystemClock.uptimeMillis();
567        }
568    }
569
570    public interface ExternalStatsSync {
571        int UPDATE_CPU = 0x01;
572        int UPDATE_WIFI = 0x02;
573        int UPDATE_RADIO = 0x04;
574        int UPDATE_BT = 0x08;
575        int UPDATE_RPM = 0x10; // 16
576        int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM;
577
578        Future<?> scheduleSync(String reason, int flags);
579        Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
580        Future<?> scheduleReadProcStateCpuTimes(boolean onBattery, boolean onBatteryScreenOff,
581                long delayMillis);
582        Future<?> scheduleCopyFromAllUidsCpuTimes(boolean onBattery, boolean onBatteryScreenOff);
583        Future<?> scheduleCpuSyncDueToSettingChange();
584        Future<?> scheduleCpuSyncDueToScreenStateChange(boolean onBattery,
585                boolean onBatteryScreenOff);
586        Future<?> scheduleCpuSyncDueToWakelockChange(long delayMillis);
587        void cancelCpuSyncDueToWakelockChange();
588        Future<?> scheduleSyncDueToBatteryLevelChange(long delayMillis);
589    }
590
591    public Handler mHandler;
592    private ExternalStatsSync mExternalSync = null;
593    @VisibleForTesting
594    protected UserInfoProvider mUserInfoProvider = null;
595
596    private BatteryCallback mCallback;
597
598    /**
599     * Mapping isolated uids to the actual owning app uid.
600     */
601    final SparseIntArray mIsolatedUids = new SparseIntArray();
602
603    /**
604     * The statistics we have collected organized by uids.
605     */
606    final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
607
608    // A set of pools of currently active timers.  When a timer is queried, we will divide the
609    // elapsed time by the number of active timers to arrive at that timer's share of the time.
610    // In order to do this, we must refresh each timer whenever the number of active timers
611    // changes.
612    @VisibleForTesting
613    protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
614    final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
615    final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
616    final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
617    final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
618    final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
619    final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
620    final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
621    final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
622    final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers = new SparseArray<>();
623    final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
624    final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
625    final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
626    final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
627    final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
628
629    // Last partial timers we use for distributing CPU usage.
630    @VisibleForTesting
631    protected ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
632
633    // These are the objects that will want to do something when the device
634    // is unplugged from power.
635    protected final TimeBase mOnBatteryTimeBase = new TimeBase();
636
637    // These are the objects that will want to do something when the device
638    // is unplugged from power *and* the screen is off or doze.
639    protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase();
640
641    // Set to true when we want to distribute CPU across wakelocks for the next
642    // CPU update, even if we aren't currently running wake locks.
643    boolean mDistributeWakelockCpu;
644
645    boolean mShuttingDown;
646
647    final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
648
649    long mHistoryBaseTime;
650    protected boolean mHaveBatteryLevel = false;
651    protected boolean mRecordingHistory = false;
652    int mNumHistoryItems;
653
654    final Parcel mHistoryBuffer = Parcel.obtain();
655    final HistoryItem mHistoryLastWritten = new HistoryItem();
656    final HistoryItem mHistoryLastLastWritten = new HistoryItem();
657    final HistoryItem mHistoryReadTmp = new HistoryItem();
658    final HistoryItem mHistoryAddTmp = new HistoryItem();
659    final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
660    String[] mReadHistoryStrings;
661    int[] mReadHistoryUids;
662    int mReadHistoryChars;
663    int mNextHistoryTagIdx = 0;
664    int mNumHistoryTagChars = 0;
665    int mHistoryBufferLastPos = -1;
666    boolean mHistoryOverflow = false;
667    int mActiveHistoryStates = 0xffffffff;
668    int mActiveHistoryStates2 = 0xffffffff;
669    long mLastHistoryElapsedRealtime = 0;
670    long mTrackRunningHistoryElapsedRealtime = 0;
671    long mTrackRunningHistoryUptime = 0;
672
673    final HistoryItem mHistoryCur = new HistoryItem();
674
675    HistoryItem mHistory;
676    HistoryItem mHistoryEnd;
677    HistoryItem mHistoryLastEnd;
678    HistoryItem mHistoryCache;
679
680    // Used by computeHistoryStepDetails
681    HistoryStepDetails mLastHistoryStepDetails = null;
682    byte mLastHistoryStepLevel = 0;
683    final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
684    final HistoryStepDetails mReadHistoryStepDetails = new HistoryStepDetails();
685    final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
686
687    /**
688     * Total time (in milliseconds) spent executing in user code.
689     */
690    long mLastStepCpuUserTime;
691    long mCurStepCpuUserTime;
692    /**
693     * Total time (in milliseconds) spent executing in kernel code.
694     */
695    long mLastStepCpuSystemTime;
696    long mCurStepCpuSystemTime;
697    /**
698     * Times from /proc/stat (but measured in milliseconds).
699     */
700    long mLastStepStatUserTime;
701    long mLastStepStatSystemTime;
702    long mLastStepStatIOWaitTime;
703    long mLastStepStatIrqTime;
704    long mLastStepStatSoftIrqTime;
705    long mLastStepStatIdleTime;
706    long mCurStepStatUserTime;
707    long mCurStepStatSystemTime;
708    long mCurStepStatIOWaitTime;
709    long mCurStepStatIrqTime;
710    long mCurStepStatSoftIrqTime;
711    long mCurStepStatIdleTime;
712
713    private HistoryItem mHistoryIterator;
714    private boolean mReadOverflow;
715    private boolean mIteratingHistory;
716
717    int mStartCount;
718
719    long mStartClockTime;
720    String mStartPlatformVersion;
721    String mEndPlatformVersion;
722
723    long mUptime;
724    long mUptimeStart;
725    long mRealtime;
726    long mRealtimeStart;
727
728    int mWakeLockNesting;
729    boolean mWakeLockImportant;
730    public boolean mRecordAllHistory;
731    boolean mNoAutoReset;
732
733    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
734    protected int mScreenState = Display.STATE_UNKNOWN;
735    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
736    protected StopwatchTimer mScreenOnTimer;
737    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
738    protected StopwatchTimer mScreenDozeTimer;
739
740    int mScreenBrightnessBin = -1;
741    final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
742
743    boolean mPretendScreenOff;
744
745    boolean mInteractive;
746    StopwatchTimer mInteractiveTimer;
747
748    boolean mPowerSaveModeEnabled;
749    StopwatchTimer mPowerSaveModeEnabledTimer;
750
751    boolean mDeviceIdling;
752    StopwatchTimer mDeviceIdlingTimer;
753
754    boolean mDeviceLightIdling;
755    StopwatchTimer mDeviceLightIdlingTimer;
756
757    int mDeviceIdleMode;
758    long mLastIdleTimeStart;
759    long mLongestLightIdleTime;
760    long mLongestFullIdleTime;
761    StopwatchTimer mDeviceIdleModeLightTimer;
762    StopwatchTimer mDeviceIdleModeFullTimer;
763
764    boolean mPhoneOn;
765    StopwatchTimer mPhoneOnTimer;
766
767    int mAudioOnNesting;
768    StopwatchTimer mAudioOnTimer;
769
770    int mVideoOnNesting;
771    StopwatchTimer mVideoOnTimer;
772
773    int mFlashlightOnNesting;
774    StopwatchTimer mFlashlightOnTimer;
775
776    int mCameraOnNesting;
777    StopwatchTimer mCameraOnTimer;
778
779    private static final int USB_DATA_UNKNOWN = 0;
780    private static final int USB_DATA_DISCONNECTED = 1;
781    private static final int USB_DATA_CONNECTED = 2;
782    int mUsbDataState = USB_DATA_UNKNOWN;
783
784    int mGpsSignalQualityBin = -1;
785    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
786    protected final StopwatchTimer[] mGpsSignalQualityTimer =
787        new StopwatchTimer[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
788
789    int mPhoneSignalStrengthBin = -1;
790    int mPhoneSignalStrengthBinRaw = -1;
791    final StopwatchTimer[] mPhoneSignalStrengthsTimer =
792            new StopwatchTimer[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
793
794    StopwatchTimer mPhoneSignalScanningTimer;
795
796    int mPhoneDataConnectionType = -1;
797    final StopwatchTimer[] mPhoneDataConnectionsTimer =
798            new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
799
800    final LongSamplingCounter[] mNetworkByteActivityCounters =
801            new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
802    final LongSamplingCounter[] mNetworkPacketActivityCounters =
803            new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
804
805    /**
806     * The WiFi Overall wakelock timer
807     * This timer tracks the actual aggregate time for which MC wakelocks are enabled
808     * since addition of per UID timers would not result in an accurate value due to overlapp of
809     * per uid wakelock timers
810     */
811    StopwatchTimer mWifiMulticastWakelockTimer;
812
813    /**
814     * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
815     */
816    ControllerActivityCounterImpl mWifiActivity;
817
818    /**
819     * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
820     */
821    ControllerActivityCounterImpl mBluetoothActivity;
822
823    /**
824     * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
825     */
826    ControllerActivityCounterImpl mModemActivity;
827
828    /**
829     * Whether the device supports WiFi controller energy reporting. This is set to true on
830     * the first WiFi energy report. See {@link #mWifiActivity}.
831     */
832    boolean mHasWifiReporting = false;
833
834    /**
835     * Whether the device supports Bluetooth controller energy reporting. This is set to true on
836     * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
837     */
838    boolean mHasBluetoothReporting = false;
839
840    /**
841     * Whether the device supports Modem controller energy reporting. This is set to true on
842     * the first Modem energy report. See {@link #mModemActivity}.
843     */
844    boolean mHasModemReporting = false;
845
846    boolean mWifiOn;
847    StopwatchTimer mWifiOnTimer;
848
849    boolean mGlobalWifiRunning;
850    StopwatchTimer mGlobalWifiRunningTimer;
851
852    int mWifiState = -1;
853    final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
854
855    int mWifiSupplState = -1;
856    final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
857
858    int mWifiSignalStrengthBin = -1;
859    final StopwatchTimer[] mWifiSignalStrengthsTimer =
860            new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
861
862    StopwatchTimer mWifiActiveTimer;
863
864    int mBluetoothScanNesting;
865    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
866    protected StopwatchTimer mBluetoothScanTimer;
867
868    boolean mIsCellularTxPowerHigh = false;
869
870    int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
871    long mMobileRadioActiveStartTime;
872    StopwatchTimer mMobileRadioActiveTimer;
873    StopwatchTimer mMobileRadioActivePerAppTimer;
874    LongSamplingCounter mMobileRadioActiveAdjustedTime;
875    LongSamplingCounter mMobileRadioActiveUnknownTime;
876    LongSamplingCounter mMobileRadioActiveUnknownCount;
877
878    int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
879
880    /**
881     * These provide time bases that discount the time the device is plugged
882     * in to power.
883     */
884    boolean mOnBattery;
885    @VisibleForTesting
886    protected boolean mOnBatteryInternal;
887
888    /**
889     * External reporting of whether the device is actually charging.
890     */
891    boolean mCharging = true;
892    int mLastChargingStateLevel;
893
894    /*
895     * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
896     */
897    int mDischargeStartLevel;
898    int mDischargeUnplugLevel;
899    int mDischargePlugLevel;
900    int mDischargeCurrentLevel;
901    int mCurrentBatteryLevel;
902    int mLowDischargeAmountSinceCharge;
903    int mHighDischargeAmountSinceCharge;
904    int mDischargeScreenOnUnplugLevel;
905    int mDischargeScreenOffUnplugLevel;
906    int mDischargeScreenDozeUnplugLevel;
907    int mDischargeAmountScreenOn;
908    int mDischargeAmountScreenOnSinceCharge;
909    int mDischargeAmountScreenOff;
910    int mDischargeAmountScreenOffSinceCharge;
911    int mDischargeAmountScreenDoze;
912    int mDischargeAmountScreenDozeSinceCharge;
913
914    private LongSamplingCounter mDischargeScreenOffCounter;
915    private LongSamplingCounter mDischargeScreenDozeCounter;
916    private LongSamplingCounter mDischargeCounter;
917    private LongSamplingCounter mDischargeLightDozeCounter;
918    private LongSamplingCounter mDischargeDeepDozeCounter;
919
920    static final int MAX_LEVEL_STEPS = 200;
921
922    int mInitStepMode = 0;
923    int mCurStepMode = 0;
924    int mModStepMode = 0;
925
926    int mLastDischargeStepLevel;
927    int mMinDischargeStepLevel;
928    final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
929    final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
930    ArrayList<PackageChange> mDailyPackageChanges;
931
932    int mLastChargeStepLevel;
933    int mMaxChargeStepLevel;
934    final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
935    final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
936
937    static final int MAX_DAILY_ITEMS = 10;
938
939    long mDailyStartTime = 0;
940    long mNextMinDailyDeadline = 0;
941    long mNextMaxDailyDeadline = 0;
942
943    final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
944
945    long mLastWriteTime = 0; // Milliseconds
946
947    private int mPhoneServiceState = -1;
948    private int mPhoneServiceStateRaw = -1;
949    private int mPhoneSimStateRaw = -1;
950
951    private int mNumConnectivityChange;
952    private int mLoadedNumConnectivityChange;
953    private int mUnpluggedNumConnectivityChange;
954
955    private int mEstimatedBatteryCapacity = -1;
956
957    private int mMinLearnedBatteryCapacity = -1;
958    private int mMaxLearnedBatteryCapacity = -1;
959
960    private long[] mCpuFreqs;
961
962    @VisibleForTesting
963    protected PowerProfile mPowerProfile;
964
965    @GuardedBy("this")
966    private final Constants mConstants;
967
968    /*
969     * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
970     * recording their times when on-battery (regardless of screen state).
971     */
972    private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>();
973    /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */
974    private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>();
975
976    @Override
977    public Map<String, ? extends Timer> getRpmStats() {
978        return mRpmStats;
979    }
980
981    // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED.
982    @Override
983    public Map<String, ? extends Timer> getScreenOffRpmStats() {
984        return mScreenOffRpmStats;
985    }
986
987    /*
988     * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
989     */
990    private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
991
992    public Map<String, ? extends Timer> getKernelWakelockStats() {
993        return mKernelWakelockStats;
994    }
995
996    String mLastWakeupReason = null;
997    long mLastWakeupUptimeMs = 0;
998    private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
999
1000    public Map<String, ? extends Timer> getWakeupReasonStats() {
1001        return mWakeupReasonStats;
1002    }
1003
1004    @Override
1005    public long getUahDischarge(int which) {
1006        return mDischargeCounter.getCountLocked(which);
1007    }
1008
1009    @Override
1010    public long getUahDischargeScreenOff(int which) {
1011        return mDischargeScreenOffCounter.getCountLocked(which);
1012    }
1013
1014    @Override
1015    public long getUahDischargeScreenDoze(int which) {
1016        return mDischargeScreenDozeCounter.getCountLocked(which);
1017    }
1018
1019    @Override
1020    public long getUahDischargeLightDoze(int which) {
1021        return mDischargeLightDozeCounter.getCountLocked(which);
1022    }
1023
1024    @Override
1025    public long getUahDischargeDeepDoze(int which) {
1026        return mDischargeDeepDozeCounter.getCountLocked(which);
1027    }
1028
1029    @Override
1030    public int getEstimatedBatteryCapacity() {
1031        return mEstimatedBatteryCapacity;
1032    }
1033
1034    @Override
1035    public int getMinLearnedBatteryCapacity() {
1036        return mMinLearnedBatteryCapacity;
1037    }
1038
1039    @Override
1040    public int getMaxLearnedBatteryCapacity() {
1041        return mMaxLearnedBatteryCapacity;
1042    }
1043
1044    public BatteryStatsImpl() {
1045        this(new SystemClocks());
1046    }
1047
1048    public BatteryStatsImpl(Clocks clocks) {
1049        init(clocks);
1050        mFile = null;
1051        mCheckinFile = null;
1052        mDailyFile = null;
1053        mHandler = null;
1054        mPlatformIdleStateCallback = null;
1055        mUserInfoProvider = null;
1056        mConstants = new Constants(mHandler);
1057        clearHistoryLocked();
1058    }
1059
1060    private void init(Clocks clocks) {
1061        mClocks = clocks;
1062    }
1063
1064    public interface TimeBaseObs {
1065        void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
1066        void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
1067    }
1068
1069    // methods are protected not private to be VisibleForTesting
1070    public static class TimeBase {
1071        protected final ArrayList<TimeBaseObs> mObservers = new ArrayList<>();
1072
1073        protected long mUptime;
1074        protected long mRealtime;
1075
1076        protected boolean mRunning;
1077
1078        protected long mPastUptime;
1079        protected long mUptimeStart;
1080        protected long mPastRealtime;
1081        protected long mRealtimeStart;
1082        protected long mUnpluggedUptime;
1083        protected long mUnpluggedRealtime;
1084
1085        public void dump(PrintWriter pw, String prefix) {
1086            StringBuilder sb = new StringBuilder(128);
1087            pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
1088            sb.setLength(0);
1089            sb.append(prefix);
1090                    sb.append("mUptime=");
1091                    formatTimeMs(sb, mUptime / 1000);
1092            pw.println(sb.toString());
1093            sb.setLength(0);
1094            sb.append(prefix);
1095                    sb.append("mRealtime=");
1096                    formatTimeMs(sb, mRealtime / 1000);
1097            pw.println(sb.toString());
1098            sb.setLength(0);
1099            sb.append(prefix);
1100                    sb.append("mPastUptime=");
1101                    formatTimeMs(sb, mPastUptime / 1000); sb.append("mUptimeStart=");
1102                    formatTimeMs(sb, mUptimeStart / 1000);
1103                    sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptime / 1000);
1104            pw.println(sb.toString());
1105            sb.setLength(0);
1106            sb.append(prefix);
1107                    sb.append("mPastRealtime=");
1108                    formatTimeMs(sb, mPastRealtime / 1000); sb.append("mRealtimeStart=");
1109                    formatTimeMs(sb, mRealtimeStart / 1000);
1110                    sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000);
1111            pw.println(sb.toString());
1112        }
1113
1114        public void add(TimeBaseObs observer) {
1115            mObservers.add(observer);
1116        }
1117
1118        public void remove(TimeBaseObs observer) {
1119            if (!mObservers.remove(observer)) {
1120                Slog.wtf(TAG, "Removed unknown observer: " + observer);
1121            }
1122        }
1123
1124        public boolean hasObserver(TimeBaseObs observer) {
1125            return mObservers.contains(observer);
1126        }
1127
1128        public void init(long uptime, long realtime) {
1129            mRealtime = 0;
1130            mUptime = 0;
1131            mPastUptime = 0;
1132            mPastRealtime = 0;
1133            mUptimeStart = uptime;
1134            mRealtimeStart = realtime;
1135            mUnpluggedUptime = getUptime(mUptimeStart);
1136            mUnpluggedRealtime = getRealtime(mRealtimeStart);
1137        }
1138
1139        public void reset(long uptime, long realtime) {
1140            if (!mRunning) {
1141                mPastUptime = 0;
1142                mPastRealtime = 0;
1143            } else {
1144                mUptimeStart = uptime;
1145                mRealtimeStart = realtime;
1146                // TODO: Since mUptimeStart was just reset and we are running, getUptime will
1147                // just return mPastUptime. Also, are we sure we don't want to reset that?
1148                mUnpluggedUptime = getUptime(uptime);
1149                // TODO: likewise.
1150                mUnpluggedRealtime = getRealtime(realtime);
1151            }
1152        }
1153
1154        public long computeUptime(long curTime, int which) {
1155            switch (which) {
1156                case STATS_SINCE_CHARGED:
1157                    return mUptime + getUptime(curTime);
1158                case STATS_CURRENT:
1159                    return getUptime(curTime);
1160                case STATS_SINCE_UNPLUGGED:
1161                    return getUptime(curTime) - mUnpluggedUptime;
1162            }
1163            return 0;
1164        }
1165
1166        public long computeRealtime(long curTime, int which) {
1167            switch (which) {
1168                case STATS_SINCE_CHARGED:
1169                    return mRealtime + getRealtime(curTime);
1170                case STATS_CURRENT:
1171                    return getRealtime(curTime);
1172                case STATS_SINCE_UNPLUGGED:
1173                    return getRealtime(curTime) - mUnpluggedRealtime;
1174            }
1175            return 0;
1176        }
1177
1178        public long getUptime(long curTime) {
1179            long time = mPastUptime;
1180            if (mRunning) {
1181                time += curTime - mUptimeStart;
1182            }
1183            return time;
1184        }
1185
1186        public long getRealtime(long curTime) {
1187            long time = mPastRealtime;
1188            if (mRunning) {
1189                time += curTime - mRealtimeStart;
1190            }
1191            return time;
1192        }
1193
1194        public long getUptimeStart() {
1195            return mUptimeStart;
1196        }
1197
1198        public long getRealtimeStart() {
1199            return mRealtimeStart;
1200        }
1201
1202        public boolean isRunning() {
1203            return mRunning;
1204        }
1205
1206        public boolean setRunning(boolean running, long uptime, long realtime) {
1207            if (mRunning != running) {
1208                mRunning = running;
1209                if (running) {
1210                    mUptimeStart = uptime;
1211                    mRealtimeStart = realtime;
1212                    long batteryUptime = mUnpluggedUptime = getUptime(uptime);
1213                    long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime);
1214
1215                    for (int i = mObservers.size() - 1; i >= 0; i--) {
1216                        mObservers.get(i).onTimeStarted(realtime, batteryUptime, batteryRealtime);
1217                    }
1218                } else {
1219                    mPastUptime += uptime - mUptimeStart;
1220                    mPastRealtime += realtime - mRealtimeStart;
1221
1222                    long batteryUptime = getUptime(uptime);
1223                    long batteryRealtime = getRealtime(realtime);
1224
1225                    for (int i = mObservers.size() - 1; i >= 0; i--) {
1226                        mObservers.get(i).onTimeStopped(realtime, batteryUptime, batteryRealtime);
1227                    }
1228                }
1229                return true;
1230            }
1231            return false;
1232        }
1233
1234        public void readSummaryFromParcel(Parcel in) {
1235            mUptime = in.readLong();
1236            mRealtime = in.readLong();
1237        }
1238
1239        public void writeSummaryToParcel(Parcel out, long uptime, long realtime) {
1240            out.writeLong(computeUptime(uptime, STATS_SINCE_CHARGED));
1241            out.writeLong(computeRealtime(realtime, STATS_SINCE_CHARGED));
1242        }
1243
1244        public void readFromParcel(Parcel in) {
1245            mRunning = false;
1246            mUptime = in.readLong();
1247            mPastUptime = in.readLong();
1248            mUptimeStart = in.readLong();
1249            mRealtime = in.readLong();
1250            mPastRealtime = in.readLong();
1251            mRealtimeStart = in.readLong();
1252            mUnpluggedUptime = in.readLong();
1253            mUnpluggedRealtime = in.readLong();
1254        }
1255
1256        public void writeToParcel(Parcel out, long uptime, long realtime) {
1257            final long runningUptime = getUptime(uptime);
1258            final long runningRealtime = getRealtime(realtime);
1259            out.writeLong(mUptime);
1260            out.writeLong(runningUptime);
1261            out.writeLong(mUptimeStart);
1262            out.writeLong(mRealtime);
1263            out.writeLong(runningRealtime);
1264            out.writeLong(mRealtimeStart);
1265            out.writeLong(mUnpluggedUptime);
1266            out.writeLong(mUnpluggedRealtime);
1267        }
1268    }
1269
1270    /**
1271     * State for keeping track of counting information.
1272     */
1273    public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
1274        final AtomicInteger mCount = new AtomicInteger();
1275        final TimeBase mTimeBase;
1276        int mLoadedCount;
1277        int mUnpluggedCount;
1278        int mPluggedCount;
1279
1280        public Counter(TimeBase timeBase, Parcel in) {
1281            mTimeBase = timeBase;
1282            mPluggedCount = in.readInt();
1283            mCount.set(mPluggedCount);
1284            mLoadedCount = in.readInt();
1285            mUnpluggedCount = in.readInt();
1286            timeBase.add(this);
1287        }
1288
1289        public Counter(TimeBase timeBase) {
1290            mTimeBase = timeBase;
1291            timeBase.add(this);
1292        }
1293
1294        public void writeToParcel(Parcel out) {
1295            out.writeInt(mCount.get());
1296            out.writeInt(mLoadedCount);
1297            out.writeInt(mUnpluggedCount);
1298        }
1299
1300        @Override
1301        public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1302            mUnpluggedCount = mPluggedCount;
1303        }
1304
1305        @Override
1306        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1307            mPluggedCount = mCount.get();
1308        }
1309
1310        /**
1311         * Writes a possibly null Counter to a Parcel.
1312         *
1313         * @param out the Parcel to be written to.
1314         * @param counter a Counter, or null.
1315         */
1316        public static void writeCounterToParcel(Parcel out, @Nullable Counter counter) {
1317            if (counter == null) {
1318                out.writeInt(0); // indicates null
1319                return;
1320            }
1321            out.writeInt(1); // indicates non-null
1322
1323            counter.writeToParcel(out);
1324        }
1325
1326        /**
1327         * Reads a Counter that was written using {@link #writeCounterToParcel(Parcel, Counter)}.
1328         * @param timeBase the timebase to assign to the Counter
1329         * @param in the parcel to read from
1330         * @return the Counter or null.
1331         */
1332        public static @Nullable Counter readCounterFromParcel(TimeBase timeBase, Parcel in) {
1333            if (in.readInt() == 0) {
1334                return null;
1335            }
1336            return new Counter(timeBase, in);
1337        }
1338
1339        @Override
1340        public int getCountLocked(int which) {
1341            int val = mCount.get();
1342            if (which == STATS_SINCE_UNPLUGGED) {
1343                val -= mUnpluggedCount;
1344            } else if (which != STATS_SINCE_CHARGED) {
1345                val -= mLoadedCount;
1346            }
1347
1348            return val;
1349        }
1350
1351        public void logState(Printer pw, String prefix) {
1352            pw.println(prefix + "mCount=" + mCount.get()
1353                    + " mLoadedCount=" + mLoadedCount
1354                    + " mUnpluggedCount=" + mUnpluggedCount
1355                    + " mPluggedCount=" + mPluggedCount);
1356        }
1357
1358        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
1359        public void stepAtomic() {
1360            if (mTimeBase.isRunning()) {
1361                mCount.incrementAndGet();
1362            }
1363        }
1364
1365        void addAtomic(int delta) {
1366            if (mTimeBase.isRunning()) {
1367                mCount.addAndGet(delta);
1368            }
1369        }
1370
1371        /**
1372         * Clear state of this counter.
1373         */
1374        void reset(boolean detachIfReset) {
1375            mCount.set(0);
1376            mLoadedCount = mPluggedCount = mUnpluggedCount = 0;
1377            if (detachIfReset) {
1378                detach();
1379            }
1380        }
1381
1382        void detach() {
1383            mTimeBase.remove(this);
1384        }
1385
1386        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
1387        public void writeSummaryFromParcelLocked(Parcel out) {
1388            int count = mCount.get();
1389            out.writeInt(count);
1390        }
1391
1392        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
1393        public void readSummaryFromParcelLocked(Parcel in) {
1394            mLoadedCount = in.readInt();
1395            mCount.set(mLoadedCount);
1396            mUnpluggedCount = mPluggedCount = mLoadedCount;
1397        }
1398    }
1399
1400    @VisibleForTesting
1401    public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
1402        final TimeBase mTimeBase;
1403        public long[] mCounts;
1404        public long[] mLoadedCounts;
1405        public long[] mUnpluggedCounts;
1406
1407        private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
1408            mTimeBase = timeBase;
1409            mCounts = in.createLongArray();
1410            mLoadedCounts = in.createLongArray();
1411            mUnpluggedCounts = in.createLongArray();
1412            timeBase.add(this);
1413        }
1414
1415        public LongSamplingCounterArray(TimeBase timeBase) {
1416            mTimeBase = timeBase;
1417            timeBase.add(this);
1418        }
1419
1420        private void writeToParcel(Parcel out) {
1421            out.writeLongArray(mCounts);
1422            out.writeLongArray(mLoadedCounts);
1423            out.writeLongArray(mUnpluggedCounts);
1424        }
1425
1426        @Override
1427        public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) {
1428            mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
1429        }
1430
1431        @Override
1432        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1433        }
1434
1435        @Override
1436        public long[] getCountsLocked(int which) {
1437            long[] val = copyArray(mCounts, null);
1438            if (which == STATS_SINCE_UNPLUGGED) {
1439                subtract(val, mUnpluggedCounts);
1440            } else if (which != STATS_SINCE_CHARGED) {
1441                subtract(val, mLoadedCounts);
1442            }
1443            return val;
1444        }
1445
1446        @Override
1447        public void logState(Printer pw, String prefix) {
1448            pw.println(prefix + "mCounts=" + Arrays.toString(mCounts)
1449                    + " mLoadedCounts=" + Arrays.toString(mLoadedCounts)
1450                    + " mUnpluggedCounts=" + Arrays.toString(mUnpluggedCounts));
1451        }
1452
1453        public void addCountLocked(long[] counts) {
1454            addCountLocked(counts, mTimeBase.isRunning());
1455        }
1456
1457        public void addCountLocked(long[] counts, boolean isRunning) {
1458            if (counts == null) {
1459                return;
1460            }
1461            if (isRunning) {
1462                if (mCounts == null) {
1463                    mCounts = new long[counts.length];
1464                }
1465                for (int i = 0; i < counts.length; ++i) {
1466                    mCounts[i] += counts[i];
1467                }
1468            }
1469        }
1470
1471        public int getSize() {
1472            return mCounts == null ? 0 : mCounts.length;
1473        }
1474
1475        /**
1476         * Clear state of this counter.
1477         */
1478        public void reset(boolean detachIfReset) {
1479            fillArray(mCounts, 0);
1480            fillArray(mLoadedCounts, 0);
1481            fillArray(mUnpluggedCounts, 0);
1482            if (detachIfReset) {
1483                detach();
1484            }
1485        }
1486
1487        public void detach() {
1488            mTimeBase.remove(this);
1489        }
1490
1491        private void writeSummaryToParcelLocked(Parcel out) {
1492            out.writeLongArray(mCounts);
1493        }
1494
1495        private void readSummaryFromParcelLocked(Parcel in) {
1496            mCounts = in.createLongArray();
1497            mLoadedCounts = copyArray(mCounts, mLoadedCounts);
1498            mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
1499        }
1500
1501        public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
1502            if (counterArray != null) {
1503                out.writeInt(1);
1504                counterArray.writeToParcel(out);
1505            } else {
1506                out.writeInt(0);
1507            }
1508        }
1509
1510        public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
1511            if (in.readInt() != 0) {
1512                return new LongSamplingCounterArray(timeBase, in);
1513            } else {
1514                return null;
1515            }
1516        }
1517
1518        public static void writeSummaryToParcelLocked(Parcel out,
1519                LongSamplingCounterArray counterArray) {
1520            if (counterArray != null) {
1521                out.writeInt(1);
1522                counterArray.writeSummaryToParcelLocked(out);
1523            } else {
1524                out.writeInt(0);
1525            }
1526        }
1527
1528        public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
1529                TimeBase timeBase) {
1530            if (in.readInt() != 0) {
1531                final LongSamplingCounterArray counterArray
1532                        = new LongSamplingCounterArray(timeBase);
1533                counterArray.readSummaryFromParcelLocked(in);
1534                return counterArray;
1535            } else {
1536                return null;
1537            }
1538        }
1539
1540        private static void fillArray(long[] a, long val) {
1541            if (a != null) {
1542                Arrays.fill(a, val);
1543            }
1544        }
1545
1546        private static void subtract(@NonNull long[] val, long[] toSubtract) {
1547            if (toSubtract == null) {
1548                return;
1549            }
1550            for (int i = 0; i < val.length; i++) {
1551                val[i] -= toSubtract[i];
1552            }
1553        }
1554
1555        private static long[] copyArray(long[] src, long[] dest) {
1556            if (src == null) {
1557                return null;
1558            } else {
1559                if (dest == null) {
1560                    dest = new long[src.length];
1561                }
1562                System.arraycopy(src, 0, dest, 0, src.length);
1563                return dest;
1564            }
1565        }
1566    }
1567
1568    @VisibleForTesting
1569    public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
1570        final TimeBase mTimeBase;
1571        public long mCount;
1572        public long mCurrentCount;
1573        public long mLoadedCount;
1574        public long mUnpluggedCount;
1575
1576        public LongSamplingCounter(TimeBase timeBase, Parcel in) {
1577            mTimeBase = timeBase;
1578            mCount = in.readLong();
1579            mCurrentCount = in.readLong();
1580            mLoadedCount = in.readLong();
1581            mUnpluggedCount = in.readLong();
1582            timeBase.add(this);
1583        }
1584
1585        public LongSamplingCounter(TimeBase timeBase) {
1586            mTimeBase = timeBase;
1587            timeBase.add(this);
1588        }
1589
1590        public void writeToParcel(Parcel out) {
1591            out.writeLong(mCount);
1592            out.writeLong(mCurrentCount);
1593            out.writeLong(mLoadedCount);
1594            out.writeLong(mUnpluggedCount);
1595        }
1596
1597        @Override
1598        public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1599            mUnpluggedCount = mCount;
1600        }
1601
1602        @Override
1603        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1604        }
1605
1606        public long getCountLocked(int which) {
1607            long val = mCount;
1608            if (which == STATS_SINCE_UNPLUGGED) {
1609                val -= mUnpluggedCount;
1610            } else if (which != STATS_SINCE_CHARGED) {
1611                val -= mLoadedCount;
1612            }
1613            return val;
1614        }
1615
1616        @Override
1617        public void logState(Printer pw, String prefix) {
1618            pw.println(prefix + "mCount=" + mCount
1619                    + " mCurrentCount=" + mCurrentCount
1620                    + " mLoadedCount=" + mLoadedCount
1621                    + " mUnpluggedCount=" + mUnpluggedCount);
1622        }
1623
1624        public void addCountLocked(long count) {
1625            update(mCurrentCount + count, mTimeBase.isRunning());
1626        }
1627
1628        public void addCountLocked(long count, boolean isRunning) {
1629            update(mCurrentCount + count, isRunning);
1630        }
1631
1632        public void update(long count) {
1633            update(count, mTimeBase.isRunning());
1634        }
1635
1636        public void update(long count, boolean isRunning) {
1637            if (count < mCurrentCount) {
1638                mCurrentCount = 0;
1639            }
1640            if (isRunning) {
1641                mCount += count - mCurrentCount;
1642            }
1643            mCurrentCount = count;
1644        }
1645
1646        /**
1647         * Clear state of this counter.
1648         */
1649        public void reset(boolean detachIfReset) {
1650            mCount = 0;
1651            mLoadedCount = mUnpluggedCount = 0;
1652            if (detachIfReset) {
1653                detach();
1654            }
1655        }
1656
1657        public void detach() {
1658            mTimeBase.remove(this);
1659        }
1660
1661        public void writeSummaryFromParcelLocked(Parcel out) {
1662            out.writeLong(mCount);
1663        }
1664
1665        public void readSummaryFromParcelLocked(Parcel in) {
1666            mCount = mUnpluggedCount= mLoadedCount = in.readLong();
1667        }
1668    }
1669
1670    /**
1671     * State for keeping track of timing information.
1672     */
1673    public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
1674        protected final Clocks mClocks;
1675        protected final int mType;
1676        protected final TimeBase mTimeBase;
1677
1678        protected int mCount;
1679        protected int mLoadedCount;
1680        protected int mLastCount;
1681        protected int mUnpluggedCount;
1682
1683        // Times are in microseconds for better accuracy when dividing by the
1684        // lock count, and are in "battery realtime" units.
1685
1686        /**
1687         * The total time we have accumulated since the start of the original
1688         * boot, to the last time something interesting happened in the
1689         * current run.
1690         */
1691        protected long mTotalTime;
1692
1693        /**
1694         * The total time we loaded for the previous runs.  Subtract this from
1695         * mTotalTime to find the time for the current run of the system.
1696         */
1697        protected long mLoadedTime;
1698
1699        /**
1700         * The run time of the last run of the system, as loaded from the
1701         * saved data.
1702         */
1703        protected long mLastTime;
1704
1705        /**
1706         * The value of mTotalTime when unplug() was last called.  Subtract
1707         * this from mTotalTime to find the time since the last unplug from
1708         * power.
1709         */
1710        protected long mUnpluggedTime;
1711
1712        /**
1713         * The total time this timer has been running until the latest mark has been set.
1714         * Subtract this from mTotalTime to get the time spent running since the mark was set.
1715         */
1716        protected long mTimeBeforeMark;
1717
1718        /**
1719         * Constructs from a parcel.
1720         * @param type
1721         * @param timeBase
1722         * @param in
1723         */
1724        public Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in) {
1725            mClocks = clocks;
1726            mType = type;
1727            mTimeBase = timeBase;
1728
1729            mCount = in.readInt();
1730            mLoadedCount = in.readInt();
1731            mLastCount = 0;
1732            mUnpluggedCount = in.readInt();
1733            mTotalTime = in.readLong();
1734            mLoadedTime = in.readLong();
1735            mLastTime = 0;
1736            mUnpluggedTime = in.readLong();
1737            mTimeBeforeMark = in.readLong();
1738            timeBase.add(this);
1739            if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTime);
1740        }
1741
1742        public Timer(Clocks clocks, int type, TimeBase timeBase) {
1743            mClocks = clocks;
1744            mType = type;
1745            mTimeBase = timeBase;
1746            timeBase.add(this);
1747        }
1748
1749        protected abstract long computeRunTimeLocked(long curBatteryRealtime);
1750
1751        protected abstract int computeCurrentCountLocked();
1752
1753        /**
1754         * Clear state of this timer.  Returns true if the timer is inactive
1755         * so can be completely dropped.
1756         */
1757        public boolean reset(boolean detachIfReset) {
1758            mTotalTime = mLoadedTime = mLastTime = mTimeBeforeMark = 0;
1759            mCount = mLoadedCount = mLastCount = 0;
1760            if (detachIfReset) {
1761                detach();
1762            }
1763            return true;
1764        }
1765
1766        public void detach() {
1767            mTimeBase.remove(this);
1768        }
1769
1770        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1771            if (DEBUG) Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
1772                    + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
1773            out.writeInt(computeCurrentCountLocked());
1774            out.writeInt(mLoadedCount);
1775            out.writeInt(mUnpluggedCount);
1776            out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
1777            out.writeLong(mLoadedTime);
1778            out.writeLong(mUnpluggedTime);
1779            out.writeLong(mTimeBeforeMark);
1780        }
1781
1782        @Override
1783        public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) {
1784            if (DEBUG && mType < 0) {
1785                Log.v(TAG, "unplug #" + mType + ": realtime=" + baseRealtime
1786                        + " old mUnpluggedTime=" + mUnpluggedTime
1787                        + " old mUnpluggedCount=" + mUnpluggedCount);
1788            }
1789            mUnpluggedTime = computeRunTimeLocked(baseRealtime);
1790            mUnpluggedCount = computeCurrentCountLocked();
1791            if (DEBUG && mType < 0) {
1792                Log.v(TAG, "unplug #" + mType
1793                        + ": new mUnpluggedTime=" + mUnpluggedTime
1794                        + " new mUnpluggedCount=" + mUnpluggedCount);
1795            }
1796        }
1797
1798        @Override
1799        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1800            if (DEBUG && mType < 0) {
1801                Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtime
1802                        + " old mTotalTime=" + mTotalTime);
1803            }
1804            mTotalTime = computeRunTimeLocked(baseRealtime);
1805            mCount = computeCurrentCountLocked();
1806            if (DEBUG && mType < 0) {
1807                Log.v(TAG, "plug #" + mType
1808                        + ": new mTotalTime=" + mTotalTime);
1809            }
1810        }
1811
1812        /**
1813         * Writes a possibly null Timer to a Parcel.
1814         *
1815         * @param out the Parcel to be written to.
1816         * @param timer a Timer, or null.
1817         */
1818        public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
1819            if (timer == null) {
1820                out.writeInt(0); // indicates null
1821                return;
1822            }
1823            out.writeInt(1); // indicates non-null
1824
1825            timer.writeToParcel(out, elapsedRealtimeUs);
1826        }
1827
1828        @Override
1829        public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
1830            long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1831            if (which == STATS_SINCE_UNPLUGGED) {
1832                val -= mUnpluggedTime;
1833            } else if (which != STATS_SINCE_CHARGED) {
1834                val -= mLoadedTime;
1835            }
1836
1837            return val;
1838        }
1839
1840        @Override
1841        public int getCountLocked(int which) {
1842            int val = computeCurrentCountLocked();
1843            if (which == STATS_SINCE_UNPLUGGED) {
1844                val -= mUnpluggedCount;
1845            } else if (which != STATS_SINCE_CHARGED) {
1846                val -= mLoadedCount;
1847            }
1848
1849            return val;
1850        }
1851
1852        @Override
1853        public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
1854            long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1855            return val - mTimeBeforeMark;
1856        }
1857
1858        @Override
1859        public void logState(Printer pw, String prefix) {
1860            pw.println(prefix + "mCount=" + mCount
1861                    + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
1862                    + " mUnpluggedCount=" + mUnpluggedCount);
1863            pw.println(prefix + "mTotalTime=" + mTotalTime
1864                    + " mLoadedTime=" + mLoadedTime);
1865            pw.println(prefix + "mLastTime=" + mLastTime
1866                    + " mUnpluggedTime=" + mUnpluggedTime);
1867        }
1868
1869
1870        public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
1871            long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1872            out.writeLong(runTime);
1873            out.writeInt(computeCurrentCountLocked());
1874        }
1875
1876        public void readSummaryFromParcelLocked(Parcel in) {
1877            // Multiply by 1000 for backwards compatibility
1878            mTotalTime = mLoadedTime = in.readLong();
1879            mLastTime = 0;
1880            mUnpluggedTime = mTotalTime;
1881            mCount = mLoadedCount = in.readInt();
1882            mLastCount = 0;
1883            mUnpluggedCount = mCount;
1884
1885            // When reading the summary, we set the mark to be the latest information.
1886            mTimeBeforeMark = mTotalTime;
1887        }
1888    }
1889
1890    /**
1891     * A counter meant to accept monotonically increasing values to its {@link #update(long, int)}
1892     * method. The state of the timer according to its {@link TimeBase} will determine how much
1893     * of the value is recorded.
1894     *
1895     * If the value being recorded resets, {@link #endSample()} can be called in order to
1896     * account for the change. If the value passed in to {@link #update(long, int)} decreased
1897     * between calls, the {@link #endSample()} is automatically called and the new value is
1898     * expected to increase monotonically from that point on.
1899     */
1900    public static class SamplingTimer extends Timer {
1901
1902        /**
1903         * The most recent reported count from /proc/wakelocks.
1904         */
1905        int mCurrentReportedCount;
1906
1907        /**
1908         * The reported count from /proc/wakelocks when unplug() was last
1909         * called.
1910         */
1911        int mUnpluggedReportedCount;
1912
1913        /**
1914         * The most recent reported total_time from /proc/wakelocks.
1915         */
1916        long mCurrentReportedTotalTime;
1917
1918
1919        /**
1920         * The reported total_time from /proc/wakelocks when unplug() was last
1921         * called.
1922         */
1923        long mUnpluggedReportedTotalTime;
1924
1925        /**
1926         * Whether we are currently in a discharge cycle.
1927         */
1928        boolean mTimeBaseRunning;
1929
1930        /**
1931         * Whether we are currently recording reported values.
1932         */
1933        boolean mTrackingReportedValues;
1934
1935        /*
1936         * A sequence counter, incremented once for each update of the stats.
1937         */
1938        int mUpdateVersion;
1939
1940        @VisibleForTesting
1941        public SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in) {
1942            super(clocks, 0, timeBase, in);
1943            mCurrentReportedCount = in.readInt();
1944            mUnpluggedReportedCount = in.readInt();
1945            mCurrentReportedTotalTime = in.readLong();
1946            mUnpluggedReportedTotalTime = in.readLong();
1947            mTrackingReportedValues = in.readInt() == 1;
1948            mTimeBaseRunning = timeBase.isRunning();
1949        }
1950
1951        @VisibleForTesting
1952        public SamplingTimer(Clocks clocks, TimeBase timeBase) {
1953            super(clocks, 0, timeBase);
1954            mTrackingReportedValues = false;
1955            mTimeBaseRunning = timeBase.isRunning();
1956        }
1957
1958        /**
1959         * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to
1960         * be less than the values used for a previous invocation.
1961         */
1962        public void endSample() {
1963            mTotalTime = computeRunTimeLocked(0 /* unused by us */);
1964            mCount = computeCurrentCountLocked();
1965            mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = 0;
1966            mUnpluggedReportedCount = mCurrentReportedCount = 0;
1967        }
1968
1969        public void setUpdateVersion(int version) {
1970            mUpdateVersion = version;
1971        }
1972
1973        public int getUpdateVersion() {
1974            return mUpdateVersion;
1975        }
1976
1977        /**
1978         * Updates the current recorded values. These are meant to be monotonically increasing
1979         * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}.
1980         *
1981         * If the values being recorded have been reset, the monotonically increasing requirement
1982         * will be broken. In this case, {@link #endSample()} is automatically called and
1983         * the total value of totalTime and count are recorded, starting a new monotonically
1984         * increasing sample.
1985         *
1986         * @param totalTime total time of sample in microseconds.
1987         * @param count total number of times the event being sampled occurred.
1988         */
1989        public void update(long totalTime, int count) {
1990            if (mTimeBaseRunning && !mTrackingReportedValues) {
1991                // Updating the reported value for the first time.
1992                mUnpluggedReportedTotalTime = totalTime;
1993                mUnpluggedReportedCount = count;
1994            }
1995
1996            mTrackingReportedValues = true;
1997
1998            if (totalTime < mCurrentReportedTotalTime || count < mCurrentReportedCount) {
1999                endSample();
2000            }
2001
2002            mCurrentReportedTotalTime = totalTime;
2003            mCurrentReportedCount = count;
2004        }
2005
2006        /**
2007         * Adds deltaTime and deltaCount to the current sample.
2008         *
2009         * @param deltaTime additional time recorded since the last sampled event, in microseconds.
2010         * @param deltaCount additional number of times the event being sampled occurred.
2011         */
2012        public void add(long deltaTime, int deltaCount) {
2013            update(mCurrentReportedTotalTime + deltaTime, mCurrentReportedCount + deltaCount);
2014        }
2015
2016        @Override
2017        public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
2018            super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
2019            if (mTrackingReportedValues) {
2020                mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
2021                mUnpluggedReportedCount = mCurrentReportedCount;
2022            }
2023            mTimeBaseRunning = true;
2024        }
2025
2026        @Override
2027        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
2028            super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
2029            mTimeBaseRunning = false;
2030        }
2031
2032        @Override
2033        public void logState(Printer pw, String prefix) {
2034            super.logState(pw, prefix);
2035            pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
2036                    + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
2037                    + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
2038                    + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
2039        }
2040
2041        @Override
2042        protected long computeRunTimeLocked(long curBatteryRealtime) {
2043            return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues
2044                    ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
2045        }
2046
2047        @Override
2048        protected int computeCurrentCountLocked() {
2049            return mCount + (mTimeBaseRunning && mTrackingReportedValues
2050                    ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
2051        }
2052
2053        @Override
2054        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2055            super.writeToParcel(out, elapsedRealtimeUs);
2056            out.writeInt(mCurrentReportedCount);
2057            out.writeInt(mUnpluggedReportedCount);
2058            out.writeLong(mCurrentReportedTotalTime);
2059            out.writeLong(mUnpluggedReportedTotalTime);
2060            out.writeInt(mTrackingReportedValues ? 1 : 0);
2061        }
2062
2063        @Override
2064        public boolean reset(boolean detachIfReset) {
2065            super.reset(detachIfReset);
2066            mTrackingReportedValues = false;
2067            mUnpluggedReportedTotalTime = 0;
2068            mUnpluggedReportedCount = 0;
2069            return true;
2070        }
2071    }
2072
2073    /**
2074     * A timer that increments in batches.  It does not run for durations, but just jumps
2075     * for a pre-determined amount.
2076     */
2077    public static class BatchTimer extends Timer {
2078        final Uid mUid;
2079
2080        /**
2081         * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
2082         */
2083        long mLastAddedTime;
2084
2085        /**
2086         * The last duration that we added to the timer.  This is in microseconds.
2087         */
2088        long mLastAddedDuration;
2089
2090        /**
2091         * Whether we are currently in a discharge cycle.
2092         */
2093        boolean mInDischarge;
2094
2095        BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in) {
2096            super(clocks, type, timeBase, in);
2097            mUid = uid;
2098            mLastAddedTime = in.readLong();
2099            mLastAddedDuration = in.readLong();
2100            mInDischarge = timeBase.isRunning();
2101        }
2102
2103        BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase) {
2104            super(clocks, type, timeBase);
2105            mUid = uid;
2106            mInDischarge = timeBase.isRunning();
2107        }
2108
2109        @Override
2110        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2111            super.writeToParcel(out, elapsedRealtimeUs);
2112            out.writeLong(mLastAddedTime);
2113            out.writeLong(mLastAddedDuration);
2114        }
2115
2116        @Override
2117        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
2118            recomputeLastDuration(mClocks.elapsedRealtime() * 1000, false);
2119            mInDischarge = false;
2120            super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
2121        }
2122
2123        @Override
2124        public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
2125            recomputeLastDuration(elapsedRealtime, false);
2126            mInDischarge = true;
2127            // If we are still within the last added duration, then re-added whatever remains.
2128            if (mLastAddedTime == elapsedRealtime) {
2129                mTotalTime += mLastAddedDuration;
2130            }
2131            super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
2132        }
2133
2134        @Override
2135        public void logState(Printer pw, String prefix) {
2136            super.logState(pw, prefix);
2137            pw.println(prefix + "mLastAddedTime=" + mLastAddedTime
2138                    + " mLastAddedDuration=" + mLastAddedDuration);
2139        }
2140
2141        private long computeOverage(long curTime) {
2142            if (mLastAddedTime > 0) {
2143                return mLastTime + mLastAddedDuration - curTime;
2144            }
2145            return 0;
2146        }
2147
2148        private void recomputeLastDuration(long curTime, boolean abort) {
2149            final long overage = computeOverage(curTime);
2150            if (overage > 0) {
2151                // Aborting before the duration ran out -- roll back the remaining
2152                // duration.  Only do this if currently discharging; otherwise we didn't
2153                // actually add the time.
2154                if (mInDischarge) {
2155                    mTotalTime -= overage;
2156                }
2157                if (abort) {
2158                    mLastAddedTime = 0;
2159                } else {
2160                    mLastAddedTime = curTime;
2161                    mLastAddedDuration -= overage;
2162                }
2163            }
2164        }
2165
2166        public void addDuration(BatteryStatsImpl stats, long durationMillis) {
2167            final long now = mClocks.elapsedRealtime() * 1000;
2168            recomputeLastDuration(now, true);
2169            mLastAddedTime = now;
2170            mLastAddedDuration = durationMillis * 1000;
2171            if (mInDischarge) {
2172                mTotalTime += mLastAddedDuration;
2173                mCount++;
2174            }
2175        }
2176
2177        public void abortLastDuration(BatteryStatsImpl stats) {
2178            final long now = mClocks.elapsedRealtime() * 1000;
2179            recomputeLastDuration(now, true);
2180        }
2181
2182        @Override
2183        protected int computeCurrentCountLocked() {
2184            return mCount;
2185        }
2186
2187        @Override
2188        protected long computeRunTimeLocked(long curBatteryRealtime) {
2189            final long overage = computeOverage(mClocks.elapsedRealtime() * 1000);
2190            if (overage > 0) {
2191                return mTotalTime = overage;
2192            }
2193            return mTotalTime;
2194        }
2195
2196        @Override
2197        public boolean reset(boolean detachIfReset) {
2198            final long now = mClocks.elapsedRealtime() * 1000;
2199            recomputeLastDuration(now, true);
2200            boolean stillActive = mLastAddedTime == now;
2201            super.reset(!stillActive && detachIfReset);
2202            return !stillActive;
2203        }
2204    }
2205
2206
2207    /**
2208     * A StopwatchTimer that also tracks the total and max individual
2209     * time spent active according to the given timebase.  Whereas
2210     * StopwatchTimer apportions the time amongst all in the pool,
2211     * the total and max durations are not apportioned.
2212     */
2213    public static class DurationTimer extends StopwatchTimer {
2214        /**
2215         * The time (in ms) that the timer was last acquired or the time base
2216         * last (re-)started. Increasing the nesting depth does not reset this time.
2217         *
2218         * -1 if the timer is currently not running or the time base is not running.
2219         *
2220         * If written to a parcel, the start time is reset, as is mNesting in the base class
2221         * StopwatchTimer.
2222         */
2223        long mStartTimeMs = -1;
2224
2225        /**
2226         * The longest time period (in ms) that the timer has been active. Not pooled.
2227         */
2228        long mMaxDurationMs;
2229
2230        /**
2231         * The time (in ms) that that the timer has been active since most recent
2232         * stopRunningLocked() or reset(). Not pooled.
2233         */
2234        long mCurrentDurationMs;
2235
2236        /**
2237         * The total time (in ms) that that the timer has been active since most recent reset()
2238         * prior to the current startRunningLocked. This is the sum of all past currentDurations
2239         * (but not including the present currentDuration) since reset. Not pooled.
2240         */
2241        long mTotalDurationMs;
2242
2243        public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2244                TimeBase timeBase, Parcel in) {
2245            super(clocks, uid, type, timerPool, timeBase, in);
2246            mMaxDurationMs = in.readLong();
2247            mTotalDurationMs = in.readLong();
2248            mCurrentDurationMs = in.readLong();
2249        }
2250
2251        public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2252                TimeBase timeBase) {
2253            super(clocks, uid, type, timerPool, timeBase);
2254        }
2255
2256        @Override
2257        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2258            super.writeToParcel(out, elapsedRealtimeUs);
2259            out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2260            out.writeLong(mTotalDurationMs);
2261            out.writeLong(getCurrentDurationMsLocked(elapsedRealtimeUs / 1000));
2262        }
2263
2264        /**
2265         * Write the summary to the parcel.
2266         *
2267         * Since the time base is probably meaningless after we come back, reading
2268         * from this will have the effect of stopping the timer. So here all we write
2269         * is the max and total durations.
2270         */
2271        @Override
2272        public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2273            super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2274            out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
2275            out.writeLong(getTotalDurationMsLocked(elapsedRealtimeUs / 1000));
2276        }
2277
2278        /**
2279         * Read the summary parcel.
2280         *
2281         * Has the side effect of stopping the timer.
2282         */
2283        @Override
2284        public void readSummaryFromParcelLocked(Parcel in) {
2285            super.readSummaryFromParcelLocked(in);
2286            mMaxDurationMs = in.readLong();
2287            mTotalDurationMs = in.readLong();
2288            mStartTimeMs = -1;
2289            mCurrentDurationMs = 0;
2290        }
2291
2292        /**
2293         * The TimeBase time started (again).
2294         *
2295         * If the timer is also running, store the start time.
2296         */
2297        public void onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime) {
2298            super.onTimeStarted(elapsedRealtimeUs, baseUptime, baseRealtime);
2299            if (mNesting > 0) {
2300                mStartTimeMs = baseRealtime / 1000;
2301            }
2302        }
2303
2304        /**
2305         * The TimeBase stopped running.
2306         *
2307         * If the timer is running, add the duration into mCurrentDurationMs.
2308         */
2309        @Override
2310        public void onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtimeUs) {
2311            super.onTimeStopped(elapsedRealtimeUs, baseUptime, baseRealtimeUs);
2312            if (mNesting > 0) {
2313                // baseRealtimeUs has already been converted to the timebase's realtime.
2314                mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
2315            }
2316            mStartTimeMs = -1;
2317        }
2318
2319        @Override
2320        public void logState(Printer pw, String prefix) {
2321            super.logState(pw, prefix);
2322        }
2323
2324        @Override
2325        public void startRunningLocked(long elapsedRealtimeMs) {
2326            super.startRunningLocked(elapsedRealtimeMs);
2327            if (mNesting == 1 && mTimeBase.isRunning()) {
2328                // Just started
2329                mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000;
2330            }
2331        }
2332
2333        /**
2334         * Decrements the mNesting ref-count on this timer.
2335         *
2336         * If it actually stopped (mNesting went to 0), then possibly update
2337         * mMaxDuration if the current duration was the longest ever.
2338         */
2339        @Override
2340        public void stopRunningLocked(long elapsedRealtimeMs) {
2341            if (mNesting == 1) {
2342                final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2343                mTotalDurationMs += durationMs;
2344                if (durationMs > mMaxDurationMs) {
2345                    mMaxDurationMs = durationMs;
2346                }
2347                mStartTimeMs = -1;
2348                mCurrentDurationMs = 0;
2349            }
2350            // super method decrements mNesting, which getCurrentDurationMsLocked relies on,
2351            // so call super.stopRunningLocked after calling getCurrentDurationMsLocked.
2352            super.stopRunningLocked(elapsedRealtimeMs);
2353        }
2354
2355        @Override
2356        public boolean reset(boolean detachIfReset) {
2357            boolean result = super.reset(detachIfReset);
2358            mMaxDurationMs = 0;
2359            mTotalDurationMs = 0;
2360            mCurrentDurationMs = 0;
2361            if (mNesting > 0) {
2362                mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000;
2363            } else {
2364                mStartTimeMs = -1;
2365            }
2366            return result;
2367        }
2368
2369        /**
2370         * Returns the max duration that this timer has ever seen.
2371         *
2372         * Note that this time is NOT split between the timers in the timer group that
2373         * this timer is attached to.  It is the TOTAL time.
2374         */
2375        @Override
2376        public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
2377            if (mNesting > 0) {
2378                final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2379                if (durationMs > mMaxDurationMs) {
2380                    return durationMs;
2381                }
2382            }
2383            return mMaxDurationMs;
2384        }
2385
2386        /**
2387         * Returns the time since the timer was started.
2388         * Returns 0 if the timer is not currently running.
2389         *
2390         * Note that this time is NOT split between the timers in the timer group that
2391         * this timer is attached to.  It is the TOTAL time.
2392         *
2393         * Note that if running timer is parceled and unparceled, this method will return
2394         * current duration value at the time of parceling even though timer may not be
2395         * currently running.
2396         */
2397        @Override
2398        public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
2399            long durationMs = mCurrentDurationMs;
2400            if (mNesting > 0 && mTimeBase.isRunning()) {
2401                durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs*1000)/1000)
2402                        - mStartTimeMs;
2403            }
2404            return durationMs;
2405        }
2406
2407        /**
2408         * Returns the total cumulative duration that this timer has been on since reset().
2409         * If mTimerPool == null, this should be the same
2410         * as getTotalTimeLocked(elapsedRealtimeMs*1000, STATS_SINCE_CHARGED)/1000.
2411         *
2412         * Note that this time is NOT split between the timers in the timer group that
2413         * this timer is attached to.  It is the TOTAL time. For this reason, if mTimerPool != null,
2414         * the result will not be equivalent to getTotalTimeLocked.
2415         */
2416        @Override
2417        public long getTotalDurationMsLocked(long elapsedRealtimeMs) {
2418            return mTotalDurationMs + getCurrentDurationMsLocked(elapsedRealtimeMs);
2419        }
2420    }
2421
2422    /**
2423     * State for keeping track of timing information.
2424     */
2425    public static class StopwatchTimer extends Timer {
2426        final Uid mUid;
2427        final ArrayList<StopwatchTimer> mTimerPool;
2428
2429        int mNesting;
2430
2431        /**
2432         * The last time at which we updated the timer.  If mNesting is > 0,
2433         * subtract this from the current battery time to find the amount of
2434         * time we have been running since we last computed an update.
2435         */
2436        long mUpdateTime;
2437
2438        /**
2439         * The total time at which the timer was acquired, to determine if it
2440         * was actually held for an interesting duration. If time base was not running when timer
2441         * was acquired, will be -1.
2442         */
2443        long mAcquireTime = -1;
2444
2445        long mTimeout;
2446
2447        /**
2448         * For partial wake locks, keep track of whether we are in the list
2449         * to consume CPU cycles.
2450         */
2451        @VisibleForTesting
2452        public boolean mInList;
2453
2454        public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2455                TimeBase timeBase, Parcel in) {
2456            super(clocks, type, timeBase, in);
2457            mUid = uid;
2458            mTimerPool = timerPool;
2459            mUpdateTime = in.readLong();
2460        }
2461
2462        public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2463                TimeBase timeBase) {
2464            super(clocks, type, timeBase);
2465            mUid = uid;
2466            mTimerPool = timerPool;
2467        }
2468
2469        public void setTimeout(long timeout) {
2470            mTimeout = timeout;
2471        }
2472
2473        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2474            super.writeToParcel(out, elapsedRealtimeUs);
2475            out.writeLong(mUpdateTime);
2476        }
2477
2478        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
2479            if (mNesting > 0) {
2480                if (DEBUG && mType < 0) {
2481                    Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
2482                }
2483                super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
2484                mUpdateTime = baseRealtime;
2485                if (DEBUG && mType < 0) {
2486                    Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
2487                }
2488            }
2489        }
2490
2491        public void logState(Printer pw, String prefix) {
2492            super.logState(pw, prefix);
2493            pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTime
2494                    + " mAcquireTime=" + mAcquireTime);
2495        }
2496
2497        public void startRunningLocked(long elapsedRealtimeMs) {
2498            if (mNesting++ == 0) {
2499                final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2500                mUpdateTime = batteryRealtime;
2501                if (mTimerPool != null) {
2502                    // Accumulate time to all currently active timers before adding
2503                    // this new one to the pool.
2504                    refreshTimersLocked(batteryRealtime, mTimerPool, null);
2505                    // Add this timer to the active pool
2506                    mTimerPool.add(this);
2507                }
2508                if (mTimeBase.isRunning()) {
2509                    // Increment the count
2510                    mCount++;
2511                    mAcquireTime = mTotalTime;
2512                } else {
2513                    mAcquireTime = -1;
2514                }
2515                if (DEBUG && mType < 0) {
2516                    Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
2517                            + " mTotalTime=" + mTotalTime + " mCount=" + mCount
2518                            + " mAcquireTime=" + mAcquireTime);
2519                }
2520            }
2521        }
2522
2523        public boolean isRunningLocked() {
2524            return mNesting > 0;
2525        }
2526
2527        public void stopRunningLocked(long elapsedRealtimeMs) {
2528            // Ignore attempt to stop a timer that isn't running
2529            if (mNesting == 0) {
2530                return;
2531            }
2532            if (--mNesting == 0) {
2533                final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2534                if (mTimerPool != null) {
2535                    // Accumulate time to all active counters, scaled by the total
2536                    // active in the pool, before taking this one out of the pool.
2537                    refreshTimersLocked(batteryRealtime, mTimerPool, null);
2538                    // Remove this timer from the active pool
2539                    mTimerPool.remove(this);
2540                } else {
2541                    mNesting = 1;
2542                    mTotalTime = computeRunTimeLocked(batteryRealtime);
2543                    mNesting = 0;
2544                }
2545
2546                if (DEBUG && mType < 0) {
2547                    Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
2548                            + " mTotalTime=" + mTotalTime + " mCount=" + mCount
2549                            + " mAcquireTime=" + mAcquireTime);
2550                }
2551
2552                if (mAcquireTime >= 0 && mTotalTime == mAcquireTime) {
2553                    // If there was no change in the time, then discard this
2554                    // count.  A somewhat cheezy strategy, but hey.
2555                    mCount--;
2556                }
2557            }
2558        }
2559
2560        public void stopAllRunningLocked(long elapsedRealtimeMs) {
2561            if (mNesting > 0) {
2562                mNesting = 1;
2563                stopRunningLocked(elapsedRealtimeMs);
2564            }
2565        }
2566
2567        // Update the total time for all other running Timers with the same type as this Timer
2568        // due to a change in timer count
2569        private static long refreshTimersLocked(long batteryRealtime,
2570                final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
2571            long selfTime = 0;
2572            final int N = pool.size();
2573            for (int i=N-1; i>= 0; i--) {
2574                final StopwatchTimer t = pool.get(i);
2575                long heldTime = batteryRealtime - t.mUpdateTime;
2576                if (heldTime > 0) {
2577                    final long myTime = heldTime / N;
2578                    if (t == self) {
2579                        selfTime = myTime;
2580                    }
2581                    t.mTotalTime += myTime;
2582                }
2583                t.mUpdateTime = batteryRealtime;
2584            }
2585            return selfTime;
2586        }
2587
2588        @Override
2589        protected long computeRunTimeLocked(long curBatteryRealtime) {
2590            if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) {
2591                curBatteryRealtime = mUpdateTime + mTimeout;
2592            }
2593            return mTotalTime + (mNesting > 0
2594                    ? (curBatteryRealtime - mUpdateTime)
2595                            / (mTimerPool != null ? mTimerPool.size() : 1)
2596                    : 0);
2597        }
2598
2599        @Override
2600        protected int computeCurrentCountLocked() {
2601            return mCount;
2602        }
2603
2604        @Override
2605        public boolean reset(boolean detachIfReset) {
2606            boolean canDetach = mNesting <= 0;
2607            super.reset(canDetach && detachIfReset);
2608            if (mNesting > 0) {
2609                mUpdateTime = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000);
2610            }
2611            mAcquireTime = -1; // to ensure mCount isn't decreased to -1 if timer is stopped later.
2612            return canDetach;
2613        }
2614
2615        @Override
2616        public void detach() {
2617            super.detach();
2618            if (mTimerPool != null) {
2619                mTimerPool.remove(this);
2620            }
2621        }
2622
2623        @Override
2624        public void readSummaryFromParcelLocked(Parcel in) {
2625            super.readSummaryFromParcelLocked(in);
2626            mNesting = 0;
2627        }
2628
2629        /**
2630         * Set the mark so that we can query later for the total time the timer has
2631         * accumulated since this point. The timer can be running or not.
2632         *
2633         * @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
2634         */
2635        public void setMark(long elapsedRealtimeMs) {
2636            final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2637            if (mNesting > 0) {
2638                // We are running.
2639                if (mTimerPool != null) {
2640                    refreshTimersLocked(batteryRealtime, mTimerPool, this);
2641                } else {
2642                    mTotalTime += batteryRealtime - mUpdateTime;
2643                    mUpdateTime = batteryRealtime;
2644                }
2645            }
2646            mTimeBeforeMark = mTotalTime;
2647        }
2648    }
2649
2650    /**
2651     * State for keeping track of two DurationTimers with different TimeBases, presumably where one
2652     * TimeBase is effectively a subset of the other.
2653     */
2654    public static class DualTimer extends DurationTimer {
2655        // This class both is a DurationTimer and also holds a second DurationTimer.
2656        // The main timer (this) typically tracks the total time. It may be pooled (but since it's a
2657        // durationTimer, it also has the unpooled getTotalDurationMsLocked() for
2658        // STATS_SINCE_CHARGED).
2659        // mSubTimer typically tracks only part of the total time, such as background time, as
2660        // determined by a subTimeBase. It is NOT pooled.
2661        private final DurationTimer mSubTimer;
2662
2663        /**
2664         * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2665         * The main timer (this) is based on the given timeBase and timerPool.
2666         * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2667         * the main timer is.
2668         */
2669        public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2670                TimeBase timeBase, TimeBase subTimeBase, Parcel in) {
2671            super(clocks, uid, type, timerPool, timeBase, in);
2672            mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase, in);
2673        }
2674
2675        /**
2676         * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2677         * The main timer (this) is based on the given timeBase and timerPool.
2678         * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2679         * the main timer is.
2680         */
2681        public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2682                TimeBase timeBase, TimeBase subTimeBase) {
2683            super(clocks, uid, type, timerPool, timeBase);
2684            mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase);
2685        }
2686
2687        /** Get the secondary timer. */
2688        @Override
2689        public DurationTimer getSubTimer() {
2690            return mSubTimer;
2691        }
2692
2693        @Override
2694        public void startRunningLocked(long elapsedRealtimeMs) {
2695            super.startRunningLocked(elapsedRealtimeMs);
2696            mSubTimer.startRunningLocked(elapsedRealtimeMs);
2697        }
2698
2699        @Override
2700        public void stopRunningLocked(long elapsedRealtimeMs) {
2701            super.stopRunningLocked(elapsedRealtimeMs);
2702            mSubTimer.stopRunningLocked(elapsedRealtimeMs);
2703        }
2704
2705        @Override
2706        public void stopAllRunningLocked(long elapsedRealtimeMs) {
2707            super.stopAllRunningLocked(elapsedRealtimeMs);
2708            mSubTimer.stopAllRunningLocked(elapsedRealtimeMs);
2709        }
2710
2711        @Override
2712        public boolean reset(boolean detachIfReset) {
2713            boolean active = false;
2714            // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
2715            active |= !mSubTimer.reset(false);
2716            active |= !super.reset(detachIfReset);
2717            return !active;
2718        }
2719
2720        @Override
2721        public void detach() {
2722            mSubTimer.detach();
2723            super.detach();
2724        }
2725
2726        @Override
2727        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2728            super.writeToParcel(out, elapsedRealtimeUs);
2729            mSubTimer.writeToParcel(out, elapsedRealtimeUs);
2730        }
2731
2732        @Override
2733        public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2734            super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2735            mSubTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2736        }
2737
2738        @Override
2739        public void readSummaryFromParcelLocked(Parcel in) {
2740            super.readSummaryFromParcelLocked(in);
2741            mSubTimer.readSummaryFromParcelLocked(in);
2742        }
2743    }
2744
2745
2746    public abstract class OverflowArrayMap<T> {
2747        private static final String OVERFLOW_NAME = "*overflow*";
2748
2749        final int mUid;
2750        final ArrayMap<String, T> mMap = new ArrayMap<>();
2751        T mCurOverflow;
2752        ArrayMap<String, MutableInt> mActiveOverflow;
2753        long mLastOverflowTime;
2754        long mLastOverflowFinishTime;
2755        long mLastClearTime;
2756        long mLastCleanupTime;
2757
2758        public OverflowArrayMap(int uid) {
2759            mUid = uid;
2760        }
2761
2762        public ArrayMap<String, T> getMap() {
2763            return mMap;
2764        }
2765
2766        public void clear() {
2767            mLastClearTime = SystemClock.elapsedRealtime();
2768            mMap.clear();
2769            mCurOverflow = null;
2770            mActiveOverflow = null;
2771        }
2772
2773        public void add(String name, T obj) {
2774            if (name == null) {
2775                name = "";
2776            }
2777            mMap.put(name, obj);
2778            if (OVERFLOW_NAME.equals(name)) {
2779                mCurOverflow = obj;
2780            }
2781        }
2782
2783        public void cleanup() {
2784            mLastCleanupTime = SystemClock.elapsedRealtime();
2785            if (mActiveOverflow != null) {
2786                if (mActiveOverflow.size() == 0) {
2787                    mActiveOverflow = null;
2788                }
2789            }
2790            if (mActiveOverflow == null) {
2791                // There is no currently active overflow, so we should no longer have
2792                // an overflow entry.
2793                if (mMap.containsKey(OVERFLOW_NAME)) {
2794                    Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
2795                            + mMap.get(OVERFLOW_NAME));
2796                    mMap.remove(OVERFLOW_NAME);
2797                }
2798                mCurOverflow = null;
2799            } else {
2800                // There is currently active overflow, so we should still have an overflow entry.
2801                if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
2802                    Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
2803                            + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
2804                }
2805            }
2806        }
2807
2808        public T startObject(String name) {
2809            if (name == null) {
2810                name = "";
2811            }
2812            T obj = mMap.get(name);
2813            if (obj != null) {
2814                return obj;
2815            }
2816
2817            // No object exists for the given name, but do we currently have it
2818            // running as part of the overflow?
2819            if (mActiveOverflow != null) {
2820                MutableInt over = mActiveOverflow.get(name);
2821                if (over != null) {
2822                    // We are already actively counting this name in the overflow object.
2823                    obj = mCurOverflow;
2824                    if (obj == null) {
2825                        // Shouldn't be here, but we'll try to recover.
2826                        Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
2827                        obj = mCurOverflow = instantiateObject();
2828                        mMap.put(OVERFLOW_NAME, obj);
2829                    }
2830                    over.value++;
2831                    return obj;
2832                }
2833            }
2834
2835            // No object exists for given name nor in the overflow; we need to make
2836            // a new one.
2837            final int N = mMap.size();
2838            if (N >= MAX_WAKELOCKS_PER_UID) {
2839                // Went over the limit on number of objects to track; this one goes
2840                // in to the overflow.
2841                obj = mCurOverflow;
2842                if (obj == null) {
2843                    // Need to start overflow now...
2844                    obj = mCurOverflow = instantiateObject();
2845                    mMap.put(OVERFLOW_NAME, obj);
2846                }
2847                if (mActiveOverflow == null) {
2848                    mActiveOverflow = new ArrayMap<>();
2849                }
2850                mActiveOverflow.put(name, new MutableInt(1));
2851                mLastOverflowTime = SystemClock.elapsedRealtime();
2852                return obj;
2853            }
2854
2855            // Normal case where we just need to make a new object.
2856            obj = instantiateObject();
2857            mMap.put(name, obj);
2858            return obj;
2859        }
2860
2861        public T stopObject(String name) {
2862            if (name == null) {
2863                name = "";
2864            }
2865            T obj = mMap.get(name);
2866            if (obj != null) {
2867                return obj;
2868            }
2869
2870            // No object exists for the given name, but do we currently have it
2871            // running as part of the overflow?
2872            if (mActiveOverflow != null) {
2873                MutableInt over = mActiveOverflow.get(name);
2874                if (over != null) {
2875                    // We are already actively counting this name in the overflow object.
2876                    obj = mCurOverflow;
2877                    if (obj != null) {
2878                        over.value--;
2879                        if (over.value <= 0) {
2880                            mActiveOverflow.remove(name);
2881                            mLastOverflowFinishTime = SystemClock.elapsedRealtime();
2882                        }
2883                        return obj;
2884                    }
2885                }
2886            }
2887
2888            // Huh, they are stopping an active operation but we can't find one!
2889            // That's not good.
2890            StringBuilder sb = new StringBuilder();
2891            sb.append("Unable to find object for ");
2892            sb.append(name);
2893            sb.append(" in uid ");
2894            sb.append(mUid);
2895            sb.append(" mapsize=");
2896            sb.append(mMap.size());
2897            sb.append(" activeoverflow=");
2898            sb.append(mActiveOverflow);
2899            sb.append(" curoverflow=");
2900            sb.append(mCurOverflow);
2901            long now = SystemClock.elapsedRealtime();
2902            if (mLastOverflowTime != 0) {
2903                sb.append(" lastOverflowTime=");
2904                TimeUtils.formatDuration(mLastOverflowTime-now, sb);
2905            }
2906            if (mLastOverflowFinishTime != 0) {
2907                sb.append(" lastOverflowFinishTime=");
2908                TimeUtils.formatDuration(mLastOverflowFinishTime-now, sb);
2909            }
2910            if (mLastClearTime != 0) {
2911                sb.append(" lastClearTime=");
2912                TimeUtils.formatDuration(mLastClearTime-now, sb);
2913            }
2914            if (mLastCleanupTime != 0) {
2915                sb.append(" lastCleanupTime=");
2916                TimeUtils.formatDuration(mLastCleanupTime-now, sb);
2917            }
2918            Slog.wtf(TAG, sb.toString());
2919            return null;
2920        }
2921
2922        public abstract T instantiateObject();
2923    }
2924
2925    public static class ControllerActivityCounterImpl extends ControllerActivityCounter
2926            implements Parcelable {
2927        private final LongSamplingCounter mIdleTimeMillis;
2928        private final LongSamplingCounter mScanTimeMillis;
2929        private final LongSamplingCounter mSleepTimeMillis;
2930        private final LongSamplingCounter mRxTimeMillis;
2931        private final LongSamplingCounter[] mTxTimeMillis;
2932        private final LongSamplingCounter mPowerDrainMaMs;
2933
2934        public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates) {
2935            mIdleTimeMillis = new LongSamplingCounter(timeBase);
2936            mScanTimeMillis = new LongSamplingCounter(timeBase);
2937            mSleepTimeMillis = new LongSamplingCounter(timeBase);
2938            mRxTimeMillis = new LongSamplingCounter(timeBase);
2939            mTxTimeMillis = new LongSamplingCounter[numTxStates];
2940            for (int i = 0; i < numTxStates; i++) {
2941                mTxTimeMillis[i] = new LongSamplingCounter(timeBase);
2942            }
2943            mPowerDrainMaMs = new LongSamplingCounter(timeBase);
2944        }
2945
2946        public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in) {
2947            mIdleTimeMillis = new LongSamplingCounter(timeBase, in);
2948            mScanTimeMillis = new LongSamplingCounter(timeBase, in);
2949            mSleepTimeMillis = new LongSamplingCounter(timeBase, in);
2950            mRxTimeMillis = new LongSamplingCounter(timeBase, in);
2951            final int recordedTxStates = in.readInt();
2952            if (recordedTxStates != numTxStates) {
2953                throw new ParcelFormatException("inconsistent tx state lengths");
2954            }
2955
2956            mTxTimeMillis = new LongSamplingCounter[numTxStates];
2957            for (int i = 0; i < numTxStates; i++) {
2958                mTxTimeMillis[i] = new LongSamplingCounter(timeBase, in);
2959            }
2960            mPowerDrainMaMs = new LongSamplingCounter(timeBase, in);
2961        }
2962
2963        public void readSummaryFromParcel(Parcel in) {
2964            mIdleTimeMillis.readSummaryFromParcelLocked(in);
2965            mScanTimeMillis.readSummaryFromParcelLocked(in);
2966            mSleepTimeMillis.readSummaryFromParcelLocked(in);
2967            mRxTimeMillis.readSummaryFromParcelLocked(in);
2968            final int recordedTxStates = in.readInt();
2969            if (recordedTxStates != mTxTimeMillis.length) {
2970                throw new ParcelFormatException("inconsistent tx state lengths");
2971            }
2972            for (LongSamplingCounter counter : mTxTimeMillis) {
2973                counter.readSummaryFromParcelLocked(in);
2974            }
2975            mPowerDrainMaMs.readSummaryFromParcelLocked(in);
2976        }
2977
2978        @Override
2979        public int describeContents() {
2980            return 0;
2981        }
2982
2983        public void writeSummaryToParcel(Parcel dest) {
2984            mIdleTimeMillis.writeSummaryFromParcelLocked(dest);
2985            mScanTimeMillis.writeSummaryFromParcelLocked(dest);
2986            mSleepTimeMillis.writeSummaryFromParcelLocked(dest);
2987            mRxTimeMillis.writeSummaryFromParcelLocked(dest);
2988            dest.writeInt(mTxTimeMillis.length);
2989            for (LongSamplingCounter counter : mTxTimeMillis) {
2990                counter.writeSummaryFromParcelLocked(dest);
2991            }
2992            mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
2993        }
2994
2995        @Override
2996        public void writeToParcel(Parcel dest, int flags) {
2997            mIdleTimeMillis.writeToParcel(dest);
2998            mScanTimeMillis.writeToParcel(dest);
2999            mSleepTimeMillis.writeToParcel(dest);
3000            mRxTimeMillis.writeToParcel(dest);
3001            dest.writeInt(mTxTimeMillis.length);
3002            for (LongSamplingCounter counter : mTxTimeMillis) {
3003                counter.writeToParcel(dest);
3004            }
3005            mPowerDrainMaMs.writeToParcel(dest);
3006        }
3007
3008        public void reset(boolean detachIfReset) {
3009            mIdleTimeMillis.reset(detachIfReset);
3010            mScanTimeMillis.reset(detachIfReset);
3011            mSleepTimeMillis.reset(detachIfReset);
3012            mRxTimeMillis.reset(detachIfReset);
3013            for (LongSamplingCounter counter : mTxTimeMillis) {
3014                counter.reset(detachIfReset);
3015            }
3016            mPowerDrainMaMs.reset(detachIfReset);
3017        }
3018
3019        public void detach() {
3020            mIdleTimeMillis.detach();
3021            mScanTimeMillis.detach();
3022            mSleepTimeMillis.detach();
3023            mRxTimeMillis.detach();
3024            for (LongSamplingCounter counter : mTxTimeMillis) {
3025                counter.detach();
3026            }
3027            mPowerDrainMaMs.detach();
3028        }
3029
3030        /**
3031         * @return a LongSamplingCounter, measuring time spent in the idle state in
3032         * milliseconds.
3033         */
3034        @Override
3035        public LongSamplingCounter getIdleTimeCounter() {
3036            return mIdleTimeMillis;
3037        }
3038
3039        /**
3040         * @return a LongSamplingCounter, measuring time spent in the scan state in
3041         * milliseconds.
3042         */
3043        @Override
3044        public LongSamplingCounter getScanTimeCounter() {
3045            return mScanTimeMillis;
3046        }
3047
3048        /**
3049         * @return a LongSamplingCounter, measuring time spent in the sleep state in
3050         * milliseconds.
3051         */
3052        @Override
3053        public LongSamplingCounter getSleepTimeCounter() {
3054            return mSleepTimeMillis;
3055        }
3056
3057        /**
3058         * @return a LongSamplingCounter, measuring time spent in the receive state in
3059         * milliseconds.
3060         */
3061        @Override
3062        public LongSamplingCounter getRxTimeCounter() {
3063            return mRxTimeMillis;
3064        }
3065
3066        /**
3067         * @return a LongSamplingCounter[], measuring time spent in various transmit states in
3068         * milliseconds.
3069         */
3070        @Override
3071        public LongSamplingCounter[] getTxTimeCounters() {
3072            return mTxTimeMillis;
3073        }
3074
3075        /**
3076         * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
3077         */
3078        @Override
3079        public LongSamplingCounter getPowerCounter() {
3080            return mPowerDrainMaMs;
3081        }
3082    }
3083
3084    /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */
3085    public SamplingTimer getRpmTimerLocked(String name) {
3086        SamplingTimer rpmt = mRpmStats.get(name);
3087        if (rpmt == null) {
3088            rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3089            mRpmStats.put(name, rpmt);
3090        }
3091        return rpmt;
3092    }
3093
3094    /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */
3095    public SamplingTimer getScreenOffRpmTimerLocked(String name) {
3096        SamplingTimer rpmt = mScreenOffRpmStats.get(name);
3097        if (rpmt == null) {
3098            rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
3099            mScreenOffRpmStats.put(name, rpmt);
3100        }
3101        return rpmt;
3102    }
3103
3104    /*
3105     * Get the wakeup reason counter, and create a new one if one
3106     * doesn't already exist.
3107     */
3108    public SamplingTimer getWakeupReasonTimerLocked(String name) {
3109        SamplingTimer timer = mWakeupReasonStats.get(name);
3110        if (timer == null) {
3111            timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3112            mWakeupReasonStats.put(name, timer);
3113        }
3114        return timer;
3115    }
3116
3117    /*
3118     * Get the KernelWakelockTimer associated with name, and create a new one if one
3119     * doesn't already exist.
3120     */
3121    public SamplingTimer getKernelWakelockTimerLocked(String name) {
3122        SamplingTimer kwlt = mKernelWakelockStats.get(name);
3123        if (kwlt == null) {
3124            kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
3125            mKernelWakelockStats.put(name, kwlt);
3126        }
3127        return kwlt;
3128    }
3129
3130    public SamplingTimer getKernelMemoryTimerLocked(long bucket) {
3131        SamplingTimer kmt = mKernelMemoryStats.get(bucket);
3132        if (kmt == null) {
3133            kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
3134            mKernelMemoryStats.put(bucket, kmt);
3135        }
3136        return kmt;
3137    }
3138
3139    private int writeHistoryTag(HistoryTag tag) {
3140        Integer idxObj = mHistoryTagPool.get(tag);
3141        int idx;
3142        if (idxObj != null) {
3143            idx = idxObj;
3144        } else {
3145            idx = mNextHistoryTagIdx;
3146            HistoryTag key = new HistoryTag();
3147            key.setTo(tag);
3148            tag.poolIdx = idx;
3149            mHistoryTagPool.put(key, idx);
3150            mNextHistoryTagIdx++;
3151            mNumHistoryTagChars += key.string.length() + 1;
3152        }
3153        return idx;
3154    }
3155
3156    private void readHistoryTag(int index, HistoryTag tag) {
3157        tag.string = mReadHistoryStrings[index];
3158        tag.uid = mReadHistoryUids[index];
3159        tag.poolIdx = index;
3160    }
3161
3162    /*
3163        The history delta format uses flags to denote further data in subsequent ints in the parcel.
3164
3165        There is always the first token, which may contain the delta time, or an indicator of
3166        the length of the time (int or long) following this token.
3167
3168        First token: always present,
3169        31              23              15               7             0
3170        █M|L|K|J|I|H|G|F█E|D|C|B|A|T|T|T█T|T|T|T|T|T|T|T█T|T|T|T|T|T|T|T█
3171
3172        T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
3173           follows containing the time, and 0x7ffff indicates a long immediately follows with the
3174           delta time.
3175        A: battery level changed and an int follows with battery data.
3176        B: state changed and an int follows with state change data.
3177        C: state2 has changed and an int follows with state2 change data.
3178        D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
3179        E: event data has changed and an event struct follows.
3180        F: battery charge in coulombs has changed and an int with the charge follows.
3181        G: state flag denoting that the mobile radio was active.
3182        H: state flag denoting that the wifi radio was active.
3183        I: state flag denoting that a wifi scan occurred.
3184        J: state flag denoting that a wifi full lock was held.
3185        K: state flag denoting that the gps was on.
3186        L: state flag denoting that a wakelock was held.
3187        M: state flag denoting that the cpu was running.
3188
3189        Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
3190        with the time delta.
3191
3192        Battery level int: if A in the first token is set,
3193        31              23              15               7             0
3194        █L|L|L|L|L|L|L|T█T|T|T|T|T|T|T|T█T|V|V|V|V|V|V|V█V|V|V|V|V|V|V|D█
3195
3196        D: indicates that extra history details follow.
3197        V: the battery voltage.
3198        T: the battery temperature.
3199        L: the battery level (out of 100).
3200
3201        State change int: if B in the first token is set,
3202        31              23              15               7             0
3203        █S|S|S|H|H|H|P|P█F|E|D|C|B| | |A█ | | | | | | | █ | | | | | | | █
3204
3205        A: wifi multicast was on.
3206        B: battery was plugged in.
3207        C: screen was on.
3208        D: phone was scanning for signal.
3209        E: audio was on.
3210        F: a sensor was active.
3211
3212        State2 change int: if C in the first token is set,
3213        31              23              15               7             0
3214        █M|L|K|J|I|H|H|G█F|E|D|C| | | | █ | | | | | | | █ |B|B|B|A|A|A|A█
3215
3216        A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
3217        B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
3218        C: a bluetooth scan was active.
3219        D: the camera was active.
3220        E: bluetooth was on.
3221        F: a phone call was active.
3222        G: the device was charging.
3223        H: 2 bits indicating the device-idle (doze) state: off, light, full
3224        I: the flashlight was on.
3225        J: wifi was on.
3226        K: wifi was running.
3227        L: video was playing.
3228        M: power save mode was on.
3229
3230        Wakelock/wakereason struct: if D in the first token is set,
3231        TODO(adamlesinski): describe wakelock/wakereason struct.
3232
3233        Event struct: if E in the first token is set,
3234        TODO(adamlesinski): describe the event struct.
3235
3236        History step details struct: if D in the battery level int is set,
3237        TODO(adamlesinski): describe the history step details struct.
3238
3239        Battery charge int: if F in the first token is set, an int representing the battery charge
3240        in coulombs follows.
3241     */
3242
3243    // Part of initial delta int that specifies the time delta.
3244    static final int DELTA_TIME_MASK = 0x7ffff;
3245    static final int DELTA_TIME_LONG = 0x7ffff;   // The delta is a following long
3246    static final int DELTA_TIME_INT = 0x7fffe;    // The delta is a following int
3247    static final int DELTA_TIME_ABS = 0x7fffd;    // Following is an entire abs update.
3248    // Flag in delta int: a new battery level int follows.
3249    static final int DELTA_BATTERY_LEVEL_FLAG               = 0x00080000;
3250    // Flag in delta int: a new full state and battery status int follows.
3251    static final int DELTA_STATE_FLAG                       = 0x00100000;
3252    // Flag in delta int: a new full state2 int follows.
3253    static final int DELTA_STATE2_FLAG                      = 0x00200000;
3254    // Flag in delta int: contains a wakelock or wakeReason tag.
3255    static final int DELTA_WAKELOCK_FLAG                    = 0x00400000;
3256    // Flag in delta int: contains an event description.
3257    static final int DELTA_EVENT_FLAG                       = 0x00800000;
3258    // Flag in delta int: contains the battery charge count in uAh.
3259    static final int DELTA_BATTERY_CHARGE_FLAG              = 0x01000000;
3260    // These upper bits are the frequently changing state bits.
3261    static final int DELTA_STATE_MASK                       = 0xfe000000;
3262
3263    // These are the pieces of battery state that are packed in to the upper bits of
3264    // the state int that have been packed in to the first delta int.  They must fit
3265    // in STATE_BATTERY_MASK.
3266    static final int STATE_BATTERY_MASK         = 0xff000000;
3267    static final int STATE_BATTERY_STATUS_MASK  = 0x00000007;
3268    static final int STATE_BATTERY_STATUS_SHIFT = 29;
3269    static final int STATE_BATTERY_HEALTH_MASK  = 0x00000007;
3270    static final int STATE_BATTERY_HEALTH_SHIFT = 26;
3271    static final int STATE_BATTERY_PLUG_MASK    = 0x00000003;
3272    static final int STATE_BATTERY_PLUG_SHIFT   = 24;
3273
3274    // We use the low bit of the battery state int to indicate that we have full details
3275    // from a battery level change.
3276    static final int BATTERY_DELTA_LEVEL_FLAG   = 0x00000001;
3277
3278    public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
3279        if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
3280            dest.writeInt(DELTA_TIME_ABS);
3281            cur.writeToParcel(dest, 0);
3282            return;
3283        }
3284
3285        final long deltaTime = cur.time - last.time;
3286        final int lastBatteryLevelInt = buildBatteryLevelInt(last);
3287        final int lastStateInt = buildStateInt(last);
3288
3289        int deltaTimeToken;
3290        if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
3291            deltaTimeToken = DELTA_TIME_LONG;
3292        } else if (deltaTime >= DELTA_TIME_ABS) {
3293            deltaTimeToken = DELTA_TIME_INT;
3294        } else {
3295            deltaTimeToken = (int)deltaTime;
3296        }
3297        int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
3298        final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
3299                ? BATTERY_DELTA_LEVEL_FLAG : 0;
3300        final boolean computeStepDetails = includeStepDetails != 0
3301                || mLastHistoryStepDetails == null;
3302        final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
3303        final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
3304        if (batteryLevelIntChanged) {
3305            firstToken |= DELTA_BATTERY_LEVEL_FLAG;
3306        }
3307        final int stateInt = buildStateInt(cur);
3308        final boolean stateIntChanged = stateInt != lastStateInt;
3309        if (stateIntChanged) {
3310            firstToken |= DELTA_STATE_FLAG;
3311        }
3312        final boolean state2IntChanged = cur.states2 != last.states2;
3313        if (state2IntChanged) {
3314            firstToken |= DELTA_STATE2_FLAG;
3315        }
3316        if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
3317            firstToken |= DELTA_WAKELOCK_FLAG;
3318        }
3319        if (cur.eventCode != HistoryItem.EVENT_NONE) {
3320            firstToken |= DELTA_EVENT_FLAG;
3321        }
3322
3323        final boolean batteryChargeChanged = cur.batteryChargeUAh != last.batteryChargeUAh;
3324        if (batteryChargeChanged) {
3325            firstToken |= DELTA_BATTERY_CHARGE_FLAG;
3326        }
3327        dest.writeInt(firstToken);
3328        if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
3329                + " deltaTime=" + deltaTime);
3330
3331        if (deltaTimeToken >= DELTA_TIME_INT) {
3332            if (deltaTimeToken == DELTA_TIME_INT) {
3333                if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
3334                dest.writeInt((int)deltaTime);
3335            } else {
3336                if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
3337                dest.writeLong(deltaTime);
3338            }
3339        }
3340        if (batteryLevelIntChanged) {
3341            dest.writeInt(batteryLevelInt);
3342            if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
3343                    + Integer.toHexString(batteryLevelInt)
3344                    + " batteryLevel=" + cur.batteryLevel
3345                    + " batteryTemp=" + cur.batteryTemperature
3346                    + " batteryVolt=" + (int)cur.batteryVoltage);
3347        }
3348        if (stateIntChanged) {
3349            dest.writeInt(stateInt);
3350            if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
3351                    + Integer.toHexString(stateInt)
3352                    + " batteryStatus=" + cur.batteryStatus
3353                    + " batteryHealth=" + cur.batteryHealth
3354                    + " batteryPlugType=" + cur.batteryPlugType
3355                    + " states=0x" + Integer.toHexString(cur.states));
3356        }
3357        if (state2IntChanged) {
3358            dest.writeInt(cur.states2);
3359            if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x"
3360                    + Integer.toHexString(cur.states2));
3361        }
3362        if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
3363            int wakeLockIndex;
3364            int wakeReasonIndex;
3365            if (cur.wakelockTag != null) {
3366                wakeLockIndex = writeHistoryTag(cur.wakelockTag);
3367                if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
3368                    + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
3369            } else {
3370                wakeLockIndex = 0xffff;
3371            }
3372            if (cur.wakeReasonTag != null) {
3373                wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
3374                if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
3375                    + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
3376            } else {
3377                wakeReasonIndex = 0xffff;
3378            }
3379            dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
3380        }
3381        if (cur.eventCode != HistoryItem.EVENT_NONE) {
3382            int index = writeHistoryTag(cur.eventTag);
3383            int codeAndIndex = (cur.eventCode&0xffff) | (index<<16);
3384            dest.writeInt(codeAndIndex);
3385            if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
3386                    + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
3387                    + cur.eventTag.string);
3388        }
3389        if (computeStepDetails) {
3390            if (mPlatformIdleStateCallback != null) {
3391                mCurHistoryStepDetails.statPlatformIdleState =
3392                        mPlatformIdleStateCallback.getPlatformLowPowerStats();
3393                if (DEBUG) Slog.i(TAG, "WRITE PlatformIdleState:" +
3394                        mCurHistoryStepDetails.statPlatformIdleState);
3395
3396                mCurHistoryStepDetails.statSubsystemPowerState =
3397                        mPlatformIdleStateCallback.getSubsystemLowPowerStats();
3398                if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
3399                        mCurHistoryStepDetails.statSubsystemPowerState);
3400
3401            }
3402            computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
3403            if (includeStepDetails != 0) {
3404                mCurHistoryStepDetails.writeToParcel(dest);
3405            }
3406            cur.stepDetails = mCurHistoryStepDetails;
3407            mLastHistoryStepDetails = mCurHistoryStepDetails;
3408        } else {
3409            cur.stepDetails = null;
3410        }
3411        if (mLastHistoryStepLevel < cur.batteryLevel) {
3412            mLastHistoryStepDetails = null;
3413        }
3414        mLastHistoryStepLevel = cur.batteryLevel;
3415
3416        if (batteryChargeChanged) {
3417            if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUAh=" + cur.batteryChargeUAh);
3418            dest.writeInt(cur.batteryChargeUAh);
3419        }
3420    }
3421
3422    private int buildBatteryLevelInt(HistoryItem h) {
3423        return ((((int)h.batteryLevel)<<25)&0xfe000000)
3424                | ((((int)h.batteryTemperature)<<15)&0x01ff8000)
3425                | ((((int)h.batteryVoltage)<<1)&0x00007ffe);
3426    }
3427
3428    private void readBatteryLevelInt(int batteryLevelInt, HistoryItem out) {
3429        out.batteryLevel = (byte)((batteryLevelInt & 0xfe000000) >>> 25);
3430        out.batteryTemperature = (short)((batteryLevelInt & 0x01ff8000) >>> 15);
3431        out.batteryVoltage = (char)((batteryLevelInt & 0x00007ffe) >>> 1);
3432    }
3433
3434    private int buildStateInt(HistoryItem h) {
3435        int plugType = 0;
3436        if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
3437            plugType = 1;
3438        } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
3439            plugType = 2;
3440        } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
3441            plugType = 3;
3442        }
3443        return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT)
3444                | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT)
3445                | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT)
3446                | (h.states&(~STATE_BATTERY_MASK));
3447    }
3448
3449    private void computeHistoryStepDetails(final HistoryStepDetails out,
3450            final HistoryStepDetails last) {
3451        final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
3452
3453        // Perform a CPU update right after we do this collection, so we have started
3454        // collecting good data for the next step.
3455        requestImmediateCpuUpdate();
3456
3457        if (last == null) {
3458            // We are not generating a delta, so all we need to do is reset the stats
3459            // we will later be doing a delta from.
3460            final int NU = mUidStats.size();
3461            for (int i=0; i<NU; i++) {
3462                final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3463                uid.mLastStepUserTime = uid.mCurStepUserTime;
3464                uid.mLastStepSystemTime = uid.mCurStepSystemTime;
3465            }
3466            mLastStepCpuUserTime = mCurStepCpuUserTime;
3467            mLastStepCpuSystemTime = mCurStepCpuSystemTime;
3468            mLastStepStatUserTime = mCurStepStatUserTime;
3469            mLastStepStatSystemTime = mCurStepStatSystemTime;
3470            mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
3471            mLastStepStatIrqTime = mCurStepStatIrqTime;
3472            mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
3473            mLastStepStatIdleTime = mCurStepStatIdleTime;
3474            tmp.clear();
3475            return;
3476        }
3477        if (DEBUG) {
3478            Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTime + " sys="
3479                    + mLastStepStatSystemTime + " io=" + mLastStepStatIOWaitTime
3480                    + " irq=" + mLastStepStatIrqTime + " sirq="
3481                    + mLastStepStatSoftIrqTime + " idle=" + mLastStepStatIdleTime);
3482            Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTime + " sys="
3483                    + mCurStepStatSystemTime + " io=" + mCurStepStatIOWaitTime
3484                    + " irq=" + mCurStepStatIrqTime + " sirq="
3485                    + mCurStepStatSoftIrqTime + " idle=" + mCurStepStatIdleTime);
3486        }
3487        out.userTime = (int)(mCurStepCpuUserTime - mLastStepCpuUserTime);
3488        out.systemTime = (int)(mCurStepCpuSystemTime - mLastStepCpuSystemTime);
3489        out.statUserTime = (int)(mCurStepStatUserTime - mLastStepStatUserTime);
3490        out.statSystemTime = (int)(mCurStepStatSystemTime - mLastStepStatSystemTime);
3491        out.statIOWaitTime = (int)(mCurStepStatIOWaitTime - mLastStepStatIOWaitTime);
3492        out.statIrqTime = (int)(mCurStepStatIrqTime - mLastStepStatIrqTime);
3493        out.statSoftIrqTime = (int)(mCurStepStatSoftIrqTime - mLastStepStatSoftIrqTime);
3494        out.statIdlTime = (int)(mCurStepStatIdleTime - mLastStepStatIdleTime);
3495        out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
3496        out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
3497        out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
3498        final int NU = mUidStats.size();
3499        for (int i=0; i<NU; i++) {
3500            final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3501            final int totalUTime = (int)(uid.mCurStepUserTime - uid.mLastStepUserTime);
3502            final int totalSTime = (int)(uid.mCurStepSystemTime - uid.mLastStepSystemTime);
3503            final int totalTime = totalUTime + totalSTime;
3504            uid.mLastStepUserTime = uid.mCurStepUserTime;
3505            uid.mLastStepSystemTime = uid.mCurStepSystemTime;
3506            if (totalTime <= (out.appCpuUTime3+out.appCpuSTime3)) {
3507                continue;
3508            }
3509            if (totalTime <= (out.appCpuUTime2+out.appCpuSTime2)) {
3510                out.appCpuUid3 = uid.mUid;
3511                out.appCpuUTime3 = totalUTime;
3512                out.appCpuSTime3 = totalSTime;
3513            } else {
3514                out.appCpuUid3 = out.appCpuUid2;
3515                out.appCpuUTime3 = out.appCpuUTime2;
3516                out.appCpuSTime3 = out.appCpuSTime2;
3517                if (totalTime <= (out.appCpuUTime1+out.appCpuSTime1)) {
3518                    out.appCpuUid2 = uid.mUid;
3519                    out.appCpuUTime2 = totalUTime;
3520                    out.appCpuSTime2 = totalSTime;
3521                } else {
3522                    out.appCpuUid2 = out.appCpuUid1;
3523                    out.appCpuUTime2 = out.appCpuUTime1;
3524                    out.appCpuSTime2 = out.appCpuSTime1;
3525                    out.appCpuUid1 = uid.mUid;
3526                    out.appCpuUTime1 = totalUTime;
3527                    out.appCpuSTime1 = totalSTime;
3528                }
3529            }
3530        }
3531        mLastStepCpuUserTime = mCurStepCpuUserTime;
3532        mLastStepCpuSystemTime = mCurStepCpuSystemTime;
3533        mLastStepStatUserTime = mCurStepStatUserTime;
3534        mLastStepStatSystemTime = mCurStepStatSystemTime;
3535        mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
3536        mLastStepStatIrqTime = mCurStepStatIrqTime;
3537        mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
3538        mLastStepStatIdleTime = mCurStepStatIdleTime;
3539    }
3540
3541    public void readHistoryDelta(Parcel src, HistoryItem cur) {
3542        int firstToken = src.readInt();
3543        int deltaTimeToken = firstToken&DELTA_TIME_MASK;
3544        cur.cmd = HistoryItem.CMD_UPDATE;
3545        cur.numReadInts = 1;
3546        if (DEBUG) Slog.i(TAG, "READ DELTA: firstToken=0x" + Integer.toHexString(firstToken)
3547                + " deltaTimeToken=" + deltaTimeToken);
3548
3549        if (deltaTimeToken < DELTA_TIME_ABS) {
3550            cur.time += deltaTimeToken;
3551        } else if (deltaTimeToken == DELTA_TIME_ABS) {
3552            cur.time = src.readLong();
3553            cur.numReadInts += 2;
3554            if (DEBUG) Slog.i(TAG, "READ DELTA: ABS time=" + cur.time);
3555            cur.readFromParcel(src);
3556            return;
3557        } else if (deltaTimeToken == DELTA_TIME_INT) {
3558            int delta = src.readInt();
3559            cur.time += delta;
3560            cur.numReadInts += 1;
3561            if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
3562        } else {
3563            long delta = src.readLong();
3564            if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
3565            cur.time += delta;
3566            cur.numReadInts += 2;
3567        }
3568
3569        final int batteryLevelInt;
3570        if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
3571            batteryLevelInt = src.readInt();
3572            readBatteryLevelInt(batteryLevelInt, cur);
3573            cur.numReadInts += 1;
3574            if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x"
3575                    + Integer.toHexString(batteryLevelInt)
3576                    + " batteryLevel=" + cur.batteryLevel
3577                    + " batteryTemp=" + cur.batteryTemperature
3578                    + " batteryVolt=" + (int)cur.batteryVoltage);
3579        } else {
3580            batteryLevelInt = 0;
3581        }
3582
3583        if ((firstToken&DELTA_STATE_FLAG) != 0) {
3584            int stateInt = src.readInt();
3585            cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~STATE_BATTERY_MASK));
3586            cur.batteryStatus = (byte)((stateInt>>STATE_BATTERY_STATUS_SHIFT)
3587                    & STATE_BATTERY_STATUS_MASK);
3588            cur.batteryHealth = (byte)((stateInt>>STATE_BATTERY_HEALTH_SHIFT)
3589                    & STATE_BATTERY_HEALTH_MASK);
3590            cur.batteryPlugType = (byte)((stateInt>>STATE_BATTERY_PLUG_SHIFT)
3591                    & STATE_BATTERY_PLUG_MASK);
3592            switch (cur.batteryPlugType) {
3593                case 1:
3594                    cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_AC;
3595                    break;
3596                case 2:
3597                    cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_USB;
3598                    break;
3599                case 3:
3600                    cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
3601                    break;
3602            }
3603            cur.numReadInts += 1;
3604            if (DEBUG) Slog.i(TAG, "READ DELTA: stateToken=0x"
3605                    + Integer.toHexString(stateInt)
3606                    + " batteryStatus=" + cur.batteryStatus
3607                    + " batteryHealth=" + cur.batteryHealth
3608                    + " batteryPlugType=" + cur.batteryPlugType
3609                    + " states=0x" + Integer.toHexString(cur.states));
3610        } else {
3611            cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~STATE_BATTERY_MASK));
3612        }
3613
3614        if ((firstToken&DELTA_STATE2_FLAG) != 0) {
3615            cur.states2 = src.readInt();
3616            if (DEBUG) Slog.i(TAG, "READ DELTA: states2=0x"
3617                    + Integer.toHexString(cur.states2));
3618        }
3619
3620        if ((firstToken&DELTA_WAKELOCK_FLAG) != 0) {
3621            int indexes = src.readInt();
3622            int wakeLockIndex = indexes&0xffff;
3623            int wakeReasonIndex = (indexes>>16)&0xffff;
3624            if (wakeLockIndex != 0xffff) {
3625                cur.wakelockTag = cur.localWakelockTag;
3626                readHistoryTag(wakeLockIndex, cur.wakelockTag);
3627                if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
3628                    + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
3629            } else {
3630                cur.wakelockTag = null;
3631            }
3632            if (wakeReasonIndex != 0xffff) {
3633                cur.wakeReasonTag = cur.localWakeReasonTag;
3634                readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
3635                if (DEBUG) Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
3636                    + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
3637            } else {
3638                cur.wakeReasonTag = null;
3639            }
3640            cur.numReadInts += 1;
3641        } else {
3642            cur.wakelockTag = null;
3643            cur.wakeReasonTag = null;
3644        }
3645
3646        if ((firstToken&DELTA_EVENT_FLAG) != 0) {
3647            cur.eventTag = cur.localEventTag;
3648            final int codeAndIndex = src.readInt();
3649            cur.eventCode = (codeAndIndex&0xffff);
3650            final int index = ((codeAndIndex>>16)&0xffff);
3651            readHistoryTag(index, cur.eventTag);
3652            cur.numReadInts += 1;
3653            if (DEBUG) Slog.i(TAG, "READ DELTA: event=" + cur.eventCode + " tag=#"
3654                    + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
3655                    + cur.eventTag.string);
3656        } else {
3657            cur.eventCode = HistoryItem.EVENT_NONE;
3658        }
3659
3660        if ((batteryLevelInt&BATTERY_DELTA_LEVEL_FLAG) != 0) {
3661            cur.stepDetails = mReadHistoryStepDetails;
3662            cur.stepDetails.readFromParcel(src);
3663        } else {
3664            cur.stepDetails = null;
3665        }
3666
3667        if ((firstToken&DELTA_BATTERY_CHARGE_FLAG) != 0) {
3668            cur.batteryChargeUAh = src.readInt();
3669        }
3670    }
3671
3672    @Override
3673    public void commitCurrentHistoryBatchLocked() {
3674        mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
3675    }
3676
3677    void addHistoryBufferLocked(long elapsedRealtimeMs, HistoryItem cur) {
3678        if (!mHaveBatteryLevel || !mRecordingHistory) {
3679            return;
3680        }
3681
3682        final long timeDiff = (mHistoryBaseTime+elapsedRealtimeMs) - mHistoryLastWritten.time;
3683        final int diffStates = mHistoryLastWritten.states^(cur.states&mActiveHistoryStates);
3684        final int diffStates2 = mHistoryLastWritten.states2^(cur.states2&mActiveHistoryStates2);
3685        final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
3686        final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
3687        if (DEBUG) Slog.i(TAG, "ADD: tdelta=" + timeDiff + " diff="
3688                + Integer.toHexString(diffStates) + " lastDiff="
3689                + Integer.toHexString(lastDiffStates) + " diff2="
3690                + Integer.toHexString(diffStates2) + " lastDiff2="
3691                + Integer.toHexString(lastDiffStates2));
3692        if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
3693                && timeDiff < 1000 && (diffStates&lastDiffStates) == 0
3694                && (diffStates2&lastDiffStates2) == 0
3695                && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
3696                && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
3697                && mHistoryLastWritten.stepDetails == null
3698                && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
3699                        || cur.eventCode == HistoryItem.EVENT_NONE)
3700                && mHistoryLastWritten.batteryLevel == cur.batteryLevel
3701                && mHistoryLastWritten.batteryStatus == cur.batteryStatus
3702                && mHistoryLastWritten.batteryHealth == cur.batteryHealth
3703                && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
3704                && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
3705                && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
3706            // We can merge this new change in with the last one.  Merging is
3707            // allowed as long as only the states have changed, and within those states
3708            // as long as no bit has changed both between now and the last entry, as
3709            // well as the last entry and the one before it (so we capture any toggles).
3710            if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
3711            mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
3712            mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
3713            mHistoryBufferLastPos = -1;
3714            elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTime;
3715            // If the last written history had a wakelock tag, we need to retain it.
3716            // Note that the condition above made sure that we aren't in a case where
3717            // both it and the current history item have a wakelock tag.
3718            if (mHistoryLastWritten.wakelockTag != null) {
3719                cur.wakelockTag = cur.localWakelockTag;
3720                cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
3721            }
3722            // If the last written history had a wake reason tag, we need to retain it.
3723            // Note that the condition above made sure that we aren't in a case where
3724            // both it and the current history item have a wakelock tag.
3725            if (mHistoryLastWritten.wakeReasonTag != null) {
3726                cur.wakeReasonTag = cur.localWakeReasonTag;
3727                cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
3728            }
3729            // If the last written history had an event, we need to retain it.
3730            // Note that the condition above made sure that we aren't in a case where
3731            // both it and the current history item have an event.
3732            if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
3733                cur.eventCode = mHistoryLastWritten.eventCode;
3734                cur.eventTag = cur.localEventTag;
3735                cur.eventTag.setTo(mHistoryLastWritten.eventTag);
3736            }
3737            mHistoryLastWritten.setTo(mHistoryLastLastWritten);
3738        }
3739
3740        boolean recordResetDueToOverflow = false;
3741        final int dataSize = mHistoryBuffer.dataSize();
3742        if (dataSize >= MAX_MAX_HISTORY_BUFFER*3) {
3743            // Clients can't deal with history buffers this large. This only
3744            // really happens when the device is on charger and interacted with
3745            // for long periods of time, like in retail mode. Since the device is
3746            // most likely charged, when unplugged, stats would have reset anyways.
3747            // Reset the stats and mark that we overflowed.
3748            // b/32540341
3749            resetAllStatsLocked();
3750
3751            // Mark that we want to set *OVERFLOW* event and the RESET:START
3752            // events.
3753            recordResetDueToOverflow = true;
3754
3755        } else if (dataSize >= MAX_HISTORY_BUFFER) {
3756            if (!mHistoryOverflow) {
3757                mHistoryOverflow = true;
3758                addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3759                addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
3760                return;
3761            }
3762
3763            // After overflow, we allow various bit-wise states to settle to 0.
3764            boolean writeAnyway = false;
3765            final int curStates = cur.states & HistoryItem.SETTLE_TO_ZERO_STATES
3766                    & mActiveHistoryStates;
3767            if (mHistoryLastWritten.states != curStates) {
3768                // mActiveHistoryStates keeps track of which bits in .states are now being
3769                // forced to 0.
3770                int old = mActiveHistoryStates;
3771                mActiveHistoryStates &= curStates | ~HistoryItem.SETTLE_TO_ZERO_STATES;
3772                writeAnyway |= old != mActiveHistoryStates;
3773            }
3774            final int curStates2 = cur.states2 & HistoryItem.SETTLE_TO_ZERO_STATES2
3775                    & mActiveHistoryStates2;
3776            if (mHistoryLastWritten.states2 != curStates2) {
3777                // mActiveHistoryStates2 keeps track of which bits in .states2 are now being
3778                // forced to 0.
3779                int old = mActiveHistoryStates2;
3780                mActiveHistoryStates2 &= curStates2 | ~HistoryItem.SETTLE_TO_ZERO_STATES2;
3781                writeAnyway |= old != mActiveHistoryStates2;
3782            }
3783
3784            // Once we've reached the maximum number of items, we only
3785            // record changes to the battery level and the most interesting states.
3786            // Once we've reached the maximum maximum number of items, we only
3787            // record changes to the battery level.
3788            if (!writeAnyway && mHistoryLastWritten.batteryLevel == cur.batteryLevel &&
3789                    (dataSize >= MAX_MAX_HISTORY_BUFFER
3790                            || ((mHistoryLastWritten.states^cur.states)
3791                                    & HistoryItem.MOST_INTERESTING_STATES) == 0
3792                            || ((mHistoryLastWritten.states2^cur.states2)
3793                                    & HistoryItem.MOST_INTERESTING_STATES2) == 0)) {
3794                return;
3795            }
3796
3797            addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3798            return;
3799        }
3800
3801        if (dataSize == 0 || recordResetDueToOverflow) {
3802            // The history is currently empty; we need it to start with a time stamp.
3803            cur.currentTime = System.currentTimeMillis();
3804            if (recordResetDueToOverflow) {
3805                addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
3806            }
3807            addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
3808        }
3809        addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3810    }
3811
3812    private void addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur) {
3813        if (mIteratingHistory) {
3814            throw new IllegalStateException("Can't do this while iterating history!");
3815        }
3816        mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
3817        mHistoryLastLastWritten.setTo(mHistoryLastWritten);
3818        mHistoryLastWritten.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
3819        mHistoryLastWritten.states &= mActiveHistoryStates;
3820        mHistoryLastWritten.states2 &= mActiveHistoryStates2;
3821        writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
3822        mLastHistoryElapsedRealtime = elapsedRealtimeMs;
3823        cur.wakelockTag = null;
3824        cur.wakeReasonTag = null;
3825        cur.eventCode = HistoryItem.EVENT_NONE;
3826        cur.eventTag = null;
3827        if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
3828                + " now " + mHistoryBuffer.dataPosition()
3829                + " size is now " + mHistoryBuffer.dataSize());
3830    }
3831
3832    int mChangedStates = 0;
3833    int mChangedStates2 = 0;
3834
3835    void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
3836        if (mTrackRunningHistoryElapsedRealtime != 0) {
3837            final long diffElapsed = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtime;
3838            final long diffUptime = uptimeMs - mTrackRunningHistoryUptime;
3839            if (diffUptime < (diffElapsed-20)) {
3840                final long wakeElapsedTime = elapsedRealtimeMs - (diffElapsed - diffUptime);
3841                mHistoryAddTmp.setTo(mHistoryLastWritten);
3842                mHistoryAddTmp.wakelockTag = null;
3843                mHistoryAddTmp.wakeReasonTag = null;
3844                mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
3845                mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
3846                addHistoryRecordInnerLocked(wakeElapsedTime, mHistoryAddTmp);
3847            }
3848        }
3849        mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
3850        mTrackRunningHistoryElapsedRealtime = elapsedRealtimeMs;
3851        mTrackRunningHistoryUptime = uptimeMs;
3852        addHistoryRecordInnerLocked(elapsedRealtimeMs, mHistoryCur);
3853    }
3854
3855    void addHistoryRecordInnerLocked(long elapsedRealtimeMs, HistoryItem cur) {
3856        addHistoryBufferLocked(elapsedRealtimeMs, cur);
3857
3858        if (!USE_OLD_HISTORY) {
3859            return;
3860        }
3861
3862        if (!mHaveBatteryLevel || !mRecordingHistory) {
3863            return;
3864        }
3865
3866        // If the current time is basically the same as the last time,
3867        // and no states have since the last recorded entry changed and
3868        // are now resetting back to their original value, then just collapse
3869        // into one record.
3870        if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE
3871                && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+1000)
3872                && ((mHistoryEnd.states^cur.states)&mChangedStates&mActiveHistoryStates) == 0
3873                && ((mHistoryEnd.states2^cur.states2)&mChangedStates2&mActiveHistoryStates2) == 0) {
3874            // If the current is the same as the one before, then we no
3875            // longer need the entry.
3876            if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE
3877                    && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+500)
3878                    && mHistoryLastEnd.sameNonEvent(cur)) {
3879                mHistoryLastEnd.next = null;
3880                mHistoryEnd.next = mHistoryCache;
3881                mHistoryCache = mHistoryEnd;
3882                mHistoryEnd = mHistoryLastEnd;
3883                mHistoryLastEnd = null;
3884            } else {
3885                mChangedStates |= mHistoryEnd.states^(cur.states&mActiveHistoryStates);
3886                mChangedStates2 |= mHistoryEnd.states^(cur.states2&mActiveHistoryStates2);
3887                mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, cur);
3888            }
3889            return;
3890        }
3891
3892        mChangedStates = 0;
3893        mChangedStates2 = 0;
3894
3895        if (mNumHistoryItems == MAX_HISTORY_ITEMS
3896                || mNumHistoryItems == MAX_MAX_HISTORY_ITEMS) {
3897            addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
3898        }
3899
3900        if (mNumHistoryItems >= MAX_HISTORY_ITEMS) {
3901            // Once we've reached the maximum number of items, we only
3902            // record changes to the battery level and the most interesting states.
3903            // Once we've reached the maximum maximum number of items, we only
3904            // record changes to the battery level.
3905            if (mHistoryEnd != null && mHistoryEnd.batteryLevel
3906                    == cur.batteryLevel &&
3907                    (mNumHistoryItems >= MAX_MAX_HISTORY_ITEMS
3908                            || ((mHistoryEnd.states^(cur.states&mActiveHistoryStates))
3909                                    & HistoryItem.MOST_INTERESTING_STATES) == 0)) {
3910                return;
3911            }
3912        }
3913
3914        addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
3915    }
3916
3917    public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
3918            String name, int uid) {
3919        mHistoryCur.eventCode = code;
3920        mHistoryCur.eventTag = mHistoryCur.localEventTag;
3921        mHistoryCur.eventTag.string = name;
3922        mHistoryCur.eventTag.uid = uid;
3923        addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
3924    }
3925
3926    void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) {
3927        HistoryItem rec = mHistoryCache;
3928        if (rec != null) {
3929            mHistoryCache = rec.next;
3930        } else {
3931            rec = new HistoryItem();
3932        }
3933        rec.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
3934
3935        addHistoryRecordLocked(rec);
3936    }
3937
3938    void addHistoryRecordLocked(HistoryItem rec) {
3939        mNumHistoryItems++;
3940        rec.next = null;
3941        mHistoryLastEnd = mHistoryEnd;
3942        if (mHistoryEnd != null) {
3943            mHistoryEnd.next = rec;
3944            mHistoryEnd = rec;
3945        } else {
3946            mHistory = mHistoryEnd = rec;
3947        }
3948    }
3949
3950    void clearHistoryLocked() {
3951        if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
3952        if (USE_OLD_HISTORY) {
3953            if (mHistory != null) {
3954                mHistoryEnd.next = mHistoryCache;
3955                mHistoryCache = mHistory;
3956                mHistory = mHistoryLastEnd = mHistoryEnd = null;
3957            }
3958            mNumHistoryItems = 0;
3959        }
3960
3961        mHistoryBaseTime = 0;
3962        mLastHistoryElapsedRealtime = 0;
3963        mTrackRunningHistoryElapsedRealtime = 0;
3964        mTrackRunningHistoryUptime = 0;
3965
3966        mHistoryBuffer.setDataSize(0);
3967        mHistoryBuffer.setDataPosition(0);
3968        mHistoryBuffer.setDataCapacity(MAX_HISTORY_BUFFER / 2);
3969        mHistoryLastLastWritten.clear();
3970        mHistoryLastWritten.clear();
3971        mHistoryTagPool.clear();
3972        mNextHistoryTagIdx = 0;
3973        mNumHistoryTagChars = 0;
3974        mHistoryBufferLastPos = -1;
3975        mHistoryOverflow = false;
3976        mActiveHistoryStates = 0xffffffff;
3977        mActiveHistoryStates2 = 0xffffffff;
3978    }
3979
3980    @GuardedBy("this")
3981    public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptime,
3982            long realtime) {
3983        final boolean screenOff = !isScreenOn(screenState);
3984        final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
3985        final boolean updateOnBatteryScreenOffTimeBase =
3986                (unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
3987
3988        if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) {
3989            if (updateOnBatteryScreenOffTimeBase) {
3990                updateKernelWakelocksLocked();
3991                updateBatteryPropertiesLocked();
3992            }
3993            // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
3994            // updateRpmStatsLocked is too slow to run each screen change. When the speed is
3995            // improved, remove the surrounding if{}.
3996            if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
3997                updateRpmStatsLocked(); // if either OnBattery or OnBatteryScreenOff timebase changes.
3998            }
3999            if (DEBUG_ENERGY_CPU) {
4000                Slog.d(TAG, "Updating cpu time because screen is now "
4001                        + Display.stateToString(screenState)
4002                        + " and battery is " + (unplugged ? "on" : "off"));
4003            }
4004
4005            mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime);
4006            if (updateOnBatteryTimeBase) {
4007                for (int i = mUidStats.size() - 1; i >= 0; --i) {
4008                    mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptime, realtime);
4009                }
4010            }
4011            if (updateOnBatteryScreenOffTimeBase) {
4012                mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff, uptime, realtime);
4013                for (int i = mUidStats.size() - 1; i >= 0; --i) {
4014                    mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptime, realtime);
4015                }
4016            }
4017        }
4018    }
4019
4020    private void updateBatteryPropertiesLocked() {
4021        try {
4022            IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
4023                    ServiceManager.getService("batteryproperties"));
4024            registrar.scheduleUpdate();
4025        } catch (RemoteException e) {
4026            // Ignore.
4027        }
4028    }
4029
4030    public void addIsolatedUidLocked(int isolatedUid, int appUid) {
4031        mIsolatedUids.put(isolatedUid, appUid);
4032        StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, appUid, isolatedUid,
4033                StatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED);
4034        final Uid u = getUidStatsLocked(appUid);
4035        u.addIsolatedUid(isolatedUid);
4036    }
4037
4038    /**
4039     * Schedules a read of the latest cpu times before removing the isolated UID.
4040     * @see #removeIsolatedUidLocked(int)
4041     */
4042    public void scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid) {
4043        int curUid = mIsolatedUids.get(isolatedUid, -1);
4044        if (curUid == appUid) {
4045            if (mExternalSync != null) {
4046                mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
4047            }
4048        }
4049    }
4050
4051    /**
4052     * This should only be called after the cpu times have been read.
4053     * @see #scheduleRemoveIsolatedUidLocked(int, int)
4054     */
4055    @GuardedBy("this")
4056    public void removeIsolatedUidLocked(int isolatedUid) {
4057        StatsLog.write(
4058                StatsLog.ISOLATED_UID_CHANGED, mIsolatedUids.get(isolatedUid, -1),
4059                isolatedUid, StatsLog.ISOLATED_UID_CHANGED__EVENT__REMOVED);
4060        final int idx = mIsolatedUids.indexOfKey(isolatedUid);
4061        if (idx >= 0) {
4062            final int ownerUid = mIsolatedUids.valueAt(idx);
4063            final Uid u = getUidStatsLocked(ownerUid);
4064            u.removeIsolatedUid(isolatedUid);
4065            mIsolatedUids.removeAt(idx);
4066        }
4067        mPendingRemovedUids.add(new UidToRemove(isolatedUid, mClocks.elapsedRealtime()));
4068    }
4069
4070    public int mapUid(int uid) {
4071        int isolated = mIsolatedUids.get(uid, -1);
4072        return isolated > 0 ? isolated : uid;
4073    }
4074
4075    public void noteEventLocked(int code, String name, int uid) {
4076        uid = mapUid(uid);
4077        if (!mActiveEvents.updateState(code, name, uid, 0)) {
4078            return;
4079        }
4080        final long elapsedRealtime = mClocks.elapsedRealtime();
4081        final long uptime = mClocks.uptimeMillis();
4082        addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
4083    }
4084
4085    boolean ensureStartClockTime(final long currentTime) {
4086        final long ABOUT_ONE_YEAR = 365*24*60*60*1000L;
4087        if ((currentTime > ABOUT_ONE_YEAR && mStartClockTime < (currentTime-ABOUT_ONE_YEAR))
4088                || (mStartClockTime > currentTime)) {
4089            // If the start clock time has changed by more than a year, then presumably
4090            // the previous time was completely bogus.  So we are going to figure out a
4091            // new time based on how much time has elapsed since we started counting.
4092            mStartClockTime = currentTime - (mClocks.elapsedRealtime()-(mRealtimeStart/1000));
4093            return true;
4094        }
4095        return false;
4096    }
4097
4098    public void noteCurrentTimeChangedLocked() {
4099        final long currentTime = System.currentTimeMillis();
4100        final long elapsedRealtime = mClocks.elapsedRealtime();
4101        final long uptime = mClocks.uptimeMillis();
4102        recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
4103        ensureStartClockTime(currentTime);
4104    }
4105
4106    public void noteProcessStartLocked(String name, int uid) {
4107        uid = mapUid(uid);
4108        if (isOnBattery()) {
4109            Uid u = getUidStatsLocked(uid);
4110            u.getProcessStatsLocked(name).incStartsLocked();
4111        }
4112        if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
4113            return;
4114        }
4115        if (!mRecordAllHistory) {
4116            return;
4117        }
4118        final long elapsedRealtime = mClocks.elapsedRealtime();
4119        final long uptime = mClocks.uptimeMillis();
4120        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid);
4121    }
4122
4123    public void noteProcessCrashLocked(String name, int uid) {
4124        uid = mapUid(uid);
4125        if (isOnBattery()) {
4126            Uid u = getUidStatsLocked(uid);
4127            u.getProcessStatsLocked(name).incNumCrashesLocked();
4128        }
4129    }
4130
4131    public void noteProcessAnrLocked(String name, int uid) {
4132        uid = mapUid(uid);
4133        if (isOnBattery()) {
4134            Uid u = getUidStatsLocked(uid);
4135            u.getProcessStatsLocked(name).incNumAnrsLocked();
4136        }
4137    }
4138
4139    public void noteUidProcessStateLocked(int uid, int state) {
4140        int parentUid = mapUid(uid);
4141        if (uid != parentUid) {
4142            // Isolated UIDs process state is already rolled up into parent, so no need to track
4143            // Otherwise the parent's process state will get downgraded incorrectly
4144            return;
4145        }
4146        getUidStatsLocked(uid).updateUidProcessStateLocked(state);
4147    }
4148
4149    public void noteProcessFinishLocked(String name, int uid) {
4150        uid = mapUid(uid);
4151        if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
4152            return;
4153        }
4154        if (!mRecordAllHistory) {
4155            return;
4156        }
4157        final long elapsedRealtime = mClocks.elapsedRealtime();
4158        final long uptime = mClocks.uptimeMillis();
4159        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
4160    }
4161
4162    public void noteSyncStartLocked(String name, int uid) {
4163        uid = mapUid(uid);
4164        final long elapsedRealtime = mClocks.elapsedRealtime();
4165        final long uptime = mClocks.uptimeMillis();
4166        getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime);
4167        if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
4168            return;
4169        }
4170        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_START, name, uid);
4171    }
4172
4173    public void noteSyncFinishLocked(String name, int uid) {
4174        uid = mapUid(uid);
4175        final long elapsedRealtime = mClocks.elapsedRealtime();
4176        final long uptime = mClocks.uptimeMillis();
4177        getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime);
4178        if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
4179            return;
4180        }
4181        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_FINISH, name, uid);
4182    }
4183
4184    public void noteJobStartLocked(String name, int uid) {
4185        uid = mapUid(uid);
4186        final long elapsedRealtime = mClocks.elapsedRealtime();
4187        final long uptime = mClocks.uptimeMillis();
4188        getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime);
4189        if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
4190            return;
4191        }
4192        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid);
4193    }
4194
4195    public void noteJobFinishLocked(String name, int uid, int stopReason) {
4196        uid = mapUid(uid);
4197        final long elapsedRealtime = mClocks.elapsedRealtime();
4198        final long uptime = mClocks.uptimeMillis();
4199        getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime, stopReason);
4200        if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
4201            return;
4202        }
4203        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
4204    }
4205
4206    public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast) {
4207        uid = mapUid(uid);
4208        getUidStatsLocked(uid).noteJobsDeferredLocked(numDeferred, sinceLast);
4209    }
4210
4211    public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
4212        noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid);
4213    }
4214
4215    public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
4216        noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid);
4217    }
4218
4219    private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
4220            int uid) {
4221        if (!mRecordAllHistory) {
4222            return;
4223        }
4224
4225        final long elapsedRealtime = mClocks.elapsedRealtime();
4226        final long uptime = mClocks.uptimeMillis();
4227
4228        if (workSource != null) {
4229            for (int i = 0; i < workSource.size(); ++i) {
4230                uid = mapUid(workSource.get(i));
4231                if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4232                    addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4233                }
4234            }
4235
4236            List<WorkChain> workChains = workSource.getWorkChains();
4237            if (workChains != null) {
4238                for (int i = 0; i < workChains.size(); ++i) {
4239                    uid = mapUid(workChains.get(i).getAttributionUid());
4240                    if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4241                        addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4242                    }
4243                }
4244            }
4245        } else {
4246            uid = mapUid(uid);
4247
4248            if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
4249                addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
4250            }
4251        }
4252    }
4253
4254    public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
4255            String tag) {
4256        if (workSource != null) {
4257            for (int i = 0; i < workSource.size(); ++i) {
4258                uid = workSource.get(i);
4259                final String workSourceName = workSource.getName(i);
4260
4261                if (isOnBattery()) {
4262                    BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
4263                            workSourceName != null ? workSourceName : packageName);
4264                    pkg.noteWakeupAlarmLocked(tag);
4265                }
4266                StatsLog.write_non_chained(StatsLog.WAKEUP_ALARM_OCCURRED, workSource.get(i),
4267                        workSource.getName(i), tag);
4268            }
4269
4270            ArrayList<WorkChain> workChains = workSource.getWorkChains();
4271            if (workChains != null) {
4272                for (int i = 0; i < workChains.size(); ++i) {
4273                    final WorkChain wc = workChains.get(i);
4274                    uid = wc.getAttributionUid();
4275
4276                    if (isOnBattery()) {
4277                        BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
4278                        pkg.noteWakeupAlarmLocked(tag);
4279                    }
4280                    StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, wc.getUids(), wc.getTags(), tag);
4281                }
4282            }
4283        } else {
4284            if (isOnBattery()) {
4285                BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
4286                pkg.noteWakeupAlarmLocked(tag);
4287            }
4288            StatsLog.write_non_chained(StatsLog.WAKEUP_ALARM_OCCURRED, uid, null, tag);
4289        }
4290    }
4291
4292    private void requestWakelockCpuUpdate() {
4293        mExternalSync.scheduleCpuSyncDueToWakelockChange(DELAY_UPDATE_WAKELOCKS);
4294    }
4295
4296    private void requestImmediateCpuUpdate() {
4297        mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */);
4298    }
4299
4300    public void setRecordAllHistoryLocked(boolean enabled) {
4301        mRecordAllHistory = enabled;
4302        if (!enabled) {
4303            // Clear out any existing state.
4304            mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
4305            mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
4306            // Record the currently running processes as stopping, now that we are no
4307            // longer tracking them.
4308            HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4309                    HistoryItem.EVENT_PROC);
4310            if (active != null) {
4311                long mSecRealtime = mClocks.elapsedRealtime();
4312                final long mSecUptime = mClocks.uptimeMillis();
4313                for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4314                    SparseIntArray uids = ent.getValue();
4315                    for (int j=0; j<uids.size(); j++) {
4316                        addHistoryEventLocked(mSecRealtime, mSecUptime,
4317                                HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
4318                    }
4319                }
4320            }
4321        } else {
4322            // Record the currently running processes as starting, now that we are tracking them.
4323            HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
4324                    HistoryItem.EVENT_PROC);
4325            if (active != null) {
4326                long mSecRealtime = mClocks.elapsedRealtime();
4327                final long mSecUptime = mClocks.uptimeMillis();
4328                for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
4329                    SparseIntArray uids = ent.getValue();
4330                    for (int j=0; j<uids.size(); j++) {
4331                        addHistoryEventLocked(mSecRealtime, mSecUptime,
4332                                HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
4333                    }
4334                }
4335            }
4336        }
4337    }
4338
4339    public void setNoAutoReset(boolean enabled) {
4340        mNoAutoReset = enabled;
4341    }
4342
4343    public void setPretendScreenOff(boolean pretendScreenOff) {
4344        if (mPretendScreenOff != pretendScreenOff) {
4345            mPretendScreenOff = pretendScreenOff;
4346            noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON);
4347        }
4348    }
4349
4350    private String mInitialAcquireWakeName;
4351    private int mInitialAcquireWakeUid = -1;
4352
4353    public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4354        int type, boolean unimportantForLogging, long elapsedRealtime, long uptime) {
4355        uid = mapUid(uid);
4356        if (type == WAKE_TYPE_PARTIAL) {
4357            // Only care about partial wake locks, since full wake locks
4358            // will be canceled when the user puts the screen to sleep.
4359            aggregateLastWakeupUptimeLocked(uptime);
4360            if (historyName == null) {
4361                historyName = name;
4362            }
4363            if (mRecordAllHistory) {
4364                if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
4365                        uid, 0)) {
4366                    addHistoryEventLocked(elapsedRealtime, uptime,
4367                            HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
4368                }
4369            }
4370            if (mWakeLockNesting == 0) {
4371                mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
4372                if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
4373                        + Integer.toHexString(mHistoryCur.states));
4374                mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
4375                mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
4376                mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
4377                mWakeLockImportant = !unimportantForLogging;
4378                addHistoryRecordLocked(elapsedRealtime, uptime);
4379            } else if (!mWakeLockImportant && !unimportantForLogging
4380                    && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
4381                if (mHistoryLastWritten.wakelockTag != null) {
4382                    // We'll try to update the last tag.
4383                    mHistoryLastWritten.wakelockTag = null;
4384                    mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
4385                    mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
4386                    mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
4387                    addHistoryRecordLocked(elapsedRealtime, uptime);
4388                }
4389                mWakeLockImportant = true;
4390            }
4391            mWakeLockNesting++;
4392        }
4393        if (uid >= 0) {
4394            if (mOnBatteryScreenOffTimeBase.isRunning()) {
4395                // We only update the cpu time when a wake lock is acquired if the screen is off.
4396                // If the screen is on, we don't distribute the power amongst partial wakelocks.
4397                if (DEBUG_ENERGY_CPU) {
4398                    Slog.d(TAG, "Updating cpu time because of +wake_lock");
4399                }
4400                requestWakelockCpuUpdate();
4401            }
4402
4403            getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
4404
4405            if (wc != null) {
4406                StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(),
4407                        getPowerManagerWakeLockLevel(type), name,
4408                        StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
4409            } else {
4410                StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null,
4411                        getPowerManagerWakeLockLevel(type), name,
4412                        StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
4413            }
4414        }
4415    }
4416
4417    public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName,
4418            int type, long elapsedRealtime, long uptime) {
4419        uid = mapUid(uid);
4420        if (type == WAKE_TYPE_PARTIAL) {
4421            mWakeLockNesting--;
4422            if (mRecordAllHistory) {
4423                if (historyName == null) {
4424                    historyName = name;
4425                }
4426                if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
4427                        uid, 0)) {
4428                    addHistoryEventLocked(elapsedRealtime, uptime,
4429                            HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
4430                }
4431            }
4432            if (mWakeLockNesting == 0) {
4433                mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
4434                if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
4435                        + Integer.toHexString(mHistoryCur.states));
4436                mInitialAcquireWakeName = null;
4437                mInitialAcquireWakeUid = -1;
4438                addHistoryRecordLocked(elapsedRealtime, uptime);
4439            }
4440        }
4441        if (uid >= 0) {
4442            if (mOnBatteryScreenOffTimeBase.isRunning()) {
4443                if (DEBUG_ENERGY_CPU) {
4444                    Slog.d(TAG, "Updating cpu time because of -wake_lock");
4445                }
4446                requestWakelockCpuUpdate();
4447            }
4448
4449            getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
4450            if (wc != null) {
4451                StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(),
4452                        getPowerManagerWakeLockLevel(type), name,
4453                        StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
4454            } else {
4455                StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null,
4456                        getPowerManagerWakeLockLevel(type), name,
4457                        StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
4458            }
4459        }
4460    }
4461
4462    /**
4463     * Converts BatteryStats wakelock types back into PowerManager wakelock levels.
4464     * This is the inverse map of Notifier.getBatteryStatsWakeLockMonitorType().
4465     * These are estimations, since batterystats loses some of the original data.
4466     * TODO: Delete this. Instead, StatsLog.write should be called from PowerManager's Notifier.
4467     */
4468    private int getPowerManagerWakeLockLevel(int battertStatsWakelockType) {
4469        switch (battertStatsWakelockType) {
4470            // PowerManager.PARTIAL_WAKE_LOCK or PROXIMITY_SCREEN_OFF_WAKE_LOCK
4471            case BatteryStats.WAKE_TYPE_PARTIAL:
4472                return PowerManager.PARTIAL_WAKE_LOCK;
4473
4474            // PowerManager.SCREEN_DIM_WAKE_LOCK or SCREEN_BRIGHT_WAKE_LOCK
4475            case BatteryStats.WAKE_TYPE_FULL:
4476                return PowerManager.FULL_WAKE_LOCK;
4477
4478            case BatteryStats.WAKE_TYPE_DRAW:
4479                return PowerManager.DRAW_WAKE_LOCK;
4480
4481            // It appears that nothing can ever make a Window and PowerManager lacks an equivalent.
4482            case BatteryStats.WAKE_TYPE_WINDOW:
4483                Slog.e(TAG, "Illegal window wakelock type observed in batterystats.");
4484                return -1;
4485
4486            default:
4487                Slog.e(TAG, "Illegal wakelock type in batterystats: " + battertStatsWakelockType);
4488                return -1;
4489        }
4490    }
4491
4492    public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
4493            String historyName, int type, boolean unimportantForLogging) {
4494        final long elapsedRealtime = mClocks.elapsedRealtime();
4495        final long uptime = mClocks.uptimeMillis();
4496        final int N = ws.size();
4497        for (int i=0; i<N; i++) {
4498            noteStartWakeLocked(ws.get(i), pid, null, name, historyName, type,
4499                    unimportantForLogging, elapsedRealtime, uptime);
4500        }
4501
4502        List<WorkChain> wcs = ws.getWorkChains();
4503        if (wcs != null) {
4504            for (int i = 0; i < wcs.size(); ++i) {
4505                final WorkChain wc = wcs.get(i);
4506                noteStartWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4507                        unimportantForLogging, elapsedRealtime, uptime);
4508            }
4509        }
4510    }
4511
4512    public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
4513            String historyName, int type, WorkSource newWs, int newPid, String newName,
4514            String newHistoryName, int newType, boolean newUnimportantForLogging) {
4515        final long elapsedRealtime = mClocks.elapsedRealtime();
4516        final long uptime = mClocks.uptimeMillis();
4517
4518        List<WorkChain>[] wcs = WorkSource.diffChains(ws, newWs);
4519
4520        // For correct semantics, we start the need worksources first, so that we won't
4521        // make inappropriate history items as if all wake locks went away and new ones
4522        // appeared.  This is okay because tracking of wake locks allows nesting.
4523        //
4524        // First the starts :
4525        final int NN = newWs.size();
4526        for (int i=0; i<NN; i++) {
4527            noteStartWakeLocked(newWs.get(i), newPid, null, newName, newHistoryName, newType,
4528                    newUnimportantForLogging, elapsedRealtime, uptime);
4529        }
4530        if (wcs != null) {
4531            List<WorkChain> newChains = wcs[0];
4532            if (newChains != null) {
4533                for (int i = 0; i < newChains.size(); ++i) {
4534                    final WorkChain newChain = newChains.get(i);
4535                    noteStartWakeLocked(newChain.getAttributionUid(), newPid, newChain, newName,
4536                        newHistoryName, newType, newUnimportantForLogging, elapsedRealtime,
4537                        uptime);
4538                }
4539            }
4540        }
4541
4542        // Then the stops :
4543        final int NO = ws.size();
4544        for (int i=0; i<NO; i++) {
4545            noteStopWakeLocked(ws.get(i), pid, null, name, historyName, type, elapsedRealtime,
4546                    uptime);
4547        }
4548        if (wcs != null) {
4549            List<WorkChain> goneChains = wcs[1];
4550            if (goneChains != null) {
4551                for (int i = 0; i < goneChains.size(); ++i) {
4552                    final WorkChain goneChain = goneChains.get(i);
4553                    noteStopWakeLocked(goneChain.getAttributionUid(), pid, goneChain, name,
4554                            historyName, type, elapsedRealtime, uptime);
4555                }
4556            }
4557        }
4558    }
4559
4560    public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
4561            String historyName, int type) {
4562        final long elapsedRealtime = mClocks.elapsedRealtime();
4563        final long uptime = mClocks.uptimeMillis();
4564        final int N = ws.size();
4565        for (int i=0; i<N; i++) {
4566            noteStopWakeLocked(ws.get(i), pid, null, name, historyName, type, elapsedRealtime,
4567                    uptime);
4568        }
4569
4570        List<WorkChain> wcs = ws.getWorkChains();
4571        if (wcs != null) {
4572            for (int i = 0; i < wcs.size(); ++i) {
4573                final WorkChain wc = wcs.get(i);
4574                noteStopWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type,
4575                        elapsedRealtime, uptime);
4576            }
4577        }
4578    }
4579
4580    public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
4581        StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
4582                uid, null, name, historyName,
4583                StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
4584
4585        uid = mapUid(uid);
4586        noteLongPartialWakeLockStartInternal(name, historyName, uid);
4587    }
4588
4589    public void noteLongPartialWakelockStartFromSource(String name, String historyName,
4590            WorkSource workSource) {
4591        final int N = workSource.size();
4592        for (int i = 0; i < N; ++i) {
4593            final int uid = mapUid(workSource.get(i));
4594            noteLongPartialWakeLockStartInternal(name, historyName, uid);
4595            StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
4596                    workSource.get(i), workSource.getName(i), name, historyName,
4597                    StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
4598        }
4599
4600        final ArrayList<WorkChain> workChains = workSource.getWorkChains();
4601        if (workChains != null) {
4602            for (int i = 0; i < workChains.size(); ++i) {
4603                final WorkChain workChain = workChains.get(i);
4604                final int uid = workChain.getAttributionUid();
4605                noteLongPartialWakeLockStartInternal(name, historyName, uid);
4606
4607                StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
4608                        workChain.getUids(), workChain.getTags(), name, historyName,
4609                        StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
4610            }
4611        }
4612    }
4613
4614    private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid) {
4615        final long elapsedRealtime = mClocks.elapsedRealtime();
4616        final long uptime = mClocks.uptimeMillis();
4617        if (historyName == null) {
4618            historyName = name;
4619        }
4620        if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid,
4621                0)) {
4622            return;
4623        }
4624        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
4625                historyName, uid);
4626    }
4627
4628    public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
4629        StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, uid, null,
4630                name, historyName, StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
4631
4632        uid = mapUid(uid);
4633        noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4634    }
4635
4636    public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
4637            WorkSource workSource) {
4638        final int N = workSource.size();
4639        for (int i = 0; i < N; ++i) {
4640            final int uid = mapUid(workSource.get(i));
4641            noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4642            StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
4643                    workSource.get(i), workSource.getName(i), name, historyName,
4644                    StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
4645        }
4646
4647        final ArrayList<WorkChain> workChains = workSource.getWorkChains();
4648        if (workChains != null) {
4649            for (int i = 0; i < workChains.size(); ++i) {
4650                final WorkChain workChain = workChains.get(i);
4651                final int uid = workChain.getAttributionUid();
4652                noteLongPartialWakeLockFinishInternal(name, historyName, uid);
4653                StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
4654                        workChain.getUids(), workChain.getTags(), name, historyName,
4655                        StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
4656            }
4657        }
4658    }
4659
4660    private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid) {
4661        final long elapsedRealtime = mClocks.elapsedRealtime();
4662        final long uptime = mClocks.uptimeMillis();
4663        if (historyName == null) {
4664            historyName = name;
4665        }
4666        if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid,
4667                0)) {
4668            return;
4669        }
4670        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
4671                historyName, uid);
4672    }
4673
4674    void aggregateLastWakeupUptimeLocked(long uptimeMs) {
4675        if (mLastWakeupReason != null) {
4676            long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
4677            SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
4678            timer.add(deltaUptime * 1000, 1); // time in in microseconds
4679            StatsLog.write(StatsLog.KERNEL_WAKEUP_REPORTED, mLastWakeupReason,
4680                    /* duration_usec */ deltaUptime * 1000);
4681            mLastWakeupReason = null;
4682        }
4683    }
4684
4685    public void noteWakeupReasonLocked(String reason) {
4686        final long elapsedRealtime = mClocks.elapsedRealtime();
4687        final long uptime = mClocks.uptimeMillis();
4688        if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
4689                + Integer.toHexString(mHistoryCur.states));
4690        aggregateLastWakeupUptimeLocked(uptime);
4691        mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
4692        mHistoryCur.wakeReasonTag.string = reason;
4693        mHistoryCur.wakeReasonTag.uid = 0;
4694        mLastWakeupReason = reason;
4695        mLastWakeupUptimeMs = uptime;
4696        addHistoryRecordLocked(elapsedRealtime, uptime);
4697    }
4698
4699    public boolean startAddingCpuLocked() {
4700        mExternalSync.cancelCpuSyncDueToWakelockChange();
4701        return mOnBatteryInternal;
4702    }
4703
4704    public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime,
4705                                      int statSystemTime, int statIOWaitTime, int statIrqTime,
4706                                      int statSoftIrqTime, int statIdleTime) {
4707        if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
4708                + " user=" + statUserTime + " sys=" + statSystemTime
4709                + " io=" + statIOWaitTime + " irq=" + statIrqTime
4710                + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime);
4711        mCurStepCpuUserTime += totalUTime;
4712        mCurStepCpuSystemTime += totalSTime;
4713        mCurStepStatUserTime += statUserTime;
4714        mCurStepStatSystemTime += statSystemTime;
4715        mCurStepStatIOWaitTime += statIOWaitTime;
4716        mCurStepStatIrqTime += statIrqTime;
4717        mCurStepStatSoftIrqTime += statSoftIrqTime;
4718        mCurStepStatIdleTime += statIdleTime;
4719    }
4720
4721    public void noteProcessDiedLocked(int uid, int pid) {
4722        uid = mapUid(uid);
4723        Uid u = mUidStats.get(uid);
4724        if (u != null) {
4725            u.mPids.remove(pid);
4726        }
4727    }
4728
4729    public long getProcessWakeTime(int uid, int pid, long realtime) {
4730        uid = mapUid(uid);
4731        Uid u = mUidStats.get(uid);
4732        if (u != null) {
4733            Uid.Pid p = u.mPids.get(pid);
4734            if (p != null) {
4735                return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0);
4736            }
4737        }
4738        return 0;
4739    }
4740
4741    public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
4742        uid = mapUid(uid);
4743        Uid u = mUidStats.get(uid);
4744        if (u != null) {
4745            u.reportExcessiveCpuLocked(proc, overTime, usedTime);
4746        }
4747    }
4748
4749    int mSensorNesting;
4750
4751    public void noteStartSensorLocked(int uid, int sensor) {
4752        uid = mapUid(uid);
4753        final long elapsedRealtime = mClocks.elapsedRealtime();
4754        final long uptime = mClocks.uptimeMillis();
4755        if (mSensorNesting == 0) {
4756            mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
4757            if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
4758                    + Integer.toHexString(mHistoryCur.states));
4759            addHistoryRecordLocked(elapsedRealtime, uptime);
4760        }
4761        mSensorNesting++;
4762        getUidStatsLocked(uid).noteStartSensor(sensor, elapsedRealtime);
4763    }
4764
4765    public void noteStopSensorLocked(int uid, int sensor) {
4766        uid = mapUid(uid);
4767        final long elapsedRealtime = mClocks.elapsedRealtime();
4768        final long uptime = mClocks.uptimeMillis();
4769        mSensorNesting--;
4770        if (mSensorNesting == 0) {
4771            mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
4772            if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
4773                    + Integer.toHexString(mHistoryCur.states));
4774            addHistoryRecordLocked(elapsedRealtime, uptime);
4775        }
4776        getUidStatsLocked(uid).noteStopSensor(sensor, elapsedRealtime);
4777    }
4778
4779    int mGpsNesting;
4780
4781    public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) {
4782        for (int i = 0; i < newWs.size(); ++i) {
4783            noteStartGpsLocked(newWs.get(i), null);
4784        }
4785
4786        for (int i = 0; i < oldWs.size(); ++i) {
4787            noteStopGpsLocked((oldWs.get(i)), null);
4788        }
4789
4790        List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs);
4791        if (wcs != null) {
4792            if (wcs[0] != null) {
4793                final List<WorkChain> newChains = wcs[0];
4794                for (int i = 0; i < newChains.size(); ++i) {
4795                    noteStartGpsLocked(-1, newChains.get(i));
4796                }
4797            }
4798
4799            if (wcs[1] != null) {
4800                final List<WorkChain> goneChains = wcs[1];
4801                for (int i = 0; i < goneChains.size(); ++i) {
4802                    noteStopGpsLocked(-1, goneChains.get(i));
4803                }
4804            }
4805        }
4806    }
4807
4808    private void noteStartGpsLocked(int uid, WorkChain workChain) {
4809        uid = getAttributionUid(uid, workChain);
4810        final long elapsedRealtime = mClocks.elapsedRealtime();
4811        final long uptime = mClocks.uptimeMillis();
4812        if (mGpsNesting == 0) {
4813            mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
4814            if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
4815                    + Integer.toHexString(mHistoryCur.states));
4816            addHistoryRecordLocked(elapsedRealtime, uptime);
4817        }
4818        mGpsNesting++;
4819
4820        if (workChain == null) {
4821            StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
4822                    StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
4823        } else {
4824            StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED,
4825                    workChain.getUids(), workChain.getTags(),
4826                    StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON);
4827        }
4828
4829        getUidStatsLocked(uid).noteStartGps(elapsedRealtime);
4830    }
4831
4832    private void noteStopGpsLocked(int uid, WorkChain workChain) {
4833        uid = getAttributionUid(uid, workChain);
4834        final long elapsedRealtime = mClocks.elapsedRealtime();
4835        final long uptime = mClocks.uptimeMillis();
4836        mGpsNesting--;
4837        if (mGpsNesting == 0) {
4838            mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
4839            if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
4840                    + Integer.toHexString(mHistoryCur.states));
4841            addHistoryRecordLocked(elapsedRealtime, uptime);
4842            stopAllGpsSignalQualityTimersLocked(-1);
4843            mGpsSignalQualityBin = -1;
4844        }
4845
4846        if (workChain == null) {
4847            StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, uid, null,
4848                    StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
4849        } else {
4850            StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, workChain.getUids(),
4851                    workChain.getTags(), StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF);
4852        }
4853
4854        getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
4855    }
4856
4857    public void noteGpsSignalQualityLocked(int signalLevel) {
4858        if (mGpsNesting == 0) {
4859            return;
4860        }
4861        if (signalLevel < 0 || signalLevel >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
4862            stopAllGpsSignalQualityTimersLocked(-1);
4863            return;
4864        }
4865        final long elapsedRealtime = mClocks.elapsedRealtime();
4866        final long uptime = mClocks.uptimeMillis();
4867        if (mGpsSignalQualityBin != signalLevel) {
4868            if (mGpsSignalQualityBin >= 0) {
4869                mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtime);
4870            }
4871            if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
4872                mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtime);
4873            }
4874            mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
4875                    | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
4876            addHistoryRecordLocked(elapsedRealtime, uptime);
4877            mGpsSignalQualityBin = signalLevel;
4878        }
4879        return;
4880    }
4881
4882    @GuardedBy("this")
4883    public void noteScreenStateLocked(int state) {
4884        state = mPretendScreenOff ? Display.STATE_OFF : state;
4885
4886        // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
4887        // original 4 are mapped to one of the originals.
4888        if (state > MAX_TRACKED_SCREEN_STATE) {
4889            switch (state) {
4890                case Display.STATE_VR:
4891                    state = Display.STATE_ON;
4892                    break;
4893                default:
4894                    Slog.wtf(TAG, "Unknown screen state (not mapped): " + state);
4895                    break;
4896            }
4897        }
4898
4899        if (mScreenState != state) {
4900            recordDailyStatsIfNeededLocked(true);
4901            final int oldState = mScreenState;
4902            mScreenState = state;
4903            if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
4904                    + ", newState=" + Display.stateToString(state));
4905
4906            if (state != Display.STATE_UNKNOWN) {
4907                int stepState = state-1;
4908                if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
4909                    mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
4910                    mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
4911                } else {
4912                    Slog.wtf(TAG, "Unexpected screen state: " + state);
4913                }
4914            }
4915
4916            final long elapsedRealtime = mClocks.elapsedRealtime();
4917            final long uptime = mClocks.uptimeMillis();
4918
4919            boolean updateHistory = false;
4920            if (isScreenDoze(state)) {
4921                mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
4922                mScreenDozeTimer.startRunningLocked(elapsedRealtime);
4923                updateHistory = true;
4924            } else if (isScreenDoze(oldState)) {
4925                mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG;
4926                mScreenDozeTimer.stopRunningLocked(elapsedRealtime);
4927                updateHistory = true;
4928            }
4929            if (isScreenOn(state)) {
4930                mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
4931                if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
4932                        + Integer.toHexString(mHistoryCur.states));
4933                mScreenOnTimer.startRunningLocked(elapsedRealtime);
4934                if (mScreenBrightnessBin >= 0) {
4935                    mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
4936                }
4937                updateHistory = true;
4938            } else if (isScreenOn(oldState)) {
4939                mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
4940                if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
4941                        + Integer.toHexString(mHistoryCur.states));
4942                mScreenOnTimer.stopRunningLocked(elapsedRealtime);
4943                if (mScreenBrightnessBin >= 0) {
4944                    mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
4945                }
4946                updateHistory = true;
4947            }
4948            if (updateHistory) {
4949                if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: "
4950                        + Display.stateToString(state));
4951                addHistoryRecordLocked(elapsedRealtime, uptime);
4952            }
4953            mExternalSync.scheduleCpuSyncDueToScreenStateChange(
4954                    mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning());
4955            if (isScreenOn(state)) {
4956                updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
4957                        mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
4958                // Fake a wake lock, so we consider the device waked as long as the screen is on.
4959                noteStartWakeLocked(-1, -1, null, "screen", null, WAKE_TYPE_PARTIAL, false,
4960                        elapsedRealtime, uptime);
4961            } else if (isScreenOn(oldState)) {
4962                noteStopWakeLocked(-1, -1, null, "screen", "screen", WAKE_TYPE_PARTIAL,
4963                        elapsedRealtime, uptime);
4964                updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
4965                        mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
4966            }
4967            // Update discharge amounts.
4968            if (mOnBatteryInternal) {
4969                updateDischargeScreenLevelsLocked(oldState, state);
4970            }
4971        }
4972    }
4973
4974    public void noteScreenBrightnessLocked(int brightness) {
4975        // Bin the brightness.
4976        int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
4977        if (bin < 0) bin = 0;
4978        else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
4979        if (mScreenBrightnessBin != bin) {
4980            final long elapsedRealtime = mClocks.elapsedRealtime();
4981            final long uptime = mClocks.uptimeMillis();
4982            mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
4983                    | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
4984            if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
4985                    + Integer.toHexString(mHistoryCur.states));
4986            addHistoryRecordLocked(elapsedRealtime, uptime);
4987            if (mScreenState == Display.STATE_ON) {
4988                if (mScreenBrightnessBin >= 0) {
4989                    mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
4990                }
4991                mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime);
4992            }
4993            mScreenBrightnessBin = bin;
4994        }
4995    }
4996
4997    public void noteUserActivityLocked(int uid, int event) {
4998        if (mOnBatteryInternal) {
4999            uid = mapUid(uid);
5000            getUidStatsLocked(uid).noteUserActivityLocked(event);
5001        }
5002    }
5003
5004    public void noteWakeUpLocked(String reason, int reasonUid) {
5005        final long elapsedRealtime = mClocks.elapsedRealtime();
5006        final long uptime = mClocks.uptimeMillis();
5007        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SCREEN_WAKE_UP,
5008                reason, reasonUid);
5009    }
5010
5011    public void noteInteractiveLocked(boolean interactive) {
5012        if (mInteractive != interactive) {
5013            final long elapsedRealtime = mClocks.elapsedRealtime();
5014            mInteractive = interactive;
5015            if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
5016            if (interactive) {
5017                mInteractiveTimer.startRunningLocked(elapsedRealtime);
5018            } else {
5019                mInteractiveTimer.stopRunningLocked(elapsedRealtime);
5020            }
5021        }
5022    }
5023
5024    public void noteConnectivityChangedLocked(int type, String extra) {
5025        final long elapsedRealtime = mClocks.elapsedRealtime();
5026        final long uptime = mClocks.uptimeMillis();
5027        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
5028                extra, type);
5029        mNumConnectivityChange++;
5030    }
5031
5032    private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
5033            final long uptimeMillis, int uid) {
5034        uid = mapUid(uid);
5035        addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
5036                uid);
5037        getUidStatsLocked(uid).noteMobileRadioApWakeupLocked();
5038    }
5039
5040    /**
5041     * Updates the radio power state and returns true if an external stats collection should occur.
5042     */
5043    public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
5044        final long elapsedRealtime = mClocks.elapsedRealtime();
5045        final long uptime = mClocks.uptimeMillis();
5046        if (mMobileRadioPowerState != powerState) {
5047            long realElapsedRealtimeMs;
5048            final boolean active =
5049                    powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
5050                            || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
5051            if (active) {
5052                if (uid > 0) {
5053                    noteMobileRadioApWakeupLocked(elapsedRealtime, uptime, uid);
5054                }
5055
5056                mMobileRadioActiveStartTime = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
5057                mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
5058            } else {
5059                realElapsedRealtimeMs = timestampNs / (1000*1000);
5060                long lastUpdateTimeMs = mMobileRadioActiveStartTime;
5061                if (realElapsedRealtimeMs < lastUpdateTimeMs) {
5062                    Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
5063                            + " is before start time " + lastUpdateTimeMs);
5064                    realElapsedRealtimeMs = elapsedRealtime;
5065                } else if (realElapsedRealtimeMs < elapsedRealtime) {
5066                    mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
5067                            - realElapsedRealtimeMs);
5068                }
5069                mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
5070            }
5071            if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
5072                    + Integer.toHexString(mHistoryCur.states));
5073            addHistoryRecordLocked(elapsedRealtime, uptime);
5074            mMobileRadioPowerState = powerState;
5075            StatsLog.write_non_chained(StatsLog.MOBILE_RADIO_POWER_STATE_CHANGED, uid, null,
5076                    powerState);
5077            if (active) {
5078                mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
5079                mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
5080            } else {
5081                mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
5082                mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
5083                // Tell the caller to collect radio network/power stats.
5084                return true;
5085            }
5086        }
5087        return false;
5088    }
5089
5090    public void notePowerSaveModeLocked(boolean enabled) {
5091        if (mPowerSaveModeEnabled != enabled) {
5092            int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
5093            mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
5094            mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
5095            final long elapsedRealtime = mClocks.elapsedRealtime();
5096            final long uptime = mClocks.uptimeMillis();
5097            mPowerSaveModeEnabled = enabled;
5098            if (enabled) {
5099                mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
5100                if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
5101                        + Integer.toHexString(mHistoryCur.states2));
5102                mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtime);
5103            } else {
5104                mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
5105                if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
5106                        + Integer.toHexString(mHistoryCur.states2));
5107                mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtime);
5108            }
5109            addHistoryRecordLocked(elapsedRealtime, uptime);
5110            StatsLog.write(StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED, enabled ?
5111                    StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON :
5112                    StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__OFF);
5113        }
5114    }
5115
5116    public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid) {
5117        final long elapsedRealtime = mClocks.elapsedRealtime();
5118        final long uptime = mClocks.uptimeMillis();
5119        boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
5120        if (mDeviceIdling && !nowIdling && activeReason == null) {
5121            // We don't go out of general idling mode until explicitly taken out of
5122            // device idle through going active or significant motion.
5123            nowIdling = true;
5124        }
5125        boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
5126        if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
5127            // We don't go out of general light idling mode until explicitly taken out of
5128            // device idle through going active or significant motion.
5129            nowLightIdling = true;
5130        }
5131        if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
5132            addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
5133                    activeReason, activeUid);
5134        }
5135        if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
5136            int statsmode;
5137            if (nowIdling)           statsmode = DEVICE_IDLE_MODE_DEEP;
5138            else if (nowLightIdling) statsmode = DEVICE_IDLE_MODE_LIGHT;
5139            else                     statsmode = DEVICE_IDLE_MODE_OFF;
5140            StatsLog.write(StatsLog.DEVICE_IDLING_MODE_STATE_CHANGED, statsmode);
5141        }
5142        if (mDeviceIdling != nowIdling) {
5143            mDeviceIdling = nowIdling;
5144            int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
5145            mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
5146            mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
5147            if (nowIdling) {
5148                mDeviceIdlingTimer.startRunningLocked(elapsedRealtime);
5149            } else {
5150                mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime);
5151            }
5152        }
5153        if (mDeviceLightIdling != nowLightIdling) {
5154            mDeviceLightIdling = nowLightIdling;
5155            if (nowLightIdling) {
5156                mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtime);
5157            } else {
5158                mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtime);
5159            }
5160        }
5161        if (mDeviceIdleMode != mode) {
5162            mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
5163                    | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
5164            if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
5165                    + Integer.toHexString(mHistoryCur.states2));
5166            addHistoryRecordLocked(elapsedRealtime, uptime);
5167            long lastDuration = elapsedRealtime - mLastIdleTimeStart;
5168            mLastIdleTimeStart = elapsedRealtime;
5169            if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
5170                if (lastDuration > mLongestLightIdleTime) {
5171                    mLongestLightIdleTime = lastDuration;
5172                }
5173                mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtime);
5174            } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
5175                if (lastDuration > mLongestFullIdleTime) {
5176                    mLongestFullIdleTime = lastDuration;
5177                }
5178                mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtime);
5179            }
5180            if (mode == DEVICE_IDLE_MODE_LIGHT) {
5181                mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtime);
5182            } else if (mode == DEVICE_IDLE_MODE_DEEP) {
5183                mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtime);
5184            }
5185            mDeviceIdleMode = mode;
5186            StatsLog.write(StatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mode);
5187        }
5188    }
5189
5190    public void notePackageInstalledLocked(String pkgName, long versionCode) {
5191        final long elapsedRealtime = mClocks.elapsedRealtime();
5192        final long uptime = mClocks.uptimeMillis();
5193        // XXX need to figure out what to do with long version codes.
5194        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED,
5195                pkgName, (int)versionCode);
5196        PackageChange pc = new PackageChange();
5197        pc.mPackageName = pkgName;
5198        pc.mUpdate = true;
5199        pc.mVersionCode = versionCode;
5200        addPackageChange(pc);
5201    }
5202
5203    public void notePackageUninstalledLocked(String pkgName) {
5204        final long elapsedRealtime = mClocks.elapsedRealtime();
5205        final long uptime = mClocks.uptimeMillis();
5206        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
5207                pkgName, 0);
5208        PackageChange pc = new PackageChange();
5209        pc.mPackageName = pkgName;
5210        pc.mUpdate = true;
5211        addPackageChange(pc);
5212    }
5213
5214    private void addPackageChange(PackageChange pc) {
5215        if (mDailyPackageChanges == null) {
5216            mDailyPackageChanges = new ArrayList<>();
5217        }
5218        mDailyPackageChanges.add(pc);
5219    }
5220
5221    void stopAllGpsSignalQualityTimersLocked(int except) {
5222        final long elapsedRealtime = mClocks.elapsedRealtime();
5223        for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
5224            if (i == except) {
5225                continue;
5226            }
5227            while (mGpsSignalQualityTimer[i].isRunningLocked()) {
5228                mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtime);
5229            }
5230        }
5231    }
5232
5233    public void notePhoneOnLocked() {
5234        if (!mPhoneOn) {
5235            final long elapsedRealtime = mClocks.elapsedRealtime();
5236            final long uptime = mClocks.uptimeMillis();
5237            mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
5238            if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
5239                    + Integer.toHexString(mHistoryCur.states));
5240            addHistoryRecordLocked(elapsedRealtime, uptime);
5241            mPhoneOn = true;
5242            mPhoneOnTimer.startRunningLocked(elapsedRealtime);
5243        }
5244    }
5245
5246    public void notePhoneOffLocked() {
5247        if (mPhoneOn) {
5248            final long elapsedRealtime = mClocks.elapsedRealtime();
5249            final long uptime = mClocks.uptimeMillis();
5250            mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
5251            if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
5252                    + Integer.toHexString(mHistoryCur.states));
5253            addHistoryRecordLocked(elapsedRealtime, uptime);
5254            mPhoneOn = false;
5255            mPhoneOnTimer.stopRunningLocked(elapsedRealtime);
5256        }
5257    }
5258
5259    private void registerUsbStateReceiver(Context context) {
5260        final IntentFilter usbStateFilter = new IntentFilter();
5261        usbStateFilter.addAction(UsbManager.ACTION_USB_STATE);
5262        context.registerReceiver(new BroadcastReceiver() {
5263            @Override
5264            public void onReceive(Context context, Intent intent) {
5265                final boolean state = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
5266                synchronized (BatteryStatsImpl.this) {
5267                    noteUsbConnectionStateLocked(state);
5268                }
5269            }
5270        }, usbStateFilter);
5271        synchronized (this) {
5272            if (mUsbDataState == USB_DATA_UNKNOWN) {
5273                final Intent usbState = context.registerReceiver(null, usbStateFilter);
5274                final boolean initState = usbState != null && usbState.getBooleanExtra(
5275                        UsbManager.USB_CONNECTED, false);
5276                noteUsbConnectionStateLocked(initState);
5277            }
5278        }
5279    }
5280
5281    private void noteUsbConnectionStateLocked(boolean connected) {
5282        int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED;
5283        if (mUsbDataState != newState) {
5284            mUsbDataState = newState;
5285            if (connected) {
5286                mHistoryCur.states2 |= HistoryItem.STATE2_USB_DATA_LINK_FLAG;
5287            } else {
5288                mHistoryCur.states2 &= ~HistoryItem.STATE2_USB_DATA_LINK_FLAG;
5289            }
5290            addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
5291        }
5292    }
5293
5294    void stopAllPhoneSignalStrengthTimersLocked(int except) {
5295        final long elapsedRealtime = mClocks.elapsedRealtime();
5296        for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
5297            if (i == except) {
5298                continue;
5299            }
5300            while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
5301                mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
5302            }
5303        }
5304    }
5305
5306    private int fixPhoneServiceState(int state, int signalBin) {
5307        if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
5308            // In this case we will always be STATE_OUT_OF_SERVICE, so need
5309            // to infer that we are scanning from other data.
5310            if (state == ServiceState.STATE_OUT_OF_SERVICE
5311                    && signalBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5312                state = ServiceState.STATE_IN_SERVICE;
5313            }
5314        }
5315
5316        return state;
5317    }
5318
5319    private void updateAllPhoneStateLocked(int state, int simState, int strengthBin) {
5320        boolean scanning = false;
5321        boolean newHistory = false;
5322
5323        mPhoneServiceStateRaw = state;
5324        mPhoneSimStateRaw = simState;
5325        mPhoneSignalStrengthBinRaw = strengthBin;
5326
5327        final long elapsedRealtime = mClocks.elapsedRealtime();
5328        final long uptime = mClocks.uptimeMillis();
5329
5330        if (simState == TelephonyManager.SIM_STATE_ABSENT) {
5331            // In this case we will always be STATE_OUT_OF_SERVICE, so need
5332            // to infer that we are scanning from other data.
5333            if (state == ServiceState.STATE_OUT_OF_SERVICE
5334                    && strengthBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
5335                state = ServiceState.STATE_IN_SERVICE;
5336            }
5337        }
5338
5339        // If the phone is powered off, stop all timers.
5340        if (state == ServiceState.STATE_POWER_OFF) {
5341            strengthBin = -1;
5342
5343        // If we are in service, make sure the correct signal string timer is running.
5344        } else if (state == ServiceState.STATE_IN_SERVICE) {
5345            // Bin will be changed below.
5346
5347        // If we're out of service, we are in the lowest signal strength
5348        // bin and have the scanning bit set.
5349        } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
5350            scanning = true;
5351            strengthBin = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
5352            if (!mPhoneSignalScanningTimer.isRunningLocked()) {
5353                mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
5354                newHistory = true;
5355                if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
5356                        + Integer.toHexString(mHistoryCur.states));
5357                mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
5358            }
5359        }
5360
5361        if (!scanning) {
5362            // If we are no longer scanning, then stop the scanning timer.
5363            if (mPhoneSignalScanningTimer.isRunningLocked()) {
5364                mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
5365                if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
5366                        + Integer.toHexString(mHistoryCur.states));
5367                newHistory = true;
5368                mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
5369            }
5370        }
5371
5372        if (mPhoneServiceState != state) {
5373            mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
5374                    | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
5375            if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
5376                    + Integer.toHexString(mHistoryCur.states));
5377            newHistory = true;
5378            mPhoneServiceState = state;
5379        }
5380
5381        if (mPhoneSignalStrengthBin != strengthBin) {
5382            if (mPhoneSignalStrengthBin >= 0) {
5383                mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
5384                        elapsedRealtime);
5385            }
5386            if (strengthBin >= 0) {
5387                if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
5388                    mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
5389                }
5390                mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
5391                        | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
5392                if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
5393                        + Integer.toHexString(mHistoryCur.states));
5394                newHistory = true;
5395                StatsLog.write(StatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
5396            } else {
5397                stopAllPhoneSignalStrengthTimersLocked(-1);
5398            }
5399            mPhoneSignalStrengthBin = strengthBin;
5400        }
5401
5402        if (newHistory) {
5403            addHistoryRecordLocked(elapsedRealtime, uptime);
5404        }
5405    }
5406
5407    /**
5408     * Telephony stack updates the phone state.
5409     * @param state phone state from ServiceState.getState()
5410     */
5411    public void notePhoneStateLocked(int state, int simState) {
5412        updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
5413    }
5414
5415    public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
5416        // Bin the strength.
5417        int bin = signalStrength.getLevel();
5418        updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
5419    }
5420
5421    public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
5422        // BatteryStats uses 0 to represent no network type.
5423        // Telephony does not have a concept of no network type, and uses 0 to represent unknown.
5424        // Unknown is included in DATA_CONNECTION_OTHER.
5425        int bin = DATA_CONNECTION_NONE;
5426        if (hasData) {
5427            if (dataType > 0 && dataType <= TelephonyManager.MAX_NETWORK_TYPE) {
5428                bin = dataType;
5429            } else {
5430                bin = DATA_CONNECTION_OTHER;
5431            }
5432        }
5433        if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
5434        if (mPhoneDataConnectionType != bin) {
5435            final long elapsedRealtime = mClocks.elapsedRealtime();
5436            final long uptime = mClocks.uptimeMillis();
5437            mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
5438                    | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
5439            if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
5440                    + Integer.toHexString(mHistoryCur.states));
5441            addHistoryRecordLocked(elapsedRealtime, uptime);
5442            if (mPhoneDataConnectionType >= 0) {
5443                mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
5444                        elapsedRealtime);
5445            }
5446            mPhoneDataConnectionType = bin;
5447            mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime);
5448        }
5449    }
5450
5451    public void noteWifiOnLocked() {
5452        if (!mWifiOn) {
5453            final long elapsedRealtime = mClocks.elapsedRealtime();
5454            final long uptime = mClocks.uptimeMillis();
5455            mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
5456            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
5457                    + Integer.toHexString(mHistoryCur.states));
5458            addHistoryRecordLocked(elapsedRealtime, uptime);
5459            mWifiOn = true;
5460            mWifiOnTimer.startRunningLocked(elapsedRealtime);
5461            scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
5462        }
5463    }
5464
5465    public void noteWifiOffLocked() {
5466        final long elapsedRealtime = mClocks.elapsedRealtime();
5467        final long uptime = mClocks.uptimeMillis();
5468        if (mWifiOn) {
5469            mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
5470            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
5471                    + Integer.toHexString(mHistoryCur.states));
5472            addHistoryRecordLocked(elapsedRealtime, uptime);
5473            mWifiOn = false;
5474            mWifiOnTimer.stopRunningLocked(elapsedRealtime);
5475            scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
5476        }
5477    }
5478
5479    public void noteAudioOnLocked(int uid) {
5480        uid = mapUid(uid);
5481        final long elapsedRealtime = mClocks.elapsedRealtime();
5482        final long uptime = mClocks.uptimeMillis();
5483        if (mAudioOnNesting == 0) {
5484            mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
5485            if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
5486                    + Integer.toHexString(mHistoryCur.states));
5487            addHistoryRecordLocked(elapsedRealtime, uptime);
5488            mAudioOnTimer.startRunningLocked(elapsedRealtime);
5489        }
5490        mAudioOnNesting++;
5491        getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
5492    }
5493
5494    public void noteAudioOffLocked(int uid) {
5495        if (mAudioOnNesting == 0) {
5496            return;
5497        }
5498        uid = mapUid(uid);
5499        final long elapsedRealtime = mClocks.elapsedRealtime();
5500        final long uptime = mClocks.uptimeMillis();
5501        if (--mAudioOnNesting == 0) {
5502            mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
5503            if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
5504                    + Integer.toHexString(mHistoryCur.states));
5505            addHistoryRecordLocked(elapsedRealtime, uptime);
5506            mAudioOnTimer.stopRunningLocked(elapsedRealtime);
5507        }
5508        getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
5509    }
5510
5511    public void noteVideoOnLocked(int uid) {
5512        uid = mapUid(uid);
5513        final long elapsedRealtime = mClocks.elapsedRealtime();
5514        final long uptime = mClocks.uptimeMillis();
5515        if (mVideoOnNesting == 0) {
5516            mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
5517            if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
5518                    + Integer.toHexString(mHistoryCur.states));
5519            addHistoryRecordLocked(elapsedRealtime, uptime);
5520            mVideoOnTimer.startRunningLocked(elapsedRealtime);
5521        }
5522        mVideoOnNesting++;
5523        getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
5524    }
5525
5526    public void noteVideoOffLocked(int uid) {
5527        if (mVideoOnNesting == 0) {
5528            return;
5529        }
5530        uid = mapUid(uid);
5531        final long elapsedRealtime = mClocks.elapsedRealtime();
5532        final long uptime = mClocks.uptimeMillis();
5533        if (--mVideoOnNesting == 0) {
5534            mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
5535            if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
5536                    + Integer.toHexString(mHistoryCur.states));
5537            addHistoryRecordLocked(elapsedRealtime, uptime);
5538            mVideoOnTimer.stopRunningLocked(elapsedRealtime);
5539        }
5540        getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime);
5541    }
5542
5543    public void noteResetAudioLocked() {
5544        if (mAudioOnNesting > 0) {
5545            final long elapsedRealtime = mClocks.elapsedRealtime();
5546            final long uptime = mClocks.uptimeMillis();
5547            mAudioOnNesting = 0;
5548            mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
5549            if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
5550                    + Integer.toHexString(mHistoryCur.states));
5551            addHistoryRecordLocked(elapsedRealtime, uptime);
5552            mAudioOnTimer.stopAllRunningLocked(elapsedRealtime);
5553            for (int i=0; i<mUidStats.size(); i++) {
5554                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5555                uid.noteResetAudioLocked(elapsedRealtime);
5556            }
5557        }
5558    }
5559
5560    public void noteResetVideoLocked() {
5561        if (mVideoOnNesting > 0) {
5562            final long elapsedRealtime = mClocks.elapsedRealtime();
5563            final long uptime = mClocks.uptimeMillis();
5564            mAudioOnNesting = 0;
5565            mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
5566            if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
5567                    + Integer.toHexString(mHistoryCur.states));
5568            addHistoryRecordLocked(elapsedRealtime, uptime);
5569            mVideoOnTimer.stopAllRunningLocked(elapsedRealtime);
5570            for (int i=0; i<mUidStats.size(); i++) {
5571                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5572                uid.noteResetVideoLocked(elapsedRealtime);
5573            }
5574        }
5575    }
5576
5577    public void noteActivityResumedLocked(int uid) {
5578        uid = mapUid(uid);
5579        getUidStatsLocked(uid).noteActivityResumedLocked(mClocks.elapsedRealtime());
5580    }
5581
5582    public void noteActivityPausedLocked(int uid) {
5583        uid = mapUid(uid);
5584        getUidStatsLocked(uid).noteActivityPausedLocked(mClocks.elapsedRealtime());
5585    }
5586
5587    public void noteVibratorOnLocked(int uid, long durationMillis) {
5588        uid = mapUid(uid);
5589        getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis);
5590    }
5591
5592    public void noteVibratorOffLocked(int uid) {
5593        uid = mapUid(uid);
5594        getUidStatsLocked(uid).noteVibratorOffLocked();
5595    }
5596
5597    public void noteFlashlightOnLocked(int uid) {
5598        uid = mapUid(uid);
5599        final long elapsedRealtime = mClocks.elapsedRealtime();
5600        final long uptime = mClocks.uptimeMillis();
5601        if (mFlashlightOnNesting++ == 0) {
5602            mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
5603            if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
5604                    + Integer.toHexString(mHistoryCur.states2));
5605            addHistoryRecordLocked(elapsedRealtime, uptime);
5606            mFlashlightOnTimer.startRunningLocked(elapsedRealtime);
5607        }
5608        getUidStatsLocked(uid).noteFlashlightTurnedOnLocked(elapsedRealtime);
5609    }
5610
5611    public void noteFlashlightOffLocked(int uid) {
5612        if (mFlashlightOnNesting == 0) {
5613            return;
5614        }
5615        uid = mapUid(uid);
5616        final long elapsedRealtime = mClocks.elapsedRealtime();
5617        final long uptime = mClocks.uptimeMillis();
5618        if (--mFlashlightOnNesting == 0) {
5619            mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
5620            if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
5621                    + Integer.toHexString(mHistoryCur.states2));
5622            addHistoryRecordLocked(elapsedRealtime, uptime);
5623            mFlashlightOnTimer.stopRunningLocked(elapsedRealtime);
5624        }
5625        getUidStatsLocked(uid).noteFlashlightTurnedOffLocked(elapsedRealtime);
5626    }
5627
5628    public void noteCameraOnLocked(int uid) {
5629        uid = mapUid(uid);
5630        final long elapsedRealtime = mClocks.elapsedRealtime();
5631        final long uptime = mClocks.uptimeMillis();
5632        if (mCameraOnNesting++ == 0) {
5633            mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
5634            if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
5635                    + Integer.toHexString(mHistoryCur.states2));
5636            addHistoryRecordLocked(elapsedRealtime, uptime);
5637            mCameraOnTimer.startRunningLocked(elapsedRealtime);
5638        }
5639        getUidStatsLocked(uid).noteCameraTurnedOnLocked(elapsedRealtime);
5640    }
5641
5642    public void noteCameraOffLocked(int uid) {
5643        if (mCameraOnNesting == 0) {
5644            return;
5645        }
5646        uid = mapUid(uid);
5647        final long elapsedRealtime = mClocks.elapsedRealtime();
5648        final long uptime = mClocks.uptimeMillis();
5649        if (--mCameraOnNesting == 0) {
5650            mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
5651            if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
5652                    + Integer.toHexString(mHistoryCur.states2));
5653            addHistoryRecordLocked(elapsedRealtime, uptime);
5654            mCameraOnTimer.stopRunningLocked(elapsedRealtime);
5655        }
5656        getUidStatsLocked(uid).noteCameraTurnedOffLocked(elapsedRealtime);
5657    }
5658
5659    public void noteResetCameraLocked() {
5660        if (mCameraOnNesting > 0) {
5661            final long elapsedRealtime = mClocks.elapsedRealtime();
5662            final long uptime = mClocks.uptimeMillis();
5663            mCameraOnNesting = 0;
5664            mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
5665            if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
5666                    + Integer.toHexString(mHistoryCur.states2));
5667            addHistoryRecordLocked(elapsedRealtime, uptime);
5668            mCameraOnTimer.stopAllRunningLocked(elapsedRealtime);
5669            for (int i=0; i<mUidStats.size(); i++) {
5670                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5671                uid.noteResetCameraLocked(elapsedRealtime);
5672            }
5673        }
5674    }
5675
5676    public void noteResetFlashlightLocked() {
5677        if (mFlashlightOnNesting > 0) {
5678            final long elapsedRealtime = mClocks.elapsedRealtime();
5679            final long uptime = mClocks.uptimeMillis();
5680            mFlashlightOnNesting = 0;
5681            mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
5682            if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
5683                    + Integer.toHexString(mHistoryCur.states2));
5684            addHistoryRecordLocked(elapsedRealtime, uptime);
5685            mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtime);
5686            for (int i=0; i<mUidStats.size(); i++) {
5687                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5688                uid.noteResetFlashlightLocked(elapsedRealtime);
5689            }
5690        }
5691    }
5692
5693    private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid,
5694            boolean isUnoptimized) {
5695        uid = getAttributionUid(uid, workChain);
5696        final long elapsedRealtime = mClocks.elapsedRealtime();
5697        final long uptime = mClocks.uptimeMillis();
5698        if (mBluetoothScanNesting == 0) {
5699            mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5700            if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
5701                    + Integer.toHexString(mHistoryCur.states2));
5702            addHistoryRecordLocked(elapsedRealtime, uptime);
5703            mBluetoothScanTimer.startRunningLocked(elapsedRealtime);
5704        }
5705        mBluetoothScanNesting++;
5706        getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime, isUnoptimized);
5707    }
5708
5709    public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
5710        final int N = ws.size();
5711        for (int i = 0; i < N; i++) {
5712            noteBluetoothScanStartedLocked(null, ws.get(i), isUnoptimized);
5713        }
5714
5715        final List<WorkChain> workChains = ws.getWorkChains();
5716        if (workChains != null) {
5717            for (int i = 0; i < workChains.size(); ++i) {
5718                noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized);
5719            }
5720        }
5721    }
5722
5723    private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid,
5724            boolean isUnoptimized) {
5725        uid = getAttributionUid(uid, workChain);
5726        final long elapsedRealtime = mClocks.elapsedRealtime();
5727        final long uptime = mClocks.uptimeMillis();
5728        mBluetoothScanNesting--;
5729        if (mBluetoothScanNesting == 0) {
5730            mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5731            if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
5732                    + Integer.toHexString(mHistoryCur.states2));
5733            addHistoryRecordLocked(elapsedRealtime, uptime);
5734            mBluetoothScanTimer.stopRunningLocked(elapsedRealtime);
5735        }
5736        getUidStatsLocked(uid).noteBluetoothScanStoppedLocked(elapsedRealtime, isUnoptimized);
5737    }
5738
5739    private int getAttributionUid(int uid, WorkChain workChain) {
5740        if (workChain != null) {
5741            return mapUid(workChain.getAttributionUid());
5742        }
5743
5744        return mapUid(uid);
5745    }
5746
5747    public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
5748        final int N = ws.size();
5749        for (int i = 0; i < N; i++) {
5750            noteBluetoothScanStoppedLocked(null, ws.get(i), isUnoptimized);
5751        }
5752
5753        final List<WorkChain> workChains = ws.getWorkChains();
5754        if (workChains != null) {
5755            for (int i = 0; i < workChains.size(); ++i) {
5756                noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized);
5757            }
5758        }
5759    }
5760
5761    public void noteResetBluetoothScanLocked() {
5762        if (mBluetoothScanNesting > 0) {
5763            final long elapsedRealtime = mClocks.elapsedRealtime();
5764            final long uptime = mClocks.uptimeMillis();
5765            mBluetoothScanNesting = 0;
5766            mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5767            if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
5768                    + Integer.toHexString(mHistoryCur.states2));
5769            addHistoryRecordLocked(elapsedRealtime, uptime);
5770            mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtime);
5771            for (int i=0; i<mUidStats.size(); i++) {
5772                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5773                uid.noteResetBluetoothScanLocked(elapsedRealtime);
5774            }
5775        }
5776    }
5777
5778    public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
5779        final int N = ws.size();
5780        for (int i = 0; i < N; i++) {
5781            int uid = mapUid(ws.get(i));
5782            getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
5783            StatsLog.write_non_chained(StatsLog.BLE_SCAN_RESULT_RECEIVED, ws.get(i), ws.getName(i),
5784                    numNewResults);
5785        }
5786
5787        final List<WorkChain> workChains = ws.getWorkChains();
5788        if (workChains != null) {
5789            for (int i = 0; i < workChains.size(); ++i) {
5790                final WorkChain wc = workChains.get(i);
5791                int uid = mapUid(wc.getAttributionUid());
5792                getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
5793                StatsLog.write(StatsLog.BLE_SCAN_RESULT_RECEIVED,
5794                        wc.getUids(), wc.getTags(), numNewResults);
5795            }
5796        }
5797    }
5798
5799    private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
5800            final long uptimeMillis, int uid) {
5801        uid = mapUid(uid);
5802        addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
5803                uid);
5804        getUidStatsLocked(uid).noteWifiRadioApWakeupLocked();
5805    }
5806
5807    public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) {
5808        final long elapsedRealtime = mClocks.elapsedRealtime();
5809        final long uptime = mClocks.uptimeMillis();
5810        if (mWifiRadioPowerState != powerState) {
5811            final boolean active =
5812                    powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
5813                            || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
5814            if (active) {
5815                if (uid > 0) {
5816                    noteWifiRadioApWakeupLocked(elapsedRealtime, uptime, uid);
5817                }
5818                mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
5819                mWifiActiveTimer.startRunningLocked(elapsedRealtime);
5820            } else {
5821                mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
5822                mWifiActiveTimer.stopRunningLocked(
5823                    timestampNs / (1000 * 1000));
5824            }
5825            if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
5826                    + Integer.toHexString(mHistoryCur.states));
5827            addHistoryRecordLocked(elapsedRealtime, uptime);
5828            mWifiRadioPowerState = powerState;
5829            StatsLog.write_non_chained(StatsLog.WIFI_RADIO_POWER_STATE_CHANGED, uid, null,
5830                    powerState);
5831        }
5832    }
5833
5834    public void noteWifiRunningLocked(WorkSource ws) {
5835        if (!mGlobalWifiRunning) {
5836            final long elapsedRealtime = mClocks.elapsedRealtime();
5837            final long uptime = mClocks.uptimeMillis();
5838            mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
5839            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
5840                    + Integer.toHexString(mHistoryCur.states));
5841            addHistoryRecordLocked(elapsedRealtime, uptime);
5842            mGlobalWifiRunning = true;
5843            mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
5844            int N = ws.size();
5845            for (int i=0; i<N; i++) {
5846                int uid = mapUid(ws.get(i));
5847                getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5848            }
5849
5850            List<WorkChain> workChains = ws.getWorkChains();
5851            if (workChains != null) {
5852                for (int i = 0; i < workChains.size(); ++i) {
5853                    int uid = mapUid(workChains.get(i).getAttributionUid());
5854                    getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5855                }
5856            }
5857
5858            scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
5859        } else {
5860            Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
5861        }
5862    }
5863
5864    public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
5865        if (mGlobalWifiRunning) {
5866            final long elapsedRealtime = mClocks.elapsedRealtime();
5867            int N = oldWs.size();
5868            for (int i=0; i<N; i++) {
5869                int uid = mapUid(oldWs.get(i));
5870                getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5871            }
5872
5873            List<WorkChain> workChains = oldWs.getWorkChains();
5874            if (workChains != null) {
5875                for (int i = 0; i < workChains.size(); ++i) {
5876                    int uid = mapUid(workChains.get(i).getAttributionUid());
5877                    getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5878                }
5879            }
5880
5881            N = newWs.size();
5882            for (int i=0; i<N; i++) {
5883                int uid = mapUid(newWs.get(i));
5884                getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5885            }
5886
5887            workChains = newWs.getWorkChains();
5888            if (workChains != null) {
5889                for (int i = 0; i < workChains.size(); ++i) {
5890                    int uid = mapUid(workChains.get(i).getAttributionUid());
5891                    getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5892                }
5893            }
5894        } else {
5895            Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
5896        }
5897    }
5898
5899    public void noteWifiStoppedLocked(WorkSource ws) {
5900        if (mGlobalWifiRunning) {
5901            final long elapsedRealtime = mClocks.elapsedRealtime();
5902            final long uptime = mClocks.uptimeMillis();
5903            mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
5904            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
5905                    + Integer.toHexString(mHistoryCur.states));
5906            addHistoryRecordLocked(elapsedRealtime, uptime);
5907            mGlobalWifiRunning = false;
5908            mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
5909            int N = ws.size();
5910            for (int i=0; i<N; i++) {
5911                int uid = mapUid(ws.get(i));
5912                getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5913            }
5914
5915            List<WorkChain> workChains = ws.getWorkChains();
5916            if (workChains != null) {
5917                for (int i = 0; i < workChains.size(); ++i) {
5918                    int uid = mapUid(workChains.get(i).getAttributionUid());
5919                    getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5920                }
5921            }
5922
5923            scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
5924        } else {
5925            Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
5926        }
5927    }
5928
5929    public void noteWifiStateLocked(int wifiState, String accessPoint) {
5930        if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
5931        if (mWifiState != wifiState) {
5932            final long elapsedRealtime = mClocks.elapsedRealtime();
5933            if (mWifiState >= 0) {
5934                mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
5935            }
5936            mWifiState = wifiState;
5937            mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
5938            scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
5939        }
5940    }
5941
5942    public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
5943        if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
5944        if (mWifiSupplState != supplState) {
5945            final long elapsedRealtime = mClocks.elapsedRealtime();
5946            final long uptime = mClocks.uptimeMillis();
5947            if (mWifiSupplState >= 0) {
5948                mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime);
5949            }
5950            mWifiSupplState = supplState;
5951            mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtime);
5952            mHistoryCur.states2 =
5953                    (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
5954                    | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
5955            if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
5956                    + Integer.toHexString(mHistoryCur.states2));
5957            addHistoryRecordLocked(elapsedRealtime, uptime);
5958        }
5959    }
5960
5961    void stopAllWifiSignalStrengthTimersLocked(int except) {
5962        final long elapsedRealtime = mClocks.elapsedRealtime();
5963        for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
5964            if (i == except) {
5965                continue;
5966            }
5967            while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
5968                mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
5969            }
5970        }
5971    }
5972
5973    public void noteWifiRssiChangedLocked(int newRssi) {
5974        int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
5975        if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
5976        if (mWifiSignalStrengthBin != strengthBin) {
5977            final long elapsedRealtime = mClocks.elapsedRealtime();
5978            final long uptime = mClocks.uptimeMillis();
5979            if (mWifiSignalStrengthBin >= 0) {
5980                mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
5981                        elapsedRealtime);
5982            }
5983            if (strengthBin >= 0) {
5984                if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
5985                    mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
5986                }
5987                mHistoryCur.states2 =
5988                        (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
5989                        | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
5990                if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
5991                        + Integer.toHexString(mHistoryCur.states2));
5992                addHistoryRecordLocked(elapsedRealtime, uptime);
5993            } else {
5994                stopAllWifiSignalStrengthTimersLocked(-1);
5995            }
5996            StatsLog.write(StatsLog.WIFI_SIGNAL_STRENGTH_CHANGED, strengthBin);
5997            mWifiSignalStrengthBin = strengthBin;
5998        }
5999    }
6000
6001    int mWifiFullLockNesting = 0;
6002
6003    public void noteFullWifiLockAcquiredLocked(int uid) {
6004        final long elapsedRealtime = mClocks.elapsedRealtime();
6005        final long uptime = mClocks.uptimeMillis();
6006        if (mWifiFullLockNesting == 0) {
6007            mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
6008            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
6009                    + Integer.toHexString(mHistoryCur.states));
6010            addHistoryRecordLocked(elapsedRealtime, uptime);
6011        }
6012        mWifiFullLockNesting++;
6013        getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
6014    }
6015
6016    public void noteFullWifiLockReleasedLocked(int uid) {
6017        final long elapsedRealtime = mClocks.elapsedRealtime();
6018        final long uptime = mClocks.uptimeMillis();
6019        mWifiFullLockNesting--;
6020        if (mWifiFullLockNesting == 0) {
6021            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
6022            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
6023                    + Integer.toHexString(mHistoryCur.states));
6024            addHistoryRecordLocked(elapsedRealtime, uptime);
6025        }
6026        getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime);
6027    }
6028
6029    int mWifiScanNesting = 0;
6030
6031    public void noteWifiScanStartedLocked(int uid) {
6032        final long elapsedRealtime = mClocks.elapsedRealtime();
6033        final long uptime = mClocks.uptimeMillis();
6034        if (mWifiScanNesting == 0) {
6035            mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
6036            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
6037                    + Integer.toHexString(mHistoryCur.states));
6038            addHistoryRecordLocked(elapsedRealtime, uptime);
6039        }
6040        mWifiScanNesting++;
6041        getUidStatsLocked(uid).noteWifiScanStartedLocked(elapsedRealtime);
6042    }
6043
6044    public void noteWifiScanStoppedLocked(int uid) {
6045        final long elapsedRealtime = mClocks.elapsedRealtime();
6046        final long uptime = mClocks.uptimeMillis();
6047        mWifiScanNesting--;
6048        if (mWifiScanNesting == 0) {
6049            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
6050            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
6051                    + Integer.toHexString(mHistoryCur.states));
6052            addHistoryRecordLocked(elapsedRealtime, uptime);
6053        }
6054        getUidStatsLocked(uid).noteWifiScanStoppedLocked(elapsedRealtime);
6055    }
6056
6057    public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
6058        uid = mapUid(uid);
6059        final long elapsedRealtime = mClocks.elapsedRealtime();
6060        getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime);
6061    }
6062
6063    public void noteWifiBatchedScanStoppedLocked(int uid) {
6064        uid = mapUid(uid);
6065        final long elapsedRealtime = mClocks.elapsedRealtime();
6066        getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime);
6067    }
6068
6069    int mWifiMulticastNesting = 0;
6070
6071    public void noteWifiMulticastEnabledLocked(int uid) {
6072        uid = mapUid(uid);
6073        final long elapsedRealtime = mClocks.elapsedRealtime();
6074        final long uptime = mClocks.uptimeMillis();
6075        if (mWifiMulticastNesting == 0) {
6076            mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
6077            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
6078                    + Integer.toHexString(mHistoryCur.states));
6079            addHistoryRecordLocked(elapsedRealtime, uptime);
6080
6081            // Start Wifi Multicast overall timer
6082            if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
6083                if (DEBUG_HISTORY) Slog.v(TAG, "WiFi Multicast Overall Timer Started");
6084                mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtime);
6085            }
6086        }
6087        mWifiMulticastNesting++;
6088        getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
6089    }
6090
6091    public void noteWifiMulticastDisabledLocked(int uid) {
6092        uid = mapUid(uid);
6093        final long elapsedRealtime = mClocks.elapsedRealtime();
6094        final long uptime = mClocks.uptimeMillis();
6095        mWifiMulticastNesting--;
6096        if (mWifiMulticastNesting == 0) {
6097            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
6098            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
6099                    + Integer.toHexString(mHistoryCur.states));
6100            addHistoryRecordLocked(elapsedRealtime, uptime);
6101
6102            // Stop Wifi Multicast overall timer
6103            if (mWifiMulticastWakelockTimer.isRunningLocked()) {
6104                if (DEBUG_HISTORY) Slog.v(TAG, "Multicast Overall Timer Stopped");
6105                mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtime);
6106            }
6107        }
6108        getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime);
6109    }
6110
6111    public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
6112        int N = ws.size();
6113        for (int i=0; i<N; i++) {
6114            final int uid = mapUid(ws.get(i));
6115            noteFullWifiLockAcquiredLocked(uid);
6116            StatsLog.write_non_chained(StatsLog.WIFI_LOCK_STATE_CHANGED, ws.get(i), ws.getName(i),
6117                    StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON);
6118        }
6119
6120        final List<WorkChain> workChains = ws.getWorkChains();
6121        if (workChains != null) {
6122            for (int i = 0; i < workChains.size(); ++i) {
6123                final WorkChain workChain = workChains.get(i);
6124                final int uid = mapUid(workChain.getAttributionUid());
6125                noteFullWifiLockAcquiredLocked(uid);
6126                StatsLog.write(StatsLog.WIFI_LOCK_STATE_CHANGED,
6127                        workChain.getUids(), workChain.getTags(),
6128                        StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON);
6129            }
6130        }
6131    }
6132
6133    public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
6134        int N = ws.size();
6135        for (int i=0; i<N; i++) {
6136            final int uid = mapUid(ws.get(i));
6137            noteFullWifiLockReleasedLocked(uid);
6138            StatsLog.write_non_chained(StatsLog.WIFI_LOCK_STATE_CHANGED, ws.get(i), ws.getName(i),
6139                    StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF);
6140        }
6141
6142        final List<WorkChain> workChains = ws.getWorkChains();
6143        if (workChains != null) {
6144            for (int i = 0; i < workChains.size(); ++i) {
6145                final WorkChain workChain = workChains.get(i);
6146                final int uid = mapUid(workChain.getAttributionUid());
6147                noteFullWifiLockReleasedLocked(uid);
6148                StatsLog.write(StatsLog.WIFI_LOCK_STATE_CHANGED,
6149                        workChain.getUids(), workChain.getTags(),
6150                        StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF);
6151            }
6152        }
6153    }
6154
6155    public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
6156        int N = ws.size();
6157        for (int i=0; i<N; i++) {
6158            final int uid = mapUid(ws.get(i));
6159            noteWifiScanStartedLocked(uid);
6160            StatsLog.write_non_chained(StatsLog.WIFI_SCAN_STATE_CHANGED, ws.get(i), ws.getName(i),
6161                    StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__ON);
6162        }
6163
6164        final List<WorkChain> workChains = ws.getWorkChains();
6165        if (workChains != null) {
6166            for (int i = 0; i < workChains.size(); ++i) {
6167                final WorkChain workChain = workChains.get(i);
6168                final int uid = mapUid(workChain.getAttributionUid());
6169                noteWifiScanStartedLocked(uid);
6170                StatsLog.write(StatsLog.WIFI_SCAN_STATE_CHANGED, workChain.getUids(),
6171                        workChain.getTags(), StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__ON);
6172            }
6173        }
6174    }
6175
6176    public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
6177        int N = ws.size();
6178        for (int i=0; i<N; i++) {
6179            final int uid = mapUid(ws.get(i));
6180            noteWifiScanStoppedLocked(uid);
6181            StatsLog.write_non_chained(StatsLog.WIFI_SCAN_STATE_CHANGED, ws.get(i), ws.getName(i),
6182                    StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__OFF);
6183        }
6184
6185        final List<WorkChain> workChains = ws.getWorkChains();
6186        if (workChains != null) {
6187            for (int i = 0; i < workChains.size(); ++i) {
6188                final WorkChain workChain = workChains.get(i);
6189                final int uid = mapUid(workChain.getAttributionUid());
6190                noteWifiScanStoppedLocked(uid);
6191                StatsLog.write(StatsLog.WIFI_SCAN_STATE_CHANGED,
6192                        workChain.getUids(), workChain.getTags(),
6193                        StatsLog.WIFI_SCAN_STATE_CHANGED__STATE__OFF);
6194            }
6195        }
6196    }
6197
6198    public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
6199        int N = ws.size();
6200        for (int i=0; i<N; i++) {
6201            noteWifiBatchedScanStartedLocked(ws.get(i), csph);
6202        }
6203
6204        final List<WorkChain> workChains = ws.getWorkChains();
6205        if (workChains != null) {
6206            for (int i = 0; i < workChains.size(); ++i) {
6207                noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph);
6208            }
6209        }
6210    }
6211
6212    public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
6213        int N = ws.size();
6214        for (int i=0; i<N; i++) {
6215            noteWifiBatchedScanStoppedLocked(ws.get(i));
6216        }
6217
6218        final List<WorkChain> workChains = ws.getWorkChains();
6219        if (workChains != null) {
6220            for (int i = 0; i < workChains.size(); ++i) {
6221                noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid());
6222            }
6223        }
6224    }
6225
6226    private static String[] includeInStringArray(String[] array, String str) {
6227        if (ArrayUtils.indexOf(array, str) >= 0) {
6228            return array;
6229        }
6230        String[] newArray = new String[array.length+1];
6231        System.arraycopy(array, 0, newArray, 0, array.length);
6232        newArray[array.length] = str;
6233        return newArray;
6234    }
6235
6236    private static String[] excludeFromStringArray(String[] array, String str) {
6237        int index = ArrayUtils.indexOf(array, str);
6238        if (index >= 0) {
6239            String[] newArray = new String[array.length-1];
6240            if (index > 0) {
6241                System.arraycopy(array, 0, newArray, 0, index);
6242            }
6243            if (index < array.length-1) {
6244                System.arraycopy(array, index+1, newArray, index, array.length-index-1);
6245            }
6246            return newArray;
6247        }
6248        return array;
6249    }
6250
6251    public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
6252        if (TextUtils.isEmpty(iface)) return;
6253
6254        synchronized (mModemNetworkLock) {
6255            if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
6256                mModemIfaces = includeInStringArray(mModemIfaces, iface);
6257                if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mModemIfaces);
6258            } else {
6259                mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
6260                if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mModemIfaces);
6261            }
6262        }
6263
6264        synchronized (mWifiNetworkLock) {
6265            if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
6266                mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
6267                if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
6268            } else {
6269                mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
6270                if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
6271            }
6272        }
6273    }
6274
6275    public String[] getWifiIfaces() {
6276        synchronized (mWifiNetworkLock) {
6277            return mWifiIfaces;
6278        }
6279    }
6280
6281    public String[] getMobileIfaces() {
6282        synchronized (mModemNetworkLock) {
6283            return mModemIfaces;
6284        }
6285    }
6286
6287    @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
6288        return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6289    }
6290
6291    @Override public int getScreenOnCount(int which) {
6292        return mScreenOnTimer.getCountLocked(which);
6293    }
6294
6295    @Override public long getScreenDozeTime(long elapsedRealtimeUs, int which) {
6296        return mScreenDozeTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6297    }
6298
6299    @Override public int getScreenDozeCount(int which) {
6300        return mScreenDozeTimer.getCountLocked(which);
6301    }
6302
6303    @Override public long getScreenBrightnessTime(int brightnessBin,
6304            long elapsedRealtimeUs, int which) {
6305        return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
6306                elapsedRealtimeUs, which);
6307    }
6308
6309    @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
6310        return mScreenBrightnessTimer[brightnessBin];
6311    }
6312
6313    @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
6314        return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6315    }
6316
6317    @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
6318        return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6319    }
6320
6321    @Override public int getPowerSaveModeEnabledCount(int which) {
6322        return mPowerSaveModeEnabledTimer.getCountLocked(which);
6323    }
6324
6325    @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
6326            int which) {
6327        switch (mode) {
6328            case DEVICE_IDLE_MODE_LIGHT:
6329                return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6330            case DEVICE_IDLE_MODE_DEEP:
6331                return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6332        }
6333        return 0;
6334    }
6335
6336    @Override public int getDeviceIdleModeCount(int mode, int which) {
6337        switch (mode) {
6338            case DEVICE_IDLE_MODE_LIGHT:
6339                return mDeviceIdleModeLightTimer.getCountLocked(which);
6340            case DEVICE_IDLE_MODE_DEEP:
6341                return mDeviceIdleModeFullTimer.getCountLocked(which);
6342        }
6343        return 0;
6344    }
6345
6346    @Override public long getLongestDeviceIdleModeTime(int mode) {
6347        switch (mode) {
6348            case DEVICE_IDLE_MODE_LIGHT:
6349                return mLongestLightIdleTime;
6350            case DEVICE_IDLE_MODE_DEEP:
6351                return mLongestFullIdleTime;
6352        }
6353        return 0;
6354    }
6355
6356    @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
6357        switch (mode) {
6358            case DEVICE_IDLE_MODE_LIGHT:
6359                return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6360            case DEVICE_IDLE_MODE_DEEP:
6361                return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6362        }
6363        return 0;
6364    }
6365
6366    @Override public int getDeviceIdlingCount(int mode, int which) {
6367        switch (mode) {
6368            case DEVICE_IDLE_MODE_LIGHT:
6369                return mDeviceLightIdlingTimer.getCountLocked(which);
6370            case DEVICE_IDLE_MODE_DEEP:
6371                return mDeviceIdlingTimer.getCountLocked(which);
6372        }
6373        return 0;
6374    }
6375
6376    @Override public int getNumConnectivityChange(int which) {
6377        int val = mNumConnectivityChange;
6378        if (which == STATS_CURRENT) {
6379            val -= mLoadedNumConnectivityChange;
6380        } else if (which == STATS_SINCE_UNPLUGGED) {
6381            val -= mUnpluggedNumConnectivityChange;
6382        }
6383        return val;
6384    }
6385
6386    @Override public long getGpsSignalQualityTime(int strengthBin,
6387        long elapsedRealtimeUs, int which) {
6388        if (strengthBin < 0 || strengthBin >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
6389            return 0;
6390        }
6391        return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
6392            elapsedRealtimeUs, which);
6393    }
6394
6395    @Override public long getGpsBatteryDrainMaMs() {
6396        final double opVolt = mPowerProfile.getAveragePower(
6397            PowerProfile.POWER_GPS_OPERATING_VOLTAGE) / 1000.0;
6398        if (opVolt == 0) {
6399            return 0;
6400        }
6401        double energyUsedMaMs = 0.0;
6402        final int which = STATS_SINCE_CHARGED;
6403        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
6404        for(int i=0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
6405            energyUsedMaMs
6406                += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
6407                * (getGpsSignalQualityTime(i, rawRealtime, which) / 1000);
6408        }
6409        return (long) energyUsedMaMs;
6410    }
6411
6412    @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
6413        return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6414    }
6415
6416    @Override public int getPhoneOnCount(int which) {
6417        return mPhoneOnTimer.getCountLocked(which);
6418    }
6419
6420    @Override public long getPhoneSignalStrengthTime(int strengthBin,
6421            long elapsedRealtimeUs, int which) {
6422        return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
6423                elapsedRealtimeUs, which);
6424    }
6425
6426    @Override public long getPhoneSignalScanningTime(
6427            long elapsedRealtimeUs, int which) {
6428        return mPhoneSignalScanningTimer.getTotalTimeLocked(
6429                elapsedRealtimeUs, which);
6430    }
6431
6432    @Override public Timer getPhoneSignalScanningTimer() {
6433        return mPhoneSignalScanningTimer;
6434    }
6435
6436    @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
6437        return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
6438    }
6439
6440    @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
6441        return mPhoneSignalStrengthsTimer[strengthBin];
6442    }
6443
6444    @Override public long getPhoneDataConnectionTime(int dataType,
6445            long elapsedRealtimeUs, int which) {
6446        return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
6447                elapsedRealtimeUs, which);
6448    }
6449
6450    @Override public int getPhoneDataConnectionCount(int dataType, int which) {
6451        return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
6452    }
6453
6454    @Override public Timer getPhoneDataConnectionTimer(int dataType) {
6455        return mPhoneDataConnectionsTimer[dataType];
6456    }
6457
6458    @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
6459        return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6460    }
6461
6462    @Override public int getMobileRadioActiveCount(int which) {
6463        return mMobileRadioActiveTimer.getCountLocked(which);
6464    }
6465
6466    @Override public long getMobileRadioActiveAdjustedTime(int which) {
6467        return mMobileRadioActiveAdjustedTime.getCountLocked(which);
6468    }
6469
6470    @Override public long getMobileRadioActiveUnknownTime(int which) {
6471        return mMobileRadioActiveUnknownTime.getCountLocked(which);
6472    }
6473
6474    @Override public int getMobileRadioActiveUnknownCount(int which) {
6475        return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
6476    }
6477
6478    @Override public long getWifiMulticastWakelockTime(
6479            long elapsedRealtimeUs, int which) {
6480        return mWifiMulticastWakelockTimer.getTotalTimeLocked(
6481                elapsedRealtimeUs, which);
6482    }
6483
6484    @Override public int getWifiMulticastWakelockCount(int which) {
6485        return mWifiMulticastWakelockTimer.getCountLocked(which);
6486    }
6487
6488    @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
6489        return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6490    }
6491
6492    @Override public long getWifiActiveTime(long elapsedRealtimeUs, int which) {
6493        return mWifiActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6494    }
6495
6496    @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
6497        return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6498    }
6499
6500    @Override public long getWifiStateTime(int wifiState,
6501            long elapsedRealtimeUs, int which) {
6502        return mWifiStateTimer[wifiState].getTotalTimeLocked(
6503                elapsedRealtimeUs, which);
6504    }
6505
6506    @Override public int getWifiStateCount(int wifiState, int which) {
6507        return mWifiStateTimer[wifiState].getCountLocked(which);
6508    }
6509
6510    @Override public Timer getWifiStateTimer(int wifiState) {
6511        return mWifiStateTimer[wifiState];
6512    }
6513
6514    @Override public long getWifiSupplStateTime(int state,
6515            long elapsedRealtimeUs, int which) {
6516        return mWifiSupplStateTimer[state].getTotalTimeLocked(
6517                elapsedRealtimeUs, which);
6518    }
6519
6520    @Override public int getWifiSupplStateCount(int state, int which) {
6521        return mWifiSupplStateTimer[state].getCountLocked(which);
6522    }
6523
6524    @Override public Timer getWifiSupplStateTimer(int state) {
6525        return mWifiSupplStateTimer[state];
6526    }
6527
6528    @Override public long getWifiSignalStrengthTime(int strengthBin,
6529            long elapsedRealtimeUs, int which) {
6530        return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
6531                elapsedRealtimeUs, which);
6532    }
6533
6534    @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
6535        return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
6536    }
6537
6538    @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
6539        return mWifiSignalStrengthsTimer[strengthBin];
6540    }
6541
6542    @Override
6543    public ControllerActivityCounter getBluetoothControllerActivity() {
6544        return mBluetoothActivity;
6545    }
6546
6547    @Override
6548    public ControllerActivityCounter getWifiControllerActivity() {
6549        return mWifiActivity;
6550    }
6551
6552    @Override
6553    public ControllerActivityCounter getModemControllerActivity() {
6554        return mModemActivity;
6555    }
6556
6557    @Override
6558    public boolean hasBluetoothActivityReporting() {
6559        return mHasBluetoothReporting;
6560    }
6561
6562    @Override
6563    public boolean hasWifiActivityReporting() {
6564        return mHasWifiReporting;
6565    }
6566
6567    @Override
6568    public boolean hasModemActivityReporting() {
6569        return mHasModemReporting;
6570    }
6571
6572    @Override
6573    public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
6574        return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6575    }
6576
6577    @Override
6578    public long getFlashlightOnCount(int which) {
6579        return mFlashlightOnTimer.getCountLocked(which);
6580    }
6581
6582    @Override
6583    public long getCameraOnTime(long elapsedRealtimeUs, int which) {
6584        return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6585    }
6586
6587    @Override
6588    public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
6589        return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6590    }
6591
6592    @Override
6593    public long getNetworkActivityBytes(int type, int which) {
6594        if (type >= 0 && type < mNetworkByteActivityCounters.length) {
6595            return mNetworkByteActivityCounters[type].getCountLocked(which);
6596        } else {
6597            return 0;
6598        }
6599    }
6600
6601    @Override
6602    public long getNetworkActivityPackets(int type, int which) {
6603        if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
6604            return mNetworkPacketActivityCounters[type].getCountLocked(which);
6605        } else {
6606            return 0;
6607        }
6608    }
6609
6610    @Override public long getStartClockTime() {
6611        final long currentTime = System.currentTimeMillis();
6612        if (ensureStartClockTime(currentTime)) {
6613            recordCurrentTimeChangeLocked(currentTime, mClocks.elapsedRealtime(),
6614                    mClocks.uptimeMillis());
6615        }
6616        return mStartClockTime;
6617    }
6618
6619    @Override public String getStartPlatformVersion() {
6620        return mStartPlatformVersion;
6621    }
6622
6623    @Override public String getEndPlatformVersion() {
6624        return mEndPlatformVersion;
6625    }
6626
6627    @Override public int getParcelVersion() {
6628        return VERSION;
6629    }
6630
6631    @Override public boolean getIsOnBattery() {
6632        return mOnBattery;
6633    }
6634
6635    @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
6636        return mUidStats;
6637    }
6638
6639    private static void detachTimerIfNotNull(BatteryStatsImpl.Timer timer) {
6640        if (timer != null) {
6641            timer.detach();
6642        }
6643    }
6644
6645    private static boolean resetTimerIfNotNull(BatteryStatsImpl.Timer timer,
6646            boolean detachIfReset) {
6647        if (timer != null) {
6648            return timer.reset(detachIfReset);
6649        }
6650        return true;
6651    }
6652
6653    private static boolean resetTimerIfNotNull(DualTimer timer, boolean detachIfReset) {
6654        if (timer != null) {
6655            return timer.reset(detachIfReset);
6656        }
6657        return true;
6658    }
6659
6660    private static void detachLongCounterIfNotNull(LongSamplingCounter counter) {
6661        if (counter != null) {
6662            counter.detach();
6663        }
6664    }
6665
6666    private static void resetLongCounterIfNotNull(LongSamplingCounter counter,
6667            boolean detachIfReset) {
6668        if (counter != null) {
6669            counter.reset(detachIfReset);
6670        }
6671    }
6672
6673    /**
6674     * The statistics associated with a particular uid.
6675     */
6676    public static class Uid extends BatteryStats.Uid {
6677        /**
6678         * BatteryStatsImpl that we are associated with.
6679         */
6680        protected BatteryStatsImpl mBsi;
6681
6682        final int mUid;
6683
6684        /** TimeBase for when uid is in background and device is on battery. */
6685        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
6686        public final TimeBase mOnBatteryBackgroundTimeBase;
6687        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
6688        public final TimeBase mOnBatteryScreenOffBackgroundTimeBase;
6689
6690        boolean mWifiRunning;
6691        StopwatchTimer mWifiRunningTimer;
6692
6693        boolean mFullWifiLockOut;
6694        StopwatchTimer mFullWifiLockTimer;
6695
6696        boolean mWifiScanStarted;
6697        DualTimer mWifiScanTimer;
6698
6699        static final int NO_BATCHED_SCAN_STARTED = -1;
6700        int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
6701        StopwatchTimer[] mWifiBatchedScanTimer;
6702
6703        boolean mWifiMulticastEnabled;
6704        StopwatchTimer mWifiMulticastTimer;
6705
6706        StopwatchTimer mAudioTurnedOnTimer;
6707        StopwatchTimer mVideoTurnedOnTimer;
6708        StopwatchTimer mFlashlightTurnedOnTimer;
6709        StopwatchTimer mCameraTurnedOnTimer;
6710        StopwatchTimer mForegroundActivityTimer;
6711        StopwatchTimer mForegroundServiceTimer;
6712        /** Total time spent by the uid holding any partial wakelocks. */
6713        DualTimer mAggregatedPartialWakelockTimer;
6714        DualTimer mBluetoothScanTimer;
6715        DualTimer mBluetoothUnoptimizedScanTimer;
6716        Counter mBluetoothScanResultCounter;
6717        Counter mBluetoothScanResultBgCounter;
6718
6719        int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
6720        StopwatchTimer[] mProcessStateTimer;
6721
6722        boolean mInForegroundService = false;
6723
6724        BatchTimer mVibratorOnTimer;
6725
6726        Counter[] mUserActivityCounters;
6727
6728        LongSamplingCounter[] mNetworkByteActivityCounters;
6729        LongSamplingCounter[] mNetworkPacketActivityCounters;
6730        LongSamplingCounter mMobileRadioActiveTime;
6731        LongSamplingCounter mMobileRadioActiveCount;
6732
6733        /**
6734         * How many times this UID woke up the Application Processor due to a Mobile radio packet.
6735         */
6736        private LongSamplingCounter mMobileRadioApWakeupCount;
6737
6738        /**
6739         * How many times this UID woke up the Application Processor due to a Wifi packet.
6740         */
6741        private LongSamplingCounter mWifiRadioApWakeupCount;
6742
6743        /**
6744         * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
6745         * Can be null if the UID has had no such activity.
6746         */
6747        private ControllerActivityCounterImpl mWifiControllerActivity;
6748
6749        /**
6750         * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
6751         * Can be null if the UID has had no such activity.
6752         */
6753        private ControllerActivityCounterImpl mBluetoothControllerActivity;
6754
6755        /**
6756         * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
6757         * Can be null if the UID has had no such activity.
6758         */
6759        private ControllerActivityCounterImpl mModemControllerActivity;
6760
6761        /**
6762         * The CPU times we had at the last history details update.
6763         */
6764        long mLastStepUserTime;
6765        long mLastStepSystemTime;
6766        long mCurStepUserTime;
6767        long mCurStepSystemTime;
6768
6769        LongSamplingCounter mUserCpuTime;
6770        LongSamplingCounter mSystemCpuTime;
6771        LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
6772        LongSamplingCounter mCpuActiveTimeMs;
6773
6774        LongSamplingCounterArray mCpuFreqTimeMs;
6775        LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
6776        LongSamplingCounterArray mCpuClusterTimesMs;
6777
6778        LongSamplingCounterArray[] mProcStateTimeMs;
6779        LongSamplingCounterArray[] mProcStateScreenOffTimeMs;
6780
6781        IntArray mChildUids;
6782
6783        /**
6784         * The statistics we have collected for this uid's wake locks.
6785         */
6786        final OverflowArrayMap<Wakelock> mWakelockStats;
6787
6788        /**
6789         * The statistics we have collected for this uid's syncs.
6790         */
6791        final OverflowArrayMap<DualTimer> mSyncStats;
6792
6793        /**
6794         * The statistics we have collected for this uid's jobs.
6795         */
6796        final OverflowArrayMap<DualTimer> mJobStats;
6797
6798        /**
6799         * Count of the jobs that have completed and the reasons why they completed.
6800         */
6801        final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
6802
6803        /**
6804         * Count of app launch events that had associated deferred job counts or info about
6805         * last time a job was run.
6806         */
6807        Counter mJobsDeferredEventCount;
6808
6809        /**
6810         * Count of deferred jobs that were pending when the app was launched or brought to
6811         * the foreground through a user interaction.
6812         */
6813        Counter mJobsDeferredCount;
6814
6815        /**
6816         * Sum of time since the last time a job was run for this app before it was launched.
6817         */
6818        LongSamplingCounter mJobsFreshnessTimeMs;
6819
6820        /**
6821         * Array of counts of instances where the time since the last job was run for the app
6822         * fell within one of the thresholds in {@link #JOB_FRESHNESS_BUCKETS}.
6823         */
6824        final Counter[] mJobsFreshnessBuckets;
6825
6826        /**
6827         * The statistics we have collected for this uid's sensor activations.
6828         */
6829        final SparseArray<Sensor> mSensorStats = new SparseArray<>();
6830
6831        /**
6832         * The statistics we have collected for this uid's processes.
6833         */
6834        final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
6835
6836        /**
6837         * The statistics we have collected for this uid's processes.
6838         */
6839        final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
6840
6841        /**
6842         * The transient wake stats we have collected for this uid's pids.
6843         */
6844        final SparseArray<Pid> mPids = new SparseArray<>();
6845
6846        public Uid(BatteryStatsImpl bsi, int uid) {
6847            mBsi = bsi;
6848            mUid = uid;
6849
6850            mOnBatteryBackgroundTimeBase = new TimeBase();
6851            mOnBatteryBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
6852                    mBsi.mClocks.elapsedRealtime() * 1000);
6853
6854            mOnBatteryScreenOffBackgroundTimeBase = new TimeBase();
6855            mOnBatteryScreenOffBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
6856                    mBsi.mClocks.elapsedRealtime() * 1000);
6857
6858            mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6859            mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6860            mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6861            mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase);
6862
6863            mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
6864                @Override public Wakelock instantiateObject() {
6865                    return new Wakelock(mBsi, Uid.this);
6866                }
6867            };
6868            mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
6869                @Override public DualTimer instantiateObject() {
6870                    return new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
6871                            mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6872                }
6873            };
6874            mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
6875                @Override public DualTimer instantiateObject() {
6876                    return new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
6877                            mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6878                }
6879            };
6880
6881            mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_RUNNING,
6882                    mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
6883            mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, this, FULL_WIFI_LOCK,
6884                    mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
6885            mWifiScanTimer = new DualTimer(mBsi.mClocks, this, WIFI_SCAN,
6886                    mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6887            mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
6888            mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_MULTICAST_ENABLED,
6889                    mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
6890            mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
6891            mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase);
6892            mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase);
6893            mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6894            mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length];
6895        }
6896
6897        @VisibleForTesting
6898        public void setProcessStateForTest(int procState) {
6899            mProcessState = procState;
6900        }
6901
6902        @Override
6903        public long[] getCpuFreqTimes(int which) {
6904            return nullIfAllZeros(mCpuFreqTimeMs, which);
6905        }
6906
6907        @Override
6908        public long[] getScreenOffCpuFreqTimes(int which) {
6909            return nullIfAllZeros(mScreenOffCpuFreqTimeMs, which);
6910        }
6911
6912        @Override
6913        public long getCpuActiveTime() {
6914            return mCpuActiveTimeMs.getCountLocked(STATS_SINCE_CHARGED);
6915        }
6916
6917        @Override
6918        public long[] getCpuClusterTimes() {
6919            return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
6920        }
6921
6922
6923        @Override
6924        public long[] getCpuFreqTimes(int which, int procState) {
6925            if (which < 0 || which >= NUM_PROCESS_STATE) {
6926                return null;
6927            }
6928            if (mProcStateTimeMs == null) {
6929                return null;
6930            }
6931            if (!mBsi.mPerProcStateCpuTimesAvailable) {
6932                mProcStateTimeMs = null;
6933                return null;
6934            }
6935            return nullIfAllZeros(mProcStateTimeMs[procState], which);
6936        }
6937
6938        @Override
6939        public long[] getScreenOffCpuFreqTimes(int which, int procState) {
6940            if (which < 0 || which >= NUM_PROCESS_STATE) {
6941                return null;
6942            }
6943            if (mProcStateScreenOffTimeMs == null) {
6944                return null;
6945            }
6946            if (!mBsi.mPerProcStateCpuTimesAvailable) {
6947                mProcStateScreenOffTimeMs = null;
6948                return null;
6949            }
6950            return nullIfAllZeros(mProcStateScreenOffTimeMs[procState], which);
6951        }
6952
6953        public void addIsolatedUid(int isolatedUid) {
6954            if (mChildUids == null) {
6955                mChildUids = new IntArray();
6956            } else if (mChildUids.indexOf(isolatedUid) >= 0) {
6957                return;
6958            }
6959            mChildUids.add(isolatedUid);
6960        }
6961
6962        public void removeIsolatedUid(int isolatedUid) {
6963            final int idx = mChildUids == null ? -1 : mChildUids.indexOf(isolatedUid);
6964            if (idx < 0) {
6965                return;
6966            }
6967            mChildUids.remove(idx);
6968        }
6969
6970        private long[] nullIfAllZeros(LongSamplingCounterArray cpuTimesMs, int which) {
6971            if (cpuTimesMs == null) {
6972                return null;
6973            }
6974            final long[] counts = cpuTimesMs.getCountsLocked(which);
6975            if (counts == null) {
6976                return null;
6977            }
6978            // Return counts only if at least one of the elements is non-zero.
6979            for (int i = counts.length - 1; i >= 0; --i) {
6980                if (counts[i] != 0) {
6981                    return counts;
6982                }
6983            }
6984            return null;
6985        }
6986
6987        private void addProcStateTimesMs(int procState, long[] cpuTimesMs, boolean onBattery) {
6988            if (mProcStateTimeMs == null) {
6989                mProcStateTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
6990            }
6991            if (mProcStateTimeMs[procState] == null
6992                    || mProcStateTimeMs[procState].getSize() != cpuTimesMs.length) {
6993                mProcStateTimeMs[procState] = new LongSamplingCounterArray(
6994                        mBsi.mOnBatteryTimeBase);
6995            }
6996            mProcStateTimeMs[procState].addCountLocked(cpuTimesMs, onBattery);
6997        }
6998
6999        private void addProcStateScreenOffTimesMs(int procState, long[] cpuTimesMs,
7000                boolean onBatteryScreenOff) {
7001            if (mProcStateScreenOffTimeMs == null) {
7002                mProcStateScreenOffTimeMs = new LongSamplingCounterArray[NUM_PROCESS_STATE];
7003            }
7004            if (mProcStateScreenOffTimeMs[procState] == null
7005                    || mProcStateScreenOffTimeMs[procState].getSize() != cpuTimesMs.length) {
7006                mProcStateScreenOffTimeMs[procState] = new LongSamplingCounterArray(
7007                        mBsi.mOnBatteryScreenOffTimeBase);
7008            }
7009            mProcStateScreenOffTimeMs[procState].addCountLocked(cpuTimesMs, onBatteryScreenOff);
7010        }
7011
7012        @Override
7013        public Timer getAggregatedPartialWakelockTimer() {
7014            return mAggregatedPartialWakelockTimer;
7015        }
7016
7017        @Override
7018        public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
7019            return mWakelockStats.getMap();
7020        }
7021
7022        @Override
7023        public Timer getMulticastWakelockStats() {
7024            return mWifiMulticastTimer;
7025        }
7026
7027        @Override
7028        public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
7029            return mSyncStats.getMap();
7030        }
7031
7032        @Override
7033        public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
7034            return mJobStats.getMap();
7035        }
7036
7037        @Override
7038        public ArrayMap<String, SparseIntArray> getJobCompletionStats() {
7039            return mJobCompletions;
7040        }
7041
7042        @Override
7043        public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
7044            return mSensorStats;
7045        }
7046
7047        @Override
7048        public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
7049            return mProcessStats;
7050        }
7051
7052        @Override
7053        public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
7054            return mPackageStats;
7055        }
7056
7057        @Override
7058        public int getUid() {
7059            return mUid;
7060        }
7061
7062        @Override
7063        public void noteWifiRunningLocked(long elapsedRealtimeMs) {
7064            if (!mWifiRunning) {
7065                mWifiRunning = true;
7066                if (mWifiRunningTimer == null) {
7067                    mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
7068                            mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
7069                }
7070                mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
7071            }
7072        }
7073
7074        @Override
7075        public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
7076            if (mWifiRunning) {
7077                mWifiRunning = false;
7078                mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
7079            }
7080        }
7081
7082        @Override
7083        public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
7084            if (!mFullWifiLockOut) {
7085                mFullWifiLockOut = true;
7086                if (mFullWifiLockTimer == null) {
7087                    mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
7088                            mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
7089                }
7090                mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
7091            }
7092        }
7093
7094        @Override
7095        public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
7096            if (mFullWifiLockOut) {
7097                mFullWifiLockOut = false;
7098                mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
7099            }
7100        }
7101
7102        @Override
7103        public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
7104            if (!mWifiScanStarted) {
7105                mWifiScanStarted = true;
7106                if (mWifiScanTimer == null) {
7107                    mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
7108                            mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase,
7109                            mOnBatteryBackgroundTimeBase);
7110                }
7111                mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
7112            }
7113        }
7114
7115        @Override
7116        public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
7117            if (mWifiScanStarted) {
7118                mWifiScanStarted = false;
7119                mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
7120            }
7121        }
7122
7123        @Override
7124        public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
7125            int bin = 0;
7126            while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
7127                csph = csph >> 3;
7128                bin++;
7129            }
7130
7131            if (mWifiBatchedScanBinStarted == bin) return;
7132
7133            if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
7134                mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
7135                        stopRunningLocked(elapsedRealtimeMs);
7136            }
7137            mWifiBatchedScanBinStarted = bin;
7138            if (mWifiBatchedScanTimer[bin] == null) {
7139                makeWifiBatchedScanBin(bin, null);
7140            }
7141            mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
7142        }
7143
7144        @Override
7145        public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
7146            if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
7147                mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
7148                        stopRunningLocked(elapsedRealtimeMs);
7149                mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
7150            }
7151        }
7152
7153        @Override
7154        public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
7155            if (!mWifiMulticastEnabled) {
7156                mWifiMulticastEnabled = true;
7157                if (mWifiMulticastTimer == null) {
7158                    mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7159                            WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
7160                }
7161                mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
7162                StatsLog.write_non_chained(
7163                        StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null,
7164                        StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED__STATE__ON);
7165            }
7166        }
7167
7168        @Override
7169        public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
7170            if (mWifiMulticastEnabled) {
7171                mWifiMulticastEnabled = false;
7172                mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
7173                StatsLog.write_non_chained(
7174                        StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null,
7175                        StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED__STATE__OFF);
7176            }
7177        }
7178
7179        @Override
7180        public ControllerActivityCounter getWifiControllerActivity() {
7181            return mWifiControllerActivity;
7182        }
7183
7184        @Override
7185        public ControllerActivityCounter getBluetoothControllerActivity() {
7186            return mBluetoothControllerActivity;
7187        }
7188
7189        @Override
7190        public ControllerActivityCounter getModemControllerActivity() {
7191            return mModemControllerActivity;
7192        }
7193
7194        public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
7195            if (mWifiControllerActivity == null) {
7196                mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7197                        NUM_BT_TX_LEVELS);
7198            }
7199            return mWifiControllerActivity;
7200        }
7201
7202        public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
7203            if (mBluetoothControllerActivity == null) {
7204                mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7205                        NUM_BT_TX_LEVELS);
7206            }
7207            return mBluetoothControllerActivity;
7208        }
7209
7210        public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
7211            if (mModemControllerActivity == null) {
7212                mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7213                        ModemActivityInfo.TX_POWER_LEVELS);
7214            }
7215            return mModemControllerActivity;
7216        }
7217
7218        public StopwatchTimer createAudioTurnedOnTimerLocked() {
7219            if (mAudioTurnedOnTimer == null) {
7220                mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
7221                        mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7222            }
7223            return mAudioTurnedOnTimer;
7224        }
7225
7226        public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
7227            createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7228        }
7229
7230        public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
7231            if (mAudioTurnedOnTimer != null) {
7232                mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7233            }
7234        }
7235
7236        public void noteResetAudioLocked(long elapsedRealtimeMs) {
7237            if (mAudioTurnedOnTimer != null) {
7238                mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7239            }
7240        }
7241
7242        public StopwatchTimer createVideoTurnedOnTimerLocked() {
7243            if (mVideoTurnedOnTimer == null) {
7244                mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
7245                        mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7246            }
7247            return mVideoTurnedOnTimer;
7248        }
7249
7250        public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
7251            createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7252        }
7253
7254        public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
7255            if (mVideoTurnedOnTimer != null) {
7256                mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7257            }
7258        }
7259
7260        public void noteResetVideoLocked(long elapsedRealtimeMs) {
7261            if (mVideoTurnedOnTimer != null) {
7262                mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7263            }
7264        }
7265
7266        public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
7267            if (mFlashlightTurnedOnTimer == null) {
7268                mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7269                        FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7270            }
7271            return mFlashlightTurnedOnTimer;
7272        }
7273
7274        public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
7275            createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7276        }
7277
7278        public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
7279            if (mFlashlightTurnedOnTimer != null) {
7280                mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7281            }
7282        }
7283
7284        public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
7285            if (mFlashlightTurnedOnTimer != null) {
7286                mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7287            }
7288        }
7289
7290        public StopwatchTimer createCameraTurnedOnTimerLocked() {
7291            if (mCameraTurnedOnTimer == null) {
7292                mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
7293                        mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
7294            }
7295            return mCameraTurnedOnTimer;
7296        }
7297
7298        public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
7299            createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
7300        }
7301
7302        public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
7303            if (mCameraTurnedOnTimer != null) {
7304                mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
7305            }
7306        }
7307
7308        public void noteResetCameraLocked(long elapsedRealtimeMs) {
7309            if (mCameraTurnedOnTimer != null) {
7310                mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
7311            }
7312        }
7313
7314        public StopwatchTimer createForegroundActivityTimerLocked() {
7315            if (mForegroundActivityTimer == null) {
7316                mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7317                        FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
7318            }
7319            return mForegroundActivityTimer;
7320        }
7321
7322        public StopwatchTimer createForegroundServiceTimerLocked() {
7323            if (mForegroundServiceTimer == null) {
7324                mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7325                        FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase);
7326            }
7327            return mForegroundServiceTimer;
7328        }
7329
7330        public DualTimer createAggregatedPartialWakelockTimerLocked() {
7331            if (mAggregatedPartialWakelockTimer == null) {
7332                mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
7333                        AGGREGATED_WAKE_TYPE_PARTIAL, null,
7334                        mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase);
7335            }
7336            return mAggregatedPartialWakelockTimer;
7337        }
7338
7339        public DualTimer createBluetoothScanTimerLocked() {
7340            if (mBluetoothScanTimer == null) {
7341                mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
7342                        mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
7343                        mOnBatteryBackgroundTimeBase);
7344            }
7345            return mBluetoothScanTimer;
7346        }
7347
7348        public DualTimer createBluetoothUnoptimizedScanTimerLocked() {
7349            if (mBluetoothUnoptimizedScanTimer == null) {
7350                mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
7351                        BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
7352                        mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
7353            }
7354            return mBluetoothUnoptimizedScanTimer;
7355        }
7356
7357        public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs,
7358                boolean isUnoptimized) {
7359            createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
7360            if (isUnoptimized) {
7361                createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
7362            }
7363        }
7364
7365        public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
7366            if (mBluetoothScanTimer != null) {
7367                mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
7368            }
7369            if (isUnoptimized && mBluetoothUnoptimizedScanTimer != null) {
7370                mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs);
7371            }
7372        }
7373
7374        public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
7375            if (mBluetoothScanTimer != null) {
7376                mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
7377            }
7378            if (mBluetoothUnoptimizedScanTimer != null) {
7379                mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
7380            }
7381        }
7382
7383        public Counter createBluetoothScanResultCounterLocked() {
7384            if (mBluetoothScanResultCounter == null) {
7385                mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase);
7386            }
7387            return mBluetoothScanResultCounter;
7388        }
7389
7390        public Counter createBluetoothScanResultBgCounterLocked() {
7391            if (mBluetoothScanResultBgCounter == null) {
7392                mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase);
7393            }
7394            return mBluetoothScanResultBgCounter;
7395        }
7396
7397        public void noteBluetoothScanResultsLocked(int numNewResults) {
7398            createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
7399            // Uses background timebase, so the count will only be incremented if uid in background.
7400            createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults);
7401        }
7402
7403        @Override
7404        public void noteActivityResumedLocked(long elapsedRealtimeMs) {
7405            // We always start, since we want multiple foreground PIDs to nest
7406            createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
7407        }
7408
7409        @Override
7410        public void noteActivityPausedLocked(long elapsedRealtimeMs) {
7411            if (mForegroundActivityTimer != null) {
7412                mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
7413            }
7414        }
7415
7416        public void noteForegroundServiceResumedLocked(long elapsedRealtimeMs) {
7417            createForegroundServiceTimerLocked().startRunningLocked(elapsedRealtimeMs);
7418        }
7419
7420        public void noteForegroundServicePausedLocked(long elapsedRealtimeMs) {
7421            if (mForegroundServiceTimer != null) {
7422                mForegroundServiceTimer.stopRunningLocked(elapsedRealtimeMs);
7423            }
7424        }
7425
7426        public BatchTimer createVibratorOnTimerLocked() {
7427            if (mVibratorOnTimer == null) {
7428                mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
7429                        mBsi.mOnBatteryTimeBase);
7430            }
7431            return mVibratorOnTimer;
7432        }
7433
7434        public void noteVibratorOnLocked(long durationMillis) {
7435            createVibratorOnTimerLocked().addDuration(mBsi, durationMillis);
7436        }
7437
7438        public void noteVibratorOffLocked() {
7439            if (mVibratorOnTimer != null) {
7440                mVibratorOnTimer.abortLastDuration(mBsi);
7441            }
7442        }
7443
7444        @Override
7445        public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
7446            if (mWifiRunningTimer == null) {
7447                return 0;
7448            }
7449            return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7450        }
7451
7452        @Override
7453        public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
7454            if (mFullWifiLockTimer == null) {
7455                return 0;
7456            }
7457            return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7458        }
7459
7460        @Override
7461        public long getWifiScanTime(long elapsedRealtimeUs, int which) {
7462            if (mWifiScanTimer == null) {
7463                return 0;
7464            }
7465            return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7466        }
7467
7468        @Override
7469        public int getWifiScanCount(int which) {
7470            if (mWifiScanTimer == null) {
7471                return 0;
7472            }
7473            return mWifiScanTimer.getCountLocked(which);
7474        }
7475
7476        @Override
7477        public Timer getWifiScanTimer() {
7478            return mWifiScanTimer;
7479        }
7480
7481        @Override
7482        public int getWifiScanBackgroundCount(int which) {
7483            if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
7484                return 0;
7485            }
7486            return mWifiScanTimer.getSubTimer().getCountLocked(which);
7487        }
7488
7489        @Override
7490        public long getWifiScanActualTime(final long elapsedRealtimeUs) {
7491            if (mWifiScanTimer == null) {
7492                return 0;
7493            }
7494            final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
7495            return mWifiScanTimer.getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
7496        }
7497
7498        @Override
7499        public long getWifiScanBackgroundTime(final long elapsedRealtimeUs) {
7500            if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
7501                return 0;
7502            }
7503            final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
7504            return mWifiScanTimer.getSubTimer().getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
7505        }
7506
7507        @Override
7508        public Timer getWifiScanBackgroundTimer() {
7509            if (mWifiScanTimer == null) {
7510                return null;
7511            }
7512            return mWifiScanTimer.getSubTimer();
7513        }
7514
7515        @Override
7516        public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
7517            if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
7518            if (mWifiBatchedScanTimer[csphBin] == null) {
7519                return 0;
7520            }
7521            return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
7522        }
7523
7524        @Override
7525        public int getWifiBatchedScanCount(int csphBin, int which) {
7526            if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
7527            if (mWifiBatchedScanTimer[csphBin] == null) {
7528                return 0;
7529            }
7530            return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
7531        }
7532
7533        @Override
7534        public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
7535            if (mWifiMulticastTimer == null) {
7536                return 0;
7537            }
7538            return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
7539        }
7540
7541        @Override
7542        public Timer getAudioTurnedOnTimer() {
7543            return mAudioTurnedOnTimer;
7544        }
7545
7546        @Override
7547        public Timer getVideoTurnedOnTimer() {
7548            return mVideoTurnedOnTimer;
7549        }
7550
7551        @Override
7552        public Timer getFlashlightTurnedOnTimer() {
7553            return mFlashlightTurnedOnTimer;
7554        }
7555
7556        @Override
7557        public Timer getCameraTurnedOnTimer() {
7558            return mCameraTurnedOnTimer;
7559        }
7560
7561        @Override
7562        public Timer getForegroundActivityTimer() {
7563            return mForegroundActivityTimer;
7564        }
7565
7566        @Override
7567        public Timer getForegroundServiceTimer() {
7568            return mForegroundServiceTimer;
7569        }
7570
7571        @Override
7572        public Timer getBluetoothScanTimer() {
7573            return mBluetoothScanTimer;
7574        }
7575
7576        @Override
7577        public Timer getBluetoothScanBackgroundTimer() {
7578            if (mBluetoothScanTimer == null) {
7579                return null;
7580            }
7581            return mBluetoothScanTimer.getSubTimer();
7582        }
7583
7584        @Override
7585        public Timer getBluetoothUnoptimizedScanTimer() {
7586            return mBluetoothUnoptimizedScanTimer;
7587        }
7588
7589        @Override
7590        public Timer getBluetoothUnoptimizedScanBackgroundTimer() {
7591            if (mBluetoothUnoptimizedScanTimer == null) {
7592                return null;
7593            }
7594            return mBluetoothUnoptimizedScanTimer.getSubTimer();
7595        }
7596
7597        @Override
7598        public Counter getBluetoothScanResultCounter() {
7599            return mBluetoothScanResultCounter;
7600        }
7601
7602        @Override
7603        public Counter getBluetoothScanResultBgCounter() {
7604            return mBluetoothScanResultBgCounter;
7605        }
7606
7607        void makeProcessState(int i, Parcel in) {
7608            if (i < 0 || i >= NUM_PROCESS_STATE) return;
7609
7610            if (in == null) {
7611                mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
7612                        mBsi.mOnBatteryTimeBase);
7613            } else {
7614                mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
7615                        mBsi.mOnBatteryTimeBase, in);
7616            }
7617        }
7618
7619        @Override
7620        public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
7621            if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
7622            if (mProcessStateTimer[state] == null) {
7623                return 0;
7624            }
7625            return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
7626        }
7627
7628        @Override
7629        public Timer getProcessStateTimer(int state) {
7630            if (state < 0 || state >= NUM_PROCESS_STATE) return null;
7631            return mProcessStateTimer[state];
7632        }
7633
7634        @Override
7635        public Timer getVibratorOnTimer() {
7636            return mVibratorOnTimer;
7637        }
7638
7639        @Override
7640        public void noteUserActivityLocked(int type) {
7641            if (mUserActivityCounters == null) {
7642                initUserActivityLocked();
7643            }
7644            if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
7645                mUserActivityCounters[type].stepAtomic();
7646            } else {
7647                Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
7648                        new Throwable());
7649            }
7650        }
7651
7652        @Override
7653        public boolean hasUserActivity() {
7654            return mUserActivityCounters != null;
7655        }
7656
7657        @Override
7658        public int getUserActivityCount(int type, int which) {
7659            if (mUserActivityCounters == null) {
7660                return 0;
7661            }
7662            return mUserActivityCounters[type].getCountLocked(which);
7663        }
7664
7665        void makeWifiBatchedScanBin(int i, Parcel in) {
7666            if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
7667
7668            ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
7669            if (collected == null) {
7670                collected = new ArrayList<StopwatchTimer>();
7671                mBsi.mWifiBatchedScanTimers.put(i, collected);
7672            }
7673            if (in == null) {
7674                mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
7675                        collected, mBsi.mOnBatteryTimeBase);
7676            } else {
7677                mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
7678                        collected, mBsi.mOnBatteryTimeBase, in);
7679            }
7680        }
7681
7682
7683        void initUserActivityLocked() {
7684            mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
7685            for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
7686                mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
7687            }
7688        }
7689
7690        void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
7691            if (mNetworkByteActivityCounters == null) {
7692                initNetworkActivityLocked();
7693            }
7694            if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
7695                mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
7696                mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
7697            } else {
7698                Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
7699                        new Throwable());
7700            }
7701        }
7702
7703        void noteMobileRadioActiveTimeLocked(long batteryUptime) {
7704            if (mNetworkByteActivityCounters == null) {
7705                initNetworkActivityLocked();
7706            }
7707            mMobileRadioActiveTime.addCountLocked(batteryUptime);
7708            mMobileRadioActiveCount.addCountLocked(1);
7709        }
7710
7711        @Override
7712        public boolean hasNetworkActivity() {
7713            return mNetworkByteActivityCounters != null;
7714        }
7715
7716        @Override
7717        public long getNetworkActivityBytes(int type, int which) {
7718            if (mNetworkByteActivityCounters != null && type >= 0
7719                    && type < mNetworkByteActivityCounters.length) {
7720                return mNetworkByteActivityCounters[type].getCountLocked(which);
7721            } else {
7722                return 0;
7723            }
7724        }
7725
7726        @Override
7727        public long getNetworkActivityPackets(int type, int which) {
7728            if (mNetworkPacketActivityCounters != null && type >= 0
7729                    && type < mNetworkPacketActivityCounters.length) {
7730                return mNetworkPacketActivityCounters[type].getCountLocked(which);
7731            } else {
7732                return 0;
7733            }
7734        }
7735
7736        @Override
7737        public long getMobileRadioActiveTime(int which) {
7738            return mMobileRadioActiveTime != null
7739                    ? mMobileRadioActiveTime.getCountLocked(which) : 0;
7740        }
7741
7742        @Override
7743        public int getMobileRadioActiveCount(int which) {
7744            return mMobileRadioActiveCount != null
7745                    ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
7746        }
7747
7748        @Override
7749        public long getUserCpuTimeUs(int which) {
7750            return mUserCpuTime.getCountLocked(which);
7751        }
7752
7753        @Override
7754        public long getSystemCpuTimeUs(int which) {
7755            return mSystemCpuTime.getCountLocked(which);
7756        }
7757
7758        @Override
7759        public long getTimeAtCpuSpeed(int cluster, int step, int which) {
7760            if (mCpuClusterSpeedTimesUs != null) {
7761                if (cluster >= 0 && cluster < mCpuClusterSpeedTimesUs.length) {
7762                    final LongSamplingCounter[] cpuSpeedTimesUs = mCpuClusterSpeedTimesUs[cluster];
7763                    if (cpuSpeedTimesUs != null) {
7764                        if (step >= 0 && step < cpuSpeedTimesUs.length) {
7765                            final LongSamplingCounter c = cpuSpeedTimesUs[step];
7766                            if (c != null) {
7767                                return c.getCountLocked(which);
7768                            }
7769                        }
7770                    }
7771                }
7772            }
7773            return 0;
7774        }
7775
7776        public void noteMobileRadioApWakeupLocked() {
7777            if (mMobileRadioApWakeupCount == null) {
7778                mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7779            }
7780            mMobileRadioApWakeupCount.addCountLocked(1);
7781        }
7782
7783        @Override
7784        public long getMobileRadioApWakeupCount(int which) {
7785            if (mMobileRadioApWakeupCount != null) {
7786                return mMobileRadioApWakeupCount.getCountLocked(which);
7787            }
7788            return 0;
7789        }
7790
7791        public void noteWifiRadioApWakeupLocked() {
7792            if (mWifiRadioApWakeupCount == null) {
7793                mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7794            }
7795            mWifiRadioApWakeupCount.addCountLocked(1);
7796        }
7797
7798        @Override
7799        public long getWifiRadioApWakeupCount(int which) {
7800            if (mWifiRadioApWakeupCount != null) {
7801                return mWifiRadioApWakeupCount.getCountLocked(which);
7802            }
7803            return 0;
7804        }
7805
7806        @Override
7807        public void getDeferredJobsCheckinLineLocked(StringBuilder sb, int which) {
7808            sb.setLength(0);
7809            final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
7810            if (deferredEventCount == 0) {
7811                return;
7812            }
7813            final int deferredCount = mJobsDeferredCount.getCountLocked(which);
7814            final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
7815            sb.append(deferredEventCount); sb.append(',');
7816            sb.append(deferredCount); sb.append(',');
7817            sb.append(totalLatency);
7818            for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
7819                if (mJobsFreshnessBuckets[i] == null) {
7820                    sb.append(",0");
7821                } else {
7822                    sb.append(",");
7823                    sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
7824                }
7825            }
7826        }
7827
7828        @Override
7829        public void getDeferredJobsLineLocked(StringBuilder sb, int which) {
7830            sb.setLength(0);
7831            final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
7832            if (deferredEventCount == 0) {
7833                return;
7834            }
7835            final int deferredCount = mJobsDeferredCount.getCountLocked(which);
7836            final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
7837            sb.append("times="); sb.append(deferredEventCount); sb.append(", ");
7838            sb.append("count="); sb.append(deferredCount); sb.append(", ");
7839            sb.append("totalLatencyMs="); sb.append(totalLatency); sb.append(", ");
7840            for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
7841                sb.append("<"); sb.append(JOB_FRESHNESS_BUCKETS[i]); sb.append("ms=");
7842                if (mJobsFreshnessBuckets[i] == null) {
7843                    sb.append("0");
7844                } else {
7845                    sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
7846                }
7847                sb.append(" ");
7848            }
7849        }
7850
7851        void initNetworkActivityLocked() {
7852            mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
7853            mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
7854            for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7855                mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7856                mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7857            }
7858            mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7859            mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
7860        }
7861
7862        /**
7863         * Clear all stats for this uid.  Returns true if the uid is completely
7864         * inactive so can be dropped.
7865         */
7866        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
7867        public boolean reset(long uptime, long realtime) {
7868            boolean active = false;
7869
7870            mOnBatteryBackgroundTimeBase.init(uptime, realtime);
7871            mOnBatteryScreenOffBackgroundTimeBase.init(uptime, realtime);
7872
7873            if (mWifiRunningTimer != null) {
7874                active |= !mWifiRunningTimer.reset(false);
7875                active |= mWifiRunning;
7876            }
7877            if (mFullWifiLockTimer != null) {
7878                active |= !mFullWifiLockTimer.reset(false);
7879                active |= mFullWifiLockOut;
7880            }
7881            if (mWifiScanTimer != null) {
7882                active |= !mWifiScanTimer.reset(false);
7883                active |= mWifiScanStarted;
7884            }
7885            if (mWifiBatchedScanTimer != null) {
7886                for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
7887                    if (mWifiBatchedScanTimer[i] != null) {
7888                        active |= !mWifiBatchedScanTimer[i].reset(false);
7889                    }
7890                }
7891                active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
7892            }
7893            if (mWifiMulticastTimer != null) {
7894                active |= !mWifiMulticastTimer.reset(false);
7895                active |= mWifiMulticastEnabled;
7896            }
7897
7898            active |= !resetTimerIfNotNull(mAudioTurnedOnTimer, false);
7899            active |= !resetTimerIfNotNull(mVideoTurnedOnTimer, false);
7900            active |= !resetTimerIfNotNull(mFlashlightTurnedOnTimer, false);
7901            active |= !resetTimerIfNotNull(mCameraTurnedOnTimer, false);
7902            active |= !resetTimerIfNotNull(mForegroundActivityTimer, false);
7903            active |= !resetTimerIfNotNull(mForegroundServiceTimer, false);
7904            active |= !resetTimerIfNotNull(mAggregatedPartialWakelockTimer, false);
7905            active |= !resetTimerIfNotNull(mBluetoothScanTimer, false);
7906            active |= !resetTimerIfNotNull(mBluetoothUnoptimizedScanTimer, false);
7907            if (mBluetoothScanResultCounter != null) {
7908                mBluetoothScanResultCounter.reset(false);
7909            }
7910            if (mBluetoothScanResultBgCounter != null) {
7911                mBluetoothScanResultBgCounter.reset(false);
7912            }
7913
7914            if (mProcessStateTimer != null) {
7915                for (int i = 0; i < NUM_PROCESS_STATE; i++) {
7916                    if (mProcessStateTimer[i] != null) {
7917                        active |= !mProcessStateTimer[i].reset(false);
7918                    }
7919                }
7920                active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
7921            }
7922            if (mVibratorOnTimer != null) {
7923                if (mVibratorOnTimer.reset(false)) {
7924                    mVibratorOnTimer.detach();
7925                    mVibratorOnTimer = null;
7926                } else {
7927                    active = true;
7928                }
7929            }
7930
7931            if (mUserActivityCounters != null) {
7932                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
7933                    mUserActivityCounters[i].reset(false);
7934                }
7935            }
7936
7937            if (mNetworkByteActivityCounters != null) {
7938                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7939                    mNetworkByteActivityCounters[i].reset(false);
7940                    mNetworkPacketActivityCounters[i].reset(false);
7941                }
7942                mMobileRadioActiveTime.reset(false);
7943                mMobileRadioActiveCount.reset(false);
7944            }
7945
7946            if (mWifiControllerActivity != null) {
7947                mWifiControllerActivity.reset(false);
7948            }
7949
7950            if (mBluetoothControllerActivity != null) {
7951                mBluetoothControllerActivity.reset(false);
7952            }
7953
7954            if (mModemControllerActivity != null) {
7955                mModemControllerActivity.reset(false);
7956            }
7957
7958            mUserCpuTime.reset(false);
7959            mSystemCpuTime.reset(false);
7960
7961            if (mCpuClusterSpeedTimesUs != null) {
7962                for (LongSamplingCounter[] speeds : mCpuClusterSpeedTimesUs) {
7963                    if (speeds != null) {
7964                        for (LongSamplingCounter speed : speeds) {
7965                            if (speed != null) {
7966                                speed.reset(false);
7967                            }
7968                        }
7969                    }
7970                }
7971            }
7972
7973            if (mCpuFreqTimeMs != null) {
7974                mCpuFreqTimeMs.reset(false);
7975            }
7976            if (mScreenOffCpuFreqTimeMs != null) {
7977                mScreenOffCpuFreqTimeMs.reset(false);
7978            }
7979
7980            mCpuActiveTimeMs.reset(false);
7981            mCpuClusterTimesMs.reset(false);
7982
7983            if (mProcStateTimeMs != null) {
7984                for (LongSamplingCounterArray counters : mProcStateTimeMs) {
7985                    if (counters != null) {
7986                        counters.reset(false);
7987                    }
7988                }
7989            }
7990            if (mProcStateScreenOffTimeMs != null) {
7991                for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
7992                    if (counters != null) {
7993                        counters.reset(false);
7994                    }
7995                }
7996            }
7997
7998            resetLongCounterIfNotNull(mMobileRadioApWakeupCount, false);
7999            resetLongCounterIfNotNull(mWifiRadioApWakeupCount, false);
8000
8001            final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
8002            for (int iw=wakeStats.size()-1; iw>=0; iw--) {
8003                Wakelock wl = wakeStats.valueAt(iw);
8004                if (wl.reset()) {
8005                    wakeStats.removeAt(iw);
8006                } else {
8007                    active = true;
8008                }
8009            }
8010            mWakelockStats.cleanup();
8011            final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
8012            for (int is=syncStats.size()-1; is>=0; is--) {
8013                DualTimer timer = syncStats.valueAt(is);
8014                if (timer.reset(false)) {
8015                    syncStats.removeAt(is);
8016                    timer.detach();
8017                } else {
8018                    active = true;
8019                }
8020            }
8021            mSyncStats.cleanup();
8022            final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
8023            for (int ij=jobStats.size()-1; ij>=0; ij--) {
8024                DualTimer timer = jobStats.valueAt(ij);
8025                if (timer.reset(false)) {
8026                    jobStats.removeAt(ij);
8027                    timer.detach();
8028                } else {
8029                    active = true;
8030                }
8031            }
8032            mJobStats.cleanup();
8033            mJobCompletions.clear();
8034
8035            mJobsDeferredEventCount.reset(false);
8036            mJobsDeferredCount.reset(false);
8037            mJobsFreshnessTimeMs.reset(false);
8038            for (int ij = 0; ij < JOB_FRESHNESS_BUCKETS.length; ij++) {
8039                if (mJobsFreshnessBuckets[ij] != null) {
8040                    mJobsFreshnessBuckets[ij].reset(false);
8041                }
8042            }
8043
8044            for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
8045                Sensor s = mSensorStats.valueAt(ise);
8046                if (s.reset()) {
8047                    mSensorStats.removeAt(ise);
8048                } else {
8049                    active = true;
8050                }
8051            }
8052
8053            for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
8054                Proc proc = mProcessStats.valueAt(ip);
8055                proc.detach();
8056            }
8057            mProcessStats.clear();
8058            if (mPids.size() > 0) {
8059                for (int i=mPids.size()-1; i>=0; i--) {
8060                    Pid pid = mPids.valueAt(i);
8061                    if (pid.mWakeNesting > 0) {
8062                        active = true;
8063                    } else {
8064                        mPids.removeAt(i);
8065                    }
8066                }
8067            }
8068            if (mPackageStats.size() > 0) {
8069                Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator();
8070                while (it.hasNext()) {
8071                    Map.Entry<String, Pkg> pkgEntry = it.next();
8072                    Pkg p = pkgEntry.getValue();
8073                    p.detach();
8074                    if (p.mServiceStats.size() > 0) {
8075                        Iterator<Map.Entry<String, Pkg.Serv>> it2
8076                                = p.mServiceStats.entrySet().iterator();
8077                        while (it2.hasNext()) {
8078                            Map.Entry<String, Pkg.Serv> servEntry = it2.next();
8079                            servEntry.getValue().detach();
8080                        }
8081                    }
8082                }
8083                mPackageStats.clear();
8084            }
8085
8086            mLastStepUserTime = mLastStepSystemTime = 0;
8087            mCurStepUserTime = mCurStepSystemTime = 0;
8088
8089            if (!active) {
8090                if (mWifiRunningTimer != null) {
8091                    mWifiRunningTimer.detach();
8092                }
8093                if (mFullWifiLockTimer != null) {
8094                    mFullWifiLockTimer.detach();
8095                }
8096                if (mWifiScanTimer != null) {
8097                    mWifiScanTimer.detach();
8098                }
8099                for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8100                    if (mWifiBatchedScanTimer[i] != null) {
8101                        mWifiBatchedScanTimer[i].detach();
8102                    }
8103                }
8104                if (mWifiMulticastTimer != null) {
8105                    mWifiMulticastTimer.detach();
8106                }
8107                if (mAudioTurnedOnTimer != null) {
8108                    mAudioTurnedOnTimer.detach();
8109                    mAudioTurnedOnTimer = null;
8110                }
8111                if (mVideoTurnedOnTimer != null) {
8112                    mVideoTurnedOnTimer.detach();
8113                    mVideoTurnedOnTimer = null;
8114                }
8115                if (mFlashlightTurnedOnTimer != null) {
8116                    mFlashlightTurnedOnTimer.detach();
8117                    mFlashlightTurnedOnTimer = null;
8118                }
8119                if (mCameraTurnedOnTimer != null) {
8120                    mCameraTurnedOnTimer.detach();
8121                    mCameraTurnedOnTimer = null;
8122                }
8123                if (mForegroundActivityTimer != null) {
8124                    mForegroundActivityTimer.detach();
8125                    mForegroundActivityTimer = null;
8126                }
8127                if (mForegroundServiceTimer != null) {
8128                    mForegroundServiceTimer.detach();
8129                    mForegroundServiceTimer = null;
8130                }
8131                if (mAggregatedPartialWakelockTimer != null) {
8132                    mAggregatedPartialWakelockTimer.detach();
8133                    mAggregatedPartialWakelockTimer = null;
8134                }
8135                if (mBluetoothScanTimer != null) {
8136                    mBluetoothScanTimer.detach();
8137                    mBluetoothScanTimer = null;
8138                }
8139                if (mBluetoothUnoptimizedScanTimer != null) {
8140                    mBluetoothUnoptimizedScanTimer.detach();
8141                    mBluetoothUnoptimizedScanTimer = null;
8142                }
8143                if (mBluetoothScanResultCounter != null) {
8144                    mBluetoothScanResultCounter.detach();
8145                    mBluetoothScanResultCounter = null;
8146                }
8147                if (mBluetoothScanResultBgCounter != null) {
8148                    mBluetoothScanResultBgCounter.detach();
8149                    mBluetoothScanResultBgCounter = null;
8150                }
8151                if (mUserActivityCounters != null) {
8152                    for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8153                        mUserActivityCounters[i].detach();
8154                    }
8155                }
8156                if (mNetworkByteActivityCounters != null) {
8157                    for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8158                        mNetworkByteActivityCounters[i].detach();
8159                        mNetworkPacketActivityCounters[i].detach();
8160                    }
8161                }
8162
8163                if (mWifiControllerActivity != null) {
8164                    mWifiControllerActivity.detach();
8165                }
8166
8167                if (mBluetoothControllerActivity != null) {
8168                    mBluetoothControllerActivity.detach();
8169                }
8170
8171                if (mModemControllerActivity != null) {
8172                    mModemControllerActivity.detach();
8173                }
8174
8175                mPids.clear();
8176
8177                mUserCpuTime.detach();
8178                mSystemCpuTime.detach();
8179
8180                if (mCpuClusterSpeedTimesUs != null) {
8181                    for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) {
8182                        if (cpuSpeeds != null) {
8183                            for (LongSamplingCounter c : cpuSpeeds) {
8184                                if (c != null) {
8185                                    c.detach();
8186                                }
8187                            }
8188                        }
8189                    }
8190                }
8191
8192                if (mCpuFreqTimeMs != null) {
8193                    mCpuFreqTimeMs.detach();
8194                }
8195                if (mScreenOffCpuFreqTimeMs != null) {
8196                    mScreenOffCpuFreqTimeMs.detach();
8197                }
8198                mCpuActiveTimeMs.detach();
8199                mCpuClusterTimesMs.detach();
8200
8201                if (mProcStateTimeMs != null) {
8202                    for (LongSamplingCounterArray counters : mProcStateTimeMs) {
8203                        if (counters != null) {
8204                            counters.detach();
8205                        }
8206                    }
8207                }
8208                if (mProcStateScreenOffTimeMs != null) {
8209                    for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
8210                        if (counters != null) {
8211                            counters.detach();
8212                        }
8213                    }
8214                }
8215                detachLongCounterIfNotNull(mMobileRadioApWakeupCount);
8216                detachLongCounterIfNotNull(mWifiRadioApWakeupCount);
8217            }
8218
8219            return !active;
8220        }
8221
8222        void writeJobCompletionsToParcelLocked(Parcel out) {
8223            int NJC = mJobCompletions.size();
8224            out.writeInt(NJC);
8225            for (int ijc=0; ijc<NJC; ijc++) {
8226                out.writeString(mJobCompletions.keyAt(ijc));
8227                SparseIntArray types = mJobCompletions.valueAt(ijc);
8228                int NT = types.size();
8229                out.writeInt(NT);
8230                for (int it=0; it<NT; it++) {
8231                    out.writeInt(types.keyAt(it));
8232                    out.writeInt(types.valueAt(it));
8233                }
8234            }
8235        }
8236
8237        void writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
8238            mOnBatteryBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
8239            mOnBatteryScreenOffBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
8240
8241            final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
8242            int NW = wakeStats.size();
8243            out.writeInt(NW);
8244            for (int iw=0; iw<NW; iw++) {
8245                out.writeString(wakeStats.keyAt(iw));
8246                Uid.Wakelock wakelock = wakeStats.valueAt(iw);
8247                wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
8248            }
8249
8250            final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
8251            int NS = syncStats.size();
8252            out.writeInt(NS);
8253            for (int is=0; is<NS; is++) {
8254                out.writeString(syncStats.keyAt(is));
8255                DualTimer timer = syncStats.valueAt(is);
8256                Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
8257            }
8258
8259            final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
8260            int NJ = jobStats.size();
8261            out.writeInt(NJ);
8262            for (int ij=0; ij<NJ; ij++) {
8263                out.writeString(jobStats.keyAt(ij));
8264                DualTimer timer = jobStats.valueAt(ij);
8265                Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
8266            }
8267
8268            writeJobCompletionsToParcelLocked(out);
8269
8270            mJobsDeferredEventCount.writeToParcel(out);
8271            mJobsDeferredCount.writeToParcel(out);
8272            mJobsFreshnessTimeMs.writeToParcel(out);
8273            for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8274                Counter.writeCounterToParcel(out, mJobsFreshnessBuckets[i]);
8275            }
8276
8277            int NSE = mSensorStats.size();
8278            out.writeInt(NSE);
8279            for (int ise=0; ise<NSE; ise++) {
8280                out.writeInt(mSensorStats.keyAt(ise));
8281                Uid.Sensor sensor = mSensorStats.valueAt(ise);
8282                sensor.writeToParcelLocked(out, elapsedRealtimeUs);
8283            }
8284
8285            int NP = mProcessStats.size();
8286            out.writeInt(NP);
8287            for (int ip=0; ip<NP; ip++) {
8288                out.writeString(mProcessStats.keyAt(ip));
8289                Uid.Proc proc = mProcessStats.valueAt(ip);
8290                proc.writeToParcelLocked(out);
8291            }
8292
8293            out.writeInt(mPackageStats.size());
8294            for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
8295                out.writeString(pkgEntry.getKey());
8296                Uid.Pkg pkg = pkgEntry.getValue();
8297                pkg.writeToParcelLocked(out);
8298            }
8299
8300            if (mWifiRunningTimer != null) {
8301                out.writeInt(1);
8302                mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
8303            } else {
8304                out.writeInt(0);
8305            }
8306            if (mFullWifiLockTimer != null) {
8307                out.writeInt(1);
8308                mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
8309            } else {
8310                out.writeInt(0);
8311            }
8312            if (mWifiScanTimer != null) {
8313                out.writeInt(1);
8314                mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
8315            } else {
8316                out.writeInt(0);
8317            }
8318            for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8319                if (mWifiBatchedScanTimer[i] != null) {
8320                    out.writeInt(1);
8321                    mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
8322                } else {
8323                    out.writeInt(0);
8324                }
8325            }
8326            if (mWifiMulticastTimer != null) {
8327                out.writeInt(1);
8328                mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
8329            } else {
8330                out.writeInt(0);
8331            }
8332
8333            if (mAudioTurnedOnTimer != null) {
8334                out.writeInt(1);
8335                mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8336            } else {
8337                out.writeInt(0);
8338            }
8339            if (mVideoTurnedOnTimer != null) {
8340                out.writeInt(1);
8341                mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8342            } else {
8343                out.writeInt(0);
8344            }
8345            if (mFlashlightTurnedOnTimer != null) {
8346                out.writeInt(1);
8347                mFlashlightTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8348            } else {
8349                out.writeInt(0);
8350            }
8351            if (mCameraTurnedOnTimer != null) {
8352                out.writeInt(1);
8353                mCameraTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
8354            } else {
8355                out.writeInt(0);
8356            }
8357            if (mForegroundActivityTimer != null) {
8358                out.writeInt(1);
8359                mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
8360            } else {
8361                out.writeInt(0);
8362            }
8363            if (mForegroundServiceTimer != null) {
8364                out.writeInt(1);
8365                mForegroundServiceTimer.writeToParcel(out, elapsedRealtimeUs);
8366            } else {
8367                out.writeInt(0);
8368            }
8369            if (mAggregatedPartialWakelockTimer != null) {
8370                out.writeInt(1);
8371                mAggregatedPartialWakelockTimer.writeToParcel(out, elapsedRealtimeUs);
8372            } else {
8373                out.writeInt(0);
8374            }
8375            if (mBluetoothScanTimer != null) {
8376                out.writeInt(1);
8377                mBluetoothScanTimer.writeToParcel(out, elapsedRealtimeUs);
8378            } else {
8379                out.writeInt(0);
8380            }
8381            if (mBluetoothUnoptimizedScanTimer != null) {
8382                out.writeInt(1);
8383                mBluetoothUnoptimizedScanTimer.writeToParcel(out, elapsedRealtimeUs);
8384            } else {
8385                out.writeInt(0);
8386            }
8387            if (mBluetoothScanResultCounter != null) {
8388                out.writeInt(1);
8389                mBluetoothScanResultCounter.writeToParcel(out);
8390            } else {
8391                out.writeInt(0);
8392            }
8393            if (mBluetoothScanResultBgCounter != null) {
8394                out.writeInt(1);
8395                mBluetoothScanResultBgCounter.writeToParcel(out);
8396            } else {
8397                out.writeInt(0);
8398            }
8399            for (int i = 0; i < NUM_PROCESS_STATE; i++) {
8400                if (mProcessStateTimer[i] != null) {
8401                    out.writeInt(1);
8402                    mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
8403                } else {
8404                    out.writeInt(0);
8405                }
8406            }
8407            if (mVibratorOnTimer != null) {
8408                out.writeInt(1);
8409                mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
8410            } else {
8411                out.writeInt(0);
8412            }
8413            if (mUserActivityCounters != null) {
8414                out.writeInt(1);
8415                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8416                    mUserActivityCounters[i].writeToParcel(out);
8417                }
8418            } else {
8419                out.writeInt(0);
8420            }
8421            if (mNetworkByteActivityCounters != null) {
8422                out.writeInt(1);
8423                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8424                    mNetworkByteActivityCounters[i].writeToParcel(out);
8425                    mNetworkPacketActivityCounters[i].writeToParcel(out);
8426                }
8427                mMobileRadioActiveTime.writeToParcel(out);
8428                mMobileRadioActiveCount.writeToParcel(out);
8429            } else {
8430                out.writeInt(0);
8431            }
8432
8433            if (mWifiControllerActivity != null) {
8434                out.writeInt(1);
8435                mWifiControllerActivity.writeToParcel(out, 0);
8436            } else {
8437                out.writeInt(0);
8438            }
8439
8440            if (mBluetoothControllerActivity != null) {
8441                out.writeInt(1);
8442                mBluetoothControllerActivity.writeToParcel(out, 0);
8443            } else {
8444                out.writeInt(0);
8445            }
8446
8447            if (mModemControllerActivity != null) {
8448                out.writeInt(1);
8449                mModemControllerActivity.writeToParcel(out, 0);
8450            } else {
8451                out.writeInt(0);
8452            }
8453
8454            mUserCpuTime.writeToParcel(out);
8455            mSystemCpuTime.writeToParcel(out);
8456
8457            if (mCpuClusterSpeedTimesUs != null) {
8458                out.writeInt(1);
8459                out.writeInt(mCpuClusterSpeedTimesUs.length);
8460                for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) {
8461                    if (cpuSpeeds != null) {
8462                        out.writeInt(1);
8463                        out.writeInt(cpuSpeeds.length);
8464                        for (LongSamplingCounter c : cpuSpeeds) {
8465                            if (c != null) {
8466                                out.writeInt(1);
8467                                c.writeToParcel(out);
8468                            } else {
8469                                out.writeInt(0);
8470                            }
8471                        }
8472                    } else {
8473                        out.writeInt(0);
8474                    }
8475                }
8476            } else {
8477                out.writeInt(0);
8478            }
8479
8480            LongSamplingCounterArray.writeToParcel(out, mCpuFreqTimeMs);
8481            LongSamplingCounterArray.writeToParcel(out, mScreenOffCpuFreqTimeMs);
8482
8483            mCpuActiveTimeMs.writeToParcel(out);
8484            mCpuClusterTimesMs.writeToParcel(out);
8485
8486            if (mProcStateTimeMs != null) {
8487                out.writeInt(mProcStateTimeMs.length);
8488                for (LongSamplingCounterArray counters : mProcStateTimeMs) {
8489                    LongSamplingCounterArray.writeToParcel(out, counters);
8490                }
8491            } else {
8492                out.writeInt(0);
8493            }
8494            if (mProcStateScreenOffTimeMs != null) {
8495                out.writeInt(mProcStateScreenOffTimeMs.length);
8496                for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
8497                    LongSamplingCounterArray.writeToParcel(out, counters);
8498                }
8499            } else {
8500                out.writeInt(0);
8501            }
8502
8503            if (mMobileRadioApWakeupCount != null) {
8504                out.writeInt(1);
8505                mMobileRadioApWakeupCount.writeToParcel(out);
8506            } else {
8507                out.writeInt(0);
8508            }
8509
8510            if (mWifiRadioApWakeupCount != null) {
8511                out.writeInt(1);
8512                mWifiRadioApWakeupCount.writeToParcel(out);
8513            } else {
8514                out.writeInt(0);
8515            }
8516        }
8517
8518        void readJobCompletionsFromParcelLocked(Parcel in) {
8519            int numJobCompletions = in.readInt();
8520            mJobCompletions.clear();
8521            for (int j = 0; j < numJobCompletions; j++) {
8522                String jobName = in.readString();
8523                int numTypes = in.readInt();
8524                if (numTypes > 0) {
8525                    SparseIntArray types = new SparseIntArray();
8526                    for (int k = 0; k < numTypes; k++) {
8527                        int type = in.readInt();
8528                        int count = in.readInt();
8529                        types.put(type, count);
8530                    }
8531                    mJobCompletions.put(jobName, types);
8532                }
8533            }
8534        }
8535
8536        void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
8537            mOnBatteryBackgroundTimeBase.readFromParcel(in);
8538            mOnBatteryScreenOffBackgroundTimeBase.readFromParcel(in);
8539
8540            int numWakelocks = in.readInt();
8541            mWakelockStats.clear();
8542            for (int j = 0; j < numWakelocks; j++) {
8543                String wakelockName = in.readString();
8544                Uid.Wakelock wakelock = new Wakelock(mBsi, this);
8545                wakelock.readFromParcelLocked(
8546                        timeBase, screenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase, in);
8547                mWakelockStats.add(wakelockName, wakelock);
8548            }
8549
8550            int numSyncs = in.readInt();
8551            mSyncStats.clear();
8552            for (int j = 0; j < numSyncs; j++) {
8553                String syncName = in.readString();
8554                if (in.readInt() != 0) {
8555                    mSyncStats.add(syncName, new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
8556                            mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
8557                }
8558            }
8559
8560            int numJobs = in.readInt();
8561            mJobStats.clear();
8562            for (int j = 0; j < numJobs; j++) {
8563                String jobName = in.readString();
8564                if (in.readInt() != 0) {
8565                    mJobStats.add(jobName, new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
8566                            mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
8567                }
8568            }
8569
8570            readJobCompletionsFromParcelLocked(in);
8571
8572            mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase, in);
8573            mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase, in);
8574            mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8575            for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8576                mJobsFreshnessBuckets[i] = Counter.readCounterFromParcel(mBsi.mOnBatteryTimeBase,
8577                        in);
8578            }
8579
8580            int numSensors = in.readInt();
8581            mSensorStats.clear();
8582            for (int k = 0; k < numSensors; k++) {
8583                int sensorNumber = in.readInt();
8584                Uid.Sensor sensor = new Sensor(mBsi, this, sensorNumber);
8585                sensor.readFromParcelLocked(mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
8586                        in);
8587                mSensorStats.put(sensorNumber, sensor);
8588            }
8589
8590            int numProcs = in.readInt();
8591            mProcessStats.clear();
8592            for (int k = 0; k < numProcs; k++) {
8593                String processName = in.readString();
8594                Uid.Proc proc = new Proc(mBsi, processName);
8595                proc.readFromParcelLocked(in);
8596                mProcessStats.put(processName, proc);
8597            }
8598
8599            int numPkgs = in.readInt();
8600            mPackageStats.clear();
8601            for (int l = 0; l < numPkgs; l++) {
8602                String packageName = in.readString();
8603                Uid.Pkg pkg = new Pkg(mBsi);
8604                pkg.readFromParcelLocked(in);
8605                mPackageStats.put(packageName, pkg);
8606            }
8607
8608            mWifiRunning = false;
8609            if (in.readInt() != 0) {
8610                mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
8611                        mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase, in);
8612            } else {
8613                mWifiRunningTimer = null;
8614            }
8615            mFullWifiLockOut = false;
8616            if (in.readInt() != 0) {
8617                mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
8618                        mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase, in);
8619            } else {
8620                mFullWifiLockTimer = null;
8621            }
8622            mWifiScanStarted = false;
8623            if (in.readInt() != 0) {
8624                mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
8625                        mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
8626                        in);
8627            } else {
8628                mWifiScanTimer = null;
8629            }
8630            mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
8631            for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
8632                if (in.readInt() != 0) {
8633                    makeWifiBatchedScanBin(i, in);
8634                } else {
8635                    mWifiBatchedScanTimer[i] = null;
8636                }
8637            }
8638            mWifiMulticastEnabled = false;
8639            if (in.readInt() != 0) {
8640                mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_MULTICAST_ENABLED,
8641                        mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase, in);
8642            } else {
8643                mWifiMulticastTimer = null;
8644            }
8645            if (in.readInt() != 0) {
8646                mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
8647                        mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8648            } else {
8649                mAudioTurnedOnTimer = null;
8650            }
8651            if (in.readInt() != 0) {
8652                mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
8653                        mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8654            } else {
8655                mVideoTurnedOnTimer = null;
8656            }
8657            if (in.readInt() != 0) {
8658                mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8659                        FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8660            } else {
8661                mFlashlightTurnedOnTimer = null;
8662            }
8663            if (in.readInt() != 0) {
8664                mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
8665                        mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
8666            } else {
8667                mCameraTurnedOnTimer = null;
8668            }
8669            if (in.readInt() != 0) {
8670                mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8671                        FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase, in);
8672            } else {
8673                mForegroundActivityTimer = null;
8674            }
8675            if (in.readInt() != 0) {
8676                mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
8677                        FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase, in);
8678            } else {
8679                mForegroundServiceTimer = null;
8680            }
8681            if (in.readInt() != 0) {
8682                mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
8683                        AGGREGATED_WAKE_TYPE_PARTIAL, null,
8684                        mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase,
8685                        in);
8686            } else {
8687                mAggregatedPartialWakelockTimer = null;
8688            }
8689            if (in.readInt() != 0) {
8690                mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
8691                        mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
8692                        mOnBatteryBackgroundTimeBase, in);
8693            } else {
8694                mBluetoothScanTimer = null;
8695            }
8696            if (in.readInt() != 0) {
8697                mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
8698                        BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
8699                        mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in);
8700            } else {
8701                mBluetoothUnoptimizedScanTimer = null;
8702            }
8703            if (in.readInt() != 0) {
8704                mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase, in);
8705            } else {
8706                mBluetoothScanResultCounter = null;
8707            }
8708            if (in.readInt() != 0) {
8709                mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase, in);
8710            } else {
8711                mBluetoothScanResultBgCounter = null;
8712            }
8713            mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
8714            for (int i = 0; i < NUM_PROCESS_STATE; i++) {
8715                if (in.readInt() != 0) {
8716                    makeProcessState(i, in);
8717                } else {
8718                    mProcessStateTimer[i] = null;
8719                }
8720            }
8721            if (in.readInt() != 0) {
8722                mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
8723                        mBsi.mOnBatteryTimeBase, in);
8724            } else {
8725                mVibratorOnTimer = null;
8726            }
8727            if (in.readInt() != 0) {
8728                mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
8729                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
8730                    mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase, in);
8731                }
8732            } else {
8733                mUserActivityCounters = null;
8734            }
8735            if (in.readInt() != 0) {
8736                mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
8737                mNetworkPacketActivityCounters
8738                        = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
8739                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8740                    mNetworkByteActivityCounters[i]
8741                            = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8742                    mNetworkPacketActivityCounters[i]
8743                            = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8744                }
8745                mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8746                mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8747            } else {
8748                mNetworkByteActivityCounters = null;
8749                mNetworkPacketActivityCounters = null;
8750            }
8751
8752            if (in.readInt() != 0) {
8753                mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8754                        NUM_WIFI_TX_LEVELS, in);
8755            } else {
8756                mWifiControllerActivity = null;
8757            }
8758
8759            if (in.readInt() != 0) {
8760                mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8761                        NUM_BT_TX_LEVELS, in);
8762            } else {
8763                mBluetoothControllerActivity = null;
8764            }
8765
8766            if (in.readInt() != 0) {
8767                mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
8768                        ModemActivityInfo.TX_POWER_LEVELS, in);
8769            } else {
8770                mModemControllerActivity = null;
8771            }
8772
8773            mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8774            mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8775
8776            if (in.readInt() != 0) {
8777                int numCpuClusters = in.readInt();
8778                if (mBsi.mPowerProfile != null && mBsi.mPowerProfile.getNumCpuClusters() != numCpuClusters) {
8779                    throw new ParcelFormatException("Incompatible number of cpu clusters");
8780                }
8781
8782                mCpuClusterSpeedTimesUs = new LongSamplingCounter[numCpuClusters][];
8783                for (int cluster = 0; cluster < numCpuClusters; cluster++) {
8784                    if (in.readInt() != 0) {
8785                        int numSpeeds = in.readInt();
8786                        if (mBsi.mPowerProfile != null &&
8787                                mBsi.mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
8788                            throw new ParcelFormatException("Incompatible number of cpu speeds");
8789                        }
8790
8791                        final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
8792                        mCpuClusterSpeedTimesUs[cluster] = cpuSpeeds;
8793                        for (int speed = 0; speed < numSpeeds; speed++) {
8794                            if (in.readInt() != 0) {
8795                                cpuSpeeds[speed] = new LongSamplingCounter(
8796                                        mBsi.mOnBatteryTimeBase, in);
8797                            }
8798                        }
8799                    } else {
8800                        mCpuClusterSpeedTimesUs[cluster] = null;
8801                    }
8802                }
8803            } else {
8804                mCpuClusterSpeedTimesUs = null;
8805            }
8806
8807            mCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(in, mBsi.mOnBatteryTimeBase);
8808            mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(
8809                    in, mBsi.mOnBatteryScreenOffTimeBase);
8810
8811            mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8812            mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
8813
8814            int length = in.readInt();
8815            if (length == NUM_PROCESS_STATE) {
8816                mProcStateTimeMs = new LongSamplingCounterArray[length];
8817                for (int procState = 0; procState < length; ++procState) {
8818                    mProcStateTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
8819                            in, mBsi.mOnBatteryTimeBase);
8820                }
8821            } else {
8822                mProcStateTimeMs = null;
8823            }
8824            length = in.readInt();
8825            if (length == NUM_PROCESS_STATE) {
8826                mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
8827                for (int procState = 0; procState < length; ++procState) {
8828                    mProcStateScreenOffTimeMs[procState] = LongSamplingCounterArray.readFromParcel(
8829                            in, mBsi.mOnBatteryScreenOffTimeBase);
8830                }
8831            } else {
8832                mProcStateScreenOffTimeMs = null;
8833            }
8834
8835            if (in.readInt() != 0) {
8836                mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8837            } else {
8838                mMobileRadioApWakeupCount = null;
8839            }
8840
8841            if (in.readInt() != 0) {
8842                mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
8843            } else {
8844                mWifiRadioApWakeupCount = null;
8845            }
8846        }
8847
8848        public void noteJobsDeferredLocked(int numDeferred, long sinceLast) {
8849            mJobsDeferredEventCount.addAtomic(1);
8850            mJobsDeferredCount.addAtomic(numDeferred);
8851            if (sinceLast != 0) {
8852                // Add the total time, which can be divided by the event count to get an average
8853                mJobsFreshnessTimeMs.addCountLocked(sinceLast);
8854                // Also keep track of how many times there were in these different buckets.
8855                for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
8856                    if (sinceLast < JOB_FRESHNESS_BUCKETS[i]) {
8857                        if (mJobsFreshnessBuckets[i] == null) {
8858                            mJobsFreshnessBuckets[i] = new Counter(
8859                                    mBsi.mOnBatteryTimeBase);
8860                        }
8861                        mJobsFreshnessBuckets[i].addAtomic(1);
8862                        break;
8863                    }
8864                }
8865            }
8866        }
8867
8868        /**
8869         * The statistics associated with a particular wake lock.
8870         */
8871        public static class Wakelock extends BatteryStats.Uid.Wakelock {
8872            /**
8873             * BatteryStatsImpl that we are associated with.
8874             */
8875            protected BatteryStatsImpl mBsi;
8876
8877            /**
8878             * BatteryStatsImpl that we are associated with.
8879             */
8880            protected Uid mUid;
8881
8882            /**
8883             * How long (in ms) this uid has been keeping the device partially awake.
8884             * Tracks both the total time and the time while the app was in the background.
8885             */
8886            DualTimer mTimerPartial;
8887
8888            /**
8889             * How long (in ms) this uid has been keeping the device fully awake.
8890             */
8891            StopwatchTimer mTimerFull;
8892
8893            /**
8894             * How long (in ms) this uid has had a window keeping the device awake.
8895             */
8896            StopwatchTimer mTimerWindow;
8897
8898            /**
8899             * How long (in ms) this uid has had a draw wake lock.
8900             */
8901            StopwatchTimer mTimerDraw;
8902
8903            public Wakelock(BatteryStatsImpl bsi, Uid uid) {
8904                mBsi = bsi;
8905                mUid = uid;
8906            }
8907
8908            /**
8909             * Reads a possibly null Timer from a Parcel.  The timer is associated with the
8910             * proper timer pool from the given BatteryStatsImpl object.
8911             *
8912             * @param in the Parcel to be read from.
8913             * return a new Timer, or null.
8914             */
8915            private StopwatchTimer readStopwatchTimerFromParcel(int type,
8916                    ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
8917                if (in.readInt() == 0) {
8918                    return null;
8919                }
8920
8921                return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
8922            }
8923
8924            /**
8925             * Reads a possibly null Timer from a Parcel.  The timer is associated with the
8926             * proper timer pool from the given BatteryStatsImpl object.
8927             *
8928             * @param in the Parcel to be read from.
8929             * return a new Timer, or null.
8930             */
8931            private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
8932                    TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
8933                if (in.readInt() == 0) {
8934                    return null;
8935                }
8936
8937                return new DualTimer(mBsi.mClocks, mUid, type, pool, timeBase, bgTimeBase, in);
8938            }
8939
8940            boolean reset() {
8941                boolean wlactive = false;
8942                if (mTimerFull != null) {
8943                    wlactive |= !mTimerFull.reset(false);
8944                }
8945                if (mTimerPartial != null) {
8946                    wlactive |= !mTimerPartial.reset(false);
8947                }
8948                if (mTimerWindow != null) {
8949                    wlactive |= !mTimerWindow.reset(false);
8950                }
8951                if (mTimerDraw != null) {
8952                    wlactive |= !mTimerDraw.reset(false);
8953                }
8954                if (!wlactive) {
8955                    if (mTimerFull != null) {
8956                        mTimerFull.detach();
8957                        mTimerFull = null;
8958                    }
8959                    if (mTimerPartial != null) {
8960                        mTimerPartial.detach();
8961                        mTimerPartial = null;
8962                    }
8963                    if (mTimerWindow != null) {
8964                        mTimerWindow.detach();
8965                        mTimerWindow = null;
8966                    }
8967                    if (mTimerDraw != null) {
8968                        mTimerDraw.detach();
8969                        mTimerDraw = null;
8970                    }
8971                }
8972                return !wlactive;
8973            }
8974
8975            void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase,
8976                    TimeBase screenOffBgTimeBase, Parcel in) {
8977                mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL,
8978                        mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in);
8979                mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
8980                        mBsi.mFullTimers, timeBase, in);
8981                mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
8982                        mBsi.mWindowTimers, timeBase, in);
8983                mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
8984                        mBsi.mDrawTimers, timeBase, in);
8985            }
8986
8987            void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
8988                Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
8989                Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
8990                Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
8991                Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
8992            }
8993
8994            @Override
8995            public Timer getWakeTime(int type) {
8996                switch (type) {
8997                case WAKE_TYPE_FULL: return mTimerFull;
8998                case WAKE_TYPE_PARTIAL: return mTimerPartial;
8999                case WAKE_TYPE_WINDOW: return mTimerWindow;
9000                case WAKE_TYPE_DRAW: return mTimerDraw;
9001                default: throw new IllegalArgumentException("type = " + type);
9002                }
9003            }
9004        }
9005
9006        public static class Sensor extends BatteryStats.Uid.Sensor {
9007            /**
9008             * BatteryStatsImpl that we are associated with.
9009             */
9010            protected BatteryStatsImpl mBsi;
9011
9012            /**
9013             * Uid that we are associated with.
9014             */
9015            protected Uid mUid;
9016
9017            final int mHandle;
9018            DualTimer mTimer;
9019
9020            public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
9021                mBsi = bsi;
9022                mUid = uid;
9023                mHandle = handle;
9024            }
9025
9026            private DualTimer readTimersFromParcel(
9027                    TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
9028                if (in.readInt() == 0) {
9029                    return null;
9030                }
9031
9032                ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
9033                if (pool == null) {
9034                    pool = new ArrayList<StopwatchTimer>();
9035                    mBsi.mSensorTimers.put(mHandle, pool);
9036                }
9037                return new DualTimer(mBsi.mClocks, mUid, 0, pool, timeBase, bgTimeBase, in);
9038            }
9039
9040            boolean reset() {
9041                if (mTimer.reset(true)) {
9042                    mTimer = null;
9043                    return true;
9044                }
9045                return false;
9046            }
9047
9048            void readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
9049                mTimer = readTimersFromParcel(timeBase, bgTimeBase, in);
9050            }
9051
9052            void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
9053                Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
9054            }
9055
9056            @Override
9057            public Timer getSensorTime() {
9058                return mTimer;
9059            }
9060
9061            @Override
9062            public Timer getSensorBackgroundTime() {
9063                if (mTimer == null) {
9064                    return null;
9065                }
9066                return mTimer.getSubTimer();
9067            }
9068
9069            @Override
9070            public int getHandle() {
9071                return mHandle;
9072            }
9073        }
9074
9075        /**
9076         * The statistics associated with a particular process.
9077         */
9078        public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
9079            /**
9080             * BatteryStatsImpl that we are associated with.
9081             */
9082            protected BatteryStatsImpl mBsi;
9083
9084            /**
9085             * The name of this process.
9086             */
9087            final String mName;
9088
9089            /**
9090             * Remains true until removed from the stats.
9091             */
9092            boolean mActive = true;
9093
9094            /**
9095             * Total time (in ms) spent executing in user code.
9096             */
9097            long mUserTime;
9098
9099            /**
9100             * Total time (in ms) spent executing in kernel code.
9101             */
9102            long mSystemTime;
9103
9104            /**
9105             * Amount of time (in ms) the process was running in the foreground.
9106             */
9107            long mForegroundTime;
9108
9109            /**
9110             * Number of times the process has been started.
9111             */
9112            int mStarts;
9113
9114            /**
9115             * Number of times the process has crashed.
9116             */
9117            int mNumCrashes;
9118
9119            /**
9120             * Number of times the process has had an ANR.
9121             */
9122            int mNumAnrs;
9123
9124            /**
9125             * The amount of user time loaded from a previous save.
9126             */
9127            long mLoadedUserTime;
9128
9129            /**
9130             * The amount of system time loaded from a previous save.
9131             */
9132            long mLoadedSystemTime;
9133
9134            /**
9135             * The amount of foreground time loaded from a previous save.
9136             */
9137            long mLoadedForegroundTime;
9138
9139            /**
9140             * The number of times the process has started from a previous save.
9141             */
9142            int mLoadedStarts;
9143
9144            /**
9145             * Number of times the process has crashed from a previous save.
9146             */
9147            int mLoadedNumCrashes;
9148
9149            /**
9150             * Number of times the process has had an ANR from a previous save.
9151             */
9152            int mLoadedNumAnrs;
9153
9154            /**
9155             * The amount of user time when last unplugged.
9156             */
9157            long mUnpluggedUserTime;
9158
9159            /**
9160             * The amount of system time when last unplugged.
9161             */
9162            long mUnpluggedSystemTime;
9163
9164            /**
9165             * The amount of foreground time since unplugged.
9166             */
9167            long mUnpluggedForegroundTime;
9168
9169            /**
9170             * The number of times the process has started before unplugged.
9171             */
9172            int mUnpluggedStarts;
9173
9174            /**
9175             * Number of times the process has crashed before unplugged.
9176             */
9177            int mUnpluggedNumCrashes;
9178
9179            /**
9180             * Number of times the process has had an ANR before unplugged.
9181             */
9182            int mUnpluggedNumAnrs;
9183
9184            ArrayList<ExcessivePower> mExcessivePower;
9185
9186            public Proc(BatteryStatsImpl bsi, String name) {
9187                mBsi = bsi;
9188                mName = name;
9189                mBsi.mOnBatteryTimeBase.add(this);
9190            }
9191
9192            public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
9193                mUnpluggedUserTime = mUserTime;
9194                mUnpluggedSystemTime = mSystemTime;
9195                mUnpluggedForegroundTime = mForegroundTime;
9196                mUnpluggedStarts = mStarts;
9197                mUnpluggedNumCrashes = mNumCrashes;
9198                mUnpluggedNumAnrs = mNumAnrs;
9199            }
9200
9201            public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
9202            }
9203
9204            void detach() {
9205                mActive = false;
9206                mBsi.mOnBatteryTimeBase.remove(this);
9207            }
9208
9209            public int countExcessivePowers() {
9210                return mExcessivePower != null ? mExcessivePower.size() : 0;
9211            }
9212
9213            public ExcessivePower getExcessivePower(int i) {
9214                if (mExcessivePower != null) {
9215                    return mExcessivePower.get(i);
9216                }
9217                return null;
9218            }
9219
9220            public void addExcessiveCpu(long overTime, long usedTime) {
9221                if (mExcessivePower == null) {
9222                    mExcessivePower = new ArrayList<ExcessivePower>();
9223                }
9224                ExcessivePower ew = new ExcessivePower();
9225                ew.type = ExcessivePower.TYPE_CPU;
9226                ew.overTime = overTime;
9227                ew.usedTime = usedTime;
9228                mExcessivePower.add(ew);
9229            }
9230
9231            void writeExcessivePowerToParcelLocked(Parcel out) {
9232                if (mExcessivePower == null) {
9233                    out.writeInt(0);
9234                    return;
9235                }
9236
9237                final int N = mExcessivePower.size();
9238                out.writeInt(N);
9239                for (int i=0; i<N; i++) {
9240                    ExcessivePower ew = mExcessivePower.get(i);
9241                    out.writeInt(ew.type);
9242                    out.writeLong(ew.overTime);
9243                    out.writeLong(ew.usedTime);
9244                }
9245            }
9246
9247            void readExcessivePowerFromParcelLocked(Parcel in) {
9248                final int N = in.readInt();
9249                if (N == 0) {
9250                    mExcessivePower = null;
9251                    return;
9252                }
9253
9254                if (N > 10000) {
9255                    throw new ParcelFormatException(
9256                            "File corrupt: too many excessive power entries " + N);
9257                }
9258
9259                mExcessivePower = new ArrayList<>();
9260                for (int i=0; i<N; i++) {
9261                    ExcessivePower ew = new ExcessivePower();
9262                    ew.type = in.readInt();
9263                    ew.overTime = in.readLong();
9264                    ew.usedTime = in.readLong();
9265                    mExcessivePower.add(ew);
9266                }
9267            }
9268
9269            void writeToParcelLocked(Parcel out) {
9270                out.writeLong(mUserTime);
9271                out.writeLong(mSystemTime);
9272                out.writeLong(mForegroundTime);
9273                out.writeInt(mStarts);
9274                out.writeInt(mNumCrashes);
9275                out.writeInt(mNumAnrs);
9276                out.writeLong(mLoadedUserTime);
9277                out.writeLong(mLoadedSystemTime);
9278                out.writeLong(mLoadedForegroundTime);
9279                out.writeInt(mLoadedStarts);
9280                out.writeInt(mLoadedNumCrashes);
9281                out.writeInt(mLoadedNumAnrs);
9282                out.writeLong(mUnpluggedUserTime);
9283                out.writeLong(mUnpluggedSystemTime);
9284                out.writeLong(mUnpluggedForegroundTime);
9285                out.writeInt(mUnpluggedStarts);
9286                out.writeInt(mUnpluggedNumCrashes);
9287                out.writeInt(mUnpluggedNumAnrs);
9288                writeExcessivePowerToParcelLocked(out);
9289            }
9290
9291            void readFromParcelLocked(Parcel in) {
9292                mUserTime = in.readLong();
9293                mSystemTime = in.readLong();
9294                mForegroundTime = in.readLong();
9295                mStarts = in.readInt();
9296                mNumCrashes = in.readInt();
9297                mNumAnrs = in.readInt();
9298                mLoadedUserTime = in.readLong();
9299                mLoadedSystemTime = in.readLong();
9300                mLoadedForegroundTime = in.readLong();
9301                mLoadedStarts = in.readInt();
9302                mLoadedNumCrashes = in.readInt();
9303                mLoadedNumAnrs = in.readInt();
9304                mUnpluggedUserTime = in.readLong();
9305                mUnpluggedSystemTime = in.readLong();
9306                mUnpluggedForegroundTime = in.readLong();
9307                mUnpluggedStarts = in.readInt();
9308                mUnpluggedNumCrashes = in.readInt();
9309                mUnpluggedNumAnrs = in.readInt();
9310                readExcessivePowerFromParcelLocked(in);
9311            }
9312
9313            public void addCpuTimeLocked(int utime, int stime) {
9314                addCpuTimeLocked(utime, stime, mBsi.mOnBatteryTimeBase.isRunning());
9315            }
9316
9317            public void addCpuTimeLocked(int utime, int stime, boolean isRunning) {
9318                if (isRunning) {
9319                    mUserTime += utime;
9320                    mSystemTime += stime;
9321                }
9322            }
9323
9324            public void addForegroundTimeLocked(long ttime) {
9325                mForegroundTime += ttime;
9326            }
9327
9328            public void incStartsLocked() {
9329                mStarts++;
9330            }
9331
9332            public void incNumCrashesLocked() {
9333                mNumCrashes++;
9334            }
9335
9336            public void incNumAnrsLocked() {
9337                mNumAnrs++;
9338            }
9339
9340            @Override
9341            public boolean isActive() {
9342                return mActive;
9343            }
9344
9345            @Override
9346            public long getUserTime(int which) {
9347                long val = mUserTime;
9348                if (which == STATS_CURRENT) {
9349                    val -= mLoadedUserTime;
9350                } else if (which == STATS_SINCE_UNPLUGGED) {
9351                    val -= mUnpluggedUserTime;
9352                }
9353                return val;
9354            }
9355
9356            @Override
9357            public long getSystemTime(int which) {
9358                long val = mSystemTime;
9359                if (which == STATS_CURRENT) {
9360                    val -= mLoadedSystemTime;
9361                } else if (which == STATS_SINCE_UNPLUGGED) {
9362                    val -= mUnpluggedSystemTime;
9363                }
9364                return val;
9365            }
9366
9367            @Override
9368            public long getForegroundTime(int which) {
9369                long val = mForegroundTime;
9370                if (which == STATS_CURRENT) {
9371                    val -= mLoadedForegroundTime;
9372                } else if (which == STATS_SINCE_UNPLUGGED) {
9373                    val -= mUnpluggedForegroundTime;
9374                }
9375                return val;
9376            }
9377
9378            @Override
9379            public int getStarts(int which) {
9380                int val = mStarts;
9381                if (which == STATS_CURRENT) {
9382                    val -= mLoadedStarts;
9383                } else if (which == STATS_SINCE_UNPLUGGED) {
9384                    val -= mUnpluggedStarts;
9385                }
9386                return val;
9387            }
9388
9389            @Override
9390            public int getNumCrashes(int which) {
9391                int val = mNumCrashes;
9392                if (which == STATS_CURRENT) {
9393                    val -= mLoadedNumCrashes;
9394                } else if (which == STATS_SINCE_UNPLUGGED) {
9395                    val -= mUnpluggedNumCrashes;
9396                }
9397                return val;
9398            }
9399
9400            @Override
9401            public int getNumAnrs(int which) {
9402                int val = mNumAnrs;
9403                if (which == STATS_CURRENT) {
9404                    val -= mLoadedNumAnrs;
9405                } else if (which == STATS_SINCE_UNPLUGGED) {
9406                    val -= mUnpluggedNumAnrs;
9407                }
9408                return val;
9409            }
9410        }
9411
9412        /**
9413         * The statistics associated with a particular package.
9414         */
9415        public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
9416            /**
9417             * BatteryStatsImpl that we are associated with.
9418             */
9419            protected BatteryStatsImpl mBsi;
9420
9421            /**
9422             * Number of times wakeup alarms have occurred for this app.
9423             * On screen-off timebase starting in report v25.
9424             */
9425            ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
9426
9427            /**
9428             * The statics we have collected for this package's services.
9429             */
9430            final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
9431
9432            public Pkg(BatteryStatsImpl bsi) {
9433                mBsi = bsi;
9434                mBsi.mOnBatteryScreenOffTimeBase.add(this);
9435            }
9436
9437            public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
9438            }
9439
9440            public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
9441            }
9442
9443            void detach() {
9444                mBsi.mOnBatteryScreenOffTimeBase.remove(this);
9445            }
9446
9447            void readFromParcelLocked(Parcel in) {
9448                int numWA = in.readInt();
9449                mWakeupAlarms.clear();
9450                for (int i=0; i<numWA; i++) {
9451                    String tag = in.readString();
9452                    mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryScreenOffTimeBase, in));
9453                }
9454
9455                int numServs = in.readInt();
9456                mServiceStats.clear();
9457                for (int m = 0; m < numServs; m++) {
9458                    String serviceName = in.readString();
9459                    Uid.Pkg.Serv serv = new Serv(mBsi);
9460                    mServiceStats.put(serviceName, serv);
9461
9462                    serv.readFromParcelLocked(in);
9463                }
9464            }
9465
9466            void writeToParcelLocked(Parcel out) {
9467                int numWA = mWakeupAlarms.size();
9468                out.writeInt(numWA);
9469                for (int i=0; i<numWA; i++) {
9470                    out.writeString(mWakeupAlarms.keyAt(i));
9471                    mWakeupAlarms.valueAt(i).writeToParcel(out);
9472                }
9473
9474                final int NS = mServiceStats.size();
9475                out.writeInt(NS);
9476                for (int i=0; i<NS; i++) {
9477                    out.writeString(mServiceStats.keyAt(i));
9478                    Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
9479                    serv.writeToParcelLocked(out);
9480                }
9481            }
9482
9483            @Override
9484            public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
9485                return mWakeupAlarms;
9486            }
9487
9488            public void noteWakeupAlarmLocked(String tag) {
9489                Counter c = mWakeupAlarms.get(tag);
9490                if (c == null) {
9491                    c = new Counter(mBsi.mOnBatteryScreenOffTimeBase);
9492                    mWakeupAlarms.put(tag, c);
9493                }
9494                c.stepAtomic();
9495            }
9496
9497            @Override
9498            public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
9499                return mServiceStats;
9500            }
9501
9502            /**
9503             * The statistics associated with a particular service.
9504             */
9505            public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
9506                /**
9507                 * BatteryStatsImpl that we are associated with.
9508                 */
9509                protected BatteryStatsImpl mBsi;
9510
9511                /**
9512                 * The android package in which this service resides.
9513                 */
9514                protected Pkg mPkg;
9515
9516                /**
9517                 * Total time (ms in battery uptime) the service has been left started.
9518                 */
9519                protected long mStartTime;
9520
9521                /**
9522                 * If service has been started and not yet stopped, this is
9523                 * when it was started.
9524                 */
9525                protected long mRunningSince;
9526
9527                /**
9528                 * True if we are currently running.
9529                 */
9530                protected boolean mRunning;
9531
9532                /**
9533                 * Total number of times startService() has been called.
9534                 */
9535                protected int mStarts;
9536
9537                /**
9538                 * Total time (ms in battery uptime) the service has been left launched.
9539                 */
9540                protected long mLaunchedTime;
9541
9542                /**
9543                 * If service has been launched and not yet exited, this is
9544                 * when it was launched (ms in battery uptime).
9545                 */
9546                protected long mLaunchedSince;
9547
9548                /**
9549                 * True if we are currently launched.
9550                 */
9551                protected boolean mLaunched;
9552
9553                /**
9554                 * Total number times the service has been launched.
9555                 */
9556                protected int mLaunches;
9557
9558                /**
9559                 * The amount of time spent started loaded from a previous save
9560                 * (ms in battery uptime).
9561                 */
9562                protected long mLoadedStartTime;
9563
9564                /**
9565                 * The number of starts loaded from a previous save.
9566                 */
9567                protected int mLoadedStarts;
9568
9569                /**
9570                 * The number of launches loaded from a previous save.
9571                 */
9572                protected int mLoadedLaunches;
9573
9574                /**
9575                 * The amount of time spent started as of the last run (ms
9576                 * in battery uptime).
9577                 */
9578                protected long mLastStartTime;
9579
9580                /**
9581                 * The number of starts as of the last run.
9582                 */
9583                protected int mLastStarts;
9584
9585                /**
9586                 * The number of launches as of the last run.
9587                 */
9588                protected int mLastLaunches;
9589
9590                /**
9591                 * The amount of time spent started when last unplugged (ms
9592                 * in battery uptime).
9593                 */
9594                protected long mUnpluggedStartTime;
9595
9596                /**
9597                 * The number of starts when last unplugged.
9598                 */
9599                protected int mUnpluggedStarts;
9600
9601                /**
9602                 * The number of launches when last unplugged.
9603                 */
9604                protected int mUnpluggedLaunches;
9605
9606                /**
9607                 * Construct a Serv. Also adds it to the on-battery time base as a listener.
9608                 */
9609                public Serv(BatteryStatsImpl bsi) {
9610                    mBsi = bsi;
9611                    mBsi.mOnBatteryTimeBase.add(this);
9612                }
9613
9614                public void onTimeStarted(long elapsedRealtime, long baseUptime,
9615                        long baseRealtime) {
9616                    mUnpluggedStartTime = getStartTimeToNowLocked(baseUptime);
9617                    mUnpluggedStarts = mStarts;
9618                    mUnpluggedLaunches = mLaunches;
9619                }
9620
9621                public void onTimeStopped(long elapsedRealtime, long baseUptime,
9622                        long baseRealtime) {
9623                }
9624
9625                /**
9626                 * Remove this Serv as a listener from the time base.
9627                 */
9628                public void detach() {
9629                    mBsi.mOnBatteryTimeBase.remove(this);
9630                }
9631
9632                public void readFromParcelLocked(Parcel in) {
9633                    mStartTime = in.readLong();
9634                    mRunningSince = in.readLong();
9635                    mRunning = in.readInt() != 0;
9636                    mStarts = in.readInt();
9637                    mLaunchedTime = in.readLong();
9638                    mLaunchedSince = in.readLong();
9639                    mLaunched = in.readInt() != 0;
9640                    mLaunches = in.readInt();
9641                    mLoadedStartTime = in.readLong();
9642                    mLoadedStarts = in.readInt();
9643                    mLoadedLaunches = in.readInt();
9644                    mLastStartTime = 0;
9645                    mLastStarts = 0;
9646                    mLastLaunches = 0;
9647                    mUnpluggedStartTime = in.readLong();
9648                    mUnpluggedStarts = in.readInt();
9649                    mUnpluggedLaunches = in.readInt();
9650                }
9651
9652                public void writeToParcelLocked(Parcel out) {
9653                    out.writeLong(mStartTime);
9654                    out.writeLong(mRunningSince);
9655                    out.writeInt(mRunning ? 1 : 0);
9656                    out.writeInt(mStarts);
9657                    out.writeLong(mLaunchedTime);
9658                    out.writeLong(mLaunchedSince);
9659                    out.writeInt(mLaunched ? 1 : 0);
9660                    out.writeInt(mLaunches);
9661                    out.writeLong(mLoadedStartTime);
9662                    out.writeInt(mLoadedStarts);
9663                    out.writeInt(mLoadedLaunches);
9664                    out.writeLong(mUnpluggedStartTime);
9665                    out.writeInt(mUnpluggedStarts);
9666                    out.writeInt(mUnpluggedLaunches);
9667                }
9668
9669                public long getLaunchTimeToNowLocked(long batteryUptime) {
9670                    if (!mLaunched) return mLaunchedTime;
9671                    return mLaunchedTime + batteryUptime - mLaunchedSince;
9672                }
9673
9674                public long getStartTimeToNowLocked(long batteryUptime) {
9675                    if (!mRunning) return mStartTime;
9676                    return mStartTime + batteryUptime - mRunningSince;
9677                }
9678
9679                public void startLaunchedLocked() {
9680                    if (!mLaunched) {
9681                        mLaunches++;
9682                        mLaunchedSince = mBsi.getBatteryUptimeLocked();
9683                        mLaunched = true;
9684                    }
9685                }
9686
9687                public void stopLaunchedLocked() {
9688                    if (mLaunched) {
9689                        long time = mBsi.getBatteryUptimeLocked() - mLaunchedSince;
9690                        if (time > 0) {
9691                            mLaunchedTime += time;
9692                        } else {
9693                            mLaunches--;
9694                        }
9695                        mLaunched = false;
9696                    }
9697                }
9698
9699                public void startRunningLocked() {
9700                    if (!mRunning) {
9701                        mStarts++;
9702                        mRunningSince = mBsi.getBatteryUptimeLocked();
9703                        mRunning = true;
9704                    }
9705                }
9706
9707                public void stopRunningLocked() {
9708                    if (mRunning) {
9709                        long time = mBsi.getBatteryUptimeLocked() - mRunningSince;
9710                        if (time > 0) {
9711                            mStartTime += time;
9712                        } else {
9713                            mStarts--;
9714                        }
9715                        mRunning = false;
9716                    }
9717                }
9718
9719                public BatteryStatsImpl getBatteryStats() {
9720                    return mBsi;
9721                }
9722
9723                @Override
9724                public int getLaunches(int which) {
9725                    int val = mLaunches;
9726                    if (which == STATS_CURRENT) {
9727                        val -= mLoadedLaunches;
9728                    } else if (which == STATS_SINCE_UNPLUGGED) {
9729                        val -= mUnpluggedLaunches;
9730                    }
9731                    return val;
9732                }
9733
9734                @Override
9735                public long getStartTime(long now, int which) {
9736                    long val = getStartTimeToNowLocked(now);
9737                    if (which == STATS_CURRENT) {
9738                        val -= mLoadedStartTime;
9739                    } else if (which == STATS_SINCE_UNPLUGGED) {
9740                        val -= mUnpluggedStartTime;
9741                    }
9742                    return val;
9743                }
9744
9745                @Override
9746                public int getStarts(int which) {
9747                    int val = mStarts;
9748                    if (which == STATS_CURRENT) {
9749                        val -= mLoadedStarts;
9750                    } else if (which == STATS_SINCE_UNPLUGGED) {
9751                        val -= mUnpluggedStarts;
9752                    }
9753
9754                    return val;
9755                }
9756            }
9757
9758            final Serv newServiceStatsLocked() {
9759                return new Serv(mBsi);
9760            }
9761        }
9762
9763        /**
9764         * Retrieve the statistics object for a particular process, creating
9765         * if needed.
9766         */
9767        public Proc getProcessStatsLocked(String name) {
9768            Proc ps = mProcessStats.get(name);
9769            if (ps == null) {
9770                ps = new Proc(mBsi, name);
9771                mProcessStats.put(name, ps);
9772            }
9773
9774            return ps;
9775        }
9776
9777        @GuardedBy("mBsi")
9778        public void updateUidProcessStateLocked(int procState) {
9779            int uidRunningState;
9780            // Make special note of Foreground Services
9781            final boolean userAwareService =
9782                    (procState == ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
9783            uidRunningState = BatteryStats.mapToInternalProcessState(procState);
9784
9785            if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
9786                return;
9787            }
9788
9789            final long elapsedRealtimeMs = mBsi.mClocks.elapsedRealtime();
9790            if (mProcessState != uidRunningState) {
9791                final long uptimeMs = mBsi.mClocks.uptimeMillis();
9792
9793                if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
9794                    mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
9795
9796                    if (mBsi.trackPerProcStateCpuTimes()) {
9797                        if (mBsi.mPendingUids.size() == 0) {
9798                            mBsi.mExternalSync.scheduleReadProcStateCpuTimes(
9799                                    mBsi.mOnBatteryTimeBase.isRunning(),
9800                                    mBsi.mOnBatteryScreenOffTimeBase.isRunning(),
9801                                    mBsi.mConstants.PROC_STATE_CPU_TIMES_READ_DELAY_MS);
9802                            mBsi.mNumSingleUidCpuTimeReads++;
9803                        } else {
9804                            mBsi.mNumBatchedSingleUidCpuTimeReads++;
9805                        }
9806                        if (mBsi.mPendingUids.indexOfKey(mUid) < 0
9807                                || ArrayUtils.contains(CRITICAL_PROC_STATES, mProcessState)) {
9808                            mBsi.mPendingUids.put(mUid, mProcessState);
9809                        }
9810                    } else {
9811                        mBsi.mPendingUids.clear();
9812                    }
9813                }
9814                mProcessState = uidRunningState;
9815                if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
9816                    if (mProcessStateTimer[uidRunningState] == null) {
9817                        makeProcessState(uidRunningState, null);
9818                    }
9819                    mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
9820                }
9821
9822                updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
9823                updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
9824            }
9825
9826            if (userAwareService != mInForegroundService) {
9827                if (userAwareService) {
9828                    noteForegroundServiceResumedLocked(elapsedRealtimeMs);
9829                } else {
9830                    noteForegroundServicePausedLocked(elapsedRealtimeMs);
9831                }
9832                mInForegroundService = userAwareService;
9833            }
9834        }
9835
9836        /** Whether to consider Uid to be in the background for background timebase purposes. */
9837        public boolean isInBackground() {
9838            // Note that PROCESS_STATE_CACHED and ActivityManager.PROCESS_STATE_NONEXISTENT is
9839            // also considered to be 'background' for our purposes, because it's not foreground.
9840            return mProcessState >= PROCESS_STATE_BACKGROUND;
9841        }
9842
9843        public boolean updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs) {
9844            boolean on = mBsi.mOnBatteryTimeBase.isRunning() && isInBackground();
9845            return mOnBatteryBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
9846        }
9847
9848        public boolean updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs) {
9849            boolean on = mBsi.mOnBatteryScreenOffTimeBase.isRunning() && isInBackground();
9850            return mOnBatteryScreenOffBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
9851        }
9852
9853        public SparseArray<? extends Pid> getPidStats() {
9854            return mPids;
9855        }
9856
9857        public Pid getPidStatsLocked(int pid) {
9858            Pid p = mPids.get(pid);
9859            if (p == null) {
9860                p = new Pid();
9861                mPids.put(pid, p);
9862            }
9863            return p;
9864        }
9865
9866        /**
9867         * Retrieve the statistics object for a particular service, creating
9868         * if needed.
9869         */
9870        public Pkg getPackageStatsLocked(String name) {
9871            Pkg ps = mPackageStats.get(name);
9872            if (ps == null) {
9873                ps = new Pkg(mBsi);
9874                mPackageStats.put(name, ps);
9875            }
9876
9877            return ps;
9878        }
9879
9880        /**
9881         * Retrieve the statistics object for a particular service, creating
9882         * if needed.
9883         */
9884        public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
9885            Pkg ps = getPackageStatsLocked(pkg);
9886            Pkg.Serv ss = ps.mServiceStats.get(serv);
9887            if (ss == null) {
9888                ss = ps.newServiceStatsLocked();
9889                ps.mServiceStats.put(serv, ss);
9890            }
9891
9892            return ss;
9893        }
9894
9895        public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
9896            DualTimer timer = mSyncStats.instantiateObject();
9897            timer.readSummaryFromParcelLocked(in);
9898            mSyncStats.add(name, timer);
9899        }
9900
9901        public void readJobSummaryFromParcelLocked(String name, Parcel in) {
9902            DualTimer timer = mJobStats.instantiateObject();
9903            timer.readSummaryFromParcelLocked(in);
9904            mJobStats.add(name, timer);
9905        }
9906
9907        public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
9908            Wakelock wl = new Wakelock(mBsi, this);
9909            mWakelockStats.add(wlName, wl);
9910            if (in.readInt() != 0) {
9911                getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
9912            }
9913            if (in.readInt() != 0) {
9914                getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
9915            }
9916            if (in.readInt() != 0) {
9917                getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
9918            }
9919            if (in.readInt() != 0) {
9920                getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
9921            }
9922        }
9923
9924        public DualTimer getSensorTimerLocked(int sensor, boolean create) {
9925            Sensor se = mSensorStats.get(sensor);
9926            if (se == null) {
9927                if (!create) {
9928                    return null;
9929                }
9930                se = new Sensor(mBsi, this, sensor);
9931                mSensorStats.put(sensor, se);
9932            }
9933            DualTimer t = se.mTimer;
9934            if (t != null) {
9935                return t;
9936            }
9937            ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
9938            if (timers == null) {
9939                timers = new ArrayList<StopwatchTimer>();
9940                mBsi.mSensorTimers.put(sensor, timers);
9941            }
9942            t = new DualTimer(mBsi.mClocks, this, BatteryStats.SENSOR, timers,
9943                    mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
9944            se.mTimer = t;
9945            return t;
9946        }
9947
9948        public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
9949            DualTimer t = mSyncStats.startObject(name);
9950            if (t != null) {
9951                t.startRunningLocked(elapsedRealtimeMs);
9952            }
9953        }
9954
9955        public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
9956            DualTimer t = mSyncStats.stopObject(name);
9957            if (t != null) {
9958                t.stopRunningLocked(elapsedRealtimeMs);
9959            }
9960        }
9961
9962        public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
9963            DualTimer t = mJobStats.startObject(name);
9964            if (t != null) {
9965                t.startRunningLocked(elapsedRealtimeMs);
9966            }
9967        }
9968
9969        public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
9970            DualTimer t = mJobStats.stopObject(name);
9971            if (t != null) {
9972                t.stopRunningLocked(elapsedRealtimeMs);
9973            }
9974            if (mBsi.mOnBatteryTimeBase.isRunning()) {
9975                SparseIntArray types = mJobCompletions.get(name);
9976                if (types == null) {
9977                    types = new SparseIntArray();
9978                    mJobCompletions.put(name, types);
9979                }
9980                int last = types.get(stopReason, 0);
9981                types.put(stopReason, last + 1);
9982            }
9983        }
9984
9985        public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
9986            if (wl == null) {
9987                return null;
9988            }
9989            switch (type) {
9990                case WAKE_TYPE_PARTIAL: {
9991                    DualTimer t = wl.mTimerPartial;
9992                    if (t == null) {
9993                        t = new DualTimer(mBsi.mClocks, this, WAKE_TYPE_PARTIAL,
9994                                mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase,
9995                                mOnBatteryScreenOffBackgroundTimeBase);
9996                        wl.mTimerPartial = t;
9997                    }
9998                    return t;
9999                }
10000                case WAKE_TYPE_FULL: {
10001                    StopwatchTimer t = wl.mTimerFull;
10002                    if (t == null) {
10003                        t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_FULL,
10004                                mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
10005                        wl.mTimerFull = t;
10006                    }
10007                    return t;
10008                }
10009                case WAKE_TYPE_WINDOW: {
10010                    StopwatchTimer t = wl.mTimerWindow;
10011                    if (t == null) {
10012                        t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_WINDOW,
10013                                mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
10014                        wl.mTimerWindow = t;
10015                    }
10016                    return t;
10017                }
10018                case WAKE_TYPE_DRAW: {
10019                    StopwatchTimer t = wl.mTimerDraw;
10020                    if (t == null) {
10021                        t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_DRAW,
10022                                mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
10023                        wl.mTimerDraw = t;
10024                    }
10025                    return t;
10026                }
10027                default:
10028                    throw new IllegalArgumentException("type=" + type);
10029            }
10030        }
10031
10032        public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
10033            Wakelock wl = mWakelockStats.startObject(name);
10034            if (wl != null) {
10035                getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
10036            }
10037            if (type == WAKE_TYPE_PARTIAL) {
10038                createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
10039                if (pid >= 0) {
10040                    Pid p = getPidStatsLocked(pid);
10041                    if (p.mWakeNesting++ == 0) {
10042                        p.mWakeStartMs = elapsedRealtimeMs;
10043                    }
10044                }
10045            }
10046        }
10047
10048        public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
10049            Wakelock wl = mWakelockStats.stopObject(name);
10050            if (wl != null) {
10051                StopwatchTimer wlt = getWakelockTimerLocked(wl, type);
10052                wlt.stopRunningLocked(elapsedRealtimeMs);
10053            }
10054            if (type == WAKE_TYPE_PARTIAL) {
10055                if (mAggregatedPartialWakelockTimer != null) {
10056                    mAggregatedPartialWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
10057                }
10058                if (pid >= 0) {
10059                    Pid p = mPids.get(pid);
10060                    if (p != null && p.mWakeNesting > 0) {
10061                        if (p.mWakeNesting-- == 1) {
10062                            p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
10063                            p.mWakeStartMs = 0;
10064                        }
10065                    }
10066                }
10067            }
10068        }
10069
10070        public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
10071            Proc p = getProcessStatsLocked(proc);
10072            if (p != null) {
10073                p.addExcessiveCpu(overTime, usedTime);
10074            }
10075        }
10076
10077        public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
10078            DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
10079            t.startRunningLocked(elapsedRealtimeMs);
10080        }
10081
10082        public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
10083            // Don't create a timer if one doesn't already exist
10084            DualTimer t = getSensorTimerLocked(sensor, false);
10085            if (t != null) {
10086                t.stopRunningLocked(elapsedRealtimeMs);
10087            }
10088        }
10089
10090        public void noteStartGps(long elapsedRealtimeMs) {
10091            noteStartSensor(Sensor.GPS, elapsedRealtimeMs);
10092        }
10093
10094        public void noteStopGps(long elapsedRealtimeMs) {
10095            noteStopSensor(Sensor.GPS, elapsedRealtimeMs);
10096        }
10097
10098        public BatteryStatsImpl getBatteryStats() {
10099            return mBsi;
10100        }
10101    }
10102
10103    public long[] getCpuFreqs() {
10104        return mCpuFreqs;
10105    }
10106
10107    public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
10108            UserInfoProvider userInfoProvider) {
10109        this(new SystemClocks(), systemDir, handler, cb, userInfoProvider);
10110    }
10111
10112    private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
10113            PlatformIdleStateCallback cb,
10114            UserInfoProvider userInfoProvider) {
10115        init(clocks);
10116
10117        if (systemDir != null) {
10118            mFile = new JournaledFile(new File(systemDir, "batterystats.bin"),
10119                    new File(systemDir, "batterystats.bin.tmp"));
10120        } else {
10121            mFile = null;
10122        }
10123        mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
10124        mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
10125        mHandler = new MyHandler(handler.getLooper());
10126        mConstants = new Constants(mHandler);
10127        mStartCount++;
10128        mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
10129        mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
10130        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10131            mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
10132                    mOnBatteryTimeBase);
10133        }
10134        mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase);
10135        mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
10136                mOnBatteryTimeBase);
10137        mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -11, null,
10138                mOnBatteryTimeBase);
10139        mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
10140        mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null, mOnBatteryTimeBase);
10141        mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase);
10142        mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase);
10143        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
10144            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i, null,
10145                    mOnBatteryTimeBase);
10146        }
10147        mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
10148                mOnBatteryTimeBase);
10149        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10150            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i, null,
10151                    mOnBatteryTimeBase);
10152        }
10153        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10154            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
10155            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
10156        }
10157        mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
10158        mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
10159                NUM_BT_TX_LEVELS);
10160        mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
10161                ModemActivityInfo.TX_POWER_LEVELS);
10162        mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase);
10163        mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
10164                mOnBatteryTimeBase);
10165        mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
10166        mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
10167        mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
10168        mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null,
10169                WIFI_AGGREGATE_MULTICAST_ENABLED, null, mOnBatteryTimeBase);
10170        mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase);
10171        mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null, mOnBatteryTimeBase);
10172        for (int i=0; i<NUM_WIFI_STATES; i++) {
10173            mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i, null,
10174                    mOnBatteryTimeBase);
10175        }
10176        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10177            mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i, null,
10178                    mOnBatteryTimeBase);
10179        }
10180        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10181            mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
10182                    mOnBatteryTimeBase);
10183        }
10184        mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null, mOnBatteryTimeBase);
10185        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
10186            mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i, null,
10187                mOnBatteryTimeBase);
10188        }
10189        mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
10190        mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
10191        mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
10192        mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase);
10193        mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
10194        mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
10195        mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10196        mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10197        mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10198        mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
10199        mOnBattery = mOnBatteryInternal = false;
10200        long uptime = mClocks.uptimeMillis() * 1000;
10201        long realtime = mClocks.elapsedRealtime() * 1000;
10202        initTimes(uptime, realtime);
10203        mStartPlatformVersion = mEndPlatformVersion = Build.ID;
10204        mDischargeStartLevel = 0;
10205        mDischargeUnplugLevel = 0;
10206        mDischargePlugLevel = -1;
10207        mDischargeCurrentLevel = 0;
10208        mCurrentBatteryLevel = 0;
10209        initDischarge();
10210        clearHistoryLocked();
10211        updateDailyDeadlineLocked();
10212        mPlatformIdleStateCallback = cb;
10213        mUserInfoProvider = userInfoProvider;
10214    }
10215
10216    public BatteryStatsImpl(Parcel p) {
10217        this(new SystemClocks(), p);
10218    }
10219
10220    public BatteryStatsImpl(Clocks clocks, Parcel p) {
10221        init(clocks);
10222        mFile = null;
10223        mCheckinFile = null;
10224        mDailyFile = null;
10225        mHandler = null;
10226        mExternalSync = null;
10227        mConstants = new Constants(mHandler);
10228        clearHistoryLocked();
10229        readFromParcel(p);
10230        mPlatformIdleStateCallback = null;
10231    }
10232
10233    public void setPowerProfileLocked(PowerProfile profile) {
10234        mPowerProfile = profile;
10235
10236        // We need to initialize the KernelCpuSpeedReaders to read from
10237        // the first cpu of each core. Once we have the PowerProfile, we have access to this
10238        // information.
10239        final int numClusters = mPowerProfile.getNumCpuClusters();
10240        mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
10241        int firstCpuOfCluster = 0;
10242        for (int i = 0; i < numClusters; i++) {
10243            final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
10244            mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
10245                    numSpeedSteps);
10246            firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
10247        }
10248
10249        if (mEstimatedBatteryCapacity == -1) {
10250            // Initialize the estimated battery capacity to a known preset one.
10251            mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
10252        }
10253    }
10254
10255    public void setCallback(BatteryCallback cb) {
10256        mCallback = cb;
10257    }
10258
10259    public void setRadioScanningTimeoutLocked(long timeout) {
10260        if (mPhoneSignalScanningTimer != null) {
10261            mPhoneSignalScanningTimer.setTimeout(timeout);
10262        }
10263    }
10264
10265    public void setExternalStatsSyncLocked(ExternalStatsSync sync) {
10266        mExternalSync = sync;
10267    }
10268
10269    public void updateDailyDeadlineLocked() {
10270        // Get the current time.
10271        long currentTime = mDailyStartTime = System.currentTimeMillis();
10272        Calendar calDeadline = Calendar.getInstance();
10273        calDeadline.setTimeInMillis(currentTime);
10274
10275        // Move time up to the next day, ranging from 1am to 3pm.
10276        calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
10277        calDeadline.set(Calendar.MILLISECOND, 0);
10278        calDeadline.set(Calendar.SECOND, 0);
10279        calDeadline.set(Calendar.MINUTE, 0);
10280        calDeadline.set(Calendar.HOUR_OF_DAY, 1);
10281        mNextMinDailyDeadline = calDeadline.getTimeInMillis();
10282        calDeadline.set(Calendar.HOUR_OF_DAY, 3);
10283        mNextMaxDailyDeadline = calDeadline.getTimeInMillis();
10284    }
10285
10286    public void recordDailyStatsIfNeededLocked(boolean settled) {
10287        long currentTime = System.currentTimeMillis();
10288        if (currentTime >= mNextMaxDailyDeadline) {
10289            recordDailyStatsLocked();
10290        } else if (settled && currentTime >= mNextMinDailyDeadline) {
10291            recordDailyStatsLocked();
10292        } else if (currentTime < (mDailyStartTime-(1000*60*60*24))) {
10293            recordDailyStatsLocked();
10294        }
10295    }
10296
10297    public void recordDailyStatsLocked() {
10298        DailyItem item = new DailyItem();
10299        item.mStartTime = mDailyStartTime;
10300        item.mEndTime = System.currentTimeMillis();
10301        boolean hasData = false;
10302        if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
10303            hasData = true;
10304            item.mDischargeSteps = new LevelStepTracker(
10305                    mDailyDischargeStepTracker.mNumStepDurations,
10306                    mDailyDischargeStepTracker.mStepDurations);
10307        }
10308        if (mDailyChargeStepTracker.mNumStepDurations > 0) {
10309            hasData = true;
10310            item.mChargeSteps = new LevelStepTracker(
10311                    mDailyChargeStepTracker.mNumStepDurations,
10312                    mDailyChargeStepTracker.mStepDurations);
10313        }
10314        if (mDailyPackageChanges != null) {
10315            hasData = true;
10316            item.mPackageChanges = mDailyPackageChanges;
10317            mDailyPackageChanges = null;
10318        }
10319        mDailyDischargeStepTracker.init();
10320        mDailyChargeStepTracker.init();
10321        updateDailyDeadlineLocked();
10322
10323        if (hasData) {
10324            final long startTime = SystemClock.uptimeMillis();
10325            mDailyItems.add(item);
10326            while (mDailyItems.size() > MAX_DAILY_ITEMS) {
10327                mDailyItems.remove(0);
10328            }
10329            final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
10330            try {
10331                XmlSerializer out = new FastXmlSerializer();
10332                out.setOutput(memStream, StandardCharsets.UTF_8.name());
10333                writeDailyItemsLocked(out);
10334                final long initialTime = SystemClock.uptimeMillis() - startTime;
10335                BackgroundThread.getHandler().post(new Runnable() {
10336                    @Override
10337                    public void run() {
10338                        synchronized (mCheckinFile) {
10339                            final long startTime2 = SystemClock.uptimeMillis();
10340                            FileOutputStream stream = null;
10341                            try {
10342                                stream = mDailyFile.startWrite();
10343                                memStream.writeTo(stream);
10344                                stream.flush();
10345                                FileUtils.sync(stream);
10346                                stream.close();
10347                                mDailyFile.finishWrite(stream);
10348                                com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
10349                                        "batterystats-daily",
10350                                        initialTime + SystemClock.uptimeMillis() - startTime2);
10351                            } catch (IOException e) {
10352                                Slog.w("BatteryStats",
10353                                        "Error writing battery daily items", e);
10354                                mDailyFile.failWrite(stream);
10355                            }
10356                        }
10357                    }
10358                });
10359            } catch (IOException e) {
10360            }
10361        }
10362    }
10363
10364    private void writeDailyItemsLocked(XmlSerializer out) throws IOException {
10365        StringBuilder sb = new StringBuilder(64);
10366        out.startDocument(null, true);
10367        out.startTag(null, "daily-items");
10368        for (int i=0; i<mDailyItems.size(); i++) {
10369            final DailyItem dit = mDailyItems.get(i);
10370            out.startTag(null, "item");
10371            out.attribute(null, "start", Long.toString(dit.mStartTime));
10372            out.attribute(null, "end", Long.toString(dit.mEndTime));
10373            writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
10374            writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
10375            if (dit.mPackageChanges != null) {
10376                for (int j=0; j<dit.mPackageChanges.size(); j++) {
10377                    PackageChange pc = dit.mPackageChanges.get(j);
10378                    if (pc.mUpdate) {
10379                        out.startTag(null, "upd");
10380                        out.attribute(null, "pkg", pc.mPackageName);
10381                        out.attribute(null, "ver", Long.toString(pc.mVersionCode));
10382                        out.endTag(null, "upd");
10383                    } else {
10384                        out.startTag(null, "rem");
10385                        out.attribute(null, "pkg", pc.mPackageName);
10386                        out.endTag(null, "rem");
10387                    }
10388                }
10389            }
10390            out.endTag(null, "item");
10391        }
10392        out.endTag(null, "daily-items");
10393        out.endDocument();
10394    }
10395
10396    private void writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps,
10397            StringBuilder tmpBuilder) throws IOException {
10398        if (steps != null) {
10399            out.startTag(null, tag);
10400            out.attribute(null, "n", Integer.toString(steps.mNumStepDurations));
10401            for (int i=0; i<steps.mNumStepDurations; i++) {
10402                out.startTag(null, "s");
10403                tmpBuilder.setLength(0);
10404                steps.encodeEntryAt(i, tmpBuilder);
10405                out.attribute(null, "v", tmpBuilder.toString());
10406                out.endTag(null, "s");
10407            }
10408            out.endTag(null, tag);
10409        }
10410    }
10411
10412    public void readDailyStatsLocked() {
10413        Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
10414        mDailyItems.clear();
10415        FileInputStream stream;
10416        try {
10417            stream = mDailyFile.openRead();
10418        } catch (FileNotFoundException e) {
10419            return;
10420        }
10421        try {
10422            XmlPullParser parser = Xml.newPullParser();
10423            parser.setInput(stream, StandardCharsets.UTF_8.name());
10424            readDailyItemsLocked(parser);
10425        } catch (XmlPullParserException e) {
10426        } finally {
10427            try {
10428                stream.close();
10429            } catch (IOException e) {
10430            }
10431        }
10432    }
10433
10434    private void readDailyItemsLocked(XmlPullParser parser) {
10435        try {
10436            int type;
10437            while ((type = parser.next()) != XmlPullParser.START_TAG
10438                    && type != XmlPullParser.END_DOCUMENT) {
10439                ;
10440            }
10441
10442            if (type != XmlPullParser.START_TAG) {
10443                throw new IllegalStateException("no start tag found");
10444            }
10445
10446            int outerDepth = parser.getDepth();
10447            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10448                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10449                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10450                    continue;
10451                }
10452
10453                String tagName = parser.getName();
10454                if (tagName.equals("item")) {
10455                    readDailyItemTagLocked(parser);
10456                } else {
10457                    Slog.w(TAG, "Unknown element under <daily-items>: "
10458                            + parser.getName());
10459                    XmlUtils.skipCurrentTag(parser);
10460                }
10461            }
10462
10463        } catch (IllegalStateException e) {
10464            Slog.w(TAG, "Failed parsing daily " + e);
10465        } catch (NullPointerException e) {
10466            Slog.w(TAG, "Failed parsing daily " + e);
10467        } catch (NumberFormatException e) {
10468            Slog.w(TAG, "Failed parsing daily " + e);
10469        } catch (XmlPullParserException e) {
10470            Slog.w(TAG, "Failed parsing daily " + e);
10471        } catch (IOException e) {
10472            Slog.w(TAG, "Failed parsing daily " + e);
10473        } catch (IndexOutOfBoundsException e) {
10474            Slog.w(TAG, "Failed parsing daily " + e);
10475        }
10476    }
10477
10478    void readDailyItemTagLocked(XmlPullParser parser) throws NumberFormatException,
10479            XmlPullParserException, IOException {
10480        DailyItem dit = new DailyItem();
10481        String attr = parser.getAttributeValue(null, "start");
10482        if (attr != null) {
10483            dit.mStartTime = Long.parseLong(attr);
10484        }
10485        attr = parser.getAttributeValue(null, "end");
10486        if (attr != null) {
10487            dit.mEndTime = Long.parseLong(attr);
10488        }
10489        int outerDepth = parser.getDepth();
10490        int type;
10491        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10492                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10493            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10494                continue;
10495            }
10496
10497            String tagName = parser.getName();
10498            if (tagName.equals("dis")) {
10499                readDailyItemTagDetailsLocked(parser, dit, false, "dis");
10500            } else if (tagName.equals("chg")) {
10501                readDailyItemTagDetailsLocked(parser, dit, true, "chg");
10502            } else if (tagName.equals("upd")) {
10503                if (dit.mPackageChanges == null) {
10504                    dit.mPackageChanges = new ArrayList<>();
10505                }
10506                PackageChange pc = new PackageChange();
10507                pc.mUpdate = true;
10508                pc.mPackageName = parser.getAttributeValue(null, "pkg");
10509                String verStr = parser.getAttributeValue(null, "ver");
10510                pc.mVersionCode = verStr != null ? Long.parseLong(verStr) : 0;
10511                dit.mPackageChanges.add(pc);
10512                XmlUtils.skipCurrentTag(parser);
10513            } else if (tagName.equals("rem")) {
10514                if (dit.mPackageChanges == null) {
10515                    dit.mPackageChanges = new ArrayList<>();
10516                }
10517                PackageChange pc = new PackageChange();
10518                pc.mUpdate = false;
10519                pc.mPackageName = parser.getAttributeValue(null, "pkg");
10520                dit.mPackageChanges.add(pc);
10521                XmlUtils.skipCurrentTag(parser);
10522            } else {
10523                Slog.w(TAG, "Unknown element under <item>: "
10524                        + parser.getName());
10525                XmlUtils.skipCurrentTag(parser);
10526            }
10527        }
10528        mDailyItems.add(dit);
10529    }
10530
10531    void readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge,
10532            String tag)
10533            throws NumberFormatException, XmlPullParserException, IOException {
10534        final String numAttr = parser.getAttributeValue(null, "n");
10535        if (numAttr == null) {
10536            Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
10537            XmlUtils.skipCurrentTag(parser);
10538            return;
10539        }
10540        final int num = Integer.parseInt(numAttr);
10541        LevelStepTracker steps = new LevelStepTracker(num);
10542        if (isCharge) {
10543            dit.mChargeSteps = steps;
10544        } else {
10545            dit.mDischargeSteps = steps;
10546        }
10547        int i = 0;
10548        int outerDepth = parser.getDepth();
10549        int type;
10550        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
10551                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
10552            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
10553                continue;
10554            }
10555
10556            String tagName = parser.getName();
10557            if ("s".equals(tagName)) {
10558                if (i < num) {
10559                    String valueAttr = parser.getAttributeValue(null, "v");
10560                    if (valueAttr != null) {
10561                        steps.decodeEntryAt(i, valueAttr);
10562                        i++;
10563                    }
10564                }
10565            } else {
10566                Slog.w(TAG, "Unknown element under <" + tag + ">: "
10567                        + parser.getName());
10568                XmlUtils.skipCurrentTag(parser);
10569            }
10570        }
10571        steps.mNumStepDurations = i;
10572    }
10573
10574    @Override
10575    public DailyItem getDailyItemLocked(int daysAgo) {
10576        int index = mDailyItems.size()-1-daysAgo;
10577        return index >= 0 ? mDailyItems.get(index) : null;
10578    }
10579
10580    @Override
10581    public long getCurrentDailyStartTime() {
10582        return mDailyStartTime;
10583    }
10584
10585    @Override
10586    public long getNextMinDailyDeadline() {
10587        return mNextMinDailyDeadline;
10588    }
10589
10590    @Override
10591    public long getNextMaxDailyDeadline() {
10592        return mNextMaxDailyDeadline;
10593    }
10594
10595    @Override
10596    public boolean startIteratingOldHistoryLocked() {
10597        if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
10598                + " pos=" + mHistoryBuffer.dataPosition());
10599        if ((mHistoryIterator = mHistory) == null) {
10600            return false;
10601        }
10602        mHistoryBuffer.setDataPosition(0);
10603        mHistoryReadTmp.clear();
10604        mReadOverflow = false;
10605        mIteratingHistory = true;
10606        return true;
10607    }
10608
10609    @Override
10610    public boolean getNextOldHistoryLocked(HistoryItem out) {
10611        boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
10612        if (!end) {
10613            readHistoryDelta(mHistoryBuffer, mHistoryReadTmp);
10614            mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
10615        }
10616        HistoryItem cur = mHistoryIterator;
10617        if (cur == null) {
10618            if (!mReadOverflow && !end) {
10619                Slog.w(TAG, "Old history ends before new history!");
10620            }
10621            return false;
10622        }
10623        out.setTo(cur);
10624        mHistoryIterator = cur.next;
10625        if (!mReadOverflow) {
10626            if (end) {
10627                Slog.w(TAG, "New history ends before old history!");
10628            } else if (!out.same(mHistoryReadTmp)) {
10629                PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
10630                pw.println("Histories differ!");
10631                pw.println("Old history:");
10632                (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
10633                pw.println("New history:");
10634                (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
10635                        true);
10636                pw.flush();
10637            }
10638        }
10639        return true;
10640    }
10641
10642    @Override
10643    public void finishIteratingOldHistoryLocked() {
10644        mIteratingHistory = false;
10645        mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
10646        mHistoryIterator = null;
10647    }
10648
10649    public int getHistoryTotalSize() {
10650        return MAX_HISTORY_BUFFER;
10651    }
10652
10653    public int getHistoryUsedSize() {
10654        return mHistoryBuffer.dataSize();
10655    }
10656
10657    @Override
10658    public boolean startIteratingHistoryLocked() {
10659        if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
10660                + " pos=" + mHistoryBuffer.dataPosition());
10661        if (mHistoryBuffer.dataSize() <= 0) {
10662            return false;
10663        }
10664        mHistoryBuffer.setDataPosition(0);
10665        mReadOverflow = false;
10666        mIteratingHistory = true;
10667        mReadHistoryStrings = new String[mHistoryTagPool.size()];
10668        mReadHistoryUids = new int[mHistoryTagPool.size()];
10669        mReadHistoryChars = 0;
10670        for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
10671            final HistoryTag tag = ent.getKey();
10672            final int idx = ent.getValue();
10673            mReadHistoryStrings[idx] = tag.string;
10674            mReadHistoryUids[idx] = tag.uid;
10675            mReadHistoryChars += tag.string.length() + 1;
10676        }
10677        return true;
10678    }
10679
10680    @Override
10681    public int getHistoryStringPoolSize() {
10682        return mReadHistoryStrings.length;
10683    }
10684
10685    @Override
10686    public int getHistoryStringPoolBytes() {
10687        // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
10688        // Each string character is 2 bytes.
10689        return (mReadHistoryStrings.length * 12) + (mReadHistoryChars * 2);
10690    }
10691
10692    @Override
10693    public String getHistoryTagPoolString(int index) {
10694        return mReadHistoryStrings[index];
10695    }
10696
10697    @Override
10698    public int getHistoryTagPoolUid(int index) {
10699        return mReadHistoryUids[index];
10700    }
10701
10702    @Override
10703    public boolean getNextHistoryLocked(HistoryItem out) {
10704        final int pos = mHistoryBuffer.dataPosition();
10705        if (pos == 0) {
10706            out.clear();
10707        }
10708        boolean end = pos >= mHistoryBuffer.dataSize();
10709        if (end) {
10710            return false;
10711        }
10712
10713        final long lastRealtime = out.time;
10714        final long lastWalltime = out.currentTime;
10715        readHistoryDelta(mHistoryBuffer, out);
10716        if (out.cmd != HistoryItem.CMD_CURRENT_TIME
10717                && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
10718            out.currentTime = lastWalltime + (out.time - lastRealtime);
10719        }
10720        return true;
10721    }
10722
10723    @Override
10724    public void finishIteratingHistoryLocked() {
10725        mIteratingHistory = false;
10726        mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
10727        mReadHistoryStrings = null;
10728    }
10729
10730    @Override
10731    public long getHistoryBaseTime() {
10732        return mHistoryBaseTime;
10733    }
10734
10735    @Override
10736    public int getStartCount() {
10737        return mStartCount;
10738    }
10739
10740    public boolean isOnBattery() {
10741        return mOnBattery;
10742    }
10743
10744    public boolean isCharging() {
10745        return mCharging;
10746    }
10747
10748    public boolean isScreenOn(int state) {
10749        return state == Display.STATE_ON || state == Display.STATE_VR
10750            || state == Display.STATE_ON_SUSPEND;
10751    }
10752
10753    public boolean isScreenOff(int state) {
10754        return state == Display.STATE_OFF;
10755    }
10756
10757    public boolean isScreenDoze(int state) {
10758        return state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND;
10759    }
10760
10761    void initTimes(long uptime, long realtime) {
10762        mStartClockTime = System.currentTimeMillis();
10763        mOnBatteryTimeBase.init(uptime, realtime);
10764        mOnBatteryScreenOffTimeBase.init(uptime, realtime);
10765        mRealtime = 0;
10766        mUptime = 0;
10767        mRealtimeStart = realtime;
10768        mUptimeStart = uptime;
10769    }
10770
10771    void initDischarge() {
10772        mLowDischargeAmountSinceCharge = 0;
10773        mHighDischargeAmountSinceCharge = 0;
10774        mDischargeAmountScreenOn = 0;
10775        mDischargeAmountScreenOnSinceCharge = 0;
10776        mDischargeAmountScreenOff = 0;
10777        mDischargeAmountScreenOffSinceCharge = 0;
10778        mDischargeAmountScreenDoze = 0;
10779        mDischargeAmountScreenDozeSinceCharge = 0;
10780        mDischargeStepTracker.init();
10781        mChargeStepTracker.init();
10782        mDischargeScreenOffCounter.reset(false);
10783        mDischargeScreenDozeCounter.reset(false);
10784        mDischargeLightDozeCounter.reset(false);
10785        mDischargeDeepDozeCounter.reset(false);
10786        mDischargeCounter.reset(false);
10787    }
10788
10789    public void resetAllStatsCmdLocked() {
10790        resetAllStatsLocked();
10791        final long mSecUptime = mClocks.uptimeMillis();
10792        long uptime = mSecUptime * 1000;
10793        long mSecRealtime = mClocks.elapsedRealtime();
10794        long realtime = mSecRealtime * 1000;
10795        mDischargeStartLevel = mHistoryCur.batteryLevel;
10796        pullPendingStateUpdatesLocked();
10797        addHistoryRecordLocked(mSecRealtime, mSecUptime);
10798        mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
10799                = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
10800        mOnBatteryTimeBase.reset(uptime, realtime);
10801        mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
10802        if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
10803            if (isScreenOn(mScreenState)) {
10804                mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
10805                mDischargeScreenDozeUnplugLevel = 0;
10806                mDischargeScreenOffUnplugLevel = 0;
10807            } else if (isScreenDoze(mScreenState)) {
10808                mDischargeScreenOnUnplugLevel = 0;
10809                mDischargeScreenDozeUnplugLevel = mHistoryCur.batteryLevel;
10810                mDischargeScreenOffUnplugLevel = 0;
10811            } else {
10812                mDischargeScreenOnUnplugLevel = 0;
10813                mDischargeScreenDozeUnplugLevel = 0;
10814                mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
10815            }
10816            mDischargeAmountScreenOn = 0;
10817            mDischargeAmountScreenOff = 0;
10818            mDischargeAmountScreenDoze = 0;
10819        }
10820        initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
10821    }
10822
10823    private void resetAllStatsLocked() {
10824        final long uptimeMillis = mClocks.uptimeMillis();
10825        final long elapsedRealtimeMillis = mClocks.elapsedRealtime();
10826        mStartCount = 0;
10827        initTimes(uptimeMillis * 1000, elapsedRealtimeMillis * 1000);
10828        mScreenOnTimer.reset(false);
10829        mScreenDozeTimer.reset(false);
10830        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10831            mScreenBrightnessTimer[i].reset(false);
10832        }
10833
10834        if (mPowerProfile != null) {
10835            mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
10836        } else {
10837            mEstimatedBatteryCapacity = -1;
10838        }
10839        mMinLearnedBatteryCapacity = -1;
10840        mMaxLearnedBatteryCapacity = -1;
10841        mInteractiveTimer.reset(false);
10842        mPowerSaveModeEnabledTimer.reset(false);
10843        mLastIdleTimeStart = elapsedRealtimeMillis;
10844        mLongestLightIdleTime = 0;
10845        mLongestFullIdleTime = 0;
10846        mDeviceIdleModeLightTimer.reset(false);
10847        mDeviceIdleModeFullTimer.reset(false);
10848        mDeviceLightIdlingTimer.reset(false);
10849        mDeviceIdlingTimer.reset(false);
10850        mPhoneOnTimer.reset(false);
10851        mAudioOnTimer.reset(false);
10852        mVideoOnTimer.reset(false);
10853        mFlashlightOnTimer.reset(false);
10854        mCameraOnTimer.reset(false);
10855        mBluetoothScanTimer.reset(false);
10856        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
10857            mPhoneSignalStrengthsTimer[i].reset(false);
10858        }
10859        mPhoneSignalScanningTimer.reset(false);
10860        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10861            mPhoneDataConnectionsTimer[i].reset(false);
10862        }
10863        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10864            mNetworkByteActivityCounters[i].reset(false);
10865            mNetworkPacketActivityCounters[i].reset(false);
10866        }
10867        mMobileRadioActiveTimer.reset(false);
10868        mMobileRadioActivePerAppTimer.reset(false);
10869        mMobileRadioActiveAdjustedTime.reset(false);
10870        mMobileRadioActiveUnknownTime.reset(false);
10871        mMobileRadioActiveUnknownCount.reset(false);
10872        mWifiOnTimer.reset(false);
10873        mGlobalWifiRunningTimer.reset(false);
10874        for (int i=0; i<NUM_WIFI_STATES; i++) {
10875            mWifiStateTimer[i].reset(false);
10876        }
10877        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10878            mWifiSupplStateTimer[i].reset(false);
10879        }
10880        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10881            mWifiSignalStrengthsTimer[i].reset(false);
10882        }
10883        mWifiMulticastWakelockTimer.reset(false);
10884        mWifiActiveTimer.reset(false);
10885        mWifiActivity.reset(false);
10886        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
10887            mGpsSignalQualityTimer[i].reset(false);
10888        }
10889        mBluetoothActivity.reset(false);
10890        mModemActivity.reset(false);
10891        mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
10892
10893        for (int i=0; i<mUidStats.size(); i++) {
10894            if (mUidStats.valueAt(i).reset(uptimeMillis * 1000, elapsedRealtimeMillis * 1000)) {
10895                mUidStats.remove(mUidStats.keyAt(i));
10896                i--;
10897            }
10898        }
10899
10900        if (mRpmStats.size() > 0) {
10901            for (SamplingTimer timer : mRpmStats.values()) {
10902                mOnBatteryTimeBase.remove(timer);
10903            }
10904            mRpmStats.clear();
10905        }
10906        if (mScreenOffRpmStats.size() > 0) {
10907            for (SamplingTimer timer : mScreenOffRpmStats.values()) {
10908                mOnBatteryScreenOffTimeBase.remove(timer);
10909            }
10910            mScreenOffRpmStats.clear();
10911        }
10912
10913        if (mKernelWakelockStats.size() > 0) {
10914            for (SamplingTimer timer : mKernelWakelockStats.values()) {
10915                mOnBatteryScreenOffTimeBase.remove(timer);
10916            }
10917            mKernelWakelockStats.clear();
10918        }
10919
10920        if (mKernelMemoryStats.size() > 0) {
10921            for (int i = 0; i < mKernelMemoryStats.size(); i++) {
10922                mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i));
10923            }
10924            mKernelMemoryStats.clear();
10925        }
10926
10927        if (mWakeupReasonStats.size() > 0) {
10928            for (SamplingTimer timer : mWakeupReasonStats.values()) {
10929                mOnBatteryTimeBase.remove(timer);
10930            }
10931            mWakeupReasonStats.clear();
10932        }
10933
10934        mLastHistoryStepDetails = null;
10935        mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
10936        mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
10937        mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
10938        mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
10939        mLastStepStatUserTime = mCurStepStatUserTime = 0;
10940        mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
10941        mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
10942        mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
10943        mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
10944        mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
10945
10946        mNumAllUidCpuTimeReads = 0;
10947        mNumUidsRemoved = 0;
10948
10949        initDischarge();
10950
10951        clearHistoryLocked();
10952        mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
10953    }
10954
10955    private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
10956        for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
10957            if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
10958                // Not recording process starts/stops.
10959                continue;
10960            }
10961            HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
10962            if (active == null) {
10963                continue;
10964            }
10965            for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
10966                SparseIntArray uids = ent.getValue();
10967                for (int j=0; j<uids.size(); j++) {
10968                    addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
10969                            uids.keyAt(j));
10970                }
10971            }
10972        }
10973    }
10974
10975    void updateDischargeScreenLevelsLocked(int oldState, int newState) {
10976        updateOldDischargeScreenLevelLocked(oldState);
10977        updateNewDischargeScreenLevelLocked(newState);
10978    }
10979
10980    private void updateOldDischargeScreenLevelLocked(int state) {
10981        if (isScreenOn(state)) {
10982            int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
10983            if (diff > 0) {
10984                mDischargeAmountScreenOn += diff;
10985                mDischargeAmountScreenOnSinceCharge += diff;
10986            }
10987        } else if (isScreenDoze(state)) {
10988            int diff = mDischargeScreenDozeUnplugLevel - mDischargeCurrentLevel;
10989            if (diff > 0) {
10990                mDischargeAmountScreenDoze += diff;
10991                mDischargeAmountScreenDozeSinceCharge += diff;
10992            }
10993        } else if (isScreenOff(state)){
10994            int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
10995            if (diff > 0) {
10996                mDischargeAmountScreenOff += diff;
10997                mDischargeAmountScreenOffSinceCharge += diff;
10998            }
10999        }
11000    }
11001
11002    private void updateNewDischargeScreenLevelLocked(int state) {
11003        if (isScreenOn(state)) {
11004            mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
11005            mDischargeScreenOffUnplugLevel = 0;
11006            mDischargeScreenDozeUnplugLevel = 0;
11007        } else if (isScreenDoze(state)){
11008            mDischargeScreenOnUnplugLevel = 0;
11009            mDischargeScreenDozeUnplugLevel = mDischargeCurrentLevel;
11010            mDischargeScreenOffUnplugLevel = 0;
11011        } else if (isScreenOff(state)) {
11012            mDischargeScreenOnUnplugLevel = 0;
11013            mDischargeScreenDozeUnplugLevel = 0;
11014            mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
11015        }
11016    }
11017
11018    public void pullPendingStateUpdatesLocked() {
11019        if (mOnBatteryInternal) {
11020            updateDischargeScreenLevelsLocked(mScreenState, mScreenState);
11021        }
11022    }
11023
11024    private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
11025    private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6);
11026
11027    private final Object mWifiNetworkLock = new Object();
11028
11029    @GuardedBy("mWifiNetworkLock")
11030    private String[] mWifiIfaces = EmptyArray.STRING;
11031
11032    @GuardedBy("mWifiNetworkLock")
11033    private NetworkStats mLastWifiNetworkStats = new NetworkStats(0, -1);
11034
11035    private final Object mModemNetworkLock = new Object();
11036
11037    @GuardedBy("mModemNetworkLock")
11038    private String[] mModemIfaces = EmptyArray.STRING;
11039
11040    @GuardedBy("mModemNetworkLock")
11041    private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
11042
11043    private NetworkStats readNetworkStatsLocked(String[] ifaces) {
11044        try {
11045            if (!ArrayUtils.isEmpty(ifaces)) {
11046                return mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces,
11047                        NetworkStats.TAG_NONE, mNetworkStatsPool.acquire());
11048            }
11049        } catch (IOException e) {
11050            Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces));
11051        }
11052        return null;
11053    }
11054
11055   /**
11056     * Distribute WiFi energy info and network traffic to apps.
11057     * @param info The energy information from the WiFi controller.
11058     */
11059    public void updateWifiState(@Nullable final WifiActivityEnergyInfo info) {
11060        if (DEBUG_ENERGY) {
11061            Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
11062        }
11063
11064        // Grab a separate lock to acquire the network stats, which may do I/O.
11065        NetworkStats delta = null;
11066        synchronized (mWifiNetworkLock) {
11067            final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces);
11068            if (latestStats != null) {
11069                delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null,
11070                        mNetworkStatsPool.acquire());
11071                mNetworkStatsPool.release(mLastWifiNetworkStats);
11072                mLastWifiNetworkStats = latestStats;
11073            }
11074        }
11075
11076        synchronized (this) {
11077            if (!mOnBatteryInternal) {
11078                if (delta != null) {
11079                    mNetworkStatsPool.release(delta);
11080                }
11081                return;
11082            }
11083
11084            final long elapsedRealtimeMs = mClocks.elapsedRealtime();
11085            SparseLongArray rxPackets = new SparseLongArray();
11086            SparseLongArray txPackets = new SparseLongArray();
11087            long totalTxPackets = 0;
11088            long totalRxPackets = 0;
11089            if (delta != null) {
11090                NetworkStats.Entry entry = new NetworkStats.Entry();
11091                final int size = delta.size();
11092                for (int i = 0; i < size; i++) {
11093                    entry = delta.getValues(i, entry);
11094
11095                    if (DEBUG_ENERGY) {
11096                        Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
11097                                + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
11098                                + " txPackets=" + entry.txPackets);
11099                    }
11100
11101                    if (entry.rxBytes == 0 && entry.txBytes == 0) {
11102                        // Skip the lookup below since there is no work to do.
11103                        continue;
11104                    }
11105
11106                    final Uid u = getUidStatsLocked(mapUid(entry.uid));
11107                    if (entry.rxBytes != 0) {
11108                        u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
11109                                entry.rxPackets);
11110                        if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11111                            u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
11112                                    entry.rxPackets);
11113                        }
11114                        mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
11115                                entry.rxBytes);
11116                        mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
11117                                entry.rxPackets);
11118
11119                        rxPackets.put(u.getUid(), entry.rxPackets);
11120
11121                        // Sum the total number of packets so that the Rx Power can
11122                        // be evenly distributed amongst the apps.
11123                        totalRxPackets += entry.rxPackets;
11124                    }
11125
11126                    if (entry.txBytes != 0) {
11127                        u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
11128                                entry.txPackets);
11129                        if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11130                            u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
11131                                    entry.txPackets);
11132                        }
11133                        mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
11134                                entry.txBytes);
11135                        mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
11136                                entry.txPackets);
11137
11138                        txPackets.put(u.getUid(), entry.txPackets);
11139
11140                        // Sum the total number of packets so that the Tx Power can
11141                        // be evenly distributed amongst the apps.
11142                        totalTxPackets += entry.txPackets;
11143                    }
11144                }
11145                mNetworkStatsPool.release(delta);
11146                delta = null;
11147            }
11148
11149            if (info != null) {
11150                mHasWifiReporting = true;
11151
11152                // Measured in mAms
11153                final long txTimeMs = info.getControllerTxTimeMillis();
11154                final long rxTimeMs = info.getControllerRxTimeMillis();
11155                final long scanTimeMs = info.getControllerScanTimeMillis();
11156                final long idleTimeMs = info.getControllerIdleTimeMillis();
11157                final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
11158
11159                long leftOverRxTimeMs = rxTimeMs;
11160                long leftOverTxTimeMs = txTimeMs;
11161
11162                if (DEBUG_ENERGY) {
11163                    Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
11164                    Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
11165                    Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
11166                    Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
11167                    Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
11168                    Slog.d(TAG, "  Scan Time:  " + scanTimeMs + " ms");
11169                }
11170
11171                long totalWifiLockTimeMs = 0;
11172                long totalScanTimeMs = 0;
11173
11174                // On the first pass, collect some totals so that we can normalize power
11175                // calculations if we need to.
11176                final int uidStatsSize = mUidStats.size();
11177                for (int i = 0; i < uidStatsSize; i++) {
11178                    final Uid uid = mUidStats.valueAt(i);
11179
11180                    // Sum the total scan power for all apps.
11181                    totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
11182                            elapsedRealtimeMs * 1000) / 1000;
11183
11184                    // Sum the total time holding wifi lock for all apps.
11185                    totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
11186                            elapsedRealtimeMs * 1000) / 1000;
11187                }
11188
11189                if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
11190                    Slog.d(TAG,
11191                            "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
11192                                    + rxTimeMs + " ms). Normalizing scan time.");
11193                }
11194                if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
11195                    Slog.d(TAG,
11196                            "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
11197                                    + txTimeMs + " ms). Normalizing scan time.");
11198                }
11199
11200                // Actually assign and distribute power usage to apps.
11201                for (int i = 0; i < uidStatsSize; i++) {
11202                    final Uid uid = mUidStats.valueAt(i);
11203
11204                    long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
11205                            elapsedRealtimeMs * 1000) / 1000;
11206                    if (scanTimeSinceMarkMs > 0) {
11207                        // Set the new mark so that next time we get new data since this point.
11208                        uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
11209
11210                        long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
11211                        long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
11212
11213                        // Our total scan time is more than the reported Tx/Rx time.
11214                        // This is possible because the cost of a scan is approximate.
11215                        // Let's normalize the result so that we evenly blame each app
11216                        // scanning.
11217                        //
11218                        // This means that we may have apps that transmitted/received packets not be
11219                        // blamed for this, but this is fine as scans are relatively more expensive.
11220                        if (totalScanTimeMs > rxTimeMs) {
11221                            scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
11222                                    totalScanTimeMs;
11223                        }
11224                        if (totalScanTimeMs > txTimeMs) {
11225                            scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
11226                                    totalScanTimeMs;
11227                        }
11228
11229                        if (DEBUG_ENERGY) {
11230                            Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
11231                                    + scanRxTimeSinceMarkMs + " ms  Tx:"
11232                                    + scanTxTimeSinceMarkMs + " ms)");
11233                        }
11234
11235                        ControllerActivityCounterImpl activityCounter =
11236                                uid.getOrCreateWifiControllerActivityLocked();
11237                        activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
11238                        activityCounter.getTxTimeCounters()[0].addCountLocked(
11239                                scanTxTimeSinceMarkMs);
11240                        leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
11241                        leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
11242                    }
11243
11244                    // Distribute evenly the power consumed while Idle to each app holding a WiFi
11245                    // lock.
11246                    final long wifiLockTimeSinceMarkMs =
11247                            uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
11248                                    elapsedRealtimeMs * 1000) / 1000;
11249                    if (wifiLockTimeSinceMarkMs > 0) {
11250                        // Set the new mark so that next time we get new data since this point.
11251                        uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
11252
11253                        final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
11254                                / totalWifiLockTimeMs;
11255                        if (DEBUG_ENERGY) {
11256                            Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
11257                                    + myIdleTimeMs + " ms");
11258                        }
11259                        uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
11260                                .addCountLocked(myIdleTimeMs);
11261                    }
11262                }
11263
11264                if (DEBUG_ENERGY) {
11265                    Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
11266                    Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
11267                }
11268
11269                // Distribute the remaining Tx power appropriately between all apps that transmitted
11270                // packets.
11271                for (int i = 0; i < txPackets.size(); i++) {
11272                    final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
11273                    final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
11274                            / totalTxPackets;
11275                    if (DEBUG_ENERGY) {
11276                        Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
11277                    }
11278                    uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
11279                            .addCountLocked(myTxTimeMs);
11280                }
11281
11282                // Distribute the remaining Rx power appropriately between all apps that received
11283                // packets.
11284                for (int i = 0; i < rxPackets.size(); i++) {
11285                    final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
11286                    final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
11287                            / totalRxPackets;
11288                    if (DEBUG_ENERGY) {
11289                        Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
11290                    }
11291                    uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
11292                            .addCountLocked(myRxTimeMs);
11293                }
11294
11295                // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
11296
11297
11298                // Update WiFi controller stats.
11299                mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
11300                mWifiActivity.getTxTimeCounters()[0].addCountLocked(
11301                        info.getControllerTxTimeMillis());
11302                mWifiActivity.getScanTimeCounter().addCountLocked(
11303                    info.getControllerScanTimeMillis());
11304                mWifiActivity.getIdleTimeCounter().addCountLocked(
11305                        info.getControllerIdleTimeMillis());
11306
11307                // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11308                final double opVolt = mPowerProfile.getAveragePower(
11309                        PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11310                if (opVolt != 0) {
11311                    // We store the power drain as mAms.
11312                    mWifiActivity.getPowerCounter().addCountLocked(
11313                            (long) (info.getControllerEnergyUsed() / opVolt));
11314                }
11315            }
11316        }
11317    }
11318
11319    private ModemActivityInfo mLastModemActivityInfo =
11320            new ModemActivityInfo(0, 0, 0, new int[0], 0, 0);
11321
11322    private ModemActivityInfo getDeltaModemActivityInfo(ModemActivityInfo activityInfo) {
11323        if (activityInfo == null) {
11324            return null;
11325        }
11326        int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
11327        for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) {
11328            txTimeMs[i] = activityInfo.getTxTimeMillis()[i]
11329                    - mLastModemActivityInfo.getTxTimeMillis()[i];
11330        }
11331        ModemActivityInfo deltaInfo = new ModemActivityInfo(activityInfo.getTimestamp(),
11332                activityInfo.getSleepTimeMillis() - mLastModemActivityInfo.getSleepTimeMillis(),
11333                activityInfo.getIdleTimeMillis() - mLastModemActivityInfo.getIdleTimeMillis(),
11334                txTimeMs,
11335                activityInfo.getRxTimeMillis() - mLastModemActivityInfo.getRxTimeMillis(),
11336                activityInfo.getEnergyUsed() - mLastModemActivityInfo.getEnergyUsed());
11337        mLastModemActivityInfo = activityInfo;
11338        return deltaInfo;
11339    }
11340
11341    /**
11342     * Distribute Cell radio energy info and network traffic to apps.
11343     */
11344    public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo) {
11345        if (DEBUG_ENERGY) {
11346            Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
11347        }
11348        ModemActivityInfo deltaInfo = getDeltaModemActivityInfo(activityInfo);
11349
11350        // Add modem tx power to history.
11351        addModemTxPowerToHistory(deltaInfo);
11352
11353        // Grab a separate lock to acquire the network stats, which may do I/O.
11354        NetworkStats delta = null;
11355        synchronized (mModemNetworkLock) {
11356            final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces);
11357            if (latestStats != null) {
11358                delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null,
11359                        mNetworkStatsPool.acquire());
11360                mNetworkStatsPool.release(mLastModemNetworkStats);
11361                mLastModemNetworkStats = latestStats;
11362            }
11363        }
11364
11365        synchronized (this) {
11366            if (!mOnBatteryInternal) {
11367                if (delta != null) {
11368                    mNetworkStatsPool.release(delta);
11369                }
11370                return;
11371            }
11372
11373            if (deltaInfo != null) {
11374                mHasModemReporting = true;
11375                mModemActivity.getIdleTimeCounter().addCountLocked(
11376                        deltaInfo.getIdleTimeMillis());
11377                mModemActivity.getSleepTimeCounter().addCountLocked(
11378                        deltaInfo.getSleepTimeMillis());
11379                mModemActivity.getRxTimeCounter().addCountLocked(deltaInfo.getRxTimeMillis());
11380                for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
11381                    mModemActivity.getTxTimeCounters()[lvl]
11382                        .addCountLocked(deltaInfo.getTxTimeMillis()[lvl]);
11383                }
11384
11385                // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11386                final double opVolt = mPowerProfile.getAveragePower(
11387                    PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11388                if (opVolt != 0) {
11389                    double energyUsed =
11390                            deltaInfo.getSleepTimeMillis() *
11391                            mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
11392                            + deltaInfo.getIdleTimeMillis() *
11393                            mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
11394                            + deltaInfo.getRxTimeMillis() *
11395                            mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
11396                    int[] txTimeMs = deltaInfo.getTxTimeMillis();
11397                    for (int i = 0; i < Math.min(txTimeMs.length,
11398                            SignalStrength.NUM_SIGNAL_STRENGTH_BINS); i++) {
11399                        energyUsed += txTimeMs[i] * mPowerProfile.getAveragePower(
11400                                PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
11401                    }
11402
11403                    // We store the power drain as mAms.
11404                    mModemActivity.getPowerCounter().addCountLocked((long) energyUsed);
11405                }
11406            }
11407
11408            final long elapsedRealtimeMs = mClocks.elapsedRealtime();
11409            long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
11410                    elapsedRealtimeMs * 1000);
11411            mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
11412
11413            long totalRxPackets = 0;
11414            long totalTxPackets = 0;
11415            if (delta != null) {
11416                NetworkStats.Entry entry = new NetworkStats.Entry();
11417                final int size = delta.size();
11418                for (int i = 0; i < size; i++) {
11419                    entry = delta.getValues(i, entry);
11420                    if (entry.rxPackets == 0 && entry.txPackets == 0) {
11421                        continue;
11422                    }
11423
11424                    if (DEBUG_ENERGY) {
11425                        Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
11426                                + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
11427                                + " txPackets=" + entry.txPackets);
11428                    }
11429
11430                    totalRxPackets += entry.rxPackets;
11431                    totalTxPackets += entry.txPackets;
11432
11433                    final Uid u = getUidStatsLocked(mapUid(entry.uid));
11434                    u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
11435                            entry.rxPackets);
11436                    u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
11437                            entry.txPackets);
11438                    if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
11439                        u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
11440                                entry.rxBytes, entry.rxPackets);
11441                        u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
11442                                entry.txBytes, entry.txPackets);
11443                    }
11444
11445                    mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
11446                            entry.rxBytes);
11447                    mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
11448                            entry.txBytes);
11449                    mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
11450                            entry.rxPackets);
11451                    mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
11452                            entry.txPackets);
11453                }
11454
11455                // Now distribute proportional blame to the apps that did networking.
11456                long totalPackets = totalRxPackets + totalTxPackets;
11457                if (totalPackets > 0) {
11458                    for (int i = 0; i < size; i++) {
11459                        entry = delta.getValues(i, entry);
11460                        if (entry.rxPackets == 0 && entry.txPackets == 0) {
11461                            continue;
11462                        }
11463
11464                        final Uid u = getUidStatsLocked(mapUid(entry.uid));
11465
11466                        // Distribute total radio active time in to this app.
11467                        final long appPackets = entry.rxPackets + entry.txPackets;
11468                        final long appRadioTime = (radioTime * appPackets) / totalPackets;
11469                        u.noteMobileRadioActiveTimeLocked(appRadioTime);
11470
11471                        // Remove this app from the totals, so that we don't lose any time
11472                        // due to rounding.
11473                        radioTime -= appRadioTime;
11474                        totalPackets -= appPackets;
11475
11476                        if (deltaInfo != null) {
11477                            ControllerActivityCounterImpl activityCounter =
11478                                    u.getOrCreateModemControllerActivityLocked();
11479                            if (totalRxPackets > 0 && entry.rxPackets > 0) {
11480                                final long rxMs = (entry.rxPackets * deltaInfo.getRxTimeMillis())
11481                                        / totalRxPackets;
11482                                activityCounter.getRxTimeCounter().addCountLocked(rxMs);
11483                            }
11484
11485                            if (totalTxPackets > 0 && entry.txPackets > 0) {
11486                                for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
11487                                    long txMs =
11488                                            entry.txPackets * deltaInfo.getTxTimeMillis()[lvl];
11489                                    txMs /= totalTxPackets;
11490                                    activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
11491                                }
11492                            }
11493                        }
11494                    }
11495                }
11496
11497                if (radioTime > 0) {
11498                    // Whoops, there is some radio time we can't blame on an app!
11499                    mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
11500                    mMobileRadioActiveUnknownCount.addCountLocked(1);
11501                }
11502
11503                mNetworkStatsPool.release(delta);
11504                delta = null;
11505            }
11506        }
11507    }
11508
11509    /**
11510     * Add modem tx power to history
11511     * Device is said to be in high cellular transmit power when it has spent most of the transmit
11512     * time at the highest power level.
11513     * @param activityInfo
11514     */
11515    private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo) {
11516        if (activityInfo == null) {
11517            return;
11518        }
11519        int[] txTimeMs = activityInfo.getTxTimeMillis();
11520        if (txTimeMs == null || txTimeMs.length != ModemActivityInfo.TX_POWER_LEVELS) {
11521            return;
11522        }
11523        final long elapsedRealtime = mClocks.elapsedRealtime();
11524        final long uptime = mClocks.uptimeMillis();
11525        int levelMaxTimeSpent = 0;
11526        for (int i = 1; i < txTimeMs.length; i++) {
11527            if (txTimeMs[i] > txTimeMs[levelMaxTimeSpent]) {
11528                levelMaxTimeSpent = i;
11529            }
11530        }
11531        if (levelMaxTimeSpent == ModemActivityInfo.TX_POWER_LEVELS - 1) {
11532            if (!mIsCellularTxPowerHigh) {
11533                mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
11534                addHistoryRecordLocked(elapsedRealtime, uptime);
11535                mIsCellularTxPowerHigh = true;
11536            }
11537            return;
11538        }
11539        if (mIsCellularTxPowerHigh) {
11540            mHistoryCur.states2 &= ~HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
11541            addHistoryRecordLocked(elapsedRealtime, uptime);
11542            mIsCellularTxPowerHigh = false;
11543        }
11544        return;
11545    }
11546
11547    private final class BluetoothActivityInfoCache {
11548        long idleTimeMs;
11549        long rxTimeMs;
11550        long txTimeMs;
11551        long energy;
11552
11553        SparseLongArray uidRxBytes = new SparseLongArray();
11554        SparseLongArray uidTxBytes = new SparseLongArray();
11555
11556        void set(BluetoothActivityEnergyInfo info) {
11557            idleTimeMs = info.getControllerIdleTimeMillis();
11558            rxTimeMs = info.getControllerRxTimeMillis();
11559            txTimeMs = info.getControllerTxTimeMillis();
11560            energy = info.getControllerEnergyUsed();
11561            if (info.getUidTraffic() != null) {
11562                for (UidTraffic traffic : info.getUidTraffic()) {
11563                    uidRxBytes.put(traffic.getUid(), traffic.getRxBytes());
11564                    uidTxBytes.put(traffic.getUid(), traffic.getTxBytes());
11565                }
11566            }
11567        }
11568    }
11569
11570    private final BluetoothActivityInfoCache mLastBluetoothActivityInfo
11571            = new BluetoothActivityInfoCache();
11572
11573    /**
11574     * Distribute Bluetooth energy info and network traffic to apps.
11575     *
11576     * @param info The energy information from the bluetooth controller.
11577     */
11578    public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
11579        if (DEBUG_ENERGY) {
11580            Slog.d(TAG, "Updating bluetooth stats: " + info);
11581        }
11582
11583        if (info == null || !mOnBatteryInternal) {
11584            return;
11585        }
11586
11587        mHasBluetoothReporting = true;
11588
11589        final long elapsedRealtimeMs = mClocks.elapsedRealtime();
11590        final long rxTimeMs =
11591                info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs;
11592        final long txTimeMs =
11593                info.getControllerTxTimeMillis() - mLastBluetoothActivityInfo.txTimeMs;
11594        final long idleTimeMs =
11595                info.getControllerIdleTimeMillis() - mLastBluetoothActivityInfo.idleTimeMs;
11596
11597        if (DEBUG_ENERGY) {
11598            Slog.d(TAG, "------ BEGIN BLE power blaming ------");
11599            Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
11600            Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
11601            Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
11602        }
11603
11604        long totalScanTimeMs = 0;
11605
11606        final int uidCount = mUidStats.size();
11607        for (int i = 0; i < uidCount; i++) {
11608            final Uid u = mUidStats.valueAt(i);
11609            if (u.mBluetoothScanTimer == null) {
11610                continue;
11611            }
11612
11613            totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
11614                    elapsedRealtimeMs * 1000) / 1000;
11615        }
11616
11617        final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
11618        final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
11619
11620        if (DEBUG_ENERGY) {
11621            Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
11622                    + " TX=" + normalizeScanTxTime);
11623        }
11624
11625        long leftOverRxTimeMs = rxTimeMs;
11626        long leftOverTxTimeMs = txTimeMs;
11627
11628        for (int i = 0; i < uidCount; i++) {
11629            final Uid u = mUidStats.valueAt(i);
11630            if (u.mBluetoothScanTimer == null) {
11631                continue;
11632            }
11633
11634            long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
11635                    elapsedRealtimeMs * 1000) / 1000;
11636            if (scanTimeSinceMarkMs > 0) {
11637                // Set the new mark so that next time we get new data since this point.
11638                u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
11639
11640                long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
11641                long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
11642
11643                if (normalizeScanRxTime) {
11644                    // Scan time is longer than the total rx time in the controller,
11645                    // so distribute the scan time proportionately. This means regular traffic
11646                    // will not blamed, but scans are more expensive anyways.
11647                    scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
11648                }
11649
11650                if (normalizeScanTxTime) {
11651                    // Scan time is longer than the total tx time in the controller,
11652                    // so distribute the scan time proportionately. This means regular traffic
11653                    // will not blamed, but scans are more expensive anyways.
11654                    scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
11655                }
11656
11657                final ControllerActivityCounterImpl counter =
11658                        u.getOrCreateBluetoothControllerActivityLocked();
11659                counter.getRxTimeCounter().addCountLocked(scanTimeRxSinceMarkMs);
11660                counter.getTxTimeCounters()[0].addCountLocked(scanTimeTxSinceMarkMs);
11661
11662                leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
11663                leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
11664            }
11665        }
11666
11667        if (DEBUG_ENERGY) {
11668            Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs + " TX="
11669                    + leftOverTxTimeMs);
11670        }
11671
11672        //
11673        // Now distribute blame to apps that did bluetooth traffic.
11674        //
11675
11676        long totalTxBytes = 0;
11677        long totalRxBytes = 0;
11678
11679        final UidTraffic[] uidTraffic = info.getUidTraffic();
11680        final int numUids = uidTraffic != null ? uidTraffic.length : 0;
11681        for (int i = 0; i < numUids; i++) {
11682            final UidTraffic traffic = uidTraffic[i];
11683            final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(
11684                    traffic.getUid());
11685            final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(
11686                    traffic.getUid());
11687
11688            // Add to the global counters.
11689            mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(rxBytes);
11690            mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes);
11691
11692            // Add to the UID counters.
11693            final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
11694            u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0);
11695            u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0);
11696
11697            // Calculate the total traffic.
11698            totalRxBytes += rxBytes;
11699            totalTxBytes += txBytes;
11700        }
11701
11702        if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0
11703                || leftOverTxTimeMs != 0)) {
11704            for (int i = 0; i < numUids; i++) {
11705                final UidTraffic traffic = uidTraffic[i];
11706                final int uid = traffic.getUid();
11707                final long rxBytes =
11708                        traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid);
11709                final long txBytes =
11710                        traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid);
11711
11712                final Uid u = getUidStatsLocked(mapUid(uid));
11713                final ControllerActivityCounterImpl counter =
11714                        u.getOrCreateBluetoothControllerActivityLocked();
11715
11716                if (totalRxBytes > 0 && rxBytes > 0) {
11717                    final long timeRxMs = (leftOverRxTimeMs * rxBytes) / totalRxBytes;
11718                    if (DEBUG_ENERGY) {
11719                        Slog.d(TAG, "UID=" + uid + " rx_bytes=" + rxBytes + " rx_time=" + timeRxMs);
11720                    }
11721                    counter.getRxTimeCounter().addCountLocked(timeRxMs);
11722                    leftOverRxTimeMs -= timeRxMs;
11723                }
11724
11725                if (totalTxBytes > 0 && txBytes > 0) {
11726                    final long timeTxMs = (leftOverTxTimeMs * txBytes) / totalTxBytes;
11727                    if (DEBUG_ENERGY) {
11728                        Slog.d(TAG, "UID=" + uid + " tx_bytes=" + txBytes + " tx_time=" + timeTxMs);
11729                    }
11730                    counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
11731                    leftOverTxTimeMs -= timeTxMs;
11732                }
11733            }
11734        }
11735
11736        mBluetoothActivity.getRxTimeCounter().addCountLocked(rxTimeMs);
11737        mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(txTimeMs);
11738        mBluetoothActivity.getIdleTimeCounter().addCountLocked(idleTimeMs);
11739
11740        // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
11741        final double opVolt = mPowerProfile.getAveragePower(
11742                PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
11743        if (opVolt != 0) {
11744            // We store the power drain as mAms.
11745            mBluetoothActivity.getPowerCounter().addCountLocked(
11746                    (long) ((info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
11747                            / opVolt));
11748        }
11749        mLastBluetoothActivityInfo.set(info);
11750    }
11751
11752    /**
11753     * Read and record Resource Power Manager (RPM) state and voter times.
11754     * If RPM stats were fetched more recently than RPM_STATS_UPDATE_FREQ_MS ago, uses the old data
11755     * instead of fetching it anew.
11756     */
11757    public void updateRpmStatsLocked() {
11758        if (mPlatformIdleStateCallback == null) return;
11759        long now = SystemClock.elapsedRealtime();
11760        if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
11761            mPlatformIdleStateCallback.fillLowPowerStats(mTmpRpmStats);
11762            mLastRpmStatsUpdateTimeMs = now;
11763        }
11764
11765        for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate
11766                : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) {
11767
11768            // Update values for this platform state.
11769            final String pName = pstate.getKey();
11770            final long pTimeUs = pstate.getValue().mTimeMs * 1000;
11771            final int pCount = pstate.getValue().mCount;
11772            getRpmTimerLocked(pName).update(pTimeUs, pCount);
11773            if (SCREEN_OFF_RPM_STATS_ENABLED) {
11774                getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount);
11775            }
11776
11777            // Update values for each voter of this platform state.
11778            for (Map.Entry<String, RpmStats.PowerStateElement> voter
11779                    : pstate.getValue().mVoters.entrySet()) {
11780                final String vName = pName + "." + voter.getKey();
11781                final long vTimeUs = voter.getValue().mTimeMs * 1000;
11782                final int vCount = voter.getValue().mCount;
11783                getRpmTimerLocked(vName).update(vTimeUs, vCount);
11784                if (SCREEN_OFF_RPM_STATS_ENABLED) {
11785                    getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount);
11786                }
11787            }
11788        }
11789
11790        for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys
11791                : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) {
11792
11793            final String subsysName = subsys.getKey();
11794            for (Map.Entry<String, RpmStats.PowerStateElement> sstate
11795                    : subsys.getValue().mStates.entrySet()) {
11796                final String name = subsysName + "." + sstate.getKey();
11797                final long timeUs = sstate.getValue().mTimeMs * 1000;
11798                final int count = sstate.getValue().mCount;
11799                getRpmTimerLocked(name).update(timeUs, count);
11800                if (SCREEN_OFF_RPM_STATS_ENABLED) {
11801                    getScreenOffRpmTimerLocked(name).update(timeUs, count);
11802                }
11803            }
11804        }
11805    }
11806
11807    /**
11808     * Read and distribute kernel wake lock use across apps.
11809     */
11810    public void updateKernelWakelocksLocked() {
11811        final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
11812                mTmpWakelockStats);
11813        if (wakelockStats == null) {
11814            // Not crashing might make board bringup easier.
11815            Slog.w(TAG, "Couldn't get kernel wake lock stats");
11816            return;
11817        }
11818
11819        for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
11820            String name = ent.getKey();
11821            KernelWakelockStats.Entry kws = ent.getValue();
11822
11823            SamplingTimer kwlt = mKernelWakelockStats.get(name);
11824            if (kwlt == null) {
11825                kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
11826                mKernelWakelockStats.put(name, kwlt);
11827            }
11828
11829            kwlt.update(kws.mTotalTime, kws.mCount);
11830            kwlt.setUpdateVersion(kws.mVersion);
11831        }
11832
11833        int numWakelocksSetStale = 0;
11834        // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
11835        // this time.
11836        for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
11837            SamplingTimer st = ent.getValue();
11838            if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
11839                st.endSample();
11840                numWakelocksSetStale++;
11841            }
11842        }
11843
11844        // Record whether we've seen a non-zero time (for debugging b/22716723).
11845        if (wakelockStats.isEmpty()) {
11846            Slog.wtf(TAG, "All kernel wakelocks had time of zero");
11847        }
11848
11849        if (numWakelocksSetStale == mKernelWakelockStats.size()) {
11850            Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
11851                    wakelockStats.kernelWakelockVersion);
11852        }
11853    }
11854
11855    // We use an anonymous class to access these variables,
11856    // so they can't live on the stack or they'd have to be
11857    // final MutableLong objects (more allocations).
11858    // Used in updateCpuTimeLocked().
11859    long mTempTotalCpuUserTimeUs;
11860    long mTempTotalCpuSystemTimeUs;
11861    long[][] mWakeLockAllocationsUs;
11862
11863    /**
11864     * Reads the newest memory stats from the kernel.
11865     */
11866    public void updateKernelMemoryBandwidthLocked() {
11867        mKernelMemoryBandwidthStats.updateStats();
11868        LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
11869        final int bandwidthEntryCount = bandwidthEntries.size();
11870        int index;
11871        for (int i = 0; i < bandwidthEntryCount; i++) {
11872            SamplingTimer timer;
11873            if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) {
11874                timer = mKernelMemoryStats.valueAt(index);
11875            } else {
11876                timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
11877                mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
11878            }
11879            timer.update(bandwidthEntries.valueAt(i), 1);
11880            if (DEBUG_MEMORY) {
11881                Slog.d(TAG, String.format("Added entry %d and updated timer to: "
11882                        + "mUnpluggedReportedTotalTime %d size %d", bandwidthEntries.keyAt(i),
11883                        mKernelMemoryStats.get(
11884                                bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTime,
11885                        mKernelMemoryStats.size()));
11886            }
11887        }
11888    }
11889
11890    public boolean isOnBatteryLocked() {
11891        return mOnBatteryTimeBase.isRunning();
11892    }
11893
11894    public boolean isOnBatteryScreenOffLocked() {
11895        return mOnBatteryScreenOffTimeBase.isRunning();
11896    }
11897
11898    /**
11899     * Read and distribute CPU usage across apps. If their are partial wakelocks being held
11900     * and we are on battery with screen off, we give more of the cpu time to those apps holding
11901     * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
11902     * It's possible this will be invoked after the internal battery/screen states are updated, so
11903     * passing the appropriate battery/screen states to try attribute the cpu times to correct
11904     * buckets.
11905     */
11906    @GuardedBy("this")
11907    public void updateCpuTimeLocked(boolean onBattery, boolean onBatteryScreenOff) {
11908        if (mPowerProfile == null) {
11909            return;
11910        }
11911
11912        if (DEBUG_ENERGY_CPU) {
11913            Slog.d(TAG, "!Cpu updating!");
11914        }
11915
11916        if (mCpuFreqs == null) {
11917            mCpuFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile);
11918        }
11919
11920        // Calculate the wakelocks we have to distribute amongst. The system is excluded as it is
11921        // usually holding the wakelock on behalf of an app.
11922        // And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
11923        ArrayList<StopwatchTimer> partialTimersToConsider = null;
11924        if (onBatteryScreenOff) {
11925            partialTimersToConsider = new ArrayList<>();
11926            for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
11927                final StopwatchTimer timer = mPartialTimers.get(i);
11928                // Since the collection and blaming of wakelocks can be scheduled to run after
11929                // some delay, the mPartialTimers list may have new entries. We can't blame
11930                // the newly added timer for past cpu time, so we only consider timers that
11931                // were present for one round of collection. Once a timer has gone through
11932                // a round of collection, its mInList field is set to true.
11933                if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
11934                    partialTimersToConsider.add(timer);
11935                }
11936            }
11937        }
11938        markPartialTimersAsEligible();
11939
11940        // When the battery is not on, we don't attribute the cpu times to any timers but we still
11941        // need to take the snapshots.
11942        if (!onBattery) {
11943            mKernelUidCpuTimeReader.readDelta(null);
11944            mKernelUidCpuFreqTimeReader.readDelta(null);
11945            mNumAllUidCpuTimeReads += 2;
11946            if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
11947                mKernelUidCpuActiveTimeReader.readDelta(null);
11948                mKernelUidCpuClusterTimeReader.readDelta(null);
11949                mNumAllUidCpuTimeReads += 2;
11950            }
11951            for (int cluster = mKernelCpuSpeedReaders.length - 1; cluster >= 0; --cluster) {
11952                mKernelCpuSpeedReaders[cluster].readDelta();
11953            }
11954            return;
11955        }
11956
11957        mUserInfoProvider.refreshUserIds();
11958        final SparseLongArray updatedUids = mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()
11959                ? null : new SparseLongArray();
11960        readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
11961        // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
11962        // freqs, so no need to approximate these values.
11963        if (updatedUids != null) {
11964            updateClusterSpeedTimes(updatedUids, onBattery);
11965        }
11966        readKernelUidCpuFreqTimesLocked(partialTimersToConsider, onBattery, onBatteryScreenOff);
11967        mNumAllUidCpuTimeReads += 2;
11968        if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
11969            readKernelUidCpuActiveTimesLocked(onBattery);
11970            readKernelUidCpuClusterTimesLocked(onBattery);
11971            mNumAllUidCpuTimeReads += 2;
11972        }
11973    }
11974
11975    /**
11976     * Mark the current partial timers as gone through a collection so that they will be
11977     * considered in the next cpu times distribution to wakelock holders.
11978     */
11979    @VisibleForTesting
11980    public void markPartialTimersAsEligible() {
11981        if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
11982            // No difference, so each timer is now considered for the next collection.
11983            for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
11984                mPartialTimers.get(i).mInList = true;
11985            }
11986        } else {
11987            // The lists are different, meaning we added (or removed a timer) since the last
11988            // collection.
11989            for (int i = mLastPartialTimers.size() - 1; i >= 0; --i) {
11990                mLastPartialTimers.get(i).mInList = false;
11991            }
11992            mLastPartialTimers.clear();
11993
11994            // Mark the current timers as gone through a collection.
11995            final int numPartialTimers = mPartialTimers.size();
11996            for (int i = 0; i < numPartialTimers; ++i) {
11997                final StopwatchTimer timer = mPartialTimers.get(i);
11998                timer.mInList = true;
11999                mLastPartialTimers.add(timer);
12000            }
12001        }
12002    }
12003
12004    /**
12005     * Take snapshot of cpu times (aggregated over all uids) at different frequencies and
12006     * calculate cpu times spent by each uid at different frequencies.
12007     *
12008     * @param updatedUids The uids for which times spent at different frequencies are calculated.
12009     */
12010    @VisibleForTesting
12011    public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids, boolean onBattery) {
12012        long totalCpuClustersTimeMs = 0;
12013        // Read the time spent for each cluster at various cpu frequencies.
12014        final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
12015        for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
12016            clusterSpeedTimesMs[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
12017            if (clusterSpeedTimesMs[cluster] != null) {
12018                for (int speed = clusterSpeedTimesMs[cluster].length - 1; speed >= 0; --speed) {
12019                    totalCpuClustersTimeMs += clusterSpeedTimesMs[cluster][speed];
12020                }
12021            }
12022        }
12023        if (totalCpuClustersTimeMs != 0) {
12024            // We have cpu times per freq aggregated over all uids but we need the times per uid.
12025            // So, we distribute total time spent by an uid to different cpu freqs based on the
12026            // amount of time cpu was running at that freq.
12027            final int updatedUidsCount = updatedUids.size();
12028            for (int i = 0; i < updatedUidsCount; ++i) {
12029                final Uid u = getUidStatsLocked(updatedUids.keyAt(i));
12030                final long appCpuTimeUs = updatedUids.valueAt(i);
12031                // Add the cpu speeds to this UID.
12032                final int numClusters = mPowerProfile.getNumCpuClusters();
12033                if (u.mCpuClusterSpeedTimesUs == null ||
12034                        u.mCpuClusterSpeedTimesUs.length != numClusters) {
12035                    u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
12036                }
12037
12038                for (int cluster = 0; cluster < clusterSpeedTimesMs.length; cluster++) {
12039                    final int speedsInCluster = clusterSpeedTimesMs[cluster].length;
12040                    if (u.mCpuClusterSpeedTimesUs[cluster] == null || speedsInCluster !=
12041                            u.mCpuClusterSpeedTimesUs[cluster].length) {
12042                        u.mCpuClusterSpeedTimesUs[cluster]
12043                                = new LongSamplingCounter[speedsInCluster];
12044                    }
12045
12046                    final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeedTimesUs[cluster];
12047                    for (int speed = 0; speed < speedsInCluster; speed++) {
12048                        if (cpuSpeeds[speed] == null) {
12049                            cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
12050                        }
12051                        cpuSpeeds[speed].addCountLocked(appCpuTimeUs
12052                                * clusterSpeedTimesMs[cluster][speed]
12053                                / totalCpuClustersTimeMs, onBattery);
12054                    }
12055                }
12056            }
12057        }
12058    }
12059
12060    /**
12061     * Take a snapshot of the cpu times spent by each uid and update the corresponding counters.
12062     * If {@param partialTimers} is not null and empty, then we assign a portion of cpu times to
12063     * wakelock holders.
12064     *
12065     * @param partialTimers The wakelock holders among which the cpu times will be distributed.
12066     * @param updatedUids If not null, then the uids found in the snapshot will be added to this.
12067     */
12068    @VisibleForTesting
12069    public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
12070            @Nullable SparseLongArray updatedUids, boolean onBattery) {
12071        mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
12072        final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
12073        final long startTimeMs = mClocks.uptimeMillis();
12074
12075        mKernelUidCpuTimeReader.readDelta((uid, userTimeUs, systemTimeUs) -> {
12076            uid = mapUid(uid);
12077            if (Process.isIsolated(uid)) {
12078                // This could happen if the isolated uid mapping was removed before that process
12079                // was actually killed.
12080                mKernelUidCpuTimeReader.removeUid(uid);
12081                Slog.d(TAG, "Got readings for an isolated uid with no mapping: " + uid);
12082                return;
12083            }
12084            if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
12085                Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
12086                mKernelUidCpuTimeReader.removeUid(uid);
12087                return;
12088            }
12089            final Uid u = getUidStatsLocked(uid);
12090
12091            // Accumulate the total system and user time.
12092            mTempTotalCpuUserTimeUs += userTimeUs;
12093            mTempTotalCpuSystemTimeUs += systemTimeUs;
12094
12095            StringBuilder sb = null;
12096            if (DEBUG_ENERGY_CPU) {
12097                sb = new StringBuilder();
12098                sb.append("  got time for uid=").append(u.mUid).append(": u=");
12099                TimeUtils.formatDuration(userTimeUs / 1000, sb);
12100                sb.append(" s=");
12101                TimeUtils.formatDuration(systemTimeUs / 1000, sb);
12102                sb.append("\n");
12103            }
12104
12105            if (numWakelocks > 0) {
12106                // We have wakelocks being held, so only give a portion of the
12107                // time to the process. The rest will be distributed among wakelock
12108                // holders.
12109                userTimeUs = (userTimeUs * WAKE_LOCK_WEIGHT) / 100;
12110                systemTimeUs = (systemTimeUs * WAKE_LOCK_WEIGHT) / 100;
12111            }
12112
12113            if (sb != null) {
12114                sb.append("  adding to uid=").append(u.mUid).append(": u=");
12115                TimeUtils.formatDuration(userTimeUs / 1000, sb);
12116                sb.append(" s=");
12117                TimeUtils.formatDuration(systemTimeUs / 1000, sb);
12118                Slog.d(TAG, sb.toString());
12119            }
12120
12121            u.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
12122            u.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
12123            if (updatedUids != null) {
12124                updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
12125            }
12126        });
12127
12128        final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
12129        if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
12130            Slog.d(TAG, "Reading cpu stats took " + elapsedTimeMs + "ms");
12131        }
12132
12133        if (numWakelocks > 0) {
12134            // Distribute a portion of the total cpu time to wakelock holders.
12135            mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
12136            mTempTotalCpuSystemTimeUs =
12137                    (mTempTotalCpuSystemTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
12138
12139            for (int i = 0; i < numWakelocks; ++i) {
12140                final StopwatchTimer timer = partialTimers.get(i);
12141                final int userTimeUs = (int) (mTempTotalCpuUserTimeUs / (numWakelocks - i));
12142                final int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / (numWakelocks - i));
12143
12144                if (DEBUG_ENERGY_CPU) {
12145                    final StringBuilder sb = new StringBuilder();
12146                    sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
12147                            .append(": u=");
12148                    TimeUtils.formatDuration(userTimeUs / 1000, sb);
12149                    sb.append(" s=");
12150                    TimeUtils.formatDuration(systemTimeUs / 1000, sb);
12151                    Slog.d(TAG, sb.toString());
12152                }
12153
12154                timer.mUid.mUserCpuTime.addCountLocked(userTimeUs, onBattery);
12155                timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs, onBattery);
12156                if (updatedUids != null) {
12157                    final int uid = timer.mUid.getUid();
12158                    updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
12159                }
12160
12161                final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
12162                proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000, onBattery);
12163
12164                mTempTotalCpuUserTimeUs -= userTimeUs;
12165                mTempTotalCpuSystemTimeUs -= systemTimeUs;
12166            }
12167        }
12168    }
12169
12170    /**
12171     * Take a snapshot of the cpu times spent by each uid in each freq and update the
12172     * corresponding counters.
12173     *
12174     * @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
12175     */
12176    @VisibleForTesting
12177    public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
12178            boolean onBattery, boolean onBatteryScreenOff) {
12179        final boolean perClusterTimesAvailable =
12180                mKernelUidCpuFreqTimeReader.perClusterTimesAvailable();
12181        final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
12182        final int numClusters = mPowerProfile.getNumCpuClusters();
12183        mWakeLockAllocationsUs = null;
12184        final long startTimeMs = mClocks.uptimeMillis();
12185        mKernelUidCpuFreqTimeReader.readDelta((uid, cpuFreqTimeMs) -> {
12186            uid = mapUid(uid);
12187            if (Process.isIsolated(uid)) {
12188                mKernelUidCpuFreqTimeReader.removeUid(uid);
12189                Slog.d(TAG, "Got freq readings for an isolated uid with no mapping: " + uid);
12190                return;
12191            }
12192            if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
12193                Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
12194                mKernelUidCpuFreqTimeReader.removeUid(uid);
12195                return;
12196            }
12197            final Uid u = getUidStatsLocked(uid);
12198            if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
12199                u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
12200            }
12201            u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
12202            if (u.mScreenOffCpuFreqTimeMs == null ||
12203                    u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
12204                u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
12205                        mOnBatteryScreenOffTimeBase);
12206            }
12207            u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBatteryScreenOff);
12208
12209            if (perClusterTimesAvailable) {
12210                if (u.mCpuClusterSpeedTimesUs == null ||
12211                        u.mCpuClusterSpeedTimesUs.length != numClusters) {
12212                    u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
12213                }
12214                if (numWakelocks > 0 && mWakeLockAllocationsUs == null) {
12215                    mWakeLockAllocationsUs = new long[numClusters][];
12216                }
12217
12218                int freqIndex = 0;
12219                for (int cluster = 0; cluster < numClusters; ++cluster) {
12220                    final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
12221                    if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
12222                            u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
12223                        u.mCpuClusterSpeedTimesUs[cluster]
12224                                = new LongSamplingCounter[speedsInCluster];
12225                    }
12226                    if (numWakelocks > 0 && mWakeLockAllocationsUs[cluster] == null) {
12227                        mWakeLockAllocationsUs[cluster] = new long[speedsInCluster];
12228                    }
12229                    final LongSamplingCounter[] cpuTimesUs = u.mCpuClusterSpeedTimesUs[cluster];
12230                    for (int speed = 0; speed < speedsInCluster; ++speed) {
12231                        if (cpuTimesUs[speed] == null) {
12232                            cpuTimesUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
12233                        }
12234                        final long appAllocationUs;
12235                        if (mWakeLockAllocationsUs != null) {
12236                            appAllocationUs =
12237                                    (cpuFreqTimeMs[freqIndex] * 1000 * WAKE_LOCK_WEIGHT) / 100;
12238                            mWakeLockAllocationsUs[cluster][speed] +=
12239                                    (cpuFreqTimeMs[freqIndex] * 1000 - appAllocationUs);
12240                        } else {
12241                            appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
12242                        }
12243                        cpuTimesUs[speed].addCountLocked(appAllocationUs, onBattery);
12244                        freqIndex++;
12245                    }
12246                }
12247            }
12248        });
12249
12250        final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
12251        if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
12252            Slog.d(TAG, "Reading cpu freq times took " + elapsedTimeMs + "ms");
12253        }
12254
12255        if (mWakeLockAllocationsUs != null) {
12256            for (int i = 0; i < numWakelocks; ++i) {
12257                final Uid u = partialTimers.get(i).mUid;
12258                if (u.mCpuClusterSpeedTimesUs == null ||
12259                        u.mCpuClusterSpeedTimesUs.length != numClusters) {
12260                    u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
12261                }
12262
12263                for (int cluster = 0; cluster < numClusters; ++cluster) {
12264                    final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
12265                    if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
12266                            u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
12267                        u.mCpuClusterSpeedTimesUs[cluster]
12268                                = new LongSamplingCounter[speedsInCluster];
12269                    }
12270                    final LongSamplingCounter[] cpuTimeUs = u.mCpuClusterSpeedTimesUs[cluster];
12271                    for (int speed = 0; speed < speedsInCluster; ++speed) {
12272                        if (cpuTimeUs[speed] == null) {
12273                            cpuTimeUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
12274                        }
12275                        final long allocationUs =
12276                                mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
12277                        cpuTimeUs[speed].addCountLocked(allocationUs, onBattery);
12278                        mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
12279                    }
12280                }
12281            }
12282        }
12283    }
12284
12285    /**
12286     * Take a snapshot of the cpu active times spent by each uid and update the corresponding
12287     * counters.
12288     */
12289    @VisibleForTesting
12290    public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
12291        final long startTimeMs = mClocks.uptimeMillis();
12292        mKernelUidCpuActiveTimeReader.readDelta((uid, cpuActiveTimesMs) -> {
12293            uid = mapUid(uid);
12294            if (Process.isIsolated(uid)) {
12295                mKernelUidCpuActiveTimeReader.removeUid(uid);
12296                Slog.w(TAG, "Got active times for an isolated uid with no mapping: " + uid);
12297                return;
12298            }
12299            if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
12300                Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
12301                mKernelUidCpuActiveTimeReader.removeUid(uid);
12302                return;
12303            }
12304            final Uid u = getUidStatsLocked(uid);
12305            u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesMs, onBattery);
12306        });
12307
12308        final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
12309        if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
12310            Slog.d(TAG, "Reading cpu active times took " + elapsedTimeMs + "ms");
12311        }
12312    }
12313
12314    /**
12315     * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding
12316     * counters.
12317     */
12318    @VisibleForTesting
12319    public void readKernelUidCpuClusterTimesLocked(boolean onBattery) {
12320        final long startTimeMs = mClocks.uptimeMillis();
12321        mKernelUidCpuClusterTimeReader.readDelta((uid, cpuClusterTimesMs) -> {
12322            uid = mapUid(uid);
12323            if (Process.isIsolated(uid)) {
12324                mKernelUidCpuClusterTimeReader.removeUid(uid);
12325                Slog.w(TAG, "Got cluster times for an isolated uid with no mapping: " + uid);
12326                return;
12327            }
12328            if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
12329                Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
12330                mKernelUidCpuClusterTimeReader.removeUid(uid);
12331                return;
12332            }
12333            final Uid u = getUidStatsLocked(uid);
12334            u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesMs, onBattery);
12335        });
12336
12337        final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
12338        if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
12339            Slog.d(TAG, "Reading cpu cluster times took " + elapsedTimeMs + "ms");
12340        }
12341    }
12342
12343    boolean setChargingLocked(boolean charging) {
12344        if (mCharging != charging) {
12345            mCharging = charging;
12346            if (charging) {
12347                mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
12348            } else {
12349                mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
12350            }
12351            mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
12352            return true;
12353        }
12354        return false;
12355    }
12356
12357    @GuardedBy("this")
12358    protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
12359            final boolean onBattery, final int oldStatus, final int level, final int chargeUAh) {
12360        boolean doWrite = false;
12361        Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
12362        m.arg1 = onBattery ? 1 : 0;
12363        mHandler.sendMessage(m);
12364
12365        final long uptime = mSecUptime * 1000;
12366        final long realtime = mSecRealtime * 1000;
12367        final int screenState = mScreenState;
12368        if (onBattery) {
12369            // We will reset our status if we are unplugging after the
12370            // battery was last full, or the level is at 100, or
12371            // we have gone through a significant charge (from a very low
12372            // level to a now very high level).
12373            boolean reset = false;
12374            if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
12375                    || level >= 90
12376                    || (mDischargeCurrentLevel < 20 && level >= 80)
12377                    || (getHighDischargeAmountSinceCharge() >= 200
12378                            && mHistoryBuffer.dataSize() >= MAX_HISTORY_BUFFER))) {
12379                Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
12380                        + " dischargeLevel=" + mDischargeCurrentLevel
12381                        + " lowAmount=" + getLowDischargeAmountSinceCharge()
12382                        + " highAmount=" + getHighDischargeAmountSinceCharge());
12383                // Before we write, collect a snapshot of the final aggregated
12384                // stats to be reported in the next checkin.  Only do this if we have
12385                // a sufficient amount of data to make it interesting.
12386                if (getLowDischargeAmountSinceCharge() >= 20) {
12387                    final long startTime = SystemClock.uptimeMillis();
12388                    final Parcel parcel = Parcel.obtain();
12389                    writeSummaryToParcel(parcel, true);
12390                    final long initialTime = SystemClock.uptimeMillis() - startTime;
12391                    BackgroundThread.getHandler().post(new Runnable() {
12392                        @Override public void run() {
12393                            synchronized (mCheckinFile) {
12394                                final long startTime2 = SystemClock.uptimeMillis();
12395                                FileOutputStream stream = null;
12396                                try {
12397                                    stream = mCheckinFile.startWrite();
12398                                    stream.write(parcel.marshall());
12399                                    stream.flush();
12400                                    FileUtils.sync(stream);
12401                                    stream.close();
12402                                    mCheckinFile.finishWrite(stream);
12403                                    com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
12404                                            "batterystats-checkin",
12405                                            initialTime + SystemClock.uptimeMillis() - startTime2);
12406                                } catch (IOException e) {
12407                                    Slog.w("BatteryStats",
12408                                            "Error writing checkin battery statistics", e);
12409                                    mCheckinFile.failWrite(stream);
12410                                } finally {
12411                                    parcel.recycle();
12412                                }
12413                            }
12414                        }
12415                    });
12416                }
12417                doWrite = true;
12418                resetAllStatsLocked();
12419                if (chargeUAh > 0 && level > 0) {
12420                    // Only use the reported coulomb charge value if it is supported and reported.
12421                    mEstimatedBatteryCapacity = (int) ((chargeUAh / 1000) / (level / 100.0));
12422                }
12423                mDischargeStartLevel = level;
12424                reset = true;
12425                mDischargeStepTracker.init();
12426            }
12427            if (mCharging) {
12428                setChargingLocked(false);
12429            }
12430            mLastChargingStateLevel = level;
12431            mOnBattery = mOnBatteryInternal = true;
12432            mLastDischargeStepLevel = level;
12433            mMinDischargeStepLevel = level;
12434            mDischargeStepTracker.clearTime();
12435            mDailyDischargeStepTracker.clearTime();
12436            mInitStepMode = mCurStepMode;
12437            mModStepMode = 0;
12438            pullPendingStateUpdatesLocked();
12439            mHistoryCur.batteryLevel = (byte)level;
12440            mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12441            if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
12442                    + Integer.toHexString(mHistoryCur.states));
12443            if (reset) {
12444                mRecordingHistory = true;
12445                startRecordingHistory(mSecRealtime, mSecUptime, reset);
12446            }
12447            addHistoryRecordLocked(mSecRealtime, mSecUptime);
12448            mDischargeCurrentLevel = mDischargeUnplugLevel = level;
12449            if (isScreenOn(screenState)) {
12450                mDischargeScreenOnUnplugLevel = level;
12451                mDischargeScreenDozeUnplugLevel = 0;
12452                mDischargeScreenOffUnplugLevel = 0;
12453            } else if (isScreenDoze(screenState)) {
12454                mDischargeScreenOnUnplugLevel = 0;
12455                mDischargeScreenDozeUnplugLevel = level;
12456                mDischargeScreenOffUnplugLevel = 0;
12457            } else {
12458                mDischargeScreenOnUnplugLevel = 0;
12459                mDischargeScreenDozeUnplugLevel = 0;
12460                mDischargeScreenOffUnplugLevel = level;
12461            }
12462            mDischargeAmountScreenOn = 0;
12463            mDischargeAmountScreenDoze = 0;
12464            mDischargeAmountScreenOff = 0;
12465            updateTimeBasesLocked(true, screenState, uptime, realtime);
12466        } else {
12467            mLastChargingStateLevel = level;
12468            mOnBattery = mOnBatteryInternal = false;
12469            pullPendingStateUpdatesLocked();
12470            mHistoryCur.batteryLevel = (byte)level;
12471            mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12472            if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
12473                    + Integer.toHexString(mHistoryCur.states));
12474            addHistoryRecordLocked(mSecRealtime, mSecUptime);
12475            mDischargeCurrentLevel = mDischargePlugLevel = level;
12476            if (level < mDischargeUnplugLevel) {
12477                mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
12478                mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
12479            }
12480            updateDischargeScreenLevelsLocked(screenState, screenState);
12481            updateTimeBasesLocked(false, screenState, uptime, realtime);
12482            mChargeStepTracker.init();
12483            mLastChargeStepLevel = level;
12484            mMaxChargeStepLevel = level;
12485            mInitStepMode = mCurStepMode;
12486            mModStepMode = 0;
12487        }
12488        if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
12489            if (mFile != null) {
12490                writeAsyncLocked();
12491            }
12492        }
12493    }
12494
12495    private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
12496            boolean reset) {
12497        mRecordingHistory = true;
12498        mHistoryCur.currentTime = System.currentTimeMillis();
12499        addHistoryBufferLocked(elapsedRealtimeMs,
12500                reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
12501                mHistoryCur);
12502        mHistoryCur.currentTime = 0;
12503        if (reset) {
12504            initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
12505        }
12506    }
12507
12508    private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
12509            final long uptimeMs) {
12510        if (mRecordingHistory) {
12511            mHistoryCur.currentTime = currentTime;
12512            addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_CURRENT_TIME, mHistoryCur);
12513            mHistoryCur.currentTime = 0;
12514        }
12515    }
12516
12517    private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
12518        if (mRecordingHistory) {
12519            mHistoryCur.currentTime = System.currentTimeMillis();
12520            addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_SHUTDOWN, mHistoryCur);
12521            mHistoryCur.currentTime = 0;
12522        }
12523    }
12524
12525    private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
12526        if (mExternalSync != null) {
12527            mExternalSync.scheduleSync(reason, updateFlags);
12528        }
12529    }
12530
12531    // This should probably be exposed in the API, though it's not critical
12532    public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
12533
12534    @GuardedBy("this")
12535    public void setBatteryStateLocked(final int status, final int health, final int plugType,
12536            final int level, /* not final */ int temp, final int volt, final int chargeUAh,
12537            final int chargeFullUAh) {
12538        // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
12539        temp = Math.max(0, temp);
12540
12541        reportChangesToStatsLog(mHaveBatteryLevel ? mHistoryCur : null,
12542                status, plugType, level);
12543
12544        final boolean onBattery = isOnBattery(plugType, status);
12545        final long uptime = mClocks.uptimeMillis();
12546        final long elapsedRealtime = mClocks.elapsedRealtime();
12547        if (!mHaveBatteryLevel) {
12548            mHaveBatteryLevel = true;
12549            // We start out assuming that the device is plugged in (not
12550            // on battery).  If our first report is now that we are indeed
12551            // plugged in, then twiddle our state to correctly reflect that
12552            // since we won't be going through the full setOnBattery().
12553            if (onBattery == mOnBattery) {
12554                if (onBattery) {
12555                    mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12556                } else {
12557                    mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
12558                }
12559            }
12560            // Always start out assuming charging, that will be updated later.
12561            mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
12562            mHistoryCur.batteryStatus = (byte)status;
12563            mHistoryCur.batteryLevel = (byte)level;
12564            mHistoryCur.batteryChargeUAh = chargeUAh;
12565            mMaxChargeStepLevel = mMinDischargeStepLevel =
12566                    mLastChargeStepLevel = mLastDischargeStepLevel = level;
12567            mLastChargingStateLevel = level;
12568        } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
12569            recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
12570        }
12571        int oldStatus = mHistoryCur.batteryStatus;
12572        if (onBattery) {
12573            mDischargeCurrentLevel = level;
12574            if (!mRecordingHistory) {
12575                mRecordingHistory = true;
12576                startRecordingHistory(elapsedRealtime, uptime, true);
12577            }
12578        } else if (level < 96 &&
12579            status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
12580            if (!mRecordingHistory) {
12581                mRecordingHistory = true;
12582                startRecordingHistory(elapsedRealtime, uptime, true);
12583            }
12584        }
12585        mCurrentBatteryLevel = level;
12586        if (mDischargePlugLevel < 0) {
12587            mDischargePlugLevel = level;
12588        }
12589
12590        if (onBattery != mOnBattery) {
12591            mHistoryCur.batteryLevel = (byte)level;
12592            mHistoryCur.batteryStatus = (byte)status;
12593            mHistoryCur.batteryHealth = (byte)health;
12594            mHistoryCur.batteryPlugType = (byte)plugType;
12595            mHistoryCur.batteryTemperature = (short)temp;
12596            mHistoryCur.batteryVoltage = (char)volt;
12597            if (chargeUAh < mHistoryCur.batteryChargeUAh) {
12598                // Only record discharges
12599                final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
12600                mDischargeCounter.addCountLocked(chargeDiff);
12601                mDischargeScreenOffCounter.addCountLocked(chargeDiff);
12602                if (isScreenDoze(mScreenState)) {
12603                    mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
12604                }
12605                if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
12606                    mDischargeLightDozeCounter.addCountLocked(chargeDiff);
12607                } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
12608                    mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
12609                }
12610            }
12611            mHistoryCur.batteryChargeUAh = chargeUAh;
12612            setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level, chargeUAh);
12613        } else {
12614            boolean changed = false;
12615            if (mHistoryCur.batteryLevel != level) {
12616                mHistoryCur.batteryLevel = (byte)level;
12617                changed = true;
12618
12619                // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
12620                // which will pull external stats.
12621                mExternalSync.scheduleSyncDueToBatteryLevelChange(
12622                        mConstants.BATTERY_LEVEL_COLLECTION_DELAY_MS);
12623            }
12624            if (mHistoryCur.batteryStatus != status) {
12625                mHistoryCur.batteryStatus = (byte)status;
12626                changed = true;
12627            }
12628            if (mHistoryCur.batteryHealth != health) {
12629                mHistoryCur.batteryHealth = (byte)health;
12630                changed = true;
12631            }
12632            if (mHistoryCur.batteryPlugType != plugType) {
12633                mHistoryCur.batteryPlugType = (byte)plugType;
12634                changed = true;
12635            }
12636            if (temp >= (mHistoryCur.batteryTemperature+10)
12637                    || temp <= (mHistoryCur.batteryTemperature-10)) {
12638                mHistoryCur.batteryTemperature = (short)temp;
12639                changed = true;
12640            }
12641            if (volt > (mHistoryCur.batteryVoltage+20)
12642                    || volt < (mHistoryCur.batteryVoltage-20)) {
12643                mHistoryCur.batteryVoltage = (char)volt;
12644                changed = true;
12645            }
12646            if (chargeUAh >= (mHistoryCur.batteryChargeUAh+10)
12647                    || chargeUAh <= (mHistoryCur.batteryChargeUAh-10)) {
12648                if (chargeUAh < mHistoryCur.batteryChargeUAh) {
12649                    // Only record discharges
12650                    final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
12651                    mDischargeCounter.addCountLocked(chargeDiff);
12652                    mDischargeScreenOffCounter.addCountLocked(chargeDiff);
12653                    if (isScreenDoze(mScreenState)) {
12654                        mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
12655                    }
12656                    if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
12657                        mDischargeLightDozeCounter.addCountLocked(chargeDiff);
12658                    } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
12659                        mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
12660                    }
12661                }
12662                mHistoryCur.batteryChargeUAh = chargeUAh;
12663                changed = true;
12664            }
12665            long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
12666                    | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
12667                    | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
12668            if (onBattery) {
12669                changed |= setChargingLocked(false);
12670                if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
12671                    mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
12672                            modeBits, elapsedRealtime);
12673                    mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
12674                            modeBits, elapsedRealtime);
12675                    mLastDischargeStepLevel = level;
12676                    mMinDischargeStepLevel = level;
12677                    mInitStepMode = mCurStepMode;
12678                    mModStepMode = 0;
12679                }
12680            } else {
12681                if (level >= 90) {
12682                    // If the battery level is at least 90%, always consider the device to be
12683                    // charging even if it happens to go down a level.
12684                    changed |= setChargingLocked(true);
12685                    mLastChargeStepLevel = level;
12686                } if (!mCharging) {
12687                    if (mLastChargeStepLevel < level) {
12688                        // We have not reporting that we are charging, but the level has now
12689                        // gone up, so consider the state to be charging.
12690                        changed |= setChargingLocked(true);
12691                        mLastChargeStepLevel = level;
12692                    }
12693                } else {
12694                    if (mLastChargeStepLevel > level) {
12695                        // We had reported that the device was charging, but here we are with
12696                        // power connected and the level going down.  Looks like the current
12697                        // power supplied isn't enough, so consider the device to now be
12698                        // discharging.
12699                        changed |= setChargingLocked(false);
12700                        mLastChargeStepLevel = level;
12701                    }
12702                }
12703                if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
12704                    mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
12705                            modeBits, elapsedRealtime);
12706                    mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
12707                            modeBits, elapsedRealtime);
12708                    mLastChargeStepLevel = level;
12709                    mMaxChargeStepLevel = level;
12710                    mInitStepMode = mCurStepMode;
12711                    mModStepMode = 0;
12712                }
12713            }
12714            if (changed) {
12715                addHistoryRecordLocked(elapsedRealtime, uptime);
12716            }
12717        }
12718        if (!onBattery &&
12719            (status == BatteryManager.BATTERY_STATUS_FULL ||
12720             status == BatteryManager.BATTERY_STATUS_UNKNOWN)) {
12721            // We don't record history while we are plugged in and fully charged
12722            // (or when battery is not present).  The next time we are
12723            // unplugged, history will be cleared.
12724            mRecordingHistory = DEBUG;
12725        }
12726
12727        if (mMinLearnedBatteryCapacity == -1) {
12728            mMinLearnedBatteryCapacity = chargeFullUAh;
12729        } else {
12730            Math.min(mMinLearnedBatteryCapacity, chargeFullUAh);
12731        }
12732        mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh);
12733    }
12734
12735    public static boolean isOnBattery(int plugType, int status) {
12736        return plugType == BATTERY_PLUGGED_NONE && status != BatteryManager.BATTERY_STATUS_UNKNOWN;
12737    }
12738
12739    // Inform StatsLog of setBatteryState changes.
12740    // If this is the first reporting, pass in recentPast == null.
12741    private void reportChangesToStatsLog(HistoryItem recentPast,
12742            final int status, final int plugType, final int level) {
12743
12744        if (recentPast == null || recentPast.batteryStatus != status) {
12745            StatsLog.write(StatsLog.CHARGING_STATE_CHANGED, status);
12746        }
12747        if (recentPast == null || recentPast.batteryPlugType != plugType) {
12748            StatsLog.write(StatsLog.PLUGGED_STATE_CHANGED, plugType);
12749        }
12750        if (recentPast == null || recentPast.batteryLevel != level) {
12751            StatsLog.write(StatsLog.BATTERY_LEVEL_CHANGED, level);
12752        }
12753    }
12754
12755    public long getAwakeTimeBattery() {
12756        return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
12757    }
12758
12759    public long getAwakeTimePlugged() {
12760        return (mClocks.uptimeMillis() * 1000) - getAwakeTimeBattery();
12761    }
12762
12763    @Override
12764    public long computeUptime(long curTime, int which) {
12765        switch (which) {
12766            case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart);
12767            case STATS_CURRENT: return (curTime-mUptimeStart);
12768            case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getUptimeStart());
12769        }
12770        return 0;
12771    }
12772
12773    @Override
12774    public long computeRealtime(long curTime, int which) {
12775        switch (which) {
12776            case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart);
12777            case STATS_CURRENT: return (curTime-mRealtimeStart);
12778            case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getRealtimeStart());
12779        }
12780        return 0;
12781    }
12782
12783    @Override
12784    public long computeBatteryUptime(long curTime, int which) {
12785        return mOnBatteryTimeBase.computeUptime(curTime, which);
12786    }
12787
12788    @Override
12789    public long computeBatteryRealtime(long curTime, int which) {
12790        return mOnBatteryTimeBase.computeRealtime(curTime, which);
12791    }
12792
12793    @Override
12794    public long computeBatteryScreenOffUptime(long curTime, int which) {
12795        return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
12796    }
12797
12798    @Override
12799    public long computeBatteryScreenOffRealtime(long curTime, int which) {
12800        return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
12801    }
12802
12803    private long computeTimePerLevel(long[] steps, int numSteps) {
12804        // For now we'll do a simple average across all steps.
12805        if (numSteps <= 0) {
12806            return -1;
12807        }
12808        long total = 0;
12809        for (int i=0; i<numSteps; i++) {
12810            total += steps[i] & STEP_LEVEL_TIME_MASK;
12811        }
12812        return total / numSteps;
12813        /*
12814        long[] buckets = new long[numSteps];
12815        int numBuckets = 0;
12816        int numToAverage = 4;
12817        int i = 0;
12818        while (i < numSteps) {
12819            long totalTime = 0;
12820            int num = 0;
12821            for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
12822                totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
12823                num++;
12824            }
12825            buckets[numBuckets] = totalTime / num;
12826            numBuckets++;
12827            numToAverage *= 2;
12828            i += num;
12829        }
12830        if (numBuckets < 1) {
12831            return -1;
12832        }
12833        long averageTime = buckets[numBuckets-1];
12834        for (i=numBuckets-2; i>=0; i--) {
12835            averageTime = (averageTime + buckets[i]) / 2;
12836        }
12837        return averageTime;
12838        */
12839    }
12840
12841    @Override
12842    public long computeBatteryTimeRemaining(long curTime) {
12843        if (!mOnBattery) {
12844            return -1;
12845        }
12846        /* Simple implementation just looks at the average discharge per level across the
12847           entire sample period.
12848        int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
12849        if (discharge < 2) {
12850            return -1;
12851        }
12852        long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
12853        if (duration < 1000*1000) {
12854            return -1;
12855        }
12856        long usPerLevel = duration/discharge;
12857        return usPerLevel * mCurrentBatteryLevel;
12858        */
12859        if (mDischargeStepTracker.mNumStepDurations < 1) {
12860            return -1;
12861        }
12862        long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
12863        if (msPerLevel <= 0) {
12864            return -1;
12865        }
12866        return (msPerLevel * mCurrentBatteryLevel) * 1000;
12867    }
12868
12869    @Override
12870    public LevelStepTracker getDischargeLevelStepTracker() {
12871        return mDischargeStepTracker;
12872    }
12873
12874    @Override
12875    public LevelStepTracker getDailyDischargeLevelStepTracker() {
12876        return mDailyDischargeStepTracker;
12877    }
12878
12879    @Override
12880    public long computeChargeTimeRemaining(long curTime) {
12881        if (mOnBattery) {
12882            // Not yet working.
12883            return -1;
12884        }
12885        /* Broken
12886        int curLevel = mCurrentBatteryLevel;
12887        int plugLevel = mDischargePlugLevel;
12888        if (plugLevel < 0 || curLevel < (plugLevel+1)) {
12889            return -1;
12890        }
12891        long duration = computeBatteryRealtime(curTime, STATS_SINCE_UNPLUGGED);
12892        if (duration < 1000*1000) {
12893            return -1;
12894        }
12895        long usPerLevel = duration/(curLevel-plugLevel);
12896        return usPerLevel * (100-curLevel);
12897        */
12898        if (mChargeStepTracker.mNumStepDurations < 1) {
12899            return -1;
12900        }
12901        long msPerLevel = mChargeStepTracker.computeTimePerLevel();
12902        if (msPerLevel <= 0) {
12903            return -1;
12904        }
12905        return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
12906    }
12907
12908    /*@hide */
12909    public CellularBatteryStats getCellularBatteryStats() {
12910        CellularBatteryStats s = new CellularBatteryStats();
12911        final int which = STATS_SINCE_CHARGED;
12912        final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
12913        final ControllerActivityCounter counter = getModemControllerActivity();
12914        final long sleepTimeMs = counter.getSleepTimeCounter().getCountLocked(which);
12915        final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
12916        final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
12917        final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
12918        long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
12919        for (int i = 0; i < timeInRatMs.length; i++) {
12920           timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTime, which) / 1000;
12921        }
12922        long[] timeInRxSignalStrengthLevelMs = new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
12923        for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
12924           timeInRxSignalStrengthLevelMs[i]
12925               = getPhoneSignalStrengthTime(i, rawRealTime, which) / 1000;
12926        }
12927        long[] txTimeMs = new long[Math.min(ModemActivityInfo.TX_POWER_LEVELS,
12928            counter.getTxTimeCounters().length)];
12929        long totalTxTimeMs = 0;
12930        for (int i = 0; i < txTimeMs.length; i++) {
12931            txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
12932            totalTxTimeMs += txTimeMs[i];
12933        }
12934        s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
12935        s.setKernelActiveTimeMs(getMobileRadioActiveTime(rawRealTime, which) / 1000);
12936        s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which));
12937        s.setNumBytesTx(getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which));
12938        s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which));
12939        s.setNumBytesRx(getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which));
12940        s.setSleepTimeMs(sleepTimeMs);
12941        s.setIdleTimeMs(idleTimeMs);
12942        s.setRxTimeMs(rxTimeMs);
12943        s.setEnergyConsumedMaMs(energyConsumedMaMs);
12944        s.setTimeInRatMs(timeInRatMs);
12945        s.setTimeInRxSignalStrengthLevelMs(timeInRxSignalStrengthLevelMs);
12946        s.setTxTimeMs(txTimeMs);
12947        return s;
12948    }
12949
12950     /*@hide */
12951     public WifiBatteryStats getWifiBatteryStats() {
12952         WifiBatteryStats s = new WifiBatteryStats();
12953         final int which = STATS_SINCE_CHARGED;
12954         final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
12955         final ControllerActivityCounter counter = getWifiControllerActivity();
12956         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
12957         final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which);
12958         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
12959         final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which);
12960         final long totalControllerActivityTimeMs
12961             = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000;
12962         final long sleepTimeMs
12963             = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs);
12964         final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
12965         long numAppScanRequest = 0;
12966         for (int i = 0; i < mUidStats.size(); i++) {
12967             numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which);
12968         }
12969         long[] timeInStateMs = new long[NUM_WIFI_STATES];
12970         for (int i=0; i<NUM_WIFI_STATES; i++) {
12971            timeInStateMs[i] = getWifiStateTime(i, rawRealTime, which) / 1000;
12972         }
12973         long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES];
12974         for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
12975             timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTime, which) / 1000;
12976         }
12977         long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS];
12978         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
12979             timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTime, which) / 1000;
12980         }
12981         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
12982         s.setKernelActiveTimeMs(getWifiActiveTime(rawRealTime, which) / 1000);
12983         s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which));
12984         s.setNumBytesTx(getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which));
12985         s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which));
12986         s.setNumBytesRx(getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which));
12987         s.setSleepTimeMs(sleepTimeMs);
12988         s.setIdleTimeMs(idleTimeMs);
12989         s.setRxTimeMs(rxTimeMs);
12990         s.setTxTimeMs(txTimeMs);
12991         s.setScanTimeMs(scanTimeMs);
12992         s.setEnergyConsumedMaMs(energyConsumedMaMs);
12993         s.setNumAppScanRequest(numAppScanRequest);
12994         s.setTimeInStateMs(timeInStateMs);
12995         s.setTimeInSupplicantStateMs(timeInSupplStateMs);
12996         s.setTimeInRxSignalStrengthLevelMs(timeSignalStrengthTimeMs);
12997         return s;
12998     }
12999
13000    /*@hide */
13001    public GpsBatteryStats getGpsBatteryStats() {
13002        GpsBatteryStats s = new GpsBatteryStats();
13003        final int which = STATS_SINCE_CHARGED;
13004        final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
13005        s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
13006        s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
13007        long[] time = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
13008        for (int i=0; i<time.length; i++) {
13009            time[i] = getGpsSignalQualityTime(i, rawRealTime, which) / 1000;
13010        }
13011        s.setTimeInGpsSignalQualityLevel(time);
13012        return s;
13013    }
13014
13015    @Override
13016    public LevelStepTracker getChargeLevelStepTracker() {
13017        return mChargeStepTracker;
13018    }
13019
13020    @Override
13021    public LevelStepTracker getDailyChargeLevelStepTracker() {
13022        return mDailyChargeStepTracker;
13023    }
13024
13025    @Override
13026    public ArrayList<PackageChange> getDailyPackageChanges() {
13027        return mDailyPackageChanges;
13028    }
13029
13030    protected long getBatteryUptimeLocked() {
13031        return mOnBatteryTimeBase.getUptime(mClocks.uptimeMillis() * 1000);
13032    }
13033
13034    @Override
13035    public long getBatteryUptime(long curTime) {
13036        return mOnBatteryTimeBase.getUptime(curTime);
13037    }
13038
13039    @Override
13040    public long getBatteryRealtime(long curTime) {
13041        return mOnBatteryTimeBase.getRealtime(curTime);
13042    }
13043
13044    @Override
13045    public int getDischargeStartLevel() {
13046        synchronized(this) {
13047            return getDischargeStartLevelLocked();
13048        }
13049    }
13050
13051    public int getDischargeStartLevelLocked() {
13052            return mDischargeUnplugLevel;
13053    }
13054
13055    @Override
13056    public int getDischargeCurrentLevel() {
13057        synchronized(this) {
13058            return getDischargeCurrentLevelLocked();
13059        }
13060    }
13061
13062    public int getDischargeCurrentLevelLocked() {
13063        return mDischargeCurrentLevel;
13064    }
13065
13066    @Override
13067    public int getLowDischargeAmountSinceCharge() {
13068        synchronized(this) {
13069            int val = mLowDischargeAmountSinceCharge;
13070            if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
13071                val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
13072            }
13073            return val;
13074        }
13075    }
13076
13077    @Override
13078    public int getHighDischargeAmountSinceCharge() {
13079        synchronized(this) {
13080            int val = mHighDischargeAmountSinceCharge;
13081            if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
13082                val += mDischargeUnplugLevel-mDischargeCurrentLevel;
13083            }
13084            return val;
13085        }
13086    }
13087
13088    @Override
13089    public int getDischargeAmount(int which) {
13090        int dischargeAmount = which == STATS_SINCE_CHARGED
13091                ? getHighDischargeAmountSinceCharge()
13092                : (getDischargeStartLevel() - getDischargeCurrentLevel());
13093        if (dischargeAmount < 0) {
13094            dischargeAmount = 0;
13095        }
13096        return dischargeAmount;
13097    }
13098
13099    @Override
13100    public int getDischargeAmountScreenOn() {
13101        synchronized(this) {
13102            int val = mDischargeAmountScreenOn;
13103            if (mOnBattery && isScreenOn(mScreenState)
13104                    && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
13105                val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
13106            }
13107            return val;
13108        }
13109    }
13110
13111    @Override
13112    public int getDischargeAmountScreenOnSinceCharge() {
13113        synchronized(this) {
13114            int val = mDischargeAmountScreenOnSinceCharge;
13115            if (mOnBattery && isScreenOn(mScreenState)
13116                    && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
13117                val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
13118            }
13119            return val;
13120        }
13121    }
13122
13123    @Override
13124    public int getDischargeAmountScreenOff() {
13125        synchronized(this) {
13126            int val = mDischargeAmountScreenOff;
13127            if (mOnBattery && isScreenOff(mScreenState)
13128                    && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
13129                val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
13130            }
13131            // For backward compatibility, doze discharge is counted into screen off.
13132            return val + getDischargeAmountScreenDoze();
13133        }
13134    }
13135
13136    @Override
13137    public int getDischargeAmountScreenOffSinceCharge() {
13138        synchronized(this) {
13139            int val = mDischargeAmountScreenOffSinceCharge;
13140            if (mOnBattery && isScreenOff(mScreenState)
13141                    && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
13142                val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
13143            }
13144            // For backward compatibility, doze discharge is counted into screen off.
13145            return val + getDischargeAmountScreenDozeSinceCharge();
13146        }
13147    }
13148
13149    @Override
13150    public int getDischargeAmountScreenDoze() {
13151        synchronized(this) {
13152            int val = mDischargeAmountScreenDoze;
13153            if (mOnBattery && isScreenDoze(mScreenState)
13154                    && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
13155                val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
13156            }
13157            return val;
13158        }
13159    }
13160
13161    @Override
13162    public int getDischargeAmountScreenDozeSinceCharge() {
13163        synchronized(this) {
13164            int val = mDischargeAmountScreenDozeSinceCharge;
13165            if (mOnBattery && isScreenDoze(mScreenState)
13166                    && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
13167                val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
13168            }
13169            return val;
13170        }
13171    }
13172
13173    /**
13174     * Retrieve the statistics object for a particular uid, creating if needed.
13175     */
13176    public Uid getUidStatsLocked(int uid) {
13177        Uid u = mUidStats.get(uid);
13178        if (u == null) {
13179            u = new Uid(this, uid);
13180            mUidStats.put(uid, u);
13181        }
13182        return u;
13183    }
13184
13185    /**
13186     * Retrieve the statistics object for a particular uid. Returns null if the object is not
13187     * available.
13188     */
13189    public Uid getAvailableUidStatsLocked(int uid) {
13190        Uid u = mUidStats.get(uid);
13191        return u;
13192    }
13193
13194    public void onCleanupUserLocked(int userId) {
13195        final int firstUidForUser = UserHandle.getUid(userId, 0);
13196        final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
13197        mPendingRemovedUids.add(
13198                new UidToRemove(firstUidForUser, lastUidForUser, mClocks.elapsedRealtime()));
13199    }
13200
13201    public void onUserRemovedLocked(int userId) {
13202        final int firstUidForUser = UserHandle.getUid(userId, 0);
13203        final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
13204        mUidStats.put(firstUidForUser, null);
13205        mUidStats.put(lastUidForUser, null);
13206        final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
13207        final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
13208        mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
13209    }
13210
13211    /**
13212     * Remove the statistics object for a particular uid.
13213     */
13214    public void removeUidStatsLocked(int uid) {
13215        mUidStats.remove(uid);
13216        mPendingRemovedUids.add(new UidToRemove(uid, mClocks.elapsedRealtime()));
13217    }
13218
13219    /**
13220     * Retrieve the statistics object for a particular process, creating
13221     * if needed.
13222     */
13223    public Uid.Proc getProcessStatsLocked(int uid, String name) {
13224        uid = mapUid(uid);
13225        Uid u = getUidStatsLocked(uid);
13226        return u.getProcessStatsLocked(name);
13227    }
13228
13229    /**
13230     * Retrieve the statistics object for a particular process, creating
13231     * if needed.
13232     */
13233    public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
13234        uid = mapUid(uid);
13235        Uid u = getUidStatsLocked(uid);
13236        return u.getPackageStatsLocked(pkg);
13237    }
13238
13239    /**
13240     * Retrieve the statistics object for a particular service, creating
13241     * if needed.
13242     */
13243    public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
13244        uid = mapUid(uid);
13245        Uid u = getUidStatsLocked(uid);
13246        return u.getServiceStatsLocked(pkg, name);
13247    }
13248
13249    public void shutdownLocked() {
13250        recordShutdownLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
13251        writeSyncLocked();
13252        mShuttingDown = true;
13253    }
13254
13255    public boolean trackPerProcStateCpuTimes() {
13256        return mConstants.TRACK_CPU_TIMES_BY_PROC_STATE && mPerProcStateCpuTimesAvailable;
13257    }
13258
13259    public void systemServicesReady(Context context) {
13260        mConstants.startObserving(context.getContentResolver());
13261        registerUsbStateReceiver(context);
13262    }
13263
13264    @VisibleForTesting
13265    public final class Constants extends ContentObserver {
13266        public static final String KEY_TRACK_CPU_TIMES_BY_PROC_STATE
13267                = "track_cpu_times_by_proc_state";
13268        public static final String KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME
13269                = "track_cpu_active_cluster_time";
13270        public static final String KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS
13271                = "proc_state_cpu_times_read_delay_ms";
13272        public static final String KEY_KERNEL_UID_READERS_THROTTLE_TIME
13273                = "kernel_uid_readers_throttle_time";
13274        public static final String KEY_UID_REMOVE_DELAY_MS
13275                = "uid_remove_delay_ms";
13276        public static final String KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
13277                = "external_stats_collection_rate_limit_ms";
13278        public static final String KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS
13279                = "battery_level_collection_delay_ms";
13280
13281        private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = true;
13282        private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
13283        private static final long DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS = 5_000;
13284        private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 10_000;
13285        private static final long DEFAULT_UID_REMOVE_DELAY_MS = 5L * 60L * 1000L;
13286        private static final long DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = 600_000;
13287        private static final long DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS = 300_000;
13288
13289        public boolean TRACK_CPU_TIMES_BY_PROC_STATE = DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE;
13290        public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
13291        public long PROC_STATE_CPU_TIMES_READ_DELAY_MS = DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS;
13292        public long KERNEL_UID_READERS_THROTTLE_TIME = DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME;
13293        public long UID_REMOVE_DELAY_MS = DEFAULT_UID_REMOVE_DELAY_MS;
13294        public long EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
13295                = DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
13296        public long BATTERY_LEVEL_COLLECTION_DELAY_MS
13297                = DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS;
13298
13299        private ContentResolver mResolver;
13300        private final KeyValueListParser mParser = new KeyValueListParser(',');
13301
13302        public Constants(Handler handler) {
13303            super(handler);
13304        }
13305
13306        public void startObserving(ContentResolver resolver) {
13307            mResolver = resolver;
13308            mResolver.registerContentObserver(
13309                    Settings.Global.getUriFor(Settings.Global.BATTERY_STATS_CONSTANTS),
13310                    false /* notifyForDescendants */, this);
13311            updateConstants();
13312        }
13313
13314        @Override
13315        public void onChange(boolean selfChange, Uri uri) {
13316            updateConstants();
13317        }
13318
13319        private void updateConstants() {
13320            synchronized (BatteryStatsImpl.this) {
13321                try {
13322                    mParser.setString(Settings.Global.getString(mResolver,
13323                            Settings.Global.BATTERY_STATS_CONSTANTS));
13324                } catch (IllegalArgumentException e) {
13325                    // Failed to parse the settings string, log this and move on
13326                    // with defaults.
13327                    Slog.e(TAG, "Bad batterystats settings", e);
13328                }
13329
13330                updateTrackCpuTimesByProcStateLocked(TRACK_CPU_TIMES_BY_PROC_STATE,
13331                        mParser.getBoolean(KEY_TRACK_CPU_TIMES_BY_PROC_STATE,
13332                                DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE));
13333                TRACK_CPU_ACTIVE_CLUSTER_TIME = mParser.getBoolean(
13334                        KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME, DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME);
13335                updateProcStateCpuTimesReadDelayMs(PROC_STATE_CPU_TIMES_READ_DELAY_MS,
13336                        mParser.getLong(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS,
13337                                DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS));
13338                updateKernelUidReadersThrottleTime(KERNEL_UID_READERS_THROTTLE_TIME,
13339                        mParser.getLong(KEY_KERNEL_UID_READERS_THROTTLE_TIME,
13340                                DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME));
13341                updateUidRemoveDelay(
13342                        mParser.getLong(KEY_UID_REMOVE_DELAY_MS, DEFAULT_UID_REMOVE_DELAY_MS));
13343                EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = mParser.getLong(
13344                        KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS,
13345                        DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
13346                BATTERY_LEVEL_COLLECTION_DELAY_MS = mParser.getLong(
13347                        KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS,
13348                        DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS);
13349            }
13350        }
13351
13352        private void updateTrackCpuTimesByProcStateLocked(boolean wasEnabled, boolean isEnabled) {
13353            TRACK_CPU_TIMES_BY_PROC_STATE = isEnabled;
13354            if (isEnabled && !wasEnabled) {
13355                mKernelSingleUidTimeReader.markDataAsStale(true);
13356                mExternalSync.scheduleCpuSyncDueToSettingChange();
13357
13358                mNumSingleUidCpuTimeReads = 0;
13359                mNumBatchedSingleUidCpuTimeReads = 0;
13360                mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
13361            }
13362        }
13363
13364        private void updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis) {
13365            PROC_STATE_CPU_TIMES_READ_DELAY_MS = newDelayMillis;
13366            if (oldDelayMillis != newDelayMillis) {
13367                mNumSingleUidCpuTimeReads = 0;
13368                mNumBatchedSingleUidCpuTimeReads = 0;
13369                mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis();
13370            }
13371        }
13372
13373        private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
13374            KERNEL_UID_READERS_THROTTLE_TIME = newTimeMs;
13375            if (oldTimeMs != newTimeMs) {
13376                mKernelUidCpuTimeReader.setThrottleInterval(KERNEL_UID_READERS_THROTTLE_TIME);
13377                mKernelUidCpuFreqTimeReader.setThrottleInterval(KERNEL_UID_READERS_THROTTLE_TIME);
13378                mKernelUidCpuActiveTimeReader.setThrottleInterval(KERNEL_UID_READERS_THROTTLE_TIME);
13379                mKernelUidCpuClusterTimeReader
13380                        .setThrottleInterval(KERNEL_UID_READERS_THROTTLE_TIME);
13381            }
13382        }
13383
13384        private void updateUidRemoveDelay(long newTimeMs) {
13385            UID_REMOVE_DELAY_MS = newTimeMs;
13386            clearPendingRemovedUids();
13387        }
13388
13389        public void dumpLocked(PrintWriter pw) {
13390            pw.print(KEY_TRACK_CPU_TIMES_BY_PROC_STATE); pw.print("=");
13391            pw.println(TRACK_CPU_TIMES_BY_PROC_STATE);
13392            pw.print(KEY_TRACK_CPU_ACTIVE_CLUSTER_TIME); pw.print("=");
13393            pw.println(TRACK_CPU_ACTIVE_CLUSTER_TIME);
13394            pw.print(KEY_PROC_STATE_CPU_TIMES_READ_DELAY_MS); pw.print("=");
13395            pw.println(PROC_STATE_CPU_TIMES_READ_DELAY_MS);
13396            pw.print(KEY_KERNEL_UID_READERS_THROTTLE_TIME); pw.print("=");
13397            pw.println(KERNEL_UID_READERS_THROTTLE_TIME);
13398            pw.print(KEY_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS); pw.print("=");
13399            pw.println(EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
13400            pw.print(KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS); pw.print("=");
13401            pw.println(BATTERY_LEVEL_COLLECTION_DELAY_MS);
13402        }
13403    }
13404
13405    public long getExternalStatsCollectionRateLimitMs() {
13406        synchronized (this) {
13407            return mConstants.EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
13408        }
13409    }
13410
13411    @GuardedBy("this")
13412    public void dumpConstantsLocked(PrintWriter pw) {
13413        mConstants.dumpLocked(pw);
13414    }
13415
13416    @GuardedBy("this")
13417    public void dumpCpuStatsLocked(PrintWriter pw) {
13418        int size = mUidStats.size();
13419        pw.println("Per UID CPU user & system time in ms:");
13420        for (int i = 0; i < size; i++) {
13421            int u = mUidStats.keyAt(i);
13422            Uid uid = mUidStats.get(u);
13423            pw.print("  "); pw.print(u); pw.print(": ");
13424            pw.print(uid.getUserCpuTimeUs(STATS_SINCE_CHARGED) / 1000); pw.print(" ");
13425            pw.println(uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED) / 1000);
13426        }
13427        pw.println("Per UID CPU active time in ms:");
13428        for (int i = 0; i < size; i++) {
13429            int u = mUidStats.keyAt(i);
13430            Uid uid = mUidStats.get(u);
13431            if (uid.getCpuActiveTime() > 0) {
13432                pw.print("  "); pw.print(u); pw.print(": "); pw.println(uid.getCpuActiveTime());
13433            }
13434        }
13435        pw.println("Per UID CPU cluster time in ms:");
13436        for (int i = 0; i < size; i++) {
13437            int u = mUidStats.keyAt(i);
13438            long[] times = mUidStats.get(u).getCpuClusterTimes();
13439            if (times != null) {
13440                pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
13441            }
13442        }
13443        pw.println("Per UID CPU frequency time in ms:");
13444        for (int i = 0; i < size; i++) {
13445            int u = mUidStats.keyAt(i);
13446            long[] times = mUidStats.get(u).getCpuFreqTimes(STATS_SINCE_CHARGED);
13447            if (times != null) {
13448                pw.print("  "); pw.print(u); pw.print(": "); pw.println(Arrays.toString(times));
13449            }
13450        }
13451    }
13452
13453    Parcel mPendingWrite = null;
13454    final ReentrantLock mWriteLock = new ReentrantLock();
13455
13456    public void writeAsyncLocked() {
13457        writeLocked(false);
13458    }
13459
13460    public void writeSyncLocked() {
13461        writeLocked(true);
13462    }
13463
13464    void writeLocked(boolean sync) {
13465        if (mFile == null) {
13466            Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
13467            return;
13468        }
13469
13470        if (mShuttingDown) {
13471            return;
13472        }
13473
13474        Parcel out = Parcel.obtain();
13475        writeSummaryToParcel(out, true);
13476        mLastWriteTime = mClocks.elapsedRealtime();
13477
13478        if (mPendingWrite != null) {
13479            mPendingWrite.recycle();
13480        }
13481        mPendingWrite = out;
13482
13483        if (sync) {
13484            commitPendingDataToDisk();
13485        } else {
13486            BackgroundThread.getHandler().post(new Runnable() {
13487                @Override public void run() {
13488                    commitPendingDataToDisk();
13489                }
13490            });
13491        }
13492    }
13493
13494    public void commitPendingDataToDisk() {
13495        final Parcel next;
13496        synchronized (this) {
13497            next = mPendingWrite;
13498            mPendingWrite = null;
13499            if (next == null) {
13500                return;
13501            }
13502        }
13503
13504        mWriteLock.lock();
13505        try {
13506            final long startTime = SystemClock.uptimeMillis();
13507            FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
13508            stream.write(next.marshall());
13509            stream.flush();
13510            FileUtils.sync(stream);
13511            stream.close();
13512            mFile.commit();
13513            com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
13514                    "batterystats", SystemClock.uptimeMillis() - startTime);
13515        } catch (IOException e) {
13516            Slog.w("BatteryStats", "Error writing battery statistics", e);
13517            mFile.rollback();
13518        } finally {
13519            next.recycle();
13520            mWriteLock.unlock();
13521        }
13522    }
13523
13524    public void readLocked() {
13525        if (mDailyFile != null) {
13526            readDailyStatsLocked();
13527        }
13528
13529        if (mFile == null) {
13530            Slog.w("BatteryStats", "readLocked: no file associated with this instance");
13531            return;
13532        }
13533
13534        mUidStats.clear();
13535
13536        try {
13537            File file = mFile.chooseForRead();
13538            if (!file.exists()) {
13539                return;
13540            }
13541            FileInputStream stream = new FileInputStream(file);
13542
13543            byte[] raw = BatteryStatsHelper.readFully(stream);
13544            Parcel in = Parcel.obtain();
13545            in.unmarshall(raw, 0, raw.length);
13546            in.setDataPosition(0);
13547            stream.close();
13548
13549            readSummaryFromParcel(in);
13550        } catch(Exception e) {
13551            Slog.e("BatteryStats", "Error reading battery statistics", e);
13552            resetAllStatsLocked();
13553        }
13554
13555        mEndPlatformVersion = Build.ID;
13556
13557        if (mHistoryBuffer.dataPosition() > 0) {
13558            mRecordingHistory = true;
13559            final long elapsedRealtime = mClocks.elapsedRealtime();
13560            final long uptime = mClocks.uptimeMillis();
13561            if (USE_OLD_HISTORY) {
13562                addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
13563            }
13564            addHistoryBufferLocked(elapsedRealtime, HistoryItem.CMD_START, mHistoryCur);
13565            startRecordingHistory(elapsedRealtime, uptime, false);
13566        }
13567
13568        recordDailyStatsIfNeededLocked(false);
13569    }
13570
13571    public int describeContents() {
13572        return 0;
13573    }
13574
13575    void readHistory(Parcel in, boolean andOldHistory) throws ParcelFormatException {
13576        final long historyBaseTime = in.readLong();
13577
13578        mHistoryBuffer.setDataSize(0);
13579        mHistoryBuffer.setDataPosition(0);
13580        mHistoryTagPool.clear();
13581        mNextHistoryTagIdx = 0;
13582        mNumHistoryTagChars = 0;
13583
13584        int numTags = in.readInt();
13585        for (int i=0; i<numTags; i++) {
13586            int idx = in.readInt();
13587            String str = in.readString();
13588            if (str == null) {
13589                throw new ParcelFormatException("null history tag string");
13590            }
13591            int uid = in.readInt();
13592            HistoryTag tag = new HistoryTag();
13593            tag.string = str;
13594            tag.uid = uid;
13595            tag.poolIdx = idx;
13596            mHistoryTagPool.put(tag, idx);
13597            if (idx >= mNextHistoryTagIdx) {
13598                mNextHistoryTagIdx = idx+1;
13599            }
13600            mNumHistoryTagChars += tag.string.length() + 1;
13601        }
13602
13603        int bufSize = in.readInt();
13604        int curPos = in.dataPosition();
13605        if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) {
13606            throw new ParcelFormatException("File corrupt: history data buffer too large " +
13607                    bufSize);
13608        } else if ((bufSize&~3) != bufSize) {
13609            throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
13610                    bufSize);
13611        } else {
13612            if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
13613                    + " bytes at " + curPos);
13614            mHistoryBuffer.appendFrom(in, curPos, bufSize);
13615            in.setDataPosition(curPos + bufSize);
13616        }
13617
13618        if (andOldHistory) {
13619            readOldHistory(in);
13620        }
13621
13622        if (DEBUG_HISTORY) {
13623            StringBuilder sb = new StringBuilder(128);
13624            sb.append("****************** OLD mHistoryBaseTime: ");
13625            TimeUtils.formatDuration(mHistoryBaseTime, sb);
13626            Slog.i(TAG, sb.toString());
13627        }
13628        mHistoryBaseTime = historyBaseTime;
13629        if (DEBUG_HISTORY) {
13630            StringBuilder sb = new StringBuilder(128);
13631            sb.append("****************** NEW mHistoryBaseTime: ");
13632            TimeUtils.formatDuration(mHistoryBaseTime, sb);
13633            Slog.i(TAG, sb.toString());
13634        }
13635
13636        // We are just arbitrarily going to insert 1 minute from the sample of
13637        // the last run until samples in this run.
13638        if (mHistoryBaseTime > 0) {
13639            long oldnow = mClocks.elapsedRealtime();
13640            mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
13641            if (DEBUG_HISTORY) {
13642                StringBuilder sb = new StringBuilder(128);
13643                sb.append("****************** ADJUSTED mHistoryBaseTime: ");
13644                TimeUtils.formatDuration(mHistoryBaseTime, sb);
13645                Slog.i(TAG, sb.toString());
13646            }
13647        }
13648    }
13649
13650    void readOldHistory(Parcel in) {
13651        if (!USE_OLD_HISTORY) {
13652            return;
13653        }
13654        mHistory = mHistoryEnd = mHistoryCache = null;
13655        long time;
13656        while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
13657            HistoryItem rec = new HistoryItem(time, in);
13658            addHistoryRecordLocked(rec);
13659        }
13660    }
13661
13662    void writeHistory(Parcel out, boolean inclData, boolean andOldHistory) {
13663        if (DEBUG_HISTORY) {
13664            StringBuilder sb = new StringBuilder(128);
13665            sb.append("****************** WRITING mHistoryBaseTime: ");
13666            TimeUtils.formatDuration(mHistoryBaseTime, sb);
13667            sb.append(" mLastHistoryElapsedRealtime: ");
13668            TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
13669            Slog.i(TAG, sb.toString());
13670        }
13671        out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
13672        if (!inclData) {
13673            out.writeInt(0);
13674            out.writeInt(0);
13675            return;
13676        }
13677        out.writeInt(mHistoryTagPool.size());
13678        for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
13679            HistoryTag tag = ent.getKey();
13680            out.writeInt(ent.getValue());
13681            out.writeString(tag.string);
13682            out.writeInt(tag.uid);
13683        }
13684        out.writeInt(mHistoryBuffer.dataSize());
13685        if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
13686                + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
13687        out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
13688
13689        if (andOldHistory) {
13690            writeOldHistory(out);
13691        }
13692    }
13693
13694    void writeOldHistory(Parcel out) {
13695        if (!USE_OLD_HISTORY) {
13696            return;
13697        }
13698        HistoryItem rec = mHistory;
13699        while (rec != null) {
13700            if (rec.time >= 0) rec.writeToParcel(out, 0);
13701            rec = rec.next;
13702        }
13703        out.writeLong(-1);
13704    }
13705
13706    public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
13707        final int version = in.readInt();
13708        if (version != VERSION) {
13709            Slog.w("BatteryStats", "readFromParcel: version got " + version
13710                + ", expected " + VERSION + "; erasing old stats");
13711            return;
13712        }
13713
13714        readHistory(in, true);
13715
13716        mStartCount = in.readInt();
13717        mUptime = in.readLong();
13718        mRealtime = in.readLong();
13719        mStartClockTime = in.readLong();
13720        mStartPlatformVersion = in.readString();
13721        mEndPlatformVersion = in.readString();
13722        mOnBatteryTimeBase.readSummaryFromParcel(in);
13723        mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
13724        mDischargeUnplugLevel = in.readInt();
13725        mDischargePlugLevel = in.readInt();
13726        mDischargeCurrentLevel = in.readInt();
13727        mCurrentBatteryLevel = in.readInt();
13728        mEstimatedBatteryCapacity = in.readInt();
13729        mMinLearnedBatteryCapacity = in.readInt();
13730        mMaxLearnedBatteryCapacity = in.readInt();
13731        mLowDischargeAmountSinceCharge = in.readInt();
13732        mHighDischargeAmountSinceCharge = in.readInt();
13733        mDischargeAmountScreenOnSinceCharge = in.readInt();
13734        mDischargeAmountScreenOffSinceCharge = in.readInt();
13735        mDischargeAmountScreenDozeSinceCharge = in.readInt();
13736        mDischargeStepTracker.readFromParcel(in);
13737        mChargeStepTracker.readFromParcel(in);
13738        mDailyDischargeStepTracker.readFromParcel(in);
13739        mDailyChargeStepTracker.readFromParcel(in);
13740        mDischargeCounter.readSummaryFromParcelLocked(in);
13741        mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
13742        mDischargeScreenDozeCounter.readSummaryFromParcelLocked(in);
13743        mDischargeLightDozeCounter.readSummaryFromParcelLocked(in);
13744        mDischargeDeepDozeCounter.readSummaryFromParcelLocked(in);
13745        int NPKG = in.readInt();
13746        if (NPKG > 0) {
13747            mDailyPackageChanges = new ArrayList<>(NPKG);
13748            while (NPKG > 0) {
13749                NPKG--;
13750                PackageChange pc = new PackageChange();
13751                pc.mPackageName = in.readString();
13752                pc.mUpdate = in.readInt() != 0;
13753                pc.mVersionCode = in.readLong();
13754                mDailyPackageChanges.add(pc);
13755            }
13756        } else {
13757            mDailyPackageChanges = null;
13758        }
13759        mDailyStartTime = in.readLong();
13760        mNextMinDailyDeadline = in.readLong();
13761        mNextMaxDailyDeadline = in.readLong();
13762
13763        mStartCount++;
13764
13765        mScreenState = Display.STATE_UNKNOWN;
13766        mScreenOnTimer.readSummaryFromParcelLocked(in);
13767        mScreenDozeTimer.readSummaryFromParcelLocked(in);
13768        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
13769            mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
13770        }
13771        mInteractive = false;
13772        mInteractiveTimer.readSummaryFromParcelLocked(in);
13773        mPhoneOn = false;
13774        mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
13775        mLongestLightIdleTime = in.readLong();
13776        mLongestFullIdleTime = in.readLong();
13777        mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
13778        mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
13779        mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
13780        mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
13781        mPhoneOnTimer.readSummaryFromParcelLocked(in);
13782        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
13783            mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
13784        }
13785        mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
13786        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
13787            mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
13788        }
13789        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
13790            mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
13791            mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
13792        }
13793        mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
13794        mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
13795        mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
13796        mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
13797        mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
13798        mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
13799        mWifiMulticastWakelockTimer.readSummaryFromParcelLocked(in);
13800        mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
13801        mWifiOn = false;
13802        mWifiOnTimer.readSummaryFromParcelLocked(in);
13803        mGlobalWifiRunning = false;
13804        mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
13805        for (int i=0; i<NUM_WIFI_STATES; i++) {
13806            mWifiStateTimer[i].readSummaryFromParcelLocked(in);
13807        }
13808        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
13809            mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
13810        }
13811        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
13812            mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
13813        }
13814        mWifiActiveTimer.readSummaryFromParcelLocked(in);
13815        mWifiActivity.readSummaryFromParcel(in);
13816        for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
13817            mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
13818        }
13819        mBluetoothActivity.readSummaryFromParcel(in);
13820        mModemActivity.readSummaryFromParcel(in);
13821        mHasWifiReporting = in.readInt() != 0;
13822        mHasBluetoothReporting = in.readInt() != 0;
13823        mHasModemReporting = in.readInt() != 0;
13824
13825        mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
13826        mFlashlightOnNesting = 0;
13827        mFlashlightOnTimer.readSummaryFromParcelLocked(in);
13828        mCameraOnNesting = 0;
13829        mCameraOnTimer.readSummaryFromParcelLocked(in);
13830        mBluetoothScanNesting = 0;
13831        mBluetoothScanTimer.readSummaryFromParcelLocked(in);
13832        mIsCellularTxPowerHigh = false;
13833
13834        int NRPMS = in.readInt();
13835        if (NRPMS > 10000) {
13836            throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS);
13837        }
13838        for (int irpm = 0; irpm < NRPMS; irpm++) {
13839            if (in.readInt() != 0) {
13840                String rpmName = in.readString();
13841                getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
13842            }
13843        }
13844        int NSORPMS = in.readInt();
13845        if (NSORPMS > 10000) {
13846            throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS);
13847        }
13848        for (int irpm = 0; irpm < NSORPMS; irpm++) {
13849            if (in.readInt() != 0) {
13850                String rpmName = in.readString();
13851                getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
13852            }
13853        }
13854
13855        int NKW = in.readInt();
13856        if (NKW > 10000) {
13857            throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
13858        }
13859        for (int ikw = 0; ikw < NKW; ikw++) {
13860            if (in.readInt() != 0) {
13861                String kwltName = in.readString();
13862                getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
13863            }
13864        }
13865
13866        int NWR = in.readInt();
13867        if (NWR > 10000) {
13868            throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
13869        }
13870        for (int iwr = 0; iwr < NWR; iwr++) {
13871            if (in.readInt() != 0) {
13872                String reasonName = in.readString();
13873                getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
13874            }
13875        }
13876
13877        int NMS = in.readInt();
13878        for (int ims = 0; ims < NMS; ims++) {
13879            if (in.readInt() != 0) {
13880                long kmstName = in.readLong();
13881                getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
13882            }
13883        }
13884
13885        final int NU = in.readInt();
13886        if (NU > 10000) {
13887            throw new ParcelFormatException("File corrupt: too many uids " + NU);
13888        }
13889        for (int iu = 0; iu < NU; iu++) {
13890            int uid = in.readInt();
13891            Uid u = new Uid(this, uid);
13892            mUidStats.put(uid, u);
13893
13894            u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
13895            u.mOnBatteryScreenOffBackgroundTimeBase.readSummaryFromParcel(in);
13896
13897            u.mWifiRunning = false;
13898            if (in.readInt() != 0) {
13899                u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
13900            }
13901            u.mFullWifiLockOut = false;
13902            if (in.readInt() != 0) {
13903                u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
13904            }
13905            u.mWifiScanStarted = false;
13906            if (in.readInt() != 0) {
13907                u.mWifiScanTimer.readSummaryFromParcelLocked(in);
13908            }
13909            u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
13910            for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
13911                if (in.readInt() != 0) {
13912                    u.makeWifiBatchedScanBin(i, null);
13913                    u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
13914                }
13915            }
13916            u.mWifiMulticastEnabled = false;
13917            if (in.readInt() != 0) {
13918                u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
13919            }
13920            if (in.readInt() != 0) {
13921                u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13922            }
13923            if (in.readInt() != 0) {
13924                u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13925            }
13926            if (in.readInt() != 0) {
13927                u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13928            }
13929            if (in.readInt() != 0) {
13930                u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
13931            }
13932            if (in.readInt() != 0) {
13933                u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
13934            }
13935            if (in.readInt() != 0) {
13936                u.createForegroundServiceTimerLocked().readSummaryFromParcelLocked(in);
13937            }
13938            if (in.readInt() != 0) {
13939                u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
13940            }
13941            if (in.readInt() != 0) {
13942                u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
13943            }
13944            if (in.readInt() != 0) {
13945                u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in);
13946            }
13947            if (in.readInt() != 0) {
13948                u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
13949            }
13950            if (in.readInt() != 0) {
13951                u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in);
13952            }
13953            u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
13954            for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
13955                if (in.readInt() != 0) {
13956                    u.makeProcessState(i, null);
13957                    u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
13958                }
13959            }
13960            if (in.readInt() != 0) {
13961                u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
13962            }
13963
13964            if (in.readInt() != 0) {
13965                if (u.mUserActivityCounters == null) {
13966                    u.initUserActivityLocked();
13967                }
13968                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
13969                    u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
13970                }
13971            }
13972
13973            if (in.readInt() != 0) {
13974                if (u.mNetworkByteActivityCounters == null) {
13975                    u.initNetworkActivityLocked();
13976                }
13977                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
13978                    u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
13979                    u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
13980                }
13981                u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
13982                u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
13983            }
13984
13985            u.mUserCpuTime.readSummaryFromParcelLocked(in);
13986            u.mSystemCpuTime.readSummaryFromParcelLocked(in);
13987
13988            if (in.readInt() != 0) {
13989                final int numClusters = in.readInt();
13990                if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
13991                    throw new ParcelFormatException("Incompatible cpu cluster arrangement");
13992                }
13993
13994                u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
13995                for (int cluster = 0; cluster < numClusters; cluster++) {
13996                    if (in.readInt() != 0) {
13997                        final int NSB = in.readInt();
13998                        if (mPowerProfile != null &&
13999                                mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
14000                            throw new ParcelFormatException("File corrupt: too many speed bins " +
14001                                    NSB);
14002                        }
14003
14004                        u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[NSB];
14005                        for (int speed = 0; speed < NSB; speed++) {
14006                            if (in.readInt() != 0) {
14007                                u.mCpuClusterSpeedTimesUs[cluster][speed] = new LongSamplingCounter(
14008                                        mOnBatteryTimeBase);
14009                                u.mCpuClusterSpeedTimesUs[cluster][speed].readSummaryFromParcelLocked(in);
14010                            }
14011                        }
14012                    } else {
14013                        u.mCpuClusterSpeedTimesUs[cluster] = null;
14014                    }
14015                }
14016            } else {
14017                u.mCpuClusterSpeedTimesUs = null;
14018            }
14019
14020            u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
14021                    in, mOnBatteryTimeBase);
14022            u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
14023                    in, mOnBatteryScreenOffTimeBase);
14024
14025            u.mCpuActiveTimeMs.readSummaryFromParcelLocked(in);
14026            u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
14027
14028            int length = in.readInt();
14029            if (length == Uid.NUM_PROCESS_STATE) {
14030                u.mProcStateTimeMs = new LongSamplingCounterArray[length];
14031                for (int procState = 0; procState < length; ++procState) {
14032                    u.mProcStateTimeMs[procState]
14033                            = LongSamplingCounterArray.readSummaryFromParcelLocked(
14034                                    in, mOnBatteryTimeBase);
14035                }
14036            } else {
14037                u.mProcStateTimeMs = null;
14038            }
14039            length = in.readInt();
14040            if (length == Uid.NUM_PROCESS_STATE) {
14041                u.mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
14042                for (int procState = 0; procState < length; ++procState) {
14043                    u.mProcStateScreenOffTimeMs[procState]
14044                            = LongSamplingCounterArray.readSummaryFromParcelLocked(
14045                                    in, mOnBatteryScreenOffTimeBase);
14046                }
14047            } else {
14048                u.mProcStateScreenOffTimeMs = null;
14049            }
14050
14051            if (in.readInt() != 0) {
14052                u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
14053                u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
14054            } else {
14055                u.mMobileRadioApWakeupCount = null;
14056            }
14057
14058            if (in.readInt() != 0) {
14059                u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
14060                u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
14061            } else {
14062                u.mWifiRadioApWakeupCount = null;
14063            }
14064
14065            int NW = in.readInt();
14066            if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
14067                throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
14068            }
14069            for (int iw = 0; iw < NW; iw++) {
14070                String wlName = in.readString();
14071                u.readWakeSummaryFromParcelLocked(wlName, in);
14072            }
14073
14074            int NS = in.readInt();
14075            if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
14076                throw new ParcelFormatException("File corrupt: too many syncs " + NS);
14077            }
14078            for (int is = 0; is < NS; is++) {
14079                String name = in.readString();
14080                u.readSyncSummaryFromParcelLocked(name, in);
14081            }
14082
14083            int NJ = in.readInt();
14084            if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
14085                throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
14086            }
14087            for (int ij = 0; ij < NJ; ij++) {
14088                String name = in.readString();
14089                u.readJobSummaryFromParcelLocked(name, in);
14090            }
14091
14092            u.readJobCompletionsFromParcelLocked(in);
14093
14094            u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in);
14095            u.mJobsDeferredCount.readSummaryFromParcelLocked(in);
14096            u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in);
14097            for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
14098                if (in.readInt() != 0) {
14099                    u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase);
14100                    u.mJobsFreshnessBuckets[i].readSummaryFromParcelLocked(in);
14101                }
14102            }
14103
14104            int NP = in.readInt();
14105            if (NP > 1000) {
14106                throw new ParcelFormatException("File corrupt: too many sensors " + NP);
14107            }
14108            for (int is = 0; is < NP; is++) {
14109                int seNumber = in.readInt();
14110                if (in.readInt() != 0) {
14111                    u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
14112                }
14113            }
14114
14115            NP = in.readInt();
14116            if (NP > 1000) {
14117                throw new ParcelFormatException("File corrupt: too many processes " + NP);
14118            }
14119            for (int ip = 0; ip < NP; ip++) {
14120                String procName = in.readString();
14121                Uid.Proc p = u.getProcessStatsLocked(procName);
14122                p.mUserTime = p.mLoadedUserTime = in.readLong();
14123                p.mSystemTime = p.mLoadedSystemTime = in.readLong();
14124                p.mForegroundTime = p.mLoadedForegroundTime = in.readLong();
14125                p.mStarts = p.mLoadedStarts = in.readInt();
14126                p.mNumCrashes = p.mLoadedNumCrashes = in.readInt();
14127                p.mNumAnrs = p.mLoadedNumAnrs = in.readInt();
14128                p.readExcessivePowerFromParcelLocked(in);
14129            }
14130
14131            NP = in.readInt();
14132            if (NP > 10000) {
14133                throw new ParcelFormatException("File corrupt: too many packages " + NP);
14134            }
14135            for (int ip = 0; ip < NP; ip++) {
14136                String pkgName = in.readString();
14137                Uid.Pkg p = u.getPackageStatsLocked(pkgName);
14138                final int NWA = in.readInt();
14139                if (NWA > 1000) {
14140                    throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
14141                }
14142                p.mWakeupAlarms.clear();
14143                for (int iwa=0; iwa<NWA; iwa++) {
14144                    String tag = in.readString();
14145                    Counter c = new Counter(mOnBatteryScreenOffTimeBase);
14146                    c.readSummaryFromParcelLocked(in);
14147                    p.mWakeupAlarms.put(tag, c);
14148                }
14149                NS = in.readInt();
14150                if (NS > 1000) {
14151                    throw new ParcelFormatException("File corrupt: too many services " + NS);
14152                }
14153                for (int is = 0; is < NS; is++) {
14154                    String servName = in.readString();
14155                    Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
14156                    s.mStartTime = s.mLoadedStartTime = in.readLong();
14157                    s.mStarts = s.mLoadedStarts = in.readInt();
14158                    s.mLaunches = s.mLoadedLaunches = in.readInt();
14159                }
14160            }
14161        }
14162    }
14163
14164    /**
14165     * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
14166     * disk.  This format does not allow a lossless round-trip.
14167     *
14168     * @param out the Parcel to be written to.
14169     */
14170    public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
14171        pullPendingStateUpdatesLocked();
14172
14173        // Pull the clock time.  This may update the time and make a new history entry
14174        // if we had originally pulled a time before the RTC was set.
14175        long startClockTime = getStartClockTime();
14176
14177        final long NOW_SYS = mClocks.uptimeMillis() * 1000;
14178        final long NOWREAL_SYS = mClocks.elapsedRealtime() * 1000;
14179
14180        out.writeInt(VERSION);
14181
14182        writeHistory(out, inclHistory, true);
14183
14184        out.writeInt(mStartCount);
14185        out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
14186        out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
14187        out.writeLong(startClockTime);
14188        out.writeString(mStartPlatformVersion);
14189        out.writeString(mEndPlatformVersion);
14190        mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14191        mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14192        out.writeInt(mDischargeUnplugLevel);
14193        out.writeInt(mDischargePlugLevel);
14194        out.writeInt(mDischargeCurrentLevel);
14195        out.writeInt(mCurrentBatteryLevel);
14196        out.writeInt(mEstimatedBatteryCapacity);
14197        out.writeInt(mMinLearnedBatteryCapacity);
14198        out.writeInt(mMaxLearnedBatteryCapacity);
14199        out.writeInt(getLowDischargeAmountSinceCharge());
14200        out.writeInt(getHighDischargeAmountSinceCharge());
14201        out.writeInt(getDischargeAmountScreenOnSinceCharge());
14202        out.writeInt(getDischargeAmountScreenOffSinceCharge());
14203        out.writeInt(getDischargeAmountScreenDozeSinceCharge());
14204        mDischargeStepTracker.writeToParcel(out);
14205        mChargeStepTracker.writeToParcel(out);
14206        mDailyDischargeStepTracker.writeToParcel(out);
14207        mDailyChargeStepTracker.writeToParcel(out);
14208        mDischargeCounter.writeSummaryFromParcelLocked(out);
14209        mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
14210        mDischargeScreenDozeCounter.writeSummaryFromParcelLocked(out);
14211        mDischargeLightDozeCounter.writeSummaryFromParcelLocked(out);
14212        mDischargeDeepDozeCounter.writeSummaryFromParcelLocked(out);
14213        if (mDailyPackageChanges != null) {
14214            final int NPKG = mDailyPackageChanges.size();
14215            out.writeInt(NPKG);
14216            for (int i=0; i<NPKG; i++) {
14217                PackageChange pc = mDailyPackageChanges.get(i);
14218                out.writeString(pc.mPackageName);
14219                out.writeInt(pc.mUpdate ? 1 : 0);
14220                out.writeLong(pc.mVersionCode);
14221            }
14222        } else {
14223            out.writeInt(0);
14224        }
14225        out.writeLong(mDailyStartTime);
14226        out.writeLong(mNextMinDailyDeadline);
14227        out.writeLong(mNextMaxDailyDeadline);
14228
14229        mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14230        mScreenDozeTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14231        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14232            mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14233        }
14234        mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14235        mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14236        out.writeLong(mLongestLightIdleTime);
14237        out.writeLong(mLongestFullIdleTime);
14238        mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14239        mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14240        mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14241        mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14242        mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14243        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
14244            mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14245        }
14246        mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14247        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14248            mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14249        }
14250        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14251            mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
14252            mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
14253        }
14254        mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14255        mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14256        mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
14257        mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
14258        mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
14259        mWifiMulticastWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14260        mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14261        mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14262        for (int i=0; i<NUM_WIFI_STATES; i++) {
14263            mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14264        }
14265        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14266            mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14267        }
14268        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14269            mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14270        }
14271        mWifiActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14272        mWifiActivity.writeSummaryToParcel(out);
14273        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14274            mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14275        }
14276        mBluetoothActivity.writeSummaryToParcel(out);
14277        mModemActivity.writeSummaryToParcel(out);
14278        out.writeInt(mHasWifiReporting ? 1 : 0);
14279        out.writeInt(mHasBluetoothReporting ? 1 : 0);
14280        out.writeInt(mHasModemReporting ? 1 : 0);
14281
14282        out.writeInt(mNumConnectivityChange);
14283        mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14284        mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14285        mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14286
14287        out.writeInt(mRpmStats.size());
14288        for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
14289            Timer rpmt = ent.getValue();
14290            if (rpmt != null) {
14291                out.writeInt(1);
14292                out.writeString(ent.getKey());
14293                rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14294            } else {
14295                out.writeInt(0);
14296            }
14297        }
14298        out.writeInt(mScreenOffRpmStats.size());
14299        for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
14300            Timer rpmt = ent.getValue();
14301            if (rpmt != null) {
14302                out.writeInt(1);
14303                out.writeString(ent.getKey());
14304                rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14305            } else {
14306                out.writeInt(0);
14307            }
14308        }
14309
14310        out.writeInt(mKernelWakelockStats.size());
14311        for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
14312            Timer kwlt = ent.getValue();
14313            if (kwlt != null) {
14314                out.writeInt(1);
14315                out.writeString(ent.getKey());
14316                kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14317            } else {
14318                out.writeInt(0);
14319            }
14320        }
14321
14322        out.writeInt(mWakeupReasonStats.size());
14323        for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
14324            SamplingTimer timer = ent.getValue();
14325            if (timer != null) {
14326                out.writeInt(1);
14327                out.writeString(ent.getKey());
14328                timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14329            } else {
14330                out.writeInt(0);
14331            }
14332        }
14333
14334        out.writeInt(mKernelMemoryStats.size());
14335        for (int i = 0; i < mKernelMemoryStats.size(); i++) {
14336            Timer kmt = mKernelMemoryStats.valueAt(i);
14337            if (kmt != null) {
14338                out.writeInt(1);
14339                out.writeLong(mKernelMemoryStats.keyAt(i));
14340                kmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14341            } else {
14342                out.writeInt(0);
14343            }
14344        }
14345
14346        final int NU = mUidStats.size();
14347        out.writeInt(NU);
14348        for (int iu = 0; iu < NU; iu++) {
14349            out.writeInt(mUidStats.keyAt(iu));
14350            Uid u = mUidStats.valueAt(iu);
14351
14352            u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14353            u.mOnBatteryScreenOffBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
14354
14355            if (u.mWifiRunningTimer != null) {
14356                out.writeInt(1);
14357                u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14358            } else {
14359                out.writeInt(0);
14360            }
14361            if (u.mFullWifiLockTimer != null) {
14362                out.writeInt(1);
14363                u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14364            } else {
14365                out.writeInt(0);
14366            }
14367            if (u.mWifiScanTimer != null) {
14368                out.writeInt(1);
14369                u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14370            } else {
14371                out.writeInt(0);
14372            }
14373            for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
14374                if (u.mWifiBatchedScanTimer[i] != null) {
14375                    out.writeInt(1);
14376                    u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14377                } else {
14378                    out.writeInt(0);
14379                }
14380            }
14381            if (u.mWifiMulticastTimer != null) {
14382                out.writeInt(1);
14383                u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14384            } else {
14385                out.writeInt(0);
14386            }
14387            if (u.mAudioTurnedOnTimer != null) {
14388                out.writeInt(1);
14389                u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14390            } else {
14391                out.writeInt(0);
14392            }
14393            if (u.mVideoTurnedOnTimer != null) {
14394                out.writeInt(1);
14395                u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14396            } else {
14397                out.writeInt(0);
14398            }
14399            if (u.mFlashlightTurnedOnTimer != null) {
14400                out.writeInt(1);
14401                u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14402            } else {
14403                out.writeInt(0);
14404            }
14405            if (u.mCameraTurnedOnTimer != null) {
14406                out.writeInt(1);
14407                u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14408            } else {
14409                out.writeInt(0);
14410            }
14411            if (u.mForegroundActivityTimer != null) {
14412                out.writeInt(1);
14413                u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14414            } else {
14415                out.writeInt(0);
14416            }
14417            if (u.mForegroundServiceTimer != null) {
14418                out.writeInt(1);
14419                u.mForegroundServiceTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14420            } else {
14421                out.writeInt(0);
14422            }
14423            if (u.mAggregatedPartialWakelockTimer != null) {
14424                out.writeInt(1);
14425                u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14426            } else {
14427                out.writeInt(0);
14428            }
14429            if (u.mBluetoothScanTimer != null) {
14430                out.writeInt(1);
14431                u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14432            } else {
14433                out.writeInt(0);
14434            }
14435            if (u.mBluetoothUnoptimizedScanTimer != null) {
14436                out.writeInt(1);
14437                u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14438            } else {
14439                out.writeInt(0);
14440            }
14441            if (u.mBluetoothScanResultCounter != null) {
14442                out.writeInt(1);
14443                u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
14444            } else {
14445                out.writeInt(0);
14446            }
14447            if (u.mBluetoothScanResultBgCounter != null) {
14448                out.writeInt(1);
14449                u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out);
14450            } else {
14451                out.writeInt(0);
14452            }
14453            for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
14454                if (u.mProcessStateTimer[i] != null) {
14455                    out.writeInt(1);
14456                    u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14457                } else {
14458                    out.writeInt(0);
14459                }
14460            }
14461            if (u.mVibratorOnTimer != null) {
14462                out.writeInt(1);
14463                u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14464            } else {
14465                out.writeInt(0);
14466            }
14467
14468            if (u.mUserActivityCounters == null) {
14469                out.writeInt(0);
14470            } else {
14471                out.writeInt(1);
14472                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
14473                    u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
14474                }
14475            }
14476
14477            if (u.mNetworkByteActivityCounters == null) {
14478                out.writeInt(0);
14479            } else {
14480                out.writeInt(1);
14481                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14482                    u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
14483                    u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
14484                }
14485                u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
14486                u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
14487            }
14488
14489            u.mUserCpuTime.writeSummaryFromParcelLocked(out);
14490            u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
14491
14492            if (u.mCpuClusterSpeedTimesUs != null) {
14493                out.writeInt(1);
14494                out.writeInt(u.mCpuClusterSpeedTimesUs.length);
14495                for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeedTimesUs) {
14496                    if (cpuSpeeds != null) {
14497                        out.writeInt(1);
14498                        out.writeInt(cpuSpeeds.length);
14499                        for (LongSamplingCounter c : cpuSpeeds) {
14500                            if (c != null) {
14501                                out.writeInt(1);
14502                                c.writeSummaryFromParcelLocked(out);
14503                            } else {
14504                                out.writeInt(0);
14505                            }
14506                        }
14507                    } else {
14508                        out.writeInt(0);
14509                    }
14510                }
14511            } else {
14512                out.writeInt(0);
14513            }
14514
14515            LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
14516            LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
14517
14518            u.mCpuActiveTimeMs.writeSummaryFromParcelLocked(out);
14519            u.mCpuClusterTimesMs.writeSummaryToParcelLocked(out);
14520
14521            if (u.mProcStateTimeMs != null) {
14522                out.writeInt(u.mProcStateTimeMs.length);
14523                for (LongSamplingCounterArray counters : u.mProcStateTimeMs) {
14524                    LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
14525                }
14526            } else {
14527                out.writeInt(0);
14528            }
14529            if (u.mProcStateScreenOffTimeMs != null) {
14530                out.writeInt(u.mProcStateScreenOffTimeMs.length);
14531                for (LongSamplingCounterArray counters : u.mProcStateScreenOffTimeMs) {
14532                    LongSamplingCounterArray.writeSummaryToParcelLocked(out, counters);
14533                }
14534            } else {
14535                out.writeInt(0);
14536            }
14537
14538            if (u.mMobileRadioApWakeupCount != null) {
14539                out.writeInt(1);
14540                u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
14541            } else {
14542                out.writeInt(0);
14543            }
14544
14545            if (u.mWifiRadioApWakeupCount != null) {
14546                out.writeInt(1);
14547                u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
14548            } else {
14549                out.writeInt(0);
14550            }
14551
14552            final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
14553            int NW = wakeStats.size();
14554            out.writeInt(NW);
14555            for (int iw=0; iw<NW; iw++) {
14556                out.writeString(wakeStats.keyAt(iw));
14557                Uid.Wakelock wl = wakeStats.valueAt(iw);
14558                if (wl.mTimerFull != null) {
14559                    out.writeInt(1);
14560                    wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14561                } else {
14562                    out.writeInt(0);
14563                }
14564                if (wl.mTimerPartial != null) {
14565                    out.writeInt(1);
14566                    wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14567                } else {
14568                    out.writeInt(0);
14569                }
14570                if (wl.mTimerWindow != null) {
14571                    out.writeInt(1);
14572                    wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14573                } else {
14574                    out.writeInt(0);
14575                }
14576                if (wl.mTimerDraw != null) {
14577                    out.writeInt(1);
14578                    wl.mTimerDraw.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14579                } else {
14580                    out.writeInt(0);
14581                }
14582            }
14583
14584            final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
14585            int NS = syncStats.size();
14586            out.writeInt(NS);
14587            for (int is=0; is<NS; is++) {
14588                out.writeString(syncStats.keyAt(is));
14589                syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14590            }
14591
14592            final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
14593            int NJ = jobStats.size();
14594            out.writeInt(NJ);
14595            for (int ij=0; ij<NJ; ij++) {
14596                out.writeString(jobStats.keyAt(ij));
14597                jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14598            }
14599
14600            u.writeJobCompletionsToParcelLocked(out);
14601
14602            u.mJobsDeferredEventCount.writeSummaryFromParcelLocked(out);
14603            u.mJobsDeferredCount.writeSummaryFromParcelLocked(out);
14604            u.mJobsFreshnessTimeMs.writeSummaryFromParcelLocked(out);
14605            for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
14606                if (u.mJobsFreshnessBuckets[i] != null) {
14607                    out.writeInt(1);
14608                    u.mJobsFreshnessBuckets[i].writeSummaryFromParcelLocked(out);
14609                } else {
14610                    out.writeInt(0);
14611                }
14612            }
14613
14614            int NSE = u.mSensorStats.size();
14615            out.writeInt(NSE);
14616            for (int ise=0; ise<NSE; ise++) {
14617                out.writeInt(u.mSensorStats.keyAt(ise));
14618                Uid.Sensor se = u.mSensorStats.valueAt(ise);
14619                if (se.mTimer != null) {
14620                    out.writeInt(1);
14621                    se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
14622                } else {
14623                    out.writeInt(0);
14624                }
14625            }
14626
14627            int NP = u.mProcessStats.size();
14628            out.writeInt(NP);
14629            for (int ip=0; ip<NP; ip++) {
14630                out.writeString(u.mProcessStats.keyAt(ip));
14631                Uid.Proc ps = u.mProcessStats.valueAt(ip);
14632                out.writeLong(ps.mUserTime);
14633                out.writeLong(ps.mSystemTime);
14634                out.writeLong(ps.mForegroundTime);
14635                out.writeInt(ps.mStarts);
14636                out.writeInt(ps.mNumCrashes);
14637                out.writeInt(ps.mNumAnrs);
14638                ps.writeExcessivePowerToParcelLocked(out);
14639            }
14640
14641            NP = u.mPackageStats.size();
14642            out.writeInt(NP);
14643            if (NP > 0) {
14644                for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
14645                    : u.mPackageStats.entrySet()) {
14646                    out.writeString(ent.getKey());
14647                    Uid.Pkg ps = ent.getValue();
14648                    final int NWA = ps.mWakeupAlarms.size();
14649                    out.writeInt(NWA);
14650                    for (int iwa=0; iwa<NWA; iwa++) {
14651                        out.writeString(ps.mWakeupAlarms.keyAt(iwa));
14652                        ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
14653                    }
14654                    NS = ps.mServiceStats.size();
14655                    out.writeInt(NS);
14656                    for (int is=0; is<NS; is++) {
14657                        out.writeString(ps.mServiceStats.keyAt(is));
14658                        BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
14659                        long time = ss.getStartTimeToNowLocked(
14660                                mOnBatteryTimeBase.getUptime(NOW_SYS));
14661                        out.writeLong(time);
14662                        out.writeInt(ss.mStarts);
14663                        out.writeInt(ss.mLaunches);
14664                    }
14665                }
14666            }
14667        }
14668    }
14669
14670    public void readFromParcel(Parcel in) {
14671        readFromParcelLocked(in);
14672    }
14673
14674    void readFromParcelLocked(Parcel in) {
14675        int magic = in.readInt();
14676        if (magic != MAGIC) {
14677            throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
14678        }
14679
14680        readHistory(in, false);
14681
14682        mStartCount = in.readInt();
14683        mStartClockTime = in.readLong();
14684        mStartPlatformVersion = in.readString();
14685        mEndPlatformVersion = in.readString();
14686        mUptime = in.readLong();
14687        mUptimeStart = in.readLong();
14688        mRealtime = in.readLong();
14689        mRealtimeStart = in.readLong();
14690        mOnBattery = in.readInt() != 0;
14691        mEstimatedBatteryCapacity = in.readInt();
14692        mMinLearnedBatteryCapacity = in.readInt();
14693        mMaxLearnedBatteryCapacity = in.readInt();
14694        mOnBatteryInternal = false; // we are no longer really running.
14695        mOnBatteryTimeBase.readFromParcel(in);
14696        mOnBatteryScreenOffTimeBase.readFromParcel(in);
14697
14698        mScreenState = Display.STATE_UNKNOWN;
14699        mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
14700        mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
14701        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14702            mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
14703                    mOnBatteryTimeBase, in);
14704        }
14705        mInteractive = false;
14706        mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase, in);
14707        mPhoneOn = false;
14708        mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
14709                mOnBatteryTimeBase, in);
14710        mLongestLightIdleTime = in.readLong();
14711        mLongestFullIdleTime = in.readLong();
14712        mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null,
14713                mOnBatteryTimeBase, in);
14714        mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null,
14715                mOnBatteryTimeBase, in);
14716        mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null,
14717                mOnBatteryTimeBase, in);
14718        mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase, in);
14719        mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase, in);
14720        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
14721            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i,
14722                    null, mOnBatteryTimeBase, in);
14723        }
14724        mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
14725                mOnBatteryTimeBase, in);
14726        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14727            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i,
14728                    null, mOnBatteryTimeBase, in);
14729        }
14730        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14731            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
14732            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
14733        }
14734        mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
14735        mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
14736                mOnBatteryTimeBase, in);
14737        mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
14738                mOnBatteryTimeBase, in);
14739        mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
14740        mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
14741        mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
14742        mWifiMulticastWakelockTimer = new StopwatchTimer(mClocks, null, -4, null,
14743                mOnBatteryTimeBase, in);
14744        mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
14745        mWifiOn = false;
14746        mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase, in);
14747        mGlobalWifiRunning = false;
14748        mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null,
14749                mOnBatteryTimeBase, in);
14750        for (int i=0; i<NUM_WIFI_STATES; i++) {
14751            mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i,
14752                    null, mOnBatteryTimeBase, in);
14753        }
14754        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14755            mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i,
14756                    null, mOnBatteryTimeBase, in);
14757        }
14758        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14759            mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
14760                    null, mOnBatteryTimeBase, in);
14761        }
14762        mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null,
14763            mOnBatteryTimeBase, in);
14764        mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14765                NUM_WIFI_TX_LEVELS, in);
14766        for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14767            mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i,
14768                null, mOnBatteryTimeBase, in);
14769        }
14770        mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14771                NUM_BT_TX_LEVELS, in);
14772        mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
14773                ModemActivityInfo.TX_POWER_LEVELS, in);
14774        mHasWifiReporting = in.readInt() != 0;
14775        mHasBluetoothReporting = in.readInt() != 0;
14776        mHasModemReporting = in.readInt() != 0;
14777
14778        mNumConnectivityChange = in.readInt();
14779        mLoadedNumConnectivityChange = in.readInt();
14780        mUnpluggedNumConnectivityChange = in.readInt();
14781        mAudioOnNesting = 0;
14782        mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
14783        mVideoOnNesting = 0;
14784        mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
14785        mFlashlightOnNesting = 0;
14786        mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase, in);
14787        mCameraOnNesting = 0;
14788        mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
14789        mBluetoothScanNesting = 0;
14790        mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
14791        mIsCellularTxPowerHigh = false;
14792        mDischargeUnplugLevel = in.readInt();
14793        mDischargePlugLevel = in.readInt();
14794        mDischargeCurrentLevel = in.readInt();
14795        mCurrentBatteryLevel = in.readInt();
14796        mLowDischargeAmountSinceCharge = in.readInt();
14797        mHighDischargeAmountSinceCharge = in.readInt();
14798        mDischargeAmountScreenOn = in.readInt();
14799        mDischargeAmountScreenOnSinceCharge = in.readInt();
14800        mDischargeAmountScreenOff = in.readInt();
14801        mDischargeAmountScreenOffSinceCharge = in.readInt();
14802        mDischargeAmountScreenDoze = in.readInt();
14803        mDischargeAmountScreenDozeSinceCharge = in.readInt();
14804        mDischargeStepTracker.readFromParcel(in);
14805        mChargeStepTracker.readFromParcel(in);
14806        mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14807        mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase, in);
14808        mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14809        mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14810        mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
14811        mLastWriteTime = in.readLong();
14812
14813        mRpmStats.clear();
14814        int NRPMS = in.readInt();
14815        for (int irpm = 0; irpm < NRPMS; irpm++) {
14816            if (in.readInt() != 0) {
14817                String rpmName = in.readString();
14818                SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14819                mRpmStats.put(rpmName, rpmt);
14820            }
14821        }
14822        mScreenOffRpmStats.clear();
14823        int NSORPMS = in.readInt();
14824        for (int irpm = 0; irpm < NSORPMS; irpm++) {
14825            if (in.readInt() != 0) {
14826                String rpmName = in.readString();
14827                SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
14828                mScreenOffRpmStats.put(rpmName, rpmt);
14829            }
14830        }
14831
14832        mKernelWakelockStats.clear();
14833        int NKW = in.readInt();
14834        for (int ikw = 0; ikw < NKW; ikw++) {
14835            if (in.readInt() != 0) {
14836                String wakelockName = in.readString();
14837                SamplingTimer kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
14838                mKernelWakelockStats.put(wakelockName, kwlt);
14839            }
14840        }
14841
14842        mWakeupReasonStats.clear();
14843        int NWR = in.readInt();
14844        for (int iwr = 0; iwr < NWR; iwr++) {
14845            if (in.readInt() != 0) {
14846                String reasonName = in.readString();
14847                SamplingTimer timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14848                mWakeupReasonStats.put(reasonName, timer);
14849            }
14850        }
14851
14852        mKernelMemoryStats.clear();
14853        int nmt = in.readInt();
14854        for (int imt = 0; imt < nmt; imt++) {
14855            if (in.readInt() != 0) {
14856                Long bucket = in.readLong();
14857                SamplingTimer kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
14858                mKernelMemoryStats.put(bucket, kmt);
14859            }
14860        }
14861
14862        mPartialTimers.clear();
14863        mFullTimers.clear();
14864        mWindowTimers.clear();
14865        mWifiRunningTimers.clear();
14866        mFullWifiLockTimers.clear();
14867        mWifiScanTimers.clear();
14868        mWifiBatchedScanTimers.clear();
14869        mWifiMulticastTimers.clear();
14870        mAudioTurnedOnTimers.clear();
14871        mVideoTurnedOnTimers.clear();
14872        mFlashlightTurnedOnTimers.clear();
14873        mCameraTurnedOnTimers.clear();
14874
14875        int numUids = in.readInt();
14876        mUidStats.clear();
14877        for (int i = 0; i < numUids; i++) {
14878            int uid = in.readInt();
14879            Uid u = new Uid(this, uid);
14880            u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
14881            mUidStats.append(uid, u);
14882        }
14883    }
14884
14885    public void writeToParcel(Parcel out, int flags) {
14886        writeToParcelLocked(out, true, flags);
14887    }
14888
14889    public void writeToParcelWithoutUids(Parcel out, int flags) {
14890        writeToParcelLocked(out, false, flags);
14891    }
14892
14893    @SuppressWarnings("unused")
14894    void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
14895        // Need to update with current kernel wake lock counts.
14896        pullPendingStateUpdatesLocked();
14897
14898        // Pull the clock time.  This may update the time and make a new history entry
14899        // if we had originally pulled a time before the RTC was set.
14900        long startClockTime = getStartClockTime();
14901
14902        final long uSecUptime = mClocks.uptimeMillis() * 1000;
14903        final long uSecRealtime = mClocks.elapsedRealtime() * 1000;
14904        final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
14905        final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
14906
14907        out.writeInt(MAGIC);
14908
14909        writeHistory(out, true, false);
14910
14911        out.writeInt(mStartCount);
14912        out.writeLong(startClockTime);
14913        out.writeString(mStartPlatformVersion);
14914        out.writeString(mEndPlatformVersion);
14915        out.writeLong(mUptime);
14916        out.writeLong(mUptimeStart);
14917        out.writeLong(mRealtime);
14918        out.writeLong(mRealtimeStart);
14919        out.writeInt(mOnBattery ? 1 : 0);
14920        out.writeInt(mEstimatedBatteryCapacity);
14921        out.writeInt(mMinLearnedBatteryCapacity);
14922        out.writeInt(mMaxLearnedBatteryCapacity);
14923        mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
14924        mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
14925
14926        mScreenOnTimer.writeToParcel(out, uSecRealtime);
14927        mScreenDozeTimer.writeToParcel(out, uSecRealtime);
14928        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
14929            mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
14930        }
14931        mInteractiveTimer.writeToParcel(out, uSecRealtime);
14932        mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
14933        out.writeLong(mLongestLightIdleTime);
14934        out.writeLong(mLongestFullIdleTime);
14935        mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
14936        mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
14937        mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
14938        mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
14939        mPhoneOnTimer.writeToParcel(out, uSecRealtime);
14940        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
14941            mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
14942        }
14943        mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
14944        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
14945            mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
14946        }
14947        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
14948            mNetworkByteActivityCounters[i].writeToParcel(out);
14949            mNetworkPacketActivityCounters[i].writeToParcel(out);
14950        }
14951        mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
14952        mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
14953        mMobileRadioActiveAdjustedTime.writeToParcel(out);
14954        mMobileRadioActiveUnknownTime.writeToParcel(out);
14955        mMobileRadioActiveUnknownCount.writeToParcel(out);
14956        mWifiMulticastWakelockTimer.writeToParcel(out, uSecRealtime);
14957        mWifiOnTimer.writeToParcel(out, uSecRealtime);
14958        mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
14959        for (int i=0; i<NUM_WIFI_STATES; i++) {
14960            mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
14961        }
14962        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
14963            mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
14964        }
14965        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
14966            mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
14967        }
14968        mWifiActiveTimer.writeToParcel(out, uSecRealtime);
14969        mWifiActivity.writeToParcel(out, 0);
14970        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
14971            mGpsSignalQualityTimer[i].writeToParcel(out, uSecRealtime);
14972        }
14973        mBluetoothActivity.writeToParcel(out, 0);
14974        mModemActivity.writeToParcel(out, 0);
14975        out.writeInt(mHasWifiReporting ? 1 : 0);
14976        out.writeInt(mHasBluetoothReporting ? 1 : 0);
14977        out.writeInt(mHasModemReporting ? 1 : 0);
14978
14979        out.writeInt(mNumConnectivityChange);
14980        out.writeInt(mLoadedNumConnectivityChange);
14981        out.writeInt(mUnpluggedNumConnectivityChange);
14982        mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
14983        mCameraOnTimer.writeToParcel(out, uSecRealtime);
14984        mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
14985        out.writeInt(mDischargeUnplugLevel);
14986        out.writeInt(mDischargePlugLevel);
14987        out.writeInt(mDischargeCurrentLevel);
14988        out.writeInt(mCurrentBatteryLevel);
14989        out.writeInt(mLowDischargeAmountSinceCharge);
14990        out.writeInt(mHighDischargeAmountSinceCharge);
14991        out.writeInt(mDischargeAmountScreenOn);
14992        out.writeInt(mDischargeAmountScreenOnSinceCharge);
14993        out.writeInt(mDischargeAmountScreenOff);
14994        out.writeInt(mDischargeAmountScreenOffSinceCharge);
14995        out.writeInt(mDischargeAmountScreenDoze);
14996        out.writeInt(mDischargeAmountScreenDozeSinceCharge);
14997        mDischargeStepTracker.writeToParcel(out);
14998        mChargeStepTracker.writeToParcel(out);
14999        mDischargeCounter.writeToParcel(out);
15000        mDischargeScreenOffCounter.writeToParcel(out);
15001        mDischargeScreenDozeCounter.writeToParcel(out);
15002        mDischargeLightDozeCounter.writeToParcel(out);
15003        mDischargeDeepDozeCounter.writeToParcel(out);
15004        out.writeLong(mLastWriteTime);
15005
15006        out.writeInt(mRpmStats.size());
15007        for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
15008            SamplingTimer rpmt = ent.getValue();
15009            if (rpmt != null) {
15010                out.writeInt(1);
15011                out.writeString(ent.getKey());
15012                rpmt.writeToParcel(out, uSecRealtime);
15013            } else {
15014                out.writeInt(0);
15015            }
15016        }
15017        out.writeInt(mScreenOffRpmStats.size());
15018        for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
15019            SamplingTimer rpmt = ent.getValue();
15020            if (rpmt != null) {
15021                out.writeInt(1);
15022                out.writeString(ent.getKey());
15023                rpmt.writeToParcel(out, uSecRealtime);
15024            } else {
15025                out.writeInt(0);
15026            }
15027        }
15028
15029        if (inclUids) {
15030            out.writeInt(mKernelWakelockStats.size());
15031            for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
15032                SamplingTimer kwlt = ent.getValue();
15033                if (kwlt != null) {
15034                    out.writeInt(1);
15035                    out.writeString(ent.getKey());
15036                    kwlt.writeToParcel(out, uSecRealtime);
15037                } else {
15038                    out.writeInt(0);
15039                }
15040            }
15041            out.writeInt(mWakeupReasonStats.size());
15042            for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
15043                SamplingTimer timer = ent.getValue();
15044                if (timer != null) {
15045                    out.writeInt(1);
15046                    out.writeString(ent.getKey());
15047                    timer.writeToParcel(out, uSecRealtime);
15048                } else {
15049                    out.writeInt(0);
15050                }
15051            }
15052        } else {
15053            out.writeInt(0);
15054            out.writeInt(0);
15055        }
15056
15057        out.writeInt(mKernelMemoryStats.size());
15058        for (int i = 0; i < mKernelMemoryStats.size(); i++) {
15059            SamplingTimer kmt = mKernelMemoryStats.valueAt(i);
15060            if (kmt != null) {
15061                out.writeInt(1);
15062                out.writeLong(mKernelMemoryStats.keyAt(i));
15063                kmt.writeToParcel(out, uSecRealtime);
15064            } else {
15065                out.writeInt(0);
15066            }
15067        }
15068
15069        if (inclUids) {
15070            int size = mUidStats.size();
15071            out.writeInt(size);
15072            for (int i = 0; i < size; i++) {
15073                out.writeInt(mUidStats.keyAt(i));
15074                Uid uid = mUidStats.valueAt(i);
15075
15076                uid.writeToParcelLocked(out, uSecUptime, uSecRealtime);
15077            }
15078        } else {
15079            out.writeInt(0);
15080        }
15081    }
15082
15083    public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
15084        new Parcelable.Creator<BatteryStatsImpl>() {
15085        public BatteryStatsImpl createFromParcel(Parcel in) {
15086            return new BatteryStatsImpl(in);
15087        }
15088
15089        public BatteryStatsImpl[] newArray(int size) {
15090            return new BatteryStatsImpl[size];
15091        }
15092    };
15093
15094    public void prepareForDumpLocked() {
15095        // Need to retrieve current kernel wake lock stats before printing.
15096        pullPendingStateUpdatesLocked();
15097
15098        // Pull the clock time.  This may update the time and make a new history entry
15099        // if we had originally pulled a time before the RTC was set.
15100        getStartClockTime();
15101    }
15102
15103    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
15104        if (DEBUG) {
15105            pw.println("mOnBatteryTimeBase:");
15106            mOnBatteryTimeBase.dump(pw, "  ");
15107            pw.println("mOnBatteryScreenOffTimeBase:");
15108            mOnBatteryScreenOffTimeBase.dump(pw, "  ");
15109            Printer pr = new PrintWriterPrinter(pw);
15110            pr.println("*** Screen on timer:");
15111            mScreenOnTimer.logState(pr, "  ");
15112            pr.println("*** Screen doze timer:");
15113            mScreenDozeTimer.logState(pr, "  ");
15114            for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
15115                pr.println("*** Screen brightness #" + i + ":");
15116                mScreenBrightnessTimer[i].logState(pr, "  ");
15117            }
15118            pr.println("*** Interactive timer:");
15119            mInteractiveTimer.logState(pr, "  ");
15120            pr.println("*** Power save mode timer:");
15121            mPowerSaveModeEnabledTimer.logState(pr, "  ");
15122            pr.println("*** Device idle mode light timer:");
15123            mDeviceIdleModeLightTimer.logState(pr, "  ");
15124            pr.println("*** Device idle mode full timer:");
15125            mDeviceIdleModeFullTimer.logState(pr, "  ");
15126            pr.println("*** Device light idling timer:");
15127            mDeviceLightIdlingTimer.logState(pr, "  ");
15128            pr.println("*** Device idling timer:");
15129            mDeviceIdlingTimer.logState(pr, "  ");
15130            pr.println("*** Phone timer:");
15131            mPhoneOnTimer.logState(pr, "  ");
15132            for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
15133                pr.println("*** Phone signal strength #" + i + ":");
15134                mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
15135            }
15136            pr.println("*** Signal scanning :");
15137            mPhoneSignalScanningTimer.logState(pr, "  ");
15138            for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
15139                pr.println("*** Data connection type #" + i + ":");
15140                mPhoneDataConnectionsTimer[i].logState(pr, "  ");
15141            }
15142            pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
15143            pr.println("*** Mobile network active timer:");
15144            mMobileRadioActiveTimer.logState(pr, "  ");
15145            pr.println("*** Mobile network active adjusted timer:");
15146            mMobileRadioActiveAdjustedTime.logState(pr, "  ");
15147            pr.println("*** Wifi Multicast WakeLock Timer:");
15148            mWifiMulticastWakelockTimer.logState(pr, "  ");
15149            pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
15150            pr.println("*** Wifi timer:");
15151            mWifiOnTimer.logState(pr, "  ");
15152            pr.println("*** WifiRunning timer:");
15153            mGlobalWifiRunningTimer.logState(pr, "  ");
15154            for (int i=0; i<NUM_WIFI_STATES; i++) {
15155                pr.println("*** Wifi state #" + i + ":");
15156                mWifiStateTimer[i].logState(pr, "  ");
15157            }
15158            for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
15159                pr.println("*** Wifi suppl state #" + i + ":");
15160                mWifiSupplStateTimer[i].logState(pr, "  ");
15161            }
15162            for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
15163                pr.println("*** Wifi signal strength #" + i + ":");
15164                mWifiSignalStrengthsTimer[i].logState(pr, "  ");
15165            }
15166            for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
15167                pr.println("*** GPS signal quality #" + i + ":");
15168                mGpsSignalQualityTimer[i].logState(pr, "  ");
15169            }
15170            pr.println("*** Flashlight timer:");
15171            mFlashlightOnTimer.logState(pr, "  ");
15172            pr.println("*** Camera timer:");
15173            mCameraOnTimer.logState(pr, "  ");
15174        }
15175        super.dumpLocked(context, pw, flags, reqUid, histStart);
15176        pw.print("Total cpu time reads: ");
15177        pw.println(mNumSingleUidCpuTimeReads);
15178        pw.print("Batched cpu time reads: ");
15179        pw.println(mNumBatchedSingleUidCpuTimeReads);
15180        pw.print("Batching Duration (min): ");
15181        pw.println((mClocks.uptimeMillis() - mCpuTimeReadsTrackingStartTime) / (60 * 1000));
15182        pw.print("All UID cpu time reads since the later of device start or stats reset: ");
15183        pw.println(mNumAllUidCpuTimeReads);
15184        pw.print("UIDs removed since the later of device start or stats reset: ");
15185        pw.println(mNumUidsRemoved);
15186    }
15187}
15188