blob: 9cc1959f296c0a29e615b93406ca856128ee07ff [file] [log] [blame]
Justin Klaassen10d07c82017-09-15 17:58:39 -04001/*
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.Context;
25import android.content.Intent;
26import android.net.ConnectivityManager;
27import android.net.NetworkStats;
28import android.net.wifi.WifiActivityEnergyInfo;
29import android.net.wifi.WifiManager;
30import android.os.BatteryManager;
31import android.os.BatteryStats;
32import android.os.Build;
33import android.os.FileUtils;
34import android.os.Handler;
35import android.os.IBatteryPropertiesRegistrar;
36import android.os.Looper;
37import android.os.Message;
38import android.os.Parcel;
39import android.os.ParcelFormatException;
40import android.os.Parcelable;
41import android.os.Process;
42import android.os.RemoteException;
43import android.os.ServiceManager;
44import android.os.SystemClock;
45import android.os.UserHandle;
46import android.os.WorkSource;
47import android.telephony.DataConnectionRealTimeInfo;
48import android.telephony.ModemActivityInfo;
49import android.telephony.ServiceState;
50import android.telephony.SignalStrength;
51import android.telephony.TelephonyManager;
52import android.text.TextUtils;
53import android.util.ArrayMap;
54import android.util.Log;
55import android.util.LogWriter;
56import android.util.LongSparseArray;
57import android.util.LongSparseLongArray;
58import android.util.MutableInt;
59import android.util.Pools;
60import android.util.PrintWriterPrinter;
61import android.util.Printer;
62import android.util.Slog;
63import android.util.SparseArray;
64import android.util.SparseIntArray;
65import android.util.SparseLongArray;
Justin Klaassen47ed54e2017-10-24 19:50:40 -040066import android.util.StatsLog;
Justin Klaassen10d07c82017-09-15 17:58:39 -040067import android.util.TimeUtils;
68import android.util.Xml;
69import android.view.Display;
70
71import com.android.internal.annotations.GuardedBy;
72import com.android.internal.annotations.VisibleForTesting;
73import com.android.internal.net.NetworkStatsFactory;
74import com.android.internal.util.ArrayUtils;
75import com.android.internal.util.FastPrintWriter;
76import com.android.internal.util.FastXmlSerializer;
77import com.android.internal.util.JournaledFile;
78import com.android.internal.util.XmlUtils;
79
80import libcore.util.EmptyArray;
81import org.xmlpull.v1.XmlPullParser;
82import org.xmlpull.v1.XmlPullParserException;
83import org.xmlpull.v1.XmlSerializer;
84
85import java.io.ByteArrayOutputStream;
86import java.io.File;
87import java.io.FileInputStream;
88import java.io.FileNotFoundException;
89import java.io.FileOutputStream;
90import java.io.IOException;
91import java.io.PrintWriter;
92import java.nio.charset.StandardCharsets;
93import java.util.ArrayList;
94import java.util.Arrays;
95import java.util.Calendar;
96import java.util.HashMap;
97import java.util.Iterator;
98import java.util.Map;
99import java.util.concurrent.Future;
100import java.util.concurrent.atomic.AtomicInteger;
101import java.util.concurrent.locks.ReentrantLock;
102
103/**
104 * All information we are collecting about things that can happen that impact
105 * battery life. All times are represented in microseconds except where indicated
106 * otherwise.
107 */
108public class BatteryStatsImpl extends BatteryStats {
109 private static final String TAG = "BatteryStatsImpl";
110 private static final boolean DEBUG = false;
111 public static final boolean DEBUG_ENERGY = false;
112 private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
113 private static final boolean DEBUG_MEMORY = false;
114 private static final boolean DEBUG_HISTORY = false;
115 private static final boolean USE_OLD_HISTORY = false; // for debugging.
116
117 // TODO: remove "tcp" from network methods, since we measure total stats.
118
119 // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
120 private static final int MAGIC = 0xBA757475; // 'BATSTATS'
121
122 // Current on-disk Parcel version
Justin Klaassen47ed54e2017-10-24 19:50:40 -0400123 private static final int VERSION = 168 + (USE_OLD_HISTORY ? 1000 : 0);
Justin Klaassen10d07c82017-09-15 17:58:39 -0400124
125 // Maximum number of items we will record in the history.
126 private static final int MAX_HISTORY_ITEMS;
127
128 // No, really, THIS is the maximum number of items we will record in the history.
129 private static final int MAX_MAX_HISTORY_ITEMS;
130
131 // The maximum number of names wakelocks we will keep track of
132 // per uid; once the limit is reached, we batch the remaining wakelocks
133 // in to one common name.
134 private static final int MAX_WAKELOCKS_PER_UID;
135
136 static final int MAX_HISTORY_BUFFER; // 256KB
137 static final int MAX_MAX_HISTORY_BUFFER; // 320KB
138
139 static {
140 if (ActivityManager.isLowRamDeviceStatic()) {
141 MAX_HISTORY_ITEMS = 800;
142 MAX_MAX_HISTORY_ITEMS = 1200;
143 MAX_WAKELOCKS_PER_UID = 40;
144 MAX_HISTORY_BUFFER = 96*1024; // 96KB
145 MAX_MAX_HISTORY_BUFFER = 128*1024; // 128KB
146 } else {
147 MAX_HISTORY_ITEMS = 2000;
148 MAX_MAX_HISTORY_ITEMS = 3000;
149 MAX_WAKELOCKS_PER_UID = 100;
150 MAX_HISTORY_BUFFER = 256*1024; // 256KB
151 MAX_MAX_HISTORY_BUFFER = 320*1024; // 256KB
152 }
153 }
154
155 // Number of transmit power states the Wifi controller can be in.
156 private static final int NUM_WIFI_TX_LEVELS = 1;
157
158 // Number of transmit power states the Bluetooth controller can be in.
159 private static final int NUM_BT_TX_LEVELS = 1;
160
161 /**
162 * Holding a wakelock costs more than just using the cpu.
163 * Currently, we assign only half the cpu time to an app that is running but
164 * not holding a wakelock. The apps holding wakelocks get the rest of the blame.
165 * If no app is holding a wakelock, then the distribution is normal.
166 */
167 @VisibleForTesting
168 public static final int WAKE_LOCK_WEIGHT = 50;
169
170 protected Clocks mClocks;
171
172 private final JournaledFile mFile;
173 public final AtomicFile mCheckinFile;
174 public final AtomicFile mDailyFile;
175
176 static final int MSG_UPDATE_WAKELOCKS = 1;
177 static final int MSG_REPORT_POWER_CHANGE = 2;
178 static final int MSG_REPORT_CHARGING = 3;
179 static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
180
181 private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
182 private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
183
184 @VisibleForTesting
185 protected KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader();
186 @VisibleForTesting
187 protected KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
188 @VisibleForTesting
189 protected KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader =
190 new KernelUidCpuFreqTimeReader();
191
192 private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats
193 = new KernelMemoryBandwidthStats();
194 private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>();
195 public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
196 return mKernelMemoryStats;
197 }
198
Justin Klaassenbc81c7a2017-09-18 17:38:50 -0400199 /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
200 private final RpmStats mTmpRpmStats = new RpmStats();
201 /** The soonest the RPM stats can be updated after it was last updated. */
202 private static final long RPM_STATS_UPDATE_FREQ_MS = 1000;
203 /** Last time that RPM stats were updated by updateRpmStatsLocked. */
204 private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
205
Justin Klaassen10d07c82017-09-15 17:58:39 -0400206 public interface BatteryCallback {
207 public void batteryNeedsCpuUpdate();
208 public void batteryPowerChanged(boolean onBattery);
209 public void batterySendBroadcast(Intent intent);
210 }
211
212 public interface PlatformIdleStateCallback {
Justin Klaassenbc81c7a2017-09-18 17:38:50 -0400213 public void fillLowPowerStats(RpmStats rpmStats);
Justin Klaassen10d07c82017-09-15 17:58:39 -0400214 public String getPlatformLowPowerStats();
215 public String getSubsystemLowPowerStats();
216 }
217
218 public static abstract class UserInfoProvider {
219 private int[] userIds;
220 protected abstract @Nullable int[] getUserIds();
221 @VisibleForTesting
222 public final void refreshUserIds() {
223 userIds = getUserIds();
224 }
225 @VisibleForTesting
226 public boolean exists(int userId) {
227 return userIds != null ? ArrayUtils.contains(userIds, userId) : true;
228 }
229 }
230
231 private final PlatformIdleStateCallback mPlatformIdleStateCallback;
232
233 final class MyHandler extends Handler {
234 public MyHandler(Looper looper) {
235 super(looper, null, true);
236 }
237
238 @Override
239 public void handleMessage(Message msg) {
240 BatteryCallback cb = mCallback;
241 switch (msg.what) {
242 case MSG_UPDATE_WAKELOCKS:
243 synchronized (BatteryStatsImpl.this) {
244 updateCpuTimeLocked();
245 }
246 if (cb != null) {
247 cb.batteryNeedsCpuUpdate();
248 }
249 break;
250 case MSG_REPORT_POWER_CHANGE:
251 if (cb != null) {
252 cb.batteryPowerChanged(msg.arg1 != 0);
253 }
254 break;
255 case MSG_REPORT_CHARGING:
256 if (cb != null) {
257 final String action;
258 synchronized (BatteryStatsImpl.this) {
259 action = mCharging ? BatteryManager.ACTION_CHARGING
260 : BatteryManager.ACTION_DISCHARGING;
261 }
262 Intent intent = new Intent(action);
263 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
264 cb.batterySendBroadcast(intent);
265 }
266 break;
267 }
268 }
269 }
270
271 public interface Clocks {
272 public long elapsedRealtime();
273 public long uptimeMillis();
274 }
275
276 public static class SystemClocks implements Clocks {
277 public long elapsedRealtime() {
278 return SystemClock.elapsedRealtime();
279 }
280
281 public long uptimeMillis() {
282 return SystemClock.uptimeMillis();
283 }
284 }
285
286 public interface ExternalStatsSync {
287 int UPDATE_CPU = 0x01;
288 int UPDATE_WIFI = 0x02;
289 int UPDATE_RADIO = 0x04;
290 int UPDATE_BT = 0x08;
Justin Klaassenbc81c7a2017-09-18 17:38:50 -0400291 int UPDATE_RPM = 0x10; // 16
292 int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM;
Justin Klaassen10d07c82017-09-15 17:58:39 -0400293
294 Future<?> scheduleSync(String reason, int flags);
295 Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
296 }
297
298 public final MyHandler mHandler;
299 private ExternalStatsSync mExternalSync = null;
300 @VisibleForTesting
301 protected UserInfoProvider mUserInfoProvider = null;
302
303 private BatteryCallback mCallback;
304
305 /**
306 * Mapping isolated uids to the actual owning app uid.
307 */
308 final SparseIntArray mIsolatedUids = new SparseIntArray();
309
310 /**
311 * The statistics we have collected organized by uids.
312 */
313 final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
314
315 // A set of pools of currently active timers. When a timer is queried, we will divide the
316 // elapsed time by the number of active timers to arrive at that timer's share of the time.
317 // In order to do this, we must refresh each timer whenever the number of active timers
318 // changes.
319 @VisibleForTesting
320 protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
321 final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
322 final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
323 final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
324 final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
325 final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
326 final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
327 final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
328 final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
329 final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers = new SparseArray<>();
330 final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
331 final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
332 final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
333 final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
334 final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
335
336 // Last partial timers we use for distributing CPU usage.
337 @VisibleForTesting
338 protected ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
339
340 // These are the objects that will want to do something when the device
341 // is unplugged from power.
342 protected final TimeBase mOnBatteryTimeBase = new TimeBase();
343
344 // These are the objects that will want to do something when the device
Justin Klaassen93b7ee42017-10-10 15:20:13 -0400345 // is unplugged from power *and* the screen is off or doze.
346 protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase();
Justin Klaassen10d07c82017-09-15 17:58:39 -0400347
348 // Set to true when we want to distribute CPU across wakelocks for the next
349 // CPU update, even if we aren't currently running wake locks.
350 boolean mDistributeWakelockCpu;
351
352 boolean mShuttingDown;
353
354 final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
355
356 long mHistoryBaseTime;
357 boolean mHaveBatteryLevel = false;
358 boolean mRecordingHistory = false;
359 int mNumHistoryItems;
360
361 final Parcel mHistoryBuffer = Parcel.obtain();
362 final HistoryItem mHistoryLastWritten = new HistoryItem();
363 final HistoryItem mHistoryLastLastWritten = new HistoryItem();
364 final HistoryItem mHistoryReadTmp = new HistoryItem();
365 final HistoryItem mHistoryAddTmp = new HistoryItem();
366 final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
367 String[] mReadHistoryStrings;
368 int[] mReadHistoryUids;
369 int mReadHistoryChars;
370 int mNextHistoryTagIdx = 0;
371 int mNumHistoryTagChars = 0;
372 int mHistoryBufferLastPos = -1;
373 boolean mHistoryOverflow = false;
374 int mActiveHistoryStates = 0xffffffff;
375 int mActiveHistoryStates2 = 0xffffffff;
376 long mLastHistoryElapsedRealtime = 0;
377 long mTrackRunningHistoryElapsedRealtime = 0;
378 long mTrackRunningHistoryUptime = 0;
379
380 final HistoryItem mHistoryCur = new HistoryItem();
381
382 HistoryItem mHistory;
383 HistoryItem mHistoryEnd;
384 HistoryItem mHistoryLastEnd;
385 HistoryItem mHistoryCache;
386
387 // Used by computeHistoryStepDetails
388 HistoryStepDetails mLastHistoryStepDetails = null;
389 byte mLastHistoryStepLevel = 0;
390 final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
391 final HistoryStepDetails mReadHistoryStepDetails = new HistoryStepDetails();
392 final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
393
394 /**
395 * Total time (in milliseconds) spent executing in user code.
396 */
397 long mLastStepCpuUserTime;
398 long mCurStepCpuUserTime;
399 /**
400 * Total time (in milliseconds) spent executing in kernel code.
401 */
402 long mLastStepCpuSystemTime;
403 long mCurStepCpuSystemTime;
404 /**
405 * Times from /proc/stat (but measured in milliseconds).
406 */
407 long mLastStepStatUserTime;
408 long mLastStepStatSystemTime;
409 long mLastStepStatIOWaitTime;
410 long mLastStepStatIrqTime;
411 long mLastStepStatSoftIrqTime;
412 long mLastStepStatIdleTime;
413 long mCurStepStatUserTime;
414 long mCurStepStatSystemTime;
415 long mCurStepStatIOWaitTime;
416 long mCurStepStatIrqTime;
417 long mCurStepStatSoftIrqTime;
418 long mCurStepStatIdleTime;
419
420 private HistoryItem mHistoryIterator;
421 private boolean mReadOverflow;
422 private boolean mIteratingHistory;
423
424 int mStartCount;
425
426 long mStartClockTime;
427 String mStartPlatformVersion;
428 String mEndPlatformVersion;
429
430 long mUptime;
431 long mUptimeStart;
432 long mRealtime;
433 long mRealtimeStart;
434
435 int mWakeLockNesting;
436 boolean mWakeLockImportant;
437 public boolean mRecordAllHistory;
438 boolean mNoAutoReset;
439
Justin Klaassen93b7ee42017-10-10 15:20:13 -0400440 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
441 protected int mScreenState = Display.STATE_UNKNOWN;
442 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
443 protected StopwatchTimer mScreenOnTimer;
444 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
445 protected StopwatchTimer mScreenDozeTimer;
Justin Klaassen10d07c82017-09-15 17:58:39 -0400446
447 int mScreenBrightnessBin = -1;
448 final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
449
450 boolean mPretendScreenOff;
451
452 boolean mInteractive;
453 StopwatchTimer mInteractiveTimer;
454
455 boolean mPowerSaveModeEnabled;
456 StopwatchTimer mPowerSaveModeEnabledTimer;
457
458 boolean mDeviceIdling;
459 StopwatchTimer mDeviceIdlingTimer;
460
461 boolean mDeviceLightIdling;
462 StopwatchTimer mDeviceLightIdlingTimer;
463
464 int mDeviceIdleMode;
465 long mLastIdleTimeStart;
466 long mLongestLightIdleTime;
467 long mLongestFullIdleTime;
468 StopwatchTimer mDeviceIdleModeLightTimer;
469 StopwatchTimer mDeviceIdleModeFullTimer;
470
471 boolean mPhoneOn;
472 StopwatchTimer mPhoneOnTimer;
473
474 int mAudioOnNesting;
475 StopwatchTimer mAudioOnTimer;
476
477 int mVideoOnNesting;
478 StopwatchTimer mVideoOnTimer;
479
480 int mFlashlightOnNesting;
481 StopwatchTimer mFlashlightOnTimer;
482
483 int mCameraOnNesting;
484 StopwatchTimer mCameraOnTimer;
485
486 int mPhoneSignalStrengthBin = -1;
487 int mPhoneSignalStrengthBinRaw = -1;
488 final StopwatchTimer[] mPhoneSignalStrengthsTimer =
489 new StopwatchTimer[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
490
491 StopwatchTimer mPhoneSignalScanningTimer;
492
493 int mPhoneDataConnectionType = -1;
494 final StopwatchTimer[] mPhoneDataConnectionsTimer =
495 new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
496
497 final LongSamplingCounter[] mNetworkByteActivityCounters =
498 new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
499 final LongSamplingCounter[] mNetworkPacketActivityCounters =
500 new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
501
502 /**
503 * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
504 */
505 ControllerActivityCounterImpl mWifiActivity;
506
507 /**
508 * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
509 */
510 ControllerActivityCounterImpl mBluetoothActivity;
511
512 /**
513 * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
514 */
515 ControllerActivityCounterImpl mModemActivity;
516
517 /**
518 * Whether the device supports WiFi controller energy reporting. This is set to true on
519 * the first WiFi energy report. See {@link #mWifiActivity}.
520 */
521 boolean mHasWifiReporting = false;
522
523 /**
524 * Whether the device supports Bluetooth controller energy reporting. This is set to true on
525 * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
526 */
527 boolean mHasBluetoothReporting = false;
528
529 /**
530 * Whether the device supports Modem controller energy reporting. This is set to true on
531 * the first Modem energy report. See {@link #mModemActivity}.
532 */
533 boolean mHasModemReporting = false;
534
535 boolean mWifiOn;
536 StopwatchTimer mWifiOnTimer;
537
538 boolean mGlobalWifiRunning;
539 StopwatchTimer mGlobalWifiRunningTimer;
540
541 int mWifiState = -1;
542 final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
543
544 int mWifiSupplState = -1;
545 final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
546
547 int mWifiSignalStrengthBin = -1;
548 final StopwatchTimer[] mWifiSignalStrengthsTimer =
549 new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
550
551 int mBluetoothScanNesting;
552 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
553 protected StopwatchTimer mBluetoothScanTimer;
554
555 int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
556 long mMobileRadioActiveStartTime;
557 StopwatchTimer mMobileRadioActiveTimer;
558 StopwatchTimer mMobileRadioActivePerAppTimer;
559 LongSamplingCounter mMobileRadioActiveAdjustedTime;
560 LongSamplingCounter mMobileRadioActiveUnknownTime;
561 LongSamplingCounter mMobileRadioActiveUnknownCount;
562
563 int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
564
565 /**
566 * These provide time bases that discount the time the device is plugged
567 * in to power.
568 */
569 boolean mOnBattery;
570 @VisibleForTesting
571 protected boolean mOnBatteryInternal;
572
573 /**
574 * External reporting of whether the device is actually charging.
575 */
576 boolean mCharging = true;
577 int mLastChargingStateLevel;
578
579 /*
580 * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
581 */
582 int mDischargeStartLevel;
583 int mDischargeUnplugLevel;
584 int mDischargePlugLevel;
585 int mDischargeCurrentLevel;
586 int mCurrentBatteryLevel;
587 int mLowDischargeAmountSinceCharge;
588 int mHighDischargeAmountSinceCharge;
589 int mDischargeScreenOnUnplugLevel;
590 int mDischargeScreenOffUnplugLevel;
Justin Klaassen93b7ee42017-10-10 15:20:13 -0400591 int mDischargeScreenDozeUnplugLevel;
Justin Klaassen10d07c82017-09-15 17:58:39 -0400592 int mDischargeAmountScreenOn;
593 int mDischargeAmountScreenOnSinceCharge;
594 int mDischargeAmountScreenOff;
595 int mDischargeAmountScreenOffSinceCharge;
Justin Klaassen93b7ee42017-10-10 15:20:13 -0400596 int mDischargeAmountScreenDoze;
597 int mDischargeAmountScreenDozeSinceCharge;
Justin Klaassen10d07c82017-09-15 17:58:39 -0400598
599 private LongSamplingCounter mDischargeScreenOffCounter;
Justin Klaassen93b7ee42017-10-10 15:20:13 -0400600 private LongSamplingCounter mDischargeScreenDozeCounter;
Justin Klaassen10d07c82017-09-15 17:58:39 -0400601 private LongSamplingCounter mDischargeCounter;
602
603 static final int MAX_LEVEL_STEPS = 200;
604
605 int mInitStepMode = 0;
606 int mCurStepMode = 0;
607 int mModStepMode = 0;
608
609 int mLastDischargeStepLevel;
610 int mMinDischargeStepLevel;
611 final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
612 final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
613 ArrayList<PackageChange> mDailyPackageChanges;
614
615 int mLastChargeStepLevel;
616 int mMaxChargeStepLevel;
617 final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
618 final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
619
620 static final int MAX_DAILY_ITEMS = 10;
621
622 long mDailyStartTime = 0;
623 long mNextMinDailyDeadline = 0;
624 long mNextMaxDailyDeadline = 0;
625
626 final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
627
628 long mLastWriteTime = 0; // Milliseconds
629
630 private int mPhoneServiceState = -1;
631 private int mPhoneServiceStateRaw = -1;
632 private int mPhoneSimStateRaw = -1;
633
634 private int mNumConnectivityChange;
635 private int mLoadedNumConnectivityChange;
636 private int mUnpluggedNumConnectivityChange;
637
638 private int mEstimatedBatteryCapacity = -1;
639
640 private int mMinLearnedBatteryCapacity = -1;
641 private int mMaxLearnedBatteryCapacity = -1;
642
643 private long[] mCpuFreqs;
644
645 @VisibleForTesting
646 protected PowerProfile mPowerProfile;
647
648 /*
Justin Klaassenbc81c7a2017-09-18 17:38:50 -0400649 * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
650 * recording their times when on-battery (regardless of screen state).
651 */
652 private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>();
653 /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */
654 private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>();
655
656 @Override
657 public Map<String, ? extends Timer> getRpmStats() {
658 return mRpmStats;
659 }
660
661 // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED.
662 @Override
663 public Map<String, ? extends Timer> getScreenOffRpmStats() {
664 return mScreenOffRpmStats;
665 }
666
667 /*
Justin Klaassen10d07c82017-09-15 17:58:39 -0400668 * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
669 */
670 private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
671
672 public Map<String, ? extends Timer> getKernelWakelockStats() {
673 return mKernelWakelockStats;
674 }
675
676 String mLastWakeupReason = null;
677 long mLastWakeupUptimeMs = 0;
678 private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
679
680 public Map<String, ? extends Timer> getWakeupReasonStats() {
681 return mWakeupReasonStats;
682 }
683
684 @Override
Justin Klaassen47ed54e2017-10-24 19:50:40 -0400685 public long getUahDischarge(int which) {
Justin Klaassen93b7ee42017-10-10 15:20:13 -0400686 return mDischargeCounter.getCountLocked(which);
Justin Klaassen10d07c82017-09-15 17:58:39 -0400687 }
688
689 @Override
Justin Klaassen47ed54e2017-10-24 19:50:40 -0400690 public long getUahDischargeScreenOff(int which) {
Justin Klaassen93b7ee42017-10-10 15:20:13 -0400691 return mDischargeScreenOffCounter.getCountLocked(which);
692 }
693
694 @Override
Justin Klaassen47ed54e2017-10-24 19:50:40 -0400695 public long getUahDischargeScreenDoze(int which) {
Justin Klaassen93b7ee42017-10-10 15:20:13 -0400696 return mDischargeScreenDozeCounter.getCountLocked(which);
Justin Klaassen10d07c82017-09-15 17:58:39 -0400697 }
698
699 @Override
700 public int getEstimatedBatteryCapacity() {
701 return mEstimatedBatteryCapacity;
702 }
703
704 @Override
705 public int getMinLearnedBatteryCapacity() {
706 return mMinLearnedBatteryCapacity;
707 }
708
709 @Override
710 public int getMaxLearnedBatteryCapacity() {
711 return mMaxLearnedBatteryCapacity;
712 }
713
714 public BatteryStatsImpl() {
715 this(new SystemClocks());
716 }
717
718 public BatteryStatsImpl(Clocks clocks) {
719 init(clocks);
720 mFile = null;
721 mCheckinFile = null;
722 mDailyFile = null;
723 mHandler = null;
724 mPlatformIdleStateCallback = null;
725 mUserInfoProvider = null;
726 clearHistoryLocked();
727 }
728
729 private void init(Clocks clocks) {
730 mClocks = clocks;
731 }
732
733 public interface TimeBaseObs {
734 void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
735 void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
736 }
737
738 // methods are protected not private to be VisibleForTesting
739 public static class TimeBase {
740 protected final ArrayList<TimeBaseObs> mObservers = new ArrayList<>();
741
742 protected long mUptime;
743 protected long mRealtime;
744
745 protected boolean mRunning;
746
747 protected long mPastUptime;
748 protected long mUptimeStart;
749 protected long mPastRealtime;
750 protected long mRealtimeStart;
751 protected long mUnpluggedUptime;
752 protected long mUnpluggedRealtime;
753
754 public void dump(PrintWriter pw, String prefix) {
755 StringBuilder sb = new StringBuilder(128);
756 pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
757 sb.setLength(0);
758 sb.append(prefix);
759 sb.append("mUptime=");
760 formatTimeMs(sb, mUptime / 1000);
761 pw.println(sb.toString());
762 sb.setLength(0);
763 sb.append(prefix);
764 sb.append("mRealtime=");
765 formatTimeMs(sb, mRealtime / 1000);
766 pw.println(sb.toString());
767 sb.setLength(0);
768 sb.append(prefix);
769 sb.append("mPastUptime=");
770 formatTimeMs(sb, mPastUptime / 1000); sb.append("mUptimeStart=");
771 formatTimeMs(sb, mUptimeStart / 1000);
772 sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptime / 1000);
773 pw.println(sb.toString());
774 sb.setLength(0);
775 sb.append(prefix);
776 sb.append("mPastRealtime=");
777 formatTimeMs(sb, mPastRealtime / 1000); sb.append("mRealtimeStart=");
778 formatTimeMs(sb, mRealtimeStart / 1000);
779 sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000);
780 pw.println(sb.toString());
781 }
782
783 public void add(TimeBaseObs observer) {
784 mObservers.add(observer);
785 }
786
787 public void remove(TimeBaseObs observer) {
788 if (!mObservers.remove(observer)) {
789 Slog.wtf(TAG, "Removed unknown observer: " + observer);
790 }
791 }
792
793 public boolean hasObserver(TimeBaseObs observer) {
794 return mObservers.contains(observer);
795 }
796
797 public void init(long uptime, long realtime) {
798 mRealtime = 0;
799 mUptime = 0;
800 mPastUptime = 0;
801 mPastRealtime = 0;
802 mUptimeStart = uptime;
803 mRealtimeStart = realtime;
804 mUnpluggedUptime = getUptime(mUptimeStart);
805 mUnpluggedRealtime = getRealtime(mRealtimeStart);
806 }
807
808 public void reset(long uptime, long realtime) {
809 if (!mRunning) {
810 mPastUptime = 0;
811 mPastRealtime = 0;
812 } else {
813 mUptimeStart = uptime;
814 mRealtimeStart = realtime;
815 // TODO: Since mUptimeStart was just reset and we are running, getUptime will
816 // just return mPastUptime. Also, are we sure we don't want to reset that?
817 mUnpluggedUptime = getUptime(uptime);
818 // TODO: likewise.
819 mUnpluggedRealtime = getRealtime(realtime);
820 }
821 }
822
823 public long computeUptime(long curTime, int which) {
824 switch (which) {
825 case STATS_SINCE_CHARGED:
826 return mUptime + getUptime(curTime);
827 case STATS_CURRENT:
828 return getUptime(curTime);
829 case STATS_SINCE_UNPLUGGED:
830 return getUptime(curTime) - mUnpluggedUptime;
831 }
832 return 0;
833 }
834
835 public long computeRealtime(long curTime, int which) {
836 switch (which) {
837 case STATS_SINCE_CHARGED:
838 return mRealtime + getRealtime(curTime);
839 case STATS_CURRENT:
840 return getRealtime(curTime);
841 case STATS_SINCE_UNPLUGGED:
842 return getRealtime(curTime) - mUnpluggedRealtime;
843 }
844 return 0;
845 }
846
847 public long getUptime(long curTime) {
848 long time = mPastUptime;
849 if (mRunning) {
850 time += curTime - mUptimeStart;
851 }
852 return time;
853 }
854
855 public long getRealtime(long curTime) {
856 long time = mPastRealtime;
857 if (mRunning) {
858 time += curTime - mRealtimeStart;
859 }
860 return time;
861 }
862
863 public long getUptimeStart() {
864 return mUptimeStart;
865 }
866
867 public long getRealtimeStart() {
868 return mRealtimeStart;
869 }
870
871 public boolean isRunning() {
872 return mRunning;
873 }
874
875 public boolean setRunning(boolean running, long uptime, long realtime) {
876 if (mRunning != running) {
877 mRunning = running;
878 if (running) {
879 mUptimeStart = uptime;
880 mRealtimeStart = realtime;
881 long batteryUptime = mUnpluggedUptime = getUptime(uptime);
882 long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime);
883
884 for (int i = mObservers.size() - 1; i >= 0; i--) {
885 mObservers.get(i).onTimeStarted(realtime, batteryUptime, batteryRealtime);
886 }
887 } else {
888 mPastUptime += uptime - mUptimeStart;
889 mPastRealtime += realtime - mRealtimeStart;
890
891 long batteryUptime = getUptime(uptime);
892 long batteryRealtime = getRealtime(realtime);
893
894 for (int i = mObservers.size() - 1; i >= 0; i--) {
895 mObservers.get(i).onTimeStopped(realtime, batteryUptime, batteryRealtime);
896 }
897 }
898 return true;
899 }
900 return false;
901 }
902
903 public void readSummaryFromParcel(Parcel in) {
904 mUptime = in.readLong();
905 mRealtime = in.readLong();
906 }
907
908 public void writeSummaryToParcel(Parcel out, long uptime, long realtime) {
909 out.writeLong(computeUptime(uptime, STATS_SINCE_CHARGED));
910 out.writeLong(computeRealtime(realtime, STATS_SINCE_CHARGED));
911 }
912
913 public void readFromParcel(Parcel in) {
914 mRunning = false;
915 mUptime = in.readLong();
916 mPastUptime = in.readLong();
917 mUptimeStart = in.readLong();
918 mRealtime = in.readLong();
919 mPastRealtime = in.readLong();
920 mRealtimeStart = in.readLong();
921 mUnpluggedUptime = in.readLong();
922 mUnpluggedRealtime = in.readLong();
923 }
924
925 public void writeToParcel(Parcel out, long uptime, long realtime) {
926 final long runningUptime = getUptime(uptime);
927 final long runningRealtime = getRealtime(realtime);
928 out.writeLong(mUptime);
929 out.writeLong(runningUptime);
930 out.writeLong(mUptimeStart);
931 out.writeLong(mRealtime);
932 out.writeLong(runningRealtime);
933 out.writeLong(mRealtimeStart);
934 out.writeLong(mUnpluggedUptime);
935 out.writeLong(mUnpluggedRealtime);
936 }
937 }
938
939 /**
940 * State for keeping track of counting information.
941 */
942 public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
943 final AtomicInteger mCount = new AtomicInteger();
944 final TimeBase mTimeBase;
945 int mLoadedCount;
946 int mUnpluggedCount;
947 int mPluggedCount;
948
949 public Counter(TimeBase timeBase, Parcel in) {
950 mTimeBase = timeBase;
951 mPluggedCount = in.readInt();
952 mCount.set(mPluggedCount);
953 mLoadedCount = in.readInt();
954 mUnpluggedCount = in.readInt();
955 timeBase.add(this);
956 }
957
958 public Counter(TimeBase timeBase) {
959 mTimeBase = timeBase;
960 timeBase.add(this);
961 }
962
963 public void writeToParcel(Parcel out) {
964 out.writeInt(mCount.get());
965 out.writeInt(mLoadedCount);
966 out.writeInt(mUnpluggedCount);
967 }
968
969 @Override
970 public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
971 mUnpluggedCount = mPluggedCount;
972 }
973
974 @Override
975 public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
976 mPluggedCount = mCount.get();
977 }
978
979 /**
980 * Writes a possibly null Counter to a Parcel.
981 *
982 * @param out the Parcel to be written to.
983 * @param counter a Counter, or null.
984 */
985 public static void writeCounterToParcel(Parcel out, Counter counter) {
986 if (counter == null) {
987 out.writeInt(0); // indicates null
988 return;
989 }
990 out.writeInt(1); // indicates non-null
991
992 counter.writeToParcel(out);
993 }
994
995 @Override
996 public int getCountLocked(int which) {
997 int val = mCount.get();
998 if (which == STATS_SINCE_UNPLUGGED) {
999 val -= mUnpluggedCount;
1000 } else if (which != STATS_SINCE_CHARGED) {
1001 val -= mLoadedCount;
1002 }
1003
1004 return val;
1005 }
1006
1007 public void logState(Printer pw, String prefix) {
1008 pw.println(prefix + "mCount=" + mCount.get()
1009 + " mLoadedCount=" + mLoadedCount
1010 + " mUnpluggedCount=" + mUnpluggedCount
1011 + " mPluggedCount=" + mPluggedCount);
1012 }
1013
1014 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
1015 public void stepAtomic() {
1016 if (mTimeBase.isRunning()) {
1017 mCount.incrementAndGet();
1018 }
1019 }
1020
1021 void addAtomic(int delta) {
1022 if (mTimeBase.isRunning()) {
1023 mCount.addAndGet(delta);
1024 }
1025 }
1026
1027 /**
1028 * Clear state of this counter.
1029 */
1030 void reset(boolean detachIfReset) {
1031 mCount.set(0);
1032 mLoadedCount = mPluggedCount = mUnpluggedCount = 0;
1033 if (detachIfReset) {
1034 detach();
1035 }
1036 }
1037
1038 void detach() {
1039 mTimeBase.remove(this);
1040 }
1041
1042 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
1043 public void writeSummaryFromParcelLocked(Parcel out) {
1044 int count = mCount.get();
1045 out.writeInt(count);
1046 }
1047
1048 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
1049 public void readSummaryFromParcelLocked(Parcel in) {
1050 mLoadedCount = in.readInt();
1051 mCount.set(mLoadedCount);
1052 mUnpluggedCount = mPluggedCount = mLoadedCount;
1053 }
1054 }
1055
1056 @VisibleForTesting
1057 public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
1058 final TimeBase mTimeBase;
1059 public long[] mCounts;
1060 public long[] mLoadedCounts;
1061 public long[] mUnpluggedCounts;
1062 public long[] mPluggedCounts;
1063
1064 private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
1065 mTimeBase = timeBase;
1066 mPluggedCounts = in.createLongArray();
1067 mCounts = copyArray(mPluggedCounts, mCounts);
1068 mLoadedCounts = in.createLongArray();
1069 mUnpluggedCounts = in.createLongArray();
1070 timeBase.add(this);
1071 }
1072
1073 public LongSamplingCounterArray(TimeBase timeBase) {
1074 mTimeBase = timeBase;
1075 timeBase.add(this);
1076 }
1077
1078 private void writeToParcel(Parcel out) {
1079 out.writeLongArray(mCounts);
1080 out.writeLongArray(mLoadedCounts);
1081 out.writeLongArray(mUnpluggedCounts);
1082 }
1083
1084 @Override
1085 public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) {
1086 mUnpluggedCounts = copyArray(mPluggedCounts, mUnpluggedCounts);
1087 }
1088
1089 @Override
1090 public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1091 mPluggedCounts = copyArray(mCounts, mPluggedCounts);
1092 }
1093
1094 @Override
1095 public long[] getCountsLocked(int which) {
1096 long[] val = copyArray(mTimeBase.isRunning() ? mCounts : mPluggedCounts, null);
1097 if (which == STATS_SINCE_UNPLUGGED) {
1098 subtract(val, mUnpluggedCounts);
1099 } else if (which != STATS_SINCE_CHARGED) {
1100 subtract(val, mLoadedCounts);
1101 }
1102 return val;
1103 }
1104
1105 @Override
1106 public void logState(Printer pw, String prefix) {
1107 pw.println(prefix + "mCounts=" + Arrays.toString(mCounts)
1108 + " mLoadedCounts=" + Arrays.toString(mLoadedCounts)
1109 + " mUnpluggedCounts=" + Arrays.toString(mUnpluggedCounts)
1110 + " mPluggedCounts=" + Arrays.toString(mPluggedCounts));
1111 }
1112
1113 public void addCountLocked(long[] counts) {
1114 if (counts == null) {
1115 return;
1116 }
1117 if (mTimeBase.isRunning()) {
1118 if (mCounts == null) {
1119 mCounts = new long[counts.length];
1120 }
1121 for (int i = 0; i < counts.length; ++i) {
1122 mCounts[i] += counts[i];
1123 }
1124 }
1125 }
1126
1127 public int getSize() {
1128 return mCounts == null ? 0 : mCounts.length;
1129 }
1130
1131 /**
1132 * Clear state of this counter.
1133 */
1134 public void reset(boolean detachIfReset) {
1135 fillArray(mCounts, 0);
1136 fillArray(mLoadedCounts, 0);
1137 fillArray(mPluggedCounts, 0);
1138 fillArray(mUnpluggedCounts, 0);
1139 if (detachIfReset) {
1140 detach();
1141 }
1142 }
1143
1144 public void detach() {
1145 mTimeBase.remove(this);
1146 }
1147
1148 private void writeSummaryToParcelLocked(Parcel out) {
1149 out.writeLongArray(mCounts);
1150 }
1151
1152 private void readSummaryFromParcelLocked(Parcel in) {
1153 mCounts = in.createLongArray();
1154 mLoadedCounts = copyArray(mCounts, mLoadedCounts);
1155 mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
1156 mPluggedCounts = copyArray(mCounts, mPluggedCounts);
1157 }
1158
1159 public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
1160 if (counterArray != null) {
1161 out.writeInt(1);
1162 counterArray.writeToParcel(out);
1163 } else {
1164 out.writeInt(0);
1165 }
1166 }
1167
1168 public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
1169 if (in.readInt() != 0) {
1170 return new LongSamplingCounterArray(timeBase, in);
1171 } else {
1172 return null;
1173 }
1174 }
1175
1176 public static void writeSummaryToParcelLocked(Parcel out,
1177 LongSamplingCounterArray counterArray) {
1178 if (counterArray != null) {
1179 out.writeInt(1);
1180 counterArray.writeSummaryToParcelLocked(out);
1181 } else {
1182 out.writeInt(0);
1183 }
1184 }
1185
1186 public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
1187 TimeBase timeBase) {
1188 if (in.readInt() != 0) {
1189 final LongSamplingCounterArray counterArray
1190 = new LongSamplingCounterArray(timeBase);
1191 counterArray.readSummaryFromParcelLocked(in);
1192 return counterArray;
1193 } else {
1194 return null;
1195 }
1196 }
1197
1198 private static void fillArray(long[] a, long val) {
1199 if (a != null) {
1200 Arrays.fill(a, val);
1201 }
1202 }
1203
1204 private static void subtract(@NonNull long[] val, long[] toSubtract) {
1205 if (toSubtract == null) {
1206 return;
1207 }
1208 for (int i = 0; i < val.length; i++) {
1209 val[i] -= toSubtract[i];
1210 }
1211 }
1212
1213 private static long[] copyArray(long[] src, long[] dest) {
1214 if (src == null) {
1215 return null;
1216 } else {
1217 if (dest == null) {
1218 dest = new long[src.length];
1219 }
1220 System.arraycopy(src, 0, dest, 0, src.length);
1221 return dest;
1222 }
1223 }
1224 }
1225
1226 public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
1227 final TimeBase mTimeBase;
1228 long mCount;
1229 long mLoadedCount;
1230 long mUnpluggedCount;
1231 long mPluggedCount;
1232
1233 LongSamplingCounter(TimeBase timeBase, Parcel in) {
1234 mTimeBase = timeBase;
1235 mPluggedCount = in.readLong();
1236 mCount = mPluggedCount;
1237 mLoadedCount = in.readLong();
1238 mUnpluggedCount = in.readLong();
1239 timeBase.add(this);
1240 }
1241
1242 LongSamplingCounter(TimeBase timeBase) {
1243 mTimeBase = timeBase;
1244 timeBase.add(this);
1245 }
1246
1247 public void writeToParcel(Parcel out) {
1248 out.writeLong(mCount);
1249 out.writeLong(mLoadedCount);
1250 out.writeLong(mUnpluggedCount);
1251 }
1252
1253 @Override
1254 public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1255 mUnpluggedCount = mPluggedCount;
1256 }
1257
1258 @Override
1259 public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1260 mPluggedCount = mCount;
1261 }
1262
1263 public long getCountLocked(int which) {
1264 long val = mTimeBase.isRunning() ? mCount : mPluggedCount;
1265 if (which == STATS_SINCE_UNPLUGGED) {
1266 val -= mUnpluggedCount;
1267 } else if (which != STATS_SINCE_CHARGED) {
1268 val -= mLoadedCount;
1269 }
1270 return val;
1271 }
1272
1273 @Override
1274 public void logState(Printer pw, String prefix) {
1275 pw.println(prefix + "mCount=" + mCount
1276 + " mLoadedCount=" + mLoadedCount
1277 + " mUnpluggedCount=" + mUnpluggedCount
1278 + " mPluggedCount=" + mPluggedCount);
1279 }
1280
1281 void addCountLocked(long count) {
1282 if (mTimeBase.isRunning()) {
1283 mCount += count;
1284 }
1285 }
1286
1287 /**
1288 * Clear state of this counter.
1289 */
1290 void reset(boolean detachIfReset) {
1291 mCount = 0;
1292 mLoadedCount = mPluggedCount = mUnpluggedCount = 0;
1293 if (detachIfReset) {
1294 detach();
1295 }
1296 }
1297
1298 void detach() {
1299 mTimeBase.remove(this);
1300 }
1301
1302 void writeSummaryFromParcelLocked(Parcel out) {
1303 out.writeLong(mCount);
1304 }
1305
1306 void readSummaryFromParcelLocked(Parcel in) {
1307 mLoadedCount = in.readLong();
1308 mCount = mLoadedCount;
1309 mUnpluggedCount = mPluggedCount = mLoadedCount;
1310 }
1311 }
1312
1313 /**
1314 * State for keeping track of timing information.
1315 */
1316 public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
1317 protected final Clocks mClocks;
1318 protected final int mType;
1319 protected final TimeBase mTimeBase;
1320
1321 protected int mCount;
1322 protected int mLoadedCount;
1323 protected int mLastCount;
1324 protected int mUnpluggedCount;
1325
1326 // Times are in microseconds for better accuracy when dividing by the
1327 // lock count, and are in "battery realtime" units.
1328
1329 /**
1330 * The total time we have accumulated since the start of the original
1331 * boot, to the last time something interesting happened in the
1332 * current run.
1333 */
1334 protected long mTotalTime;
1335
1336 /**
1337 * The total time we loaded for the previous runs. Subtract this from
1338 * mTotalTime to find the time for the current run of the system.
1339 */
1340 protected long mLoadedTime;
1341
1342 /**
1343 * The run time of the last run of the system, as loaded from the
1344 * saved data.
1345 */
1346 protected long mLastTime;
1347
1348 /**
1349 * The value of mTotalTime when unplug() was last called. Subtract
1350 * this from mTotalTime to find the time since the last unplug from
1351 * power.
1352 */
1353 protected long mUnpluggedTime;
1354
1355 /**
1356 * The total time this timer has been running until the latest mark has been set.
1357 * Subtract this from mTotalTime to get the time spent running since the mark was set.
1358 */
1359 protected long mTimeBeforeMark;
1360
1361 /**
1362 * Constructs from a parcel.
1363 * @param type
1364 * @param timeBase
1365 * @param in
1366 */
1367 public Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in) {
1368 mClocks = clocks;
1369 mType = type;
1370 mTimeBase = timeBase;
1371
1372 mCount = in.readInt();
1373 mLoadedCount = in.readInt();
1374 mLastCount = 0;
1375 mUnpluggedCount = in.readInt();
1376 mTotalTime = in.readLong();
1377 mLoadedTime = in.readLong();
1378 mLastTime = 0;
1379 mUnpluggedTime = in.readLong();
1380 mTimeBeforeMark = in.readLong();
1381 timeBase.add(this);
1382 if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTime);
1383 }
1384
1385 public Timer(Clocks clocks, int type, TimeBase timeBase) {
1386 mClocks = clocks;
1387 mType = type;
1388 mTimeBase = timeBase;
1389 timeBase.add(this);
1390 }
1391
1392 protected abstract long computeRunTimeLocked(long curBatteryRealtime);
1393
1394 protected abstract int computeCurrentCountLocked();
1395
1396 /**
1397 * Clear state of this timer. Returns true if the timer is inactive
1398 * so can be completely dropped.
1399 */
1400 public boolean reset(boolean detachIfReset) {
1401 mTotalTime = mLoadedTime = mLastTime = mTimeBeforeMark = 0;
1402 mCount = mLoadedCount = mLastCount = 0;
1403 if (detachIfReset) {
1404 detach();
1405 }
1406 return true;
1407 }
1408
1409 public void detach() {
1410 mTimeBase.remove(this);
1411 }
1412
1413 public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1414 if (DEBUG) Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
1415 + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
1416 out.writeInt(computeCurrentCountLocked());
1417 out.writeInt(mLoadedCount);
1418 out.writeInt(mUnpluggedCount);
1419 out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
1420 out.writeLong(mLoadedTime);
1421 out.writeLong(mUnpluggedTime);
1422 out.writeLong(mTimeBeforeMark);
1423 }
1424
1425 @Override
1426 public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) {
1427 if (DEBUG && mType < 0) {
1428 Log.v(TAG, "unplug #" + mType + ": realtime=" + baseRealtime
1429 + " old mUnpluggedTime=" + mUnpluggedTime
1430 + " old mUnpluggedCount=" + mUnpluggedCount);
1431 }
1432 mUnpluggedTime = computeRunTimeLocked(baseRealtime);
1433 mUnpluggedCount = computeCurrentCountLocked();
1434 if (DEBUG && mType < 0) {
1435 Log.v(TAG, "unplug #" + mType
1436 + ": new mUnpluggedTime=" + mUnpluggedTime
1437 + " new mUnpluggedCount=" + mUnpluggedCount);
1438 }
1439 }
1440
1441 @Override
1442 public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1443 if (DEBUG && mType < 0) {
1444 Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtime
1445 + " old mTotalTime=" + mTotalTime);
1446 }
1447 mTotalTime = computeRunTimeLocked(baseRealtime);
1448 mCount = computeCurrentCountLocked();
1449 if (DEBUG && mType < 0) {
1450 Log.v(TAG, "plug #" + mType
1451 + ": new mTotalTime=" + mTotalTime);
1452 }
1453 }
1454
1455 /**
1456 * Writes a possibly null Timer to a Parcel.
1457 *
1458 * @param out the Parcel to be written to.
1459 * @param timer a Timer, or null.
1460 */
1461 public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
1462 if (timer == null) {
1463 out.writeInt(0); // indicates null
1464 return;
1465 }
1466 out.writeInt(1); // indicates non-null
1467
1468 timer.writeToParcel(out, elapsedRealtimeUs);
1469 }
1470
1471 @Override
1472 public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
1473 long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1474 if (which == STATS_SINCE_UNPLUGGED) {
1475 val -= mUnpluggedTime;
1476 } else if (which != STATS_SINCE_CHARGED) {
1477 val -= mLoadedTime;
1478 }
1479
1480 return val;
1481 }
1482
1483 @Override
1484 public int getCountLocked(int which) {
1485 int val = computeCurrentCountLocked();
1486 if (which == STATS_SINCE_UNPLUGGED) {
1487 val -= mUnpluggedCount;
1488 } else if (which != STATS_SINCE_CHARGED) {
1489 val -= mLoadedCount;
1490 }
1491
1492 return val;
1493 }
1494
1495 @Override
1496 public long getTimeSinceMarkLocked(long elapsedRealtimeUs) {
1497 long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1498 return val - mTimeBeforeMark;
1499 }
1500
1501 @Override
1502 public void logState(Printer pw, String prefix) {
1503 pw.println(prefix + "mCount=" + mCount
1504 + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
1505 + " mUnpluggedCount=" + mUnpluggedCount);
1506 pw.println(prefix + "mTotalTime=" + mTotalTime
1507 + " mLoadedTime=" + mLoadedTime);
1508 pw.println(prefix + "mLastTime=" + mLastTime
1509 + " mUnpluggedTime=" + mUnpluggedTime);
1510 }
1511
1512
1513 public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
1514 long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1515 out.writeLong(runTime);
1516 out.writeInt(computeCurrentCountLocked());
1517 }
1518
1519 public void readSummaryFromParcelLocked(Parcel in) {
1520 // Multiply by 1000 for backwards compatibility
1521 mTotalTime = mLoadedTime = in.readLong();
1522 mLastTime = 0;
1523 mUnpluggedTime = mTotalTime;
1524 mCount = mLoadedCount = in.readInt();
1525 mLastCount = 0;
1526 mUnpluggedCount = mCount;
1527
1528 // When reading the summary, we set the mark to be the latest information.
1529 mTimeBeforeMark = mTotalTime;
1530 }
1531 }
1532
1533 /**
1534 * A counter meant to accept monotonically increasing values to its {@link #update(long, int)}
1535 * method. The state of the timer according to its {@link TimeBase} will determine how much
1536 * of the value is recorded.
1537 *
1538 * If the value being recorded resets, {@link #endSample()} can be called in order to
1539 * account for the change. If the value passed in to {@link #update(long, int)} decreased
1540 * between calls, the {@link #endSample()} is automatically called and the new value is
1541 * expected to increase monotonically from that point on.
1542 */
1543 public static class SamplingTimer extends Timer {
1544
1545 /**
1546 * The most recent reported count from /proc/wakelocks.
1547 */
1548 int mCurrentReportedCount;
1549
1550 /**
1551 * The reported count from /proc/wakelocks when unplug() was last
1552 * called.
1553 */
1554 int mUnpluggedReportedCount;
1555
1556 /**
1557 * The most recent reported total_time from /proc/wakelocks.
1558 */
1559 long mCurrentReportedTotalTime;
1560
1561
1562 /**
1563 * The reported total_time from /proc/wakelocks when unplug() was last
1564 * called.
1565 */
1566 long mUnpluggedReportedTotalTime;
1567
1568 /**
1569 * Whether we are currently in a discharge cycle.
1570 */
1571 boolean mTimeBaseRunning;
1572
1573 /**
1574 * Whether we are currently recording reported values.
1575 */
1576 boolean mTrackingReportedValues;
1577
1578 /*
1579 * A sequence counter, incremented once for each update of the stats.
1580 */
1581 int mUpdateVersion;
1582
1583 @VisibleForTesting
1584 public SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in) {
1585 super(clocks, 0, timeBase, in);
1586 mCurrentReportedCount = in.readInt();
1587 mUnpluggedReportedCount = in.readInt();
1588 mCurrentReportedTotalTime = in.readLong();
1589 mUnpluggedReportedTotalTime = in.readLong();
1590 mTrackingReportedValues = in.readInt() == 1;
1591 mTimeBaseRunning = timeBase.isRunning();
1592 }
1593
1594 @VisibleForTesting
1595 public SamplingTimer(Clocks clocks, TimeBase timeBase) {
1596 super(clocks, 0, timeBase);
1597 mTrackingReportedValues = false;
1598 mTimeBaseRunning = timeBase.isRunning();
1599 }
1600
1601 /**
1602 * Ends the current sample, allowing subsequent values to {@link #update(long, int)} to
1603 * be less than the values used for a previous invocation.
1604 */
1605 public void endSample() {
1606 mTotalTime = computeRunTimeLocked(0 /* unused by us */);
1607 mCount = computeCurrentCountLocked();
1608 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = 0;
1609 mUnpluggedReportedCount = mCurrentReportedCount = 0;
1610 }
1611
1612 public void setUpdateVersion(int version) {
1613 mUpdateVersion = version;
1614 }
1615
1616 public int getUpdateVersion() {
1617 return mUpdateVersion;
1618 }
1619
1620 /**
1621 * Updates the current recorded values. These are meant to be monotonically increasing
1622 * and cumulative. If you are dealing with deltas, use {@link #add(long, int)}.
1623 *
1624 * If the values being recorded have been reset, the monotonically increasing requirement
1625 * will be broken. In this case, {@link #endSample()} is automatically called and
1626 * the total value of totalTime and count are recorded, starting a new monotonically
1627 * increasing sample.
1628 *
1629 * @param totalTime total time of sample in microseconds.
1630 * @param count total number of times the event being sampled occurred.
1631 */
1632 public void update(long totalTime, int count) {
1633 if (mTimeBaseRunning && !mTrackingReportedValues) {
1634 // Updating the reported value for the first time.
1635 mUnpluggedReportedTotalTime = totalTime;
1636 mUnpluggedReportedCount = count;
1637 }
1638
1639 mTrackingReportedValues = true;
1640
1641 if (totalTime < mCurrentReportedTotalTime || count < mCurrentReportedCount) {
1642 endSample();
1643 }
1644
1645 mCurrentReportedTotalTime = totalTime;
1646 mCurrentReportedCount = count;
1647 }
1648
1649 /**
1650 * Adds deltaTime and deltaCount to the current sample.
1651 *
1652 * @param deltaTime additional time recorded since the last sampled event, in microseconds.
1653 * @param deltaCount additional number of times the event being sampled occurred.
1654 */
1655 public void add(long deltaTime, int deltaCount) {
1656 update(mCurrentReportedTotalTime + deltaTime, mCurrentReportedCount + deltaCount);
1657 }
1658
1659 @Override
1660 public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1661 super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
1662 if (mTrackingReportedValues) {
1663 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
1664 mUnpluggedReportedCount = mCurrentReportedCount;
1665 }
1666 mTimeBaseRunning = true;
1667 }
1668
1669 @Override
1670 public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1671 super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
1672 mTimeBaseRunning = false;
1673 }
1674
1675 @Override
1676 public void logState(Printer pw, String prefix) {
1677 super.logState(pw, prefix);
1678 pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
1679 + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
1680 + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
1681 + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
1682 }
1683
1684 @Override
1685 protected long computeRunTimeLocked(long curBatteryRealtime) {
1686 return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues
1687 ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
1688 }
1689
1690 @Override
1691 protected int computeCurrentCountLocked() {
1692 return mCount + (mTimeBaseRunning && mTrackingReportedValues
1693 ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
1694 }
1695
1696 @Override
1697 public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1698 super.writeToParcel(out, elapsedRealtimeUs);
1699 out.writeInt(mCurrentReportedCount);
1700 out.writeInt(mUnpluggedReportedCount);
1701 out.writeLong(mCurrentReportedTotalTime);
1702 out.writeLong(mUnpluggedReportedTotalTime);
1703 out.writeInt(mTrackingReportedValues ? 1 : 0);
1704 }
1705
1706 @Override
1707 public boolean reset(boolean detachIfReset) {
1708 super.reset(detachIfReset);
1709 mTrackingReportedValues = false;
1710 mUnpluggedReportedTotalTime = 0;
1711 mUnpluggedReportedCount = 0;
1712 return true;
1713 }
1714 }
1715
1716 /**
1717 * A timer that increments in batches. It does not run for durations, but just jumps
1718 * for a pre-determined amount.
1719 */
1720 public static class BatchTimer extends Timer {
1721 final Uid mUid;
1722
1723 /**
1724 * The last time at which we updated the timer. This is in elapsed realtime microseconds.
1725 */
1726 long mLastAddedTime;
1727
1728 /**
1729 * The last duration that we added to the timer. This is in microseconds.
1730 */
1731 long mLastAddedDuration;
1732
1733 /**
1734 * Whether we are currently in a discharge cycle.
1735 */
1736 boolean mInDischarge;
1737
1738 BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in) {
1739 super(clocks, type, timeBase, in);
1740 mUid = uid;
1741 mLastAddedTime = in.readLong();
1742 mLastAddedDuration = in.readLong();
1743 mInDischarge = timeBase.isRunning();
1744 }
1745
1746 BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase) {
1747 super(clocks, type, timeBase);
1748 mUid = uid;
1749 mInDischarge = timeBase.isRunning();
1750 }
1751
1752 @Override
1753 public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1754 super.writeToParcel(out, elapsedRealtimeUs);
1755 out.writeLong(mLastAddedTime);
1756 out.writeLong(mLastAddedDuration);
1757 }
1758
1759 @Override
1760 public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1761 recomputeLastDuration(mClocks.elapsedRealtime() * 1000, false);
1762 mInDischarge = false;
1763 super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
1764 }
1765
1766 @Override
1767 public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1768 recomputeLastDuration(elapsedRealtime, false);
1769 mInDischarge = true;
1770 // If we are still within the last added duration, then re-added whatever remains.
1771 if (mLastAddedTime == elapsedRealtime) {
1772 mTotalTime += mLastAddedDuration;
1773 }
1774 super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
1775 }
1776
1777 @Override
1778 public void logState(Printer pw, String prefix) {
1779 super.logState(pw, prefix);
1780 pw.println(prefix + "mLastAddedTime=" + mLastAddedTime
1781 + " mLastAddedDuration=" + mLastAddedDuration);
1782 }
1783
1784 private long computeOverage(long curTime) {
1785 if (mLastAddedTime > 0) {
1786 return mLastTime + mLastAddedDuration - curTime;
1787 }
1788 return 0;
1789 }
1790
1791 private void recomputeLastDuration(long curTime, boolean abort) {
1792 final long overage = computeOverage(curTime);
1793 if (overage > 0) {
1794 // Aborting before the duration ran out -- roll back the remaining
1795 // duration. Only do this if currently discharging; otherwise we didn't
1796 // actually add the time.
1797 if (mInDischarge) {
1798 mTotalTime -= overage;
1799 }
1800 if (abort) {
1801 mLastAddedTime = 0;
1802 } else {
1803 mLastAddedTime = curTime;
1804 mLastAddedDuration -= overage;
1805 }
1806 }
1807 }
1808
1809 public void addDuration(BatteryStatsImpl stats, long durationMillis) {
1810 final long now = mClocks.elapsedRealtime() * 1000;
1811 recomputeLastDuration(now, true);
1812 mLastAddedTime = now;
1813 mLastAddedDuration = durationMillis * 1000;
1814 if (mInDischarge) {
1815 mTotalTime += mLastAddedDuration;
1816 mCount++;
1817 }
1818 }
1819
1820 public void abortLastDuration(BatteryStatsImpl stats) {
1821 final long now = mClocks.elapsedRealtime() * 1000;
1822 recomputeLastDuration(now, true);
1823 }
1824
1825 @Override
1826 protected int computeCurrentCountLocked() {
1827 return mCount;
1828 }
1829
1830 @Override
1831 protected long computeRunTimeLocked(long curBatteryRealtime) {
1832 final long overage = computeOverage(mClocks.elapsedRealtime() * 1000);
1833 if (overage > 0) {
1834 return mTotalTime = overage;
1835 }
1836 return mTotalTime;
1837 }
1838
1839 @Override
1840 public boolean reset(boolean detachIfReset) {
1841 final long now = mClocks.elapsedRealtime() * 1000;
1842 recomputeLastDuration(now, true);
1843 boolean stillActive = mLastAddedTime == now;
1844 super.reset(!stillActive && detachIfReset);
1845 return !stillActive;
1846 }
1847 }
1848
1849
1850 /**
1851 * A StopwatchTimer that also tracks the total and max individual
1852 * time spent active according to the given timebase. Whereas
1853 * StopwatchTimer apportions the time amongst all in the pool,
1854 * the total and max durations are not apportioned.
1855 */
1856 public static class DurationTimer extends StopwatchTimer {
1857 /**
1858 * The time (in ms) that the timer was last acquired or the time base
1859 * last (re-)started. Increasing the nesting depth does not reset this time.
1860 *
1861 * -1 if the timer is currently not running or the time base is not running.
1862 *
1863 * If written to a parcel, the start time is reset, as is mNesting in the base class
1864 * StopwatchTimer.
1865 */
1866 long mStartTimeMs = -1;
1867
1868 /**
1869 * The longest time period (in ms) that the timer has been active. Not pooled.
1870 */
1871 long mMaxDurationMs;
1872
1873 /**
1874 * The time (in ms) that that the timer has been active since most recent
1875 * stopRunningLocked() or reset(). Not pooled.
1876 */
1877 long mCurrentDurationMs;
1878
1879 /**
1880 * The total time (in ms) that that the timer has been active since most recent reset()
1881 * prior to the current startRunningLocked. This is the sum of all past currentDurations
1882 * (but not including the present currentDuration) since reset. Not pooled.
1883 */
1884 long mTotalDurationMs;
1885
1886 public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
1887 TimeBase timeBase, Parcel in) {
1888 super(clocks, uid, type, timerPool, timeBase, in);
1889 mMaxDurationMs = in.readLong();
1890 mTotalDurationMs = in.readLong();
1891 mCurrentDurationMs = in.readLong();
1892 }
1893
1894 public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
1895 TimeBase timeBase) {
1896 super(clocks, uid, type, timerPool, timeBase);
1897 }
1898
1899 @Override
1900 public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1901 super.writeToParcel(out, elapsedRealtimeUs);
1902 out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
1903 out.writeLong(mTotalDurationMs);
1904 out.writeLong(getCurrentDurationMsLocked(elapsedRealtimeUs / 1000));
1905 }
1906
1907 /**
1908 * Write the summary to the parcel.
1909 *
1910 * Since the time base is probably meaningless after we come back, reading
1911 * from this will have the effect of stopping the timer. So here all we write
1912 * is the max and total durations.
1913 */
1914 @Override
1915 public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
1916 super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
1917 out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
1918 out.writeLong(getTotalDurationMsLocked(elapsedRealtimeUs / 1000));
1919 }
1920
1921 /**
1922 * Read the summary parcel.
1923 *
1924 * Has the side effect of stopping the timer.
1925 */
1926 @Override
1927 public void readSummaryFromParcelLocked(Parcel in) {
1928 super.readSummaryFromParcelLocked(in);
1929 mMaxDurationMs = in.readLong();
1930 mTotalDurationMs = in.readLong();
1931 mStartTimeMs = -1;
1932 mCurrentDurationMs = 0;
1933 }
1934
1935 /**
1936 * The TimeBase time started (again).
1937 *
1938 * If the timer is also running, store the start time.
1939 */
1940 public void onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime) {
1941 super.onTimeStarted(elapsedRealtimeUs, baseUptime, baseRealtime);
1942 if (mNesting > 0) {
1943 mStartTimeMs = baseRealtime / 1000;
1944 }
1945 }
1946
1947 /**
1948 * The TimeBase stopped running.
1949 *
1950 * If the timer is running, add the duration into mCurrentDurationMs.
1951 */
1952 @Override
1953 public void onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtimeUs) {
1954 super.onTimeStopped(elapsedRealtimeUs, baseUptime, baseRealtimeUs);
1955 if (mNesting > 0) {
1956 // baseRealtimeUs has already been converted to the timebase's realtime.
1957 mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
1958 }
1959 mStartTimeMs = -1;
1960 }
1961
1962 @Override
1963 public void logState(Printer pw, String prefix) {
1964 super.logState(pw, prefix);
1965 }
1966
1967 @Override
1968 public void startRunningLocked(long elapsedRealtimeMs) {
1969 super.startRunningLocked(elapsedRealtimeMs);
1970 if (mNesting == 1 && mTimeBase.isRunning()) {
1971 // Just started
1972 mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000;
1973 }
1974 }
1975
1976 /**
1977 * Decrements the mNesting ref-count on this timer.
1978 *
1979 * If it actually stopped (mNesting went to 0), then possibly update
1980 * mMaxDuration if the current duration was the longest ever.
1981 */
1982 @Override
1983 public void stopRunningLocked(long elapsedRealtimeMs) {
1984 if (mNesting == 1) {
1985 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
1986 mTotalDurationMs += durationMs;
1987 if (durationMs > mMaxDurationMs) {
1988 mMaxDurationMs = durationMs;
1989 }
1990 mStartTimeMs = -1;
1991 mCurrentDurationMs = 0;
1992 }
1993 // super method decrements mNesting, which getCurrentDurationMsLocked relies on,
1994 // so call super.stopRunningLocked after calling getCurrentDurationMsLocked.
1995 super.stopRunningLocked(elapsedRealtimeMs);
1996 }
1997
1998 @Override
1999 public boolean reset(boolean detachIfReset) {
2000 boolean result = super.reset(detachIfReset);
2001 mMaxDurationMs = 0;
2002 mTotalDurationMs = 0;
2003 mCurrentDurationMs = 0;
2004 if (mNesting > 0) {
2005 mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000;
2006 } else {
2007 mStartTimeMs = -1;
2008 }
2009 return result;
2010 }
2011
2012 /**
2013 * Returns the max duration that this timer has ever seen.
2014 *
2015 * Note that this time is NOT split between the timers in the timer group that
2016 * this timer is attached to. It is the TOTAL time.
2017 */
2018 @Override
2019 public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
2020 if (mNesting > 0) {
2021 final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
2022 if (durationMs > mMaxDurationMs) {
2023 return durationMs;
2024 }
2025 }
2026 return mMaxDurationMs;
2027 }
2028
2029 /**
2030 * Returns the time since the timer was started.
2031 * Returns 0 if the timer is not currently running.
2032 *
2033 * Note that this time is NOT split between the timers in the timer group that
2034 * this timer is attached to. It is the TOTAL time.
2035 *
2036 * Note that if running timer is parceled and unparceled, this method will return
2037 * current duration value at the time of parceling even though timer may not be
2038 * currently running.
2039 */
2040 @Override
2041 public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
2042 long durationMs = mCurrentDurationMs;
2043 if (mNesting > 0 && mTimeBase.isRunning()) {
2044 durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs*1000)/1000)
2045 - mStartTimeMs;
2046 }
2047 return durationMs;
2048 }
2049
2050 /**
2051 * Returns the total cumulative duration that this timer has been on since reset().
2052 * If mTimerPool == null, this should be the same
2053 * as getTotalTimeLocked(elapsedRealtimeMs*1000, STATS_SINCE_CHARGED)/1000.
2054 *
2055 * Note that this time is NOT split between the timers in the timer group that
2056 * this timer is attached to. It is the TOTAL time. For this reason, if mTimerPool != null,
2057 * the result will not be equivalent to getTotalTimeLocked.
2058 */
2059 @Override
2060 public long getTotalDurationMsLocked(long elapsedRealtimeMs) {
2061 return mTotalDurationMs + getCurrentDurationMsLocked(elapsedRealtimeMs);
2062 }
2063 }
2064
2065 /**
2066 * State for keeping track of timing information.
2067 */
2068 public static class StopwatchTimer extends Timer {
2069 final Uid mUid;
2070 final ArrayList<StopwatchTimer> mTimerPool;
2071
2072 int mNesting;
2073
2074 /**
2075 * The last time at which we updated the timer. If mNesting is > 0,
2076 * subtract this from the current battery time to find the amount of
2077 * time we have been running since we last computed an update.
2078 */
2079 long mUpdateTime;
2080
2081 /**
2082 * The total time at which the timer was acquired, to determine if it
2083 * was actually held for an interesting duration. If time base was not running when timer
2084 * was acquired, will be -1.
2085 */
2086 long mAcquireTime = -1;
2087
2088 long mTimeout;
2089
2090 /**
2091 * For partial wake locks, keep track of whether we are in the list
2092 * to consume CPU cycles.
2093 */
2094 @VisibleForTesting
2095 public boolean mInList;
2096
2097 public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2098 TimeBase timeBase, Parcel in) {
2099 super(clocks, type, timeBase, in);
2100 mUid = uid;
2101 mTimerPool = timerPool;
2102 mUpdateTime = in.readLong();
2103 }
2104
2105 public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2106 TimeBase timeBase) {
2107 super(clocks, type, timeBase);
2108 mUid = uid;
2109 mTimerPool = timerPool;
2110 }
2111
2112 public void setTimeout(long timeout) {
2113 mTimeout = timeout;
2114 }
2115
2116 public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2117 super.writeToParcel(out, elapsedRealtimeUs);
2118 out.writeLong(mUpdateTime);
2119 }
2120
2121 public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
2122 if (mNesting > 0) {
2123 if (DEBUG && mType < 0) {
2124 Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
2125 }
2126 super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
2127 mUpdateTime = baseRealtime;
2128 if (DEBUG && mType < 0) {
2129 Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
2130 }
2131 }
2132 }
2133
2134 public void logState(Printer pw, String prefix) {
2135 super.logState(pw, prefix);
2136 pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTime
2137 + " mAcquireTime=" + mAcquireTime);
2138 }
2139
2140 public void startRunningLocked(long elapsedRealtimeMs) {
2141 if (mNesting++ == 0) {
2142 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2143 mUpdateTime = batteryRealtime;
2144 if (mTimerPool != null) {
2145 // Accumulate time to all currently active timers before adding
2146 // this new one to the pool.
2147 refreshTimersLocked(batteryRealtime, mTimerPool, null);
2148 // Add this timer to the active pool
2149 mTimerPool.add(this);
2150 }
2151 if (mTimeBase.isRunning()) {
2152 // Increment the count
2153 mCount++;
2154 mAcquireTime = mTotalTime;
2155 } else {
2156 mAcquireTime = -1;
2157 }
2158 if (DEBUG && mType < 0) {
2159 Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
2160 + " mTotalTime=" + mTotalTime + " mCount=" + mCount
2161 + " mAcquireTime=" + mAcquireTime);
2162 }
2163 }
2164 }
2165
2166 public boolean isRunningLocked() {
2167 return mNesting > 0;
2168 }
2169
2170 public void stopRunningLocked(long elapsedRealtimeMs) {
2171 // Ignore attempt to stop a timer that isn't running
2172 if (mNesting == 0) {
2173 return;
2174 }
2175 if (--mNesting == 0) {
2176 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2177 if (mTimerPool != null) {
2178 // Accumulate time to all active counters, scaled by the total
2179 // active in the pool, before taking this one out of the pool.
2180 refreshTimersLocked(batteryRealtime, mTimerPool, null);
2181 // Remove this timer from the active pool
2182 mTimerPool.remove(this);
2183 } else {
2184 mNesting = 1;
2185 mTotalTime = computeRunTimeLocked(batteryRealtime);
2186 mNesting = 0;
2187 }
2188
2189 if (DEBUG && mType < 0) {
2190 Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
2191 + " mTotalTime=" + mTotalTime + " mCount=" + mCount
2192 + " mAcquireTime=" + mAcquireTime);
2193 }
2194
2195 if (mAcquireTime >= 0 && mTotalTime == mAcquireTime) {
2196 // If there was no change in the time, then discard this
2197 // count. A somewhat cheezy strategy, but hey.
2198 mCount--;
2199 }
2200 }
2201 }
2202
2203 public void stopAllRunningLocked(long elapsedRealtimeMs) {
2204 if (mNesting > 0) {
2205 mNesting = 1;
2206 stopRunningLocked(elapsedRealtimeMs);
2207 }
2208 }
2209
2210 // Update the total time for all other running Timers with the same type as this Timer
2211 // due to a change in timer count
2212 private static long refreshTimersLocked(long batteryRealtime,
2213 final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
2214 long selfTime = 0;
2215 final int N = pool.size();
2216 for (int i=N-1; i>= 0; i--) {
2217 final StopwatchTimer t = pool.get(i);
2218 long heldTime = batteryRealtime - t.mUpdateTime;
2219 if (heldTime > 0) {
2220 final long myTime = heldTime / N;
2221 if (t == self) {
2222 selfTime = myTime;
2223 }
2224 t.mTotalTime += myTime;
2225 }
2226 t.mUpdateTime = batteryRealtime;
2227 }
2228 return selfTime;
2229 }
2230
2231 @Override
2232 protected long computeRunTimeLocked(long curBatteryRealtime) {
2233 if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) {
2234 curBatteryRealtime = mUpdateTime + mTimeout;
2235 }
2236 return mTotalTime + (mNesting > 0
2237 ? (curBatteryRealtime - mUpdateTime)
2238 / (mTimerPool != null ? mTimerPool.size() : 1)
2239 : 0);
2240 }
2241
2242 @Override
2243 protected int computeCurrentCountLocked() {
2244 return mCount;
2245 }
2246
2247 @Override
2248 public boolean reset(boolean detachIfReset) {
2249 boolean canDetach = mNesting <= 0;
2250 super.reset(canDetach && detachIfReset);
2251 if (mNesting > 0) {
2252 mUpdateTime = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000);
2253 }
2254 mAcquireTime = -1; // to ensure mCount isn't decreased to -1 if timer is stopped later.
2255 return canDetach;
2256 }
2257
2258 @Override
2259 public void detach() {
2260 super.detach();
2261 if (mTimerPool != null) {
2262 mTimerPool.remove(this);
2263 }
2264 }
2265
2266 @Override
2267 public void readSummaryFromParcelLocked(Parcel in) {
2268 super.readSummaryFromParcelLocked(in);
2269 mNesting = 0;
2270 }
2271
2272 /**
2273 * Set the mark so that we can query later for the total time the timer has
2274 * accumulated since this point. The timer can be running or not.
2275 *
2276 * @param elapsedRealtimeMs the current elapsed realtime in milliseconds.
2277 */
2278 public void setMark(long elapsedRealtimeMs) {
2279 final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
2280 if (mNesting > 0) {
2281 // We are running.
2282 if (mTimerPool != null) {
2283 refreshTimersLocked(batteryRealtime, mTimerPool, this);
2284 } else {
2285 mTotalTime += batteryRealtime - mUpdateTime;
2286 mUpdateTime = batteryRealtime;
2287 }
2288 }
2289 mTimeBeforeMark = mTotalTime;
2290 }
2291 }
2292
2293 /**
2294 * State for keeping track of two DurationTimers with different TimeBases, presumably where one
2295 * TimeBase is effectively a subset of the other.
2296 */
2297 public static class DualTimer extends DurationTimer {
2298 // This class both is a DurationTimer and also holds a second DurationTimer.
2299 // The main timer (this) typically tracks the total time. It may be pooled (but since it's a
2300 // durationTimer, it also has the unpooled getTotalDurationMsLocked() for
2301 // STATS_SINCE_CHARGED).
2302 // mSubTimer typically tracks only part of the total time, such as background time, as
2303 // determined by a subTimeBase. It is NOT pooled.
2304 private final DurationTimer mSubTimer;
2305
2306 /**
2307 * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2308 * The main timer (this) is based on the given timeBase and timerPool.
2309 * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2310 * the main timer is.
2311 */
2312 public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2313 TimeBase timeBase, TimeBase subTimeBase, Parcel in) {
2314 super(clocks, uid, type, timerPool, timeBase, in);
2315 mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase, in);
2316 }
2317
2318 /**
2319 * Creates a DualTimer to hold a main timer (this) and a mSubTimer.
2320 * The main timer (this) is based on the given timeBase and timerPool.
2321 * The mSubTimer is based on the given subTimeBase. The mSubTimer is not pooled, even if
2322 * the main timer is.
2323 */
2324 public DualTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
2325 TimeBase timeBase, TimeBase subTimeBase) {
2326 super(clocks, uid, type, timerPool, timeBase);
2327 mSubTimer = new DurationTimer(clocks, uid, type, null, subTimeBase);
2328 }
2329
2330 /** Get the secondary timer. */
2331 @Override
2332 public DurationTimer getSubTimer() {
2333 return mSubTimer;
2334 }
2335
2336 @Override
2337 public void startRunningLocked(long elapsedRealtimeMs) {
2338 super.startRunningLocked(elapsedRealtimeMs);
2339 mSubTimer.startRunningLocked(elapsedRealtimeMs);
2340 }
2341
2342 @Override
2343 public void stopRunningLocked(long elapsedRealtimeMs) {
2344 super.stopRunningLocked(elapsedRealtimeMs);
2345 mSubTimer.stopRunningLocked(elapsedRealtimeMs);
2346 }
2347
2348 @Override
2349 public void stopAllRunningLocked(long elapsedRealtimeMs) {
2350 super.stopAllRunningLocked(elapsedRealtimeMs);
2351 mSubTimer.stopAllRunningLocked(elapsedRealtimeMs);
2352 }
2353
2354 @Override
2355 public boolean reset(boolean detachIfReset) {
2356 boolean active = false;
2357 // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
2358 active |= !mSubTimer.reset(false);
2359 active |= !super.reset(detachIfReset);
2360 return !active;
2361 }
2362
2363 @Override
2364 public void detach() {
2365 mSubTimer.detach();
2366 super.detach();
2367 }
2368
2369 @Override
2370 public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
2371 super.writeToParcel(out, elapsedRealtimeUs);
2372 mSubTimer.writeToParcel(out, elapsedRealtimeUs);
2373 }
2374
2375 @Override
2376 public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
2377 super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2378 mSubTimer.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
2379 }
2380
2381 @Override
2382 public void readSummaryFromParcelLocked(Parcel in) {
2383 super.readSummaryFromParcelLocked(in);
2384 mSubTimer.readSummaryFromParcelLocked(in);
2385 }
2386 }
2387
2388
2389 public abstract class OverflowArrayMap<T> {
2390 private static final String OVERFLOW_NAME = "*overflow*";
2391
2392 final int mUid;
2393 final ArrayMap<String, T> mMap = new ArrayMap<>();
2394 T mCurOverflow;
2395 ArrayMap<String, MutableInt> mActiveOverflow;
2396 long mLastOverflowTime;
2397 long mLastOverflowFinishTime;
2398 long mLastClearTime;
2399 long mLastCleanupTime;
2400
2401 public OverflowArrayMap(int uid) {
2402 mUid = uid;
2403 }
2404
2405 public ArrayMap<String, T> getMap() {
2406 return mMap;
2407 }
2408
2409 public void clear() {
2410 mLastClearTime = SystemClock.elapsedRealtime();
2411 mMap.clear();
2412 mCurOverflow = null;
2413 mActiveOverflow = null;
2414 }
2415
2416 public void add(String name, T obj) {
2417 if (name == null) {
2418 name = "";
2419 }
2420 mMap.put(name, obj);
2421 if (OVERFLOW_NAME.equals(name)) {
2422 mCurOverflow = obj;
2423 }
2424 }
2425
2426 public void cleanup() {
2427 mLastCleanupTime = SystemClock.elapsedRealtime();
2428 if (mActiveOverflow != null) {
2429 if (mActiveOverflow.size() == 0) {
2430 mActiveOverflow = null;
2431 }
2432 }
2433 if (mActiveOverflow == null) {
2434 // There is no currently active overflow, so we should no longer have
2435 // an overflow entry.
2436 if (mMap.containsKey(OVERFLOW_NAME)) {
2437 Slog.wtf(TAG, "Cleaning up with no active overflow, but have overflow entry "
2438 + mMap.get(OVERFLOW_NAME));
2439 mMap.remove(OVERFLOW_NAME);
2440 }
2441 mCurOverflow = null;
2442 } else {
2443 // There is currently active overflow, so we should still have an overflow entry.
2444 if (mCurOverflow == null || !mMap.containsKey(OVERFLOW_NAME)) {
2445 Slog.wtf(TAG, "Cleaning up with active overflow, but no overflow entry: cur="
2446 + mCurOverflow + " map=" + mMap.get(OVERFLOW_NAME));
2447 }
2448 }
2449 }
2450
2451 public T startObject(String name) {
2452 if (name == null) {
2453 name = "";
2454 }
2455 T obj = mMap.get(name);
2456 if (obj != null) {
2457 return obj;
2458 }
2459
2460 // No object exists for the given name, but do we currently have it
2461 // running as part of the overflow?
2462 if (mActiveOverflow != null) {
2463 MutableInt over = mActiveOverflow.get(name);
2464 if (over != null) {
2465 // We are already actively counting this name in the overflow object.
2466 obj = mCurOverflow;
2467 if (obj == null) {
2468 // Shouldn't be here, but we'll try to recover.
2469 Slog.wtf(TAG, "Have active overflow " + name + " but null overflow");
2470 obj = mCurOverflow = instantiateObject();
2471 mMap.put(OVERFLOW_NAME, obj);
2472 }
2473 over.value++;
2474 return obj;
2475 }
2476 }
2477
2478 // No object exists for given name nor in the overflow; we need to make
2479 // a new one.
2480 final int N = mMap.size();
2481 if (N >= MAX_WAKELOCKS_PER_UID) {
2482 // Went over the limit on number of objects to track; this one goes
2483 // in to the overflow.
2484 obj = mCurOverflow;
2485 if (obj == null) {
2486 // Need to start overflow now...
2487 obj = mCurOverflow = instantiateObject();
2488 mMap.put(OVERFLOW_NAME, obj);
2489 }
2490 if (mActiveOverflow == null) {
2491 mActiveOverflow = new ArrayMap<>();
2492 }
2493 mActiveOverflow.put(name, new MutableInt(1));
2494 mLastOverflowTime = SystemClock.elapsedRealtime();
2495 return obj;
2496 }
2497
2498 // Normal case where we just need to make a new object.
2499 obj = instantiateObject();
2500 mMap.put(name, obj);
2501 return obj;
2502 }
2503
2504 public T stopObject(String name) {
2505 if (name == null) {
2506 name = "";
2507 }
2508 T obj = mMap.get(name);
2509 if (obj != null) {
2510 return obj;
2511 }
2512
2513 // No object exists for the given name, but do we currently have it
2514 // running as part of the overflow?
2515 if (mActiveOverflow != null) {
2516 MutableInt over = mActiveOverflow.get(name);
2517 if (over != null) {
2518 // We are already actively counting this name in the overflow object.
2519 obj = mCurOverflow;
2520 if (obj != null) {
2521 over.value--;
2522 if (over.value <= 0) {
2523 mActiveOverflow.remove(name);
2524 mLastOverflowFinishTime = SystemClock.elapsedRealtime();
2525 }
2526 return obj;
2527 }
2528 }
2529 }
2530
2531 // Huh, they are stopping an active operation but we can't find one!
2532 // That's not good.
2533 StringBuilder sb = new StringBuilder();
2534 sb.append("Unable to find object for ");
2535 sb.append(name);
2536 sb.append(" in uid ");
2537 sb.append(mUid);
2538 sb.append(" mapsize=");
2539 sb.append(mMap.size());
2540 sb.append(" activeoverflow=");
2541 sb.append(mActiveOverflow);
2542 sb.append(" curoverflow=");
2543 sb.append(mCurOverflow);
2544 long now = SystemClock.elapsedRealtime();
2545 if (mLastOverflowTime != 0) {
2546 sb.append(" lastOverflowTime=");
2547 TimeUtils.formatDuration(mLastOverflowTime-now, sb);
2548 }
2549 if (mLastOverflowFinishTime != 0) {
2550 sb.append(" lastOverflowFinishTime=");
2551 TimeUtils.formatDuration(mLastOverflowFinishTime-now, sb);
2552 }
2553 if (mLastClearTime != 0) {
2554 sb.append(" lastClearTime=");
2555 TimeUtils.formatDuration(mLastClearTime-now, sb);
2556 }
2557 if (mLastCleanupTime != 0) {
2558 sb.append(" lastCleanupTime=");
2559 TimeUtils.formatDuration(mLastCleanupTime-now, sb);
2560 }
2561 Slog.wtf(TAG, sb.toString());
2562 return null;
2563 }
2564
2565 public abstract T instantiateObject();
2566 }
2567
2568 public static class ControllerActivityCounterImpl extends ControllerActivityCounter
2569 implements Parcelable {
2570 private final LongSamplingCounter mIdleTimeMillis;
2571 private final LongSamplingCounter mRxTimeMillis;
2572 private final LongSamplingCounter[] mTxTimeMillis;
2573 private final LongSamplingCounter mPowerDrainMaMs;
2574
2575 public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates) {
2576 mIdleTimeMillis = new LongSamplingCounter(timeBase);
2577 mRxTimeMillis = new LongSamplingCounter(timeBase);
2578 mTxTimeMillis = new LongSamplingCounter[numTxStates];
2579 for (int i = 0; i < numTxStates; i++) {
2580 mTxTimeMillis[i] = new LongSamplingCounter(timeBase);
2581 }
2582 mPowerDrainMaMs = new LongSamplingCounter(timeBase);
2583 }
2584
2585 public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in) {
2586 mIdleTimeMillis = new LongSamplingCounter(timeBase, in);
2587 mRxTimeMillis = new LongSamplingCounter(timeBase, in);
2588 final int recordedTxStates = in.readInt();
2589 if (recordedTxStates != numTxStates) {
2590 throw new ParcelFormatException("inconsistent tx state lengths");
2591 }
2592
2593 mTxTimeMillis = new LongSamplingCounter[numTxStates];
2594 for (int i = 0; i < numTxStates; i++) {
2595 mTxTimeMillis[i] = new LongSamplingCounter(timeBase, in);
2596 }
2597 mPowerDrainMaMs = new LongSamplingCounter(timeBase, in);
2598 }
2599
2600 public void readSummaryFromParcel(Parcel in) {
2601 mIdleTimeMillis.readSummaryFromParcelLocked(in);
2602 mRxTimeMillis.readSummaryFromParcelLocked(in);
2603 final int recordedTxStates = in.readInt();
2604 if (recordedTxStates != mTxTimeMillis.length) {
2605 throw new ParcelFormatException("inconsistent tx state lengths");
2606 }
2607 for (LongSamplingCounter counter : mTxTimeMillis) {
2608 counter.readSummaryFromParcelLocked(in);
2609 }
2610 mPowerDrainMaMs.readSummaryFromParcelLocked(in);
2611 }
2612
2613 @Override
2614 public int describeContents() {
2615 return 0;
2616 }
2617
2618 public void writeSummaryToParcel(Parcel dest) {
2619 mIdleTimeMillis.writeSummaryFromParcelLocked(dest);
2620 mRxTimeMillis.writeSummaryFromParcelLocked(dest);
2621 dest.writeInt(mTxTimeMillis.length);
2622 for (LongSamplingCounter counter : mTxTimeMillis) {
2623 counter.writeSummaryFromParcelLocked(dest);
2624 }
2625 mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
2626 }
2627
2628 @Override
2629 public void writeToParcel(Parcel dest, int flags) {
2630 mIdleTimeMillis.writeToParcel(dest);
2631 mRxTimeMillis.writeToParcel(dest);
2632 dest.writeInt(mTxTimeMillis.length);
2633 for (LongSamplingCounter counter : mTxTimeMillis) {
2634 counter.writeToParcel(dest);
2635 }
2636 mPowerDrainMaMs.writeToParcel(dest);
2637 }
2638
2639 public void reset(boolean detachIfReset) {
2640 mIdleTimeMillis.reset(detachIfReset);
2641 mRxTimeMillis.reset(detachIfReset);
2642 for (LongSamplingCounter counter : mTxTimeMillis) {
2643 counter.reset(detachIfReset);
2644 }
2645 mPowerDrainMaMs.reset(detachIfReset);
2646 }
2647
2648 public void detach() {
2649 mIdleTimeMillis.detach();
2650 mRxTimeMillis.detach();
2651 for (LongSamplingCounter counter : mTxTimeMillis) {
2652 counter.detach();
2653 }
2654 mPowerDrainMaMs.detach();
2655 }
2656
2657 /**
2658 * @return a LongSamplingCounter, measuring time spent in the idle state in
2659 * milliseconds.
2660 */
2661 @Override
2662 public LongSamplingCounter getIdleTimeCounter() {
2663 return mIdleTimeMillis;
2664 }
2665
2666 /**
2667 * @return a LongSamplingCounter, measuring time spent in the receive state in
2668 * milliseconds.
2669 */
2670 @Override
2671 public LongSamplingCounter getRxTimeCounter() {
2672 return mRxTimeMillis;
2673 }
2674
2675 /**
2676 * @return a LongSamplingCounter[], measuring time spent in various transmit states in
2677 * milliseconds.
2678 */
2679 @Override
2680 public LongSamplingCounter[] getTxTimeCounters() {
2681 return mTxTimeMillis;
2682 }
2683
2684 /**
2685 * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
2686 */
2687 @Override
2688 public LongSamplingCounter getPowerCounter() {
2689 return mPowerDrainMaMs;
2690 }
2691 }
2692
Justin Klaassenbc81c7a2017-09-18 17:38:50 -04002693 /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */
2694 public SamplingTimer getRpmTimerLocked(String name) {
2695 SamplingTimer rpmt = mRpmStats.get(name);
2696 if (rpmt == null) {
2697 rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
2698 mRpmStats.put(name, rpmt);
2699 }
2700 return rpmt;
2701 }
2702
2703 /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */
2704 public SamplingTimer getScreenOffRpmTimerLocked(String name) {
2705 SamplingTimer rpmt = mScreenOffRpmStats.get(name);
2706 if (rpmt == null) {
2707 rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
2708 mScreenOffRpmStats.put(name, rpmt);
2709 }
2710 return rpmt;
2711 }
2712
Justin Klaassen10d07c82017-09-15 17:58:39 -04002713 /*
2714 * Get the wakeup reason counter, and create a new one if one
2715 * doesn't already exist.
2716 */
2717 public SamplingTimer getWakeupReasonTimerLocked(String name) {
2718 SamplingTimer timer = mWakeupReasonStats.get(name);
2719 if (timer == null) {
2720 timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
2721 mWakeupReasonStats.put(name, timer);
2722 }
2723 return timer;
2724 }
2725
2726 /*
2727 * Get the KernelWakelockTimer associated with name, and create a new one if one
2728 * doesn't already exist.
2729 */
2730 public SamplingTimer getKernelWakelockTimerLocked(String name) {
2731 SamplingTimer kwlt = mKernelWakelockStats.get(name);
2732 if (kwlt == null) {
2733 kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
2734 mKernelWakelockStats.put(name, kwlt);
2735 }
2736 return kwlt;
2737 }
2738
2739 public SamplingTimer getKernelMemoryTimerLocked(long bucket) {
2740 SamplingTimer kmt = mKernelMemoryStats.get(bucket);
2741 if (kmt == null) {
2742 kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
2743 mKernelMemoryStats.put(bucket, kmt);
2744 }
2745 return kmt;
2746 }
2747
2748 private int writeHistoryTag(HistoryTag tag) {
2749 Integer idxObj = mHistoryTagPool.get(tag);
2750 int idx;
2751 if (idxObj != null) {
2752 idx = idxObj;
2753 } else {
2754 idx = mNextHistoryTagIdx;
2755 HistoryTag key = new HistoryTag();
2756 key.setTo(tag);
2757 tag.poolIdx = idx;
2758 mHistoryTagPool.put(key, idx);
2759 mNextHistoryTagIdx++;
2760 mNumHistoryTagChars += key.string.length() + 1;
2761 }
2762 return idx;
2763 }
2764
2765 private void readHistoryTag(int index, HistoryTag tag) {
2766 tag.string = mReadHistoryStrings[index];
2767 tag.uid = mReadHistoryUids[index];
2768 tag.poolIdx = index;
2769 }
2770
2771 /*
2772 The history delta format uses flags to denote further data in subsequent ints in the parcel.
2773
2774 There is always the first token, which may contain the delta time, or an indicator of
2775 the length of the time (int or long) following this token.
2776
2777 First token: always present,
2778 31 23 15 7 0
2779 â–ˆ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â–ˆ
2780
2781 T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
2782 follows containing the time, and 0x7ffff indicates a long immediately follows with the
2783 delta time.
2784 A: battery level changed and an int follows with battery data.
2785 B: state changed and an int follows with state change data.
2786 C: state2 has changed and an int follows with state2 change data.
2787 D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
2788 E: event data has changed and an event struct follows.
2789 F: battery charge in coulombs has changed and an int with the charge follows.
2790 G: state flag denoting that the mobile radio was active.
2791 H: state flag denoting that the wifi radio was active.
2792 I: state flag denoting that a wifi scan occurred.
2793 J: state flag denoting that a wifi full lock was held.
2794 K: state flag denoting that the gps was on.
2795 L: state flag denoting that a wakelock was held.
2796 M: state flag denoting that the cpu was running.
2797
2798 Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
2799 with the time delta.
2800
2801 Battery level int: if A in the first token is set,
2802 31 23 15 7 0
2803 â–ˆ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â–ˆ
2804
2805 D: indicates that extra history details follow.
2806 V: the battery voltage.
2807 T: the battery temperature.
2808 L: the battery level (out of 100).
2809
2810 State change int: if B in the first token is set,
2811 31 23 15 7 0
2812 â–ˆS|S|S|H|H|H|P|Pâ–ˆF|E|D|C|B| | |Aâ–ˆ | | | | | | | â–ˆ | | | | | | | â–ˆ
2813
2814 A: wifi multicast was on.
2815 B: battery was plugged in.
2816 C: screen was on.
2817 D: phone was scanning for signal.
2818 E: audio was on.
2819 F: a sensor was active.
2820
2821 State2 change int: if C in the first token is set,
2822 31 23 15 7 0
2823 â–ˆM|L|K|J|I|H|H|Gâ–ˆF|E|D|C| | | | â–ˆ | | | | | | | â–ˆ |B|B|B|A|A|A|Aâ–ˆ
2824
2825 A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
2826 B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
2827 C: a bluetooth scan was active.
2828 D: the camera was active.
2829 E: bluetooth was on.
2830 F: a phone call was active.
2831 G: the device was charging.
2832 H: 2 bits indicating the device-idle (doze) state: off, light, full
2833 I: the flashlight was on.
2834 J: wifi was on.
2835 K: wifi was running.
2836 L: video was playing.
2837 M: power save mode was on.
2838
2839 Wakelock/wakereason struct: if D in the first token is set,
2840 TODO(adamlesinski): describe wakelock/wakereason struct.
2841
2842 Event struct: if E in the first token is set,
2843 TODO(adamlesinski): describe the event struct.
2844
2845 History step details struct: if D in the battery level int is set,
2846 TODO(adamlesinski): describe the history step details struct.
2847
2848 Battery charge int: if F in the first token is set, an int representing the battery charge
2849 in coulombs follows.
2850 */
2851
2852 // Part of initial delta int that specifies the time delta.
2853 static final int DELTA_TIME_MASK = 0x7ffff;
2854 static final int DELTA_TIME_LONG = 0x7ffff; // The delta is a following long
2855 static final int DELTA_TIME_INT = 0x7fffe; // The delta is a following int
2856 static final int DELTA_TIME_ABS = 0x7fffd; // Following is an entire abs update.
2857 // Flag in delta int: a new battery level int follows.
2858 static final int DELTA_BATTERY_LEVEL_FLAG = 0x00080000;
2859 // Flag in delta int: a new full state and battery status int follows.
2860 static final int DELTA_STATE_FLAG = 0x00100000;
2861 // Flag in delta int: a new full state2 int follows.
2862 static final int DELTA_STATE2_FLAG = 0x00200000;
2863 // Flag in delta int: contains a wakelock or wakeReason tag.
2864 static final int DELTA_WAKELOCK_FLAG = 0x00400000;
2865 // Flag in delta int: contains an event description.
2866 static final int DELTA_EVENT_FLAG = 0x00800000;
2867 // Flag in delta int: contains the battery charge count in uAh.
2868 static final int DELTA_BATTERY_CHARGE_FLAG = 0x01000000;
2869 // These upper bits are the frequently changing state bits.
2870 static final int DELTA_STATE_MASK = 0xfe000000;
2871
2872 // These are the pieces of battery state that are packed in to the upper bits of
2873 // the state int that have been packed in to the first delta int. They must fit
2874 // in STATE_BATTERY_MASK.
2875 static final int STATE_BATTERY_MASK = 0xff000000;
2876 static final int STATE_BATTERY_STATUS_MASK = 0x00000007;
2877 static final int STATE_BATTERY_STATUS_SHIFT = 29;
2878 static final int STATE_BATTERY_HEALTH_MASK = 0x00000007;
2879 static final int STATE_BATTERY_HEALTH_SHIFT = 26;
2880 static final int STATE_BATTERY_PLUG_MASK = 0x00000003;
2881 static final int STATE_BATTERY_PLUG_SHIFT = 24;
2882
2883 // We use the low bit of the battery state int to indicate that we have full details
2884 // from a battery level change.
2885 static final int BATTERY_DELTA_LEVEL_FLAG = 0x00000001;
2886
2887 public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
2888 if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
2889 dest.writeInt(DELTA_TIME_ABS);
2890 cur.writeToParcel(dest, 0);
2891 return;
2892 }
2893
2894 final long deltaTime = cur.time - last.time;
2895 final int lastBatteryLevelInt = buildBatteryLevelInt(last);
2896 final int lastStateInt = buildStateInt(last);
2897
2898 int deltaTimeToken;
2899 if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
2900 deltaTimeToken = DELTA_TIME_LONG;
2901 } else if (deltaTime >= DELTA_TIME_ABS) {
2902 deltaTimeToken = DELTA_TIME_INT;
2903 } else {
2904 deltaTimeToken = (int)deltaTime;
2905 }
2906 int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
2907 final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
2908 ? BATTERY_DELTA_LEVEL_FLAG : 0;
2909 final boolean computeStepDetails = includeStepDetails != 0
2910 || mLastHistoryStepDetails == null;
2911 final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
2912 final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
2913 if (batteryLevelIntChanged) {
2914 firstToken |= DELTA_BATTERY_LEVEL_FLAG;
2915 }
2916 final int stateInt = buildStateInt(cur);
2917 final boolean stateIntChanged = stateInt != lastStateInt;
2918 if (stateIntChanged) {
2919 firstToken |= DELTA_STATE_FLAG;
2920 }
2921 final boolean state2IntChanged = cur.states2 != last.states2;
2922 if (state2IntChanged) {
2923 firstToken |= DELTA_STATE2_FLAG;
2924 }
2925 if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
2926 firstToken |= DELTA_WAKELOCK_FLAG;
2927 }
2928 if (cur.eventCode != HistoryItem.EVENT_NONE) {
2929 firstToken |= DELTA_EVENT_FLAG;
2930 }
2931
2932 final boolean batteryChargeChanged = cur.batteryChargeUAh != last.batteryChargeUAh;
2933 if (batteryChargeChanged) {
2934 firstToken |= DELTA_BATTERY_CHARGE_FLAG;
2935 }
2936 dest.writeInt(firstToken);
2937 if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
2938 + " deltaTime=" + deltaTime);
2939
2940 if (deltaTimeToken >= DELTA_TIME_INT) {
2941 if (deltaTimeToken == DELTA_TIME_INT) {
2942 if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
2943 dest.writeInt((int)deltaTime);
2944 } else {
2945 if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
2946 dest.writeLong(deltaTime);
2947 }
2948 }
2949 if (batteryLevelIntChanged) {
2950 dest.writeInt(batteryLevelInt);
2951 if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
2952 + Integer.toHexString(batteryLevelInt)
2953 + " batteryLevel=" + cur.batteryLevel
2954 + " batteryTemp=" + cur.batteryTemperature
2955 + " batteryVolt=" + (int)cur.batteryVoltage);
2956 }
2957 if (stateIntChanged) {
2958 dest.writeInt(stateInt);
2959 if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
2960 + Integer.toHexString(stateInt)
2961 + " batteryStatus=" + cur.batteryStatus
2962 + " batteryHealth=" + cur.batteryHealth
2963 + " batteryPlugType=" + cur.batteryPlugType
2964 + " states=0x" + Integer.toHexString(cur.states));
2965 }
2966 if (state2IntChanged) {
2967 dest.writeInt(cur.states2);
2968 if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x"
2969 + Integer.toHexString(cur.states2));
2970 }
2971 if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
2972 int wakeLockIndex;
2973 int wakeReasonIndex;
2974 if (cur.wakelockTag != null) {
2975 wakeLockIndex = writeHistoryTag(cur.wakelockTag);
2976 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
2977 + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
2978 } else {
2979 wakeLockIndex = 0xffff;
2980 }
2981 if (cur.wakeReasonTag != null) {
2982 wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
2983 if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
2984 + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
2985 } else {
2986 wakeReasonIndex = 0xffff;
2987 }
2988 dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
2989 }
2990 if (cur.eventCode != HistoryItem.EVENT_NONE) {
2991 int index = writeHistoryTag(cur.eventTag);
2992 int codeAndIndex = (cur.eventCode&0xffff) | (index<<16);
2993 dest.writeInt(codeAndIndex);
2994 if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
2995 + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
2996 + cur.eventTag.string);
2997 }
2998 if (computeStepDetails) {
2999 if (mPlatformIdleStateCallback != null) {
3000 mCurHistoryStepDetails.statPlatformIdleState =
3001 mPlatformIdleStateCallback.getPlatformLowPowerStats();
3002 if (DEBUG) Slog.i(TAG, "WRITE PlatformIdleState:" +
3003 mCurHistoryStepDetails.statPlatformIdleState);
3004
3005 mCurHistoryStepDetails.statSubsystemPowerState =
3006 mPlatformIdleStateCallback.getSubsystemLowPowerStats();
3007 if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
3008 mCurHistoryStepDetails.statSubsystemPowerState);
3009
3010 }
3011 computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
3012 if (includeStepDetails != 0) {
3013 mCurHistoryStepDetails.writeToParcel(dest);
3014 }
3015 cur.stepDetails = mCurHistoryStepDetails;
3016 mLastHistoryStepDetails = mCurHistoryStepDetails;
3017 } else {
3018 cur.stepDetails = null;
3019 }
3020 if (mLastHistoryStepLevel < cur.batteryLevel) {
3021 mLastHistoryStepDetails = null;
3022 }
3023 mLastHistoryStepLevel = cur.batteryLevel;
3024
3025 if (batteryChargeChanged) {
3026 if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUAh=" + cur.batteryChargeUAh);
3027 dest.writeInt(cur.batteryChargeUAh);
3028 }
3029 }
3030
3031 private int buildBatteryLevelInt(HistoryItem h) {
3032 return ((((int)h.batteryLevel)<<25)&0xfe000000)
3033 | ((((int)h.batteryTemperature)<<15)&0x01ff8000)
3034 | ((((int)h.batteryVoltage)<<1)&0x00007ffe);
3035 }
3036
3037 private void readBatteryLevelInt(int batteryLevelInt, HistoryItem out) {
3038 out.batteryLevel = (byte)((batteryLevelInt & 0xfe000000) >>> 25);
3039 out.batteryTemperature = (short)((batteryLevelInt & 0x01ff8000) >>> 15);
3040 out.batteryVoltage = (char)((batteryLevelInt & 0x00007ffe) >>> 1);
3041 }
3042
3043 private int buildStateInt(HistoryItem h) {
3044 int plugType = 0;
3045 if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
3046 plugType = 1;
3047 } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
3048 plugType = 2;
3049 } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
3050 plugType = 3;
3051 }
3052 return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT)
3053 | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT)
3054 | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT)
3055 | (h.states&(~STATE_BATTERY_MASK));
3056 }
3057
3058 private void computeHistoryStepDetails(final HistoryStepDetails out,
3059 final HistoryStepDetails last) {
3060 final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
3061
3062 // Perform a CPU update right after we do this collection, so we have started
3063 // collecting good data for the next step.
3064 requestImmediateCpuUpdate();
3065
3066 if (last == null) {
3067 // We are not generating a delta, so all we need to do is reset the stats
3068 // we will later be doing a delta from.
3069 final int NU = mUidStats.size();
3070 for (int i=0; i<NU; i++) {
3071 final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3072 uid.mLastStepUserTime = uid.mCurStepUserTime;
3073 uid.mLastStepSystemTime = uid.mCurStepSystemTime;
3074 }
3075 mLastStepCpuUserTime = mCurStepCpuUserTime;
3076 mLastStepCpuSystemTime = mCurStepCpuSystemTime;
3077 mLastStepStatUserTime = mCurStepStatUserTime;
3078 mLastStepStatSystemTime = mCurStepStatSystemTime;
3079 mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
3080 mLastStepStatIrqTime = mCurStepStatIrqTime;
3081 mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
3082 mLastStepStatIdleTime = mCurStepStatIdleTime;
3083 tmp.clear();
3084 return;
3085 }
3086 if (DEBUG) {
3087 Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTime + " sys="
3088 + mLastStepStatSystemTime + " io=" + mLastStepStatIOWaitTime
3089 + " irq=" + mLastStepStatIrqTime + " sirq="
3090 + mLastStepStatSoftIrqTime + " idle=" + mLastStepStatIdleTime);
3091 Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTime + " sys="
3092 + mCurStepStatSystemTime + " io=" + mCurStepStatIOWaitTime
3093 + " irq=" + mCurStepStatIrqTime + " sirq="
3094 + mCurStepStatSoftIrqTime + " idle=" + mCurStepStatIdleTime);
3095 }
3096 out.userTime = (int)(mCurStepCpuUserTime - mLastStepCpuUserTime);
3097 out.systemTime = (int)(mCurStepCpuSystemTime - mLastStepCpuSystemTime);
3098 out.statUserTime = (int)(mCurStepStatUserTime - mLastStepStatUserTime);
3099 out.statSystemTime = (int)(mCurStepStatSystemTime - mLastStepStatSystemTime);
3100 out.statIOWaitTime = (int)(mCurStepStatIOWaitTime - mLastStepStatIOWaitTime);
3101 out.statIrqTime = (int)(mCurStepStatIrqTime - mLastStepStatIrqTime);
3102 out.statSoftIrqTime = (int)(mCurStepStatSoftIrqTime - mLastStepStatSoftIrqTime);
3103 out.statIdlTime = (int)(mCurStepStatIdleTime - mLastStepStatIdleTime);
3104 out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
3105 out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
3106 out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
3107 final int NU = mUidStats.size();
3108 for (int i=0; i<NU; i++) {
3109 final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3110 final int totalUTime = (int)(uid.mCurStepUserTime - uid.mLastStepUserTime);
3111 final int totalSTime = (int)(uid.mCurStepSystemTime - uid.mLastStepSystemTime);
3112 final int totalTime = totalUTime + totalSTime;
3113 uid.mLastStepUserTime = uid.mCurStepUserTime;
3114 uid.mLastStepSystemTime = uid.mCurStepSystemTime;
3115 if (totalTime <= (out.appCpuUTime3+out.appCpuSTime3)) {
3116 continue;
3117 }
3118 if (totalTime <= (out.appCpuUTime2+out.appCpuSTime2)) {
3119 out.appCpuUid3 = uid.mUid;
3120 out.appCpuUTime3 = totalUTime;
3121 out.appCpuSTime3 = totalSTime;
3122 } else {
3123 out.appCpuUid3 = out.appCpuUid2;
3124 out.appCpuUTime3 = out.appCpuUTime2;
3125 out.appCpuSTime3 = out.appCpuSTime2;
3126 if (totalTime <= (out.appCpuUTime1+out.appCpuSTime1)) {
3127 out.appCpuUid2 = uid.mUid;
3128 out.appCpuUTime2 = totalUTime;
3129 out.appCpuSTime2 = totalSTime;
3130 } else {
3131 out.appCpuUid2 = out.appCpuUid1;
3132 out.appCpuUTime2 = out.appCpuUTime1;
3133 out.appCpuSTime2 = out.appCpuSTime1;
3134 out.appCpuUid1 = uid.mUid;
3135 out.appCpuUTime1 = totalUTime;
3136 out.appCpuSTime1 = totalSTime;
3137 }
3138 }
3139 }
3140 mLastStepCpuUserTime = mCurStepCpuUserTime;
3141 mLastStepCpuSystemTime = mCurStepCpuSystemTime;
3142 mLastStepStatUserTime = mCurStepStatUserTime;
3143 mLastStepStatSystemTime = mCurStepStatSystemTime;
3144 mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
3145 mLastStepStatIrqTime = mCurStepStatIrqTime;
3146 mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
3147 mLastStepStatIdleTime = mCurStepStatIdleTime;
3148 }
3149
3150 public void readHistoryDelta(Parcel src, HistoryItem cur) {
3151 int firstToken = src.readInt();
3152 int deltaTimeToken = firstToken&DELTA_TIME_MASK;
3153 cur.cmd = HistoryItem.CMD_UPDATE;
3154 cur.numReadInts = 1;
3155 if (DEBUG) Slog.i(TAG, "READ DELTA: firstToken=0x" + Integer.toHexString(firstToken)
3156 + " deltaTimeToken=" + deltaTimeToken);
3157
3158 if (deltaTimeToken < DELTA_TIME_ABS) {
3159 cur.time += deltaTimeToken;
3160 } else if (deltaTimeToken == DELTA_TIME_ABS) {
3161 cur.time = src.readLong();
3162 cur.numReadInts += 2;
3163 if (DEBUG) Slog.i(TAG, "READ DELTA: ABS time=" + cur.time);
3164 cur.readFromParcel(src);
3165 return;
3166 } else if (deltaTimeToken == DELTA_TIME_INT) {
3167 int delta = src.readInt();
3168 cur.time += delta;
3169 cur.numReadInts += 1;
3170 if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
3171 } else {
3172 long delta = src.readLong();
3173 if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
3174 cur.time += delta;
3175 cur.numReadInts += 2;
3176 }
3177
3178 final int batteryLevelInt;
3179 if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
3180 batteryLevelInt = src.readInt();
3181 readBatteryLevelInt(batteryLevelInt, cur);
3182 cur.numReadInts += 1;
3183 if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x"
3184 + Integer.toHexString(batteryLevelInt)
3185 + " batteryLevel=" + cur.batteryLevel
3186 + " batteryTemp=" + cur.batteryTemperature
3187 + " batteryVolt=" + (int)cur.batteryVoltage);
3188 } else {
3189 batteryLevelInt = 0;
3190 }
3191
3192 if ((firstToken&DELTA_STATE_FLAG) != 0) {
3193 int stateInt = src.readInt();
3194 cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~STATE_BATTERY_MASK));
3195 cur.batteryStatus = (byte)((stateInt>>STATE_BATTERY_STATUS_SHIFT)
3196 & STATE_BATTERY_STATUS_MASK);
3197 cur.batteryHealth = (byte)((stateInt>>STATE_BATTERY_HEALTH_SHIFT)
3198 & STATE_BATTERY_HEALTH_MASK);
3199 cur.batteryPlugType = (byte)((stateInt>>STATE_BATTERY_PLUG_SHIFT)
3200 & STATE_BATTERY_PLUG_MASK);
3201 switch (cur.batteryPlugType) {
3202 case 1:
3203 cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_AC;
3204 break;
3205 case 2:
3206 cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_USB;
3207 break;
3208 case 3:
3209 cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
3210 break;
3211 }
3212 cur.numReadInts += 1;
3213 if (DEBUG) Slog.i(TAG, "READ DELTA: stateToken=0x"
3214 + Integer.toHexString(stateInt)
3215 + " batteryStatus=" + cur.batteryStatus
3216 + " batteryHealth=" + cur.batteryHealth
3217 + " batteryPlugType=" + cur.batteryPlugType
3218 + " states=0x" + Integer.toHexString(cur.states));
3219 } else {
3220 cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~STATE_BATTERY_MASK));
3221 }
3222
3223 if ((firstToken&DELTA_STATE2_FLAG) != 0) {
3224 cur.states2 = src.readInt();
3225 if (DEBUG) Slog.i(TAG, "READ DELTA: states2=0x"
3226 + Integer.toHexString(cur.states2));
3227 }
3228
3229 if ((firstToken&DELTA_WAKELOCK_FLAG) != 0) {
3230 int indexes = src.readInt();
3231 int wakeLockIndex = indexes&0xffff;
3232 int wakeReasonIndex = (indexes>>16)&0xffff;
3233 if (wakeLockIndex != 0xffff) {
3234 cur.wakelockTag = cur.localWakelockTag;
3235 readHistoryTag(wakeLockIndex, cur.wakelockTag);
3236 if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
3237 + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
3238 } else {
3239 cur.wakelockTag = null;
3240 }
3241 if (wakeReasonIndex != 0xffff) {
3242 cur.wakeReasonTag = cur.localWakeReasonTag;
3243 readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
3244 if (DEBUG) Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
3245 + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
3246 } else {
3247 cur.wakeReasonTag = null;
3248 }
3249 cur.numReadInts += 1;
3250 } else {
3251 cur.wakelockTag = null;
3252 cur.wakeReasonTag = null;
3253 }
3254
3255 if ((firstToken&DELTA_EVENT_FLAG) != 0) {
3256 cur.eventTag = cur.localEventTag;
3257 final int codeAndIndex = src.readInt();
3258 cur.eventCode = (codeAndIndex&0xffff);
3259 final int index = ((codeAndIndex>>16)&0xffff);
3260 readHistoryTag(index, cur.eventTag);
3261 cur.numReadInts += 1;
3262 if (DEBUG) Slog.i(TAG, "READ DELTA: event=" + cur.eventCode + " tag=#"
3263 + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
3264 + cur.eventTag.string);
3265 } else {
3266 cur.eventCode = HistoryItem.EVENT_NONE;
3267 }
3268
3269 if ((batteryLevelInt&BATTERY_DELTA_LEVEL_FLAG) != 0) {
3270 cur.stepDetails = mReadHistoryStepDetails;
3271 cur.stepDetails.readFromParcel(src);
3272 } else {
3273 cur.stepDetails = null;
3274 }
3275
3276 if ((firstToken&DELTA_BATTERY_CHARGE_FLAG) != 0) {
3277 cur.batteryChargeUAh = src.readInt();
3278 }
3279 }
3280
3281 @Override
3282 public void commitCurrentHistoryBatchLocked() {
3283 mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
3284 }
3285
3286 void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
3287 if (!mHaveBatteryLevel || !mRecordingHistory) {
3288 return;
3289 }
3290
3291 final long timeDiff = (mHistoryBaseTime+elapsedRealtimeMs) - mHistoryLastWritten.time;
3292 final int diffStates = mHistoryLastWritten.states^(cur.states&mActiveHistoryStates);
3293 final int diffStates2 = mHistoryLastWritten.states2^(cur.states2&mActiveHistoryStates2);
3294 final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
3295 final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
3296 if (DEBUG) Slog.i(TAG, "ADD: tdelta=" + timeDiff + " diff="
3297 + Integer.toHexString(diffStates) + " lastDiff="
3298 + Integer.toHexString(lastDiffStates) + " diff2="
3299 + Integer.toHexString(diffStates2) + " lastDiff2="
3300 + Integer.toHexString(lastDiffStates2));
3301 if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
3302 && timeDiff < 1000 && (diffStates&lastDiffStates) == 0
3303 && (diffStates2&lastDiffStates2) == 0
3304 && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
3305 && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
3306 && mHistoryLastWritten.stepDetails == null
3307 && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
3308 || cur.eventCode == HistoryItem.EVENT_NONE)
3309 && mHistoryLastWritten.batteryLevel == cur.batteryLevel
3310 && mHistoryLastWritten.batteryStatus == cur.batteryStatus
3311 && mHistoryLastWritten.batteryHealth == cur.batteryHealth
3312 && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
3313 && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
3314 && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
3315 // We can merge this new change in with the last one. Merging is
3316 // allowed as long as only the states have changed, and within those states
3317 // as long as no bit has changed both between now and the last entry, as
3318 // well as the last entry and the one before it (so we capture any toggles).
3319 if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
3320 mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
3321 mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
3322 mHistoryBufferLastPos = -1;
3323 elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTime;
3324 // If the last written history had a wakelock tag, we need to retain it.
3325 // Note that the condition above made sure that we aren't in a case where
3326 // both it and the current history item have a wakelock tag.
3327 if (mHistoryLastWritten.wakelockTag != null) {
3328 cur.wakelockTag = cur.localWakelockTag;
3329 cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
3330 }
3331 // If the last written history had a wake reason tag, we need to retain it.
3332 // Note that the condition above made sure that we aren't in a case where
3333 // both it and the current history item have a wakelock tag.
3334 if (mHistoryLastWritten.wakeReasonTag != null) {
3335 cur.wakeReasonTag = cur.localWakeReasonTag;
3336 cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
3337 }
3338 // If the last written history had an event, we need to retain it.
3339 // Note that the condition above made sure that we aren't in a case where
3340 // both it and the current history item have an event.
3341 if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
3342 cur.eventCode = mHistoryLastWritten.eventCode;
3343 cur.eventTag = cur.localEventTag;
3344 cur.eventTag.setTo(mHistoryLastWritten.eventTag);
3345 }
3346 mHistoryLastWritten.setTo(mHistoryLastLastWritten);
3347 }
3348
3349 boolean recordResetDueToOverflow = false;
3350 final int dataSize = mHistoryBuffer.dataSize();
3351 if (dataSize >= MAX_MAX_HISTORY_BUFFER*3) {
3352 // Clients can't deal with history buffers this large. This only
3353 // really happens when the device is on charger and interacted with
3354 // for long periods of time, like in retail mode. Since the device is
3355 // most likely charged, when unplugged, stats would have reset anyways.
3356 // Reset the stats and mark that we overflowed.
3357 // b/32540341
3358 resetAllStatsLocked();
3359
3360 // Mark that we want to set *OVERFLOW* event and the RESET:START
3361 // events.
3362 recordResetDueToOverflow = true;
3363
3364 } else if (dataSize >= MAX_HISTORY_BUFFER) {
3365 if (!mHistoryOverflow) {
3366 mHistoryOverflow = true;
3367 addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
3368 addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_OVERFLOW, cur);
3369 return;
3370 }
3371
3372 // After overflow, we allow various bit-wise states to settle to 0.
3373 boolean writeAnyway = false;
3374 final int curStates = cur.states & HistoryItem.SETTLE_TO_ZERO_STATES
3375 & mActiveHistoryStates;
3376 if (mHistoryLastWritten.states != curStates) {
3377 // mActiveHistoryStates keeps track of which bits in .states are now being
3378 // forced to 0.
3379 int old = mActiveHistoryStates;
3380 mActiveHistoryStates &= curStates | ~HistoryItem.SETTLE_TO_ZERO_STATES;
3381 writeAnyway |= old != mActiveHistoryStates;
3382 }
3383 final int curStates2 = cur.states2 & HistoryItem.SETTLE_TO_ZERO_STATES2
3384 & mActiveHistoryStates2;
3385 if (mHistoryLastWritten.states2 != curStates2) {
3386 // mActiveHistoryStates2 keeps track of which bits in .states2 are now being
3387 // forced to 0.
3388 int old = mActiveHistoryStates2;
3389 mActiveHistoryStates2 &= curStates2 | ~HistoryItem.SETTLE_TO_ZERO_STATES2;
3390 writeAnyway |= old != mActiveHistoryStates2;
3391 }
3392
3393 // Once we've reached the maximum number of items, we only
3394 // record changes to the battery level and the most interesting states.
3395 // Once we've reached the maximum maximum number of items, we only
3396 // record changes to the battery level.
3397 if (!writeAnyway && mHistoryLastWritten.batteryLevel == cur.batteryLevel &&
3398 (dataSize >= MAX_MAX_HISTORY_BUFFER
3399 || ((mHistoryLastWritten.states^cur.states)
3400 & HistoryItem.MOST_INTERESTING_STATES) == 0
3401 || ((mHistoryLastWritten.states2^cur.states2)
3402 & HistoryItem.MOST_INTERESTING_STATES2) == 0)) {
3403 return;
3404 }
3405
3406 addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
3407 return;
3408 }
3409
3410 if (dataSize == 0 || recordResetDueToOverflow) {
3411 // The history is currently empty; we need it to start with a time stamp.
3412 cur.currentTime = System.currentTimeMillis();
3413 if (recordResetDueToOverflow) {
3414 addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_OVERFLOW, cur);
3415 }
3416 addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_RESET, cur);
3417 }
3418 addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
3419 }
3420
3421 private void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd,
3422 HistoryItem cur) {
3423 if (mIteratingHistory) {
3424 throw new IllegalStateException("Can't do this while iterating history!");
3425 }
3426 mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
3427 mHistoryLastLastWritten.setTo(mHistoryLastWritten);
3428 mHistoryLastWritten.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
3429 mHistoryLastWritten.states &= mActiveHistoryStates;
3430 mHistoryLastWritten.states2 &= mActiveHistoryStates2;
3431 writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
3432 mLastHistoryElapsedRealtime = elapsedRealtimeMs;
3433 cur.wakelockTag = null;
3434 cur.wakeReasonTag = null;
3435 cur.eventCode = HistoryItem.EVENT_NONE;
3436 cur.eventTag = null;
3437 if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
3438 + " now " + mHistoryBuffer.dataPosition()
3439 + " size is now " + mHistoryBuffer.dataSize());
3440 }
3441
3442 int mChangedStates = 0;
3443 int mChangedStates2 = 0;
3444
3445 void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
3446 if (mTrackRunningHistoryElapsedRealtime != 0) {
3447 final long diffElapsed = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtime;
3448 final long diffUptime = uptimeMs - mTrackRunningHistoryUptime;
3449 if (diffUptime < (diffElapsed-20)) {
3450 final long wakeElapsedTime = elapsedRealtimeMs - (diffElapsed - diffUptime);
3451 mHistoryAddTmp.setTo(mHistoryLastWritten);
3452 mHistoryAddTmp.wakelockTag = null;
3453 mHistoryAddTmp.wakeReasonTag = null;
3454 mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
3455 mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
3456 addHistoryRecordInnerLocked(wakeElapsedTime, uptimeMs, mHistoryAddTmp);
3457 }
3458 }
3459 mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
3460 mTrackRunningHistoryElapsedRealtime = elapsedRealtimeMs;
3461 mTrackRunningHistoryUptime = uptimeMs;
3462 addHistoryRecordInnerLocked(elapsedRealtimeMs, uptimeMs, mHistoryCur);
3463 }
3464
3465 void addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
3466 addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, cur);
3467
3468 if (!USE_OLD_HISTORY) {
3469 return;
3470 }
3471
3472 if (!mHaveBatteryLevel || !mRecordingHistory) {
3473 return;
3474 }
3475
3476 // If the current time is basically the same as the last time,
3477 // and no states have since the last recorded entry changed and
3478 // are now resetting back to their original value, then just collapse
3479 // into one record.
3480 if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE
3481 && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+1000)
3482 && ((mHistoryEnd.states^cur.states)&mChangedStates&mActiveHistoryStates) == 0
3483 && ((mHistoryEnd.states2^cur.states2)&mChangedStates2&mActiveHistoryStates2) == 0) {
3484 // If the current is the same as the one before, then we no
3485 // longer need the entry.
3486 if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE
3487 && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+500)
3488 && mHistoryLastEnd.sameNonEvent(cur)) {
3489 mHistoryLastEnd.next = null;
3490 mHistoryEnd.next = mHistoryCache;
3491 mHistoryCache = mHistoryEnd;
3492 mHistoryEnd = mHistoryLastEnd;
3493 mHistoryLastEnd = null;
3494 } else {
3495 mChangedStates |= mHistoryEnd.states^(cur.states&mActiveHistoryStates);
3496 mChangedStates2 |= mHistoryEnd.states^(cur.states2&mActiveHistoryStates2);
3497 mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, cur);
3498 }
3499 return;
3500 }
3501
3502 mChangedStates = 0;
3503 mChangedStates2 = 0;
3504
3505 if (mNumHistoryItems == MAX_HISTORY_ITEMS
3506 || mNumHistoryItems == MAX_MAX_HISTORY_ITEMS) {
3507 addHistoryRecordLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW);
3508 }
3509
3510 if (mNumHistoryItems >= MAX_HISTORY_ITEMS) {
3511 // Once we've reached the maximum number of items, we only
3512 // record changes to the battery level and the most interesting states.
3513 // Once we've reached the maximum maximum number of items, we only
3514 // record changes to the battery level.
3515 if (mHistoryEnd != null && mHistoryEnd.batteryLevel
3516 == cur.batteryLevel &&
3517 (mNumHistoryItems >= MAX_MAX_HISTORY_ITEMS
3518 || ((mHistoryEnd.states^(cur.states&mActiveHistoryStates))
3519 & HistoryItem.MOST_INTERESTING_STATES) == 0)) {
3520 return;
3521 }
3522 }
3523
3524 addHistoryRecordLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE);
3525 }
3526
3527 public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
3528 String name, int uid) {
3529 mHistoryCur.eventCode = code;
3530 mHistoryCur.eventTag = mHistoryCur.localEventTag;
3531 mHistoryCur.eventTag.string = name;
3532 mHistoryCur.eventTag.uid = uid;
3533 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
3534 }
3535
3536 void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) {
3537 HistoryItem rec = mHistoryCache;
3538 if (rec != null) {
3539 mHistoryCache = rec.next;
3540 } else {
3541 rec = new HistoryItem();
3542 }
3543 rec.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
3544
3545 addHistoryRecordLocked(rec);
3546 }
3547
3548 void addHistoryRecordLocked(HistoryItem rec) {
3549 mNumHistoryItems++;
3550 rec.next = null;
3551 mHistoryLastEnd = mHistoryEnd;
3552 if (mHistoryEnd != null) {
3553 mHistoryEnd.next = rec;
3554 mHistoryEnd = rec;
3555 } else {
3556 mHistory = mHistoryEnd = rec;
3557 }
3558 }
3559
3560 void clearHistoryLocked() {
3561 if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
3562 if (USE_OLD_HISTORY) {
3563 if (mHistory != null) {
3564 mHistoryEnd.next = mHistoryCache;
3565 mHistoryCache = mHistory;
3566 mHistory = mHistoryLastEnd = mHistoryEnd = null;
3567 }
3568 mNumHistoryItems = 0;
3569 }
3570
3571 mHistoryBaseTime = 0;
3572 mLastHistoryElapsedRealtime = 0;
3573 mTrackRunningHistoryElapsedRealtime = 0;
3574 mTrackRunningHistoryUptime = 0;
3575
3576 mHistoryBuffer.setDataSize(0);
3577 mHistoryBuffer.setDataPosition(0);
3578 mHistoryBuffer.setDataCapacity(MAX_HISTORY_BUFFER / 2);
3579 mHistoryLastLastWritten.clear();
3580 mHistoryLastWritten.clear();
3581 mHistoryTagPool.clear();
3582 mNextHistoryTagIdx = 0;
3583 mNumHistoryTagChars = 0;
3584 mHistoryBufferLastPos = -1;
3585 mHistoryOverflow = false;
3586 mActiveHistoryStates = 0xffffffff;
3587 mActiveHistoryStates2 = 0xffffffff;
3588 }
3589
Justin Klaassen93b7ee42017-10-10 15:20:13 -04003590 public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptime,
Justin Klaassen10d07c82017-09-15 17:58:39 -04003591 long realtime) {
Justin Klaassen47ed54e2017-10-24 19:50:40 -04003592 final boolean screenOff = !isScreenOn(screenState);
Justin Klaassen10d07c82017-09-15 17:58:39 -04003593 final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
3594 final boolean updateOnBatteryScreenOffTimeBase =
3595 (unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
3596
3597 if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) {
3598 if (updateOnBatteryScreenOffTimeBase) {
3599 updateKernelWakelocksLocked();
3600 updateBatteryPropertiesLocked();
3601 }
Justin Klaassenbc81c7a2017-09-18 17:38:50 -04003602 // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
3603 // updateRpmStatsLocked is too slow to run each screen change. When the speed is
3604 // improved, remove the surrounding if{}.
3605 if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
3606 updateRpmStatsLocked(); // if either OnBattery or OnBatteryScreenOff timebase changes.
3607 }
Justin Klaassen10d07c82017-09-15 17:58:39 -04003608 if (DEBUG_ENERGY_CPU) {
Justin Klaassen93b7ee42017-10-10 15:20:13 -04003609 Slog.d(TAG, "Updating cpu time because screen is now "
3610 + Display.stateToString(screenState)
Justin Klaassen10d07c82017-09-15 17:58:39 -04003611 + " and battery is " + (unplugged ? "on" : "off"));
3612 }
3613 updateCpuTimeLocked();
3614
3615 mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime);
Justin Klaassen93b7ee42017-10-10 15:20:13 -04003616 if (updateOnBatteryTimeBase) {
3617 for (int i = mUidStats.size() - 1; i >= 0; --i) {
3618 mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptime, realtime);
Justin Klaassen10d07c82017-09-15 17:58:39 -04003619 }
Justin Klaassen93b7ee42017-10-10 15:20:13 -04003620 }
3621 if (updateOnBatteryScreenOffTimeBase) {
3622 mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff, uptime, realtime);
3623 for (int i = mUidStats.size() - 1; i >= 0; --i) {
3624 mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptime, realtime);
Justin Klaassen10d07c82017-09-15 17:58:39 -04003625 }
3626 }
3627 }
3628 }
3629
3630 private void updateBatteryPropertiesLocked() {
3631 try {
3632 IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
3633 ServiceManager.getService("batteryproperties"));
3634 registrar.scheduleUpdate();
3635 } catch (RemoteException e) {
3636 // Ignore.
3637 }
3638 }
3639
3640 public void addIsolatedUidLocked(int isolatedUid, int appUid) {
3641 mIsolatedUids.put(isolatedUid, appUid);
3642 }
3643
3644 /**
3645 * Schedules a read of the latest cpu times before removing the isolated UID.
3646 * @see #removeIsolatedUidLocked(int)
3647 */
3648 public void scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid) {
3649 int curUid = mIsolatedUids.get(isolatedUid, -1);
3650 if (curUid == appUid) {
3651 if (mExternalSync != null) {
3652 mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
3653 }
3654 }
3655 }
3656
3657 /**
3658 * This should only be called after the cpu times have been read.
3659 * @see #scheduleRemoveIsolatedUidLocked(int, int)
3660 */
3661 public void removeIsolatedUidLocked(int isolatedUid) {
3662 mIsolatedUids.delete(isolatedUid);
3663 mKernelUidCpuTimeReader.removeUid(isolatedUid);
3664 mKernelUidCpuFreqTimeReader.removeUid(isolatedUid);
3665 }
3666
3667 public int mapUid(int uid) {
3668 int isolated = mIsolatedUids.get(uid, -1);
3669 return isolated > 0 ? isolated : uid;
3670 }
3671
3672 public void noteEventLocked(int code, String name, int uid) {
3673 uid = mapUid(uid);
3674 if (!mActiveEvents.updateState(code, name, uid, 0)) {
3675 return;
3676 }
3677 final long elapsedRealtime = mClocks.elapsedRealtime();
3678 final long uptime = mClocks.uptimeMillis();
3679 addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
3680 }
3681
3682 boolean ensureStartClockTime(final long currentTime) {
3683 final long ABOUT_ONE_YEAR = 365*24*60*60*1000L;
3684 if (currentTime > ABOUT_ONE_YEAR && mStartClockTime < (currentTime-ABOUT_ONE_YEAR)) {
3685 // If the start clock time has changed by more than a year, then presumably
3686 // the previous time was completely bogus. So we are going to figure out a
3687 // new time based on how much time has elapsed since we started counting.
3688 mStartClockTime = currentTime - (mClocks.elapsedRealtime()-(mRealtimeStart/1000));
3689 return true;
3690 }
3691 return false;
3692 }
3693
3694 public void noteCurrentTimeChangedLocked() {
3695 final long currentTime = System.currentTimeMillis();
3696 final long elapsedRealtime = mClocks.elapsedRealtime();
3697 final long uptime = mClocks.uptimeMillis();
3698 recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
3699 ensureStartClockTime(currentTime);
3700 }
3701
3702 public void noteProcessStartLocked(String name, int uid) {
3703 uid = mapUid(uid);
3704 if (isOnBattery()) {
3705 Uid u = getUidStatsLocked(uid);
3706 u.getProcessStatsLocked(name).incStartsLocked();
3707 }
3708 if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
3709 return;
3710 }
3711 if (!mRecordAllHistory) {
3712 return;
3713 }
3714 final long elapsedRealtime = mClocks.elapsedRealtime();
3715 final long uptime = mClocks.uptimeMillis();
3716 addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid);
3717 }
3718
3719 public void noteProcessCrashLocked(String name, int uid) {
3720 uid = mapUid(uid);
3721 if (isOnBattery()) {
3722 Uid u = getUidStatsLocked(uid);
3723 u.getProcessStatsLocked(name).incNumCrashesLocked();
3724 }
3725 }
3726
3727 public void noteProcessAnrLocked(String name, int uid) {
3728 uid = mapUid(uid);
3729 if (isOnBattery()) {
3730 Uid u = getUidStatsLocked(uid);
3731 u.getProcessStatsLocked(name).incNumAnrsLocked();
3732 }
3733 }
3734
3735 public void noteUidProcessStateLocked(int uid, int state) {
3736 int parentUid = mapUid(uid);
3737 if (uid != parentUid) {
3738 // Isolated UIDs process state is already rolled up into parent, so no need to track
3739 // Otherwise the parent's process state will get downgraded incorrectly
3740 return;
3741 }
3742 getUidStatsLocked(uid).updateUidProcessStateLocked(state);
3743 }
3744
3745 public void noteProcessFinishLocked(String name, int uid) {
3746 uid = mapUid(uid);
3747 if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
3748 return;
3749 }
3750 if (!mRecordAllHistory) {
3751 return;
3752 }
3753 final long elapsedRealtime = mClocks.elapsedRealtime();
3754 final long uptime = mClocks.uptimeMillis();
3755 addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
3756 }
3757
3758 public void noteSyncStartLocked(String name, int uid) {
3759 uid = mapUid(uid);
3760 final long elapsedRealtime = mClocks.elapsedRealtime();
3761 final long uptime = mClocks.uptimeMillis();
3762 getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime);
3763 if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
3764 return;
3765 }
3766 addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_START, name, uid);
3767 }
3768
3769 public void noteSyncFinishLocked(String name, int uid) {
3770 uid = mapUid(uid);
3771 final long elapsedRealtime = mClocks.elapsedRealtime();
3772 final long uptime = mClocks.uptimeMillis();
3773 getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime);
3774 if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
3775 return;
3776 }
3777 addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_FINISH, name, uid);
3778 }
3779
3780 public void noteJobStartLocked(String name, int uid) {
3781 uid = mapUid(uid);
3782 final long elapsedRealtime = mClocks.elapsedRealtime();
3783 final long uptime = mClocks.uptimeMillis();
3784 getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime);
3785 if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
3786 return;
3787 }
3788 addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid);
3789 }
3790
3791 public void noteJobFinishLocked(String name, int uid, int stopReason) {
3792 uid = mapUid(uid);
3793 final long elapsedRealtime = mClocks.elapsedRealtime();
3794 final long uptime = mClocks.uptimeMillis();
3795 getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime, stopReason);
3796 if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
3797 return;
3798 }
3799 addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
3800 }
3801
3802 public void noteAlarmStartLocked(String name, int uid) {
3803 if (!mRecordAllHistory) {
3804 return;
3805 }
3806 uid = mapUid(uid);
3807 final long elapsedRealtime = mClocks.elapsedRealtime();
3808 final long uptime = mClocks.uptimeMillis();
3809 if (!mActiveEvents.updateState(HistoryItem.EVENT_ALARM_START, name, uid, 0)) {
3810 return;
3811 }
3812 addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ALARM_START, name, uid);
3813 }
3814
3815 public void noteAlarmFinishLocked(String name, int uid) {
3816 if (!mRecordAllHistory) {
3817 return;
3818 }
3819 uid = mapUid(uid);
3820 final long elapsedRealtime = mClocks.elapsedRealtime();
3821 final long uptime = mClocks.uptimeMillis();
3822 if (!mActiveEvents.updateState(HistoryItem.EVENT_ALARM_FINISH, name, uid, 0)) {
3823 return;
3824 }
3825 addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ALARM_FINISH, name, uid);
3826 }
3827
3828 private void requestWakelockCpuUpdate() {
3829 if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
3830 Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
3831 mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
3832 }
3833 }
3834
3835 private void requestImmediateCpuUpdate() {
3836 mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
3837 mHandler.sendEmptyMessage(MSG_UPDATE_WAKELOCKS);
3838 }
3839
3840 public void setRecordAllHistoryLocked(boolean enabled) {
3841 mRecordAllHistory = enabled;
3842 if (!enabled) {
3843 // Clear out any existing state.
3844 mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
3845 mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
3846 // Record the currently running processes as stopping, now that we are no
3847 // longer tracking them.
3848 HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
3849 HistoryItem.EVENT_PROC);
3850 if (active != null) {
3851 long mSecRealtime = mClocks.elapsedRealtime();
3852 final long mSecUptime = mClocks.uptimeMillis();
3853 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
3854 SparseIntArray uids = ent.getValue();
3855 for (int j=0; j<uids.size(); j++) {
3856 addHistoryEventLocked(mSecRealtime, mSecUptime,
3857 HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
3858 }
3859 }
3860 }
3861 } else {
3862 // Record the currently running processes as starting, now that we are tracking them.
3863 HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
3864 HistoryItem.EVENT_PROC);
3865 if (active != null) {
3866 long mSecRealtime = mClocks.elapsedRealtime();
3867 final long mSecUptime = mClocks.uptimeMillis();
3868 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
3869 SparseIntArray uids = ent.getValue();
3870 for (int j=0; j<uids.size(); j++) {
3871 addHistoryEventLocked(mSecRealtime, mSecUptime,
3872 HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
3873 }
3874 }
3875 }
3876 }
3877 }
3878
3879 public void setNoAutoReset(boolean enabled) {
3880 mNoAutoReset = enabled;
3881 }
3882
3883 public void setPretendScreenOff(boolean pretendScreenOff) {
Justin Klaassen93b7ee42017-10-10 15:20:13 -04003884 if (mPretendScreenOff != pretendScreenOff) {
3885 mPretendScreenOff = pretendScreenOff;
3886 noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON);
3887 }
Justin Klaassen10d07c82017-09-15 17:58:39 -04003888 }
3889
3890 private String mInitialAcquireWakeName;
3891 private int mInitialAcquireWakeUid = -1;
3892
3893 public void noteStartWakeLocked(int uid, int pid, String name, String historyName, int type,
3894 boolean unimportantForLogging, long elapsedRealtime, long uptime) {
3895 uid = mapUid(uid);
3896 if (type == WAKE_TYPE_PARTIAL) {
3897 // Only care about partial wake locks, since full wake locks
3898 // will be canceled when the user puts the screen to sleep.
3899 aggregateLastWakeupUptimeLocked(uptime);
3900 if (historyName == null) {
3901 historyName = name;
3902 }
3903 if (mRecordAllHistory) {
3904 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
3905 uid, 0)) {
3906 addHistoryEventLocked(elapsedRealtime, uptime,
3907 HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
3908 }
3909 }
3910 if (mWakeLockNesting == 0) {
3911 mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
3912 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
3913 + Integer.toHexString(mHistoryCur.states));
3914 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
3915 mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
3916 mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
3917 mWakeLockImportant = !unimportantForLogging;
3918 addHistoryRecordLocked(elapsedRealtime, uptime);
3919 } else if (!mWakeLockImportant && !unimportantForLogging
3920 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
3921 if (mHistoryLastWritten.wakelockTag != null) {
3922 // We'll try to update the last tag.
3923 mHistoryLastWritten.wakelockTag = null;
3924 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
3925 mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
3926 mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
3927 addHistoryRecordLocked(elapsedRealtime, uptime);
3928 }
3929 mWakeLockImportant = true;
3930 }
3931 mWakeLockNesting++;
3932 }
3933 if (uid >= 0) {
3934 if (mOnBatteryScreenOffTimeBase.isRunning()) {
3935 // We only update the cpu time when a wake lock is acquired if the screen is off.
3936 // If the screen is on, we don't distribute the power amongst partial wakelocks.
3937 if (DEBUG_ENERGY_CPU) {
3938 Slog.d(TAG, "Updating cpu time because of +wake_lock");
3939 }
3940 requestWakelockCpuUpdate();
3941 }
3942 getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
3943 }
3944 }
3945
3946 public void noteStopWakeLocked(int uid, int pid, String name, String historyName, int type,
3947 long elapsedRealtime, long uptime) {
3948 uid = mapUid(uid);
3949 if (type == WAKE_TYPE_PARTIAL) {
3950 mWakeLockNesting--;
3951 if (mRecordAllHistory) {
3952 if (historyName == null) {
3953 historyName = name;
3954 }
3955 if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
3956 uid, 0)) {
3957 addHistoryEventLocked(elapsedRealtime, uptime,
3958 HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
3959 }
3960 }
3961 if (mWakeLockNesting == 0) {
3962 mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
3963 if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
3964 + Integer.toHexString(mHistoryCur.states));
3965 mInitialAcquireWakeName = null;
3966 mInitialAcquireWakeUid = -1;
3967 addHistoryRecordLocked(elapsedRealtime, uptime);
3968 }
3969 }
3970 if (uid >= 0) {
3971 if (mOnBatteryScreenOffTimeBase.isRunning()) {
3972 if (DEBUG_ENERGY_CPU) {
3973 Slog.d(TAG, "Updating cpu time because of -wake_lock");
3974 }
3975 requestWakelockCpuUpdate();
3976 }
3977 getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
3978 }
3979 }
3980
3981 public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
3982 String historyName, int type, boolean unimportantForLogging) {
3983 final long elapsedRealtime = mClocks.elapsedRealtime();
3984 final long uptime = mClocks.uptimeMillis();
3985 final int N = ws.size();
3986 for (int i=0; i<N; i++) {
3987 noteStartWakeLocked(ws.get(i), pid, name, historyName, type, unimportantForLogging,
3988 elapsedRealtime, uptime);
3989 }
3990 }
3991
3992 public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
3993 String historyName, int type, WorkSource newWs, int newPid, String newName,
3994 String newHistoryName, int newType, boolean newUnimportantForLogging) {
3995 final long elapsedRealtime = mClocks.elapsedRealtime();
3996 final long uptime = mClocks.uptimeMillis();
3997 // For correct semantics, we start the need worksources first, so that we won't
3998 // make inappropriate history items as if all wake locks went away and new ones
3999 // appeared. This is okay because tracking of wake locks allows nesting.
4000 final int NN = newWs.size();
4001 for (int i=0; i<NN; i++) {
4002 noteStartWakeLocked(newWs.get(i), newPid, newName, newHistoryName, newType,
4003 newUnimportantForLogging, elapsedRealtime, uptime);
4004 }
4005 final int NO = ws.size();
4006 for (int i=0; i<NO; i++) {
4007 noteStopWakeLocked(ws.get(i), pid, name, historyName, type, elapsedRealtime, uptime);
4008 }
4009 }
4010
4011 public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
4012 String historyName, int type) {
4013 final long elapsedRealtime = mClocks.elapsedRealtime();
4014 final long uptime = mClocks.uptimeMillis();
4015 final int N = ws.size();
4016 for (int i=0; i<N; i++) {
4017 noteStopWakeLocked(ws.get(i), pid, name, historyName, type, elapsedRealtime, uptime);
4018 }
4019 }
4020
4021 public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
4022 uid = mapUid(uid);
4023 final long elapsedRealtime = mClocks.elapsedRealtime();
4024 final long uptime = mClocks.uptimeMillis();
4025 if (historyName == null) {
4026 historyName = name;
4027 }
4028 if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid,
4029 0)) {
4030 return;
4031 }
4032 addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
4033 historyName, uid);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04004034 StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, uid, name, historyName, 1);
Justin Klaassen10d07c82017-09-15 17:58:39 -04004035 }
4036
4037 public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
4038 uid = mapUid(uid);
4039 final long elapsedRealtime = mClocks.elapsedRealtime();
4040 final long uptime = mClocks.uptimeMillis();
4041 if (historyName == null) {
4042 historyName = name;
4043 }
4044 if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid,
4045 0)) {
4046 return;
4047 }
4048 addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
4049 historyName, uid);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04004050 StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, uid, name, historyName, 0);
Justin Klaassen10d07c82017-09-15 17:58:39 -04004051 }
4052
4053 void aggregateLastWakeupUptimeLocked(long uptimeMs) {
4054 if (mLastWakeupReason != null) {
4055 long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
4056 SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
4057 timer.add(deltaUptime * 1000, 1); // time in in microseconds
4058 mLastWakeupReason = null;
4059 }
4060 }
4061
4062 public void noteWakeupReasonLocked(String reason) {
4063 final long elapsedRealtime = mClocks.elapsedRealtime();
4064 final long uptime = mClocks.uptimeMillis();
4065 if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
4066 + Integer.toHexString(mHistoryCur.states));
4067 aggregateLastWakeupUptimeLocked(uptime);
4068 mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
4069 mHistoryCur.wakeReasonTag.string = reason;
4070 mHistoryCur.wakeReasonTag.uid = 0;
4071 mLastWakeupReason = reason;
4072 mLastWakeupUptimeMs = uptime;
4073 addHistoryRecordLocked(elapsedRealtime, uptime);
4074 }
4075
4076 public boolean startAddingCpuLocked() {
4077 mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
4078 return mOnBatteryInternal;
4079 }
4080
4081 public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime,
4082 int statSystemTime, int statIOWaitTime, int statIrqTime,
4083 int statSoftIrqTime, int statIdleTime) {
4084 if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
4085 + " user=" + statUserTime + " sys=" + statSystemTime
4086 + " io=" + statIOWaitTime + " irq=" + statIrqTime
4087 + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime);
4088 mCurStepCpuUserTime += totalUTime;
4089 mCurStepCpuSystemTime += totalSTime;
4090 mCurStepStatUserTime += statUserTime;
4091 mCurStepStatSystemTime += statSystemTime;
4092 mCurStepStatIOWaitTime += statIOWaitTime;
4093 mCurStepStatIrqTime += statIrqTime;
4094 mCurStepStatSoftIrqTime += statSoftIrqTime;
4095 mCurStepStatIdleTime += statIdleTime;
4096 }
4097
4098 public void noteProcessDiedLocked(int uid, int pid) {
4099 uid = mapUid(uid);
4100 Uid u = mUidStats.get(uid);
4101 if (u != null) {
4102 u.mPids.remove(pid);
4103 }
4104 }
4105
4106 public long getProcessWakeTime(int uid, int pid, long realtime) {
4107 uid = mapUid(uid);
4108 Uid u = mUidStats.get(uid);
4109 if (u != null) {
4110 Uid.Pid p = u.mPids.get(pid);
4111 if (p != null) {
4112 return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0);
4113 }
4114 }
4115 return 0;
4116 }
4117
4118 public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
4119 uid = mapUid(uid);
4120 Uid u = mUidStats.get(uid);
4121 if (u != null) {
4122 u.reportExcessiveCpuLocked(proc, overTime, usedTime);
4123 }
4124 }
4125
4126 int mSensorNesting;
4127
4128 public void noteStartSensorLocked(int uid, int sensor) {
4129 uid = mapUid(uid);
4130 final long elapsedRealtime = mClocks.elapsedRealtime();
4131 final long uptime = mClocks.uptimeMillis();
4132 if (mSensorNesting == 0) {
4133 mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
4134 if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
4135 + Integer.toHexString(mHistoryCur.states));
4136 addHistoryRecordLocked(elapsedRealtime, uptime);
4137 }
4138 mSensorNesting++;
4139 getUidStatsLocked(uid).noteStartSensor(sensor, elapsedRealtime);
4140 }
4141
4142 public void noteStopSensorLocked(int uid, int sensor) {
4143 uid = mapUid(uid);
4144 final long elapsedRealtime = mClocks.elapsedRealtime();
4145 final long uptime = mClocks.uptimeMillis();
4146 mSensorNesting--;
4147 if (mSensorNesting == 0) {
4148 mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
4149 if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
4150 + Integer.toHexString(mHistoryCur.states));
4151 addHistoryRecordLocked(elapsedRealtime, uptime);
4152 }
4153 getUidStatsLocked(uid).noteStopSensor(sensor, elapsedRealtime);
4154 }
4155
4156 int mGpsNesting;
4157
4158 public void noteStartGpsLocked(int uid) {
4159 uid = mapUid(uid);
4160 final long elapsedRealtime = mClocks.elapsedRealtime();
4161 final long uptime = mClocks.uptimeMillis();
4162 if (mGpsNesting == 0) {
4163 mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
4164 if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
4165 + Integer.toHexString(mHistoryCur.states));
4166 addHistoryRecordLocked(elapsedRealtime, uptime);
4167 }
4168 mGpsNesting++;
4169 getUidStatsLocked(uid).noteStartGps(elapsedRealtime);
4170 }
4171
4172 public void noteStopGpsLocked(int uid) {
4173 uid = mapUid(uid);
4174 final long elapsedRealtime = mClocks.elapsedRealtime();
4175 final long uptime = mClocks.uptimeMillis();
4176 mGpsNesting--;
4177 if (mGpsNesting == 0) {
4178 mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
4179 if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
4180 + Integer.toHexString(mHistoryCur.states));
4181 addHistoryRecordLocked(elapsedRealtime, uptime);
4182 }
4183 getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
4184 }
4185
4186 public void noteScreenStateLocked(int state) {
4187 state = mPretendScreenOff ? Display.STATE_OFF : state;
4188
4189 // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
4190 // original 4 are mapped to one of the originals.
4191 if (state > MAX_TRACKED_SCREEN_STATE) {
4192 switch (state) {
4193 case Display.STATE_VR:
4194 state = Display.STATE_ON;
4195 break;
4196 default:
4197 Slog.wtf(TAG, "Unknown screen state (not mapped): " + state);
4198 break;
4199 }
4200 }
4201
4202 if (mScreenState != state) {
4203 recordDailyStatsIfNeededLocked(true);
4204 final int oldState = mScreenState;
4205 mScreenState = state;
4206 if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
4207 + ", newState=" + Display.stateToString(state));
4208
4209 if (state != Display.STATE_UNKNOWN) {
4210 int stepState = state-1;
4211 if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
4212 mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
4213 mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
4214 } else {
4215 Slog.wtf(TAG, "Unexpected screen state: " + state);
4216 }
4217 }
4218
Justin Klaassen93b7ee42017-10-10 15:20:13 -04004219 final long elapsedRealtime = mClocks.elapsedRealtime();
4220 final long uptime = mClocks.uptimeMillis();
4221
4222 boolean updateHistory = false;
4223 if (isScreenDoze(state)) {
4224 mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
4225 mScreenDozeTimer.startRunningLocked(elapsedRealtime);
4226 updateHistory = true;
4227 } else if (isScreenDoze(oldState)) {
4228 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG;
4229 mScreenDozeTimer.stopRunningLocked(elapsedRealtime);
4230 updateHistory = true;
4231 }
4232 if (isScreenOn(state)) {
Justin Klaassen10d07c82017-09-15 17:58:39 -04004233 mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
4234 if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
4235 + Integer.toHexString(mHistoryCur.states));
Justin Klaassen10d07c82017-09-15 17:58:39 -04004236 mScreenOnTimer.startRunningLocked(elapsedRealtime);
4237 if (mScreenBrightnessBin >= 0) {
4238 mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
4239 }
Justin Klaassen93b7ee42017-10-10 15:20:13 -04004240 updateHistory = true;
4241 } else if (isScreenOn(oldState)) {
Justin Klaassen10d07c82017-09-15 17:58:39 -04004242 mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
4243 if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
4244 + Integer.toHexString(mHistoryCur.states));
Justin Klaassen10d07c82017-09-15 17:58:39 -04004245 mScreenOnTimer.stopRunningLocked(elapsedRealtime);
4246 if (mScreenBrightnessBin >= 0) {
4247 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
4248 }
Justin Klaassen93b7ee42017-10-10 15:20:13 -04004249 updateHistory = true;
4250 }
4251 if (updateHistory) {
4252 if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: "
4253 + Display.stateToString(state));
4254 addHistoryRecordLocked(elapsedRealtime, uptime);
4255 }
4256 if (isScreenOn(state)) {
4257 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
4258 mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
4259 // Fake a wake lock, so we consider the device waked as long as the screen is on.
4260 noteStartWakeLocked(-1, -1, "screen", null, WAKE_TYPE_PARTIAL, false,
4261 elapsedRealtime, uptime);
4262 } else if (isScreenOn(oldState)) {
Justin Klaassen10d07c82017-09-15 17:58:39 -04004263 noteStopWakeLocked(-1, -1, "screen", "screen", WAKE_TYPE_PARTIAL,
4264 elapsedRealtime, uptime);
Justin Klaassen93b7ee42017-10-10 15:20:13 -04004265 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
Justin Klaassen10d07c82017-09-15 17:58:39 -04004266 mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
Justin Klaassen93b7ee42017-10-10 15:20:13 -04004267 }
4268 // Update discharge amounts.
4269 if (mOnBatteryInternal) {
4270 updateDischargeScreenLevelsLocked(oldState, state);
Justin Klaassen10d07c82017-09-15 17:58:39 -04004271 }
4272 }
4273 }
4274
4275 public void noteScreenBrightnessLocked(int brightness) {
4276 // Bin the brightness.
4277 int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
4278 if (bin < 0) bin = 0;
4279 else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
4280 if (mScreenBrightnessBin != bin) {
4281 final long elapsedRealtime = mClocks.elapsedRealtime();
4282 final long uptime = mClocks.uptimeMillis();
4283 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
4284 | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
4285 if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
4286 + Integer.toHexString(mHistoryCur.states));
4287 addHistoryRecordLocked(elapsedRealtime, uptime);
4288 if (mScreenState == Display.STATE_ON) {
4289 if (mScreenBrightnessBin >= 0) {
4290 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
4291 }
4292 mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime);
4293 }
4294 mScreenBrightnessBin = bin;
4295 }
4296 }
4297
4298 public void noteUserActivityLocked(int uid, int event) {
4299 if (mOnBatteryInternal) {
4300 uid = mapUid(uid);
4301 getUidStatsLocked(uid).noteUserActivityLocked(event);
4302 }
4303 }
4304
4305 public void noteWakeUpLocked(String reason, int reasonUid) {
4306 final long elapsedRealtime = mClocks.elapsedRealtime();
4307 final long uptime = mClocks.uptimeMillis();
4308 addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SCREEN_WAKE_UP,
4309 reason, reasonUid);
4310 }
4311
4312 public void noteInteractiveLocked(boolean interactive) {
4313 if (mInteractive != interactive) {
4314 final long elapsedRealtime = mClocks.elapsedRealtime();
4315 mInteractive = interactive;
4316 if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
4317 if (interactive) {
4318 mInteractiveTimer.startRunningLocked(elapsedRealtime);
4319 } else {
4320 mInteractiveTimer.stopRunningLocked(elapsedRealtime);
4321 }
4322 }
4323 }
4324
4325 public void noteConnectivityChangedLocked(int type, String extra) {
4326 final long elapsedRealtime = mClocks.elapsedRealtime();
4327 final long uptime = mClocks.uptimeMillis();
4328 addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
4329 extra, type);
4330 mNumConnectivityChange++;
4331 }
4332
4333 private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
4334 final long uptimeMillis, int uid) {
4335 uid = mapUid(uid);
4336 addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
4337 uid);
4338 getUidStatsLocked(uid).noteMobileRadioApWakeupLocked();
4339 }
4340
4341 /**
4342 * Updates the radio power state and returns true if an external stats collection should occur.
4343 */
4344 public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
4345 final long elapsedRealtime = mClocks.elapsedRealtime();
4346 final long uptime = mClocks.uptimeMillis();
4347 if (mMobileRadioPowerState != powerState) {
4348 long realElapsedRealtimeMs;
4349 final boolean active =
4350 powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
4351 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
4352 if (active) {
4353 if (uid > 0) {
4354 noteMobileRadioApWakeupLocked(elapsedRealtime, uptime, uid);
4355 }
4356
4357 mMobileRadioActiveStartTime = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
4358 mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
4359 } else {
4360 realElapsedRealtimeMs = timestampNs / (1000*1000);
4361 long lastUpdateTimeMs = mMobileRadioActiveStartTime;
4362 if (realElapsedRealtimeMs < lastUpdateTimeMs) {
4363 Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
4364 + " is before start time " + lastUpdateTimeMs);
4365 realElapsedRealtimeMs = elapsedRealtime;
4366 } else if (realElapsedRealtimeMs < elapsedRealtime) {
4367 mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
4368 - realElapsedRealtimeMs);
4369 }
4370 mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
4371 }
4372 if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
4373 + Integer.toHexString(mHistoryCur.states));
4374 addHistoryRecordLocked(elapsedRealtime, uptime);
4375 mMobileRadioPowerState = powerState;
4376 if (active) {
4377 mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
4378 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
4379 } else {
4380 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
4381 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
4382 // Tell the caller to collect radio network/power stats.
4383 return true;
4384 }
4385 }
4386 return false;
4387 }
4388
4389 public void notePowerSaveModeLocked(boolean enabled) {
4390 if (mPowerSaveModeEnabled != enabled) {
4391 int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
4392 mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
4393 mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
4394 final long elapsedRealtime = mClocks.elapsedRealtime();
4395 final long uptime = mClocks.uptimeMillis();
4396 mPowerSaveModeEnabled = enabled;
4397 if (enabled) {
4398 mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
4399 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
4400 + Integer.toHexString(mHistoryCur.states2));
4401 mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtime);
4402 } else {
4403 mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
4404 if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
4405 + Integer.toHexString(mHistoryCur.states2));
4406 mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtime);
4407 }
4408 addHistoryRecordLocked(elapsedRealtime, uptime);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04004409 StatsLog.write(StatsLog.BATTERY_SAVER_MODE_STATE_CHANGED, enabled ? 1 : 0);
Justin Klaassen10d07c82017-09-15 17:58:39 -04004410 }
4411 }
4412
4413 public void noteDeviceIdleModeLocked(int mode, String activeReason, int activeUid) {
4414 final long elapsedRealtime = mClocks.elapsedRealtime();
4415 final long uptime = mClocks.uptimeMillis();
4416 boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
4417 if (mDeviceIdling && !nowIdling && activeReason == null) {
4418 // We don't go out of general idling mode until explicitly taken out of
4419 // device idle through going active or significant motion.
4420 nowIdling = true;
4421 }
4422 boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
4423 if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
4424 // We don't go out of general light idling mode until explicitly taken out of
4425 // device idle through going active or significant motion.
4426 nowLightIdling = true;
4427 }
4428 if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
4429 addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
4430 activeReason, activeUid);
4431 }
4432 if (mDeviceIdling != nowIdling) {
4433 mDeviceIdling = nowIdling;
4434 int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
4435 mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
4436 mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
4437 if (nowIdling) {
4438 mDeviceIdlingTimer.startRunningLocked(elapsedRealtime);
4439 } else {
4440 mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime);
4441 }
4442 }
4443 if (mDeviceLightIdling != nowLightIdling) {
4444 mDeviceLightIdling = nowLightIdling;
4445 if (nowLightIdling) {
4446 mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtime);
4447 } else {
4448 mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtime);
4449 }
4450 }
4451 if (mDeviceIdleMode != mode) {
4452 mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
4453 | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
4454 if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
4455 + Integer.toHexString(mHistoryCur.states2));
4456 addHistoryRecordLocked(elapsedRealtime, uptime);
4457 long lastDuration = elapsedRealtime - mLastIdleTimeStart;
4458 mLastIdleTimeStart = elapsedRealtime;
4459 if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
4460 if (lastDuration > mLongestLightIdleTime) {
4461 mLongestLightIdleTime = lastDuration;
4462 }
4463 mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtime);
4464 } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
4465 if (lastDuration > mLongestFullIdleTime) {
4466 mLongestFullIdleTime = lastDuration;
4467 }
4468 mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtime);
4469 }
4470 if (mode == DEVICE_IDLE_MODE_LIGHT) {
4471 mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtime);
4472 } else if (mode == DEVICE_IDLE_MODE_DEEP) {
4473 mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtime);
4474 }
4475 mDeviceIdleMode = mode;
4476 }
4477 }
4478
4479 public void notePackageInstalledLocked(String pkgName, int versionCode) {
4480 final long elapsedRealtime = mClocks.elapsedRealtime();
4481 final long uptime = mClocks.uptimeMillis();
4482 addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED,
4483 pkgName, versionCode);
4484 PackageChange pc = new PackageChange();
4485 pc.mPackageName = pkgName;
4486 pc.mUpdate = true;
4487 pc.mVersionCode = versionCode;
4488 addPackageChange(pc);
4489 }
4490
4491 public void notePackageUninstalledLocked(String pkgName) {
4492 final long elapsedRealtime = mClocks.elapsedRealtime();
4493 final long uptime = mClocks.uptimeMillis();
4494 addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
4495 pkgName, 0);
4496 PackageChange pc = new PackageChange();
4497 pc.mPackageName = pkgName;
4498 pc.mUpdate = true;
4499 addPackageChange(pc);
4500 }
4501
4502 private void addPackageChange(PackageChange pc) {
4503 if (mDailyPackageChanges == null) {
4504 mDailyPackageChanges = new ArrayList<>();
4505 }
4506 mDailyPackageChanges.add(pc);
4507 }
4508
4509 public void notePhoneOnLocked() {
4510 if (!mPhoneOn) {
4511 final long elapsedRealtime = mClocks.elapsedRealtime();
4512 final long uptime = mClocks.uptimeMillis();
4513 mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
4514 if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
4515 + Integer.toHexString(mHistoryCur.states));
4516 addHistoryRecordLocked(elapsedRealtime, uptime);
4517 mPhoneOn = true;
4518 mPhoneOnTimer.startRunningLocked(elapsedRealtime);
4519 }
4520 }
4521
4522 public void notePhoneOffLocked() {
4523 if (mPhoneOn) {
4524 final long elapsedRealtime = mClocks.elapsedRealtime();
4525 final long uptime = mClocks.uptimeMillis();
4526 mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
4527 if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
4528 + Integer.toHexString(mHistoryCur.states));
4529 addHistoryRecordLocked(elapsedRealtime, uptime);
4530 mPhoneOn = false;
4531 mPhoneOnTimer.stopRunningLocked(elapsedRealtime);
4532 }
4533 }
4534
4535 void stopAllPhoneSignalStrengthTimersLocked(int except) {
4536 final long elapsedRealtime = mClocks.elapsedRealtime();
4537 for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
4538 if (i == except) {
4539 continue;
4540 }
4541 while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
4542 mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
4543 }
4544 }
4545 }
4546
4547 private int fixPhoneServiceState(int state, int signalBin) {
4548 if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
4549 // In this case we will always be STATE_OUT_OF_SERVICE, so need
4550 // to infer that we are scanning from other data.
4551 if (state == ServiceState.STATE_OUT_OF_SERVICE
4552 && signalBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
4553 state = ServiceState.STATE_IN_SERVICE;
4554 }
4555 }
4556
4557 return state;
4558 }
4559
4560 private void updateAllPhoneStateLocked(int state, int simState, int strengthBin) {
4561 boolean scanning = false;
4562 boolean newHistory = false;
4563
4564 mPhoneServiceStateRaw = state;
4565 mPhoneSimStateRaw = simState;
4566 mPhoneSignalStrengthBinRaw = strengthBin;
4567
4568 final long elapsedRealtime = mClocks.elapsedRealtime();
4569 final long uptime = mClocks.uptimeMillis();
4570
4571 if (simState == TelephonyManager.SIM_STATE_ABSENT) {
4572 // In this case we will always be STATE_OUT_OF_SERVICE, so need
4573 // to infer that we are scanning from other data.
4574 if (state == ServiceState.STATE_OUT_OF_SERVICE
4575 && strengthBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
4576 state = ServiceState.STATE_IN_SERVICE;
4577 }
4578 }
4579
4580 // If the phone is powered off, stop all timers.
4581 if (state == ServiceState.STATE_POWER_OFF) {
4582 strengthBin = -1;
4583
4584 // If we are in service, make sure the correct signal string timer is running.
4585 } else if (state == ServiceState.STATE_IN_SERVICE) {
4586 // Bin will be changed below.
4587
4588 // If we're out of service, we are in the lowest signal strength
4589 // bin and have the scanning bit set.
4590 } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
4591 scanning = true;
4592 strengthBin = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
4593 if (!mPhoneSignalScanningTimer.isRunningLocked()) {
4594 mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
4595 newHistory = true;
4596 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
4597 + Integer.toHexString(mHistoryCur.states));
4598 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
4599 }
4600 }
4601
4602 if (!scanning) {
4603 // If we are no longer scanning, then stop the scanning timer.
4604 if (mPhoneSignalScanningTimer.isRunningLocked()) {
4605 mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
4606 if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
4607 + Integer.toHexString(mHistoryCur.states));
4608 newHistory = true;
4609 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
4610 }
4611 }
4612
4613 if (mPhoneServiceState != state) {
4614 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
4615 | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
4616 if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
4617 + Integer.toHexString(mHistoryCur.states));
4618 newHistory = true;
4619 mPhoneServiceState = state;
4620 }
4621
4622 if (mPhoneSignalStrengthBin != strengthBin) {
4623 if (mPhoneSignalStrengthBin >= 0) {
4624 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
4625 elapsedRealtime);
4626 }
4627 if (strengthBin >= 0) {
4628 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
4629 mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
4630 }
4631 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
4632 | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
4633 if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
4634 + Integer.toHexString(mHistoryCur.states));
4635 newHistory = true;
4636 } else {
4637 stopAllPhoneSignalStrengthTimersLocked(-1);
4638 }
4639 mPhoneSignalStrengthBin = strengthBin;
4640 }
4641
4642 if (newHistory) {
4643 addHistoryRecordLocked(elapsedRealtime, uptime);
4644 }
4645 }
4646
4647 /**
4648 * Telephony stack updates the phone state.
4649 * @param state phone state from ServiceState.getState()
4650 */
4651 public void notePhoneStateLocked(int state, int simState) {
4652 updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
4653 }
4654
4655 public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
4656 // Bin the strength.
4657 int bin = signalStrength.getLevel();
4658 updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
4659 }
4660
4661 public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
4662 int bin = DATA_CONNECTION_NONE;
4663 if (hasData) {
4664 switch (dataType) {
4665 case TelephonyManager.NETWORK_TYPE_EDGE:
4666 bin = DATA_CONNECTION_EDGE;
4667 break;
4668 case TelephonyManager.NETWORK_TYPE_GPRS:
4669 bin = DATA_CONNECTION_GPRS;
4670 break;
4671 case TelephonyManager.NETWORK_TYPE_UMTS:
4672 bin = DATA_CONNECTION_UMTS;
4673 break;
4674 case TelephonyManager.NETWORK_TYPE_CDMA:
4675 bin = DATA_CONNECTION_CDMA;
4676 break;
4677 case TelephonyManager.NETWORK_TYPE_EVDO_0:
4678 bin = DATA_CONNECTION_EVDO_0;
4679 break;
4680 case TelephonyManager.NETWORK_TYPE_EVDO_A:
4681 bin = DATA_CONNECTION_EVDO_A;
4682 break;
4683 case TelephonyManager.NETWORK_TYPE_1xRTT:
4684 bin = DATA_CONNECTION_1xRTT;
4685 break;
4686 case TelephonyManager.NETWORK_TYPE_HSDPA:
4687 bin = DATA_CONNECTION_HSDPA;
4688 break;
4689 case TelephonyManager.NETWORK_TYPE_HSUPA:
4690 bin = DATA_CONNECTION_HSUPA;
4691 break;
4692 case TelephonyManager.NETWORK_TYPE_HSPA:
4693 bin = DATA_CONNECTION_HSPA;
4694 break;
4695 case TelephonyManager.NETWORK_TYPE_IDEN:
4696 bin = DATA_CONNECTION_IDEN;
4697 break;
4698 case TelephonyManager.NETWORK_TYPE_EVDO_B:
4699 bin = DATA_CONNECTION_EVDO_B;
4700 break;
4701 case TelephonyManager.NETWORK_TYPE_LTE:
4702 bin = DATA_CONNECTION_LTE;
4703 break;
4704 case TelephonyManager.NETWORK_TYPE_EHRPD:
4705 bin = DATA_CONNECTION_EHRPD;
4706 break;
4707 case TelephonyManager.NETWORK_TYPE_HSPAP:
4708 bin = DATA_CONNECTION_HSPAP;
4709 break;
4710 default:
4711 bin = DATA_CONNECTION_OTHER;
4712 break;
4713 }
4714 }
4715 if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
4716 if (mPhoneDataConnectionType != bin) {
4717 final long elapsedRealtime = mClocks.elapsedRealtime();
4718 final long uptime = mClocks.uptimeMillis();
4719 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
4720 | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
4721 if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
4722 + Integer.toHexString(mHistoryCur.states));
4723 addHistoryRecordLocked(elapsedRealtime, uptime);
4724 if (mPhoneDataConnectionType >= 0) {
4725 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
4726 elapsedRealtime);
4727 }
4728 mPhoneDataConnectionType = bin;
4729 mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime);
4730 }
4731 }
4732
4733 public void noteWifiOnLocked() {
4734 if (!mWifiOn) {
4735 final long elapsedRealtime = mClocks.elapsedRealtime();
4736 final long uptime = mClocks.uptimeMillis();
4737 mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
4738 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
4739 + Integer.toHexString(mHistoryCur.states));
4740 addHistoryRecordLocked(elapsedRealtime, uptime);
4741 mWifiOn = true;
4742 mWifiOnTimer.startRunningLocked(elapsedRealtime);
4743 scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
4744 }
4745 }
4746
4747 public void noteWifiOffLocked() {
4748 final long elapsedRealtime = mClocks.elapsedRealtime();
4749 final long uptime = mClocks.uptimeMillis();
4750 if (mWifiOn) {
4751 mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
4752 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
4753 + Integer.toHexString(mHistoryCur.states));
4754 addHistoryRecordLocked(elapsedRealtime, uptime);
4755 mWifiOn = false;
4756 mWifiOnTimer.stopRunningLocked(elapsedRealtime);
4757 scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
4758 }
4759 }
4760
4761 public void noteAudioOnLocked(int uid) {
4762 uid = mapUid(uid);
4763 final long elapsedRealtime = mClocks.elapsedRealtime();
4764 final long uptime = mClocks.uptimeMillis();
4765 if (mAudioOnNesting == 0) {
4766 mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
4767 if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
4768 + Integer.toHexString(mHistoryCur.states));
4769 addHistoryRecordLocked(elapsedRealtime, uptime);
4770 mAudioOnTimer.startRunningLocked(elapsedRealtime);
4771 }
4772 mAudioOnNesting++;
4773 getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
4774 }
4775
4776 public void noteAudioOffLocked(int uid) {
4777 if (mAudioOnNesting == 0) {
4778 return;
4779 }
4780 uid = mapUid(uid);
4781 final long elapsedRealtime = mClocks.elapsedRealtime();
4782 final long uptime = mClocks.uptimeMillis();
4783 if (--mAudioOnNesting == 0) {
4784 mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
4785 if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
4786 + Integer.toHexString(mHistoryCur.states));
4787 addHistoryRecordLocked(elapsedRealtime, uptime);
4788 mAudioOnTimer.stopRunningLocked(elapsedRealtime);
4789 }
4790 getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
4791 }
4792
4793 public void noteVideoOnLocked(int uid) {
4794 uid = mapUid(uid);
4795 final long elapsedRealtime = mClocks.elapsedRealtime();
4796 final long uptime = mClocks.uptimeMillis();
4797 if (mVideoOnNesting == 0) {
4798 mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
4799 if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
4800 + Integer.toHexString(mHistoryCur.states));
4801 addHistoryRecordLocked(elapsedRealtime, uptime);
4802 mVideoOnTimer.startRunningLocked(elapsedRealtime);
4803 }
4804 mVideoOnNesting++;
4805 getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
4806 }
4807
4808 public void noteVideoOffLocked(int uid) {
4809 if (mVideoOnNesting == 0) {
4810 return;
4811 }
4812 uid = mapUid(uid);
4813 final long elapsedRealtime = mClocks.elapsedRealtime();
4814 final long uptime = mClocks.uptimeMillis();
4815 if (--mVideoOnNesting == 0) {
4816 mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
4817 if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
4818 + Integer.toHexString(mHistoryCur.states));
4819 addHistoryRecordLocked(elapsedRealtime, uptime);
4820 mVideoOnTimer.stopRunningLocked(elapsedRealtime);
4821 }
4822 getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime);
4823 }
4824
4825 public void noteResetAudioLocked() {
4826 if (mAudioOnNesting > 0) {
4827 final long elapsedRealtime = mClocks.elapsedRealtime();
4828 final long uptime = mClocks.uptimeMillis();
4829 mAudioOnNesting = 0;
4830 mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
4831 if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
4832 + Integer.toHexString(mHistoryCur.states));
4833 addHistoryRecordLocked(elapsedRealtime, uptime);
4834 mAudioOnTimer.stopAllRunningLocked(elapsedRealtime);
4835 for (int i=0; i<mUidStats.size(); i++) {
4836 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4837 uid.noteResetAudioLocked(elapsedRealtime);
4838 }
4839 }
4840 }
4841
4842 public void noteResetVideoLocked() {
4843 if (mVideoOnNesting > 0) {
4844 final long elapsedRealtime = mClocks.elapsedRealtime();
4845 final long uptime = mClocks.uptimeMillis();
4846 mAudioOnNesting = 0;
4847 mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
4848 if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
4849 + Integer.toHexString(mHistoryCur.states));
4850 addHistoryRecordLocked(elapsedRealtime, uptime);
4851 mVideoOnTimer.stopAllRunningLocked(elapsedRealtime);
4852 for (int i=0; i<mUidStats.size(); i++) {
4853 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4854 uid.noteResetVideoLocked(elapsedRealtime);
4855 }
4856 }
4857 }
4858
4859 public void noteActivityResumedLocked(int uid) {
4860 uid = mapUid(uid);
4861 getUidStatsLocked(uid).noteActivityResumedLocked(mClocks.elapsedRealtime());
4862 }
4863
4864 public void noteActivityPausedLocked(int uid) {
4865 uid = mapUid(uid);
4866 getUidStatsLocked(uid).noteActivityPausedLocked(mClocks.elapsedRealtime());
4867 }
4868
4869 public void noteVibratorOnLocked(int uid, long durationMillis) {
4870 uid = mapUid(uid);
4871 getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis);
4872 }
4873
4874 public void noteVibratorOffLocked(int uid) {
4875 uid = mapUid(uid);
4876 getUidStatsLocked(uid).noteVibratorOffLocked();
4877 }
4878
4879 public void noteFlashlightOnLocked(int uid) {
4880 uid = mapUid(uid);
4881 final long elapsedRealtime = mClocks.elapsedRealtime();
4882 final long uptime = mClocks.uptimeMillis();
4883 if (mFlashlightOnNesting++ == 0) {
4884 mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
4885 if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
4886 + Integer.toHexString(mHistoryCur.states2));
4887 addHistoryRecordLocked(elapsedRealtime, uptime);
4888 mFlashlightOnTimer.startRunningLocked(elapsedRealtime);
4889 }
4890 getUidStatsLocked(uid).noteFlashlightTurnedOnLocked(elapsedRealtime);
4891 }
4892
4893 public void noteFlashlightOffLocked(int uid) {
4894 if (mFlashlightOnNesting == 0) {
4895 return;
4896 }
4897 uid = mapUid(uid);
4898 final long elapsedRealtime = mClocks.elapsedRealtime();
4899 final long uptime = mClocks.uptimeMillis();
4900 if (--mFlashlightOnNesting == 0) {
4901 mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
4902 if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
4903 + Integer.toHexString(mHistoryCur.states2));
4904 addHistoryRecordLocked(elapsedRealtime, uptime);
4905 mFlashlightOnTimer.stopRunningLocked(elapsedRealtime);
4906 }
4907 getUidStatsLocked(uid).noteFlashlightTurnedOffLocked(elapsedRealtime);
4908 }
4909
4910 public void noteCameraOnLocked(int uid) {
4911 uid = mapUid(uid);
4912 final long elapsedRealtime = mClocks.elapsedRealtime();
4913 final long uptime = mClocks.uptimeMillis();
4914 if (mCameraOnNesting++ == 0) {
4915 mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
4916 if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
4917 + Integer.toHexString(mHistoryCur.states2));
4918 addHistoryRecordLocked(elapsedRealtime, uptime);
4919 mCameraOnTimer.startRunningLocked(elapsedRealtime);
4920 }
4921 getUidStatsLocked(uid).noteCameraTurnedOnLocked(elapsedRealtime);
4922 }
4923
4924 public void noteCameraOffLocked(int uid) {
4925 if (mCameraOnNesting == 0) {
4926 return;
4927 }
4928 uid = mapUid(uid);
4929 final long elapsedRealtime = mClocks.elapsedRealtime();
4930 final long uptime = mClocks.uptimeMillis();
4931 if (--mCameraOnNesting == 0) {
4932 mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
4933 if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
4934 + Integer.toHexString(mHistoryCur.states2));
4935 addHistoryRecordLocked(elapsedRealtime, uptime);
4936 mCameraOnTimer.stopRunningLocked(elapsedRealtime);
4937 }
4938 getUidStatsLocked(uid).noteCameraTurnedOffLocked(elapsedRealtime);
4939 }
4940
4941 public void noteResetCameraLocked() {
4942 if (mCameraOnNesting > 0) {
4943 final long elapsedRealtime = mClocks.elapsedRealtime();
4944 final long uptime = mClocks.uptimeMillis();
4945 mCameraOnNesting = 0;
4946 mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
4947 if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
4948 + Integer.toHexString(mHistoryCur.states2));
4949 addHistoryRecordLocked(elapsedRealtime, uptime);
4950 mCameraOnTimer.stopAllRunningLocked(elapsedRealtime);
4951 for (int i=0; i<mUidStats.size(); i++) {
4952 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4953 uid.noteResetCameraLocked(elapsedRealtime);
4954 }
4955 }
4956 }
4957
4958 public void noteResetFlashlightLocked() {
4959 if (mFlashlightOnNesting > 0) {
4960 final long elapsedRealtime = mClocks.elapsedRealtime();
4961 final long uptime = mClocks.uptimeMillis();
4962 mFlashlightOnNesting = 0;
4963 mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
4964 if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
4965 + Integer.toHexString(mHistoryCur.states2));
4966 addHistoryRecordLocked(elapsedRealtime, uptime);
4967 mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtime);
4968 for (int i=0; i<mUidStats.size(); i++) {
4969 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4970 uid.noteResetFlashlightLocked(elapsedRealtime);
4971 }
4972 }
4973 }
4974
4975 private void noteBluetoothScanStartedLocked(int uid, boolean isUnoptimized) {
4976 uid = mapUid(uid);
4977 final long elapsedRealtime = mClocks.elapsedRealtime();
4978 final long uptime = mClocks.uptimeMillis();
4979 if (mBluetoothScanNesting == 0) {
4980 mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
4981 if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
4982 + Integer.toHexString(mHistoryCur.states2));
4983 addHistoryRecordLocked(elapsedRealtime, uptime);
4984 mBluetoothScanTimer.startRunningLocked(elapsedRealtime);
4985 }
4986 mBluetoothScanNesting++;
4987 getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime, isUnoptimized);
4988 }
4989
4990 public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
4991 final int N = ws.size();
4992 for (int i = 0; i < N; i++) {
4993 noteBluetoothScanStartedLocked(ws.get(i), isUnoptimized);
4994 }
4995 }
4996
4997 private void noteBluetoothScanStoppedLocked(int uid, boolean isUnoptimized) {
4998 uid = mapUid(uid);
4999 final long elapsedRealtime = mClocks.elapsedRealtime();
5000 final long uptime = mClocks.uptimeMillis();
5001 mBluetoothScanNesting--;
5002 if (mBluetoothScanNesting == 0) {
5003 mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5004 if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
5005 + Integer.toHexString(mHistoryCur.states2));
5006 addHistoryRecordLocked(elapsedRealtime, uptime);
5007 mBluetoothScanTimer.stopRunningLocked(elapsedRealtime);
5008 }
5009 getUidStatsLocked(uid).noteBluetoothScanStoppedLocked(elapsedRealtime, isUnoptimized);
5010 }
5011
5012 public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
5013 final int N = ws.size();
5014 for (int i = 0; i < N; i++) {
5015 noteBluetoothScanStoppedLocked(ws.get(i), isUnoptimized);
5016 }
5017 }
5018
5019 public void noteResetBluetoothScanLocked() {
5020 if (mBluetoothScanNesting > 0) {
5021 final long elapsedRealtime = mClocks.elapsedRealtime();
5022 final long uptime = mClocks.uptimeMillis();
5023 mBluetoothScanNesting = 0;
5024 mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
5025 if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
5026 + Integer.toHexString(mHistoryCur.states2));
5027 addHistoryRecordLocked(elapsedRealtime, uptime);
5028 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtime);
5029 for (int i=0; i<mUidStats.size(); i++) {
5030 BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
5031 uid.noteResetBluetoothScanLocked(elapsedRealtime);
5032 }
5033 }
5034 }
5035
5036 public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
5037 final int N = ws.size();
5038 for (int i = 0; i < N; i++) {
5039 int uid = mapUid(ws.get(i));
5040 getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
5041 }
5042 }
5043
5044 private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
5045 final long uptimeMillis, int uid) {
5046 uid = mapUid(uid);
5047 addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
5048 uid);
5049 getUidStatsLocked(uid).noteWifiRadioApWakeupLocked();
5050 }
5051
5052 public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) {
5053 final long elapsedRealtime = mClocks.elapsedRealtime();
5054 final long uptime = mClocks.uptimeMillis();
5055 if (mWifiRadioPowerState != powerState) {
5056 final boolean active =
5057 powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
5058 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
5059 if (active) {
5060 if (uid > 0) {
5061 noteWifiRadioApWakeupLocked(elapsedRealtime, uptime, uid);
5062 }
5063 mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
5064 } else {
5065 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
5066 }
5067 if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
5068 + Integer.toHexString(mHistoryCur.states));
5069 addHistoryRecordLocked(elapsedRealtime, uptime);
5070 mWifiRadioPowerState = powerState;
5071 }
5072 }
5073
5074 public void noteWifiRunningLocked(WorkSource ws) {
5075 if (!mGlobalWifiRunning) {
5076 final long elapsedRealtime = mClocks.elapsedRealtime();
5077 final long uptime = mClocks.uptimeMillis();
5078 mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
5079 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
5080 + Integer.toHexString(mHistoryCur.states));
5081 addHistoryRecordLocked(elapsedRealtime, uptime);
5082 mGlobalWifiRunning = true;
5083 mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
5084 int N = ws.size();
5085 for (int i=0; i<N; i++) {
5086 int uid = mapUid(ws.get(i));
5087 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5088 }
5089 scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
5090 } else {
5091 Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
5092 }
5093 }
5094
5095 public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
5096 if (mGlobalWifiRunning) {
5097 final long elapsedRealtime = mClocks.elapsedRealtime();
5098 int N = oldWs.size();
5099 for (int i=0; i<N; i++) {
5100 int uid = mapUid(oldWs.get(i));
5101 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5102 }
5103 N = newWs.size();
5104 for (int i=0; i<N; i++) {
5105 int uid = mapUid(newWs.get(i));
5106 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
5107 }
5108 } else {
5109 Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
5110 }
5111 }
5112
5113 public void noteWifiStoppedLocked(WorkSource ws) {
5114 if (mGlobalWifiRunning) {
5115 final long elapsedRealtime = mClocks.elapsedRealtime();
5116 final long uptime = mClocks.uptimeMillis();
5117 mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
5118 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
5119 + Integer.toHexString(mHistoryCur.states));
5120 addHistoryRecordLocked(elapsedRealtime, uptime);
5121 mGlobalWifiRunning = false;
5122 mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
5123 int N = ws.size();
5124 for (int i=0; i<N; i++) {
5125 int uid = mapUid(ws.get(i));
5126 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
5127 }
5128 scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
5129 } else {
5130 Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
5131 }
5132 }
5133
5134 public void noteWifiStateLocked(int wifiState, String accessPoint) {
5135 if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
5136 if (mWifiState != wifiState) {
5137 final long elapsedRealtime = mClocks.elapsedRealtime();
5138 if (mWifiState >= 0) {
5139 mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
5140 }
5141 mWifiState = wifiState;
5142 mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
5143 scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
5144 }
5145 }
5146
5147 public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
5148 if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
5149 if (mWifiSupplState != supplState) {
5150 final long elapsedRealtime = mClocks.elapsedRealtime();
5151 final long uptime = mClocks.uptimeMillis();
5152 if (mWifiSupplState >= 0) {
5153 mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime);
5154 }
5155 mWifiSupplState = supplState;
5156 mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtime);
5157 mHistoryCur.states2 =
5158 (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
5159 | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
5160 if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
5161 + Integer.toHexString(mHistoryCur.states2));
5162 addHistoryRecordLocked(elapsedRealtime, uptime);
5163 }
5164 }
5165
5166 void stopAllWifiSignalStrengthTimersLocked(int except) {
5167 final long elapsedRealtime = mClocks.elapsedRealtime();
5168 for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
5169 if (i == except) {
5170 continue;
5171 }
5172 while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
5173 mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
5174 }
5175 }
5176 }
5177
5178 public void noteWifiRssiChangedLocked(int newRssi) {
5179 int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
5180 if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
5181 if (mWifiSignalStrengthBin != strengthBin) {
5182 final long elapsedRealtime = mClocks.elapsedRealtime();
5183 final long uptime = mClocks.uptimeMillis();
5184 if (mWifiSignalStrengthBin >= 0) {
5185 mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
5186 elapsedRealtime);
5187 }
5188 if (strengthBin >= 0) {
5189 if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
5190 mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
5191 }
5192 mHistoryCur.states2 =
5193 (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
5194 | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
5195 if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
5196 + Integer.toHexString(mHistoryCur.states2));
5197 addHistoryRecordLocked(elapsedRealtime, uptime);
5198 } else {
5199 stopAllWifiSignalStrengthTimersLocked(-1);
5200 }
5201 mWifiSignalStrengthBin = strengthBin;
5202 }
5203 }
5204
5205 int mWifiFullLockNesting = 0;
5206
5207 public void noteFullWifiLockAcquiredLocked(int uid) {
5208 uid = mapUid(uid);
5209 final long elapsedRealtime = mClocks.elapsedRealtime();
5210 final long uptime = mClocks.uptimeMillis();
5211 if (mWifiFullLockNesting == 0) {
5212 mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
5213 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
5214 + Integer.toHexString(mHistoryCur.states));
5215 addHistoryRecordLocked(elapsedRealtime, uptime);
5216 }
5217 mWifiFullLockNesting++;
5218 getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
5219 }
5220
5221 public void noteFullWifiLockReleasedLocked(int uid) {
5222 uid = mapUid(uid);
5223 final long elapsedRealtime = mClocks.elapsedRealtime();
5224 final long uptime = mClocks.uptimeMillis();
5225 mWifiFullLockNesting--;
5226 if (mWifiFullLockNesting == 0) {
5227 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
5228 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
5229 + Integer.toHexString(mHistoryCur.states));
5230 addHistoryRecordLocked(elapsedRealtime, uptime);
5231 }
5232 getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime);
5233 }
5234
5235 int mWifiScanNesting = 0;
5236
5237 public void noteWifiScanStartedLocked(int uid) {
5238 uid = mapUid(uid);
5239 final long elapsedRealtime = mClocks.elapsedRealtime();
5240 final long uptime = mClocks.uptimeMillis();
5241 if (mWifiScanNesting == 0) {
5242 mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
5243 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
5244 + Integer.toHexString(mHistoryCur.states));
5245 addHistoryRecordLocked(elapsedRealtime, uptime);
5246 }
5247 mWifiScanNesting++;
5248 getUidStatsLocked(uid).noteWifiScanStartedLocked(elapsedRealtime);
5249 }
5250
5251 public void noteWifiScanStoppedLocked(int uid) {
5252 uid = mapUid(uid);
5253 final long elapsedRealtime = mClocks.elapsedRealtime();
5254 final long uptime = mClocks.uptimeMillis();
5255 mWifiScanNesting--;
5256 if (mWifiScanNesting == 0) {
5257 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
5258 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
5259 + Integer.toHexString(mHistoryCur.states));
5260 addHistoryRecordLocked(elapsedRealtime, uptime);
5261 }
5262 getUidStatsLocked(uid).noteWifiScanStoppedLocked(elapsedRealtime);
5263 }
5264
5265 public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
5266 uid = mapUid(uid);
5267 final long elapsedRealtime = mClocks.elapsedRealtime();
5268 getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime);
5269 }
5270
5271 public void noteWifiBatchedScanStoppedLocked(int uid) {
5272 uid = mapUid(uid);
5273 final long elapsedRealtime = mClocks.elapsedRealtime();
5274 getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime);
5275 }
5276
5277 int mWifiMulticastNesting = 0;
5278
5279 public void noteWifiMulticastEnabledLocked(int uid) {
5280 uid = mapUid(uid);
5281 final long elapsedRealtime = mClocks.elapsedRealtime();
5282 final long uptime = mClocks.uptimeMillis();
5283 if (mWifiMulticastNesting == 0) {
5284 mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
5285 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
5286 + Integer.toHexString(mHistoryCur.states));
5287 addHistoryRecordLocked(elapsedRealtime, uptime);
5288 }
5289 mWifiMulticastNesting++;
5290 getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
5291 }
5292
5293 public void noteWifiMulticastDisabledLocked(int uid) {
5294 uid = mapUid(uid);
5295 final long elapsedRealtime = mClocks.elapsedRealtime();
5296 final long uptime = mClocks.uptimeMillis();
5297 mWifiMulticastNesting--;
5298 if (mWifiMulticastNesting == 0) {
5299 mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
5300 if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
5301 + Integer.toHexString(mHistoryCur.states));
5302 addHistoryRecordLocked(elapsedRealtime, uptime);
5303 }
5304 getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime);
5305 }
5306
5307 public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
5308 int N = ws.size();
5309 for (int i=0; i<N; i++) {
5310 noteFullWifiLockAcquiredLocked(ws.get(i));
5311 }
5312 }
5313
5314 public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
5315 int N = ws.size();
5316 for (int i=0; i<N; i++) {
5317 noteFullWifiLockReleasedLocked(ws.get(i));
5318 }
5319 }
5320
5321 public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
5322 int N = ws.size();
5323 for (int i=0; i<N; i++) {
5324 noteWifiScanStartedLocked(ws.get(i));
5325 }
5326 }
5327
5328 public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
5329 int N = ws.size();
5330 for (int i=0; i<N; i++) {
5331 noteWifiScanStoppedLocked(ws.get(i));
5332 }
5333 }
5334
5335 public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
5336 int N = ws.size();
5337 for (int i=0; i<N; i++) {
5338 noteWifiBatchedScanStartedLocked(ws.get(i), csph);
5339 }
5340 }
5341
5342 public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
5343 int N = ws.size();
5344 for (int i=0; i<N; i++) {
5345 noteWifiBatchedScanStoppedLocked(ws.get(i));
5346 }
5347 }
5348
5349 public void noteWifiMulticastEnabledFromSourceLocked(WorkSource ws) {
5350 int N = ws.size();
5351 for (int i=0; i<N; i++) {
5352 noteWifiMulticastEnabledLocked(ws.get(i));
5353 }
5354 }
5355
5356 public void noteWifiMulticastDisabledFromSourceLocked(WorkSource ws) {
5357 int N = ws.size();
5358 for (int i=0; i<N; i++) {
5359 noteWifiMulticastDisabledLocked(ws.get(i));
5360 }
5361 }
5362
5363 private static String[] includeInStringArray(String[] array, String str) {
5364 if (ArrayUtils.indexOf(array, str) >= 0) {
5365 return array;
5366 }
5367 String[] newArray = new String[array.length+1];
5368 System.arraycopy(array, 0, newArray, 0, array.length);
5369 newArray[array.length] = str;
5370 return newArray;
5371 }
5372
5373 private static String[] excludeFromStringArray(String[] array, String str) {
5374 int index = ArrayUtils.indexOf(array, str);
5375 if (index >= 0) {
5376 String[] newArray = new String[array.length-1];
5377 if (index > 0) {
5378 System.arraycopy(array, 0, newArray, 0, index);
5379 }
5380 if (index < array.length-1) {
5381 System.arraycopy(array, index+1, newArray, index, array.length-index-1);
5382 }
5383 return newArray;
5384 }
5385 return array;
5386 }
5387
5388 public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
5389 if (TextUtils.isEmpty(iface)) return;
5390
5391 synchronized (mModemNetworkLock) {
5392 if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
5393 mModemIfaces = includeInStringArray(mModemIfaces, iface);
5394 if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mModemIfaces);
5395 } else {
5396 mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
5397 if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mModemIfaces);
5398 }
5399 }
5400
5401 synchronized (mWifiNetworkLock) {
5402 if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
5403 mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
5404 if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
5405 } else {
5406 mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
5407 if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
5408 }
5409 }
5410 }
5411
5412 @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
5413 return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5414 }
5415
5416 @Override public int getScreenOnCount(int which) {
5417 return mScreenOnTimer.getCountLocked(which);
5418 }
5419
Justin Klaassen93b7ee42017-10-10 15:20:13 -04005420 @Override public long getScreenDozeTime(long elapsedRealtimeUs, int which) {
5421 return mScreenDozeTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5422 }
5423
5424 @Override public int getScreenDozeCount(int which) {
5425 return mScreenDozeTimer.getCountLocked(which);
5426 }
5427
Justin Klaassen10d07c82017-09-15 17:58:39 -04005428 @Override public long getScreenBrightnessTime(int brightnessBin,
5429 long elapsedRealtimeUs, int which) {
5430 return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
5431 elapsedRealtimeUs, which);
5432 }
5433
Justin Klaassen47ed54e2017-10-24 19:50:40 -04005434 @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
5435 return mScreenBrightnessTimer[brightnessBin];
5436 }
5437
Justin Klaassen10d07c82017-09-15 17:58:39 -04005438 @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
5439 return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5440 }
5441
5442 @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
5443 return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5444 }
5445
5446 @Override public int getPowerSaveModeEnabledCount(int which) {
5447 return mPowerSaveModeEnabledTimer.getCountLocked(which);
5448 }
5449
5450 @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
5451 int which) {
5452 switch (mode) {
5453 case DEVICE_IDLE_MODE_LIGHT:
5454 return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5455 case DEVICE_IDLE_MODE_DEEP:
5456 return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5457 }
5458 return 0;
5459 }
5460
5461 @Override public int getDeviceIdleModeCount(int mode, int which) {
5462 switch (mode) {
5463 case DEVICE_IDLE_MODE_LIGHT:
5464 return mDeviceIdleModeLightTimer.getCountLocked(which);
5465 case DEVICE_IDLE_MODE_DEEP:
5466 return mDeviceIdleModeFullTimer.getCountLocked(which);
5467 }
5468 return 0;
5469 }
5470
5471 @Override public long getLongestDeviceIdleModeTime(int mode) {
5472 switch (mode) {
5473 case DEVICE_IDLE_MODE_LIGHT:
5474 return mLongestLightIdleTime;
5475 case DEVICE_IDLE_MODE_DEEP:
5476 return mLongestFullIdleTime;
5477 }
5478 return 0;
5479 }
5480
5481 @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
5482 switch (mode) {
5483 case DEVICE_IDLE_MODE_LIGHT:
5484 return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5485 case DEVICE_IDLE_MODE_DEEP:
5486 return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5487 }
5488 return 0;
5489 }
5490
5491 @Override public int getDeviceIdlingCount(int mode, int which) {
5492 switch (mode) {
5493 case DEVICE_IDLE_MODE_LIGHT:
5494 return mDeviceLightIdlingTimer.getCountLocked(which);
5495 case DEVICE_IDLE_MODE_DEEP:
5496 return mDeviceIdlingTimer.getCountLocked(which);
5497 }
5498 return 0;
5499 }
5500
5501 @Override public int getNumConnectivityChange(int which) {
5502 int val = mNumConnectivityChange;
5503 if (which == STATS_CURRENT) {
5504 val -= mLoadedNumConnectivityChange;
5505 } else if (which == STATS_SINCE_UNPLUGGED) {
5506 val -= mUnpluggedNumConnectivityChange;
5507 }
5508 return val;
5509 }
5510
5511 @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
5512 return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5513 }
5514
5515 @Override public int getPhoneOnCount(int which) {
5516 return mPhoneOnTimer.getCountLocked(which);
5517 }
5518
5519 @Override public long getPhoneSignalStrengthTime(int strengthBin,
5520 long elapsedRealtimeUs, int which) {
5521 return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
5522 elapsedRealtimeUs, which);
5523 }
5524
5525 @Override public long getPhoneSignalScanningTime(
5526 long elapsedRealtimeUs, int which) {
5527 return mPhoneSignalScanningTimer.getTotalTimeLocked(
5528 elapsedRealtimeUs, which);
5529 }
5530
Justin Klaassen47ed54e2017-10-24 19:50:40 -04005531 @Override public Timer getPhoneSignalScanningTimer() {
5532 return mPhoneSignalScanningTimer;
5533 }
5534
Justin Klaassen10d07c82017-09-15 17:58:39 -04005535 @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
5536 return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
5537 }
5538
Justin Klaassen47ed54e2017-10-24 19:50:40 -04005539 @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
5540 return mPhoneSignalStrengthsTimer[strengthBin];
5541 }
5542
Justin Klaassen10d07c82017-09-15 17:58:39 -04005543 @Override public long getPhoneDataConnectionTime(int dataType,
5544 long elapsedRealtimeUs, int which) {
5545 return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
5546 elapsedRealtimeUs, which);
5547 }
5548
5549 @Override public int getPhoneDataConnectionCount(int dataType, int which) {
5550 return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
5551 }
5552
Justin Klaassen47ed54e2017-10-24 19:50:40 -04005553 @Override public Timer getPhoneDataConnectionTimer(int dataType) {
5554 return mPhoneDataConnectionsTimer[dataType];
5555 }
5556
Justin Klaassen10d07c82017-09-15 17:58:39 -04005557 @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
5558 return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5559 }
5560
5561 @Override public int getMobileRadioActiveCount(int which) {
5562 return mMobileRadioActiveTimer.getCountLocked(which);
5563 }
5564
5565 @Override public long getMobileRadioActiveAdjustedTime(int which) {
5566 return mMobileRadioActiveAdjustedTime.getCountLocked(which);
5567 }
5568
5569 @Override public long getMobileRadioActiveUnknownTime(int which) {
5570 return mMobileRadioActiveUnknownTime.getCountLocked(which);
5571 }
5572
5573 @Override public int getMobileRadioActiveUnknownCount(int which) {
5574 return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
5575 }
5576
5577 @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
5578 return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5579 }
5580
5581 @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
5582 return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5583 }
5584
5585 @Override public long getWifiStateTime(int wifiState,
5586 long elapsedRealtimeUs, int which) {
5587 return mWifiStateTimer[wifiState].getTotalTimeLocked(
5588 elapsedRealtimeUs, which);
5589 }
5590
5591 @Override public int getWifiStateCount(int wifiState, int which) {
5592 return mWifiStateTimer[wifiState].getCountLocked(which);
5593 }
5594
Justin Klaassen47ed54e2017-10-24 19:50:40 -04005595 @Override public Timer getWifiStateTimer(int wifiState) {
5596 return mWifiStateTimer[wifiState];
5597 }
5598
Justin Klaassen10d07c82017-09-15 17:58:39 -04005599 @Override public long getWifiSupplStateTime(int state,
5600 long elapsedRealtimeUs, int which) {
5601 return mWifiSupplStateTimer[state].getTotalTimeLocked(
5602 elapsedRealtimeUs, which);
5603 }
5604
5605 @Override public int getWifiSupplStateCount(int state, int which) {
5606 return mWifiSupplStateTimer[state].getCountLocked(which);
5607 }
5608
Justin Klaassen47ed54e2017-10-24 19:50:40 -04005609 @Override public Timer getWifiSupplStateTimer(int state) {
5610 return mWifiSupplStateTimer[state];
5611 }
5612
Justin Klaassen10d07c82017-09-15 17:58:39 -04005613 @Override public long getWifiSignalStrengthTime(int strengthBin,
5614 long elapsedRealtimeUs, int which) {
5615 return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
5616 elapsedRealtimeUs, which);
5617 }
5618
5619 @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
5620 return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
5621 }
5622
Justin Klaassen47ed54e2017-10-24 19:50:40 -04005623 @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
5624 return mWifiSignalStrengthsTimer[strengthBin];
5625 }
5626
Justin Klaassen10d07c82017-09-15 17:58:39 -04005627 @Override
5628 public ControllerActivityCounter getBluetoothControllerActivity() {
5629 return mBluetoothActivity;
5630 }
5631
5632 @Override
5633 public ControllerActivityCounter getWifiControllerActivity() {
5634 return mWifiActivity;
5635 }
5636
5637 @Override
5638 public ControllerActivityCounter getModemControllerActivity() {
5639 return mModemActivity;
5640 }
5641
5642 @Override
5643 public boolean hasBluetoothActivityReporting() {
5644 return mHasBluetoothReporting;
5645 }
5646
5647 @Override
5648 public boolean hasWifiActivityReporting() {
5649 return mHasWifiReporting;
5650 }
5651
5652 @Override
5653 public boolean hasModemActivityReporting() {
5654 return mHasModemReporting;
5655 }
5656
5657 @Override
5658 public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
5659 return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5660 }
5661
5662 @Override
5663 public long getFlashlightOnCount(int which) {
5664 return mFlashlightOnTimer.getCountLocked(which);
5665 }
5666
5667 @Override
5668 public long getCameraOnTime(long elapsedRealtimeUs, int which) {
5669 return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5670 }
5671
5672 @Override
5673 public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
5674 return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5675 }
5676
5677 @Override
5678 public long getNetworkActivityBytes(int type, int which) {
5679 if (type >= 0 && type < mNetworkByteActivityCounters.length) {
5680 return mNetworkByteActivityCounters[type].getCountLocked(which);
5681 } else {
5682 return 0;
5683 }
5684 }
5685
5686 @Override
5687 public long getNetworkActivityPackets(int type, int which) {
5688 if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
5689 return mNetworkPacketActivityCounters[type].getCountLocked(which);
5690 } else {
5691 return 0;
5692 }
5693 }
5694
5695 @Override public long getStartClockTime() {
5696 final long currentTime = System.currentTimeMillis();
5697 if (ensureStartClockTime(currentTime)) {
5698 recordCurrentTimeChangeLocked(currentTime, mClocks.elapsedRealtime(),
5699 mClocks.uptimeMillis());
5700 }
5701 return mStartClockTime;
5702 }
5703
5704 @Override public String getStartPlatformVersion() {
5705 return mStartPlatformVersion;
5706 }
5707
5708 @Override public String getEndPlatformVersion() {
5709 return mEndPlatformVersion;
5710 }
5711
5712 @Override public int getParcelVersion() {
5713 return VERSION;
5714 }
5715
5716 @Override public boolean getIsOnBattery() {
5717 return mOnBattery;
5718 }
5719
5720 @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
5721 return mUidStats;
5722 }
5723
5724 private static void detachTimerIfNotNull(BatteryStatsImpl.Timer timer) {
5725 if (timer != null) {
5726 timer.detach();
5727 }
5728 }
5729
5730 private static boolean resetTimerIfNotNull(BatteryStatsImpl.Timer timer,
5731 boolean detachIfReset) {
5732 if (timer != null) {
5733 return timer.reset(detachIfReset);
5734 }
5735 return true;
5736 }
5737
5738 private static boolean resetTimerIfNotNull(DualTimer timer, boolean detachIfReset) {
5739 if (timer != null) {
5740 return timer.reset(detachIfReset);
5741 }
5742 return true;
5743 }
5744
5745 private static void detachLongCounterIfNotNull(LongSamplingCounter counter) {
5746 if (counter != null) {
5747 counter.detach();
5748 }
5749 }
5750
5751 private static void resetLongCounterIfNotNull(LongSamplingCounter counter,
5752 boolean detachIfReset) {
5753 if (counter != null) {
5754 counter.reset(detachIfReset);
5755 }
5756 }
5757
5758 /**
5759 * The statistics associated with a particular uid.
5760 */
5761 public static class Uid extends BatteryStats.Uid {
5762 /**
5763 * BatteryStatsImpl that we are associated with.
5764 */
5765 protected BatteryStatsImpl mBsi;
5766
5767 final int mUid;
5768
5769 /** TimeBase for when uid is in background and device is on battery. */
5770 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
5771 public final TimeBase mOnBatteryBackgroundTimeBase;
5772 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
5773 public final TimeBase mOnBatteryScreenOffBackgroundTimeBase;
5774
5775 boolean mWifiRunning;
5776 StopwatchTimer mWifiRunningTimer;
5777
5778 boolean mFullWifiLockOut;
5779 StopwatchTimer mFullWifiLockTimer;
5780
5781 boolean mWifiScanStarted;
5782 DualTimer mWifiScanTimer;
5783
5784 static final int NO_BATCHED_SCAN_STARTED = -1;
5785 int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
5786 StopwatchTimer[] mWifiBatchedScanTimer;
5787
5788 boolean mWifiMulticastEnabled;
5789 StopwatchTimer mWifiMulticastTimer;
5790
5791 StopwatchTimer mAudioTurnedOnTimer;
5792 StopwatchTimer mVideoTurnedOnTimer;
5793 StopwatchTimer mFlashlightTurnedOnTimer;
5794 StopwatchTimer mCameraTurnedOnTimer;
5795 StopwatchTimer mForegroundActivityTimer;
5796 StopwatchTimer mForegroundServiceTimer;
5797 /** Total time spent by the uid holding any partial wakelocks. */
5798 DualTimer mAggregatedPartialWakelockTimer;
5799 DualTimer mBluetoothScanTimer;
5800 DualTimer mBluetoothUnoptimizedScanTimer;
5801 Counter mBluetoothScanResultCounter;
5802 Counter mBluetoothScanResultBgCounter;
5803
5804 int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
5805 StopwatchTimer[] mProcessStateTimer;
5806
5807 boolean mInForegroundService = false;
5808
5809 BatchTimer mVibratorOnTimer;
5810
5811 Counter[] mUserActivityCounters;
5812
5813 LongSamplingCounter[] mNetworkByteActivityCounters;
5814 LongSamplingCounter[] mNetworkPacketActivityCounters;
5815 LongSamplingCounter mMobileRadioActiveTime;
5816 LongSamplingCounter mMobileRadioActiveCount;
5817
5818 /**
5819 * How many times this UID woke up the Application Processor due to a Mobile radio packet.
5820 */
5821 private LongSamplingCounter mMobileRadioApWakeupCount;
5822
5823 /**
5824 * How many times this UID woke up the Application Processor due to a Wifi packet.
5825 */
5826 private LongSamplingCounter mWifiRadioApWakeupCount;
5827
5828 /**
5829 * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
5830 * Can be null if the UID has had no such activity.
5831 */
5832 private ControllerActivityCounterImpl mWifiControllerActivity;
5833
5834 /**
5835 * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
5836 * Can be null if the UID has had no such activity.
5837 */
5838 private ControllerActivityCounterImpl mBluetoothControllerActivity;
5839
5840 /**
5841 * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
5842 * Can be null if the UID has had no such activity.
5843 */
5844 private ControllerActivityCounterImpl mModemControllerActivity;
5845
5846 /**
5847 * The CPU times we had at the last history details update.
5848 */
5849 long mLastStepUserTime;
5850 long mLastStepSystemTime;
5851 long mCurStepUserTime;
5852 long mCurStepSystemTime;
5853
5854 LongSamplingCounter mUserCpuTime;
5855 LongSamplingCounter mSystemCpuTime;
5856 LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
5857
5858 LongSamplingCounterArray mCpuFreqTimeMs;
5859 LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
5860
5861 /**
5862 * The statistics we have collected for this uid's wake locks.
5863 */
5864 final OverflowArrayMap<Wakelock> mWakelockStats;
5865
5866 /**
5867 * The statistics we have collected for this uid's syncs.
5868 */
5869 final OverflowArrayMap<DualTimer> mSyncStats;
5870
5871 /**
5872 * The statistics we have collected for this uid's jobs.
5873 */
5874 final OverflowArrayMap<DualTimer> mJobStats;
5875
5876 /**
5877 * Count of the jobs that have completed and the reasons why they completed.
5878 */
5879 final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
5880
5881 /**
5882 * The statistics we have collected for this uid's sensor activations.
5883 */
5884 final SparseArray<Sensor> mSensorStats = new SparseArray<>();
5885
5886 /**
5887 * The statistics we have collected for this uid's processes.
5888 */
5889 final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
5890
5891 /**
5892 * The statistics we have collected for this uid's processes.
5893 */
5894 final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
5895
5896 /**
5897 * The transient wake stats we have collected for this uid's pids.
5898 */
5899 final SparseArray<Pid> mPids = new SparseArray<>();
5900
5901 public Uid(BatteryStatsImpl bsi, int uid) {
5902 mBsi = bsi;
5903 mUid = uid;
5904
5905 mOnBatteryBackgroundTimeBase = new TimeBase();
5906 mOnBatteryBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
5907 mBsi.mClocks.elapsedRealtime() * 1000);
5908
5909 mOnBatteryScreenOffBackgroundTimeBase = new TimeBase();
5910 mOnBatteryScreenOffBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
5911 mBsi.mClocks.elapsedRealtime() * 1000);
5912
5913 mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
5914 mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
5915
5916 mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
5917 @Override public Wakelock instantiateObject() {
5918 return new Wakelock(mBsi, Uid.this);
5919 }
5920 };
5921 mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
5922 @Override public DualTimer instantiateObject() {
5923 return new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
5924 mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
5925 }
5926 };
5927 mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
5928 @Override public DualTimer instantiateObject() {
5929 return new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
5930 mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
5931 }
5932 };
5933
5934 mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_RUNNING,
5935 mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
5936 mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, this, FULL_WIFI_LOCK,
5937 mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
5938 mWifiScanTimer = new DualTimer(mBsi.mClocks, this, WIFI_SCAN,
5939 mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
5940 mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
5941 mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_MULTICAST_ENABLED,
5942 mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
5943 mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
5944 }
5945
5946 @Override
5947 public long[] getCpuFreqTimes(int which) {
5948 if (mCpuFreqTimeMs == null) {
5949 return null;
5950 }
5951 final long[] cpuFreqTimes = mCpuFreqTimeMs.getCountsLocked(which);
5952 if (cpuFreqTimes == null) {
5953 return null;
5954 }
5955 // Return cpuFreqTimes only if atleast one of the elements in non-zero.
5956 for (int i = 0; i < cpuFreqTimes.length; ++i) {
5957 if (cpuFreqTimes[i] != 0) {
5958 return cpuFreqTimes;
5959 }
5960 }
5961 return null;
5962 }
5963
5964 @Override
5965 public long[] getScreenOffCpuFreqTimes(int which) {
5966 if (mScreenOffCpuFreqTimeMs == null) {
5967 return null;
5968 }
5969 final long[] cpuFreqTimes = mScreenOffCpuFreqTimeMs.getCountsLocked(which);
5970 if (cpuFreqTimes == null) {
5971 return null;
5972 }
5973 // Return cpuFreqTimes only if atleast one of the elements in non-zero.
5974 for (int i = 0; i < cpuFreqTimes.length; ++i) {
5975 if (cpuFreqTimes[i] != 0) {
5976 return cpuFreqTimes;
5977 }
5978 }
5979 return null;
5980 }
5981
5982 @Override
5983 public Timer getAggregatedPartialWakelockTimer() {
5984 return mAggregatedPartialWakelockTimer;
5985 }
5986
5987 @Override
5988 public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
5989 return mWakelockStats.getMap();
5990 }
5991
5992 @Override
5993 public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
5994 return mSyncStats.getMap();
5995 }
5996
5997 @Override
5998 public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
5999 return mJobStats.getMap();
6000 }
6001
6002 @Override
6003 public ArrayMap<String, SparseIntArray> getJobCompletionStats() {
6004 return mJobCompletions;
6005 }
6006
6007 @Override
6008 public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
6009 return mSensorStats;
6010 }
6011
6012 @Override
6013 public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
6014 return mProcessStats;
6015 }
6016
6017 @Override
6018 public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
6019 return mPackageStats;
6020 }
6021
6022 @Override
6023 public int getUid() {
6024 return mUid;
6025 }
6026
6027 @Override
6028 public void noteWifiRunningLocked(long elapsedRealtimeMs) {
6029 if (!mWifiRunning) {
6030 mWifiRunning = true;
6031 if (mWifiRunningTimer == null) {
6032 mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
6033 mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
6034 }
6035 mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
6036 }
6037 }
6038
6039 @Override
6040 public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
6041 if (mWifiRunning) {
6042 mWifiRunning = false;
6043 mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
6044 }
6045 }
6046
6047 @Override
6048 public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
6049 if (!mFullWifiLockOut) {
6050 mFullWifiLockOut = true;
6051 if (mFullWifiLockTimer == null) {
6052 mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
6053 mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
6054 }
6055 mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
6056 }
6057 }
6058
6059 @Override
6060 public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
6061 if (mFullWifiLockOut) {
6062 mFullWifiLockOut = false;
6063 mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
6064 }
6065 }
6066
6067 @Override
6068 public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
6069 if (!mWifiScanStarted) {
6070 mWifiScanStarted = true;
6071 if (mWifiScanTimer == null) {
6072 mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
6073 mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase,
6074 mOnBatteryBackgroundTimeBase);
6075 }
6076 mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
6077 }
6078 }
6079
6080 @Override
6081 public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
6082 if (mWifiScanStarted) {
6083 mWifiScanStarted = false;
6084 mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
6085 }
6086 }
6087
6088 @Override
6089 public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
6090 int bin = 0;
6091 while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
6092 csph = csph >> 3;
6093 bin++;
6094 }
6095
6096 if (mWifiBatchedScanBinStarted == bin) return;
6097
6098 if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
6099 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
6100 stopRunningLocked(elapsedRealtimeMs);
6101 }
6102 mWifiBatchedScanBinStarted = bin;
6103 if (mWifiBatchedScanTimer[bin] == null) {
6104 makeWifiBatchedScanBin(bin, null);
6105 }
6106 mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
6107 }
6108
6109 @Override
6110 public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
6111 if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
6112 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
6113 stopRunningLocked(elapsedRealtimeMs);
6114 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
6115 }
6116 }
6117
6118 @Override
6119 public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
6120 if (!mWifiMulticastEnabled) {
6121 mWifiMulticastEnabled = true;
6122 if (mWifiMulticastTimer == null) {
6123 mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
6124 WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
6125 }
6126 mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
6127 }
6128 }
6129
6130 @Override
6131 public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
6132 if (mWifiMulticastEnabled) {
6133 mWifiMulticastEnabled = false;
6134 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
6135 }
6136 }
6137
6138 @Override
6139 public ControllerActivityCounter getWifiControllerActivity() {
6140 return mWifiControllerActivity;
6141 }
6142
6143 @Override
6144 public ControllerActivityCounter getBluetoothControllerActivity() {
6145 return mBluetoothControllerActivity;
6146 }
6147
6148 @Override
6149 public ControllerActivityCounter getModemControllerActivity() {
6150 return mModemControllerActivity;
6151 }
6152
6153 public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
6154 if (mWifiControllerActivity == null) {
6155 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
6156 NUM_BT_TX_LEVELS);
6157 }
6158 return mWifiControllerActivity;
6159 }
6160
6161 public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
6162 if (mBluetoothControllerActivity == null) {
6163 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
6164 NUM_BT_TX_LEVELS);
6165 }
6166 return mBluetoothControllerActivity;
6167 }
6168
6169 public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
6170 if (mModemControllerActivity == null) {
6171 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
6172 ModemActivityInfo.TX_POWER_LEVELS);
6173 }
6174 return mModemControllerActivity;
6175 }
6176
6177 public StopwatchTimer createAudioTurnedOnTimerLocked() {
6178 if (mAudioTurnedOnTimer == null) {
6179 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
6180 mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
6181 }
6182 return mAudioTurnedOnTimer;
6183 }
6184
6185 public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
6186 createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006187 // TODO(statsd): Possibly use a worksource instead of a uid.
6188 StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, getUid(), 1);
Justin Klaassen10d07c82017-09-15 17:58:39 -04006189 }
6190
6191 public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
6192 if (mAudioTurnedOnTimer != null) {
6193 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006194 if (!mAudioTurnedOnTimer.isRunningLocked()) { // only tell statsd if truly stopped
6195 // TODO(statsd): Possibly use a worksource instead of a uid.
6196 StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, getUid(), 0);
6197 }
Justin Klaassen10d07c82017-09-15 17:58:39 -04006198 }
6199 }
6200
6201 public void noteResetAudioLocked(long elapsedRealtimeMs) {
6202 if (mAudioTurnedOnTimer != null) {
6203 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006204 // TODO(statsd): Possibly use a worksource instead of a uid.
6205 StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, getUid(), 0);
Justin Klaassen10d07c82017-09-15 17:58:39 -04006206 }
6207 }
6208
6209 public StopwatchTimer createVideoTurnedOnTimerLocked() {
6210 if (mVideoTurnedOnTimer == null) {
6211 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
6212 mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
6213 }
6214 return mVideoTurnedOnTimer;
6215 }
6216
6217 public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
6218 createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006219 // TODO(statsd): Possibly use a worksource instead of a uid.
6220 StatsLog.write(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, getUid(), 1);
Justin Klaassen10d07c82017-09-15 17:58:39 -04006221 }
6222
6223 public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
6224 if (mVideoTurnedOnTimer != null) {
6225 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006226 if (!mVideoTurnedOnTimer.isRunningLocked()) { // only tell statsd if truly stopped
6227 // TODO(statsd): Possibly use a worksource instead of a uid.
6228 StatsLog.write(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, getUid(), 0);
6229 }
Justin Klaassen10d07c82017-09-15 17:58:39 -04006230 }
6231 }
6232
6233 public void noteResetVideoLocked(long elapsedRealtimeMs) {
6234 if (mVideoTurnedOnTimer != null) {
6235 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006236 // TODO(statsd): Possibly use a worksource instead of a uid.
6237 StatsLog.write(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, getUid(), 0);
Justin Klaassen10d07c82017-09-15 17:58:39 -04006238 }
6239 }
6240
6241 public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
6242 if (mFlashlightTurnedOnTimer == null) {
6243 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
6244 FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
6245 }
6246 return mFlashlightTurnedOnTimer;
6247 }
6248
6249 public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
6250 createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006251 // TODO(statsd): Possibly use a worksource instead of a uid.
6252 StatsLog.write(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), 1);
Justin Klaassen10d07c82017-09-15 17:58:39 -04006253 }
6254
6255 public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
6256 if (mFlashlightTurnedOnTimer != null) {
6257 mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006258 if (!mFlashlightTurnedOnTimer.isRunningLocked()) {
6259 // TODO(statsd): Possibly use a worksource instead of a uid.
6260 StatsLog.write(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), 0);
6261 }
Justin Klaassen10d07c82017-09-15 17:58:39 -04006262 }
6263 }
6264
6265 public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
6266 if (mFlashlightTurnedOnTimer != null) {
6267 mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006268 // TODO(statsd): Possibly use a worksource instead of a uid.
6269 StatsLog.write(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), 0);
Justin Klaassen10d07c82017-09-15 17:58:39 -04006270 }
6271 }
6272
6273 public StopwatchTimer createCameraTurnedOnTimerLocked() {
6274 if (mCameraTurnedOnTimer == null) {
6275 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
6276 mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
6277 }
6278 return mCameraTurnedOnTimer;
6279 }
6280
6281 public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
6282 createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006283 // TODO(statsd): Possibly use a worksource instead of a uid.
6284 StatsLog.write(StatsLog.CAMERA_STATE_CHANGED, getUid(), 1);
Justin Klaassen10d07c82017-09-15 17:58:39 -04006285 }
6286
6287 public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
6288 if (mCameraTurnedOnTimer != null) {
6289 mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006290 if (!mCameraTurnedOnTimer.isRunningLocked()) { // only tell statsd if truly stopped
6291 // TODO(statsd): Possibly use a worksource instead of a uid.
6292 StatsLog.write(StatsLog.CAMERA_STATE_CHANGED, getUid(), 0);
6293 }
Justin Klaassen10d07c82017-09-15 17:58:39 -04006294 }
6295 }
6296
6297 public void noteResetCameraLocked(long elapsedRealtimeMs) {
6298 if (mCameraTurnedOnTimer != null) {
6299 mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006300 // TODO(statsd): Possibly use a worksource instead of a uid.
6301 StatsLog.write(StatsLog.CAMERA_STATE_CHANGED, getUid(), 0);
Justin Klaassen10d07c82017-09-15 17:58:39 -04006302 }
6303 }
6304
6305 public StopwatchTimer createForegroundActivityTimerLocked() {
6306 if (mForegroundActivityTimer == null) {
6307 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
6308 FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
6309 }
6310 return mForegroundActivityTimer;
6311 }
6312
6313 public StopwatchTimer createForegroundServiceTimerLocked() {
6314 if (mForegroundServiceTimer == null) {
6315 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
6316 FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase);
6317 }
6318 return mForegroundServiceTimer;
6319 }
6320
6321 public DualTimer createAggregatedPartialWakelockTimerLocked() {
6322 if (mAggregatedPartialWakelockTimer == null) {
6323 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
6324 AGGREGATED_WAKE_TYPE_PARTIAL, null,
6325 mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase);
6326 }
6327 return mAggregatedPartialWakelockTimer;
6328 }
6329
6330 public DualTimer createBluetoothScanTimerLocked() {
6331 if (mBluetoothScanTimer == null) {
6332 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
6333 mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
6334 mOnBatteryBackgroundTimeBase);
6335 }
6336 return mBluetoothScanTimer;
6337 }
6338
6339 public DualTimer createBluetoothUnoptimizedScanTimerLocked() {
6340 if (mBluetoothUnoptimizedScanTimer == null) {
6341 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
6342 BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
6343 mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
6344 }
6345 return mBluetoothUnoptimizedScanTimer;
6346 }
6347
6348 public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
6349 createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006350 // TODO(statsd): Possibly use a worksource instead of a uid.
6351 StatsLog.write(StatsLog.BLE_SCAN_STATE_CHANGED, getUid(), 1);
Justin Klaassen10d07c82017-09-15 17:58:39 -04006352 if (isUnoptimized) {
6353 createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006354 // TODO(statsd): Possibly use a worksource instead of a uid.
6355 StatsLog.write(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED, getUid(), 1);
Justin Klaassen10d07c82017-09-15 17:58:39 -04006356 }
6357 }
6358
6359 public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
6360 if (mBluetoothScanTimer != null) {
6361 mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006362 if (!mBluetoothScanTimer.isRunningLocked()) { // only tell statsd if truly stopped
6363 // TODO(statsd): Possibly use a worksource instead of a uid.
6364 StatsLog.write(StatsLog.BLE_SCAN_STATE_CHANGED, getUid(), 0);
6365 }
Justin Klaassen10d07c82017-09-15 17:58:39 -04006366 }
6367 if (isUnoptimized && mBluetoothUnoptimizedScanTimer != null) {
6368 mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006369 if (!mBluetoothUnoptimizedScanTimer.isRunningLocked()) {
6370 // TODO(statsd): Possibly use a worksource instead of a uid.
6371 StatsLog.write(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED, getUid(), 0);
6372 }
Justin Klaassen10d07c82017-09-15 17:58:39 -04006373 }
6374 }
6375
6376 public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
6377 if (mBluetoothScanTimer != null) {
6378 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006379 // TODO(statsd): Possibly use a worksource instead of a uid.
6380 StatsLog.write(StatsLog.BLE_SCAN_STATE_CHANGED, getUid(), 0);
Justin Klaassen10d07c82017-09-15 17:58:39 -04006381 }
6382 if (mBluetoothUnoptimizedScanTimer != null) {
6383 mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006384 // TODO(statsd): Possibly use a worksource instead of a uid.
6385 StatsLog.write(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED, getUid(), 0);
Justin Klaassen10d07c82017-09-15 17:58:39 -04006386 }
6387 }
6388
6389 public Counter createBluetoothScanResultCounterLocked() {
6390 if (mBluetoothScanResultCounter == null) {
6391 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase);
6392 }
6393 return mBluetoothScanResultCounter;
6394 }
6395
6396 public Counter createBluetoothScanResultBgCounterLocked() {
6397 if (mBluetoothScanResultBgCounter == null) {
6398 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase);
6399 }
6400 return mBluetoothScanResultBgCounter;
6401 }
6402
6403 public void noteBluetoothScanResultsLocked(int numNewResults) {
6404 createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
6405 // Uses background timebase, so the count will only be incremented if uid in background.
6406 createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006407 // TODO(statsd): Possibly use a worksource instead of a uid.
6408 // TODO(statsd): This could be in AppScanStats instead, if desired.
6409 StatsLog.write(StatsLog.BLE_SCAN_RESULT_RECEIVED, getUid(), numNewResults);
Justin Klaassen10d07c82017-09-15 17:58:39 -04006410 }
6411
6412 @Override
6413 public void noteActivityResumedLocked(long elapsedRealtimeMs) {
6414 // We always start, since we want multiple foreground PIDs to nest
6415 createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
6416 }
6417
6418 @Override
6419 public void noteActivityPausedLocked(long elapsedRealtimeMs) {
6420 if (mForegroundActivityTimer != null) {
6421 mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
6422 }
6423 }
6424
6425 public void noteForegroundServiceResumedLocked(long elapsedRealtimeMs) {
6426 createForegroundServiceTimerLocked().startRunningLocked(elapsedRealtimeMs);
6427 }
6428
6429 public void noteForegroundServicePausedLocked(long elapsedRealtimeMs) {
6430 if (mForegroundServiceTimer != null) {
6431 mForegroundServiceTimer.stopRunningLocked(elapsedRealtimeMs);
6432 }
6433 }
6434
6435 public BatchTimer createVibratorOnTimerLocked() {
6436 if (mVibratorOnTimer == null) {
6437 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
6438 mBsi.mOnBatteryTimeBase);
6439 }
6440 return mVibratorOnTimer;
6441 }
6442
6443 public void noteVibratorOnLocked(long durationMillis) {
6444 createVibratorOnTimerLocked().addDuration(mBsi, durationMillis);
6445 }
6446
6447 public void noteVibratorOffLocked() {
6448 if (mVibratorOnTimer != null) {
6449 mVibratorOnTimer.abortLastDuration(mBsi);
6450 }
6451 }
6452
6453 @Override
6454 public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
6455 if (mWifiRunningTimer == null) {
6456 return 0;
6457 }
6458 return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6459 }
6460
6461 @Override
6462 public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
6463 if (mFullWifiLockTimer == null) {
6464 return 0;
6465 }
6466 return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6467 }
6468
6469 @Override
6470 public long getWifiScanTime(long elapsedRealtimeUs, int which) {
6471 if (mWifiScanTimer == null) {
6472 return 0;
6473 }
6474 return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6475 }
6476
6477 @Override
6478 public int getWifiScanCount(int which) {
6479 if (mWifiScanTimer == null) {
6480 return 0;
6481 }
6482 return mWifiScanTimer.getCountLocked(which);
6483 }
6484
6485 @Override
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006486 public Timer getWifiScanTimer() {
6487 return mWifiScanTimer;
6488 }
6489
6490 @Override
Justin Klaassen10d07c82017-09-15 17:58:39 -04006491 public int getWifiScanBackgroundCount(int which) {
6492 if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
6493 return 0;
6494 }
6495 return mWifiScanTimer.getSubTimer().getCountLocked(which);
6496 }
6497
6498 @Override
6499 public long getWifiScanActualTime(final long elapsedRealtimeUs) {
6500 if (mWifiScanTimer == null) {
6501 return 0;
6502 }
6503 final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
6504 return mWifiScanTimer.getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
6505 }
6506
6507 @Override
6508 public long getWifiScanBackgroundTime(final long elapsedRealtimeUs) {
6509 if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
6510 return 0;
6511 }
6512 final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
6513 return mWifiScanTimer.getSubTimer().getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
6514 }
6515
6516 @Override
Justin Klaassen47ed54e2017-10-24 19:50:40 -04006517 public Timer getWifiScanBackgroundTimer() {
6518 if (mWifiScanTimer == null) {
6519 return null;
6520 }
6521 return mWifiScanTimer.getSubTimer();
6522 }
6523
6524 @Override
Justin Klaassen10d07c82017-09-15 17:58:39 -04006525 public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
6526 if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
6527 if (mWifiBatchedScanTimer[csphBin] == null) {
6528 return 0;
6529 }
6530 return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
6531 }
6532
6533 @Override
6534 public int getWifiBatchedScanCount(int csphBin, int which) {
6535 if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
6536 if (mWifiBatchedScanTimer[csphBin] == null) {
6537 return 0;
6538 }
6539 return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
6540 }
6541
6542 @Override
6543 public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
6544 if (mWifiMulticastTimer == null) {
6545 return 0;
6546 }
6547 return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
6548 }
6549
6550 @Override
6551 public Timer getAudioTurnedOnTimer() {
6552 return mAudioTurnedOnTimer;
6553 }
6554
6555 @Override
6556 public Timer getVideoTurnedOnTimer() {
6557 return mVideoTurnedOnTimer;
6558 }
6559
6560 @Override
6561 public Timer getFlashlightTurnedOnTimer() {
6562 return mFlashlightTurnedOnTimer;
6563 }
6564
6565 @Override
6566 public Timer getCameraTurnedOnTimer() {
6567 return mCameraTurnedOnTimer;
6568 }
6569
6570 @Override
6571 public Timer getForegroundActivityTimer() {
6572 return mForegroundActivityTimer;
6573 }
6574
6575 @Override
6576 public Timer getForegroundServiceTimer() {
6577 return mForegroundServiceTimer;
6578 }
6579
6580 @Override
6581 public Timer getBluetoothScanTimer() {
6582 return mBluetoothScanTimer;
6583 }
6584
6585 @Override
6586 public Timer getBluetoothScanBackgroundTimer() {
6587 if (mBluetoothScanTimer == null) {
6588 return null;
6589 }
6590 return mBluetoothScanTimer.getSubTimer();
6591 }
6592
6593 @Override
6594 public Timer getBluetoothUnoptimizedScanTimer() {
6595 return mBluetoothUnoptimizedScanTimer;
6596 }
6597
6598 @Override
6599 public Timer getBluetoothUnoptimizedScanBackgroundTimer() {
6600 if (mBluetoothUnoptimizedScanTimer == null) {
6601 return null;
6602 }
6603 return mBluetoothUnoptimizedScanTimer.getSubTimer();
6604 }
6605
6606 @Override
6607 public Counter getBluetoothScanResultCounter() {
6608 return mBluetoothScanResultCounter;
6609 }
6610
6611 @Override
6612 public Counter getBluetoothScanResultBgCounter() {
6613 return mBluetoothScanResultBgCounter;
6614 }
6615
6616 void makeProcessState(int i, Parcel in) {
6617 if (i < 0 || i >= NUM_PROCESS_STATE) return;
6618
6619 if (in == null) {
6620 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
6621 mBsi.mOnBatteryTimeBase);
6622 } else {
6623 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
6624 mBsi.mOnBatteryTimeBase, in);
6625 }
6626 }
6627
6628 @Override
6629 public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
6630 if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
6631 if (mProcessStateTimer[state] == null) {
6632 return 0;
6633 }
6634 return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
6635 }
6636
6637 @Override
6638 public Timer getProcessStateTimer(int state) {
6639 if (state < 0 || state >= NUM_PROCESS_STATE) return null;
6640 return mProcessStateTimer[state];
6641 }
6642
6643 @Override
6644 public Timer getVibratorOnTimer() {
6645 return mVibratorOnTimer;
6646 }
6647
6648 @Override
6649 public void noteUserActivityLocked(int type) {
6650 if (mUserActivityCounters == null) {
6651 initUserActivityLocked();
6652 }
6653 if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
6654 mUserActivityCounters[type].stepAtomic();
6655 } else {
6656 Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
6657 new Throwable());
6658 }
6659 }
6660
6661 @Override
6662 public boolean hasUserActivity() {
6663 return mUserActivityCounters != null;
6664 }
6665
6666 @Override
6667 public int getUserActivityCount(int type, int which) {
6668 if (mUserActivityCounters == null) {
6669 return 0;
6670 }
6671 return mUserActivityCounters[type].getCountLocked(which);
6672 }
6673
6674 void makeWifiBatchedScanBin(int i, Parcel in) {
6675 if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
6676
6677 ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
6678 if (collected == null) {
6679 collected = new ArrayList<StopwatchTimer>();
6680 mBsi.mWifiBatchedScanTimers.put(i, collected);
6681 }
6682 if (in == null) {
6683 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
6684 collected, mBsi.mOnBatteryTimeBase);
6685 } else {
6686 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
6687 collected, mBsi.mOnBatteryTimeBase, in);
6688 }
6689 }
6690
6691
6692 void initUserActivityLocked() {
6693 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
6694 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
6695 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
6696 }
6697 }
6698
6699 void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
6700 if (mNetworkByteActivityCounters == null) {
6701 initNetworkActivityLocked();
6702 }
6703 if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
6704 mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
6705 mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
6706 } else {
6707 Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
6708 new Throwable());
6709 }
6710 }
6711
6712 void noteMobileRadioActiveTimeLocked(long batteryUptime) {
6713 if (mNetworkByteActivityCounters == null) {
6714 initNetworkActivityLocked();
6715 }
6716 mMobileRadioActiveTime.addCountLocked(batteryUptime);
6717 mMobileRadioActiveCount.addCountLocked(1);
6718 }
6719
6720 @Override
6721 public boolean hasNetworkActivity() {
6722 return mNetworkByteActivityCounters != null;
6723 }
6724
6725 @Override
6726 public long getNetworkActivityBytes(int type, int which) {
6727 if (mNetworkByteActivityCounters != null && type >= 0
6728 && type < mNetworkByteActivityCounters.length) {
6729 return mNetworkByteActivityCounters[type].getCountLocked(which);
6730 } else {
6731 return 0;
6732 }
6733 }
6734
6735 @Override
6736 public long getNetworkActivityPackets(int type, int which) {
6737 if (mNetworkPacketActivityCounters != null && type >= 0
6738 && type < mNetworkPacketActivityCounters.length) {
6739 return mNetworkPacketActivityCounters[type].getCountLocked(which);
6740 } else {
6741 return 0;
6742 }
6743 }
6744
6745 @Override
6746 public long getMobileRadioActiveTime(int which) {
6747 return mMobileRadioActiveTime != null
6748 ? mMobileRadioActiveTime.getCountLocked(which) : 0;
6749 }
6750
6751 @Override
6752 public int getMobileRadioActiveCount(int which) {
6753 return mMobileRadioActiveCount != null
6754 ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
6755 }
6756
6757 @Override
6758 public long getUserCpuTimeUs(int which) {
6759 return mUserCpuTime.getCountLocked(which);
6760 }
6761
6762 @Override
6763 public long getSystemCpuTimeUs(int which) {
6764 return mSystemCpuTime.getCountLocked(which);
6765 }
6766
6767 @Override
6768 public long getTimeAtCpuSpeed(int cluster, int step, int which) {
6769 if (mCpuClusterSpeedTimesUs != null) {
6770 if (cluster >= 0 && cluster < mCpuClusterSpeedTimesUs.length) {
6771 final LongSamplingCounter[] cpuSpeedTimesUs = mCpuClusterSpeedTimesUs[cluster];
6772 if (cpuSpeedTimesUs != null) {
6773 if (step >= 0 && step < cpuSpeedTimesUs.length) {
6774 final LongSamplingCounter c = cpuSpeedTimesUs[step];
6775 if (c != null) {
6776 return c.getCountLocked(which);
6777 }
6778 }
6779 }
6780 }
6781 }
6782 return 0;
6783 }
6784
6785 public void noteMobileRadioApWakeupLocked() {
6786 if (mMobileRadioApWakeupCount == null) {
6787 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6788 }
6789 mMobileRadioApWakeupCount.addCountLocked(1);
6790 }
6791
6792 @Override
6793 public long getMobileRadioApWakeupCount(int which) {
6794 if (mMobileRadioApWakeupCount != null) {
6795 return mMobileRadioApWakeupCount.getCountLocked(which);
6796 }
6797 return 0;
6798 }
6799
6800 public void noteWifiRadioApWakeupLocked() {
6801 if (mWifiRadioApWakeupCount == null) {
6802 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6803 }
6804 mWifiRadioApWakeupCount.addCountLocked(1);
6805 }
6806
6807 @Override
6808 public long getWifiRadioApWakeupCount(int which) {
6809 if (mWifiRadioApWakeupCount != null) {
6810 return mWifiRadioApWakeupCount.getCountLocked(which);
6811 }
6812 return 0;
6813 }
6814
6815 void initNetworkActivityLocked() {
6816 mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
6817 mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
6818 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
6819 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6820 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6821 }
6822 mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6823 mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6824 }
6825
6826 /**
6827 * Clear all stats for this uid. Returns true if the uid is completely
6828 * inactive so can be dropped.
6829 */
6830 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
6831 public boolean reset(long uptime, long realtime) {
6832 boolean active = false;
6833
6834 mOnBatteryBackgroundTimeBase.init(uptime, realtime);
6835 mOnBatteryScreenOffBackgroundTimeBase.init(uptime, realtime);
6836
6837 if (mWifiRunningTimer != null) {
6838 active |= !mWifiRunningTimer.reset(false);
6839 active |= mWifiRunning;
6840 }
6841 if (mFullWifiLockTimer != null) {
6842 active |= !mFullWifiLockTimer.reset(false);
6843 active |= mFullWifiLockOut;
6844 }
6845 if (mWifiScanTimer != null) {
6846 active |= !mWifiScanTimer.reset(false);
6847 active |= mWifiScanStarted;
6848 }
6849 if (mWifiBatchedScanTimer != null) {
6850 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
6851 if (mWifiBatchedScanTimer[i] != null) {
6852 active |= !mWifiBatchedScanTimer[i].reset(false);
6853 }
6854 }
6855 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
6856 }
6857 if (mWifiMulticastTimer != null) {
6858 active |= !mWifiMulticastTimer.reset(false);
6859 active |= mWifiMulticastEnabled;
6860 }
6861
6862 active |= !resetTimerIfNotNull(mAudioTurnedOnTimer, false);
6863 active |= !resetTimerIfNotNull(mVideoTurnedOnTimer, false);
6864 active |= !resetTimerIfNotNull(mFlashlightTurnedOnTimer, false);
6865 active |= !resetTimerIfNotNull(mCameraTurnedOnTimer, false);
6866 active |= !resetTimerIfNotNull(mForegroundActivityTimer, false);
6867 active |= !resetTimerIfNotNull(mForegroundServiceTimer, false);
6868 active |= !resetTimerIfNotNull(mAggregatedPartialWakelockTimer, false);
6869 active |= !resetTimerIfNotNull(mBluetoothScanTimer, false);
6870 active |= !resetTimerIfNotNull(mBluetoothUnoptimizedScanTimer, false);
6871 if (mBluetoothScanResultCounter != null) {
6872 mBluetoothScanResultCounter.reset(false);
6873 }
6874 if (mBluetoothScanResultBgCounter != null) {
6875 mBluetoothScanResultBgCounter.reset(false);
6876 }
6877
6878 if (mProcessStateTimer != null) {
6879 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
6880 if (mProcessStateTimer[i] != null) {
6881 active |= !mProcessStateTimer[i].reset(false);
6882 }
6883 }
6884 active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
6885 }
6886 if (mVibratorOnTimer != null) {
6887 if (mVibratorOnTimer.reset(false)) {
6888 mVibratorOnTimer.detach();
6889 mVibratorOnTimer = null;
6890 } else {
6891 active = true;
6892 }
6893 }
6894
6895 if (mUserActivityCounters != null) {
6896 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
6897 mUserActivityCounters[i].reset(false);
6898 }
6899 }
6900
6901 if (mNetworkByteActivityCounters != null) {
6902 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
6903 mNetworkByteActivityCounters[i].reset(false);
6904 mNetworkPacketActivityCounters[i].reset(false);
6905 }
6906 mMobileRadioActiveTime.reset(false);
6907 mMobileRadioActiveCount.reset(false);
6908 }
6909
6910 if (mWifiControllerActivity != null) {
6911 mWifiControllerActivity.reset(false);
6912 }
6913
6914 if (mBluetoothControllerActivity != null) {
6915 mBluetoothControllerActivity.reset(false);
6916 }
6917
6918 if (mModemControllerActivity != null) {
6919 mModemControllerActivity.reset(false);
6920 }
6921
6922 mUserCpuTime.reset(false);
6923 mSystemCpuTime.reset(false);
6924
6925 if (mCpuClusterSpeedTimesUs != null) {
6926 for (LongSamplingCounter[] speeds : mCpuClusterSpeedTimesUs) {
6927 if (speeds != null) {
6928 for (LongSamplingCounter speed : speeds) {
6929 if (speed != null) {
6930 speed.reset(false);
6931 }
6932 }
6933 }
6934 }
6935 }
6936
6937 if (mCpuFreqTimeMs != null) {
6938 mCpuFreqTimeMs.reset(false);
6939 }
6940 if (mScreenOffCpuFreqTimeMs != null) {
6941 mScreenOffCpuFreqTimeMs.reset(false);
6942 }
6943
6944 resetLongCounterIfNotNull(mMobileRadioApWakeupCount, false);
6945 resetLongCounterIfNotNull(mWifiRadioApWakeupCount, false);
6946
6947 final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
6948 for (int iw=wakeStats.size()-1; iw>=0; iw--) {
6949 Wakelock wl = wakeStats.valueAt(iw);
6950 if (wl.reset()) {
6951 wakeStats.removeAt(iw);
6952 } else {
6953 active = true;
6954 }
6955 }
6956 mWakelockStats.cleanup();
6957 final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
6958 for (int is=syncStats.size()-1; is>=0; is--) {
6959 DualTimer timer = syncStats.valueAt(is);
6960 if (timer.reset(false)) {
6961 syncStats.removeAt(is);
6962 timer.detach();
6963 } else {
6964 active = true;
6965 }
6966 }
6967 mSyncStats.cleanup();
6968 final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
6969 for (int ij=jobStats.size()-1; ij>=0; ij--) {
6970 DualTimer timer = jobStats.valueAt(ij);
6971 if (timer.reset(false)) {
6972 jobStats.removeAt(ij);
6973 timer.detach();
6974 } else {
6975 active = true;
6976 }
6977 }
6978 mJobStats.cleanup();
6979 mJobCompletions.clear();
6980 for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
6981 Sensor s = mSensorStats.valueAt(ise);
6982 if (s.reset()) {
6983 mSensorStats.removeAt(ise);
6984 } else {
6985 active = true;
6986 }
6987 }
6988 for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
6989 Proc proc = mProcessStats.valueAt(ip);
6990 proc.detach();
6991 }
6992 mProcessStats.clear();
6993 if (mPids.size() > 0) {
6994 for (int i=mPids.size()-1; i>=0; i--) {
6995 Pid pid = mPids.valueAt(i);
6996 if (pid.mWakeNesting > 0) {
6997 active = true;
6998 } else {
6999 mPids.removeAt(i);
7000 }
7001 }
7002 }
7003 if (mPackageStats.size() > 0) {
7004 Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator();
7005 while (it.hasNext()) {
7006 Map.Entry<String, Pkg> pkgEntry = it.next();
7007 Pkg p = pkgEntry.getValue();
7008 p.detach();
7009 if (p.mServiceStats.size() > 0) {
7010 Iterator<Map.Entry<String, Pkg.Serv>> it2
7011 = p.mServiceStats.entrySet().iterator();
7012 while (it2.hasNext()) {
7013 Map.Entry<String, Pkg.Serv> servEntry = it2.next();
7014 servEntry.getValue().detach();
7015 }
7016 }
7017 }
7018 mPackageStats.clear();
7019 }
7020
7021 mLastStepUserTime = mLastStepSystemTime = 0;
7022 mCurStepUserTime = mCurStepSystemTime = 0;
7023
7024 if (!active) {
7025 if (mWifiRunningTimer != null) {
7026 mWifiRunningTimer.detach();
7027 }
7028 if (mFullWifiLockTimer != null) {
7029 mFullWifiLockTimer.detach();
7030 }
7031 if (mWifiScanTimer != null) {
7032 mWifiScanTimer.detach();
7033 }
7034 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
7035 if (mWifiBatchedScanTimer[i] != null) {
7036 mWifiBatchedScanTimer[i].detach();
7037 }
7038 }
7039 if (mWifiMulticastTimer != null) {
7040 mWifiMulticastTimer.detach();
7041 }
7042 if (mAudioTurnedOnTimer != null) {
7043 mAudioTurnedOnTimer.detach();
7044 mAudioTurnedOnTimer = null;
7045 }
7046 if (mVideoTurnedOnTimer != null) {
7047 mVideoTurnedOnTimer.detach();
7048 mVideoTurnedOnTimer = null;
7049 }
7050 if (mFlashlightTurnedOnTimer != null) {
7051 mFlashlightTurnedOnTimer.detach();
7052 mFlashlightTurnedOnTimer = null;
7053 }
7054 if (mCameraTurnedOnTimer != null) {
7055 mCameraTurnedOnTimer.detach();
7056 mCameraTurnedOnTimer = null;
7057 }
7058 if (mForegroundActivityTimer != null) {
7059 mForegroundActivityTimer.detach();
7060 mForegroundActivityTimer = null;
7061 }
7062 if (mForegroundServiceTimer != null) {
7063 mForegroundServiceTimer.detach();
7064 mForegroundServiceTimer = null;
7065 }
7066 if (mAggregatedPartialWakelockTimer != null) {
7067 mAggregatedPartialWakelockTimer.detach();
7068 mAggregatedPartialWakelockTimer = null;
7069 }
7070 if (mBluetoothScanTimer != null) {
7071 mBluetoothScanTimer.detach();
7072 mBluetoothScanTimer = null;
7073 }
7074 if (mBluetoothUnoptimizedScanTimer != null) {
7075 mBluetoothUnoptimizedScanTimer.detach();
7076 mBluetoothUnoptimizedScanTimer = null;
7077 }
7078 if (mBluetoothScanResultCounter != null) {
7079 mBluetoothScanResultCounter.detach();
7080 mBluetoothScanResultCounter = null;
7081 }
7082 if (mBluetoothScanResultBgCounter != null) {
7083 mBluetoothScanResultBgCounter.detach();
7084 mBluetoothScanResultBgCounter = null;
7085 }
7086 if (mUserActivityCounters != null) {
7087 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
7088 mUserActivityCounters[i].detach();
7089 }
7090 }
7091 if (mNetworkByteActivityCounters != null) {
7092 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7093 mNetworkByteActivityCounters[i].detach();
7094 mNetworkPacketActivityCounters[i].detach();
7095 }
7096 }
7097
7098 if (mWifiControllerActivity != null) {
7099 mWifiControllerActivity.detach();
7100 }
7101
7102 if (mBluetoothControllerActivity != null) {
7103 mBluetoothControllerActivity.detach();
7104 }
7105
7106 if (mModemControllerActivity != null) {
7107 mModemControllerActivity.detach();
7108 }
7109
7110 mPids.clear();
7111
7112 mUserCpuTime.detach();
7113 mSystemCpuTime.detach();
7114
7115 if (mCpuClusterSpeedTimesUs != null) {
7116 for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) {
7117 if (cpuSpeeds != null) {
7118 for (LongSamplingCounter c : cpuSpeeds) {
7119 if (c != null) {
7120 c.detach();
7121 }
7122 }
7123 }
7124 }
7125 }
7126
7127 if (mCpuFreqTimeMs != null) {
7128 mCpuFreqTimeMs.detach();
7129 }
7130 if (mScreenOffCpuFreqTimeMs != null) {
7131 mScreenOffCpuFreqTimeMs.detach();
7132 }
7133
7134 detachLongCounterIfNotNull(mMobileRadioApWakeupCount);
7135 detachLongCounterIfNotNull(mWifiRadioApWakeupCount);
7136 }
7137
7138 return !active;
7139 }
7140
7141 void writeJobCompletionsToParcelLocked(Parcel out) {
7142 int NJC = mJobCompletions.size();
7143 out.writeInt(NJC);
7144 for (int ijc=0; ijc<NJC; ijc++) {
7145 out.writeString(mJobCompletions.keyAt(ijc));
7146 SparseIntArray types = mJobCompletions.valueAt(ijc);
7147 int NT = types.size();
7148 out.writeInt(NT);
7149 for (int it=0; it<NT; it++) {
7150 out.writeInt(types.keyAt(it));
7151 out.writeInt(types.valueAt(it));
7152 }
7153 }
7154 }
7155
7156 void writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
7157 mOnBatteryBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
7158 mOnBatteryScreenOffBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
7159
7160 final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
7161 int NW = wakeStats.size();
7162 out.writeInt(NW);
7163 for (int iw=0; iw<NW; iw++) {
7164 out.writeString(wakeStats.keyAt(iw));
7165 Uid.Wakelock wakelock = wakeStats.valueAt(iw);
7166 wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
7167 }
7168
7169 final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
7170 int NS = syncStats.size();
7171 out.writeInt(NS);
7172 for (int is=0; is<NS; is++) {
7173 out.writeString(syncStats.keyAt(is));
7174 DualTimer timer = syncStats.valueAt(is);
7175 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
7176 }
7177
7178 final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
7179 int NJ = jobStats.size();
7180 out.writeInt(NJ);
7181 for (int ij=0; ij<NJ; ij++) {
7182 out.writeString(jobStats.keyAt(ij));
7183 DualTimer timer = jobStats.valueAt(ij);
7184 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
7185 }
7186
7187 writeJobCompletionsToParcelLocked(out);
7188
7189 int NSE = mSensorStats.size();
7190 out.writeInt(NSE);
7191 for (int ise=0; ise<NSE; ise++) {
7192 out.writeInt(mSensorStats.keyAt(ise));
7193 Uid.Sensor sensor = mSensorStats.valueAt(ise);
7194 sensor.writeToParcelLocked(out, elapsedRealtimeUs);
7195 }
7196
7197 int NP = mProcessStats.size();
7198 out.writeInt(NP);
7199 for (int ip=0; ip<NP; ip++) {
7200 out.writeString(mProcessStats.keyAt(ip));
7201 Uid.Proc proc = mProcessStats.valueAt(ip);
7202 proc.writeToParcelLocked(out);
7203 }
7204
7205 out.writeInt(mPackageStats.size());
7206 for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
7207 out.writeString(pkgEntry.getKey());
7208 Uid.Pkg pkg = pkgEntry.getValue();
7209 pkg.writeToParcelLocked(out);
7210 }
7211
7212 if (mWifiRunningTimer != null) {
7213 out.writeInt(1);
7214 mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
7215 } else {
7216 out.writeInt(0);
7217 }
7218 if (mFullWifiLockTimer != null) {
7219 out.writeInt(1);
7220 mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
7221 } else {
7222 out.writeInt(0);
7223 }
7224 if (mWifiScanTimer != null) {
7225 out.writeInt(1);
7226 mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
7227 } else {
7228 out.writeInt(0);
7229 }
7230 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
7231 if (mWifiBatchedScanTimer[i] != null) {
7232 out.writeInt(1);
7233 mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
7234 } else {
7235 out.writeInt(0);
7236 }
7237 }
7238 if (mWifiMulticastTimer != null) {
7239 out.writeInt(1);
7240 mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
7241 } else {
7242 out.writeInt(0);
7243 }
7244
7245 if (mAudioTurnedOnTimer != null) {
7246 out.writeInt(1);
7247 mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
7248 } else {
7249 out.writeInt(0);
7250 }
7251 if (mVideoTurnedOnTimer != null) {
7252 out.writeInt(1);
7253 mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
7254 } else {
7255 out.writeInt(0);
7256 }
7257 if (mFlashlightTurnedOnTimer != null) {
7258 out.writeInt(1);
7259 mFlashlightTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
7260 } else {
7261 out.writeInt(0);
7262 }
7263 if (mCameraTurnedOnTimer != null) {
7264 out.writeInt(1);
7265 mCameraTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
7266 } else {
7267 out.writeInt(0);
7268 }
7269 if (mForegroundActivityTimer != null) {
7270 out.writeInt(1);
7271 mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
7272 } else {
7273 out.writeInt(0);
7274 }
7275 if (mForegroundServiceTimer != null) {
7276 out.writeInt(1);
7277 mForegroundServiceTimer.writeToParcel(out, elapsedRealtimeUs);
7278 } else {
7279 out.writeInt(0);
7280 }
7281 if (mAggregatedPartialWakelockTimer != null) {
7282 out.writeInt(1);
7283 mAggregatedPartialWakelockTimer.writeToParcel(out, elapsedRealtimeUs);
7284 } else {
7285 out.writeInt(0);
7286 }
7287 if (mBluetoothScanTimer != null) {
7288 out.writeInt(1);
7289 mBluetoothScanTimer.writeToParcel(out, elapsedRealtimeUs);
7290 } else {
7291 out.writeInt(0);
7292 }
7293 if (mBluetoothUnoptimizedScanTimer != null) {
7294 out.writeInt(1);
7295 mBluetoothUnoptimizedScanTimer.writeToParcel(out, elapsedRealtimeUs);
7296 } else {
7297 out.writeInt(0);
7298 }
7299 if (mBluetoothScanResultCounter != null) {
7300 out.writeInt(1);
7301 mBluetoothScanResultCounter.writeToParcel(out);
7302 } else {
7303 out.writeInt(0);
7304 }
7305 if (mBluetoothScanResultBgCounter != null) {
7306 out.writeInt(1);
7307 mBluetoothScanResultBgCounter.writeToParcel(out);
7308 } else {
7309 out.writeInt(0);
7310 }
7311 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
7312 if (mProcessStateTimer[i] != null) {
7313 out.writeInt(1);
7314 mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
7315 } else {
7316 out.writeInt(0);
7317 }
7318 }
7319 if (mVibratorOnTimer != null) {
7320 out.writeInt(1);
7321 mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
7322 } else {
7323 out.writeInt(0);
7324 }
7325 if (mUserActivityCounters != null) {
7326 out.writeInt(1);
7327 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
7328 mUserActivityCounters[i].writeToParcel(out);
7329 }
7330 } else {
7331 out.writeInt(0);
7332 }
7333 if (mNetworkByteActivityCounters != null) {
7334 out.writeInt(1);
7335 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7336 mNetworkByteActivityCounters[i].writeToParcel(out);
7337 mNetworkPacketActivityCounters[i].writeToParcel(out);
7338 }
7339 mMobileRadioActiveTime.writeToParcel(out);
7340 mMobileRadioActiveCount.writeToParcel(out);
7341 } else {
7342 out.writeInt(0);
7343 }
7344
7345 if (mWifiControllerActivity != null) {
7346 out.writeInt(1);
7347 mWifiControllerActivity.writeToParcel(out, 0);
7348 } else {
7349 out.writeInt(0);
7350 }
7351
7352 if (mBluetoothControllerActivity != null) {
7353 out.writeInt(1);
7354 mBluetoothControllerActivity.writeToParcel(out, 0);
7355 } else {
7356 out.writeInt(0);
7357 }
7358
7359 if (mModemControllerActivity != null) {
7360 out.writeInt(1);
7361 mModemControllerActivity.writeToParcel(out, 0);
7362 } else {
7363 out.writeInt(0);
7364 }
7365
7366 mUserCpuTime.writeToParcel(out);
7367 mSystemCpuTime.writeToParcel(out);
7368
7369 if (mCpuClusterSpeedTimesUs != null) {
7370 out.writeInt(1);
7371 out.writeInt(mCpuClusterSpeedTimesUs.length);
7372 for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) {
7373 if (cpuSpeeds != null) {
7374 out.writeInt(1);
7375 out.writeInt(cpuSpeeds.length);
7376 for (LongSamplingCounter c : cpuSpeeds) {
7377 if (c != null) {
7378 out.writeInt(1);
7379 c.writeToParcel(out);
7380 } else {
7381 out.writeInt(0);
7382 }
7383 }
7384 } else {
7385 out.writeInt(0);
7386 }
7387 }
7388 } else {
7389 out.writeInt(0);
7390 }
7391
7392 LongSamplingCounterArray.writeToParcel(out, mCpuFreqTimeMs);
7393 LongSamplingCounterArray.writeToParcel(out, mScreenOffCpuFreqTimeMs);
7394
7395 if (mMobileRadioApWakeupCount != null) {
7396 out.writeInt(1);
7397 mMobileRadioApWakeupCount.writeToParcel(out);
7398 } else {
7399 out.writeInt(0);
7400 }
7401
7402 if (mWifiRadioApWakeupCount != null) {
7403 out.writeInt(1);
7404 mWifiRadioApWakeupCount.writeToParcel(out);
7405 } else {
7406 out.writeInt(0);
7407 }
7408 }
7409
7410 void readJobCompletionsFromParcelLocked(Parcel in) {
7411 int numJobCompletions = in.readInt();
7412 mJobCompletions.clear();
7413 for (int j = 0; j < numJobCompletions; j++) {
7414 String jobName = in.readString();
7415 int numTypes = in.readInt();
7416 if (numTypes > 0) {
7417 SparseIntArray types = new SparseIntArray();
7418 for (int k = 0; k < numTypes; k++) {
7419 int type = in.readInt();
7420 int count = in.readInt();
7421 types.put(type, count);
7422 }
7423 mJobCompletions.put(jobName, types);
7424 }
7425 }
7426 }
7427
7428 void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
7429 mOnBatteryBackgroundTimeBase.readFromParcel(in);
7430 mOnBatteryScreenOffBackgroundTimeBase.readFromParcel(in);
7431
7432 int numWakelocks = in.readInt();
7433 mWakelockStats.clear();
7434 for (int j = 0; j < numWakelocks; j++) {
7435 String wakelockName = in.readString();
7436 Uid.Wakelock wakelock = new Wakelock(mBsi, this);
7437 wakelock.readFromParcelLocked(
7438 timeBase, screenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase, in);
7439 mWakelockStats.add(wakelockName, wakelock);
7440 }
7441
7442 int numSyncs = in.readInt();
7443 mSyncStats.clear();
7444 for (int j = 0; j < numSyncs; j++) {
7445 String syncName = in.readString();
7446 if (in.readInt() != 0) {
7447 mSyncStats.add(syncName, new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
7448 mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
7449 }
7450 }
7451
7452 int numJobs = in.readInt();
7453 mJobStats.clear();
7454 for (int j = 0; j < numJobs; j++) {
7455 String jobName = in.readString();
7456 if (in.readInt() != 0) {
7457 mJobStats.add(jobName, new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
7458 mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
7459 }
7460 }
7461
7462 readJobCompletionsFromParcelLocked(in);
7463
7464 int numSensors = in.readInt();
7465 mSensorStats.clear();
7466 for (int k = 0; k < numSensors; k++) {
7467 int sensorNumber = in.readInt();
7468 Uid.Sensor sensor = new Sensor(mBsi, this, sensorNumber);
7469 sensor.readFromParcelLocked(mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
7470 in);
7471 mSensorStats.put(sensorNumber, sensor);
7472 }
7473
7474 int numProcs = in.readInt();
7475 mProcessStats.clear();
7476 for (int k = 0; k < numProcs; k++) {
7477 String processName = in.readString();
7478 Uid.Proc proc = new Proc(mBsi, processName);
7479 proc.readFromParcelLocked(in);
7480 mProcessStats.put(processName, proc);
7481 }
7482
7483 int numPkgs = in.readInt();
7484 mPackageStats.clear();
7485 for (int l = 0; l < numPkgs; l++) {
7486 String packageName = in.readString();
7487 Uid.Pkg pkg = new Pkg(mBsi);
7488 pkg.readFromParcelLocked(in);
7489 mPackageStats.put(packageName, pkg);
7490 }
7491
7492 mWifiRunning = false;
7493 if (in.readInt() != 0) {
7494 mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
7495 mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase, in);
7496 } else {
7497 mWifiRunningTimer = null;
7498 }
7499 mFullWifiLockOut = false;
7500 if (in.readInt() != 0) {
7501 mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
7502 mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase, in);
7503 } else {
7504 mFullWifiLockTimer = null;
7505 }
7506 mWifiScanStarted = false;
7507 if (in.readInt() != 0) {
7508 mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
7509 mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
7510 in);
7511 } else {
7512 mWifiScanTimer = null;
7513 }
7514 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
7515 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
7516 if (in.readInt() != 0) {
7517 makeWifiBatchedScanBin(i, in);
7518 } else {
7519 mWifiBatchedScanTimer[i] = null;
7520 }
7521 }
7522 mWifiMulticastEnabled = false;
7523 if (in.readInt() != 0) {
7524 mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_MULTICAST_ENABLED,
7525 mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase, in);
7526 } else {
7527 mWifiMulticastTimer = null;
7528 }
7529 if (in.readInt() != 0) {
7530 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
7531 mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
7532 } else {
7533 mAudioTurnedOnTimer = null;
7534 }
7535 if (in.readInt() != 0) {
7536 mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
7537 mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
7538 } else {
7539 mVideoTurnedOnTimer = null;
7540 }
7541 if (in.readInt() != 0) {
7542 mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7543 FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
7544 } else {
7545 mFlashlightTurnedOnTimer = null;
7546 }
7547 if (in.readInt() != 0) {
7548 mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
7549 mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
7550 } else {
7551 mCameraTurnedOnTimer = null;
7552 }
7553 if (in.readInt() != 0) {
7554 mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7555 FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase, in);
7556 } else {
7557 mForegroundActivityTimer = null;
7558 }
7559 if (in.readInt() != 0) {
7560 mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
7561 FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase, in);
7562 } else {
7563 mForegroundServiceTimer = null;
7564 }
7565 if (in.readInt() != 0) {
7566 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
7567 AGGREGATED_WAKE_TYPE_PARTIAL, null,
7568 mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase,
7569 in);
7570 } else {
7571 mAggregatedPartialWakelockTimer = null;
7572 }
7573 if (in.readInt() != 0) {
7574 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
7575 mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
7576 mOnBatteryBackgroundTimeBase, in);
7577 } else {
7578 mBluetoothScanTimer = null;
7579 }
7580 if (in.readInt() != 0) {
7581 mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
7582 BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
7583 mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in);
7584 } else {
7585 mBluetoothUnoptimizedScanTimer = null;
7586 }
7587 if (in.readInt() != 0) {
7588 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase, in);
7589 } else {
7590 mBluetoothScanResultCounter = null;
7591 }
7592 if (in.readInt() != 0) {
7593 mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase, in);
7594 } else {
7595 mBluetoothScanResultBgCounter = null;
7596 }
7597 mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
7598 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
7599 if (in.readInt() != 0) {
7600 makeProcessState(i, in);
7601 } else {
7602 mProcessStateTimer[i] = null;
7603 }
7604 }
7605 if (in.readInt() != 0) {
7606 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
7607 mBsi.mOnBatteryTimeBase, in);
7608 } else {
7609 mVibratorOnTimer = null;
7610 }
7611 if (in.readInt() != 0) {
7612 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
7613 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
7614 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase, in);
7615 }
7616 } else {
7617 mUserActivityCounters = null;
7618 }
7619 if (in.readInt() != 0) {
7620 mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
7621 mNetworkPacketActivityCounters
7622 = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
7623 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7624 mNetworkByteActivityCounters[i]
7625 = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
7626 mNetworkPacketActivityCounters[i]
7627 = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
7628 }
7629 mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
7630 mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
7631 } else {
7632 mNetworkByteActivityCounters = null;
7633 mNetworkPacketActivityCounters = null;
7634 }
7635
7636 if (in.readInt() != 0) {
7637 mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7638 NUM_WIFI_TX_LEVELS, in);
7639 } else {
7640 mWifiControllerActivity = null;
7641 }
7642
7643 if (in.readInt() != 0) {
7644 mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7645 NUM_BT_TX_LEVELS, in);
7646 } else {
7647 mBluetoothControllerActivity = null;
7648 }
7649
7650 if (in.readInt() != 0) {
7651 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
7652 ModemActivityInfo.TX_POWER_LEVELS, in);
7653 } else {
7654 mModemControllerActivity = null;
7655 }
7656
7657 mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
7658 mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
7659
7660 if (in.readInt() != 0) {
7661 int numCpuClusters = in.readInt();
7662 if (mBsi.mPowerProfile != null && mBsi.mPowerProfile.getNumCpuClusters() != numCpuClusters) {
7663 throw new ParcelFormatException("Incompatible number of cpu clusters");
7664 }
7665
7666 mCpuClusterSpeedTimesUs = new LongSamplingCounter[numCpuClusters][];
7667 for (int cluster = 0; cluster < numCpuClusters; cluster++) {
7668 if (in.readInt() != 0) {
7669 int numSpeeds = in.readInt();
7670 if (mBsi.mPowerProfile != null &&
7671 mBsi.mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
7672 throw new ParcelFormatException("Incompatible number of cpu speeds");
7673 }
7674
7675 final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
7676 mCpuClusterSpeedTimesUs[cluster] = cpuSpeeds;
7677 for (int speed = 0; speed < numSpeeds; speed++) {
7678 if (in.readInt() != 0) {
7679 cpuSpeeds[speed] = new LongSamplingCounter(
7680 mBsi.mOnBatteryTimeBase, in);
7681 }
7682 }
7683 } else {
7684 mCpuClusterSpeedTimesUs[cluster] = null;
7685 }
7686 }
7687 } else {
7688 mCpuClusterSpeedTimesUs = null;
7689 }
7690
7691 mCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(in, mBsi.mOnBatteryTimeBase);
7692 mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(
7693 in, mBsi.mOnBatteryScreenOffTimeBase);
7694
7695 if (in.readInt() != 0) {
7696 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
7697 } else {
7698 mMobileRadioApWakeupCount = null;
7699 }
7700
7701 if (in.readInt() != 0) {
7702 mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
7703 } else {
7704 mWifiRadioApWakeupCount = null;
7705 }
7706 }
7707
7708 /**
7709 * The statistics associated with a particular wake lock.
7710 */
7711 public static class Wakelock extends BatteryStats.Uid.Wakelock {
7712 /**
7713 * BatteryStatsImpl that we are associated with.
7714 */
7715 protected BatteryStatsImpl mBsi;
7716
7717 /**
7718 * BatteryStatsImpl that we are associated with.
7719 */
7720 protected Uid mUid;
7721
7722 /**
7723 * How long (in ms) this uid has been keeping the device partially awake.
7724 * Tracks both the total time and the time while the app was in the background.
7725 */
7726 DualTimer mTimerPartial;
7727
7728 /**
7729 * How long (in ms) this uid has been keeping the device fully awake.
7730 */
7731 StopwatchTimer mTimerFull;
7732
7733 /**
7734 * How long (in ms) this uid has had a window keeping the device awake.
7735 */
7736 StopwatchTimer mTimerWindow;
7737
7738 /**
7739 * How long (in ms) this uid has had a draw wake lock.
7740 */
7741 StopwatchTimer mTimerDraw;
7742
7743 public Wakelock(BatteryStatsImpl bsi, Uid uid) {
7744 mBsi = bsi;
7745 mUid = uid;
7746 }
7747
7748 /**
7749 * Reads a possibly null Timer from a Parcel. The timer is associated with the
7750 * proper timer pool from the given BatteryStatsImpl object.
7751 *
7752 * @param in the Parcel to be read from.
7753 * return a new Timer, or null.
7754 */
7755 private StopwatchTimer readStopwatchTimerFromParcel(int type,
7756 ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
7757 if (in.readInt() == 0) {
7758 return null;
7759 }
7760
7761 return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
7762 }
7763
7764 /**
7765 * Reads a possibly null Timer from a Parcel. The timer is associated with the
7766 * proper timer pool from the given BatteryStatsImpl object.
7767 *
7768 * @param in the Parcel to be read from.
7769 * return a new Timer, or null.
7770 */
7771 private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
7772 TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
7773 if (in.readInt() == 0) {
7774 return null;
7775 }
7776
7777 return new DualTimer(mBsi.mClocks, mUid, type, pool, timeBase, bgTimeBase, in);
7778 }
7779
7780 boolean reset() {
7781 boolean wlactive = false;
7782 if (mTimerFull != null) {
7783 wlactive |= !mTimerFull.reset(false);
7784 }
7785 if (mTimerPartial != null) {
7786 wlactive |= !mTimerPartial.reset(false);
7787 }
7788 if (mTimerWindow != null) {
7789 wlactive |= !mTimerWindow.reset(false);
7790 }
7791 if (mTimerDraw != null) {
7792 wlactive |= !mTimerDraw.reset(false);
7793 }
7794 if (!wlactive) {
7795 if (mTimerFull != null) {
7796 mTimerFull.detach();
7797 mTimerFull = null;
7798 }
7799 if (mTimerPartial != null) {
7800 mTimerPartial.detach();
7801 mTimerPartial = null;
7802 }
7803 if (mTimerWindow != null) {
7804 mTimerWindow.detach();
7805 mTimerWindow = null;
7806 }
7807 if (mTimerDraw != null) {
7808 mTimerDraw.detach();
7809 mTimerDraw = null;
7810 }
7811 }
7812 return !wlactive;
7813 }
7814
7815 void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase,
7816 TimeBase screenOffBgTimeBase, Parcel in) {
7817 mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL,
7818 mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in);
7819 mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
7820 mBsi.mFullTimers, timeBase, in);
7821 mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
7822 mBsi.mWindowTimers, timeBase, in);
7823 mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
7824 mBsi.mDrawTimers, timeBase, in);
7825 }
7826
7827 void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
7828 Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
7829 Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
7830 Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
7831 Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
7832 }
7833
7834 @Override
7835 public Timer getWakeTime(int type) {
7836 switch (type) {
7837 case WAKE_TYPE_FULL: return mTimerFull;
7838 case WAKE_TYPE_PARTIAL: return mTimerPartial;
7839 case WAKE_TYPE_WINDOW: return mTimerWindow;
7840 case WAKE_TYPE_DRAW: return mTimerDraw;
7841 default: throw new IllegalArgumentException("type = " + type);
7842 }
7843 }
7844 }
7845
7846 public static class Sensor extends BatteryStats.Uid.Sensor {
7847 /**
7848 * BatteryStatsImpl that we are associated with.
7849 */
7850 protected BatteryStatsImpl mBsi;
7851
7852 /**
7853 * Uid that we are associated with.
7854 */
7855 protected Uid mUid;
7856
7857 final int mHandle;
7858 DualTimer mTimer;
7859
7860 public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
7861 mBsi = bsi;
7862 mUid = uid;
7863 mHandle = handle;
7864 }
7865
7866 private DualTimer readTimersFromParcel(
7867 TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
7868 if (in.readInt() == 0) {
7869 return null;
7870 }
7871
7872 ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
7873 if (pool == null) {
7874 pool = new ArrayList<StopwatchTimer>();
7875 mBsi.mSensorTimers.put(mHandle, pool);
7876 }
7877 return new DualTimer(mBsi.mClocks, mUid, 0, pool, timeBase, bgTimeBase, in);
7878 }
7879
7880 boolean reset() {
7881 if (mTimer.reset(true)) {
7882 mTimer = null;
7883 return true;
7884 }
7885 return false;
7886 }
7887
7888 void readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
7889 mTimer = readTimersFromParcel(timeBase, bgTimeBase, in);
7890 }
7891
7892 void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
7893 Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
7894 }
7895
7896 @Override
7897 public Timer getSensorTime() {
7898 return mTimer;
7899 }
7900
7901 @Override
7902 public Timer getSensorBackgroundTime() {
7903 if (mTimer == null) {
7904 return null;
7905 }
7906 return mTimer.getSubTimer();
7907 }
7908
7909 @Override
7910 public int getHandle() {
7911 return mHandle;
7912 }
7913 }
7914
7915 /**
7916 * The statistics associated with a particular process.
7917 */
7918 public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
7919 /**
7920 * BatteryStatsImpl that we are associated with.
7921 */
7922 protected BatteryStatsImpl mBsi;
7923
7924 /**
7925 * The name of this process.
7926 */
7927 final String mName;
7928
7929 /**
7930 * Remains true until removed from the stats.
7931 */
7932 boolean mActive = true;
7933
7934 /**
7935 * Total time (in ms) spent executing in user code.
7936 */
7937 long mUserTime;
7938
7939 /**
7940 * Total time (in ms) spent executing in kernel code.
7941 */
7942 long mSystemTime;
7943
7944 /**
7945 * Amount of time (in ms) the process was running in the foreground.
7946 */
7947 long mForegroundTime;
7948
7949 /**
7950 * Number of times the process has been started.
7951 */
7952 int mStarts;
7953
7954 /**
7955 * Number of times the process has crashed.
7956 */
7957 int mNumCrashes;
7958
7959 /**
7960 * Number of times the process has had an ANR.
7961 */
7962 int mNumAnrs;
7963
7964 /**
7965 * The amount of user time loaded from a previous save.
7966 */
7967 long mLoadedUserTime;
7968
7969 /**
7970 * The amount of system time loaded from a previous save.
7971 */
7972 long mLoadedSystemTime;
7973
7974 /**
7975 * The amount of foreground time loaded from a previous save.
7976 */
7977 long mLoadedForegroundTime;
7978
7979 /**
7980 * The number of times the process has started from a previous save.
7981 */
7982 int mLoadedStarts;
7983
7984 /**
7985 * Number of times the process has crashed from a previous save.
7986 */
7987 int mLoadedNumCrashes;
7988
7989 /**
7990 * Number of times the process has had an ANR from a previous save.
7991 */
7992 int mLoadedNumAnrs;
7993
7994 /**
7995 * The amount of user time when last unplugged.
7996 */
7997 long mUnpluggedUserTime;
7998
7999 /**
8000 * The amount of system time when last unplugged.
8001 */
8002 long mUnpluggedSystemTime;
8003
8004 /**
8005 * The amount of foreground time since unplugged.
8006 */
8007 long mUnpluggedForegroundTime;
8008
8009 /**
8010 * The number of times the process has started before unplugged.
8011 */
8012 int mUnpluggedStarts;
8013
8014 /**
8015 * Number of times the process has crashed before unplugged.
8016 */
8017 int mUnpluggedNumCrashes;
8018
8019 /**
8020 * Number of times the process has had an ANR before unplugged.
8021 */
8022 int mUnpluggedNumAnrs;
8023
8024 ArrayList<ExcessivePower> mExcessivePower;
8025
8026 public Proc(BatteryStatsImpl bsi, String name) {
8027 mBsi = bsi;
8028 mName = name;
8029 mBsi.mOnBatteryTimeBase.add(this);
8030 }
8031
8032 public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
8033 mUnpluggedUserTime = mUserTime;
8034 mUnpluggedSystemTime = mSystemTime;
8035 mUnpluggedForegroundTime = mForegroundTime;
8036 mUnpluggedStarts = mStarts;
8037 mUnpluggedNumCrashes = mNumCrashes;
8038 mUnpluggedNumAnrs = mNumAnrs;
8039 }
8040
8041 public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
8042 }
8043
8044 void detach() {
8045 mActive = false;
8046 mBsi.mOnBatteryTimeBase.remove(this);
8047 }
8048
8049 public int countExcessivePowers() {
8050 return mExcessivePower != null ? mExcessivePower.size() : 0;
8051 }
8052
8053 public ExcessivePower getExcessivePower(int i) {
8054 if (mExcessivePower != null) {
8055 return mExcessivePower.get(i);
8056 }
8057 return null;
8058 }
8059
8060 public void addExcessiveCpu(long overTime, long usedTime) {
8061 if (mExcessivePower == null) {
8062 mExcessivePower = new ArrayList<ExcessivePower>();
8063 }
8064 ExcessivePower ew = new ExcessivePower();
8065 ew.type = ExcessivePower.TYPE_CPU;
8066 ew.overTime = overTime;
8067 ew.usedTime = usedTime;
8068 mExcessivePower.add(ew);
8069 }
8070
8071 void writeExcessivePowerToParcelLocked(Parcel out) {
8072 if (mExcessivePower == null) {
8073 out.writeInt(0);
8074 return;
8075 }
8076
8077 final int N = mExcessivePower.size();
8078 out.writeInt(N);
8079 for (int i=0; i<N; i++) {
8080 ExcessivePower ew = mExcessivePower.get(i);
8081 out.writeInt(ew.type);
8082 out.writeLong(ew.overTime);
8083 out.writeLong(ew.usedTime);
8084 }
8085 }
8086
8087 void readExcessivePowerFromParcelLocked(Parcel in) {
8088 final int N = in.readInt();
8089 if (N == 0) {
8090 mExcessivePower = null;
8091 return;
8092 }
8093
8094 if (N > 10000) {
8095 throw new ParcelFormatException(
8096 "File corrupt: too many excessive power entries " + N);
8097 }
8098
8099 mExcessivePower = new ArrayList<>();
8100 for (int i=0; i<N; i++) {
8101 ExcessivePower ew = new ExcessivePower();
8102 ew.type = in.readInt();
8103 ew.overTime = in.readLong();
8104 ew.usedTime = in.readLong();
8105 mExcessivePower.add(ew);
8106 }
8107 }
8108
8109 void writeToParcelLocked(Parcel out) {
8110 out.writeLong(mUserTime);
8111 out.writeLong(mSystemTime);
8112 out.writeLong(mForegroundTime);
8113 out.writeInt(mStarts);
8114 out.writeInt(mNumCrashes);
8115 out.writeInt(mNumAnrs);
8116 out.writeLong(mLoadedUserTime);
8117 out.writeLong(mLoadedSystemTime);
8118 out.writeLong(mLoadedForegroundTime);
8119 out.writeInt(mLoadedStarts);
8120 out.writeInt(mLoadedNumCrashes);
8121 out.writeInt(mLoadedNumAnrs);
8122 out.writeLong(mUnpluggedUserTime);
8123 out.writeLong(mUnpluggedSystemTime);
8124 out.writeLong(mUnpluggedForegroundTime);
8125 out.writeInt(mUnpluggedStarts);
8126 out.writeInt(mUnpluggedNumCrashes);
8127 out.writeInt(mUnpluggedNumAnrs);
8128 writeExcessivePowerToParcelLocked(out);
8129 }
8130
8131 void readFromParcelLocked(Parcel in) {
8132 mUserTime = in.readLong();
8133 mSystemTime = in.readLong();
8134 mForegroundTime = in.readLong();
8135 mStarts = in.readInt();
8136 mNumCrashes = in.readInt();
8137 mNumAnrs = in.readInt();
8138 mLoadedUserTime = in.readLong();
8139 mLoadedSystemTime = in.readLong();
8140 mLoadedForegroundTime = in.readLong();
8141 mLoadedStarts = in.readInt();
8142 mLoadedNumCrashes = in.readInt();
8143 mLoadedNumAnrs = in.readInt();
8144 mUnpluggedUserTime = in.readLong();
8145 mUnpluggedSystemTime = in.readLong();
8146 mUnpluggedForegroundTime = in.readLong();
8147 mUnpluggedStarts = in.readInt();
8148 mUnpluggedNumCrashes = in.readInt();
8149 mUnpluggedNumAnrs = in.readInt();
8150 readExcessivePowerFromParcelLocked(in);
8151 }
8152
8153 public void addCpuTimeLocked(int utime, int stime) {
8154 mUserTime += utime;
8155 mSystemTime += stime;
8156 }
8157
8158 public void addForegroundTimeLocked(long ttime) {
8159 mForegroundTime += ttime;
8160 }
8161
8162 public void incStartsLocked() {
8163 mStarts++;
8164 }
8165
8166 public void incNumCrashesLocked() {
8167 mNumCrashes++;
8168 }
8169
8170 public void incNumAnrsLocked() {
8171 mNumAnrs++;
8172 }
8173
8174 @Override
8175 public boolean isActive() {
8176 return mActive;
8177 }
8178
8179 @Override
8180 public long getUserTime(int which) {
8181 long val = mUserTime;
8182 if (which == STATS_CURRENT) {
8183 val -= mLoadedUserTime;
8184 } else if (which == STATS_SINCE_UNPLUGGED) {
8185 val -= mUnpluggedUserTime;
8186 }
8187 return val;
8188 }
8189
8190 @Override
8191 public long getSystemTime(int which) {
8192 long val = mSystemTime;
8193 if (which == STATS_CURRENT) {
8194 val -= mLoadedSystemTime;
8195 } else if (which == STATS_SINCE_UNPLUGGED) {
8196 val -= mUnpluggedSystemTime;
8197 }
8198 return val;
8199 }
8200
8201 @Override
8202 public long getForegroundTime(int which) {
8203 long val = mForegroundTime;
8204 if (which == STATS_CURRENT) {
8205 val -= mLoadedForegroundTime;
8206 } else if (which == STATS_SINCE_UNPLUGGED) {
8207 val -= mUnpluggedForegroundTime;
8208 }
8209 return val;
8210 }
8211
8212 @Override
8213 public int getStarts(int which) {
8214 int val = mStarts;
8215 if (which == STATS_CURRENT) {
8216 val -= mLoadedStarts;
8217 } else if (which == STATS_SINCE_UNPLUGGED) {
8218 val -= mUnpluggedStarts;
8219 }
8220 return val;
8221 }
8222
8223 @Override
8224 public int getNumCrashes(int which) {
8225 int val = mNumCrashes;
8226 if (which == STATS_CURRENT) {
8227 val -= mLoadedNumCrashes;
8228 } else if (which == STATS_SINCE_UNPLUGGED) {
8229 val -= mUnpluggedNumCrashes;
8230 }
8231 return val;
8232 }
8233
8234 @Override
8235 public int getNumAnrs(int which) {
8236 int val = mNumAnrs;
8237 if (which == STATS_CURRENT) {
8238 val -= mLoadedNumAnrs;
8239 } else if (which == STATS_SINCE_UNPLUGGED) {
8240 val -= mUnpluggedNumAnrs;
8241 }
8242 return val;
8243 }
8244 }
8245
8246 /**
8247 * The statistics associated with a particular package.
8248 */
8249 public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
8250 /**
8251 * BatteryStatsImpl that we are associated with.
8252 */
8253 protected BatteryStatsImpl mBsi;
8254
8255 /**
8256 * Number of times wakeup alarms have occurred for this app.
8257 * On screen-off timebase starting in report v25.
8258 */
8259 ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
8260
8261 /**
8262 * The statics we have collected for this package's services.
8263 */
8264 final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
8265
8266 public Pkg(BatteryStatsImpl bsi) {
8267 mBsi = bsi;
8268 mBsi.mOnBatteryScreenOffTimeBase.add(this);
8269 }
8270
8271 public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
8272 }
8273
8274 public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
8275 }
8276
8277 void detach() {
8278 mBsi.mOnBatteryScreenOffTimeBase.remove(this);
8279 }
8280
8281 void readFromParcelLocked(Parcel in) {
8282 int numWA = in.readInt();
8283 mWakeupAlarms.clear();
8284 for (int i=0; i<numWA; i++) {
8285 String tag = in.readString();
8286 mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryScreenOffTimeBase, in));
8287 }
8288
8289 int numServs = in.readInt();
8290 mServiceStats.clear();
8291 for (int m = 0; m < numServs; m++) {
8292 String serviceName = in.readString();
8293 Uid.Pkg.Serv serv = new Serv(mBsi);
8294 mServiceStats.put(serviceName, serv);
8295
8296 serv.readFromParcelLocked(in);
8297 }
8298 }
8299
8300 void writeToParcelLocked(Parcel out) {
8301 int numWA = mWakeupAlarms.size();
8302 out.writeInt(numWA);
8303 for (int i=0; i<numWA; i++) {
8304 out.writeString(mWakeupAlarms.keyAt(i));
8305 mWakeupAlarms.valueAt(i).writeToParcel(out);
8306 }
8307
8308 final int NS = mServiceStats.size();
8309 out.writeInt(NS);
8310 for (int i=0; i<NS; i++) {
8311 out.writeString(mServiceStats.keyAt(i));
8312 Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
8313 serv.writeToParcelLocked(out);
8314 }
8315 }
8316
8317 @Override
8318 public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
8319 return mWakeupAlarms;
8320 }
8321
8322 public void noteWakeupAlarmLocked(String tag) {
8323 Counter c = mWakeupAlarms.get(tag);
8324 if (c == null) {
8325 c = new Counter(mBsi.mOnBatteryScreenOffTimeBase);
8326 mWakeupAlarms.put(tag, c);
8327 }
8328 c.stepAtomic();
8329 }
8330
8331 @Override
8332 public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
8333 return mServiceStats;
8334 }
8335
8336 /**
8337 * The statistics associated with a particular service.
8338 */
8339 public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
8340 /**
8341 * BatteryStatsImpl that we are associated with.
8342 */
8343 protected BatteryStatsImpl mBsi;
8344
8345 /**
8346 * The android package in which this service resides.
8347 */
8348 protected Pkg mPkg;
8349
8350 /**
8351 * Total time (ms in battery uptime) the service has been left started.
8352 */
8353 protected long mStartTime;
8354
8355 /**
8356 * If service has been started and not yet stopped, this is
8357 * when it was started.
8358 */
8359 protected long mRunningSince;
8360
8361 /**
8362 * True if we are currently running.
8363 */
8364 protected boolean mRunning;
8365
8366 /**
8367 * Total number of times startService() has been called.
8368 */
8369 protected int mStarts;
8370
8371 /**
8372 * Total time (ms in battery uptime) the service has been left launched.
8373 */
8374 protected long mLaunchedTime;
8375
8376 /**
8377 * If service has been launched and not yet exited, this is
8378 * when it was launched (ms in battery uptime).
8379 */
8380 protected long mLaunchedSince;
8381
8382 /**
8383 * True if we are currently launched.
8384 */
8385 protected boolean mLaunched;
8386
8387 /**
8388 * Total number times the service has been launched.
8389 */
8390 protected int mLaunches;
8391
8392 /**
8393 * The amount of time spent started loaded from a previous save
8394 * (ms in battery uptime).
8395 */
8396 protected long mLoadedStartTime;
8397
8398 /**
8399 * The number of starts loaded from a previous save.
8400 */
8401 protected int mLoadedStarts;
8402
8403 /**
8404 * The number of launches loaded from a previous save.
8405 */
8406 protected int mLoadedLaunches;
8407
8408 /**
8409 * The amount of time spent started as of the last run (ms
8410 * in battery uptime).
8411 */
8412 protected long mLastStartTime;
8413
8414 /**
8415 * The number of starts as of the last run.
8416 */
8417 protected int mLastStarts;
8418
8419 /**
8420 * The number of launches as of the last run.
8421 */
8422 protected int mLastLaunches;
8423
8424 /**
8425 * The amount of time spent started when last unplugged (ms
8426 * in battery uptime).
8427 */
8428 protected long mUnpluggedStartTime;
8429
8430 /**
8431 * The number of starts when last unplugged.
8432 */
8433 protected int mUnpluggedStarts;
8434
8435 /**
8436 * The number of launches when last unplugged.
8437 */
8438 protected int mUnpluggedLaunches;
8439
8440 /**
8441 * Construct a Serv. Also adds it to the on-battery time base as a listener.
8442 */
8443 public Serv(BatteryStatsImpl bsi) {
8444 mBsi = bsi;
8445 mBsi.mOnBatteryTimeBase.add(this);
8446 }
8447
8448 public void onTimeStarted(long elapsedRealtime, long baseUptime,
8449 long baseRealtime) {
8450 mUnpluggedStartTime = getStartTimeToNowLocked(baseUptime);
8451 mUnpluggedStarts = mStarts;
8452 mUnpluggedLaunches = mLaunches;
8453 }
8454
8455 public void onTimeStopped(long elapsedRealtime, long baseUptime,
8456 long baseRealtime) {
8457 }
8458
8459 /**
8460 * Remove this Serv as a listener from the time base.
8461 */
8462 public void detach() {
8463 mBsi.mOnBatteryTimeBase.remove(this);
8464 }
8465
8466 public void readFromParcelLocked(Parcel in) {
8467 mStartTime = in.readLong();
8468 mRunningSince = in.readLong();
8469 mRunning = in.readInt() != 0;
8470 mStarts = in.readInt();
8471 mLaunchedTime = in.readLong();
8472 mLaunchedSince = in.readLong();
8473 mLaunched = in.readInt() != 0;
8474 mLaunches = in.readInt();
8475 mLoadedStartTime = in.readLong();
8476 mLoadedStarts = in.readInt();
8477 mLoadedLaunches = in.readInt();
8478 mLastStartTime = 0;
8479 mLastStarts = 0;
8480 mLastLaunches = 0;
8481 mUnpluggedStartTime = in.readLong();
8482 mUnpluggedStarts = in.readInt();
8483 mUnpluggedLaunches = in.readInt();
8484 }
8485
8486 public void writeToParcelLocked(Parcel out) {
8487 out.writeLong(mStartTime);
8488 out.writeLong(mRunningSince);
8489 out.writeInt(mRunning ? 1 : 0);
8490 out.writeInt(mStarts);
8491 out.writeLong(mLaunchedTime);
8492 out.writeLong(mLaunchedSince);
8493 out.writeInt(mLaunched ? 1 : 0);
8494 out.writeInt(mLaunches);
8495 out.writeLong(mLoadedStartTime);
8496 out.writeInt(mLoadedStarts);
8497 out.writeInt(mLoadedLaunches);
8498 out.writeLong(mUnpluggedStartTime);
8499 out.writeInt(mUnpluggedStarts);
8500 out.writeInt(mUnpluggedLaunches);
8501 }
8502
8503 public long getLaunchTimeToNowLocked(long batteryUptime) {
8504 if (!mLaunched) return mLaunchedTime;
8505 return mLaunchedTime + batteryUptime - mLaunchedSince;
8506 }
8507
8508 public long getStartTimeToNowLocked(long batteryUptime) {
8509 if (!mRunning) return mStartTime;
8510 return mStartTime + batteryUptime - mRunningSince;
8511 }
8512
8513 public void startLaunchedLocked() {
8514 if (!mLaunched) {
8515 mLaunches++;
8516 mLaunchedSince = mBsi.getBatteryUptimeLocked();
8517 mLaunched = true;
8518 }
8519 }
8520
8521 public void stopLaunchedLocked() {
8522 if (mLaunched) {
8523 long time = mBsi.getBatteryUptimeLocked() - mLaunchedSince;
8524 if (time > 0) {
8525 mLaunchedTime += time;
8526 } else {
8527 mLaunches--;
8528 }
8529 mLaunched = false;
8530 }
8531 }
8532
8533 public void startRunningLocked() {
8534 if (!mRunning) {
8535 mStarts++;
8536 mRunningSince = mBsi.getBatteryUptimeLocked();
8537 mRunning = true;
8538 }
8539 }
8540
8541 public void stopRunningLocked() {
8542 if (mRunning) {
8543 long time = mBsi.getBatteryUptimeLocked() - mRunningSince;
8544 if (time > 0) {
8545 mStartTime += time;
8546 } else {
8547 mStarts--;
8548 }
8549 mRunning = false;
8550 }
8551 }
8552
8553 public BatteryStatsImpl getBatteryStats() {
8554 return mBsi;
8555 }
8556
8557 @Override
8558 public int getLaunches(int which) {
8559 int val = mLaunches;
8560 if (which == STATS_CURRENT) {
8561 val -= mLoadedLaunches;
8562 } else if (which == STATS_SINCE_UNPLUGGED) {
8563 val -= mUnpluggedLaunches;
8564 }
8565 return val;
8566 }
8567
8568 @Override
8569 public long getStartTime(long now, int which) {
8570 long val = getStartTimeToNowLocked(now);
8571 if (which == STATS_CURRENT) {
8572 val -= mLoadedStartTime;
8573 } else if (which == STATS_SINCE_UNPLUGGED) {
8574 val -= mUnpluggedStartTime;
8575 }
8576 return val;
8577 }
8578
8579 @Override
8580 public int getStarts(int which) {
8581 int val = mStarts;
8582 if (which == STATS_CURRENT) {
8583 val -= mLoadedStarts;
8584 } else if (which == STATS_SINCE_UNPLUGGED) {
8585 val -= mUnpluggedStarts;
8586 }
8587
8588 return val;
8589 }
8590 }
8591
8592 final Serv newServiceStatsLocked() {
8593 return new Serv(mBsi);
8594 }
8595 }
8596
8597 /**
8598 * Retrieve the statistics object for a particular process, creating
8599 * if needed.
8600 */
8601 public Proc getProcessStatsLocked(String name) {
8602 Proc ps = mProcessStats.get(name);
8603 if (ps == null) {
8604 ps = new Proc(mBsi, name);
8605 mProcessStats.put(name, ps);
8606 }
8607
8608 return ps;
8609 }
8610
8611 public void updateUidProcessStateLocked(int procState) {
8612 int uidRunningState;
8613 // Make special note of Foreground Services
8614 final boolean userAwareService =
8615 (procState == ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
8616 if (procState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
8617 uidRunningState = ActivityManager.PROCESS_STATE_NONEXISTENT;
8618 } else if (procState == ActivityManager.PROCESS_STATE_TOP) {
8619 uidRunningState = PROCESS_STATE_TOP;
8620 } else if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
8621 // Persistent and other foreground states go here.
8622 uidRunningState = PROCESS_STATE_FOREGROUND_SERVICE;
8623 } else if (procState <= ActivityManager.PROCESS_STATE_TOP_SLEEPING) {
8624 uidRunningState = PROCESS_STATE_TOP_SLEEPING;
8625 } else if (procState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
8626 // Persistent and other foreground states go here.
8627 uidRunningState = PROCESS_STATE_FOREGROUND;
8628 } else if (procState <= ActivityManager.PROCESS_STATE_RECEIVER) {
8629 uidRunningState = PROCESS_STATE_BACKGROUND;
8630 } else {
8631 uidRunningState = PROCESS_STATE_CACHED;
8632 }
8633
8634 if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
8635 return;
8636 }
8637
8638 final long elapsedRealtimeMs = mBsi.mClocks.elapsedRealtime();
8639 if (mProcessState != uidRunningState) {
8640 final long uptimeMs = mBsi.mClocks.uptimeMillis();
8641
8642 if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
8643 mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
8644 }
8645 mProcessState = uidRunningState;
8646 if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
8647 if (mProcessStateTimer[uidRunningState] == null) {
8648 makeProcessState(uidRunningState, null);
8649 }
8650 mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
8651 }
8652
8653 updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
8654 updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
8655 }
8656
8657 if (userAwareService != mInForegroundService) {
8658 if (userAwareService) {
8659 noteForegroundServiceResumedLocked(elapsedRealtimeMs);
8660 } else {
8661 noteForegroundServicePausedLocked(elapsedRealtimeMs);
8662 }
8663 mInForegroundService = userAwareService;
8664 }
8665 }
8666
8667 /** Whether to consider Uid to be in the background for background timebase purposes. */
8668 public boolean isInBackground() {
8669 // Note that PROCESS_STATE_CACHED and ActivityManager.PROCESS_STATE_NONEXISTENT is
8670 // also considered to be 'background' for our purposes, because it's not foreground.
8671 return mProcessState >= PROCESS_STATE_BACKGROUND;
8672 }
8673
8674 public boolean updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs) {
8675 boolean on = mBsi.mOnBatteryTimeBase.isRunning() && isInBackground();
8676 return mOnBatteryBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
8677 }
8678
8679 public boolean updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs) {
8680 boolean on = mBsi.mOnBatteryScreenOffTimeBase.isRunning() && isInBackground();
8681 return mOnBatteryScreenOffBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
8682 }
8683
8684 public SparseArray<? extends Pid> getPidStats() {
8685 return mPids;
8686 }
8687
8688 public Pid getPidStatsLocked(int pid) {
8689 Pid p = mPids.get(pid);
8690 if (p == null) {
8691 p = new Pid();
8692 mPids.put(pid, p);
8693 }
8694 return p;
8695 }
8696
8697 /**
8698 * Retrieve the statistics object for a particular service, creating
8699 * if needed.
8700 */
8701 public Pkg getPackageStatsLocked(String name) {
8702 Pkg ps = mPackageStats.get(name);
8703 if (ps == null) {
8704 ps = new Pkg(mBsi);
8705 mPackageStats.put(name, ps);
8706 }
8707
8708 return ps;
8709 }
8710
8711 /**
8712 * Retrieve the statistics object for a particular service, creating
8713 * if needed.
8714 */
8715 public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
8716 Pkg ps = getPackageStatsLocked(pkg);
8717 Pkg.Serv ss = ps.mServiceStats.get(serv);
8718 if (ss == null) {
8719 ss = ps.newServiceStatsLocked();
8720 ps.mServiceStats.put(serv, ss);
8721 }
8722
8723 return ss;
8724 }
8725
8726 public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
8727 DualTimer timer = mSyncStats.instantiateObject();
8728 timer.readSummaryFromParcelLocked(in);
8729 mSyncStats.add(name, timer);
8730 }
8731
8732 public void readJobSummaryFromParcelLocked(String name, Parcel in) {
8733 DualTimer timer = mJobStats.instantiateObject();
8734 timer.readSummaryFromParcelLocked(in);
8735 mJobStats.add(name, timer);
8736 }
8737
8738 public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
8739 Wakelock wl = new Wakelock(mBsi, this);
8740 mWakelockStats.add(wlName, wl);
8741 if (in.readInt() != 0) {
8742 getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
8743 }
8744 if (in.readInt() != 0) {
8745 getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
8746 }
8747 if (in.readInt() != 0) {
8748 getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
8749 }
8750 if (in.readInt() != 0) {
8751 getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
8752 }
8753 }
8754
8755 public DualTimer getSensorTimerLocked(int sensor, boolean create) {
8756 Sensor se = mSensorStats.get(sensor);
8757 if (se == null) {
8758 if (!create) {
8759 return null;
8760 }
8761 se = new Sensor(mBsi, this, sensor);
8762 mSensorStats.put(sensor, se);
8763 }
8764 DualTimer t = se.mTimer;
8765 if (t != null) {
8766 return t;
8767 }
8768 ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
8769 if (timers == null) {
8770 timers = new ArrayList<StopwatchTimer>();
8771 mBsi.mSensorTimers.put(sensor, timers);
8772 }
8773 t = new DualTimer(mBsi.mClocks, this, BatteryStats.SENSOR, timers,
8774 mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8775 se.mTimer = t;
8776 return t;
8777 }
8778
8779 public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
8780 DualTimer t = mSyncStats.startObject(name);
8781 if (t != null) {
8782 t.startRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04008783 // TODO(statsd): Possibly use a worksource instead of a uid.
8784 StatsLog.write(StatsLog.SYNC_STATE_CHANGED, getUid(), name, 1);
Justin Klaassen10d07c82017-09-15 17:58:39 -04008785 }
8786 }
8787
8788 public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
8789 DualTimer t = mSyncStats.stopObject(name);
8790 if (t != null) {
8791 t.stopRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04008792 if (!t.isRunningLocked()) { // only tell statsd if truly stopped
8793 // TODO(statsd): Possibly use a worksource instead of a uid.
8794 StatsLog.write(StatsLog.SYNC_STATE_CHANGED, getUid(), name, 0);
8795 }
Justin Klaassen10d07c82017-09-15 17:58:39 -04008796 }
8797 }
8798
8799 public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
8800 DualTimer t = mJobStats.startObject(name);
8801 if (t != null) {
8802 t.startRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04008803 // TODO(statsd): Possibly use a worksource instead of a uid.
8804 StatsLog.write(StatsLog.SCHEDULED_JOB_STATE_CHANGED, getUid(), name, 1);
Justin Klaassen10d07c82017-09-15 17:58:39 -04008805 }
8806 }
8807
8808 public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
8809 DualTimer t = mJobStats.stopObject(name);
8810 if (t != null) {
8811 t.stopRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04008812 if (!t.isRunningLocked()) { // only tell statsd if truly stopped
8813 // TODO(statsd): Possibly use a worksource instead of a uid.
8814 StatsLog.write(StatsLog.SCHEDULED_JOB_STATE_CHANGED, getUid(), name, 0);
8815 }
Justin Klaassen10d07c82017-09-15 17:58:39 -04008816 }
8817 if (mBsi.mOnBatteryTimeBase.isRunning()) {
8818 SparseIntArray types = mJobCompletions.get(name);
8819 if (types == null) {
8820 types = new SparseIntArray();
8821 mJobCompletions.put(name, types);
8822 }
8823 int last = types.get(stopReason, 0);
8824 types.put(stopReason, last + 1);
8825 }
8826 }
8827
8828 public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
8829 if (wl == null) {
8830 return null;
8831 }
8832 switch (type) {
8833 case WAKE_TYPE_PARTIAL: {
8834 DualTimer t = wl.mTimerPartial;
8835 if (t == null) {
8836 t = new DualTimer(mBsi.mClocks, this, WAKE_TYPE_PARTIAL,
8837 mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase,
8838 mOnBatteryScreenOffBackgroundTimeBase);
8839 wl.mTimerPartial = t;
8840 }
8841 return t;
8842 }
8843 case WAKE_TYPE_FULL: {
8844 StopwatchTimer t = wl.mTimerFull;
8845 if (t == null) {
8846 t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_FULL,
8847 mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
8848 wl.mTimerFull = t;
8849 }
8850 return t;
8851 }
8852 case WAKE_TYPE_WINDOW: {
8853 StopwatchTimer t = wl.mTimerWindow;
8854 if (t == null) {
8855 t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_WINDOW,
8856 mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
8857 wl.mTimerWindow = t;
8858 }
8859 return t;
8860 }
8861 case WAKE_TYPE_DRAW: {
8862 StopwatchTimer t = wl.mTimerDraw;
8863 if (t == null) {
8864 t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_DRAW,
8865 mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
8866 wl.mTimerDraw = t;
8867 }
8868 return t;
8869 }
8870 default:
8871 throw new IllegalArgumentException("type=" + type);
8872 }
8873 }
8874
8875 public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
8876 Wakelock wl = mWakelockStats.startObject(name);
8877 if (wl != null) {
8878 getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
8879 }
8880 if (type == WAKE_TYPE_PARTIAL) {
8881 createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04008882 // TODO(statsd): Possibly use a worksource instead of a uid.
8883 StatsLog.write(StatsLog.UID_WAKELOCK_STATE_CHANGED, getUid(), type, 1);
Justin Klaassen10d07c82017-09-15 17:58:39 -04008884 if (pid >= 0) {
8885 Pid p = getPidStatsLocked(pid);
8886 if (p.mWakeNesting++ == 0) {
8887 p.mWakeStartMs = elapsedRealtimeMs;
8888 }
8889 }
8890 }
8891 }
8892
8893 public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
8894 Wakelock wl = mWakelockStats.stopObject(name);
8895 if (wl != null) {
8896 getWakelockTimerLocked(wl, type).stopRunningLocked(elapsedRealtimeMs);
8897 }
8898 if (type == WAKE_TYPE_PARTIAL) {
8899 if (mAggregatedPartialWakelockTimer != null) {
8900 mAggregatedPartialWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04008901 if (!mAggregatedPartialWakelockTimer.isRunningLocked()) {
8902 // TODO(statsd): Possibly use a worksource instead of a uid.
8903 StatsLog.write(StatsLog.UID_WAKELOCK_STATE_CHANGED, getUid(), type,
8904 0);
8905 }
Justin Klaassen10d07c82017-09-15 17:58:39 -04008906 }
8907 if (pid >= 0) {
8908 Pid p = mPids.get(pid);
8909 if (p != null && p.mWakeNesting > 0) {
8910 if (p.mWakeNesting-- == 1) {
8911 p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
8912 p.mWakeStartMs = 0;
8913 }
8914 }
8915 }
8916 }
8917 }
8918
8919 public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
8920 Proc p = getProcessStatsLocked(proc);
8921 if (p != null) {
8922 p.addExcessiveCpu(overTime, usedTime);
8923 }
8924 }
8925
8926 public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
8927 DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
8928 t.startRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04008929 // TODO(statsd): Possibly use a worksource instead of a uid.
8930 if (sensor == Sensor.GPS) {
8931 StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, getUid(), 1);
8932 } else {
8933 StatsLog.write(StatsLog.SENSOR_STATE_CHANGED, getUid(), sensor, 1);
8934 }
Justin Klaassen10d07c82017-09-15 17:58:39 -04008935 }
8936
8937 public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
8938 // Don't create a timer if one doesn't already exist
8939 DualTimer t = getSensorTimerLocked(sensor, false);
8940 if (t != null) {
8941 t.stopRunningLocked(elapsedRealtimeMs);
Justin Klaassen47ed54e2017-10-24 19:50:40 -04008942 if (!t.isRunningLocked()) { // only tell statsd if truly stopped
8943 // TODO(statsd): Possibly use a worksource instead of a uid.
8944 if (sensor == Sensor.GPS) {
8945 StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, getUid(), 0);
8946 } else {
8947 StatsLog.write(StatsLog.SENSOR_STATE_CHANGED, getUid(), sensor, 0);
8948 }
8949 }
Justin Klaassen10d07c82017-09-15 17:58:39 -04008950 }
8951 }
8952
8953 public void noteStartGps(long elapsedRealtimeMs) {
8954 noteStartSensor(Sensor.GPS, elapsedRealtimeMs);
8955 }
8956
8957 public void noteStopGps(long elapsedRealtimeMs) {
8958 noteStopSensor(Sensor.GPS, elapsedRealtimeMs);
8959 }
8960
8961 public BatteryStatsImpl getBatteryStats() {
8962 return mBsi;
8963 }
8964 }
8965
8966 public long[] getCpuFreqs() {
8967 return mCpuFreqs;
8968 }
8969
8970 public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
8971 UserInfoProvider userInfoProvider) {
8972 this(new SystemClocks(), systemDir, handler, cb, userInfoProvider);
8973 }
8974
8975 private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
8976 PlatformIdleStateCallback cb,
8977 UserInfoProvider userInfoProvider) {
8978 init(clocks);
8979
8980 if (systemDir != null) {
8981 mFile = new JournaledFile(new File(systemDir, "batterystats.bin"),
8982 new File(systemDir, "batterystats.bin.tmp"));
8983 } else {
8984 mFile = null;
8985 }
8986 mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
8987 mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
8988 mHandler = new MyHandler(handler.getLooper());
8989 mStartCount++;
8990 mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
Justin Klaassen93b7ee42017-10-10 15:20:13 -04008991 mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
Justin Klaassen10d07c82017-09-15 17:58:39 -04008992 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
8993 mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
8994 mOnBatteryTimeBase);
8995 }
8996 mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase);
8997 mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
8998 mOnBatteryTimeBase);
8999 mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -11, null,
9000 mOnBatteryTimeBase);
9001 mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
9002 mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null, mOnBatteryTimeBase);
9003 mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase);
9004 mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase);
9005 for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
9006 mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i, null,
9007 mOnBatteryTimeBase);
9008 }
9009 mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
9010 mOnBatteryTimeBase);
9011 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
9012 mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i, null,
9013 mOnBatteryTimeBase);
9014 }
9015 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9016 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
9017 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
9018 }
9019 mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
9020 mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
9021 NUM_BT_TX_LEVELS);
9022 mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
9023 ModemActivityInfo.TX_POWER_LEVELS);
9024 mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase);
9025 mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
9026 mOnBatteryTimeBase);
9027 mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
9028 mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
9029 mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
9030 mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase);
9031 mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null, mOnBatteryTimeBase);
9032 for (int i=0; i<NUM_WIFI_STATES; i++) {
9033 mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i, null,
9034 mOnBatteryTimeBase);
9035 }
9036 for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
9037 mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i, null,
9038 mOnBatteryTimeBase);
9039 }
9040 for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
9041 mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
9042 mOnBatteryTimeBase);
9043 }
9044 mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
9045 mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
9046 mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
9047 mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase);
9048 mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
9049 mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
Justin Klaassen93b7ee42017-10-10 15:20:13 -04009050 mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
Justin Klaassen10d07c82017-09-15 17:58:39 -04009051 mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
9052 mOnBattery = mOnBatteryInternal = false;
9053 long uptime = mClocks.uptimeMillis() * 1000;
9054 long realtime = mClocks.elapsedRealtime() * 1000;
9055 initTimes(uptime, realtime);
9056 mStartPlatformVersion = mEndPlatformVersion = Build.ID;
9057 mDischargeStartLevel = 0;
9058 mDischargeUnplugLevel = 0;
9059 mDischargePlugLevel = -1;
9060 mDischargeCurrentLevel = 0;
9061 mCurrentBatteryLevel = 0;
9062 initDischarge();
9063 clearHistoryLocked();
9064 updateDailyDeadlineLocked();
9065 mPlatformIdleStateCallback = cb;
9066 mUserInfoProvider = userInfoProvider;
9067 }
9068
9069 public BatteryStatsImpl(Parcel p) {
9070 this(new SystemClocks(), p);
9071 }
9072
9073 public BatteryStatsImpl(Clocks clocks, Parcel p) {
9074 init(clocks);
9075 mFile = null;
9076 mCheckinFile = null;
9077 mDailyFile = null;
9078 mHandler = null;
9079 mExternalSync = null;
9080 clearHistoryLocked();
9081 readFromParcel(p);
9082 mPlatformIdleStateCallback = null;
9083 }
9084
9085 public void setPowerProfileLocked(PowerProfile profile) {
9086 mPowerProfile = profile;
9087
9088 // We need to initialize the KernelCpuSpeedReaders to read from
9089 // the first cpu of each core. Once we have the PowerProfile, we have access to this
9090 // information.
9091 final int numClusters = mPowerProfile.getNumCpuClusters();
9092 mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
9093 int firstCpuOfCluster = 0;
9094 for (int i = 0; i < numClusters; i++) {
9095 final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
9096 mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
9097 numSpeedSteps);
9098 firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
9099 }
9100
9101 if (mEstimatedBatteryCapacity == -1) {
9102 // Initialize the estimated battery capacity to a known preset one.
9103 mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
9104 }
9105 }
9106
9107 public void setCallback(BatteryCallback cb) {
9108 mCallback = cb;
9109 }
9110
9111 public void setRadioScanningTimeoutLocked(long timeout) {
9112 if (mPhoneSignalScanningTimer != null) {
9113 mPhoneSignalScanningTimer.setTimeout(timeout);
9114 }
9115 }
9116
9117 public void setExternalStatsSyncLocked(ExternalStatsSync sync) {
9118 mExternalSync = sync;
9119 }
9120
9121 public void updateDailyDeadlineLocked() {
9122 // Get the current time.
9123 long currentTime = mDailyStartTime = System.currentTimeMillis();
9124 Calendar calDeadline = Calendar.getInstance();
9125 calDeadline.setTimeInMillis(currentTime);
9126
9127 // Move time up to the next day, ranging from 1am to 3pm.
9128 calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
9129 calDeadline.set(Calendar.MILLISECOND, 0);
9130 calDeadline.set(Calendar.SECOND, 0);
9131 calDeadline.set(Calendar.MINUTE, 0);
9132 calDeadline.set(Calendar.HOUR_OF_DAY, 1);
9133 mNextMinDailyDeadline = calDeadline.getTimeInMillis();
9134 calDeadline.set(Calendar.HOUR_OF_DAY, 3);
9135 mNextMaxDailyDeadline = calDeadline.getTimeInMillis();
9136 }
9137
9138 public void recordDailyStatsIfNeededLocked(boolean settled) {
9139 long currentTime = System.currentTimeMillis();
9140 if (currentTime >= mNextMaxDailyDeadline) {
9141 recordDailyStatsLocked();
9142 } else if (settled && currentTime >= mNextMinDailyDeadline) {
9143 recordDailyStatsLocked();
9144 } else if (currentTime < (mDailyStartTime-(1000*60*60*24))) {
9145 recordDailyStatsLocked();
9146 }
9147 }
9148
9149 public void recordDailyStatsLocked() {
9150 DailyItem item = new DailyItem();
9151 item.mStartTime = mDailyStartTime;
9152 item.mEndTime = System.currentTimeMillis();
9153 boolean hasData = false;
9154 if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
9155 hasData = true;
9156 item.mDischargeSteps = new LevelStepTracker(
9157 mDailyDischargeStepTracker.mNumStepDurations,
9158 mDailyDischargeStepTracker.mStepDurations);
9159 }
9160 if (mDailyChargeStepTracker.mNumStepDurations > 0) {
9161 hasData = true;
9162 item.mChargeSteps = new LevelStepTracker(
9163 mDailyChargeStepTracker.mNumStepDurations,
9164 mDailyChargeStepTracker.mStepDurations);
9165 }
9166 if (mDailyPackageChanges != null) {
9167 hasData = true;
9168 item.mPackageChanges = mDailyPackageChanges;
9169 mDailyPackageChanges = null;
9170 }
9171 mDailyDischargeStepTracker.init();
9172 mDailyChargeStepTracker.init();
9173 updateDailyDeadlineLocked();
9174
9175 if (hasData) {
9176 mDailyItems.add(item);
9177 while (mDailyItems.size() > MAX_DAILY_ITEMS) {
9178 mDailyItems.remove(0);
9179 }
9180 final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
9181 try {
9182 XmlSerializer out = new FastXmlSerializer();
9183 out.setOutput(memStream, StandardCharsets.UTF_8.name());
9184 writeDailyItemsLocked(out);
9185 BackgroundThread.getHandler().post(new Runnable() {
9186 @Override
9187 public void run() {
9188 synchronized (mCheckinFile) {
9189 FileOutputStream stream = null;
9190 try {
9191 stream = mDailyFile.startWrite();
9192 memStream.writeTo(stream);
9193 stream.flush();
9194 FileUtils.sync(stream);
9195 stream.close();
9196 mDailyFile.finishWrite(stream);
9197 } catch (IOException e) {
9198 Slog.w("BatteryStats",
9199 "Error writing battery daily items", e);
9200 mDailyFile.failWrite(stream);
9201 }
9202 }
9203 }
9204 });
9205 } catch (IOException e) {
9206 }
9207 }
9208 }
9209
9210 private void writeDailyItemsLocked(XmlSerializer out) throws IOException {
9211 StringBuilder sb = new StringBuilder(64);
9212 out.startDocument(null, true);
9213 out.startTag(null, "daily-items");
9214 for (int i=0; i<mDailyItems.size(); i++) {
9215 final DailyItem dit = mDailyItems.get(i);
9216 out.startTag(null, "item");
9217 out.attribute(null, "start", Long.toString(dit.mStartTime));
9218 out.attribute(null, "end", Long.toString(dit.mEndTime));
9219 writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
9220 writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
9221 if (dit.mPackageChanges != null) {
9222 for (int j=0; j<dit.mPackageChanges.size(); j++) {
9223 PackageChange pc = dit.mPackageChanges.get(j);
9224 if (pc.mUpdate) {
9225 out.startTag(null, "upd");
9226 out.attribute(null, "pkg", pc.mPackageName);
9227 out.attribute(null, "ver", Integer.toString(pc.mVersionCode));
9228 out.endTag(null, "upd");
9229 } else {
9230 out.startTag(null, "rem");
9231 out.attribute(null, "pkg", pc.mPackageName);
9232 out.endTag(null, "rem");
9233 }
9234 }
9235 }
9236 out.endTag(null, "item");
9237 }
9238 out.endTag(null, "daily-items");
9239 out.endDocument();
9240 }
9241
9242 private void writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps,
9243 StringBuilder tmpBuilder) throws IOException {
9244 if (steps != null) {
9245 out.startTag(null, tag);
9246 out.attribute(null, "n", Integer.toString(steps.mNumStepDurations));
9247 for (int i=0; i<steps.mNumStepDurations; i++) {
9248 out.startTag(null, "s");
9249 tmpBuilder.setLength(0);
9250 steps.encodeEntryAt(i, tmpBuilder);
9251 out.attribute(null, "v", tmpBuilder.toString());
9252 out.endTag(null, "s");
9253 }
9254 out.endTag(null, tag);
9255 }
9256 }
9257
9258 public void readDailyStatsLocked() {
9259 Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
9260 mDailyItems.clear();
9261 FileInputStream stream;
9262 try {
9263 stream = mDailyFile.openRead();
9264 } catch (FileNotFoundException e) {
9265 return;
9266 }
9267 try {
9268 XmlPullParser parser = Xml.newPullParser();
9269 parser.setInput(stream, StandardCharsets.UTF_8.name());
9270 readDailyItemsLocked(parser);
9271 } catch (XmlPullParserException e) {
9272 } finally {
9273 try {
9274 stream.close();
9275 } catch (IOException e) {
9276 }
9277 }
9278 }
9279
9280 private void readDailyItemsLocked(XmlPullParser parser) {
9281 try {
9282 int type;
9283 while ((type = parser.next()) != XmlPullParser.START_TAG
9284 && type != XmlPullParser.END_DOCUMENT) {
9285 ;
9286 }
9287
9288 if (type != XmlPullParser.START_TAG) {
9289 throw new IllegalStateException("no start tag found");
9290 }
9291
9292 int outerDepth = parser.getDepth();
9293 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
9294 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
9295 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
9296 continue;
9297 }
9298
9299 String tagName = parser.getName();
9300 if (tagName.equals("item")) {
9301 readDailyItemTagLocked(parser);
9302 } else {
9303 Slog.w(TAG, "Unknown element under <daily-items>: "
9304 + parser.getName());
9305 XmlUtils.skipCurrentTag(parser);
9306 }
9307 }
9308
9309 } catch (IllegalStateException e) {
9310 Slog.w(TAG, "Failed parsing daily " + e);
9311 } catch (NullPointerException e) {
9312 Slog.w(TAG, "Failed parsing daily " + e);
9313 } catch (NumberFormatException e) {
9314 Slog.w(TAG, "Failed parsing daily " + e);
9315 } catch (XmlPullParserException e) {
9316 Slog.w(TAG, "Failed parsing daily " + e);
9317 } catch (IOException e) {
9318 Slog.w(TAG, "Failed parsing daily " + e);
9319 } catch (IndexOutOfBoundsException e) {
9320 Slog.w(TAG, "Failed parsing daily " + e);
9321 }
9322 }
9323
9324 void readDailyItemTagLocked(XmlPullParser parser) throws NumberFormatException,
9325 XmlPullParserException, IOException {
9326 DailyItem dit = new DailyItem();
9327 String attr = parser.getAttributeValue(null, "start");
9328 if (attr != null) {
9329 dit.mStartTime = Long.parseLong(attr);
9330 }
9331 attr = parser.getAttributeValue(null, "end");
9332 if (attr != null) {
9333 dit.mEndTime = Long.parseLong(attr);
9334 }
9335 int outerDepth = parser.getDepth();
9336 int type;
9337 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
9338 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
9339 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
9340 continue;
9341 }
9342
9343 String tagName = parser.getName();
9344 if (tagName.equals("dis")) {
9345 readDailyItemTagDetailsLocked(parser, dit, false, "dis");
9346 } else if (tagName.equals("chg")) {
9347 readDailyItemTagDetailsLocked(parser, dit, true, "chg");
9348 } else if (tagName.equals("upd")) {
9349 if (dit.mPackageChanges == null) {
9350 dit.mPackageChanges = new ArrayList<>();
9351 }
9352 PackageChange pc = new PackageChange();
9353 pc.mUpdate = true;
9354 pc.mPackageName = parser.getAttributeValue(null, "pkg");
9355 String verStr = parser.getAttributeValue(null, "ver");
9356 pc.mVersionCode = verStr != null ? Integer.parseInt(verStr) : 0;
9357 dit.mPackageChanges.add(pc);
9358 XmlUtils.skipCurrentTag(parser);
9359 } else if (tagName.equals("rem")) {
9360 if (dit.mPackageChanges == null) {
9361 dit.mPackageChanges = new ArrayList<>();
9362 }
9363 PackageChange pc = new PackageChange();
9364 pc.mUpdate = false;
9365 pc.mPackageName = parser.getAttributeValue(null, "pkg");
9366 dit.mPackageChanges.add(pc);
9367 XmlUtils.skipCurrentTag(parser);
9368 } else {
9369 Slog.w(TAG, "Unknown element under <item>: "
9370 + parser.getName());
9371 XmlUtils.skipCurrentTag(parser);
9372 }
9373 }
9374 mDailyItems.add(dit);
9375 }
9376
9377 void readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge,
9378 String tag)
9379 throws NumberFormatException, XmlPullParserException, IOException {
9380 final String numAttr = parser.getAttributeValue(null, "n");
9381 if (numAttr == null) {
9382 Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
9383 XmlUtils.skipCurrentTag(parser);
9384 return;
9385 }
9386 final int num = Integer.parseInt(numAttr);
9387 LevelStepTracker steps = new LevelStepTracker(num);
9388 if (isCharge) {
9389 dit.mChargeSteps = steps;
9390 } else {
9391 dit.mDischargeSteps = steps;
9392 }
9393 int i = 0;
9394 int outerDepth = parser.getDepth();
9395 int type;
9396 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
9397 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
9398 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
9399 continue;
9400 }
9401
9402 String tagName = parser.getName();
9403 if ("s".equals(tagName)) {
9404 if (i < num) {
9405 String valueAttr = parser.getAttributeValue(null, "v");
9406 if (valueAttr != null) {
9407 steps.decodeEntryAt(i, valueAttr);
9408 i++;
9409 }
9410 }
9411 } else {
9412 Slog.w(TAG, "Unknown element under <" + tag + ">: "
9413 + parser.getName());
9414 XmlUtils.skipCurrentTag(parser);
9415 }
9416 }
9417 steps.mNumStepDurations = i;
9418 }
9419
9420 @Override
9421 public DailyItem getDailyItemLocked(int daysAgo) {
9422 int index = mDailyItems.size()-1-daysAgo;
9423 return index >= 0 ? mDailyItems.get(index) : null;
9424 }
9425
9426 @Override
9427 public long getCurrentDailyStartTime() {
9428 return mDailyStartTime;
9429 }
9430
9431 @Override
9432 public long getNextMinDailyDeadline() {
9433 return mNextMinDailyDeadline;
9434 }
9435
9436 @Override
9437 public long getNextMaxDailyDeadline() {
9438 return mNextMaxDailyDeadline;
9439 }
9440
9441 @Override
9442 public boolean startIteratingOldHistoryLocked() {
9443 if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
9444 + " pos=" + mHistoryBuffer.dataPosition());
9445 if ((mHistoryIterator = mHistory) == null) {
9446 return false;
9447 }
9448 mHistoryBuffer.setDataPosition(0);
9449 mHistoryReadTmp.clear();
9450 mReadOverflow = false;
9451 mIteratingHistory = true;
9452 return true;
9453 }
9454
9455 @Override
9456 public boolean getNextOldHistoryLocked(HistoryItem out) {
9457 boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
9458 if (!end) {
9459 readHistoryDelta(mHistoryBuffer, mHistoryReadTmp);
9460 mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
9461 }
9462 HistoryItem cur = mHistoryIterator;
9463 if (cur == null) {
9464 if (!mReadOverflow && !end) {
9465 Slog.w(TAG, "Old history ends before new history!");
9466 }
9467 return false;
9468 }
9469 out.setTo(cur);
9470 mHistoryIterator = cur.next;
9471 if (!mReadOverflow) {
9472 if (end) {
9473 Slog.w(TAG, "New history ends before old history!");
9474 } else if (!out.same(mHistoryReadTmp)) {
9475 PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
9476 pw.println("Histories differ!");
9477 pw.println("Old history:");
9478 (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
9479 pw.println("New history:");
9480 (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
9481 true);
9482 pw.flush();
9483 }
9484 }
9485 return true;
9486 }
9487
9488 @Override
9489 public void finishIteratingOldHistoryLocked() {
9490 mIteratingHistory = false;
9491 mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
9492 mHistoryIterator = null;
9493 }
9494
9495 public int getHistoryTotalSize() {
9496 return MAX_HISTORY_BUFFER;
9497 }
9498
9499 public int getHistoryUsedSize() {
9500 return mHistoryBuffer.dataSize();
9501 }
9502
9503 @Override
9504 public boolean startIteratingHistoryLocked() {
9505 if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
9506 + " pos=" + mHistoryBuffer.dataPosition());
9507 if (mHistoryBuffer.dataSize() <= 0) {
9508 return false;
9509 }
9510 mHistoryBuffer.setDataPosition(0);
9511 mReadOverflow = false;
9512 mIteratingHistory = true;
9513 mReadHistoryStrings = new String[mHistoryTagPool.size()];
9514 mReadHistoryUids = new int[mHistoryTagPool.size()];
9515 mReadHistoryChars = 0;
9516 for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
9517 final HistoryTag tag = ent.getKey();
9518 final int idx = ent.getValue();
9519 mReadHistoryStrings[idx] = tag.string;
9520 mReadHistoryUids[idx] = tag.uid;
9521 mReadHistoryChars += tag.string.length() + 1;
9522 }
9523 return true;
9524 }
9525
9526 @Override
9527 public int getHistoryStringPoolSize() {
9528 return mReadHistoryStrings.length;
9529 }
9530
9531 @Override
9532 public int getHistoryStringPoolBytes() {
9533 // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
9534 // Each string character is 2 bytes.
9535 return (mReadHistoryStrings.length * 12) + (mReadHistoryChars * 2);
9536 }
9537
9538 @Override
9539 public String getHistoryTagPoolString(int index) {
9540 return mReadHistoryStrings[index];
9541 }
9542
9543 @Override
9544 public int getHistoryTagPoolUid(int index) {
9545 return mReadHistoryUids[index];
9546 }
9547
9548 @Override
9549 public boolean getNextHistoryLocked(HistoryItem out) {
9550 final int pos = mHistoryBuffer.dataPosition();
9551 if (pos == 0) {
9552 out.clear();
9553 }
9554 boolean end = pos >= mHistoryBuffer.dataSize();
9555 if (end) {
9556 return false;
9557 }
9558
9559 final long lastRealtime = out.time;
9560 final long lastWalltime = out.currentTime;
9561 readHistoryDelta(mHistoryBuffer, out);
9562 if (out.cmd != HistoryItem.CMD_CURRENT_TIME
9563 && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
9564 out.currentTime = lastWalltime + (out.time - lastRealtime);
9565 }
9566 return true;
9567 }
9568
9569 @Override
9570 public void finishIteratingHistoryLocked() {
9571 mIteratingHistory = false;
9572 mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
9573 mReadHistoryStrings = null;
9574 }
9575
9576 @Override
9577 public long getHistoryBaseTime() {
9578 return mHistoryBaseTime;
9579 }
9580
9581 @Override
9582 public int getStartCount() {
9583 return mStartCount;
9584 }
9585
9586 public boolean isOnBattery() {
9587 return mOnBattery;
9588 }
9589
9590 public boolean isCharging() {
9591 return mCharging;
9592 }
9593
Justin Klaassen93b7ee42017-10-10 15:20:13 -04009594 public boolean isScreenOn(int state) {
Justin Klaassen47ed54e2017-10-24 19:50:40 -04009595 return state == Display.STATE_ON || state == Display.STATE_VR;
Justin Klaassen93b7ee42017-10-10 15:20:13 -04009596 }
9597
9598 public boolean isScreenOff(int state) {
9599 return state == Display.STATE_OFF;
9600 }
9601
9602 public boolean isScreenDoze(int state) {
9603 return state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND;
Justin Klaassen10d07c82017-09-15 17:58:39 -04009604 }
9605
9606 void initTimes(long uptime, long realtime) {
9607 mStartClockTime = System.currentTimeMillis();
9608 mOnBatteryTimeBase.init(uptime, realtime);
9609 mOnBatteryScreenOffTimeBase.init(uptime, realtime);
9610 mRealtime = 0;
9611 mUptime = 0;
9612 mRealtimeStart = realtime;
9613 mUptimeStart = uptime;
9614 }
9615
9616 void initDischarge() {
9617 mLowDischargeAmountSinceCharge = 0;
9618 mHighDischargeAmountSinceCharge = 0;
9619 mDischargeAmountScreenOn = 0;
9620 mDischargeAmountScreenOnSinceCharge = 0;
9621 mDischargeAmountScreenOff = 0;
9622 mDischargeAmountScreenOffSinceCharge = 0;
Justin Klaassen93b7ee42017-10-10 15:20:13 -04009623 mDischargeAmountScreenDoze = 0;
9624 mDischargeAmountScreenDozeSinceCharge = 0;
Justin Klaassen10d07c82017-09-15 17:58:39 -04009625 mDischargeStepTracker.init();
9626 mChargeStepTracker.init();
9627 mDischargeScreenOffCounter.reset(false);
Justin Klaassen93b7ee42017-10-10 15:20:13 -04009628 mDischargeScreenDozeCounter.reset(false);
Justin Klaassen10d07c82017-09-15 17:58:39 -04009629 mDischargeCounter.reset(false);
9630 }
9631
9632 public void resetAllStatsCmdLocked() {
9633 resetAllStatsLocked();
9634 final long mSecUptime = mClocks.uptimeMillis();
9635 long uptime = mSecUptime * 1000;
9636 long mSecRealtime = mClocks.elapsedRealtime();
9637 long realtime = mSecRealtime * 1000;
9638 mDischargeStartLevel = mHistoryCur.batteryLevel;
9639 pullPendingStateUpdatesLocked();
9640 addHistoryRecordLocked(mSecRealtime, mSecUptime);
9641 mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
9642 = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
9643 mOnBatteryTimeBase.reset(uptime, realtime);
9644 mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
9645 if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
Justin Klaassen93b7ee42017-10-10 15:20:13 -04009646 if (isScreenOn(mScreenState)) {
Justin Klaassen10d07c82017-09-15 17:58:39 -04009647 mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
Justin Klaassen93b7ee42017-10-10 15:20:13 -04009648 mDischargeScreenDozeUnplugLevel = 0;
9649 mDischargeScreenOffUnplugLevel = 0;
9650 } else if (isScreenDoze(mScreenState)) {
9651 mDischargeScreenOnUnplugLevel = 0;
9652 mDischargeScreenDozeUnplugLevel = mHistoryCur.batteryLevel;
Justin Klaassen10d07c82017-09-15 17:58:39 -04009653 mDischargeScreenOffUnplugLevel = 0;
9654 } else {
9655 mDischargeScreenOnUnplugLevel = 0;
Justin Klaassen93b7ee42017-10-10 15:20:13 -04009656 mDischargeScreenDozeUnplugLevel = 0;
Justin Klaassen10d07c82017-09-15 17:58:39 -04009657 mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
9658 }
9659 mDischargeAmountScreenOn = 0;
9660 mDischargeAmountScreenOff = 0;
Justin Klaassen93b7ee42017-10-10 15:20:13 -04009661 mDischargeAmountScreenDoze = 0;
Justin Klaassen10d07c82017-09-15 17:58:39 -04009662 }
9663 initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
9664 }
9665
9666 private void resetAllStatsLocked() {
9667 final long uptimeMillis = mClocks.uptimeMillis();
9668 final long elapsedRealtimeMillis = mClocks.elapsedRealtime();
9669 mStartCount = 0;
9670 initTimes(uptimeMillis * 1000, elapsedRealtimeMillis * 1000);
9671 mScreenOnTimer.reset(false);
Justin Klaassen93b7ee42017-10-10 15:20:13 -04009672 mScreenDozeTimer.reset(false);
Justin Klaassen10d07c82017-09-15 17:58:39 -04009673 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
9674 mScreenBrightnessTimer[i].reset(false);
9675 }
9676
9677 if (mPowerProfile != null) {
9678 mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
9679 } else {
9680 mEstimatedBatteryCapacity = -1;
9681 }
9682 mMinLearnedBatteryCapacity = -1;
9683 mMaxLearnedBatteryCapacity = -1;
9684 mInteractiveTimer.reset(false);
9685 mPowerSaveModeEnabledTimer.reset(false);
9686 mLastIdleTimeStart = elapsedRealtimeMillis;
9687 mLongestLightIdleTime = 0;
9688 mLongestFullIdleTime = 0;
9689 mDeviceIdleModeLightTimer.reset(false);
9690 mDeviceIdleModeFullTimer.reset(false);
9691 mDeviceLightIdlingTimer.reset(false);
9692 mDeviceIdlingTimer.reset(false);
9693 mPhoneOnTimer.reset(false);
9694 mAudioOnTimer.reset(false);
9695 mVideoOnTimer.reset(false);
9696 mFlashlightOnTimer.reset(false);
9697 mCameraOnTimer.reset(false);
9698 mBluetoothScanTimer.reset(false);
9699 for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
9700 mPhoneSignalStrengthsTimer[i].reset(false);
9701 }
9702 mPhoneSignalScanningTimer.reset(false);
9703 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
9704 mPhoneDataConnectionsTimer[i].reset(false);
9705 }
9706 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9707 mNetworkByteActivityCounters[i].reset(false);
9708 mNetworkPacketActivityCounters[i].reset(false);
9709 }
9710 mMobileRadioActiveTimer.reset(false);
9711 mMobileRadioActivePerAppTimer.reset(false);
9712 mMobileRadioActiveAdjustedTime.reset(false);
9713 mMobileRadioActiveUnknownTime.reset(false);
9714 mMobileRadioActiveUnknownCount.reset(false);
9715 mWifiOnTimer.reset(false);
9716 mGlobalWifiRunningTimer.reset(false);
9717 for (int i=0; i<NUM_WIFI_STATES; i++) {
9718 mWifiStateTimer[i].reset(false);
9719 }
9720 for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
9721 mWifiSupplStateTimer[i].reset(false);
9722 }
9723 for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
9724 mWifiSignalStrengthsTimer[i].reset(false);
9725 }
9726 mWifiActivity.reset(false);
9727 mBluetoothActivity.reset(false);
9728 mModemActivity.reset(false);
9729 mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
9730
9731 for (int i=0; i<mUidStats.size(); i++) {
9732 if (mUidStats.valueAt(i).reset(uptimeMillis * 1000, elapsedRealtimeMillis * 1000)) {
9733 mUidStats.remove(mUidStats.keyAt(i));
9734 i--;
9735 }
9736 }
9737
Justin Klaassenbc81c7a2017-09-18 17:38:50 -04009738 if (mRpmStats.size() > 0) {
9739 for (SamplingTimer timer : mRpmStats.values()) {
9740 mOnBatteryTimeBase.remove(timer);
9741 }
9742 mRpmStats.clear();
9743 }
9744 if (mScreenOffRpmStats.size() > 0) {
9745 for (SamplingTimer timer : mScreenOffRpmStats.values()) {
9746 mOnBatteryScreenOffTimeBase.remove(timer);
9747 }
9748 mScreenOffRpmStats.clear();
9749 }
9750
Justin Klaassen10d07c82017-09-15 17:58:39 -04009751 if (mKernelWakelockStats.size() > 0) {
9752 for (SamplingTimer timer : mKernelWakelockStats.values()) {
9753 mOnBatteryScreenOffTimeBase.remove(timer);
9754 }
9755 mKernelWakelockStats.clear();
9756 }
9757
9758 if (mKernelMemoryStats.size() > 0) {
9759 for (int i = 0; i < mKernelMemoryStats.size(); i++) {
9760 mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i));
9761 }
9762 mKernelMemoryStats.clear();
9763 }
9764
9765 if (mWakeupReasonStats.size() > 0) {
9766 for (SamplingTimer timer : mWakeupReasonStats.values()) {
9767 mOnBatteryTimeBase.remove(timer);
9768 }
9769 mWakeupReasonStats.clear();
9770 }
9771
9772 mLastHistoryStepDetails = null;
9773 mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
9774 mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
9775 mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
9776 mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
9777 mLastStepStatUserTime = mCurStepStatUserTime = 0;
9778 mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
9779 mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
9780 mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
9781 mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
9782 mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
9783
9784 initDischarge();
9785
9786 clearHistoryLocked();
9787 }
9788
9789 private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
9790 for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
9791 if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
9792 // Not recording process starts/stops.
9793 continue;
9794 }
9795 HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
9796 if (active == null) {
9797 continue;
9798 }
9799 for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
9800 SparseIntArray uids = ent.getValue();
9801 for (int j=0; j<uids.size(); j++) {
9802 addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
9803 uids.keyAt(j));
9804 }
9805 }
9806 }
9807 }
9808
Justin Klaassen93b7ee42017-10-10 15:20:13 -04009809 void updateDischargeScreenLevelsLocked(int oldState, int newState) {
9810 updateOldDischargeScreenLevelLocked(oldState);
9811 updateNewDischargeScreenLevelLocked(newState);
9812 }
9813
9814 private void updateOldDischargeScreenLevelLocked(int state) {
9815 if (isScreenOn(state)) {
Justin Klaassen10d07c82017-09-15 17:58:39 -04009816 int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
9817 if (diff > 0) {
9818 mDischargeAmountScreenOn += diff;
9819 mDischargeAmountScreenOnSinceCharge += diff;
9820 }
Justin Klaassen93b7ee42017-10-10 15:20:13 -04009821 } else if (isScreenDoze(state)) {
9822 int diff = mDischargeScreenDozeUnplugLevel - mDischargeCurrentLevel;
9823 if (diff > 0) {
9824 mDischargeAmountScreenDoze += diff;
9825 mDischargeAmountScreenDozeSinceCharge += diff;
9826 }
9827 } else if (isScreenOff(state)){
Justin Klaassen10d07c82017-09-15 17:58:39 -04009828 int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
9829 if (diff > 0) {
9830 mDischargeAmountScreenOff += diff;
9831 mDischargeAmountScreenOffSinceCharge += diff;
9832 }
9833 }
Justin Klaassen93b7ee42017-10-10 15:20:13 -04009834 }
9835
9836 private void updateNewDischargeScreenLevelLocked(int state) {
9837 if (isScreenOn(state)) {
Justin Klaassen10d07c82017-09-15 17:58:39 -04009838 mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
9839 mDischargeScreenOffUnplugLevel = 0;
Justin Klaassen93b7ee42017-10-10 15:20:13 -04009840 mDischargeScreenDozeUnplugLevel = 0;
9841 } else if (isScreenDoze(state)){
Justin Klaassen10d07c82017-09-15 17:58:39 -04009842 mDischargeScreenOnUnplugLevel = 0;
Justin Klaassen93b7ee42017-10-10 15:20:13 -04009843 mDischargeScreenDozeUnplugLevel = mDischargeCurrentLevel;
9844 mDischargeScreenOffUnplugLevel = 0;
9845 } else if (isScreenOff(state)) {
9846 mDischargeScreenOnUnplugLevel = 0;
9847 mDischargeScreenDozeUnplugLevel = 0;
Justin Klaassen10d07c82017-09-15 17:58:39 -04009848 mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
9849 }
9850 }
9851
9852 public void pullPendingStateUpdatesLocked() {
9853 if (mOnBatteryInternal) {
Justin Klaassen93b7ee42017-10-10 15:20:13 -04009854 updateDischargeScreenLevelsLocked(mScreenState, mScreenState);
Justin Klaassen10d07c82017-09-15 17:58:39 -04009855 }
9856 }
9857
9858 private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
9859 private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6);
9860
9861 private final Object mWifiNetworkLock = new Object();
9862
9863 @GuardedBy("mWifiNetworkLock")
9864 private String[] mWifiIfaces = EmptyArray.STRING;
9865
9866 @GuardedBy("mWifiNetworkLock")
9867 private NetworkStats mLastWifiNetworkStats = new NetworkStats(0, -1);
9868
9869 private final Object mModemNetworkLock = new Object();
9870
9871 @GuardedBy("mModemNetworkLock")
9872 private String[] mModemIfaces = EmptyArray.STRING;
9873
9874 @GuardedBy("mModemNetworkLock")
9875 private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
9876
9877 private NetworkStats readNetworkStatsLocked(String[] ifaces) {
9878 try {
9879 if (!ArrayUtils.isEmpty(ifaces)) {
9880 return mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces,
9881 NetworkStats.TAG_NONE, mNetworkStatsPool.acquire());
9882 }
9883 } catch (IOException e) {
9884 Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces));
9885 }
9886 return null;
9887 }
9888
9889 /**
9890 * Distribute WiFi energy info and network traffic to apps.
9891 * @param info The energy information from the WiFi controller.
9892 */
9893 public void updateWifiState(@Nullable final WifiActivityEnergyInfo info) {
9894 if (DEBUG_ENERGY) {
9895 Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
9896 }
9897
9898 // Grab a separate lock to acquire the network stats, which may do I/O.
9899 NetworkStats delta = null;
9900 synchronized (mWifiNetworkLock) {
9901 final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces);
9902 if (latestStats != null) {
9903 delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null,
9904 mNetworkStatsPool.acquire());
9905 mNetworkStatsPool.release(mLastWifiNetworkStats);
9906 mLastWifiNetworkStats = latestStats;
9907 }
9908 }
9909
9910 synchronized (this) {
9911 if (!mOnBatteryInternal) {
9912 if (delta != null) {
9913 mNetworkStatsPool.release(delta);
9914 }
9915 return;
9916 }
9917
9918 final long elapsedRealtimeMs = mClocks.elapsedRealtime();
9919 SparseLongArray rxPackets = new SparseLongArray();
9920 SparseLongArray txPackets = new SparseLongArray();
9921 long totalTxPackets = 0;
9922 long totalRxPackets = 0;
9923 if (delta != null) {
9924 NetworkStats.Entry entry = new NetworkStats.Entry();
9925 final int size = delta.size();
9926 for (int i = 0; i < size; i++) {
9927 entry = delta.getValues(i, entry);
9928
9929 if (DEBUG_ENERGY) {
9930 Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
9931 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
9932 + " txPackets=" + entry.txPackets);
9933 }
9934
9935 if (entry.rxBytes == 0 && entry.txBytes == 0) {
9936 // Skip the lookup below since there is no work to do.
9937 continue;
9938 }
9939
9940 final Uid u = getUidStatsLocked(mapUid(entry.uid));
9941 if (entry.rxBytes != 0) {
9942 u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
9943 entry.rxPackets);
9944 if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
9945 u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
9946 entry.rxPackets);
9947 }
9948 mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
9949 entry.rxBytes);
9950 mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
9951 entry.rxPackets);
9952
9953 rxPackets.put(u.getUid(), entry.rxPackets);
9954
9955 // Sum the total number of packets so that the Rx Power can
9956 // be evenly distributed amongst the apps.
9957 totalRxPackets += entry.rxPackets;
9958 }
9959
9960 if (entry.txBytes != 0) {
9961 u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
9962 entry.txPackets);
9963 if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
9964 u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
9965 entry.txPackets);
9966 }
9967 mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
9968 entry.txBytes);
9969 mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
9970 entry.txPackets);
9971
9972 txPackets.put(u.getUid(), entry.txPackets);
9973
9974 // Sum the total number of packets so that the Tx Power can
9975 // be evenly distributed amongst the apps.
9976 totalTxPackets += entry.txPackets;
9977 }
9978 }
9979 mNetworkStatsPool.release(delta);
9980 delta = null;
9981 }
9982
9983 if (info != null) {
9984 mHasWifiReporting = true;
9985
9986 // Measured in mAms
9987 final long txTimeMs = info.getControllerTxTimeMillis();
9988 final long rxTimeMs = info.getControllerRxTimeMillis();
9989 final long idleTimeMs = info.getControllerIdleTimeMillis();
9990 final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
9991
9992 long leftOverRxTimeMs = rxTimeMs;
9993 long leftOverTxTimeMs = txTimeMs;
9994
9995 if (DEBUG_ENERGY) {
9996 Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
9997 Slog.d(TAG, " Tx Time: " + txTimeMs + " ms");
9998 Slog.d(TAG, " Rx Time: " + rxTimeMs + " ms");
9999 Slog.d(TAG, " Idle Time: " + idleTimeMs + " ms");
10000 Slog.d(TAG, " Total Time: " + totalTimeMs + " ms");
10001 }
10002
10003 long totalWifiLockTimeMs = 0;
10004 long totalScanTimeMs = 0;
10005
10006 // On the first pass, collect some totals so that we can normalize power
10007 // calculations if we need to.
10008 final int uidStatsSize = mUidStats.size();
10009 for (int i = 0; i < uidStatsSize; i++) {
10010 final Uid uid = mUidStats.valueAt(i);
10011
10012 // Sum the total scan power for all apps.
10013 totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
10014 elapsedRealtimeMs * 1000) / 1000;
10015
10016 // Sum the total time holding wifi lock for all apps.
10017 totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
10018 elapsedRealtimeMs * 1000) / 1000;
10019 }
10020
10021 if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
10022 Slog.d(TAG,
10023 " !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
10024 + rxTimeMs + " ms). Normalizing scan time.");
10025 }
10026 if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
10027 Slog.d(TAG,
10028 " !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
10029 + txTimeMs + " ms). Normalizing scan time.");
10030 }
10031
10032 // Actually assign and distribute power usage to apps.
10033 for (int i = 0; i < uidStatsSize; i++) {
10034 final Uid uid = mUidStats.valueAt(i);
10035
10036 long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
10037 elapsedRealtimeMs * 1000) / 1000;
10038 if (scanTimeSinceMarkMs > 0) {
10039 // Set the new mark so that next time we get new data since this point.
10040 uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
10041
10042 long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
10043 long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
10044
10045 // Our total scan time is more than the reported Tx/Rx time.
10046 // This is possible because the cost of a scan is approximate.
10047 // Let's normalize the result so that we evenly blame each app
10048 // scanning.
10049 //
10050 // This means that we may have apps that transmitted/received packets not be
10051 // blamed for this, but this is fine as scans are relatively more expensive.
10052 if (totalScanTimeMs > rxTimeMs) {
10053 scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
10054 totalScanTimeMs;
10055 }
10056 if (totalScanTimeMs > txTimeMs) {
10057 scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
10058 totalScanTimeMs;
10059 }
10060
10061 if (DEBUG_ENERGY) {
10062 Slog.d(TAG, " ScanTime for UID " + uid.getUid() + ": Rx:"
10063 + scanRxTimeSinceMarkMs + " ms Tx:"
10064 + scanTxTimeSinceMarkMs + " ms)");
10065 }
10066
10067 ControllerActivityCounterImpl activityCounter =
10068 uid.getOrCreateWifiControllerActivityLocked();
10069 activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
10070 activityCounter.getTxTimeCounters()[0].addCountLocked(
10071 scanTxTimeSinceMarkMs);
10072 leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
10073 leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
10074 }
10075
10076 // Distribute evenly the power consumed while Idle to each app holding a WiFi
10077 // lock.
10078 final long wifiLockTimeSinceMarkMs =
10079 uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
10080 elapsedRealtimeMs * 1000) / 1000;
10081 if (wifiLockTimeSinceMarkMs > 0) {
10082 // Set the new mark so that next time we get new data since this point.
10083 uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
10084
10085 final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
10086 / totalWifiLockTimeMs;
10087 if (DEBUG_ENERGY) {
10088 Slog.d(TAG, " IdleTime for UID " + uid.getUid() + ": "
10089 + myIdleTimeMs + " ms");
10090 }
10091 uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
10092 .addCountLocked(myIdleTimeMs);
10093 }
10094 }
10095
10096 if (DEBUG_ENERGY) {
10097 Slog.d(TAG, " New RxPower: " + leftOverRxTimeMs + " ms");
10098 Slog.d(TAG, " New TxPower: " + leftOverTxTimeMs + " ms");
10099 }
10100
10101 // Distribute the remaining Tx power appropriately between all apps that transmitted
10102 // packets.
10103 for (int i = 0; i < txPackets.size(); i++) {
10104 final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
10105 final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
10106 / totalTxPackets;
10107 if (DEBUG_ENERGY) {
10108 Slog.d(TAG, " TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
10109 }
10110 uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
10111 .addCountLocked(myTxTimeMs);
10112 }
10113
10114 // Distribute the remaining Rx power appropriately between all apps that received
10115 // packets.
10116 for (int i = 0; i < rxPackets.size(); i++) {
10117 final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
10118 final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
10119 / totalRxPackets;
10120 if (DEBUG_ENERGY) {
10121 Slog.d(TAG, " RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
10122 }
10123 uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
10124 .addCountLocked(myRxTimeMs);
10125 }
10126
10127 // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
10128
10129
10130 // Update WiFi controller stats.
10131 mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
10132 mWifiActivity.getTxTimeCounters()[0].addCountLocked(
10133 info.getControllerTxTimeMillis());
10134 mWifiActivity.getIdleTimeCounter().addCountLocked(
10135 info.getControllerIdleTimeMillis());
10136
10137 // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
10138 final double opVolt = mPowerProfile.getAveragePower(
10139 PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
10140 if (opVolt != 0) {
10141 // We store the power drain as mAms.
10142 mWifiActivity.getPowerCounter().addCountLocked(
10143 (long) (info.getControllerEnergyUsed() / opVolt));
10144 }
10145 }
10146 }
10147 }
10148
10149 /**
10150 * Distribute Cell radio energy info and network traffic to apps.
10151 */
10152 public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo) {
10153 if (DEBUG_ENERGY) {
10154 Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
10155 }
10156
10157 // Grab a separate lock to acquire the network stats, which may do I/O.
10158 NetworkStats delta = null;
10159 synchronized (mModemNetworkLock) {
10160 final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces);
10161 if (latestStats != null) {
10162 delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null,
10163 mNetworkStatsPool.acquire());
10164 mNetworkStatsPool.release(mLastModemNetworkStats);
10165 mLastModemNetworkStats = latestStats;
10166 }
10167 }
10168
10169 synchronized (this) {
10170 if (!mOnBatteryInternal) {
10171 if (delta != null) {
10172 mNetworkStatsPool.release(delta);
10173 }
10174 return;
10175 }
10176
10177 final long elapsedRealtimeMs = mClocks.elapsedRealtime();
10178 long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
10179 elapsedRealtimeMs * 1000);
10180 mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
10181
10182 long totalRxPackets = 0;
10183 long totalTxPackets = 0;
10184 if (delta != null) {
10185 NetworkStats.Entry entry = new NetworkStats.Entry();
10186 final int size = delta.size();
10187 for (int i = 0; i < size; i++) {
10188 entry = delta.getValues(i, entry);
10189 if (entry.rxPackets == 0 && entry.txPackets == 0) {
10190 continue;
10191 }
10192
10193 if (DEBUG_ENERGY) {
10194 Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
10195 + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
10196 + " txPackets=" + entry.txPackets);
10197 }
10198
10199 totalRxPackets += entry.rxPackets;
10200 totalTxPackets += entry.txPackets;
10201
10202 final Uid u = getUidStatsLocked(mapUid(entry.uid));
10203 u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
10204 entry.rxPackets);
10205 u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
10206 entry.txPackets);
10207 if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
10208 u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
10209 entry.rxBytes, entry.rxPackets);
10210 u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
10211 entry.txBytes, entry.txPackets);
10212 }
10213
10214 mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
10215 entry.rxBytes);
10216 mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
10217 entry.txBytes);
10218 mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
10219 entry.rxPackets);
10220 mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
10221 entry.txPackets);
10222 }
10223
10224 // Now distribute proportional blame to the apps that did networking.
10225 long totalPackets = totalRxPackets + totalTxPackets;
10226 if (totalPackets > 0) {
10227 for (int i = 0; i < size; i++) {
10228 entry = delta.getValues(i, entry);
10229 if (entry.rxPackets == 0 && entry.txPackets == 0) {
10230 continue;
10231 }
10232
10233 final Uid u = getUidStatsLocked(mapUid(entry.uid));
10234
10235 // Distribute total radio active time in to this app.
10236 final long appPackets = entry.rxPackets + entry.txPackets;
10237 final long appRadioTime = (radioTime * appPackets) / totalPackets;
10238 u.noteMobileRadioActiveTimeLocked(appRadioTime);
10239
10240 // Remove this app from the totals, so that we don't lose any time
10241 // due to rounding.
10242 radioTime -= appRadioTime;
10243 totalPackets -= appPackets;
10244
10245 if (activityInfo != null) {
10246 ControllerActivityCounterImpl activityCounter =
10247 u.getOrCreateModemControllerActivityLocked();
10248 if (totalRxPackets > 0 && entry.rxPackets > 0) {
10249 final long rxMs = (entry.rxPackets * activityInfo.getRxTimeMillis())
10250 / totalRxPackets;
10251 activityCounter.getRxTimeCounter().addCountLocked(rxMs);
10252 }
10253
10254 if (totalTxPackets > 0 && entry.txPackets > 0) {
10255 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
10256 long txMs =
10257 entry.txPackets * activityInfo.getTxTimeMillis()[lvl];
10258 txMs /= totalTxPackets;
10259 activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
10260 }
10261 }
10262 }
10263 }
10264 }
10265
10266 if (radioTime > 0) {
10267 // Whoops, there is some radio time we can't blame on an app!
10268 mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
10269 mMobileRadioActiveUnknownCount.addCountLocked(1);
10270 }
10271
10272 mNetworkStatsPool.release(delta);
10273 delta = null;
10274 }
10275
10276 if (activityInfo != null) {
10277 mHasModemReporting = true;
10278 mModemActivity.getIdleTimeCounter().addCountLocked(
10279 activityInfo.getIdleTimeMillis());
10280 mModemActivity.getRxTimeCounter().addCountLocked(activityInfo.getRxTimeMillis());
10281 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
10282 mModemActivity.getTxTimeCounters()[lvl]
10283 .addCountLocked(activityInfo.getTxTimeMillis()[lvl]);
10284 }
10285
10286 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
10287 final double opVolt = mPowerProfile.getAveragePower(
10288 PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
10289 if (opVolt != 0) {
10290 // We store the power drain as mAms.
10291 mModemActivity.getPowerCounter().addCountLocked(
10292 (long) (activityInfo.getEnergyUsed() / opVolt));
10293 }
10294 }
10295 }
10296 }
10297
10298 /**
10299 * Distribute Bluetooth energy info and network traffic to apps.
10300 * @param info The energy information from the bluetooth controller.
10301 */
10302 public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
10303 if (DEBUG_ENERGY) {
10304 Slog.d(TAG, "Updating bluetooth stats: " + info);
10305 }
10306
10307 if (info == null || !mOnBatteryInternal) {
10308 return;
10309 }
10310
10311 mHasBluetoothReporting = true;
10312
10313 final long elapsedRealtimeMs = mClocks.elapsedRealtime();
10314 final long rxTimeMs = info.getControllerRxTimeMillis();
10315 final long txTimeMs = info.getControllerTxTimeMillis();
10316
10317 if (DEBUG_ENERGY) {
10318 Slog.d(TAG, "------ BEGIN BLE power blaming ------");
10319 Slog.d(TAG, " Tx Time: " + txTimeMs + " ms");
10320 Slog.d(TAG, " Rx Time: " + rxTimeMs + " ms");
10321 Slog.d(TAG, " Idle Time: " + info.getControllerIdleTimeMillis() + " ms");
10322 }
10323
10324 long totalScanTimeMs = 0;
10325
10326 final int uidCount = mUidStats.size();
10327 for (int i = 0; i < uidCount; i++) {
10328 final Uid u = mUidStats.valueAt(i);
10329 if (u.mBluetoothScanTimer == null) {
10330 continue;
10331 }
10332
10333 totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
10334 elapsedRealtimeMs * 1000) / 1000;
10335 }
10336
10337 final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
10338 final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
10339
10340 if (DEBUG_ENERGY) {
10341 Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
10342 + " TX=" + normalizeScanTxTime);
10343 }
10344
10345 long leftOverRxTimeMs = rxTimeMs;
10346 long leftOverTxTimeMs = txTimeMs;
10347
10348 for (int i = 0; i < uidCount; i++) {
10349 final Uid u = mUidStats.valueAt(i);
10350 if (u.mBluetoothScanTimer == null) {
10351 continue;
10352 }
10353
10354 long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
10355 elapsedRealtimeMs * 1000) / 1000;
10356 if (scanTimeSinceMarkMs > 0) {
10357 // Set the new mark so that next time we get new data since this point.
10358 u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
10359
10360 long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
10361 long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
10362
10363 if (normalizeScanRxTime) {
10364 // Scan time is longer than the total rx time in the controller,
10365 // so distribute the scan time proportionately. This means regular traffic
10366 // will not blamed, but scans are more expensive anyways.
10367 scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
10368 }
10369
10370 if (normalizeScanTxTime) {
10371 // Scan time is longer than the total tx time in the controller,
10372 // so distribute the scan time proportionately. This means regular traffic
10373 // will not blamed, but scans are more expensive anyways.
10374 scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
10375 }
10376
10377 final ControllerActivityCounterImpl counter =
10378 u.getOrCreateBluetoothControllerActivityLocked();
10379 counter.getRxTimeCounter().addCountLocked(scanTimeRxSinceMarkMs);
10380 counter.getTxTimeCounters()[0].addCountLocked(scanTimeTxSinceMarkMs);
10381
10382 leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
10383 leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
10384 }
10385 }
10386
10387 if (DEBUG_ENERGY) {
10388 Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs
10389 + " TX=" + leftOverTxTimeMs);
10390 }
10391
10392 //
10393 // Now distribute blame to apps that did bluetooth traffic.
10394 //
10395
10396 long totalTxBytes = 0;
10397 long totalRxBytes = 0;
10398
10399 final UidTraffic[] uidTraffic = info.getUidTraffic();
10400 final int numUids = uidTraffic != null ? uidTraffic.length : 0;
10401 for (int i = 0; i < numUids; i++) {
10402 final UidTraffic traffic = uidTraffic[i];
10403
10404 // Add to the global counters.
10405 mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(
10406 traffic.getRxBytes());
10407 mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(
10408 traffic.getTxBytes());
10409
10410 // Add to the UID counters.
10411 final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
10412 u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, traffic.getRxBytes(), 0);
10413 u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, traffic.getTxBytes(), 0);
10414
10415 // Calculate the total traffic.
10416 totalTxBytes += traffic.getTxBytes();
10417 totalRxBytes += traffic.getRxBytes();
10418 }
10419
10420 if ((totalTxBytes != 0 || totalRxBytes != 0) &&
10421 (leftOverRxTimeMs != 0 || leftOverTxTimeMs != 0)) {
10422 for (int i = 0; i < numUids; i++) {
10423 final UidTraffic traffic = uidTraffic[i];
10424
10425 final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
10426 final ControllerActivityCounterImpl counter =
10427 u.getOrCreateBluetoothControllerActivityLocked();
10428
10429 if (totalRxBytes > 0 && traffic.getRxBytes() > 0) {
10430 final long timeRxMs = (leftOverRxTimeMs * traffic.getRxBytes()) / totalRxBytes;
10431
10432 if (DEBUG_ENERGY) {
10433 Slog.d(TAG, "UID=" + traffic.getUid() + " rx_bytes=" + traffic.getRxBytes()
10434 + " rx_time=" + timeRxMs);
10435 }
10436 counter.getRxTimeCounter().addCountLocked(timeRxMs);
10437 leftOverRxTimeMs -= timeRxMs;
10438 }
10439
10440 if (totalTxBytes > 0 && traffic.getTxBytes() > 0) {
10441 final long timeTxMs = (leftOverTxTimeMs * traffic.getTxBytes()) / totalTxBytes;
10442
10443 if (DEBUG_ENERGY) {
10444 Slog.d(TAG, "UID=" + traffic.getUid() + " tx_bytes=" + traffic.getTxBytes()
10445 + " tx_time=" + timeTxMs);
10446 }
10447
10448 counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
10449 leftOverTxTimeMs -= timeTxMs;
10450 }
10451 }
10452 }
10453
10454 mBluetoothActivity.getRxTimeCounter().addCountLocked(
10455 info.getControllerRxTimeMillis());
10456 mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(
10457 info.getControllerTxTimeMillis());
10458 mBluetoothActivity.getIdleTimeCounter().addCountLocked(
10459 info.getControllerIdleTimeMillis());
10460
10461 // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
10462 final double opVolt = mPowerProfile.getAveragePower(
10463 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
10464 if (opVolt != 0) {
10465 // We store the power drain as mAms.
10466 mBluetoothActivity.getPowerCounter().addCountLocked(
10467 (long) (info.getControllerEnergyUsed() / opVolt));
10468 }
10469 }
10470
10471 /**
Justin Klaassenbc81c7a2017-09-18 17:38:50 -040010472 * Read and record Resource Power Manager (RPM) state and voter times.
10473 * If RPM stats were fetched more recently than RPM_STATS_UPDATE_FREQ_MS ago, uses the old data
10474 * instead of fetching it anew.
10475 */
10476 public void updateRpmStatsLocked() {
10477 if (mPlatformIdleStateCallback == null) return;
10478 long now = SystemClock.elapsedRealtime();
10479 if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
10480 mPlatformIdleStateCallback.fillLowPowerStats(mTmpRpmStats);
10481 mLastRpmStatsUpdateTimeMs = now;
10482 }
10483
10484 for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate
10485 : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) {
10486
10487 // Update values for this platform state.
10488 final String pName = pstate.getKey();
10489 final long pTimeUs = pstate.getValue().mTimeMs * 1000;
10490 final int pCount = pstate.getValue().mCount;
10491 getRpmTimerLocked(pName).update(pTimeUs, pCount);
10492 if (SCREEN_OFF_RPM_STATS_ENABLED) {
10493 getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount);
10494 }
10495
10496 // Update values for each voter of this platform state.
10497 for (Map.Entry<String, RpmStats.PowerStateElement> voter
10498 : pstate.getValue().mVoters.entrySet()) {
10499 final String vName = pName + "." + voter.getKey();
10500 final long vTimeUs = voter.getValue().mTimeMs * 1000;
10501 final int vCount = voter.getValue().mCount;
10502 getRpmTimerLocked(vName).update(vTimeUs, vCount);
10503 if (SCREEN_OFF_RPM_STATS_ENABLED) {
10504 getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount);
10505 }
10506 }
10507 }
10508
10509 for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys
10510 : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) {
10511
10512 final String subsysName = subsys.getKey();
10513 for (Map.Entry<String, RpmStats.PowerStateElement> sstate
10514 : subsys.getValue().mStates.entrySet()) {
10515 final String name = subsysName + "." + sstate.getKey();
10516 final long timeUs = sstate.getValue().mTimeMs * 1000;
10517 final int count = sstate.getValue().mCount;
10518 getRpmTimerLocked(name).update(timeUs, count);
10519 if (SCREEN_OFF_RPM_STATS_ENABLED) {
10520 getScreenOffRpmTimerLocked(name).update(timeUs, count);
10521 }
10522 }
10523 }
10524 }
10525
10526 /**
Justin Klaassen10d07c82017-09-15 17:58:39 -040010527 * Read and distribute kernel wake lock use across apps.
10528 */
10529 public void updateKernelWakelocksLocked() {
10530 final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
10531 mTmpWakelockStats);
10532 if (wakelockStats == null) {
10533 // Not crashing might make board bringup easier.
10534 Slog.w(TAG, "Couldn't get kernel wake lock stats");
10535 return;
10536 }
10537
10538 for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
10539 String name = ent.getKey();
10540 KernelWakelockStats.Entry kws = ent.getValue();
10541
10542 SamplingTimer kwlt = mKernelWakelockStats.get(name);
10543 if (kwlt == null) {
10544 kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
10545 mKernelWakelockStats.put(name, kwlt);
10546 }
10547
10548 kwlt.update(kws.mTotalTime, kws.mCount);
10549 kwlt.setUpdateVersion(kws.mVersion);
10550 }
10551
10552 int numWakelocksSetStale = 0;
10553 // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
10554 // this time.
10555 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
10556 SamplingTimer st = ent.getValue();
10557 if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
10558 st.endSample();
10559 numWakelocksSetStale++;
10560 }
10561 }
10562
10563 // Record whether we've seen a non-zero time (for debugging b/22716723).
10564 if (wakelockStats.isEmpty()) {
10565 Slog.wtf(TAG, "All kernel wakelocks had time of zero");
10566 }
10567
10568 if (numWakelocksSetStale == mKernelWakelockStats.size()) {
10569 Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
10570 wakelockStats.kernelWakelockVersion);
10571 }
10572 }
10573
10574 // We use an anonymous class to access these variables,
10575 // so they can't live on the stack or they'd have to be
10576 // final MutableLong objects (more allocations).
10577 // Used in updateCpuTimeLocked().
10578 long mTempTotalCpuUserTimeUs;
10579 long mTempTotalCpuSystemTimeUs;
10580 long[][] mWakeLockAllocationsUs;
10581
10582 /**
10583 * Reads the newest memory stats from the kernel.
10584 */
10585 public void updateKernelMemoryBandwidthLocked() {
10586 mKernelMemoryBandwidthStats.updateStats();
10587 LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
10588 final int bandwidthEntryCount = bandwidthEntries.size();
10589 int index;
10590 for (int i = 0; i < bandwidthEntryCount; i++) {
10591 SamplingTimer timer;
10592 if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) {
10593 timer = mKernelMemoryStats.valueAt(index);
10594 } else {
10595 timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
10596 mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
10597 }
10598 timer.update(bandwidthEntries.valueAt(i), 1);
10599 if (DEBUG_MEMORY) {
10600 Slog.d(TAG, String.format("Added entry %d and updated timer to: "
10601 + "mUnpluggedReportedTotalTime %d size %d", bandwidthEntries.keyAt(i),
10602 mKernelMemoryStats.get(
10603 bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTime,
10604 mKernelMemoryStats.size()));
10605 }
10606 }
10607 }
10608
10609 /**
10610 * Read and distribute CPU usage across apps. If their are partial wakelocks being held
10611 * and we are on battery with screen off, we give more of the cpu time to those apps holding
10612 * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
10613 */
10614 public void updateCpuTimeLocked() {
10615 if (mPowerProfile == null) {
10616 return;
10617 }
10618
10619 if (DEBUG_ENERGY_CPU) {
10620 Slog.d(TAG, "!Cpu updating!");
10621 }
10622
10623 if (mCpuFreqs == null) {
10624 mCpuFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile);
10625 }
10626
10627 // Calculate the wakelocks we have to distribute amongst. The system is excluded as it is
10628 // usually holding the wakelock on behalf of an app.
10629 // And Only distribute cpu power to wakelocks if the screen is off and we're on battery.
10630 ArrayList<StopwatchTimer> partialTimersToConsider = null;
10631 if (mOnBatteryScreenOffTimeBase.isRunning()) {
10632 partialTimersToConsider = new ArrayList<>();
10633 for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
10634 final StopwatchTimer timer = mPartialTimers.get(i);
10635 // Since the collection and blaming of wakelocks can be scheduled to run after
10636 // some delay, the mPartialTimers list may have new entries. We can't blame
10637 // the newly added timer for past cpu time, so we only consider timers that
10638 // were present for one round of collection. Once a timer has gone through
10639 // a round of collection, its mInList field is set to true.
10640 if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
10641 partialTimersToConsider.add(timer);
10642 }
10643 }
10644 }
10645 markPartialTimersAsEligible();
10646
10647 // When the battery is not on, we don't attribute the cpu times to any timers but we still
10648 // need to take the snapshots.
10649 if (!mOnBatteryInternal) {
10650 mKernelUidCpuTimeReader.readDelta(null);
10651 mKernelUidCpuFreqTimeReader.readDelta(null);
10652 for (int cluster = mKernelCpuSpeedReaders.length - 1; cluster >= 0; --cluster) {
10653 mKernelCpuSpeedReaders[cluster].readDelta();
10654 }
10655 return;
10656 }
10657
10658 mUserInfoProvider.refreshUserIds();
10659 final SparseLongArray updatedUids = mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()
10660 ? null : new SparseLongArray();
10661 readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids);
10662 // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
10663 // freqs, so no need to approximate these values.
10664 if (updatedUids != null) {
10665 updateClusterSpeedTimes(updatedUids);
10666 }
10667 readKernelUidCpuFreqTimesLocked(partialTimersToConsider);
10668 }
10669
10670 /**
10671 * Mark the current partial timers as gone through a collection so that they will be
10672 * considered in the next cpu times distribution to wakelock holders.
10673 */
10674 @VisibleForTesting
10675 public void markPartialTimersAsEligible() {
10676 if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
10677 // No difference, so each timer is now considered for the next collection.
10678 for (int i = mPartialTimers.size() - 1; i >= 0; --i) {
10679 mPartialTimers.get(i).mInList = true;
10680 }
10681 } else {
10682 // The lists are different, meaning we added (or removed a timer) since the last
10683 // collection.
10684 for (int i = mLastPartialTimers.size() - 1; i >= 0; --i) {
10685 mLastPartialTimers.get(i).mInList = false;
10686 }
10687 mLastPartialTimers.clear();
10688
10689 // Mark the current timers as gone through a collection.
10690 final int numPartialTimers = mPartialTimers.size();
10691 for (int i = 0; i < numPartialTimers; ++i) {
10692 final StopwatchTimer timer = mPartialTimers.get(i);
10693 timer.mInList = true;
10694 mLastPartialTimers.add(timer);
10695 }
10696 }
10697 }
10698
10699 /**
10700 * Take snapshot of cpu times (aggregated over all uids) at different frequencies and
10701 * calculate cpu times spent by each uid at different frequencies.
10702 *
10703 * @param updatedUids The uids for which times spent at different frequencies are calculated.
10704 */
10705 @VisibleForTesting
10706 public void updateClusterSpeedTimes(@NonNull SparseLongArray updatedUids) {
10707 long totalCpuClustersTimeMs = 0;
10708 // Read the time spent for each cluster at various cpu frequencies.
10709 final long[][] clusterSpeedTimesMs = new long[mKernelCpuSpeedReaders.length][];
10710 for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
10711 clusterSpeedTimesMs[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
10712 if (clusterSpeedTimesMs[cluster] != null) {
10713 for (int speed = clusterSpeedTimesMs[cluster].length - 1; speed >= 0; --speed) {
10714 totalCpuClustersTimeMs += clusterSpeedTimesMs[cluster][speed];
10715 }
10716 }
10717 }
10718 if (totalCpuClustersTimeMs != 0) {
10719 // We have cpu times per freq aggregated over all uids but we need the times per uid.
10720 // So, we distribute total time spent by an uid to different cpu freqs based on the
10721 // amount of time cpu was running at that freq.
10722 final int updatedUidsCount = updatedUids.size();
10723 for (int i = 0; i < updatedUidsCount; ++i) {
10724 final Uid u = getUidStatsLocked(updatedUids.keyAt(i));
10725 final long appCpuTimeUs = updatedUids.valueAt(i);
10726 // Add the cpu speeds to this UID.
10727 final int numClusters = mPowerProfile.getNumCpuClusters();
10728 if (u.mCpuClusterSpeedTimesUs == null ||
10729 u.mCpuClusterSpeedTimesUs.length != numClusters) {
10730 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
10731 }
10732
10733 for (int cluster = 0; cluster < clusterSpeedTimesMs.length; cluster++) {
10734 final int speedsInCluster = clusterSpeedTimesMs[cluster].length;
10735 if (u.mCpuClusterSpeedTimesUs[cluster] == null || speedsInCluster !=
10736 u.mCpuClusterSpeedTimesUs[cluster].length) {
10737 u.mCpuClusterSpeedTimesUs[cluster]
10738 = new LongSamplingCounter[speedsInCluster];
10739 }
10740
10741 final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeedTimesUs[cluster];
10742 for (int speed = 0; speed < speedsInCluster; speed++) {
10743 if (cpuSpeeds[speed] == null) {
10744 cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
10745 }
10746 cpuSpeeds[speed].addCountLocked(appCpuTimeUs
10747 * clusterSpeedTimesMs[cluster][speed]
10748 / totalCpuClustersTimeMs);
10749 }
10750 }
10751 }
10752 }
10753 }
10754
10755 /**
10756 * Take a snapshot of the cpu times spent by each uid and update the corresponding counters.
10757 * If {@param partialTimers} is not null and empty, then we assign a portion of cpu times to
10758 * wakelock holders.
10759 *
10760 * @param partialTimers The wakelock holders among which the cpu times will be distributed.
10761 * @param updatedUids If not null, then the uids found in the snapshot will be added to this.
10762 */
10763 @VisibleForTesting
10764 public void readKernelUidCpuTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
10765 @Nullable SparseLongArray updatedUids) {
10766 mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0;
10767 final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
10768 final long startTimeMs = mClocks.uptimeMillis();
10769
10770 mKernelUidCpuTimeReader.readDelta((uid, userTimeUs, systemTimeUs) -> {
10771 uid = mapUid(uid);
10772 if (Process.isIsolated(uid)) {
10773 // This could happen if the isolated uid mapping was removed before that process
10774 // was actually killed.
10775 mKernelUidCpuTimeReader.removeUid(uid);
10776 Slog.d(TAG, "Got readings for an isolated uid with no mapping: " + uid);
10777 return;
10778 }
10779 if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
10780 Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
10781 mKernelUidCpuTimeReader.removeUid(uid);
10782 return;
10783 }
10784 final Uid u = getUidStatsLocked(uid);
10785
10786 // Accumulate the total system and user time.
10787 mTempTotalCpuUserTimeUs += userTimeUs;
10788 mTempTotalCpuSystemTimeUs += systemTimeUs;
10789
10790 StringBuilder sb = null;
10791 if (DEBUG_ENERGY_CPU) {
10792 sb = new StringBuilder();
10793 sb.append(" got time for uid=").append(u.mUid).append(": u=");
10794 TimeUtils.formatDuration(userTimeUs / 1000, sb);
10795 sb.append(" s=");
10796 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
10797 sb.append("\n");
10798 }
10799
10800 if (numWakelocks > 0) {
10801 // We have wakelocks being held, so only give a portion of the
10802 // time to the process. The rest will be distributed among wakelock
10803 // holders.
10804 userTimeUs = (userTimeUs * WAKE_LOCK_WEIGHT) / 100;
10805 systemTimeUs = (systemTimeUs * WAKE_LOCK_WEIGHT) / 100;
10806 }
10807
10808 if (sb != null) {
10809 sb.append(" adding to uid=").append(u.mUid).append(": u=");
10810 TimeUtils.formatDuration(userTimeUs / 1000, sb);
10811 sb.append(" s=");
10812 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
10813 Slog.d(TAG, sb.toString());
10814 }
10815
10816 u.mUserCpuTime.addCountLocked(userTimeUs);
10817 u.mSystemCpuTime.addCountLocked(systemTimeUs);
10818 if (updatedUids != null) {
10819 updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
10820 }
10821 });
10822
10823 final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
10824 if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
10825 Slog.d(TAG, "Reading cpu stats took " + elapsedTimeMs + "ms");
10826 }
10827
10828 if (numWakelocks > 0) {
10829 // Distribute a portion of the total cpu time to wakelock holders.
10830 mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
10831 mTempTotalCpuSystemTimeUs =
10832 (mTempTotalCpuSystemTimeUs * (100 - WAKE_LOCK_WEIGHT)) / 100;
10833
10834 for (int i = 0; i < numWakelocks; ++i) {
10835 final StopwatchTimer timer = partialTimers.get(i);
10836 final int userTimeUs = (int) (mTempTotalCpuUserTimeUs / (numWakelocks - i));
10837 final int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / (numWakelocks - i));
10838
10839 if (DEBUG_ENERGY_CPU) {
10840 final StringBuilder sb = new StringBuilder();
10841 sb.append(" Distributing wakelock uid=").append(timer.mUid.mUid)
10842 .append(": u=");
10843 TimeUtils.formatDuration(userTimeUs / 1000, sb);
10844 sb.append(" s=");
10845 TimeUtils.formatDuration(systemTimeUs / 1000, sb);
10846 Slog.d(TAG, sb.toString());
10847 }
10848
10849 timer.mUid.mUserCpuTime.addCountLocked(userTimeUs);
10850 timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs);
10851 if (updatedUids != null) {
10852 final int uid = timer.mUid.getUid();
10853 updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
10854 }
10855
10856 final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
10857 proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000);
10858
10859 mTempTotalCpuUserTimeUs -= userTimeUs;
10860 mTempTotalCpuSystemTimeUs -= systemTimeUs;
10861 }
10862 }
10863 }
10864
10865 /**
10866 * Take a snapshot of the cpu times spent by each uid in each freq and update the
10867 * corresponding counters.
10868 *
10869 * @param partialTimers The wakelock holders among which the cpu freq times will be distributed.
10870 */
10871 @VisibleForTesting
10872 public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers) {
10873 final boolean perClusterTimesAvailable =
10874 mKernelUidCpuFreqTimeReader.perClusterTimesAvailable();
10875 final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
10876 final int numClusters = mPowerProfile.getNumCpuClusters();
10877 mWakeLockAllocationsUs = null;
10878 mKernelUidCpuFreqTimeReader.readDelta((uid, cpuFreqTimeMs) -> {
10879 uid = mapUid(uid);
10880 if (Process.isIsolated(uid)) {
10881 mKernelUidCpuFreqTimeReader.removeUid(uid);
10882 Slog.d(TAG, "Got freq readings for an isolated uid with no mapping: " + uid);
10883 return;
10884 }
10885 if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
10886 Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
10887 mKernelUidCpuFreqTimeReader.removeUid(uid);
10888 return;
10889 }
10890 final Uid u = getUidStatsLocked(uid);
10891 if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
10892 u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
10893 }
10894 u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs);
10895 if (u.mScreenOffCpuFreqTimeMs == null ||
10896 u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
10897 u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
10898 mOnBatteryScreenOffTimeBase);
10899 }
10900 u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs);
10901
10902 if (perClusterTimesAvailable) {
10903 if (u.mCpuClusterSpeedTimesUs == null ||
10904 u.mCpuClusterSpeedTimesUs.length != numClusters) {
10905 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
10906 }
10907 if (numWakelocks > 0 && mWakeLockAllocationsUs == null) {
10908 mWakeLockAllocationsUs = new long[numClusters][];
10909 }
10910
10911 int freqIndex = 0;
10912 for (int cluster = 0; cluster < numClusters; ++cluster) {
10913 final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
10914 if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
10915 u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
10916 u.mCpuClusterSpeedTimesUs[cluster]
10917 = new LongSamplingCounter[speedsInCluster];
10918 }
10919 if (numWakelocks > 0 && mWakeLockAllocationsUs[cluster] == null) {
10920 mWakeLockAllocationsUs[cluster] = new long[speedsInCluster];
10921 }
10922 final LongSamplingCounter[] cpuTimesUs = u.mCpuClusterSpeedTimesUs[cluster];
10923 for (int speed = 0; speed < speedsInCluster; ++speed) {
10924 if (cpuTimesUs[speed] == null) {
10925 cpuTimesUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
10926 }
10927 final long appAllocationUs;
10928 if (mWakeLockAllocationsUs != null) {
10929 appAllocationUs =
10930 (cpuFreqTimeMs[freqIndex] * 1000 * WAKE_LOCK_WEIGHT) / 100;
10931 mWakeLockAllocationsUs[cluster][speed] +=
10932 (cpuFreqTimeMs[freqIndex] * 1000 - appAllocationUs);
10933 } else {
10934 appAllocationUs = cpuFreqTimeMs[freqIndex] * 1000;
10935 }
10936 cpuTimesUs[speed].addCountLocked(appAllocationUs);
10937 freqIndex++;
10938 }
10939 }
10940 }
10941 });
10942
10943 if (mWakeLockAllocationsUs != null) {
10944 for (int i = 0; i < numWakelocks; ++i) {
10945 final Uid u = partialTimers.get(i).mUid;
10946 if (u.mCpuClusterSpeedTimesUs == null ||
10947 u.mCpuClusterSpeedTimesUs.length != numClusters) {
10948 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
10949 }
10950
10951 for (int cluster = 0; cluster < numClusters; ++cluster) {
10952 final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
10953 if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
10954 u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
10955 u.mCpuClusterSpeedTimesUs[cluster]
10956 = new LongSamplingCounter[speedsInCluster];
10957 }
10958 final LongSamplingCounter[] cpuTimeUs = u.mCpuClusterSpeedTimesUs[cluster];
10959 for (int speed = 0; speed < speedsInCluster; ++speed) {
10960 if (cpuTimeUs[speed] == null) {
10961 cpuTimeUs[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
10962 }
10963 final long allocationUs =
10964 mWakeLockAllocationsUs[cluster][speed] / (numWakelocks - i);
10965 cpuTimeUs[speed].addCountLocked(allocationUs);
10966 mWakeLockAllocationsUs[cluster][speed] -= allocationUs;
10967 }
10968 }
10969 }
10970 }
10971 }
10972
10973 boolean setChargingLocked(boolean charging) {
10974 if (mCharging != charging) {
10975 mCharging = charging;
10976 if (charging) {
10977 mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
10978 } else {
10979 mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
10980 }
10981 mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
10982 return true;
10983 }
10984 return false;
10985 }
10986
Justin Klaassen93b7ee42017-10-10 15:20:13 -040010987 protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
10988 final boolean onBattery, final int oldStatus, final int level, final int chargeUAh) {
Justin Klaassen10d07c82017-09-15 17:58:39 -040010989 boolean doWrite = false;
10990 Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
10991 m.arg1 = onBattery ? 1 : 0;
10992 mHandler.sendMessage(m);
10993
10994 final long uptime = mSecUptime * 1000;
10995 final long realtime = mSecRealtime * 1000;
Justin Klaassen93b7ee42017-10-10 15:20:13 -040010996 final int screenState = mScreenState;
Justin Klaassen10d07c82017-09-15 17:58:39 -040010997 if (onBattery) {
10998 // We will reset our status if we are unplugging after the
10999 // battery was last full, or the level is at 100, or
11000 // we have gone through a significant charge (from a very low
11001 // level to a now very high level).
11002 boolean reset = false;
11003 if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
11004 || level >= 90
11005 || (mDischargeCurrentLevel < 20 && level >= 80)
11006 || (getHighDischargeAmountSinceCharge() >= 200
11007 && mHistoryBuffer.dataSize() >= MAX_HISTORY_BUFFER))) {
11008 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
11009 + " dischargeLevel=" + mDischargeCurrentLevel
11010 + " lowAmount=" + getLowDischargeAmountSinceCharge()
11011 + " highAmount=" + getHighDischargeAmountSinceCharge());
11012 // Before we write, collect a snapshot of the final aggregated
11013 // stats to be reported in the next checkin. Only do this if we have
11014 // a sufficient amount of data to make it interesting.
11015 if (getLowDischargeAmountSinceCharge() >= 20) {
11016 final Parcel parcel = Parcel.obtain();
11017 writeSummaryToParcel(parcel, true);
11018 BackgroundThread.getHandler().post(new Runnable() {
11019 @Override public void run() {
11020 synchronized (mCheckinFile) {
11021 FileOutputStream stream = null;
11022 try {
11023 stream = mCheckinFile.startWrite();
11024 stream.write(parcel.marshall());
11025 stream.flush();
11026 FileUtils.sync(stream);
11027 stream.close();
11028 mCheckinFile.finishWrite(stream);
11029 } catch (IOException e) {
11030 Slog.w("BatteryStats",
11031 "Error writing checkin battery statistics", e);
11032 mCheckinFile.failWrite(stream);
11033 } finally {
11034 parcel.recycle();
11035 }
11036 }
11037 }
11038 });
11039 }
11040 doWrite = true;
11041 resetAllStatsLocked();
11042 if (chargeUAh > 0 && level > 0) {
11043 // Only use the reported coulomb charge value if it is supported and reported.
11044 mEstimatedBatteryCapacity = (int) ((chargeUAh / 1000) / (level / 100.0));
11045 }
11046 mDischargeStartLevel = level;
11047 reset = true;
11048 mDischargeStepTracker.init();
11049 }
11050 if (mCharging) {
11051 setChargingLocked(false);
11052 }
11053 mLastChargingStateLevel = level;
11054 mOnBattery = mOnBatteryInternal = true;
11055 mLastDischargeStepLevel = level;
11056 mMinDischargeStepLevel = level;
11057 mDischargeStepTracker.clearTime();
11058 mDailyDischargeStepTracker.clearTime();
11059 mInitStepMode = mCurStepMode;
11060 mModStepMode = 0;
11061 pullPendingStateUpdatesLocked();
11062 mHistoryCur.batteryLevel = (byte)level;
11063 mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
11064 if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
11065 + Integer.toHexString(mHistoryCur.states));
11066 if (reset) {
11067 mRecordingHistory = true;
11068 startRecordingHistory(mSecRealtime, mSecUptime, reset);
11069 }
11070 addHistoryRecordLocked(mSecRealtime, mSecUptime);
11071 mDischargeCurrentLevel = mDischargeUnplugLevel = level;
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011072 if (isScreenOn(screenState)) {
Justin Klaassen10d07c82017-09-15 17:58:39 -040011073 mDischargeScreenOnUnplugLevel = level;
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011074 mDischargeScreenDozeUnplugLevel = 0;
11075 mDischargeScreenOffUnplugLevel = 0;
11076 } else if (isScreenDoze(screenState)) {
11077 mDischargeScreenOnUnplugLevel = 0;
11078 mDischargeScreenDozeUnplugLevel = level;
Justin Klaassen10d07c82017-09-15 17:58:39 -040011079 mDischargeScreenOffUnplugLevel = 0;
11080 } else {
11081 mDischargeScreenOnUnplugLevel = 0;
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011082 mDischargeScreenDozeUnplugLevel = 0;
Justin Klaassen10d07c82017-09-15 17:58:39 -040011083 mDischargeScreenOffUnplugLevel = level;
11084 }
11085 mDischargeAmountScreenOn = 0;
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011086 mDischargeAmountScreenDoze = 0;
Justin Klaassen10d07c82017-09-15 17:58:39 -040011087 mDischargeAmountScreenOff = 0;
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011088 updateTimeBasesLocked(true, screenState, uptime, realtime);
Justin Klaassen10d07c82017-09-15 17:58:39 -040011089 } else {
11090 mLastChargingStateLevel = level;
11091 mOnBattery = mOnBatteryInternal = false;
11092 pullPendingStateUpdatesLocked();
11093 mHistoryCur.batteryLevel = (byte)level;
11094 mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
11095 if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
11096 + Integer.toHexString(mHistoryCur.states));
11097 addHistoryRecordLocked(mSecRealtime, mSecUptime);
11098 mDischargeCurrentLevel = mDischargePlugLevel = level;
11099 if (level < mDischargeUnplugLevel) {
11100 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
11101 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
11102 }
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011103 updateDischargeScreenLevelsLocked(screenState, screenState);
11104 updateTimeBasesLocked(false, screenState, uptime, realtime);
Justin Klaassen10d07c82017-09-15 17:58:39 -040011105 mChargeStepTracker.init();
11106 mLastChargeStepLevel = level;
11107 mMaxChargeStepLevel = level;
11108 mInitStepMode = mCurStepMode;
11109 mModStepMode = 0;
11110 }
11111 if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
11112 if (mFile != null) {
11113 writeAsyncLocked();
11114 }
11115 }
11116 }
11117
11118 private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
11119 boolean reset) {
11120 mRecordingHistory = true;
11121 mHistoryCur.currentTime = System.currentTimeMillis();
11122 addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs,
11123 reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
11124 mHistoryCur);
11125 mHistoryCur.currentTime = 0;
11126 if (reset) {
11127 initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
11128 }
11129 }
11130
11131 private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
11132 final long uptimeMs) {
11133 if (mRecordingHistory) {
11134 mHistoryCur.currentTime = currentTime;
11135 addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_CURRENT_TIME,
11136 mHistoryCur);
11137 mHistoryCur.currentTime = 0;
11138 }
11139 }
11140
11141 private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
11142 if (mRecordingHistory) {
11143 mHistoryCur.currentTime = System.currentTimeMillis();
11144 addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_SHUTDOWN,
11145 mHistoryCur);
11146 mHistoryCur.currentTime = 0;
11147 }
11148 }
11149
11150 private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
11151 if (mExternalSync != null) {
11152 mExternalSync.scheduleSync(reason, updateFlags);
11153 }
11154 }
11155
11156 // This should probably be exposed in the API, though it's not critical
11157 public static final int BATTERY_PLUGGED_NONE = 0;
11158
11159 public void setBatteryStateLocked(int status, int health, int plugType, int level,
11160 int temp, int volt, int chargeUAh, int chargeFullUAh) {
11161 // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
11162 temp = Math.max(0, temp);
11163
11164 final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
11165 final long uptime = mClocks.uptimeMillis();
11166 final long elapsedRealtime = mClocks.elapsedRealtime();
11167 if (!mHaveBatteryLevel) {
11168 mHaveBatteryLevel = true;
11169 // We start out assuming that the device is plugged in (not
11170 // on battery). If our first report is now that we are indeed
11171 // plugged in, then twiddle our state to correctly reflect that
11172 // since we won't be going through the full setOnBattery().
11173 if (onBattery == mOnBattery) {
11174 if (onBattery) {
11175 mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
11176 } else {
11177 mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
11178 }
11179 }
11180 // Always start out assuming charging, that will be updated later.
11181 mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
11182 mHistoryCur.batteryStatus = (byte)status;
11183 mHistoryCur.batteryLevel = (byte)level;
11184 mHistoryCur.batteryChargeUAh = chargeUAh;
11185 mMaxChargeStepLevel = mMinDischargeStepLevel =
11186 mLastChargeStepLevel = mLastDischargeStepLevel = level;
11187 mLastChargingStateLevel = level;
11188 } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
11189 recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
11190 }
11191 int oldStatus = mHistoryCur.batteryStatus;
11192 if (onBattery) {
11193 mDischargeCurrentLevel = level;
11194 if (!mRecordingHistory) {
11195 mRecordingHistory = true;
11196 startRecordingHistory(elapsedRealtime, uptime, true);
11197 }
11198 } else if (level < 96) {
11199 if (!mRecordingHistory) {
11200 mRecordingHistory = true;
11201 startRecordingHistory(elapsedRealtime, uptime, true);
11202 }
11203 }
11204 mCurrentBatteryLevel = level;
11205 if (mDischargePlugLevel < 0) {
11206 mDischargePlugLevel = level;
11207 }
11208
11209 if (onBattery != mOnBattery) {
11210 mHistoryCur.batteryLevel = (byte)level;
11211 mHistoryCur.batteryStatus = (byte)status;
11212 mHistoryCur.batteryHealth = (byte)health;
11213 mHistoryCur.batteryPlugType = (byte)plugType;
11214 mHistoryCur.batteryTemperature = (short)temp;
11215 mHistoryCur.batteryVoltage = (char)volt;
11216 if (chargeUAh < mHistoryCur.batteryChargeUAh) {
11217 // Only record discharges
11218 final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
11219 mDischargeCounter.addCountLocked(chargeDiff);
11220 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011221 if (isScreenDoze(mScreenState)) {
11222 mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
11223 }
Justin Klaassen10d07c82017-09-15 17:58:39 -040011224 }
11225 mHistoryCur.batteryChargeUAh = chargeUAh;
11226 setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level, chargeUAh);
11227 } else {
11228 boolean changed = false;
11229 if (mHistoryCur.batteryLevel != level) {
11230 mHistoryCur.batteryLevel = (byte)level;
11231 changed = true;
11232
11233 // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
11234 // which will pull external stats.
11235 scheduleSyncExternalStatsLocked("battery-level", ExternalStatsSync.UPDATE_ALL);
11236 }
11237 if (mHistoryCur.batteryStatus != status) {
11238 mHistoryCur.batteryStatus = (byte)status;
11239 changed = true;
11240 }
11241 if (mHistoryCur.batteryHealth != health) {
11242 mHistoryCur.batteryHealth = (byte)health;
11243 changed = true;
11244 }
11245 if (mHistoryCur.batteryPlugType != plugType) {
11246 mHistoryCur.batteryPlugType = (byte)plugType;
11247 changed = true;
11248 }
11249 if (temp >= (mHistoryCur.batteryTemperature+10)
11250 || temp <= (mHistoryCur.batteryTemperature-10)) {
11251 mHistoryCur.batteryTemperature = (short)temp;
11252 changed = true;
11253 }
11254 if (volt > (mHistoryCur.batteryVoltage+20)
11255 || volt < (mHistoryCur.batteryVoltage-20)) {
11256 mHistoryCur.batteryVoltage = (char)volt;
11257 changed = true;
11258 }
11259 if (chargeUAh >= (mHistoryCur.batteryChargeUAh+10)
11260 || chargeUAh <= (mHistoryCur.batteryChargeUAh-10)) {
11261 if (chargeUAh < mHistoryCur.batteryChargeUAh) {
11262 // Only record discharges
11263 final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
11264 mDischargeCounter.addCountLocked(chargeDiff);
11265 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011266 if (isScreenDoze(mScreenState)) {
11267 mDischargeScreenDozeCounter.addCountLocked(chargeDiff);
11268 }
Justin Klaassen10d07c82017-09-15 17:58:39 -040011269 }
11270 mHistoryCur.batteryChargeUAh = chargeUAh;
11271 changed = true;
11272 }
11273 long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
11274 | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
11275 | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
11276 if (onBattery) {
11277 changed |= setChargingLocked(false);
11278 if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
11279 mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
11280 modeBits, elapsedRealtime);
11281 mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
11282 modeBits, elapsedRealtime);
11283 mLastDischargeStepLevel = level;
11284 mMinDischargeStepLevel = level;
11285 mInitStepMode = mCurStepMode;
11286 mModStepMode = 0;
11287 }
11288 } else {
11289 if (level >= 90) {
11290 // If the battery level is at least 90%, always consider the device to be
11291 // charging even if it happens to go down a level.
11292 changed |= setChargingLocked(true);
11293 mLastChargeStepLevel = level;
11294 } if (!mCharging) {
11295 if (mLastChargeStepLevel < level) {
11296 // We have not reporting that we are charging, but the level has now
11297 // gone up, so consider the state to be charging.
11298 changed |= setChargingLocked(true);
11299 mLastChargeStepLevel = level;
11300 }
11301 } else {
11302 if (mLastChargeStepLevel > level) {
11303 // We had reported that the device was charging, but here we are with
11304 // power connected and the level going down. Looks like the current
11305 // power supplied isn't enough, so consider the device to now be
11306 // discharging.
11307 changed |= setChargingLocked(false);
11308 mLastChargeStepLevel = level;
11309 }
11310 }
11311 if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
11312 mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
11313 modeBits, elapsedRealtime);
11314 mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
11315 modeBits, elapsedRealtime);
11316 mLastChargeStepLevel = level;
11317 mMaxChargeStepLevel = level;
11318 mInitStepMode = mCurStepMode;
11319 mModStepMode = 0;
11320 }
11321 }
11322 if (changed) {
11323 addHistoryRecordLocked(elapsedRealtime, uptime);
11324 }
11325 }
11326 if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) {
11327 // We don't record history while we are plugged in and fully charged.
11328 // The next time we are unplugged, history will be cleared.
11329 mRecordingHistory = DEBUG;
11330 }
11331
11332 if (mMinLearnedBatteryCapacity == -1) {
11333 mMinLearnedBatteryCapacity = chargeFullUAh;
11334 } else {
11335 Math.min(mMinLearnedBatteryCapacity, chargeFullUAh);
11336 }
11337 mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh);
11338 }
11339
11340 public long getAwakeTimeBattery() {
11341 return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
11342 }
11343
11344 public long getAwakeTimePlugged() {
11345 return (mClocks.uptimeMillis() * 1000) - getAwakeTimeBattery();
11346 }
11347
11348 @Override
11349 public long computeUptime(long curTime, int which) {
11350 switch (which) {
11351 case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart);
11352 case STATS_CURRENT: return (curTime-mUptimeStart);
11353 case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getUptimeStart());
11354 }
11355 return 0;
11356 }
11357
11358 @Override
11359 public long computeRealtime(long curTime, int which) {
11360 switch (which) {
11361 case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart);
11362 case STATS_CURRENT: return (curTime-mRealtimeStart);
11363 case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getRealtimeStart());
11364 }
11365 return 0;
11366 }
11367
11368 @Override
11369 public long computeBatteryUptime(long curTime, int which) {
11370 return mOnBatteryTimeBase.computeUptime(curTime, which);
11371 }
11372
11373 @Override
11374 public long computeBatteryRealtime(long curTime, int which) {
11375 return mOnBatteryTimeBase.computeRealtime(curTime, which);
11376 }
11377
11378 @Override
11379 public long computeBatteryScreenOffUptime(long curTime, int which) {
11380 return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
11381 }
11382
11383 @Override
11384 public long computeBatteryScreenOffRealtime(long curTime, int which) {
11385 return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
11386 }
11387
11388 private long computeTimePerLevel(long[] steps, int numSteps) {
11389 // For now we'll do a simple average across all steps.
11390 if (numSteps <= 0) {
11391 return -1;
11392 }
11393 long total = 0;
11394 for (int i=0; i<numSteps; i++) {
11395 total += steps[i] & STEP_LEVEL_TIME_MASK;
11396 }
11397 return total / numSteps;
11398 /*
11399 long[] buckets = new long[numSteps];
11400 int numBuckets = 0;
11401 int numToAverage = 4;
11402 int i = 0;
11403 while (i < numSteps) {
11404 long totalTime = 0;
11405 int num = 0;
11406 for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
11407 totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
11408 num++;
11409 }
11410 buckets[numBuckets] = totalTime / num;
11411 numBuckets++;
11412 numToAverage *= 2;
11413 i += num;
11414 }
11415 if (numBuckets < 1) {
11416 return -1;
11417 }
11418 long averageTime = buckets[numBuckets-1];
11419 for (i=numBuckets-2; i>=0; i--) {
11420 averageTime = (averageTime + buckets[i]) / 2;
11421 }
11422 return averageTime;
11423 */
11424 }
11425
11426 @Override
11427 public long computeBatteryTimeRemaining(long curTime) {
11428 if (!mOnBattery) {
11429 return -1;
11430 }
11431 /* Simple implementation just looks at the average discharge per level across the
11432 entire sample period.
11433 int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
11434 if (discharge < 2) {
11435 return -1;
11436 }
11437 long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
11438 if (duration < 1000*1000) {
11439 return -1;
11440 }
11441 long usPerLevel = duration/discharge;
11442 return usPerLevel * mCurrentBatteryLevel;
11443 */
11444 if (mDischargeStepTracker.mNumStepDurations < 1) {
11445 return -1;
11446 }
11447 long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
11448 if (msPerLevel <= 0) {
11449 return -1;
11450 }
11451 return (msPerLevel * mCurrentBatteryLevel) * 1000;
11452 }
11453
11454 @Override
11455 public LevelStepTracker getDischargeLevelStepTracker() {
11456 return mDischargeStepTracker;
11457 }
11458
11459 @Override
11460 public LevelStepTracker getDailyDischargeLevelStepTracker() {
11461 return mDailyDischargeStepTracker;
11462 }
11463
11464 @Override
11465 public long computeChargeTimeRemaining(long curTime) {
11466 if (mOnBattery) {
11467 // Not yet working.
11468 return -1;
11469 }
11470 /* Broken
11471 int curLevel = mCurrentBatteryLevel;
11472 int plugLevel = mDischargePlugLevel;
11473 if (plugLevel < 0 || curLevel < (plugLevel+1)) {
11474 return -1;
11475 }
11476 long duration = computeBatteryRealtime(curTime, STATS_SINCE_UNPLUGGED);
11477 if (duration < 1000*1000) {
11478 return -1;
11479 }
11480 long usPerLevel = duration/(curLevel-plugLevel);
11481 return usPerLevel * (100-curLevel);
11482 */
11483 if (mChargeStepTracker.mNumStepDurations < 1) {
11484 return -1;
11485 }
11486 long msPerLevel = mChargeStepTracker.computeTimePerLevel();
11487 if (msPerLevel <= 0) {
11488 return -1;
11489 }
11490 return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
11491 }
11492
11493 @Override
11494 public LevelStepTracker getChargeLevelStepTracker() {
11495 return mChargeStepTracker;
11496 }
11497
11498 @Override
11499 public LevelStepTracker getDailyChargeLevelStepTracker() {
11500 return mDailyChargeStepTracker;
11501 }
11502
11503 @Override
11504 public ArrayList<PackageChange> getDailyPackageChanges() {
11505 return mDailyPackageChanges;
11506 }
11507
11508 protected long getBatteryUptimeLocked() {
11509 return mOnBatteryTimeBase.getUptime(mClocks.uptimeMillis() * 1000);
11510 }
11511
11512 @Override
11513 public long getBatteryUptime(long curTime) {
11514 return mOnBatteryTimeBase.getUptime(curTime);
11515 }
11516
11517 @Override
11518 public long getBatteryRealtime(long curTime) {
11519 return mOnBatteryTimeBase.getRealtime(curTime);
11520 }
11521
11522 @Override
11523 public int getDischargeStartLevel() {
11524 synchronized(this) {
11525 return getDischargeStartLevelLocked();
11526 }
11527 }
11528
11529 public int getDischargeStartLevelLocked() {
11530 return mDischargeUnplugLevel;
11531 }
11532
11533 @Override
11534 public int getDischargeCurrentLevel() {
11535 synchronized(this) {
11536 return getDischargeCurrentLevelLocked();
11537 }
11538 }
11539
11540 public int getDischargeCurrentLevelLocked() {
11541 return mDischargeCurrentLevel;
11542 }
11543
11544 @Override
11545 public int getLowDischargeAmountSinceCharge() {
11546 synchronized(this) {
11547 int val = mLowDischargeAmountSinceCharge;
11548 if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
11549 val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
11550 }
11551 return val;
11552 }
11553 }
11554
11555 @Override
11556 public int getHighDischargeAmountSinceCharge() {
11557 synchronized(this) {
11558 int val = mHighDischargeAmountSinceCharge;
11559 if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
11560 val += mDischargeUnplugLevel-mDischargeCurrentLevel;
11561 }
11562 return val;
11563 }
11564 }
11565
11566 @Override
11567 public int getDischargeAmount(int which) {
11568 int dischargeAmount = which == STATS_SINCE_CHARGED
11569 ? getHighDischargeAmountSinceCharge()
11570 : (getDischargeStartLevel() - getDischargeCurrentLevel());
11571 if (dischargeAmount < 0) {
11572 dischargeAmount = 0;
11573 }
11574 return dischargeAmount;
11575 }
11576
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011577 @Override
Justin Klaassen10d07c82017-09-15 17:58:39 -040011578 public int getDischargeAmountScreenOn() {
11579 synchronized(this) {
11580 int val = mDischargeAmountScreenOn;
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011581 if (mOnBattery && isScreenOn(mScreenState)
Justin Klaassen10d07c82017-09-15 17:58:39 -040011582 && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
11583 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
11584 }
11585 return val;
11586 }
11587 }
11588
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011589 @Override
Justin Klaassen10d07c82017-09-15 17:58:39 -040011590 public int getDischargeAmountScreenOnSinceCharge() {
11591 synchronized(this) {
11592 int val = mDischargeAmountScreenOnSinceCharge;
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011593 if (mOnBattery && isScreenOn(mScreenState)
Justin Klaassen10d07c82017-09-15 17:58:39 -040011594 && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
11595 val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
11596 }
11597 return val;
11598 }
11599 }
11600
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011601 @Override
Justin Klaassen10d07c82017-09-15 17:58:39 -040011602 public int getDischargeAmountScreenOff() {
11603 synchronized(this) {
11604 int val = mDischargeAmountScreenOff;
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011605 if (mOnBattery && isScreenOff(mScreenState)
Justin Klaassen10d07c82017-09-15 17:58:39 -040011606 && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
11607 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
11608 }
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011609 // For backward compatibility, doze discharge is counted into screen off.
11610 return val + getDischargeAmountScreenDoze();
11611 }
11612 }
11613
11614 @Override
11615 public int getDischargeAmountScreenOffSinceCharge() {
11616 synchronized(this) {
11617 int val = mDischargeAmountScreenOffSinceCharge;
11618 if (mOnBattery && isScreenOff(mScreenState)
11619 && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
11620 val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
11621 }
11622 // For backward compatibility, doze discharge is counted into screen off.
11623 return val + getDischargeAmountScreenDozeSinceCharge();
11624 }
11625 }
11626
11627 @Override
11628 public int getDischargeAmountScreenDoze() {
11629 synchronized(this) {
11630 int val = mDischargeAmountScreenDoze;
11631 if (mOnBattery && isScreenDoze(mScreenState)
11632 && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
11633 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
11634 }
Justin Klaassen10d07c82017-09-15 17:58:39 -040011635 return val;
11636 }
11637 }
11638
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011639 @Override
11640 public int getDischargeAmountScreenDozeSinceCharge() {
Justin Klaassen10d07c82017-09-15 17:58:39 -040011641 synchronized(this) {
Justin Klaassen93b7ee42017-10-10 15:20:13 -040011642 int val = mDischargeAmountScreenDozeSinceCharge;
11643 if (mOnBattery && isScreenDoze(mScreenState)
11644 && mDischargeCurrentLevel < mDischargeScreenDozeUnplugLevel) {
11645 val += mDischargeScreenDozeUnplugLevel-mDischargeCurrentLevel;
Justin Klaassen10d07c82017-09-15 17:58:39 -040011646 }
11647 return val;
11648 }
11649 }
11650
11651 /**
11652 * Retrieve the statistics object for a particular uid, creating if needed.
11653 */
11654 public Uid getUidStatsLocked(int uid) {
11655 Uid u = mUidStats.get(uid);
11656 if (u == null) {
11657 u = new Uid(this, uid);
11658 mUidStats.put(uid, u);
11659 }
11660 return u;
11661 }
11662
11663 public void onCleanupUserLocked(int userId) {
11664 final int firstUidForUser = UserHandle.getUid(userId, 0);
11665 final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
11666 mKernelUidCpuFreqTimeReader.removeUidsInRange(firstUidForUser, lastUidForUser);
11667 mKernelUidCpuTimeReader.removeUidsInRange(firstUidForUser, lastUidForUser);
11668 }
11669
11670 public void onUserRemovedLocked(int userId) {
11671 final int firstUidForUser = UserHandle.getUid(userId, 0);
11672 final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
11673 mUidStats.put(firstUidForUser, null);
11674 mUidStats.put(lastUidForUser, null);
11675 final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
11676 final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
11677 mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
11678 }
11679
11680 /**
11681 * Remove the statistics object for a particular uid.
11682 */
11683 public void removeUidStatsLocked(int uid) {
11684 mKernelUidCpuTimeReader.removeUid(uid);
11685 mKernelUidCpuFreqTimeReader.removeUid(uid);
11686 mUidStats.remove(uid);
11687 }
11688
11689 /**
11690 * Retrieve the statistics object for a particular process, creating
11691 * if needed.
11692 */
11693 public Uid.Proc getProcessStatsLocked(int uid, String name) {
11694 uid = mapUid(uid);
11695 Uid u = getUidStatsLocked(uid);
11696 return u.getProcessStatsLocked(name);
11697 }
11698
11699 /**
11700 * Retrieve the statistics object for a particular process, creating
11701 * if needed.
11702 */
11703 public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
11704 uid = mapUid(uid);
11705 Uid u = getUidStatsLocked(uid);
11706 return u.getPackageStatsLocked(pkg);
11707 }
11708
11709 /**
11710 * Retrieve the statistics object for a particular service, creating
11711 * if needed.
11712 */
11713 public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
11714 uid = mapUid(uid);
11715 Uid u = getUidStatsLocked(uid);
11716 return u.getServiceStatsLocked(pkg, name);
11717 }
11718
11719 public void shutdownLocked() {
11720 recordShutdownLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
11721 writeSyncLocked();
11722 mShuttingDown = true;
11723 }
11724
11725 Parcel mPendingWrite = null;
11726 final ReentrantLock mWriteLock = new ReentrantLock();
11727
11728 public void writeAsyncLocked() {
11729 writeLocked(false);
11730 }
11731
11732 public void writeSyncLocked() {
11733 writeLocked(true);
11734 }
11735
11736 void writeLocked(boolean sync) {
11737 if (mFile == null) {
11738 Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
11739 return;
11740 }
11741
11742 if (mShuttingDown) {
11743 return;
11744 }
11745
11746 Parcel out = Parcel.obtain();
11747 writeSummaryToParcel(out, true);
11748 mLastWriteTime = mClocks.elapsedRealtime();
11749
11750 if (mPendingWrite != null) {
11751 mPendingWrite.recycle();
11752 }
11753 mPendingWrite = out;
11754
11755 if (sync) {
11756 commitPendingDataToDisk();
11757 } else {
11758 BackgroundThread.getHandler().post(new Runnable() {
11759 @Override public void run() {
11760 commitPendingDataToDisk();
11761 }
11762 });
11763 }
11764 }
11765
11766 public void commitPendingDataToDisk() {
11767 final Parcel next;
11768 synchronized (this) {
11769 next = mPendingWrite;
11770 mPendingWrite = null;
11771 if (next == null) {
11772 return;
11773 }
11774 }
11775
11776 mWriteLock.lock();
11777 try {
11778 FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
11779 stream.write(next.marshall());
11780 stream.flush();
11781 FileUtils.sync(stream);
11782 stream.close();
11783 mFile.commit();
11784 } catch (IOException e) {
11785 Slog.w("BatteryStats", "Error writing battery statistics", e);
11786 mFile.rollback();
11787 } finally {
11788 next.recycle();
11789 mWriteLock.unlock();
11790 }
11791 }
11792
11793 public void readLocked() {
11794 if (mDailyFile != null) {
11795 readDailyStatsLocked();
11796 }
11797
11798 if (mFile == null) {
11799 Slog.w("BatteryStats", "readLocked: no file associated with this instance");
11800 return;
11801 }
11802
11803 mUidStats.clear();
11804
11805 try {
11806 File file = mFile.chooseForRead();
11807 if (!file.exists()) {
11808 return;
11809 }
11810 FileInputStream stream = new FileInputStream(file);
11811
11812 byte[] raw = BatteryStatsHelper.readFully(stream);
11813 Parcel in = Parcel.obtain();
11814 in.unmarshall(raw, 0, raw.length);
11815 in.setDataPosition(0);
11816 stream.close();
11817
11818 readSummaryFromParcel(in);
11819 } catch(Exception e) {
11820 Slog.e("BatteryStats", "Error reading battery statistics", e);
11821 resetAllStatsLocked();
11822 }
11823
11824 mEndPlatformVersion = Build.ID;
11825
11826 if (mHistoryBuffer.dataPosition() > 0) {
11827 mRecordingHistory = true;
11828 final long elapsedRealtime = mClocks.elapsedRealtime();
11829 final long uptime = mClocks.uptimeMillis();
11830 if (USE_OLD_HISTORY) {
11831 addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
11832 }
11833 addHistoryBufferLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
11834 startRecordingHistory(elapsedRealtime, uptime, false);
11835 }
11836
11837 recordDailyStatsIfNeededLocked(false);
11838 }
11839
11840 public int describeContents() {
11841 return 0;
11842 }
11843
11844 void readHistory(Parcel in, boolean andOldHistory) throws ParcelFormatException {
11845 final long historyBaseTime = in.readLong();
11846
11847 mHistoryBuffer.setDataSize(0);
11848 mHistoryBuffer.setDataPosition(0);
11849 mHistoryTagPool.clear();
11850 mNextHistoryTagIdx = 0;
11851 mNumHistoryTagChars = 0;
11852
11853 int numTags = in.readInt();
11854 for (int i=0; i<numTags; i++) {
11855 int idx = in.readInt();
11856 String str = in.readString();
11857 if (str == null) {
11858 throw new ParcelFormatException("null history tag string");
11859 }
11860 int uid = in.readInt();
11861 HistoryTag tag = new HistoryTag();
11862 tag.string = str;
11863 tag.uid = uid;
11864 tag.poolIdx = idx;
11865 mHistoryTagPool.put(tag, idx);
11866 if (idx >= mNextHistoryTagIdx) {
11867 mNextHistoryTagIdx = idx+1;
11868 }
11869 mNumHistoryTagChars += tag.string.length() + 1;
11870 }
11871
11872 int bufSize = in.readInt();
11873 int curPos = in.dataPosition();
11874 if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) {
11875 throw new ParcelFormatException("File corrupt: history data buffer too large " +
11876 bufSize);
11877 } else if ((bufSize&~3) != bufSize) {
11878 throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
11879 bufSize);
11880 } else {
11881 if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
11882 + " bytes at " + curPos);
11883 mHistoryBuffer.appendFrom(in, curPos, bufSize);
11884 in.setDataPosition(curPos + bufSize);
11885 }
11886
11887 if (andOldHistory) {
11888 readOldHistory(in);
11889 }
11890
11891 if (DEBUG_HISTORY) {
11892 StringBuilder sb = new StringBuilder(128);
11893 sb.append("****************** OLD mHistoryBaseTime: ");
11894 TimeUtils.formatDuration(mHistoryBaseTime, sb);
11895 Slog.i(TAG, sb.toString());
11896 }
11897 mHistoryBaseTime = historyBaseTime;
11898 if (DEBUG_HISTORY) {
11899 StringBuilder sb = new StringBuilder(128);
11900 sb.append("****************** NEW mHistoryBaseTime: ");
11901 TimeUtils.formatDuration(mHistoryBaseTime, sb);
11902 Slog.i(TAG, sb.toString());
11903 }
11904
11905 // We are just arbitrarily going to insert 1 minute from the sample of
11906 // the last run until samples in this run.
11907 if (mHistoryBaseTime > 0) {
11908 long oldnow = mClocks.elapsedRealtime();
11909 mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
11910 if (DEBUG_HISTORY) {
11911 StringBuilder sb = new StringBuilder(128);
11912 sb.append("****************** ADJUSTED mHistoryBaseTime: ");
11913 TimeUtils.formatDuration(mHistoryBaseTime, sb);
11914 Slog.i(TAG, sb.toString());
11915 }
11916 }
11917 }
11918
11919 void readOldHistory(Parcel in) {
11920 if (!USE_OLD_HISTORY) {
11921 return;
11922 }
11923 mHistory = mHistoryEnd = mHistoryCache = null;
11924 long time;
11925 while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
11926 HistoryItem rec = new HistoryItem(time, in);
11927 addHistoryRecordLocked(rec);
11928 }
11929 }
11930
11931 void writeHistory(Parcel out, boolean inclData, boolean andOldHistory) {
11932 if (DEBUG_HISTORY) {
11933 StringBuilder sb = new StringBuilder(128);
11934 sb.append("****************** WRITING mHistoryBaseTime: ");
11935 TimeUtils.formatDuration(mHistoryBaseTime, sb);
11936 sb.append(" mLastHistoryElapsedRealtime: ");
11937 TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
11938 Slog.i(TAG, sb.toString());
11939 }
11940 out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
11941 if (!inclData) {
11942 out.writeInt(0);
11943 out.writeInt(0);
11944 return;
11945 }
11946 out.writeInt(mHistoryTagPool.size());
11947 for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
11948 HistoryTag tag = ent.getKey();
11949 out.writeInt(ent.getValue());
11950 out.writeString(tag.string);
11951 out.writeInt(tag.uid);
11952 }
11953 out.writeInt(mHistoryBuffer.dataSize());
11954 if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
11955 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
11956 out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
11957
11958 if (andOldHistory) {
11959 writeOldHistory(out);
11960 }
11961 }
11962
11963 void writeOldHistory(Parcel out) {
11964 if (!USE_OLD_HISTORY) {
11965 return;
11966 }
11967 HistoryItem rec = mHistory;
11968 while (rec != null) {
11969 if (rec.time >= 0) rec.writeToParcel(out, 0);
11970 rec = rec.next;
11971 }
11972 out.writeLong(-1);
11973 }
11974
11975 public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
11976 final int version = in.readInt();
11977 if (version != VERSION) {
11978 Slog.w("BatteryStats", "readFromParcel: version got " + version
11979 + ", expected " + VERSION + "; erasing old stats");
11980 return;
11981 }
11982
11983 readHistory(in, true);
11984
11985 mStartCount = in.readInt();
11986 mUptime = in.readLong();
11987 mRealtime = in.readLong();
11988 mStartClockTime = in.readLong();
11989 mStartPlatformVersion = in.readString();
11990 mEndPlatformVersion = in.readString();
11991 mOnBatteryTimeBase.readSummaryFromParcel(in);
11992 mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
11993 mDischargeUnplugLevel = in.readInt();
11994 mDischargePlugLevel = in.readInt();
11995 mDischargeCurrentLevel = in.readInt();
11996 mCurrentBatteryLevel = in.readInt();
11997 mEstimatedBatteryCapacity = in.readInt();
11998 mMinLearnedBatteryCapacity = in.readInt();
11999 mMaxLearnedBatteryCapacity = in.readInt();
12000 mLowDischargeAmountSinceCharge = in.readInt();
12001 mHighDischargeAmountSinceCharge = in.readInt();
12002 mDischargeAmountScreenOnSinceCharge = in.readInt();
12003 mDischargeAmountScreenOffSinceCharge = in.readInt();
Justin Klaassen93b7ee42017-10-10 15:20:13 -040012004 mDischargeAmountScreenDozeSinceCharge = in.readInt();
Justin Klaassen10d07c82017-09-15 17:58:39 -040012005 mDischargeStepTracker.readFromParcel(in);
12006 mChargeStepTracker.readFromParcel(in);
12007 mDailyDischargeStepTracker.readFromParcel(in);
12008 mDailyChargeStepTracker.readFromParcel(in);
12009 mDischargeCounter.readSummaryFromParcelLocked(in);
12010 mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
Justin Klaassen93b7ee42017-10-10 15:20:13 -040012011 mDischargeScreenDozeCounter.readSummaryFromParcelLocked(in);
Justin Klaassen10d07c82017-09-15 17:58:39 -040012012 int NPKG = in.readInt();
12013 if (NPKG > 0) {
12014 mDailyPackageChanges = new ArrayList<>(NPKG);
12015 while (NPKG > 0) {
12016 NPKG--;
12017 PackageChange pc = new PackageChange();
12018 pc.mPackageName = in.readString();
12019 pc.mUpdate = in.readInt() != 0;
12020 pc.mVersionCode = in.readInt();
12021 mDailyPackageChanges.add(pc);
12022 }
12023 } else {
12024 mDailyPackageChanges = null;
12025 }
12026 mDailyStartTime = in.readLong();
12027 mNextMinDailyDeadline = in.readLong();
12028 mNextMaxDailyDeadline = in.readLong();
12029
12030 mStartCount++;
12031
12032 mScreenState = Display.STATE_UNKNOWN;
12033 mScreenOnTimer.readSummaryFromParcelLocked(in);
Justin Klaassen93b7ee42017-10-10 15:20:13 -040012034 mScreenDozeTimer.readSummaryFromParcelLocked(in);
Justin Klaassen10d07c82017-09-15 17:58:39 -040012035 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
12036 mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
12037 }
12038 mInteractive = false;
12039 mInteractiveTimer.readSummaryFromParcelLocked(in);
12040 mPhoneOn = false;
12041 mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
12042 mLongestLightIdleTime = in.readLong();
12043 mLongestFullIdleTime = in.readLong();
12044 mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
12045 mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
12046 mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
12047 mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
12048 mPhoneOnTimer.readSummaryFromParcelLocked(in);
12049 for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
12050 mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
12051 }
12052 mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
12053 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
12054 mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
12055 }
12056 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
12057 mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
12058 mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
12059 }
12060 mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
12061 mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
12062 mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
12063 mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
12064 mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
12065 mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
12066 mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
12067 mWifiOn = false;
12068 mWifiOnTimer.readSummaryFromParcelLocked(in);
12069 mGlobalWifiRunning = false;
12070 mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
12071 for (int i=0; i<NUM_WIFI_STATES; i++) {
12072 mWifiStateTimer[i].readSummaryFromParcelLocked(in);
12073 }
12074 for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
12075 mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
12076 }
12077 for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
12078 mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
12079 }
12080 mWifiActivity.readSummaryFromParcel(in);
12081 mBluetoothActivity.readSummaryFromParcel(in);
12082 mModemActivity.readSummaryFromParcel(in);
12083 mHasWifiReporting = in.readInt() != 0;
12084 mHasBluetoothReporting = in.readInt() != 0;
12085 mHasModemReporting = in.readInt() != 0;
12086
12087 mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
12088 mFlashlightOnNesting = 0;
12089 mFlashlightOnTimer.readSummaryFromParcelLocked(in);
12090 mCameraOnNesting = 0;
12091 mCameraOnTimer.readSummaryFromParcelLocked(in);
12092 mBluetoothScanNesting = 0;
12093 mBluetoothScanTimer.readSummaryFromParcelLocked(in);
12094
Justin Klaassenbc81c7a2017-09-18 17:38:50 -040012095 int NRPMS = in.readInt();
12096 if (NRPMS > 10000) {
12097 throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS);
12098 }
12099 for (int irpm = 0; irpm < NRPMS; irpm++) {
12100 if (in.readInt() != 0) {
12101 String rpmName = in.readString();
12102 getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
12103 }
12104 }
12105 int NSORPMS = in.readInt();
12106 if (NSORPMS > 10000) {
12107 throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS);
12108 }
12109 for (int irpm = 0; irpm < NSORPMS; irpm++) {
12110 if (in.readInt() != 0) {
12111 String rpmName = in.readString();
12112 getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
12113 }
12114 }
12115
Justin Klaassen10d07c82017-09-15 17:58:39 -040012116 int NKW = in.readInt();
12117 if (NKW > 10000) {
12118 throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
12119 }
12120 for (int ikw = 0; ikw < NKW; ikw++) {
12121 if (in.readInt() != 0) {
12122 String kwltName = in.readString();
12123 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
12124 }
12125 }
12126
12127 int NWR = in.readInt();
12128 if (NWR > 10000) {
12129 throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
12130 }
12131 for (int iwr = 0; iwr < NWR; iwr++) {
12132 if (in.readInt() != 0) {
12133 String reasonName = in.readString();
12134 getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
12135 }
12136 }
12137
12138 int NMS = in.readInt();
12139 for (int ims = 0; ims < NMS; ims++) {
12140 if (in.readInt() != 0) {
12141 long kmstName = in.readLong();
12142 getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
12143 }
12144 }
12145
12146 final int NU = in.readInt();
12147 if (NU > 10000) {
12148 throw new ParcelFormatException("File corrupt: too many uids " + NU);
12149 }
12150 for (int iu = 0; iu < NU; iu++) {
12151 int uid = in.readInt();
12152 Uid u = new Uid(this, uid);
12153 mUidStats.put(uid, u);
12154
12155 u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
12156 u.mOnBatteryScreenOffBackgroundTimeBase.readSummaryFromParcel(in);
12157
12158 u.mWifiRunning = false;
12159 if (in.readInt() != 0) {
12160 u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
12161 }
12162 u.mFullWifiLockOut = false;
12163 if (in.readInt() != 0) {
12164 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
12165 }
12166 u.mWifiScanStarted = false;
12167 if (in.readInt() != 0) {
12168 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
12169 }
12170 u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
12171 for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
12172 if (in.readInt() != 0) {
12173 u.makeWifiBatchedScanBin(i, null);
12174 u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
12175 }
12176 }
12177 u.mWifiMulticastEnabled = false;
12178 if (in.readInt() != 0) {
12179 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
12180 }
12181 if (in.readInt() != 0) {
12182 u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
12183 }
12184 if (in.readInt() != 0) {
12185 u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
12186 }
12187 if (in.readInt() != 0) {
12188 u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
12189 }
12190 if (in.readInt() != 0) {
12191 u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
12192 }
12193 if (in.readInt() != 0) {
12194 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
12195 }
12196 if (in.readInt() != 0) {
12197 u.createForegroundServiceTimerLocked().readSummaryFromParcelLocked(in);
12198 }
12199 if (in.readInt() != 0) {
12200 u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
12201 }
12202 if (in.readInt() != 0) {
12203 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
12204 }
12205 if (in.readInt() != 0) {
12206 u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in);
12207 }
12208 if (in.readInt() != 0) {
12209 u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
12210 }
12211 if (in.readInt() != 0) {
12212 u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in);
12213 }
12214 u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
12215 for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
12216 if (in.readInt() != 0) {
12217 u.makeProcessState(i, null);
12218 u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
12219 }
12220 }
12221 if (in.readInt() != 0) {
12222 u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
12223 }
12224
12225 if (in.readInt() != 0) {
12226 if (u.mUserActivityCounters == null) {
12227 u.initUserActivityLocked();
12228 }
12229 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
12230 u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
12231 }
12232 }
12233
12234 if (in.readInt() != 0) {
12235 if (u.mNetworkByteActivityCounters == null) {
12236 u.initNetworkActivityLocked();
12237 }
12238 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
12239 u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
12240 u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
12241 }
12242 u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
12243 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
12244 }
12245
12246 u.mUserCpuTime.readSummaryFromParcelLocked(in);
12247 u.mSystemCpuTime.readSummaryFromParcelLocked(in);
12248
12249 if (in.readInt() != 0) {
12250 final int numClusters = in.readInt();
12251 if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
12252 throw new ParcelFormatException("Incompatible cpu cluster arrangement");
12253 }
12254
12255 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
12256 for (int cluster = 0; cluster < numClusters; cluster++) {
12257 if (in.readInt() != 0) {
12258 final int NSB = in.readInt();
12259 if (mPowerProfile != null &&
12260 mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
12261 throw new ParcelFormatException("File corrupt: too many speed bins " +
12262 NSB);
12263 }
12264
12265 u.mCpuClusterSpeedTimesUs[cluster] = new LongSamplingCounter[NSB];
12266 for (int speed = 0; speed < NSB; speed++) {
12267 if (in.readInt() != 0) {
12268 u.mCpuClusterSpeedTimesUs[cluster][speed] = new LongSamplingCounter(
12269 mOnBatteryTimeBase);
12270 u.mCpuClusterSpeedTimesUs[cluster][speed].readSummaryFromParcelLocked(in);
12271 }
12272 }
12273 } else {
12274 u.mCpuClusterSpeedTimesUs[cluster] = null;
12275 }
12276 }
12277 } else {
12278 u.mCpuClusterSpeedTimesUs = null;
12279 }
12280
12281 u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
12282 in, mOnBatteryTimeBase);
12283 u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
12284 in, mOnBatteryScreenOffTimeBase);
12285
12286 if (in.readInt() != 0) {
12287 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
12288 u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
12289 } else {
12290 u.mMobileRadioApWakeupCount = null;
12291 }
12292
12293 if (in.readInt() != 0) {
12294 u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
12295 u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
12296 } else {
12297 u.mWifiRadioApWakeupCount = null;
12298 }
12299
12300 int NW = in.readInt();
12301 if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
12302 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
12303 }
12304 for (int iw = 0; iw < NW; iw++) {
12305 String wlName = in.readString();
12306 u.readWakeSummaryFromParcelLocked(wlName, in);
12307 }
12308
12309 int NS = in.readInt();
12310 if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
12311 throw new ParcelFormatException("File corrupt: too many syncs " + NS);
12312 }
12313 for (int is = 0; is < NS; is++) {
12314 String name = in.readString();
12315 u.readSyncSummaryFromParcelLocked(name, in);
12316 }
12317
12318 int NJ = in.readInt();
12319 if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
12320 throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
12321 }
12322 for (int ij = 0; ij < NJ; ij++) {
12323 String name = in.readString();
12324 u.readJobSummaryFromParcelLocked(name, in);
12325 }
12326
12327 u.readJobCompletionsFromParcelLocked(in);
12328
12329 int NP = in.readInt();
12330 if (NP > 1000) {
12331 throw new ParcelFormatException("File corrupt: too many sensors " + NP);
12332 }
12333 for (int is = 0; is < NP; is++) {
12334 int seNumber = in.readInt();
12335 if (in.readInt() != 0) {
12336 u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
12337 }
12338 }
12339
12340 NP = in.readInt();
12341 if (NP > 1000) {
12342 throw new ParcelFormatException("File corrupt: too many processes " + NP);
12343 }
12344 for (int ip = 0; ip < NP; ip++) {
12345 String procName = in.readString();
12346 Uid.Proc p = u.getProcessStatsLocked(procName);
12347 p.mUserTime = p.mLoadedUserTime = in.readLong();
12348 p.mSystemTime = p.mLoadedSystemTime = in.readLong();
12349 p.mForegroundTime = p.mLoadedForegroundTime = in.readLong();
12350 p.mStarts = p.mLoadedStarts = in.readInt();
12351 p.mNumCrashes = p.mLoadedNumCrashes = in.readInt();
12352 p.mNumAnrs = p.mLoadedNumAnrs = in.readInt();
12353 p.readExcessivePowerFromParcelLocked(in);
12354 }
12355
12356 NP = in.readInt();
12357 if (NP > 10000) {
12358 throw new ParcelFormatException("File corrupt: too many packages " + NP);
12359 }
12360 for (int ip = 0; ip < NP; ip++) {
12361 String pkgName = in.readString();
12362 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
12363 final int NWA = in.readInt();
12364 if (NWA > 1000) {
12365 throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
12366 }
12367 p.mWakeupAlarms.clear();
12368 for (int iwa=0; iwa<NWA; iwa++) {
12369 String tag = in.readString();
12370 Counter c = new Counter(mOnBatteryScreenOffTimeBase);
12371 c.readSummaryFromParcelLocked(in);
12372 p.mWakeupAlarms.put(tag, c);
12373 }
12374 NS = in.readInt();
12375 if (NS > 1000) {
12376 throw new ParcelFormatException("File corrupt: too many services " + NS);
12377 }
12378 for (int is = 0; is < NS; is++) {
12379 String servName = in.readString();
12380 Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
12381 s.mStartTime = s.mLoadedStartTime = in.readLong();
12382 s.mStarts = s.mLoadedStarts = in.readInt();
12383 s.mLaunches = s.mLoadedLaunches = in.readInt();
12384 }
12385 }
12386 }
12387 }
12388
12389 /**
12390 * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
12391 * disk. This format does not allow a lossless round-trip.
12392 *
12393 * @param out the Parcel to be written to.
12394 */
12395 public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
12396 pullPendingStateUpdatesLocked();
12397
12398 // Pull the clock time. This may update the time and make a new history entry
12399 // if we had originally pulled a time before the RTC was set.
12400 long startClockTime = getStartClockTime();
12401
12402 final long NOW_SYS = mClocks.uptimeMillis() * 1000;
12403 final long NOWREAL_SYS = mClocks.elapsedRealtime() * 1000;
12404
12405 out.writeInt(VERSION);
12406
12407 writeHistory(out, inclHistory, true);
12408
12409 out.writeInt(mStartCount);
12410 out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
12411 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
12412 out.writeLong(startClockTime);
12413 out.writeString(mStartPlatformVersion);
12414 out.writeString(mEndPlatformVersion);
12415 mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
12416 mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
12417 out.writeInt(mDischargeUnplugLevel);
12418 out.writeInt(mDischargePlugLevel);
12419 out.writeInt(mDischargeCurrentLevel);
12420 out.writeInt(mCurrentBatteryLevel);
12421 out.writeInt(mEstimatedBatteryCapacity);
12422 out.writeInt(mMinLearnedBatteryCapacity);
12423 out.writeInt(mMaxLearnedBatteryCapacity);
12424 out.writeInt(getLowDischargeAmountSinceCharge());
12425 out.writeInt(getHighDischargeAmountSinceCharge());
12426 out.writeInt(getDischargeAmountScreenOnSinceCharge());
12427 out.writeInt(getDischargeAmountScreenOffSinceCharge());
Justin Klaassen93b7ee42017-10-10 15:20:13 -040012428 out.writeInt(getDischargeAmountScreenDozeSinceCharge());
Justin Klaassen10d07c82017-09-15 17:58:39 -040012429 mDischargeStepTracker.writeToParcel(out);
12430 mChargeStepTracker.writeToParcel(out);
12431 mDailyDischargeStepTracker.writeToParcel(out);
12432 mDailyChargeStepTracker.writeToParcel(out);
12433 mDischargeCounter.writeSummaryFromParcelLocked(out);
12434 mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
Justin Klaassen93b7ee42017-10-10 15:20:13 -040012435 mDischargeScreenDozeCounter.writeSummaryFromParcelLocked(out);
Justin Klaassen10d07c82017-09-15 17:58:39 -040012436 if (mDailyPackageChanges != null) {
12437 final int NPKG = mDailyPackageChanges.size();
12438 out.writeInt(NPKG);
12439 for (int i=0; i<NPKG; i++) {
12440 PackageChange pc = mDailyPackageChanges.get(i);
12441 out.writeString(pc.mPackageName);
12442 out.writeInt(pc.mUpdate ? 1 : 0);
12443 out.writeInt(pc.mVersionCode);
12444 }
12445 } else {
12446 out.writeInt(0);
12447 }
12448 out.writeLong(mDailyStartTime);
12449 out.writeLong(mNextMinDailyDeadline);
12450 out.writeLong(mNextMaxDailyDeadline);
12451
12452 mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
Justin Klaassen93b7ee42017-10-10 15:20:13 -040012453 mScreenDozeTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
Justin Klaassen10d07c82017-09-15 17:58:39 -040012454 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
12455 mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12456 }
12457 mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12458 mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12459 out.writeLong(mLongestLightIdleTime);
12460 out.writeLong(mLongestFullIdleTime);
12461 mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12462 mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12463 mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12464 mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12465 mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12466 for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
12467 mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12468 }
12469 mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12470 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
12471 mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12472 }
12473 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
12474 mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
12475 mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
12476 }
12477 mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12478 mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12479 mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
12480 mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
12481 mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
12482 mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12483 mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12484 for (int i=0; i<NUM_WIFI_STATES; i++) {
12485 mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12486 }
12487 for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
12488 mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12489 }
12490 for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
12491 mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12492 }
12493 mWifiActivity.writeSummaryToParcel(out);
12494 mBluetoothActivity.writeSummaryToParcel(out);
12495 mModemActivity.writeSummaryToParcel(out);
12496 out.writeInt(mHasWifiReporting ? 1 : 0);
12497 out.writeInt(mHasBluetoothReporting ? 1 : 0);
12498 out.writeInt(mHasModemReporting ? 1 : 0);
12499
12500 out.writeInt(mNumConnectivityChange);
12501 mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12502 mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12503 mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12504
Justin Klaassenbc81c7a2017-09-18 17:38:50 -040012505 out.writeInt(mRpmStats.size());
12506 for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
12507 Timer rpmt = ent.getValue();
12508 if (rpmt != null) {
12509 out.writeInt(1);
12510 out.writeString(ent.getKey());
12511 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12512 } else {
12513 out.writeInt(0);
12514 }
12515 }
12516 out.writeInt(mScreenOffRpmStats.size());
12517 for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
12518 Timer rpmt = ent.getValue();
12519 if (rpmt != null) {
12520 out.writeInt(1);
12521 out.writeString(ent.getKey());
12522 rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12523 } else {
12524 out.writeInt(0);
12525 }
12526 }
12527
Justin Klaassen10d07c82017-09-15 17:58:39 -040012528 out.writeInt(mKernelWakelockStats.size());
12529 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
12530 Timer kwlt = ent.getValue();
12531 if (kwlt != null) {
12532 out.writeInt(1);
12533 out.writeString(ent.getKey());
12534 kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12535 } else {
12536 out.writeInt(0);
12537 }
12538 }
12539
12540 out.writeInt(mWakeupReasonStats.size());
12541 for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
12542 SamplingTimer timer = ent.getValue();
12543 if (timer != null) {
12544 out.writeInt(1);
12545 out.writeString(ent.getKey());
12546 timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12547 } else {
12548 out.writeInt(0);
12549 }
12550 }
12551
12552 out.writeInt(mKernelMemoryStats.size());
12553 for (int i = 0; i < mKernelMemoryStats.size(); i++) {
12554 Timer kmt = mKernelMemoryStats.valueAt(i);
12555 if (kmt != null) {
12556 out.writeInt(1);
12557 out.writeLong(mKernelMemoryStats.keyAt(i));
12558 kmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12559 } else {
12560 out.writeInt(0);
12561 }
12562 }
12563
12564 final int NU = mUidStats.size();
12565 out.writeInt(NU);
12566 for (int iu = 0; iu < NU; iu++) {
12567 out.writeInt(mUidStats.keyAt(iu));
12568 Uid u = mUidStats.valueAt(iu);
12569
12570 u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
12571 u.mOnBatteryScreenOffBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
12572
12573 if (u.mWifiRunningTimer != null) {
12574 out.writeInt(1);
12575 u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12576 } else {
12577 out.writeInt(0);
12578 }
12579 if (u.mFullWifiLockTimer != null) {
12580 out.writeInt(1);
12581 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12582 } else {
12583 out.writeInt(0);
12584 }
12585 if (u.mWifiScanTimer != null) {
12586 out.writeInt(1);
12587 u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12588 } else {
12589 out.writeInt(0);
12590 }
12591 for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
12592 if (u.mWifiBatchedScanTimer[i] != null) {
12593 out.writeInt(1);
12594 u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12595 } else {
12596 out.writeInt(0);
12597 }
12598 }
12599 if (u.mWifiMulticastTimer != null) {
12600 out.writeInt(1);
12601 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12602 } else {
12603 out.writeInt(0);
12604 }
12605 if (u.mAudioTurnedOnTimer != null) {
12606 out.writeInt(1);
12607 u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12608 } else {
12609 out.writeInt(0);
12610 }
12611 if (u.mVideoTurnedOnTimer != null) {
12612 out.writeInt(1);
12613 u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12614 } else {
12615 out.writeInt(0);
12616 }
12617 if (u.mFlashlightTurnedOnTimer != null) {
12618 out.writeInt(1);
12619 u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12620 } else {
12621 out.writeInt(0);
12622 }
12623 if (u.mCameraTurnedOnTimer != null) {
12624 out.writeInt(1);
12625 u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12626 } else {
12627 out.writeInt(0);
12628 }
12629 if (u.mForegroundActivityTimer != null) {
12630 out.writeInt(1);
12631 u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12632 } else {
12633 out.writeInt(0);
12634 }
12635 if (u.mForegroundServiceTimer != null) {
12636 out.writeInt(1);
12637 u.mForegroundServiceTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12638 } else {
12639 out.writeInt(0);
12640 }
12641 if (u.mAggregatedPartialWakelockTimer != null) {
12642 out.writeInt(1);
12643 u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12644 } else {
12645 out.writeInt(0);
12646 }
12647 if (u.mBluetoothScanTimer != null) {
12648 out.writeInt(1);
12649 u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12650 } else {
12651 out.writeInt(0);
12652 }
12653 if (u.mBluetoothUnoptimizedScanTimer != null) {
12654 out.writeInt(1);
12655 u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12656 } else {
12657 out.writeInt(0);
12658 }
12659 if (u.mBluetoothScanResultCounter != null) {
12660 out.writeInt(1);
12661 u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
12662 } else {
12663 out.writeInt(0);
12664 }
12665 if (u.mBluetoothScanResultBgCounter != null) {
12666 out.writeInt(1);
12667 u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out);
12668 } else {
12669 out.writeInt(0);
12670 }
12671 for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
12672 if (u.mProcessStateTimer[i] != null) {
12673 out.writeInt(1);
12674 u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12675 } else {
12676 out.writeInt(0);
12677 }
12678 }
12679 if (u.mVibratorOnTimer != null) {
12680 out.writeInt(1);
12681 u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12682 } else {
12683 out.writeInt(0);
12684 }
12685
12686 if (u.mUserActivityCounters == null) {
12687 out.writeInt(0);
12688 } else {
12689 out.writeInt(1);
12690 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
12691 u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
12692 }
12693 }
12694
12695 if (u.mNetworkByteActivityCounters == null) {
12696 out.writeInt(0);
12697 } else {
12698 out.writeInt(1);
12699 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
12700 u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
12701 u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
12702 }
12703 u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
12704 u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
12705 }
12706
12707 u.mUserCpuTime.writeSummaryFromParcelLocked(out);
12708 u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
12709
12710 if (u.mCpuClusterSpeedTimesUs != null) {
12711 out.writeInt(1);
12712 out.writeInt(u.mCpuClusterSpeedTimesUs.length);
12713 for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeedTimesUs) {
12714 if (cpuSpeeds != null) {
12715 out.writeInt(1);
12716 out.writeInt(cpuSpeeds.length);
12717 for (LongSamplingCounter c : cpuSpeeds) {
12718 if (c != null) {
12719 out.writeInt(1);
12720 c.writeSummaryFromParcelLocked(out);
12721 } else {
12722 out.writeInt(0);
12723 }
12724 }
12725 } else {
12726 out.writeInt(0);
12727 }
12728 }
12729 } else {
12730 out.writeInt(0);
12731 }
12732
12733 LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
12734 LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
12735
12736 if (u.mMobileRadioApWakeupCount != null) {
12737 out.writeInt(1);
12738 u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
12739 } else {
12740 out.writeInt(0);
12741 }
12742
12743 if (u.mWifiRadioApWakeupCount != null) {
12744 out.writeInt(1);
12745 u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
12746 } else {
12747 out.writeInt(0);
12748 }
12749
12750 final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
12751 int NW = wakeStats.size();
12752 out.writeInt(NW);
12753 for (int iw=0; iw<NW; iw++) {
12754 out.writeString(wakeStats.keyAt(iw));
12755 Uid.Wakelock wl = wakeStats.valueAt(iw);
12756 if (wl.mTimerFull != null) {
12757 out.writeInt(1);
12758 wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12759 } else {
12760 out.writeInt(0);
12761 }
12762 if (wl.mTimerPartial != null) {
12763 out.writeInt(1);
12764 wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12765 } else {
12766 out.writeInt(0);
12767 }
12768 if (wl.mTimerWindow != null) {
12769 out.writeInt(1);
12770 wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12771 } else {
12772 out.writeInt(0);
12773 }
12774 if (wl.mTimerDraw != null) {
12775 out.writeInt(1);
12776 wl.mTimerDraw.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12777 } else {
12778 out.writeInt(0);
12779 }
12780 }
12781
12782 final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
12783 int NS = syncStats.size();
12784 out.writeInt(NS);
12785 for (int is=0; is<NS; is++) {
12786 out.writeString(syncStats.keyAt(is));
12787 syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12788 }
12789
12790 final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
12791 int NJ = jobStats.size();
12792 out.writeInt(NJ);
12793 for (int ij=0; ij<NJ; ij++) {
12794 out.writeString(jobStats.keyAt(ij));
12795 jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12796 }
12797
12798 u.writeJobCompletionsToParcelLocked(out);
12799
12800 int NSE = u.mSensorStats.size();
12801 out.writeInt(NSE);
12802 for (int ise=0; ise<NSE; ise++) {
12803 out.writeInt(u.mSensorStats.keyAt(ise));
12804 Uid.Sensor se = u.mSensorStats.valueAt(ise);
12805 if (se.mTimer != null) {
12806 out.writeInt(1);
12807 se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
12808 } else {
12809 out.writeInt(0);
12810 }
12811 }
12812
12813 int NP = u.mProcessStats.size();
12814 out.writeInt(NP);
12815 for (int ip=0; ip<NP; ip++) {
12816 out.writeString(u.mProcessStats.keyAt(ip));
12817 Uid.Proc ps = u.mProcessStats.valueAt(ip);
12818 out.writeLong(ps.mUserTime);
12819 out.writeLong(ps.mSystemTime);
12820 out.writeLong(ps.mForegroundTime);
12821 out.writeInt(ps.mStarts);
12822 out.writeInt(ps.mNumCrashes);
12823 out.writeInt(ps.mNumAnrs);
12824 ps.writeExcessivePowerToParcelLocked(out);
12825 }
12826
12827 NP = u.mPackageStats.size();
12828 out.writeInt(NP);
12829 if (NP > 0) {
12830 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
12831 : u.mPackageStats.entrySet()) {
12832 out.writeString(ent.getKey());
12833 Uid.Pkg ps = ent.getValue();
12834 final int NWA = ps.mWakeupAlarms.size();
12835 out.writeInt(NWA);
12836 for (int iwa=0; iwa<NWA; iwa++) {
12837 out.writeString(ps.mWakeupAlarms.keyAt(iwa));
12838 ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
12839 }
12840 NS = ps.mServiceStats.size();
12841 out.writeInt(NS);
12842 for (int is=0; is<NS; is++) {
12843 out.writeString(ps.mServiceStats.keyAt(is));
12844 BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
12845 long time = ss.getStartTimeToNowLocked(
12846 mOnBatteryTimeBase.getUptime(NOW_SYS));
12847 out.writeLong(time);
12848 out.writeInt(ss.mStarts);
12849 out.writeInt(ss.mLaunches);
12850 }
12851 }
12852 }
12853 }
12854 }
12855
12856 public void readFromParcel(Parcel in) {
12857 readFromParcelLocked(in);
12858 }
12859
12860 void readFromParcelLocked(Parcel in) {
12861 int magic = in.readInt();
12862 if (magic != MAGIC) {
12863 throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
12864 }
12865
12866 readHistory(in, false);
12867
12868 mStartCount = in.readInt();
12869 mStartClockTime = in.readLong();
12870 mStartPlatformVersion = in.readString();
12871 mEndPlatformVersion = in.readString();
12872 mUptime = in.readLong();
12873 mUptimeStart = in.readLong();
12874 mRealtime = in.readLong();
12875 mRealtimeStart = in.readLong();
12876 mOnBattery = in.readInt() != 0;
12877 mEstimatedBatteryCapacity = in.readInt();
12878 mMinLearnedBatteryCapacity = in.readInt();
12879 mMaxLearnedBatteryCapacity = in.readInt();
12880 mOnBatteryInternal = false; // we are no longer really running.
12881 mOnBatteryTimeBase.readFromParcel(in);
12882 mOnBatteryScreenOffTimeBase.readFromParcel(in);
12883
12884 mScreenState = Display.STATE_UNKNOWN;
12885 mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
Justin Klaassen93b7ee42017-10-10 15:20:13 -040012886 mScreenDozeTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
Justin Klaassen10d07c82017-09-15 17:58:39 -040012887 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
12888 mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
12889 mOnBatteryTimeBase, in);
12890 }
12891 mInteractive = false;
12892 mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase, in);
12893 mPhoneOn = false;
12894 mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
12895 mOnBatteryTimeBase, in);
12896 mLongestLightIdleTime = in.readLong();
12897 mLongestFullIdleTime = in.readLong();
12898 mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null,
12899 mOnBatteryTimeBase, in);
12900 mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null,
12901 mOnBatteryTimeBase, in);
12902 mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null,
12903 mOnBatteryTimeBase, in);
12904 mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase, in);
12905 mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase, in);
12906 for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
12907 mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i,
12908 null, mOnBatteryTimeBase, in);
12909 }
12910 mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
12911 mOnBatteryTimeBase, in);
12912 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
12913 mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i,
12914 null, mOnBatteryTimeBase, in);
12915 }
12916 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
12917 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
12918 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
12919 }
12920 mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
12921 mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
12922 mOnBatteryTimeBase, in);
Justin Klaassen47ed54e2017-10-24 19:50:40 -040012923 mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
Justin Klaassen10d07c82017-09-15 17:58:39 -040012924 mOnBatteryTimeBase, in);
12925 mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
12926 mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
12927 mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
12928 mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
12929 mWifiOn = false;
12930 mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase, in);
12931 mGlobalWifiRunning = false;
12932 mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null,
12933 mOnBatteryTimeBase, in);
12934 for (int i=0; i<NUM_WIFI_STATES; i++) {
12935 mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i,
12936 null, mOnBatteryTimeBase, in);
12937 }
12938 for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
12939 mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i,
12940 null, mOnBatteryTimeBase, in);
12941 }
12942 for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
12943 mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
12944 null, mOnBatteryTimeBase, in);
12945 }
12946
12947 mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
12948 NUM_WIFI_TX_LEVELS, in);
12949 mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
12950 NUM_BT_TX_LEVELS, in);
12951 mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
12952 ModemActivityInfo.TX_POWER_LEVELS, in);
12953 mHasWifiReporting = in.readInt() != 0;
12954 mHasBluetoothReporting = in.readInt() != 0;
12955 mHasModemReporting = in.readInt() != 0;
12956
12957 mNumConnectivityChange = in.readInt();
12958 mLoadedNumConnectivityChange = in.readInt();
12959 mUnpluggedNumConnectivityChange = in.readInt();
12960 mAudioOnNesting = 0;
12961 mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
12962 mVideoOnNesting = 0;
12963 mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
12964 mFlashlightOnNesting = 0;
12965 mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase, in);
12966 mCameraOnNesting = 0;
12967 mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
12968 mBluetoothScanNesting = 0;
12969 mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
12970 mDischargeUnplugLevel = in.readInt();
12971 mDischargePlugLevel = in.readInt();
12972 mDischargeCurrentLevel = in.readInt();
12973 mCurrentBatteryLevel = in.readInt();
12974 mLowDischargeAmountSinceCharge = in.readInt();
12975 mHighDischargeAmountSinceCharge = in.readInt();
12976 mDischargeAmountScreenOn = in.readInt();
12977 mDischargeAmountScreenOnSinceCharge = in.readInt();
12978 mDischargeAmountScreenOff = in.readInt();
12979 mDischargeAmountScreenOffSinceCharge = in.readInt();
Justin Klaassen93b7ee42017-10-10 15:20:13 -040012980 mDischargeAmountScreenDoze = in.readInt();
12981 mDischargeAmountScreenDozeSinceCharge = in.readInt();
Justin Klaassen10d07c82017-09-15 17:58:39 -040012982 mDischargeStepTracker.readFromParcel(in);
12983 mChargeStepTracker.readFromParcel(in);
12984 mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
Justin Klaassen93b7ee42017-10-10 15:20:13 -040012985 mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase, in);
12986 mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
Justin Klaassen10d07c82017-09-15 17:58:39 -040012987 mLastWriteTime = in.readLong();
12988
Justin Klaassenbc81c7a2017-09-18 17:38:50 -040012989 mRpmStats.clear();
12990 int NRPMS = in.readInt();
12991 for (int irpm = 0; irpm < NRPMS; irpm++) {
12992 if (in.readInt() != 0) {
12993 String rpmName = in.readString();
12994 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
12995 mRpmStats.put(rpmName, rpmt);
12996 }
12997 }
12998 mScreenOffRpmStats.clear();
12999 int NSORPMS = in.readInt();
13000 for (int irpm = 0; irpm < NSORPMS; irpm++) {
13001 if (in.readInt() != 0) {
13002 String rpmName = in.readString();
13003 SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
13004 mScreenOffRpmStats.put(rpmName, rpmt);
13005 }
13006 }
13007
Justin Klaassen10d07c82017-09-15 17:58:39 -040013008 mKernelWakelockStats.clear();
13009 int NKW = in.readInt();
13010 for (int ikw = 0; ikw < NKW; ikw++) {
13011 if (in.readInt() != 0) {
13012 String wakelockName = in.readString();
13013 SamplingTimer kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
13014 mKernelWakelockStats.put(wakelockName, kwlt);
13015 }
13016 }
13017
13018 mWakeupReasonStats.clear();
13019 int NWR = in.readInt();
13020 for (int iwr = 0; iwr < NWR; iwr++) {
13021 if (in.readInt() != 0) {
13022 String reasonName = in.readString();
13023 SamplingTimer timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
13024 mWakeupReasonStats.put(reasonName, timer);
13025 }
13026 }
13027
13028 mKernelMemoryStats.clear();
13029 int nmt = in.readInt();
13030 for (int imt = 0; imt < nmt; imt++) {
13031 if (in.readInt() != 0) {
13032 Long bucket = in.readLong();
13033 SamplingTimer kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
13034 mKernelMemoryStats.put(bucket, kmt);
13035 }
13036 }
13037
13038 mPartialTimers.clear();
13039 mFullTimers.clear();
13040 mWindowTimers.clear();
13041 mWifiRunningTimers.clear();
13042 mFullWifiLockTimers.clear();
13043 mWifiScanTimers.clear();
13044 mWifiBatchedScanTimers.clear();
13045 mWifiMulticastTimers.clear();
13046 mAudioTurnedOnTimers.clear();
13047 mVideoTurnedOnTimers.clear();
13048 mFlashlightTurnedOnTimers.clear();
13049 mCameraTurnedOnTimers.clear();
13050
13051 int numUids = in.readInt();
13052 mUidStats.clear();
13053 for (int i = 0; i < numUids; i++) {
13054 int uid = in.readInt();
13055 Uid u = new Uid(this, uid);
13056 u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
13057 mUidStats.append(uid, u);
13058 }
13059 }
13060
13061 public void writeToParcel(Parcel out, int flags) {
13062 writeToParcelLocked(out, true, flags);
13063 }
13064
13065 public void writeToParcelWithoutUids(Parcel out, int flags) {
13066 writeToParcelLocked(out, false, flags);
13067 }
13068
13069 @SuppressWarnings("unused")
13070 void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
13071 // Need to update with current kernel wake lock counts.
13072 pullPendingStateUpdatesLocked();
13073
13074 // Pull the clock time. This may update the time and make a new history entry
13075 // if we had originally pulled a time before the RTC was set.
13076 long startClockTime = getStartClockTime();
13077
13078 final long uSecUptime = mClocks.uptimeMillis() * 1000;
13079 final long uSecRealtime = mClocks.elapsedRealtime() * 1000;
13080 final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
13081 final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
13082
13083 out.writeInt(MAGIC);
13084
13085 writeHistory(out, true, false);
13086
13087 out.writeInt(mStartCount);
13088 out.writeLong(startClockTime);
13089 out.writeString(mStartPlatformVersion);
13090 out.writeString(mEndPlatformVersion);
13091 out.writeLong(mUptime);
13092 out.writeLong(mUptimeStart);
13093 out.writeLong(mRealtime);
13094 out.writeLong(mRealtimeStart);
13095 out.writeInt(mOnBattery ? 1 : 0);
13096 out.writeInt(mEstimatedBatteryCapacity);
13097 out.writeInt(mMinLearnedBatteryCapacity);
13098 out.writeInt(mMaxLearnedBatteryCapacity);
13099 mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
13100 mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
13101
13102 mScreenOnTimer.writeToParcel(out, uSecRealtime);
Justin Klaassen93b7ee42017-10-10 15:20:13 -040013103 mScreenDozeTimer.writeToParcel(out, uSecRealtime);
Justin Klaassen10d07c82017-09-15 17:58:39 -040013104 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
13105 mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
13106 }
13107 mInteractiveTimer.writeToParcel(out, uSecRealtime);
13108 mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
13109 out.writeLong(mLongestLightIdleTime);
13110 out.writeLong(mLongestFullIdleTime);
13111 mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
13112 mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
13113 mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
13114 mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
13115 mPhoneOnTimer.writeToParcel(out, uSecRealtime);
13116 for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
13117 mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
13118 }
13119 mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
13120 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
13121 mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
13122 }
13123 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
13124 mNetworkByteActivityCounters[i].writeToParcel(out);
13125 mNetworkPacketActivityCounters[i].writeToParcel(out);
13126 }
13127 mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
13128 mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
13129 mMobileRadioActiveAdjustedTime.writeToParcel(out);
13130 mMobileRadioActiveUnknownTime.writeToParcel(out);
13131 mMobileRadioActiveUnknownCount.writeToParcel(out);
13132 mWifiOnTimer.writeToParcel(out, uSecRealtime);
13133 mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
13134 for (int i=0; i<NUM_WIFI_STATES; i++) {
13135 mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
13136 }
13137 for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
13138 mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
13139 }
13140 for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
13141 mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
13142 }
13143 mWifiActivity.writeToParcel(out, 0);
13144 mBluetoothActivity.writeToParcel(out, 0);
13145 mModemActivity.writeToParcel(out, 0);
13146 out.writeInt(mHasWifiReporting ? 1 : 0);
13147 out.writeInt(mHasBluetoothReporting ? 1 : 0);
13148 out.writeInt(mHasModemReporting ? 1 : 0);
13149
13150 out.writeInt(mNumConnectivityChange);
13151 out.writeInt(mLoadedNumConnectivityChange);
13152 out.writeInt(mUnpluggedNumConnectivityChange);
13153 mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
13154 mCameraOnTimer.writeToParcel(out, uSecRealtime);
13155 mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
13156 out.writeInt(mDischargeUnplugLevel);
13157 out.writeInt(mDischargePlugLevel);
13158 out.writeInt(mDischargeCurrentLevel);
13159 out.writeInt(mCurrentBatteryLevel);
13160 out.writeInt(mLowDischargeAmountSinceCharge);
13161 out.writeInt(mHighDischargeAmountSinceCharge);
13162 out.writeInt(mDischargeAmountScreenOn);
13163 out.writeInt(mDischargeAmountScreenOnSinceCharge);
13164 out.writeInt(mDischargeAmountScreenOff);
13165 out.writeInt(mDischargeAmountScreenOffSinceCharge);
Justin Klaassen93b7ee42017-10-10 15:20:13 -040013166 out.writeInt(mDischargeAmountScreenDoze);
13167 out.writeInt(mDischargeAmountScreenDozeSinceCharge);
Justin Klaassen10d07c82017-09-15 17:58:39 -040013168 mDischargeStepTracker.writeToParcel(out);
13169 mChargeStepTracker.writeToParcel(out);
13170 mDischargeCounter.writeToParcel(out);
13171 mDischargeScreenOffCounter.writeToParcel(out);
Justin Klaassen93b7ee42017-10-10 15:20:13 -040013172 mDischargeScreenDozeCounter.writeToParcel(out);
Justin Klaassen10d07c82017-09-15 17:58:39 -040013173 out.writeLong(mLastWriteTime);
13174
Justin Klaassenbc81c7a2017-09-18 17:38:50 -040013175 out.writeInt(mRpmStats.size());
13176 for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
13177 SamplingTimer rpmt = ent.getValue();
13178 if (rpmt != null) {
13179 out.writeInt(1);
13180 out.writeString(ent.getKey());
13181 rpmt.writeToParcel(out, uSecRealtime);
13182 } else {
13183 out.writeInt(0);
13184 }
13185 }
13186 out.writeInt(mScreenOffRpmStats.size());
13187 for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
13188 SamplingTimer rpmt = ent.getValue();
13189 if (rpmt != null) {
13190 out.writeInt(1);
13191 out.writeString(ent.getKey());
13192 rpmt.writeToParcel(out, uSecRealtime);
13193 } else {
13194 out.writeInt(0);
13195 }
13196 }
13197
Justin Klaassen10d07c82017-09-15 17:58:39 -040013198 if (inclUids) {
13199 out.writeInt(mKernelWakelockStats.size());
13200 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
13201 SamplingTimer kwlt = ent.getValue();
13202 if (kwlt != null) {
13203 out.writeInt(1);
13204 out.writeString(ent.getKey());
13205 kwlt.writeToParcel(out, uSecRealtime);
13206 } else {
13207 out.writeInt(0);
13208 }
13209 }
13210 out.writeInt(mWakeupReasonStats.size());
13211 for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
13212 SamplingTimer timer = ent.getValue();
13213 if (timer != null) {
13214 out.writeInt(1);
13215 out.writeString(ent.getKey());
13216 timer.writeToParcel(out, uSecRealtime);
13217 } else {
13218 out.writeInt(0);
13219 }
13220 }
13221 } else {
Justin Klaassen47ed54e2017-10-24 19:50:40 -040013222 out.writeInt(0);
Justin Klaassen10d07c82017-09-15 17:58:39 -040013223 out.writeInt(0);
13224 }
13225
13226 out.writeInt(mKernelMemoryStats.size());
13227 for (int i = 0; i < mKernelMemoryStats.size(); i++) {
13228 SamplingTimer kmt = mKernelMemoryStats.valueAt(i);
13229 if (kmt != null) {
13230 out.writeInt(1);
13231 out.writeLong(mKernelMemoryStats.keyAt(i));
13232 kmt.writeToParcel(out, uSecRealtime);
13233 } else {
13234 out.writeInt(0);
13235 }
13236 }
13237
13238 if (inclUids) {
13239 int size = mUidStats.size();
13240 out.writeInt(size);
13241 for (int i = 0; i < size; i++) {
13242 out.writeInt(mUidStats.keyAt(i));
13243 Uid uid = mUidStats.valueAt(i);
13244
13245 uid.writeToParcelLocked(out, uSecUptime, uSecRealtime);
13246 }
13247 } else {
13248 out.writeInt(0);
13249 }
13250 }
13251
13252 public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
13253 new Parcelable.Creator<BatteryStatsImpl>() {
13254 public BatteryStatsImpl createFromParcel(Parcel in) {
13255 return new BatteryStatsImpl(in);
13256 }
13257
13258 public BatteryStatsImpl[] newArray(int size) {
13259 return new BatteryStatsImpl[size];
13260 }
13261 };
13262
13263 public void prepareForDumpLocked() {
13264 // Need to retrieve current kernel wake lock stats before printing.
13265 pullPendingStateUpdatesLocked();
13266
13267 // Pull the clock time. This may update the time and make a new history entry
13268 // if we had originally pulled a time before the RTC was set.
13269 getStartClockTime();
13270 }
13271
13272 public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
13273 if (DEBUG) {
13274 pw.println("mOnBatteryTimeBase:");
13275 mOnBatteryTimeBase.dump(pw, " ");
13276 pw.println("mOnBatteryScreenOffTimeBase:");
13277 mOnBatteryScreenOffTimeBase.dump(pw, " ");
13278 Printer pr = new PrintWriterPrinter(pw);
Justin Klaassen93b7ee42017-10-10 15:20:13 -040013279 pr.println("*** Screen on timer:");
Justin Klaassen10d07c82017-09-15 17:58:39 -040013280 mScreenOnTimer.logState(pr, " ");
Justin Klaassen93b7ee42017-10-10 15:20:13 -040013281 pr.println("*** Screen doze timer:");
13282 mScreenDozeTimer.logState(pr, " ");
Justin Klaassen10d07c82017-09-15 17:58:39 -040013283 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
13284 pr.println("*** Screen brightness #" + i + ":");
13285 mScreenBrightnessTimer[i].logState(pr, " ");
13286 }
13287 pr.println("*** Interactive timer:");
13288 mInteractiveTimer.logState(pr, " ");
13289 pr.println("*** Power save mode timer:");
13290 mPowerSaveModeEnabledTimer.logState(pr, " ");
13291 pr.println("*** Device idle mode light timer:");
13292 mDeviceIdleModeLightTimer.logState(pr, " ");
13293 pr.println("*** Device idle mode full timer:");
13294 mDeviceIdleModeFullTimer.logState(pr, " ");
13295 pr.println("*** Device light idling timer:");
13296 mDeviceLightIdlingTimer.logState(pr, " ");
13297 pr.println("*** Device idling timer:");
13298 mDeviceIdlingTimer.logState(pr, " ");
13299 pr.println("*** Phone timer:");
13300 mPhoneOnTimer.logState(pr, " ");
13301 for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
13302 pr.println("*** Phone signal strength #" + i + ":");
13303 mPhoneSignalStrengthsTimer[i].logState(pr, " ");
13304 }
13305 pr.println("*** Signal scanning :");
13306 mPhoneSignalScanningTimer.logState(pr, " ");
13307 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
13308 pr.println("*** Data connection type #" + i + ":");
13309 mPhoneDataConnectionsTimer[i].logState(pr, " ");
13310 }
13311 pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
13312 pr.println("*** Mobile network active timer:");
13313 mMobileRadioActiveTimer.logState(pr, " ");
13314 pr.println("*** Mobile network active adjusted timer:");
13315 mMobileRadioActiveAdjustedTime.logState(pr, " ");
13316 pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
13317 pr.println("*** Wifi timer:");
13318 mWifiOnTimer.logState(pr, " ");
13319 pr.println("*** WifiRunning timer:");
13320 mGlobalWifiRunningTimer.logState(pr, " ");
13321 for (int i=0; i<NUM_WIFI_STATES; i++) {
13322 pr.println("*** Wifi state #" + i + ":");
13323 mWifiStateTimer[i].logState(pr, " ");
13324 }
13325 for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
13326 pr.println("*** Wifi suppl state #" + i + ":");
13327 mWifiSupplStateTimer[i].logState(pr, " ");
13328 }
13329 for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
13330 pr.println("*** Wifi signal strength #" + i + ":");
13331 mWifiSignalStrengthsTimer[i].logState(pr, " ");
13332 }
13333 pr.println("*** Flashlight timer:");
13334 mFlashlightOnTimer.logState(pr, " ");
13335 pr.println("*** Camera timer:");
13336 mCameraOnTimer.logState(pr, " ");
13337 }
13338 super.dumpLocked(context, pw, flags, reqUid, histStart);
13339 }
13340}