blob: 77649f0bab0ca96e587a00ace68e93b8062606a0 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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.os.BatteryStats;
20import android.os.NetStat;
21import android.os.Parcel;
22import android.os.ParcelFormatException;
23import android.os.Parcelable;
Evan Millarc64edde2009-04-18 12:26:32 -070024import android.os.Process;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.os.SystemClock;
Dianne Hackborn627bba72009-03-24 22:32:56 -070026import android.telephony.TelephonyManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.util.Log;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070028import android.util.PrintWriterPrinter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.util.Printer;
30import android.util.SparseArray;
31
32import java.io.File;
33import java.io.FileInputStream;
34import java.io.FileOutputStream;
35import java.io.IOException;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070036import java.io.PrintWriter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import java.util.ArrayList;
38import java.util.HashMap;
Evan Millarc64edde2009-04-18 12:26:32 -070039import java.util.HashSet;
40import java.util.Iterator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import java.util.Map;
Evan Millarc64edde2009-04-18 12:26:32 -070042import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043
44/**
45 * All information we are collecting about things that can happen that impact
46 * battery life. All times are represented in microseconds except where indicated
47 * otherwise.
48 */
49public final class BatteryStatsImpl extends BatteryStats {
50 private static final String TAG = "BatteryStatsImpl";
51 private static final boolean DEBUG = false;
52
53 // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
54 private static final int MAGIC = 0xBA757475; // 'BATSTATS'
55
56 // Current on-disk Parcel version
Evan Millarc64edde2009-04-18 12:26:32 -070057 private static final int VERSION = 34;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058
59 private final File mFile;
60 private final File mBackupFile;
61
62 /**
63 * The statistics we have collected organized by uids.
64 */
65 final SparseArray<BatteryStatsImpl.Uid> mUidStats =
66 new SparseArray<BatteryStatsImpl.Uid>();
67
68 // A set of pools of currently active timers. When a timer is queried, we will divide the
69 // elapsed time by the number of active timers to arrive at that timer's share of the time.
70 // In order to do this, we must refresh each timer whenever the number of active timers
71 // changes.
Evan Millarc64edde2009-04-18 12:26:32 -070072 final ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<StopwatchTimer>();
73 final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<StopwatchTimer>();
74 final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<StopwatchTimer>();
75 final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers
76 = new SparseArray<ArrayList<StopwatchTimer>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077
78 // These are the objects that will want to do something when the device
79 // is unplugged from power.
80 final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>();
81
82 int mStartCount;
83
84 long mBatteryUptime;
85 long mBatteryLastUptime;
86 long mBatteryRealtime;
87 long mBatteryLastRealtime;
88
89 long mUptime;
90 long mUptimeStart;
91 long mLastUptime;
92 long mRealtime;
93 long mRealtimeStart;
94 long mLastRealtime;
95
96 boolean mScreenOn;
Evan Millarc64edde2009-04-18 12:26:32 -070097 StopwatchTimer mScreenOnTimer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098
Dianne Hackborn617f8772009-03-31 15:04:46 -070099 int mScreenBrightnessBin = -1;
Evan Millarc64edde2009-04-18 12:26:32 -0700100 final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
Dianne Hackborn617f8772009-03-31 15:04:46 -0700101
102 Counter mInputEventCounter;
103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104 boolean mPhoneOn;
Evan Millarc64edde2009-04-18 12:26:32 -0700105 StopwatchTimer mPhoneOnTimer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106
Dianne Hackborn627bba72009-03-24 22:32:56 -0700107 int mPhoneSignalStrengthBin = -1;
Evan Millarc64edde2009-04-18 12:26:32 -0700108 final StopwatchTimer[] mPhoneSignalStrengthsTimer =
109 new StopwatchTimer[NUM_SIGNAL_STRENGTH_BINS];
Dianne Hackborn627bba72009-03-24 22:32:56 -0700110
111 int mPhoneDataConnectionType = -1;
Evan Millarc64edde2009-04-18 12:26:32 -0700112 final StopwatchTimer[] mPhoneDataConnectionsTimer =
113 new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
Dianne Hackborn627bba72009-03-24 22:32:56 -0700114
The Android Open Source Project10592532009-03-18 17:39:46 -0700115 boolean mWifiOn;
Evan Millarc64edde2009-04-18 12:26:32 -0700116 StopwatchTimer mWifiOnTimer;
Dianne Hackborn617f8772009-03-31 15:04:46 -0700117 int mWifiOnUid = -1;
Eric Shienbroodd4c5f892009-03-24 18:13:20 -0700118
119 boolean mWifiRunning;
Evan Millarc64edde2009-04-18 12:26:32 -0700120 StopwatchTimer mWifiRunningTimer;
The Android Open Source Project10592532009-03-18 17:39:46 -0700121
122 boolean mBluetoothOn;
Evan Millarc64edde2009-04-18 12:26:32 -0700123 StopwatchTimer mBluetoothOnTimer;
The Android Open Source Project10592532009-03-18 17:39:46 -0700124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125 /**
126 * These provide time bases that discount the time the device is plugged
127 * in to power.
128 */
129 boolean mOnBattery;
130 boolean mOnBatteryInternal;
131 long mTrackBatteryPastUptime;
132 long mTrackBatteryUptimeStart;
133 long mTrackBatteryPastRealtime;
134 long mTrackBatteryRealtimeStart;
135
136 long mUnpluggedBatteryUptime;
137 long mUnpluggedBatteryRealtime;
138
The Android Open Source Project10592532009-03-18 17:39:46 -0700139 /*
140 * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
141 */
Evan Millar633a1742009-04-02 16:36:33 -0700142 int mDischargeStartLevel;
143 int mDischargeCurrentLevel;
The Android Open Source Project10592532009-03-18 17:39:46 -0700144
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 long mLastWriteTime = 0; // Milliseconds
Evan Millarc64edde2009-04-18 12:26:32 -0700146
147 /*
148 * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
149 */
150 private final HashMap<String, SamplingTimer> mKernelWakelockStats =
151 new HashMap<String, SamplingTimer>();
152
153 public Map<String, ? extends SamplingTimer> getKernelWakelockStats() {
154 return mKernelWakelockStats;
155 }
156
157 private static int sKernelWakelockUpdateVersion = 0;
158
159 private static final int[] PROC_WAKELOCKS_FORMAT = new int[] {
160 Process.PROC_TAB_TERM|Process.PROC_OUT_STRING, // 0: name
161 Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 1: count
162 Process.PROC_TAB_TERM,
163 Process.PROC_TAB_TERM,
164 Process.PROC_TAB_TERM,
165 Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 5: totalTime
166 };
167
168 private final String[] mProcWakelocksName = new String[3];
169 private final long[] mProcWakelocksData = new long[3];
170
171 /*
172 * Used as a buffer for reading in data from /proc/wakelocks before it is processed and added
173 * to mKernelWakelockStats.
174 */
175 private final Map<String, KernelWakelockStats> mProcWakelockFileStats =
176 new HashMap<String, KernelWakelockStats>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177
178 // For debugging
179 public BatteryStatsImpl() {
180 mFile = mBackupFile = null;
181 }
182
183 public static interface Unpluggable {
184 void unplug(long batteryUptime, long batteryRealtime);
185 void plug(long batteryUptime, long batteryRealtime);
186 }
187
188 /**
Dianne Hackborn617f8772009-03-31 15:04:46 -0700189 * State for keeping track of counting information.
190 */
191 public static final class Counter extends BatteryStats.Counter implements Unpluggable {
192 int mCount;
193 int mLoadedCount;
194 int mLastCount;
195 int mUnpluggedCount;
196 int mPluggedCount;
197
198 Counter(ArrayList<Unpluggable> unpluggables, Parcel in) {
199 mPluggedCount = mCount = in.readInt();
200 mLoadedCount = in.readInt();
201 mLastCount = in.readInt();
202 mUnpluggedCount = in.readInt();
203 unpluggables.add(this);
204 }
205
206 Counter(ArrayList<Unpluggable> unpluggables) {
207 unpluggables.add(this);
208 }
209
210 public void writeToParcel(Parcel out) {
211 out.writeInt(mCount);
212 out.writeInt(mLoadedCount);
213 out.writeInt(mLastCount);
214 out.writeInt(mUnpluggedCount);
215 }
216
217 public void unplug(long batteryUptime, long batteryRealtime) {
218 mUnpluggedCount = mCount = mPluggedCount;
219 }
220
221 public void plug(long batteryUptime, long batteryRealtime) {
222 mPluggedCount = mCount;
223 }
224
225 /**
226 * Writes a possibly null Counter to a Parcel.
227 *
228 * @param out the Parcel to be written to.
229 * @param counter a Counter, or null.
230 */
231 public static void writeCounterToParcel(Parcel out, Counter counter) {
232 if (counter == null) {
233 out.writeInt(0); // indicates null
234 return;
235 }
236 out.writeInt(1); // indicates non-null
237
238 counter.writeToParcel(out);
239 }
240
241 @Override
Evan Millarc64edde2009-04-18 12:26:32 -0700242 public int getCountLocked(int which) {
Dianne Hackborn617f8772009-03-31 15:04:46 -0700243 int val;
244 if (which == STATS_LAST) {
245 val = mLastCount;
246 } else {
247 val = mCount;
248 if (which == STATS_UNPLUGGED) {
249 val -= mUnpluggedCount;
250 } else if (which != STATS_TOTAL) {
251 val -= mLoadedCount;
252 }
253 }
254
255 return val;
256 }
257
258 public void logState(Printer pw, String prefix) {
259 pw.println(prefix + "mCount=" + mCount
260 + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
261 + " mUnpluggedCount=" + mUnpluggedCount
262 + " mPluggedCount=" + mPluggedCount);
263 }
264
265 void stepLocked() {
266 mCount++;
267 }
268
269 void writeSummaryFromParcelLocked(Parcel out) {
270 out.writeInt(mCount);
271 out.writeInt(mCount - mLoadedCount);
272 }
273
274 void readSummaryFromParcelLocked(Parcel in) {
275 mCount = mLoadedCount = in.readInt();
276 mLastCount = in.readInt();
277 mUnpluggedCount = mPluggedCount = mCount;
278 }
279 }
280
281 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 * State for keeping track of timing information.
283 */
Evan Millarc64edde2009-04-18 12:26:32 -0700284 public static abstract class Timer extends BatteryStats.Timer implements Unpluggable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285 final int mType;
Evan Millarc64edde2009-04-18 12:26:32 -0700286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287
288 int mCount;
289 int mLoadedCount;
290 int mLastCount;
291 int mUnpluggedCount;
292
293 // Times are in microseconds for better accuracy when dividing by the
294 // lock count, and are in "battery realtime" units.
295
296 /**
297 * The total time we have accumulated since the start of the original
298 * boot, to the last time something interesting happened in the
299 * current run.
300 */
301 long mTotalTime;
302
303 /**
304 * The total time we loaded for the previous runs. Subtract this from
305 * mTotalTime to find the time for the current run of the system.
306 */
307 long mLoadedTime;
308
309 /**
310 * The run time of the last run of the system, as loaded from the
311 * saved data.
312 */
313 long mLastTime;
314
315 /**
316 * The value of mTotalTime when unplug() was last called. Subtract
317 * this from mTotalTime to find the time since the last unplug from
318 * power.
319 */
320 long mUnpluggedTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321
Evan Millarc64edde2009-04-18 12:26:32 -0700322 Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323 mType = type;
Evan Millarc64edde2009-04-18 12:26:32 -0700324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325 mCount = in.readInt();
326 mLoadedCount = in.readInt();
327 mLastCount = in.readInt();
328 mUnpluggedCount = in.readInt();
329 mTotalTime = in.readLong();
330 mLoadedTime = in.readLong();
331 mLastTime = in.readLong();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800332 mUnpluggedTime = in.readLong();
333 unpluggables.add(this);
334 }
335
Evan Millarc64edde2009-04-18 12:26:32 -0700336 Timer(int type, ArrayList<Unpluggable> unpluggables) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 mType = type;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800338 unpluggables.add(this);
339 }
Evan Millarc64edde2009-04-18 12:26:32 -0700340
341 protected abstract long computeRunTimeLocked(long curBatteryRealtime);
342
343 protected abstract int computeCurrentCountLocked();
344
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345
346 public void writeToParcel(Parcel out, long batteryRealtime) {
347 out.writeInt(mCount);
348 out.writeInt(mLoadedCount);
349 out.writeInt(mLastCount);
350 out.writeInt(mUnpluggedCount);
351 out.writeLong(computeRunTimeLocked(batteryRealtime));
352 out.writeLong(mLoadedTime);
353 out.writeLong(mLastTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 out.writeLong(mUnpluggedTime);
355 }
356
357 public void unplug(long batteryUptime, long batteryRealtime) {
358 if (DEBUG && mType < 0) {
359 Log.v(TAG, "unplug #" + mType + ": realtime=" + batteryRealtime
360 + " old mUnpluggedTime=" + mUnpluggedTime
361 + " old mUnpluggedCount=" + mUnpluggedCount);
362 }
363 mUnpluggedTime = computeRunTimeLocked(batteryRealtime);
364 mUnpluggedCount = mCount;
365 if (DEBUG && mType < 0) {
366 Log.v(TAG, "unplug #" + mType
367 + ": new mUnpluggedTime=" + mUnpluggedTime
368 + " new mUnpluggedCount=" + mUnpluggedCount);
369 }
370 }
371
372 public void plug(long batteryUptime, long batteryRealtime) {
Evan Millarc64edde2009-04-18 12:26:32 -0700373 if (DEBUG && mType < 0) {
374 Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime
375 + " old mTotalTime=" + mTotalTime);
376 }
377 mTotalTime = computeRunTimeLocked(batteryRealtime);
378 mCount = computeCurrentCountLocked();
379 if (DEBUG && mType < 0) {
380 Log.v(TAG, "plug #" + mType
381 + ": new mTotalTime=" + mTotalTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382 }
383 }
384
385 /**
386 * Writes a possibly null Timer to a Parcel.
387 *
388 * @param out the Parcel to be written to.
389 * @param timer a Timer, or null.
390 */
391 public static void writeTimerToParcel(Parcel out, Timer timer,
392 long batteryRealtime) {
393 if (timer == null) {
394 out.writeInt(0); // indicates null
395 return;
396 }
397 out.writeInt(1); // indicates non-null
398
399 timer.writeToParcel(out, batteryRealtime);
400 }
401
402 @Override
Evan Millarc64edde2009-04-18 12:26:32 -0700403 public long getTotalTimeLocked(long batteryRealtime, int which) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 long val;
405 if (which == STATS_LAST) {
406 val = mLastTime;
407 } else {
408 val = computeRunTimeLocked(batteryRealtime);
409 if (which == STATS_UNPLUGGED) {
410 val -= mUnpluggedTime;
411 } else if (which != STATS_TOTAL) {
412 val -= mLoadedTime;
413 }
414 }
415
416 return val;
417 }
418
419 @Override
Evan Millarc64edde2009-04-18 12:26:32 -0700420 public int getCountLocked(int which) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 int val;
422 if (which == STATS_LAST) {
423 val = mLastCount;
424 } else {
Evan Millarc64edde2009-04-18 12:26:32 -0700425 val = computeCurrentCountLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 if (which == STATS_UNPLUGGED) {
427 val -= mUnpluggedCount;
428 } else if (which != STATS_TOTAL) {
429 val -= mLoadedCount;
430 }
431 }
432
433 return val;
434 }
435
Dianne Hackborn627bba72009-03-24 22:32:56 -0700436 public void logState(Printer pw, String prefix) {
Evan Millarc64edde2009-04-18 12:26:32 -0700437 pw.println(prefix + " mCount=" + mCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
439 + " mUnpluggedCount=" + mUnpluggedCount);
Dianne Hackborn627bba72009-03-24 22:32:56 -0700440 pw.println(prefix + "mTotalTime=" + mTotalTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 + " mLoadedTime=" + mLoadedTime);
Dianne Hackborn627bba72009-03-24 22:32:56 -0700442 pw.println(prefix + "mLastTime=" + mLastTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 + " mUnpluggedTime=" + mUnpluggedTime);
Evan Millarc64edde2009-04-18 12:26:32 -0700444 }
445
446
447 void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
448 long runTime = computeRunTimeLocked(batteryRealtime);
449 // Divide by 1000 for backwards compatibility
450 out.writeLong((runTime + 500) / 1000);
451 out.writeLong(((runTime - mLoadedTime) + 500) / 1000);
452 out.writeInt(mCount);
453 out.writeInt(mCount - mLoadedCount);
454 }
455
456 void readSummaryFromParcelLocked(Parcel in) {
457 // Multiply by 1000 for backwards compatibility
458 mTotalTime = mLoadedTime = in.readLong() * 1000;
459 mLastTime = in.readLong() * 1000;
460 mUnpluggedTime = mTotalTime;
461 mCount = mLoadedCount = in.readInt();
462 mLastCount = in.readInt();
463 mUnpluggedCount = mCount;
464 }
465 }
466
467 public static final class SamplingTimer extends Timer {
468
469 /**
470 * The most recent reported count from /proc/wakelocks.
471 */
472 int mCurrentReportedCount;
473
474 /**
475 * The reported count from /proc/wakelocks when unplug() was last
476 * called.
477 */
478 int mUnpluggedReportedCount;
479
480 /**
481 * The most recent reported total_time from /proc/wakelocks.
482 */
483 long mCurrentReportedTotalTime;
484
485
486 /**
487 * The reported total_time from /proc/wakelocks when unplug() was last
488 * called.
489 */
490 long mUnpluggedReportedTotalTime;
491
492 /**
493 * Whether we are currently in a discharge cycle.
494 */
495 boolean mInDischarge;
496
497 /**
498 * Whether we are currently recording reported values.
499 */
500 boolean mTrackingReportedValues;
501
502 /*
503 * A sequnce counter, incremented once for each update of the stats.
504 */
505 int mUpdateVersion;
506
507 SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, Parcel in) {
508 super(0, unpluggables, in);
509 mCurrentReportedCount = in.readInt();
510 mUnpluggedReportedCount = in.readInt();
511 mCurrentReportedTotalTime = in.readLong();
512 mUnpluggedReportedTotalTime = in.readLong();
513 mTrackingReportedValues = in.readInt() == 1;
514 mInDischarge = inDischarge;
515 }
516
517 SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge,
518 boolean trackReportedValues) {
519 super(0, unpluggables);
520 mTrackingReportedValues = trackReportedValues;
521 mInDischarge = inDischarge;
522 }
523
524 public void setStale() {
525 mTrackingReportedValues = false;
526 mUnpluggedReportedTotalTime = 0;
527 mUnpluggedReportedCount = 0;
528 }
529
530 public void setUpdateVersion(int version) {
531 mUpdateVersion = version;
532 }
533
534 public int getUpdateVersion() {
535 return mUpdateVersion;
536 }
537
538 public void updateCurrentReportedCount(int count) {
539 if (mInDischarge && mUnpluggedReportedCount == 0) {
540 // Updating the reported value for the first time.
541 mUnpluggedReportedCount = count;
542 // If we are receiving an update update mTrackingReportedValues;
543 mTrackingReportedValues = true;
544 }
545 mCurrentReportedCount = count;
546 }
547
548 public void updateCurrentReportedTotalTime(long totalTime) {
549 if (mInDischarge && mUnpluggedReportedTotalTime == 0) {
550 // Updating the reported value for the first time.
551 mUnpluggedReportedTotalTime = totalTime;
552 // If we are receiving an update update mTrackingReportedValues;
553 mTrackingReportedValues = true;
554 }
555 mCurrentReportedTotalTime = totalTime;
556 }
557
558 public void unplug(long batteryUptime, long batteryRealtime) {
559 super.unplug(batteryUptime, batteryRealtime);
560 if (mTrackingReportedValues) {
561 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
562 mUnpluggedReportedCount = mCurrentReportedCount;
563 }
564 mInDischarge = true;
565 }
566
567 public void plug(long batteryUptime, long batteryRealtime) {
568 super.plug(batteryUptime, batteryRealtime);
569 mInDischarge = false;
570 }
571
572 public void logState(Printer pw, String prefix) {
573 super.logState(pw, prefix);
574 pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
575 + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
576 + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
577 + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
578 }
579
580 protected long computeRunTimeLocked(long curBatteryRealtime) {
581 return mTotalTime + (mInDischarge && mTrackingReportedValues
582 ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
583 }
584
585 protected int computeCurrentCountLocked() {
586 return mCount + (mInDischarge && mTrackingReportedValues
587 ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
588 }
589
590 public void writeToParcel(Parcel out, long batteryRealtime) {
591 super.writeToParcel(out, batteryRealtime);
592 out.writeInt(mCurrentReportedCount);
593 out.writeInt(mUnpluggedReportedCount);
594 out.writeLong(mCurrentReportedTotalTime);
595 out.writeLong(mUnpluggedReportedTotalTime);
596 out.writeInt(mTrackingReportedValues ? 1 : 0);
597 }
598
599 void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
600 super.writeSummaryFromParcelLocked(out, batteryRealtime);
601 out.writeLong(mCurrentReportedTotalTime);
602 out.writeInt(mCurrentReportedCount);
603 out.writeInt(mTrackingReportedValues ? 1 : 0);
604 }
605
606 void readSummaryFromParcelLocked(Parcel in) {
607 super.readSummaryFromParcelLocked(in);
608 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong();
609 mUnpluggedReportedCount = mCurrentReportedCount = in.readInt();
610 mTrackingReportedValues = in.readInt() == 1;
611 }
612 }
613
614 /**
615 * State for keeping track of timing information.
616 */
617 public static final class StopwatchTimer extends Timer {
618 final ArrayList<StopwatchTimer> mTimerPool;
619 int mNesting;
620
621
622 /**
623 * The last time at which we updated the timer. If mNesting is > 0,
624 * subtract this from the current battery time to find the amount of
625 * time we have been running since we last computed an update.
626 */
627 long mUpdateTime;
628
629 /**
630 * The total time at which the timer was acquired, to determine if
631 * was actually held for an interesting duration.
632 */
633 long mAcquireTime;
634
635
636 StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
637 ArrayList<Unpluggable> unpluggables, Parcel in) {
638 super(type, unpluggables, in);
639 mTimerPool = timerPool;
640 mUpdateTime = in.readLong();
641 }
642
643 StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
644 ArrayList<Unpluggable> unpluggables) {
645 super(type, unpluggables);
646 mTimerPool = timerPool;
647 }
648
649 public void writeToParcel(Parcel out, long batteryRealtime) {
650 super.writeToParcel(out, batteryRealtime);
651 out.writeLong(mUpdateTime);
652 }
653
654 public void plug(long batteryUptime, long batteryRealtime) {
655 if (mNesting > 0) {
656 if (DEBUG && mType < 0) {
657 Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
658 }
659 super.plug(batteryUptime, batteryRealtime);
660 mUpdateTime = batteryRealtime;
661 if (DEBUG && mType < 0) {
662 Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
663 }
664 }
665 }
666
667 public void logState(Printer pw, String prefix) {
668 super.logState(pw, prefix);
669 pw.println(prefix + "mNesting=" + mNesting + "mUpdateTime=" + mUpdateTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670 + " mAcquireTime=" + mAcquireTime);
671 }
672
673 void startRunningLocked(BatteryStatsImpl stats) {
674 if (mNesting++ == 0) {
675 mUpdateTime = stats.getBatteryRealtimeLocked(
676 SystemClock.elapsedRealtime() * 1000);
677 if (mTimerPool != null) {
678 // Accumulate time to all currently active timers before adding
679 // this new one to the pool.
680 refreshTimersLocked(stats, mTimerPool);
681 // Add this timer to the active pool
682 mTimerPool.add(this);
683 }
684 // Increment the count
685 mCount++;
686 mAcquireTime = mTotalTime;
687 if (DEBUG && mType < 0) {
688 Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
689 + " mTotalTime=" + mTotalTime + " mCount=" + mCount
690 + " mAcquireTime=" + mAcquireTime);
691 }
692 }
693 }
694
695 void stopRunningLocked(BatteryStatsImpl stats) {
696 // Ignore attempt to stop a timer that isn't running
697 if (mNesting == 0) {
698 return;
699 }
700 if (--mNesting == 0) {
701 if (mTimerPool != null) {
702 // Accumulate time to all active counters, scaled by the total
703 // active in the pool, before taking this one out of the pool.
704 refreshTimersLocked(stats, mTimerPool);
705 // Remove this timer from the active pool
706 mTimerPool.remove(this);
707 } else {
708 final long realtime = SystemClock.elapsedRealtime() * 1000;
709 final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
710 mNesting = 1;
711 mTotalTime = computeRunTimeLocked(batteryRealtime);
712 mNesting = 0;
713 }
714
715 if (DEBUG && mType < 0) {
716 Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
717 + " mTotalTime=" + mTotalTime + " mCount=" + mCount
718 + " mAcquireTime=" + mAcquireTime);
719 }
720
721 if (mTotalTime == mAcquireTime) {
722 // If there was no change in the time, then discard this
723 // count. A somewhat cheezy strategy, but hey.
724 mCount--;
725 }
726 }
727 }
728
729 // Update the total time for all other running Timers with the same type as this Timer
730 // due to a change in timer count
731 private static void refreshTimersLocked(final BatteryStatsImpl stats,
Evan Millarc64edde2009-04-18 12:26:32 -0700732 final ArrayList<StopwatchTimer> pool) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 final long realtime = SystemClock.elapsedRealtime() * 1000;
734 final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
735 final int N = pool.size();
736 for (int i=N-1; i>= 0; i--) {
Evan Millarc64edde2009-04-18 12:26:32 -0700737 final StopwatchTimer t = pool.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 long heldTime = batteryRealtime - t.mUpdateTime;
739 if (heldTime > 0) {
740 t.mTotalTime += heldTime / N;
741 }
742 t.mUpdateTime = batteryRealtime;
743 }
744 }
745
Evan Millarc64edde2009-04-18 12:26:32 -0700746 @Override
747 protected long computeRunTimeLocked(long curBatteryRealtime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 return mTotalTime + (mNesting > 0
749 ? (curBatteryRealtime - mUpdateTime)
750 / (mTimerPool != null ? mTimerPool.size() : 1)
751 : 0);
752 }
753
Evan Millarc64edde2009-04-18 12:26:32 -0700754 @Override
755 protected int computeCurrentCountLocked() {
756 return mCount;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800757 }
758
759 void readSummaryFromParcelLocked(Parcel in) {
Evan Millarc64edde2009-04-18 12:26:32 -0700760 super.readSummaryFromParcelLocked(in);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 mNesting = 0;
762 }
763 }
764
Evan Millarc64edde2009-04-18 12:26:32 -0700765 private final Map<String, KernelWakelockStats> readKernelWakelockStats() {
766
767 byte[] buffer = new byte[4096];
768 int len;
769
770 try {
771 FileInputStream is = new FileInputStream("/proc/wakelocks");
772 len = is.read(buffer);
773 is.close();
774
775 if (len > 0) {
776 int i;
777 for (i=0; i<len; i++) {
778 if (buffer[i] == '\0') {
779 len = i;
780 break;
781 }
782 }
783 }
784 } catch (java.io.FileNotFoundException e) {
785 return null;
786 } catch (java.io.IOException e) {
787 return null;
788 }
789
790 return parseProcWakelocks(buffer, len);
791 }
792
793 private final Map<String, KernelWakelockStats> parseProcWakelocks(
794 byte[] wlBuffer, int len) {
795 String name;
796 int count;
797 long totalTime;
798 int startIndex, endIndex;
799 int numUpdatedWlNames = 0;
800
801 // Advance past the first line.
802 int i;
803 for (i = 0; i < len && wlBuffer[i] != '\n' && wlBuffer[i] != '\0'; i++);
804 startIndex = endIndex = i + 1;
805
806 synchronized(this) {
807 Map<String, KernelWakelockStats> m = mProcWakelockFileStats;
808
809 sKernelWakelockUpdateVersion++;
810 while (endIndex < len) {
811 for (endIndex=startIndex;
812 endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0';
813 endIndex++);
814 endIndex++; // endIndex is an exclusive upper bound.
815
816 String[] nameStringArray = mProcWakelocksName;
817 long[] wlData = mProcWakelocksData;
818 Process.parseProcLine(wlBuffer, startIndex, endIndex, PROC_WAKELOCKS_FORMAT,
819 nameStringArray, wlData, null);
820
821 name = nameStringArray[0];
822 count = (int) wlData[1];
823 // convert nanoseconds to microseconds with rounding.
824 totalTime = (wlData[2] + 500) / 1000;
825
826 if (name.length() > 0) {
827 if (!m.containsKey(name)) {
828 m.put(name, new KernelWakelockStats(count, totalTime,
829 sKernelWakelockUpdateVersion));
830 numUpdatedWlNames++;
831 } else {
832 KernelWakelockStats kwlStats = m.get(name);
833 if (kwlStats.mVersion == sKernelWakelockUpdateVersion) {
834 kwlStats.mCount += count;
835 kwlStats.mTotalTime += totalTime;
836 } else {
837 kwlStats.mCount = count;
838 kwlStats.mTotalTime = totalTime;
839 kwlStats.mVersion = sKernelWakelockUpdateVersion;
840 numUpdatedWlNames++;
841 }
842 }
843 }
844 startIndex = endIndex;
845 }
846
847 if (m.size() != numUpdatedWlNames) {
848 // Don't report old data.
849 Iterator<KernelWakelockStats> itr = m.values().iterator();
850 while (itr.hasNext()) {
851 if (itr.next().mVersion != sKernelWakelockUpdateVersion) {
852 itr.remove();
853 }
854 }
855 }
856 return m;
857 }
858 }
859
860 private class KernelWakelockStats {
861 public int mCount;
862 public long mTotalTime;
863 public int mVersion;
864
865 KernelWakelockStats(int count, long totalTime, int version) {
866 mCount = count;
867 mTotalTime = totalTime;
868 mVersion = version;
869 }
870 }
871
872 /*
873 * Get the KernelWakelockTimer associated with name, and create a new one if one
874 * doesn't already exist.
875 */
876 public SamplingTimer getKernelWakelockTimerLocked(String name) {
877 SamplingTimer kwlt = mKernelWakelockStats.get(name);
878 if (kwlt == null) {
879 kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal,
880 true /* track reported values */);
881 mKernelWakelockStats.put(name, kwlt);
882 }
883 return kwlt;
884 }
885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 public void doUnplug(long batteryUptime, long batteryRealtime) {
887 for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
888 Uid u = mUidStats.valueAt(iu);
889 u.mStartedTcpBytesReceived = NetStat.getUidRxBytes(u.mUid);
890 u.mStartedTcpBytesSent = NetStat.getUidTxBytes(u.mUid);
891 u.mTcpBytesReceivedAtLastUnplug = u.mCurrentTcpBytesReceived;
892 u.mTcpBytesSentAtLastUnplug = u.mCurrentTcpBytesSent;
893 }
894 for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
895 mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime);
896 }
897 }
898
899 public void doPlug(long batteryUptime, long batteryRealtime) {
900 for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
901 Uid u = mUidStats.valueAt(iu);
902 if (u.mStartedTcpBytesReceived >= 0) {
903 u.mCurrentTcpBytesReceived = u.computeCurrentTcpBytesReceived();
904 u.mStartedTcpBytesReceived = -1;
905 }
906 if (u.mStartedTcpBytesSent >= 0) {
907 u.mCurrentTcpBytesSent = u.computeCurrentTcpBytesSent();
908 u.mStartedTcpBytesSent = -1;
909 }
910 }
911 for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
912 mUnpluggables.get(i).plug(batteryUptime, batteryRealtime);
913 }
914 }
915
916 public void noteStartGps(int uid) {
917 mUidStats.get(uid).noteStartGps();
918 }
919
920 public void noteStopGps(int uid) {
921 mUidStats.get(uid).noteStopGps();
922 }
923
924 public void noteScreenOnLocked() {
925 if (!mScreenOn) {
926 mScreenOn = true;
927 mScreenOnTimer.startRunningLocked(this);
Dianne Hackborn617f8772009-03-31 15:04:46 -0700928 if (mScreenBrightnessBin >= 0) {
929 mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(this);
930 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800931 }
932 }
933
934 public void noteScreenOffLocked() {
935 if (mScreenOn) {
936 mScreenOn = false;
937 mScreenOnTimer.stopRunningLocked(this);
Dianne Hackborn617f8772009-03-31 15:04:46 -0700938 if (mScreenBrightnessBin >= 0) {
939 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this);
940 }
941 }
942 }
943
944 public void noteScreenBrightnessLocked(int brightness) {
945 // Bin the brightness.
946 int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
947 if (bin < 0) bin = 0;
948 else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
949 if (mScreenBrightnessBin != bin) {
950 if (mScreenOn) {
951 if (mScreenBrightnessBin >= 0) {
952 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this);
953 }
954 mScreenBrightnessTimer[bin].startRunningLocked(this);
955 }
956 mScreenBrightnessBin = bin;
957 }
958 }
959
960 public void noteInputEventLocked() {
961 mInputEventCounter.stepLocked();
962 }
963
964 public void noteUserActivityLocked(int uid, int event) {
965 Uid u = mUidStats.get(uid);
966 if (u != null) {
967 u.noteUserActivityLocked(event);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 }
969 }
970
971 public void notePhoneOnLocked() {
972 if (!mPhoneOn) {
973 mPhoneOn = true;
974 mPhoneOnTimer.startRunningLocked(this);
975 }
976 }
977
978 public void notePhoneOffLocked() {
979 if (mPhoneOn) {
980 mPhoneOn = false;
981 mPhoneOnTimer.stopRunningLocked(this);
982 }
983 }
984
Dianne Hackborn627bba72009-03-24 22:32:56 -0700985 public void notePhoneSignalStrengthLocked(int asu) {
986 // Bin the strength.
987 int bin;
988 if (asu < 0 || asu >= 99) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
989 else if (asu >= 16) bin = SIGNAL_STRENGTH_GREAT;
990 else if (asu >= 8) bin = SIGNAL_STRENGTH_GOOD;
991 else if (asu >= 4) bin = SIGNAL_STRENGTH_MODERATE;
992 else bin = SIGNAL_STRENGTH_POOR;
993 if (mPhoneSignalStrengthBin != bin) {
994 if (mPhoneSignalStrengthBin >= 0) {
995 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(this);
996 }
997 mPhoneSignalStrengthBin = bin;
998 mPhoneSignalStrengthsTimer[bin].startRunningLocked(this);
999 }
1000 }
1001
1002 public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
1003 int bin = DATA_CONNECTION_NONE;
1004 if (hasData) {
1005 switch (dataType) {
1006 case TelephonyManager.NETWORK_TYPE_EDGE:
1007 bin = DATA_CONNECTION_EDGE;
1008 break;
1009 case TelephonyManager.NETWORK_TYPE_GPRS:
1010 bin = DATA_CONNECTION_GPRS;
1011 break;
1012 case TelephonyManager.NETWORK_TYPE_UMTS:
1013 bin = DATA_CONNECTION_UMTS;
1014 break;
1015 default:
1016 bin = DATA_CONNECTION_OTHER;
1017 break;
1018 }
1019 }
1020 if (mPhoneDataConnectionType != bin) {
1021 if (mPhoneDataConnectionType >= 0) {
1022 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this);
1023 }
1024 mPhoneDataConnectionType = bin;
1025 mPhoneDataConnectionsTimer[bin].startRunningLocked(this);
1026 }
1027 }
1028
Dianne Hackborn617f8772009-03-31 15:04:46 -07001029 public void noteWifiOnLocked(int uid) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001030 if (!mWifiOn) {
1031 mWifiOn = true;
1032 mWifiOnTimer.startRunningLocked(this);
1033 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07001034 if (mWifiOnUid != uid) {
1035 if (mWifiOnUid >= 0) {
1036 Uid u = mUidStats.get(mWifiOnUid);
1037 if (u != null) {
1038 u.noteWifiTurnedOffLocked();
1039 }
1040 }
1041 mWifiOnUid = uid;
1042 Uid u = mUidStats.get(uid);
1043 if (u != null) {
1044 u.noteWifiTurnedOnLocked();
1045 }
1046 }
The Android Open Source Project10592532009-03-18 17:39:46 -07001047 }
1048
Dianne Hackborn617f8772009-03-31 15:04:46 -07001049 public void noteWifiOffLocked(int uid) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001050 if (mWifiOn) {
1051 mWifiOn = false;
1052 mWifiOnTimer.stopRunningLocked(this);
1053 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07001054 if (mWifiOnUid >= 0) {
1055 Uid u = mUidStats.get(mWifiOnUid);
1056 if (u != null) {
1057 u.noteWifiTurnedOffLocked();
1058 }
1059 mWifiOnUid = -1;
1060 }
The Android Open Source Project10592532009-03-18 17:39:46 -07001061 }
1062
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07001063 public void noteWifiRunningLocked() {
1064 if (!mWifiRunning) {
1065 mWifiRunning = true;
1066 mWifiRunningTimer.startRunningLocked(this);
1067 }
1068 }
1069
1070 public void noteWifiStoppedLocked() {
1071 if (mWifiRunning) {
1072 mWifiRunning = false;
1073 mWifiRunningTimer.stopRunningLocked(this);
1074 }
1075 }
1076
The Android Open Source Project10592532009-03-18 17:39:46 -07001077 public void noteBluetoothOnLocked() {
1078 if (!mBluetoothOn) {
1079 mBluetoothOn = true;
1080 mBluetoothOnTimer.startRunningLocked(this);
1081 }
1082 }
1083
1084 public void noteBluetoothOffLocked() {
1085 if (mBluetoothOn) {
1086 mBluetoothOn = false;
1087 mBluetoothOnTimer.stopRunningLocked(this);
1088 }
1089 }
1090
1091 public void noteFullWifiLockAcquiredLocked(int uid) {
1092 Uid u = mUidStats.get(uid);
1093 if (u != null) {
1094 u.noteFullWifiLockAcquiredLocked();
1095 }
1096 }
1097
1098 public void noteFullWifiLockReleasedLocked(int uid) {
1099 Uid u = mUidStats.get(uid);
1100 if (u != null) {
1101 u.noteFullWifiLockReleasedLocked();
1102 }
1103 }
1104
1105 public void noteScanWifiLockAcquiredLocked(int uid) {
1106 Uid u = mUidStats.get(uid);
1107 if (u != null) {
1108 u.noteScanWifiLockAcquiredLocked();
1109 }
1110 }
1111
1112 public void noteScanWifiLockReleasedLocked(int uid) {
1113 Uid u = mUidStats.get(uid);
1114 if (u != null) {
1115 u.noteScanWifiLockReleasedLocked();
1116 }
1117 }
1118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 @Override public long getScreenOnTime(long batteryRealtime, int which) {
Evan Millarc64edde2009-04-18 12:26:32 -07001120 return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 }
1122
Dianne Hackborn617f8772009-03-31 15:04:46 -07001123 @Override public long getScreenBrightnessTime(int brightnessBin,
1124 long batteryRealtime, int which) {
Evan Millarc64edde2009-04-18 12:26:32 -07001125 return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
Dianne Hackborn617f8772009-03-31 15:04:46 -07001126 batteryRealtime, which);
1127 }
1128
1129 @Override public int getInputEventCount(int which) {
Evan Millarc64edde2009-04-18 12:26:32 -07001130 return mInputEventCounter.getCountLocked(which);
Dianne Hackborn617f8772009-03-31 15:04:46 -07001131 }
1132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001133 @Override public long getPhoneOnTime(long batteryRealtime, int which) {
Evan Millarc64edde2009-04-18 12:26:32 -07001134 return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135 }
1136
Dianne Hackborn627bba72009-03-24 22:32:56 -07001137 @Override public long getPhoneSignalStrengthTime(int strengthBin,
1138 long batteryRealtime, int which) {
Evan Millarc64edde2009-04-18 12:26:32 -07001139 return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
Dianne Hackborn627bba72009-03-24 22:32:56 -07001140 batteryRealtime, which);
1141 }
1142
Dianne Hackborn617f8772009-03-31 15:04:46 -07001143 @Override public int getPhoneSignalStrengthCount(int dataType, int which) {
Evan Millarc64edde2009-04-18 12:26:32 -07001144 return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
Dianne Hackborn617f8772009-03-31 15:04:46 -07001145 }
1146
Dianne Hackborn627bba72009-03-24 22:32:56 -07001147 @Override public long getPhoneDataConnectionTime(int dataType,
1148 long batteryRealtime, int which) {
Evan Millarc64edde2009-04-18 12:26:32 -07001149 return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
Dianne Hackborn627bba72009-03-24 22:32:56 -07001150 batteryRealtime, which);
1151 }
1152
Dianne Hackborn617f8772009-03-31 15:04:46 -07001153 @Override public int getPhoneDataConnectionCount(int dataType, int which) {
Evan Millarc64edde2009-04-18 12:26:32 -07001154 return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
Dianne Hackborn617f8772009-03-31 15:04:46 -07001155 }
1156
The Android Open Source Project10592532009-03-18 17:39:46 -07001157 @Override public long getWifiOnTime(long batteryRealtime, int which) {
Evan Millarc64edde2009-04-18 12:26:32 -07001158 return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which);
The Android Open Source Project10592532009-03-18 17:39:46 -07001159 }
1160
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07001161 @Override public long getWifiRunningTime(long batteryRealtime, int which) {
Evan Millarc64edde2009-04-18 12:26:32 -07001162 return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which);
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07001163 }
1164
The Android Open Source Project10592532009-03-18 17:39:46 -07001165 @Override public long getBluetoothOnTime(long batteryRealtime, int which) {
Evan Millarc64edde2009-04-18 12:26:32 -07001166 return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which);
The Android Open Source Project10592532009-03-18 17:39:46 -07001167 }
1168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001169 @Override public boolean getIsOnBattery() {
1170 return mOnBattery;
1171 }
1172
1173 @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
1174 return mUidStats;
1175 }
1176
1177 /**
1178 * The statistics associated with a particular uid.
1179 */
1180 public final class Uid extends BatteryStats.Uid {
1181
1182 final int mUid;
1183 long mLoadedTcpBytesReceived;
1184 long mLoadedTcpBytesSent;
1185 long mCurrentTcpBytesReceived;
1186 long mCurrentTcpBytesSent;
1187 long mTcpBytesReceivedAtLastUnplug;
1188 long mTcpBytesSentAtLastUnplug;
1189
1190 // These are not saved/restored when parcelling, since we want
1191 // to return from the parcel with a snapshot of the state.
1192 long mStartedTcpBytesReceived = -1;
1193 long mStartedTcpBytesSent = -1;
1194
Dianne Hackborn617f8772009-03-31 15:04:46 -07001195 boolean mWifiTurnedOn;
Evan Millarc64edde2009-04-18 12:26:32 -07001196 StopwatchTimer mWifiTurnedOnTimer;
Dianne Hackborn617f8772009-03-31 15:04:46 -07001197
The Android Open Source Project10592532009-03-18 17:39:46 -07001198 boolean mFullWifiLockOut;
Evan Millarc64edde2009-04-18 12:26:32 -07001199 StopwatchTimer mFullWifiLockTimer;
The Android Open Source Project10592532009-03-18 17:39:46 -07001200
1201 boolean mScanWifiLockOut;
Evan Millarc64edde2009-04-18 12:26:32 -07001202 StopwatchTimer mScanWifiLockTimer;
The Android Open Source Project10592532009-03-18 17:39:46 -07001203
Dianne Hackborn617f8772009-03-31 15:04:46 -07001204 Counter[] mUserActivityCounters;
1205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001206 /**
1207 * The statistics we have collected for this uid's wake locks.
1208 */
1209 final HashMap<String, Wakelock> mWakelockStats = new HashMap<String, Wakelock>();
1210
1211 /**
1212 * The statistics we have collected for this uid's sensor activations.
1213 */
1214 final HashMap<Integer, Sensor> mSensorStats = new HashMap<Integer, Sensor>();
1215
1216 /**
1217 * The statistics we have collected for this uid's processes.
1218 */
1219 final HashMap<String, Proc> mProcessStats = new HashMap<String, Proc>();
1220
1221 /**
1222 * The statistics we have collected for this uid's processes.
1223 */
1224 final HashMap<String, Pkg> mPackageStats = new HashMap<String, Pkg>();
1225
1226 public Uid(int uid) {
1227 mUid = uid;
Evan Millarc64edde2009-04-18 12:26:32 -07001228 mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables);
1229 mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables);
1230 mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 }
1232
1233 @Override
1234 public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
1235 return mWakelockStats;
1236 }
1237
1238 @Override
1239 public Map<Integer, ? extends BatteryStats.Uid.Sensor> getSensorStats() {
1240 return mSensorStats;
1241 }
1242
1243 @Override
1244 public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
1245 return mProcessStats;
1246 }
1247
1248 @Override
1249 public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
1250 return mPackageStats;
1251 }
1252
1253 public int getUid() {
1254 return mUid;
1255 }
1256
1257 public long getTcpBytesReceived(int which) {
1258 if (which == STATS_LAST) {
1259 return mLoadedTcpBytesReceived;
1260 } else {
1261 long current = computeCurrentTcpBytesReceived();
1262 if (which == STATS_UNPLUGGED) {
1263 current -= mTcpBytesReceivedAtLastUnplug;
1264 } else if (which == STATS_TOTAL) {
1265 current += mLoadedTcpBytesReceived;
1266 }
1267 return current;
1268 }
1269 }
1270
1271 public long computeCurrentTcpBytesReceived() {
1272 return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0
1273 ? (NetStat.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0);
1274 }
1275
1276 public long getTcpBytesSent(int which) {
1277 if (which == STATS_LAST) {
1278 return mLoadedTcpBytesSent;
1279 } else {
1280 long current = computeCurrentTcpBytesSent();
1281 if (which == STATS_UNPLUGGED) {
1282 current -= mTcpBytesSentAtLastUnplug;
1283 } else if (which == STATS_TOTAL) {
1284 current += mLoadedTcpBytesSent;
1285 }
1286 return current;
1287 }
1288 }
1289
The Android Open Source Project10592532009-03-18 17:39:46 -07001290 @Override
Dianne Hackborn617f8772009-03-31 15:04:46 -07001291 public void noteWifiTurnedOnLocked() {
1292 if (!mWifiTurnedOn) {
1293 mWifiTurnedOn = true;
1294 mWifiTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
1295 }
1296 }
1297
1298 @Override
1299 public void noteWifiTurnedOffLocked() {
1300 if (mWifiTurnedOn) {
1301 mWifiTurnedOn = false;
1302 mWifiTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
1303 }
1304 }
1305
1306 @Override
The Android Open Source Project10592532009-03-18 17:39:46 -07001307 public void noteFullWifiLockAcquiredLocked() {
1308 if (!mFullWifiLockOut) {
1309 mFullWifiLockOut = true;
1310 mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
1311 }
1312 }
1313
1314 @Override
1315 public void noteFullWifiLockReleasedLocked() {
1316 if (mFullWifiLockOut) {
1317 mFullWifiLockOut = false;
1318 mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
1319 }
1320 }
1321
1322 @Override
1323 public void noteScanWifiLockAcquiredLocked() {
1324 if (!mScanWifiLockOut) {
1325 mScanWifiLockOut = true;
1326 mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
1327 }
1328 }
1329
1330 @Override
1331 public void noteScanWifiLockReleasedLocked() {
1332 if (mScanWifiLockOut) {
1333 mScanWifiLockOut = false;
1334 mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
1335 }
1336 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07001337
1338 @Override
1339 public long getWifiTurnedOnTime(long batteryRealtime, int which) {
Evan Millarc64edde2009-04-18 12:26:32 -07001340 return mWifiTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
Dianne Hackborn617f8772009-03-31 15:04:46 -07001341 }
1342
The Android Open Source Project10592532009-03-18 17:39:46 -07001343 @Override
1344 public long getFullWifiLockTime(long batteryRealtime, int which) {
Evan Millarc64edde2009-04-18 12:26:32 -07001345 return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
The Android Open Source Project10592532009-03-18 17:39:46 -07001346 }
1347
1348 @Override
1349 public long getScanWifiLockTime(long batteryRealtime, int which) {
Evan Millarc64edde2009-04-18 12:26:32 -07001350 return mScanWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
The Android Open Source Project10592532009-03-18 17:39:46 -07001351 }
1352
Dianne Hackborn617f8772009-03-31 15:04:46 -07001353 @Override
1354 public void noteUserActivityLocked(int type) {
1355 if (mUserActivityCounters == null) {
1356 initUserActivityLocked();
1357 }
1358 if (type < 0) type = 0;
1359 else if (type >= NUM_USER_ACTIVITY_TYPES) type = NUM_USER_ACTIVITY_TYPES-1;
1360 mUserActivityCounters[type].stepLocked();
1361 }
1362
1363 @Override
1364 public boolean hasUserActivity() {
1365 return mUserActivityCounters != null;
1366 }
1367
1368 @Override
1369 public int getUserActivityCount(int type, int which) {
1370 if (mUserActivityCounters == null) {
1371 return 0;
1372 }
Evan Millarc64edde2009-04-18 12:26:32 -07001373 return mUserActivityCounters[type].getCountLocked(which);
Dianne Hackborn617f8772009-03-31 15:04:46 -07001374 }
1375
1376 void initUserActivityLocked() {
1377 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
1378 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
1379 mUserActivityCounters[i] = new Counter(mUnpluggables);
1380 }
1381 }
1382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 public long computeCurrentTcpBytesSent() {
1384 return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0
1385 ? (NetStat.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0);
1386 }
1387
1388 void writeToParcelLocked(Parcel out, long batteryRealtime) {
1389 out.writeInt(mWakelockStats.size());
1390 for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) {
1391 out.writeString(wakelockEntry.getKey());
1392 Uid.Wakelock wakelock = wakelockEntry.getValue();
1393 wakelock.writeToParcelLocked(out, batteryRealtime);
1394 }
1395
1396 out.writeInt(mSensorStats.size());
1397 for (Map.Entry<Integer, Uid.Sensor> sensorEntry : mSensorStats.entrySet()) {
1398 out.writeInt(sensorEntry.getKey());
1399 Uid.Sensor sensor = sensorEntry.getValue();
1400 sensor.writeToParcelLocked(out, batteryRealtime);
1401 }
1402
1403 out.writeInt(mProcessStats.size());
1404 for (Map.Entry<String, Uid.Proc> procEntry : mProcessStats.entrySet()) {
1405 out.writeString(procEntry.getKey());
1406 Uid.Proc proc = procEntry.getValue();
1407 proc.writeToParcelLocked(out);
1408 }
1409
1410 out.writeInt(mPackageStats.size());
1411 for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
1412 out.writeString(pkgEntry.getKey());
1413 Uid.Pkg pkg = pkgEntry.getValue();
1414 pkg.writeToParcelLocked(out);
1415 }
1416
1417 out.writeLong(mLoadedTcpBytesReceived);
1418 out.writeLong(mLoadedTcpBytesSent);
1419 out.writeLong(computeCurrentTcpBytesReceived());
1420 out.writeLong(computeCurrentTcpBytesSent());
1421 out.writeLong(mTcpBytesReceivedAtLastUnplug);
1422 out.writeLong(mTcpBytesSentAtLastUnplug);
Dianne Hackborn617f8772009-03-31 15:04:46 -07001423 mWifiTurnedOnTimer.writeToParcel(out, batteryRealtime);
The Android Open Source Project10592532009-03-18 17:39:46 -07001424 mFullWifiLockTimer.writeToParcel(out, batteryRealtime);
1425 mScanWifiLockTimer.writeToParcel(out, batteryRealtime);
Dianne Hackborn617f8772009-03-31 15:04:46 -07001426 if (mUserActivityCounters == null) {
1427 out.writeInt(0);
1428 } else {
1429 out.writeInt(1);
1430 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
1431 mUserActivityCounters[i].writeToParcel(out);
1432 }
1433 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 }
1435
1436 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
1437 int numWakelocks = in.readInt();
1438 mWakelockStats.clear();
1439 for (int j = 0; j < numWakelocks; j++) {
1440 String wakelockName = in.readString();
1441 Uid.Wakelock wakelock = new Wakelock();
1442 wakelock.readFromParcelLocked(unpluggables, in);
1443 mWakelockStats.put(wakelockName, wakelock);
1444 }
1445
1446 int numSensors = in.readInt();
1447 mSensorStats.clear();
1448 for (int k = 0; k < numSensors; k++) {
1449 int sensorNumber = in.readInt();
1450 Uid.Sensor sensor = new Sensor(sensorNumber);
1451 sensor.readFromParcelLocked(mUnpluggables, in);
1452 mSensorStats.put(sensorNumber, sensor);
1453 }
1454
1455 int numProcs = in.readInt();
1456 mProcessStats.clear();
1457 for (int k = 0; k < numProcs; k++) {
1458 String processName = in.readString();
1459 Uid.Proc proc = new Proc();
1460 proc.readFromParcelLocked(in);
1461 mProcessStats.put(processName, proc);
1462 }
1463
1464 int numPkgs = in.readInt();
1465 mPackageStats.clear();
1466 for (int l = 0; l < numPkgs; l++) {
1467 String packageName = in.readString();
1468 Uid.Pkg pkg = new Pkg();
1469 pkg.readFromParcelLocked(in);
1470 mPackageStats.put(packageName, pkg);
1471 }
1472
1473 mLoadedTcpBytesReceived = in.readLong();
1474 mLoadedTcpBytesSent = in.readLong();
1475 mCurrentTcpBytesReceived = in.readLong();
1476 mCurrentTcpBytesSent = in.readLong();
1477 mTcpBytesReceivedAtLastUnplug = in.readLong();
1478 mTcpBytesSentAtLastUnplug = in.readLong();
Dianne Hackborn617f8772009-03-31 15:04:46 -07001479 mWifiTurnedOn = false;
Evan Millarc64edde2009-04-18 12:26:32 -07001480 mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables, in);
The Android Open Source Project10592532009-03-18 17:39:46 -07001481 mFullWifiLockOut = false;
Evan Millarc64edde2009-04-18 12:26:32 -07001482 mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables, in);
The Android Open Source Project10592532009-03-18 17:39:46 -07001483 mScanWifiLockOut = false;
Evan Millarc64edde2009-04-18 12:26:32 -07001484 mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables, in);
Dianne Hackborn617f8772009-03-31 15:04:46 -07001485 if (in.readInt() == 0) {
1486 mUserActivityCounters = null;
1487 } else {
1488 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
1489 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
1490 mUserActivityCounters[i] = new Counter(mUnpluggables, in);
1491 }
1492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 }
1494
1495 /**
1496 * The statistics associated with a particular wake lock.
1497 */
1498 public final class Wakelock extends BatteryStats.Uid.Wakelock {
1499 /**
1500 * How long (in ms) this uid has been keeping the device partially awake.
1501 */
Evan Millarc64edde2009-04-18 12:26:32 -07001502 StopwatchTimer mTimerPartial;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503
1504 /**
1505 * How long (in ms) this uid has been keeping the device fully awake.
1506 */
Evan Millarc64edde2009-04-18 12:26:32 -07001507 StopwatchTimer mTimerFull;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508
1509 /**
1510 * How long (in ms) this uid has had a window keeping the device awake.
1511 */
Evan Millarc64edde2009-04-18 12:26:32 -07001512 StopwatchTimer mTimerWindow;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513
1514 /**
1515 * Reads a possibly null Timer from a Parcel. The timer is associated with the
1516 * proper timer pool from the given BatteryStatsImpl object.
1517 *
1518 * @param in the Parcel to be read from.
1519 * return a new Timer, or null.
1520 */
Evan Millarc64edde2009-04-18 12:26:32 -07001521 private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522 ArrayList<Unpluggable> unpluggables, Parcel in) {
1523 if (in.readInt() == 0) {
1524 return null;
1525 }
1526
Evan Millarc64edde2009-04-18 12:26:32 -07001527 return new StopwatchTimer(type, pool, unpluggables, in);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 }
1529
1530 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
1531 mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL,
1532 mPartialTimers, unpluggables, in);
1533 mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL,
1534 mFullTimers, unpluggables, in);
1535 mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW,
1536 mWindowTimers, unpluggables, in);
1537 }
1538
1539 void writeToParcelLocked(Parcel out, long batteryRealtime) {
1540 Timer.writeTimerToParcel(out, mTimerPartial, batteryRealtime);
1541 Timer.writeTimerToParcel(out, mTimerFull, batteryRealtime);
1542 Timer.writeTimerToParcel(out, mTimerWindow, batteryRealtime);
1543 }
1544
1545 @Override
1546 public Timer getWakeTime(int type) {
1547 switch (type) {
1548 case WAKE_TYPE_FULL: return mTimerFull;
1549 case WAKE_TYPE_PARTIAL: return mTimerPartial;
1550 case WAKE_TYPE_WINDOW: return mTimerWindow;
1551 default: throw new IllegalArgumentException("type = " + type);
1552 }
1553 }
1554 }
1555
1556 public final class Sensor extends BatteryStats.Uid.Sensor {
1557 final int mHandle;
Evan Millarc64edde2009-04-18 12:26:32 -07001558 StopwatchTimer mTimer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559
1560 public Sensor(int handle) {
1561 mHandle = handle;
1562 }
1563
Evan Millarc64edde2009-04-18 12:26:32 -07001564 private StopwatchTimer readTimerFromParcel(ArrayList<Unpluggable> unpluggables,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565 Parcel in) {
1566 if (in.readInt() == 0) {
1567 return null;
1568 }
1569
Evan Millarc64edde2009-04-18 12:26:32 -07001570 ArrayList<StopwatchTimer> pool = mSensorTimers.get(mHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571 if (pool == null) {
Evan Millarc64edde2009-04-18 12:26:32 -07001572 pool = new ArrayList<StopwatchTimer>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 mSensorTimers.put(mHandle, pool);
1574 }
Evan Millarc64edde2009-04-18 12:26:32 -07001575 return new StopwatchTimer(0, pool, unpluggables, in);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576 }
1577
1578 void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
1579 mTimer = readTimerFromParcel(unpluggables, in);
1580 }
1581
1582 void writeToParcelLocked(Parcel out, long batteryRealtime) {
1583 Timer.writeTimerToParcel(out, mTimer, batteryRealtime);
1584 }
1585
1586 @Override
1587 public Timer getSensorTime() {
1588 return mTimer;
1589 }
1590
1591 public int getHandle() {
1592 return mHandle;
1593 }
1594 }
1595
1596 /**
1597 * The statistics associated with a particular process.
1598 */
1599 public final class Proc extends BatteryStats.Uid.Proc implements Unpluggable {
1600 /**
1601 * Total time (in 1/100 sec) spent executing in user code.
1602 */
1603 long mUserTime;
1604
1605 /**
1606 * Total time (in 1/100 sec) spent executing in kernel code.
1607 */
1608 long mSystemTime;
1609
1610 /**
1611 * Number of times the process has been started.
1612 */
1613 int mStarts;
1614
1615 /**
1616 * The amount of user time loaded from a previous save.
1617 */
1618 long mLoadedUserTime;
1619
1620 /**
1621 * The amount of system time loaded from a previous save.
1622 */
1623 long mLoadedSystemTime;
1624
1625 /**
1626 * The number of times the process has started from a previous save.
1627 */
1628 int mLoadedStarts;
1629
1630 /**
1631 * The amount of user time loaded from the previous run.
1632 */
1633 long mLastUserTime;
1634
1635 /**
1636 * The amount of system time loaded from the previous run.
1637 */
1638 long mLastSystemTime;
1639
1640 /**
1641 * The number of times the process has started from the previous run.
1642 */
1643 int mLastStarts;
1644
1645 /**
1646 * The amount of user time when last unplugged.
1647 */
1648 long mUnpluggedUserTime;
1649
1650 /**
1651 * The amount of system time when last unplugged.
1652 */
1653 long mUnpluggedSystemTime;
1654
1655 /**
1656 * The number of times the process has started before unplugged.
1657 */
1658 int mUnpluggedStarts;
1659
1660 Proc() {
1661 mUnpluggables.add(this);
1662 }
1663
1664 public void unplug(long batteryUptime, long batteryRealtime) {
1665 mUnpluggedUserTime = mUserTime;
1666 mUnpluggedSystemTime = mSystemTime;
1667 mUnpluggedStarts = mStarts;
1668 }
1669
1670 public void plug(long batteryUptime, long batteryRealtime) {
1671 }
1672
1673 void writeToParcelLocked(Parcel out) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001674 final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
1675 final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime);
1676
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001677 out.writeLong(mUserTime);
1678 out.writeLong(mSystemTime);
1679 out.writeInt(mStarts);
1680 out.writeLong(mLoadedUserTime);
1681 out.writeLong(mLoadedSystemTime);
1682 out.writeInt(mLoadedStarts);
1683 out.writeLong(mLastUserTime);
1684 out.writeLong(mLastSystemTime);
1685 out.writeInt(mLastStarts);
1686 out.writeLong(mUnpluggedUserTime);
1687 out.writeLong(mUnpluggedSystemTime);
1688 out.writeInt(mUnpluggedStarts);
1689 }
1690
1691 void readFromParcelLocked(Parcel in) {
1692 mUserTime = in.readLong();
1693 mSystemTime = in.readLong();
1694 mStarts = in.readInt();
1695 mLoadedUserTime = in.readLong();
1696 mLoadedSystemTime = in.readLong();
1697 mLoadedStarts = in.readInt();
1698 mLastUserTime = in.readLong();
1699 mLastSystemTime = in.readLong();
1700 mLastStarts = in.readInt();
1701 mUnpluggedUserTime = in.readLong();
1702 mUnpluggedSystemTime = in.readLong();
1703 mUnpluggedStarts = in.readInt();
1704 }
1705
1706 public BatteryStatsImpl getBatteryStats() {
1707 return BatteryStatsImpl.this;
1708 }
1709
1710 public void addCpuTimeLocked(int utime, int stime) {
1711 mUserTime += utime;
1712 mSystemTime += stime;
1713 }
1714
1715 public void incStartsLocked() {
1716 mStarts++;
1717 }
1718
1719 @Override
1720 public long getUserTime(int which) {
1721 long val;
1722 if (which == STATS_LAST) {
1723 val = mLastUserTime;
1724 } else {
1725 val = mUserTime;
1726 if (which == STATS_CURRENT) {
1727 val -= mLoadedUserTime;
1728 } else if (which == STATS_UNPLUGGED) {
1729 val -= mUnpluggedUserTime;
1730 }
1731 }
1732 return val;
1733 }
1734
1735 @Override
1736 public long getSystemTime(int which) {
1737 long val;
1738 if (which == STATS_LAST) {
1739 val = mLastSystemTime;
1740 } else {
1741 val = mSystemTime;
1742 if (which == STATS_CURRENT) {
1743 val -= mLoadedSystemTime;
1744 } else if (which == STATS_UNPLUGGED) {
1745 val -= mUnpluggedSystemTime;
1746 }
1747 }
1748 return val;
1749 }
1750
1751 @Override
1752 public int getStarts(int which) {
1753 int val;
1754 if (which == STATS_LAST) {
1755 val = mLastStarts;
1756 } else {
1757 val = mStarts;
1758 if (which == STATS_CURRENT) {
1759 val -= mLoadedStarts;
1760 } else if (which == STATS_UNPLUGGED) {
1761 val -= mUnpluggedStarts;
1762 }
1763 }
1764 return val;
1765 }
1766 }
1767
1768 /**
1769 * The statistics associated with a particular package.
1770 */
1771 public final class Pkg extends BatteryStats.Uid.Pkg implements Unpluggable {
1772 /**
1773 * Number of times this package has done something that could wake up the
1774 * device from sleep.
1775 */
1776 int mWakeups;
1777
1778 /**
1779 * Number of things that could wake up the device loaded from a
1780 * previous save.
1781 */
1782 int mLoadedWakeups;
1783
1784 /**
1785 * Number of things that could wake up the device as of the
1786 * last run.
1787 */
1788 int mLastWakeups;
1789
1790 /**
1791 * Number of things that could wake up the device as of the
1792 * last run.
1793 */
1794 int mUnpluggedWakeups;
1795
1796 /**
1797 * The statics we have collected for this package's services.
1798 */
1799 final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>();
1800
1801 Pkg() {
1802 mUnpluggables.add(this);
1803 }
1804
1805 public void unplug(long batteryUptime, long batteryRealtime) {
1806 mUnpluggedWakeups = mWakeups;
1807 }
1808
1809 public void plug(long batteryUptime, long batteryRealtime) {
1810 }
1811
1812 void readFromParcelLocked(Parcel in) {
1813 mWakeups = in.readInt();
1814 mLoadedWakeups = in.readInt();
1815 mLastWakeups = in.readInt();
1816 mUnpluggedWakeups = in.readInt();
1817
1818 int numServs = in.readInt();
1819 mServiceStats.clear();
1820 for (int m = 0; m < numServs; m++) {
1821 String serviceName = in.readString();
1822 Uid.Pkg.Serv serv = new Serv();
1823 mServiceStats.put(serviceName, serv);
1824
1825 serv.readFromParcelLocked(in);
1826 }
1827 }
1828
1829 void writeToParcelLocked(Parcel out) {
1830 out.writeInt(mWakeups);
1831 out.writeInt(mLoadedWakeups);
1832 out.writeInt(mLastWakeups);
1833 out.writeInt(mUnpluggedWakeups);
1834
1835 out.writeInt(mServiceStats.size());
1836 for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) {
1837 out.writeString(servEntry.getKey());
1838 Uid.Pkg.Serv serv = servEntry.getValue();
1839
1840 serv.writeToParcelLocked(out);
1841 }
1842 }
1843
1844 @Override
1845 public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
1846 return mServiceStats;
1847 }
1848
1849 @Override
1850 public int getWakeups(int which) {
1851 int val;
1852 if (which == STATS_LAST) {
1853 val = mLastWakeups;
1854 } else {
1855 val = mWakeups;
1856 if (which == STATS_CURRENT) {
1857 val -= mLoadedWakeups;
1858 } else if (which == STATS_UNPLUGGED) {
1859 val -= mUnpluggedWakeups;
1860 }
1861 }
1862
1863 return val;
1864 }
1865
1866 /**
1867 * The statistics associated with a particular service.
1868 */
1869 public final class Serv extends BatteryStats.Uid.Pkg.Serv implements Unpluggable {
1870 /**
1871 * Total time (ms in battery uptime) the service has been left started.
1872 */
1873 long mStartTime;
1874
1875 /**
1876 * If service has been started and not yet stopped, this is
1877 * when it was started.
1878 */
1879 long mRunningSince;
1880
1881 /**
1882 * True if we are currently running.
1883 */
1884 boolean mRunning;
1885
1886 /**
1887 * Total number of times startService() has been called.
1888 */
1889 int mStarts;
1890
1891 /**
1892 * Total time (ms in battery uptime) the service has been left launched.
1893 */
1894 long mLaunchedTime;
1895
1896 /**
1897 * If service has been launched and not yet exited, this is
1898 * when it was launched (ms in battery uptime).
1899 */
1900 long mLaunchedSince;
1901
1902 /**
1903 * True if we are currently launched.
1904 */
1905 boolean mLaunched;
1906
1907 /**
1908 * Total number times the service has been launched.
1909 */
1910 int mLaunches;
1911
1912 /**
1913 * The amount of time spent started loaded from a previous save
1914 * (ms in battery uptime).
1915 */
1916 long mLoadedStartTime;
1917
1918 /**
1919 * The number of starts loaded from a previous save.
1920 */
1921 int mLoadedStarts;
1922
1923 /**
1924 * The number of launches loaded from a previous save.
1925 */
1926 int mLoadedLaunches;
1927
1928 /**
1929 * The amount of time spent started as of the last run (ms
1930 * in battery uptime).
1931 */
1932 long mLastStartTime;
1933
1934 /**
1935 * The number of starts as of the last run.
1936 */
1937 int mLastStarts;
1938
1939 /**
1940 * The number of launches as of the last run.
1941 */
1942 int mLastLaunches;
1943
1944 /**
1945 * The amount of time spent started when last unplugged (ms
1946 * in battery uptime).
1947 */
1948 long mUnpluggedStartTime;
1949
1950 /**
1951 * The number of starts when last unplugged.
1952 */
1953 int mUnpluggedStarts;
1954
1955 /**
1956 * The number of launches when last unplugged.
1957 */
1958 int mUnpluggedLaunches;
1959
1960 Serv() {
1961 mUnpluggables.add(this);
1962 }
1963
1964 public void unplug(long batteryUptime, long batteryRealtime) {
1965 mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime);
1966 mUnpluggedStarts = mStarts;
1967 mUnpluggedLaunches = mLaunches;
1968 }
1969
1970 public void plug(long batteryUptime, long batteryRealtime) {
1971 }
1972
1973 void readFromParcelLocked(Parcel in) {
1974 mStartTime = in.readLong();
1975 mRunningSince = in.readLong();
1976 mRunning = in.readInt() != 0;
1977 mStarts = in.readInt();
1978 mLaunchedTime = in.readLong();
1979 mLaunchedSince = in.readLong();
1980 mLaunched = in.readInt() != 0;
1981 mLaunches = in.readInt();
1982 mLoadedStartTime = in.readLong();
1983 mLoadedStarts = in.readInt();
1984 mLoadedLaunches = in.readInt();
1985 mLastStartTime = in.readLong();
1986 mLastStarts = in.readInt();
1987 mLastLaunches = in.readInt();
1988 mUnpluggedStartTime = in.readLong();
1989 mUnpluggedStarts = in.readInt();
1990 mUnpluggedLaunches = in.readInt();
1991 }
1992
1993 void writeToParcelLocked(Parcel out) {
1994 out.writeLong(mStartTime);
1995 out.writeLong(mRunningSince);
1996 out.writeInt(mRunning ? 1 : 0);
1997 out.writeInt(mStarts);
1998 out.writeLong(mLaunchedTime);
1999 out.writeLong(mLaunchedSince);
2000 out.writeInt(mLaunched ? 1 : 0);
2001 out.writeInt(mLaunches);
2002 out.writeLong(mLoadedStartTime);
2003 out.writeInt(mLoadedStarts);
2004 out.writeInt(mLoadedLaunches);
2005 out.writeLong(mLastStartTime);
2006 out.writeInt(mLastStarts);
2007 out.writeInt(mLastLaunches);
2008 out.writeLong(mUnpluggedStartTime);
2009 out.writeInt(mUnpluggedStarts);
2010 out.writeInt(mUnpluggedLaunches);
2011 }
2012
2013 long getLaunchTimeToNowLocked(long batteryUptime) {
2014 if (!mLaunched) return mLaunchedTime;
2015 return mLaunchedTime + batteryUptime - mLaunchedSince;
2016 }
2017
2018 long getStartTimeToNowLocked(long batteryUptime) {
2019 if (!mRunning) return mStartTime;
2020 return mStartTime + batteryUptime - mRunningSince;
2021 }
2022
2023 public void startLaunchedLocked() {
2024 if (!mLaunched) {
2025 mLaunches++;
2026 mLaunchedSince = getBatteryUptimeLocked();
2027 mLaunched = true;
2028 }
2029 }
2030
2031 public void stopLaunchedLocked() {
2032 if (mLaunched) {
2033 long time = getBatteryUptimeLocked() - mLaunchedSince;
2034 if (time > 0) {
2035 mLaunchedTime += time;
2036 } else {
2037 mLaunches--;
2038 }
2039 mLaunched = false;
2040 }
2041 }
2042
2043 public void startRunningLocked() {
2044 if (!mRunning) {
2045 mStarts++;
2046 mRunningSince = getBatteryUptimeLocked();
2047 mRunning = true;
2048 }
2049 }
2050
2051 public void stopRunningLocked() {
2052 if (mRunning) {
2053 long time = getBatteryUptimeLocked() - mRunningSince;
2054 if (time > 0) {
2055 mStartTime += time;
2056 } else {
2057 mStarts--;
2058 }
2059 mRunning = false;
2060 }
2061 }
2062
2063 public BatteryStatsImpl getBatteryStats() {
2064 return BatteryStatsImpl.this;
2065 }
2066
2067 @Override
2068 public int getLaunches(int which) {
2069 int val;
2070
2071 if (which == STATS_LAST) {
2072 val = mLastLaunches;
2073 } else {
2074 val = mLaunches;
2075 if (which == STATS_CURRENT) {
2076 val -= mLoadedLaunches;
2077 } else if (which == STATS_UNPLUGGED) {
2078 val -= mUnpluggedLaunches;
2079 }
2080 }
2081
2082 return val;
2083 }
2084
2085 @Override
2086 public long getStartTime(long now, int which) {
2087 long val;
2088 if (which == STATS_LAST) {
2089 val = mLastStartTime;
2090 } else {
2091 val = getStartTimeToNowLocked(now);
2092 if (which == STATS_CURRENT) {
2093 val -= mLoadedStartTime;
2094 } else if (which == STATS_UNPLUGGED) {
2095 val -= mUnpluggedStartTime;
2096 }
2097 }
2098
2099 return val;
2100 }
2101
2102 @Override
2103 public int getStarts(int which) {
2104 int val;
2105 if (which == STATS_LAST) {
2106 val = mLastStarts;
2107 } else {
2108 val = mStarts;
2109 if (which == STATS_CURRENT) {
2110 val -= mLoadedStarts;
2111 } else if (which == STATS_UNPLUGGED) {
2112 val -= mUnpluggedStarts;
2113 }
2114 }
2115
2116 return val;
2117 }
2118 }
2119
2120 public BatteryStatsImpl getBatteryStats() {
2121 return BatteryStatsImpl.this;
2122 }
2123
2124 public void incWakeupsLocked() {
2125 mWakeups++;
2126 }
2127
2128 final Serv newServiceStatsLocked() {
2129 return new Serv();
2130 }
2131 }
2132
2133 /**
2134 * Retrieve the statistics object for a particular process, creating
2135 * if needed.
2136 */
2137 public Proc getProcessStatsLocked(String name) {
2138 Proc ps = mProcessStats.get(name);
2139 if (ps == null) {
2140 ps = new Proc();
2141 mProcessStats.put(name, ps);
2142 }
2143
2144 return ps;
2145 }
2146
2147 /**
2148 * Retrieve the statistics object for a particular service, creating
2149 * if needed.
2150 */
2151 public Pkg getPackageStatsLocked(String name) {
2152 Pkg ps = mPackageStats.get(name);
2153 if (ps == null) {
2154 ps = new Pkg();
2155 mPackageStats.put(name, ps);
2156 }
2157
2158 return ps;
2159 }
2160
2161 /**
2162 * Retrieve the statistics object for a particular service, creating
2163 * if needed.
2164 */
2165 public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
2166 Pkg ps = getPackageStatsLocked(pkg);
2167 Pkg.Serv ss = ps.mServiceStats.get(serv);
2168 if (ss == null) {
2169 ss = ps.newServiceStatsLocked();
2170 ps.mServiceStats.put(serv, ss);
2171 }
2172
2173 return ss;
2174 }
2175
Evan Millarc64edde2009-04-18 12:26:32 -07002176 public StopwatchTimer getWakeTimerLocked(String name, int type) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002177 Wakelock wl = mWakelockStats.get(name);
2178 if (wl == null) {
2179 wl = new Wakelock();
2180 mWakelockStats.put(name, wl);
2181 }
Evan Millarc64edde2009-04-18 12:26:32 -07002182 StopwatchTimer t = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183 switch (type) {
2184 case WAKE_TYPE_PARTIAL:
2185 t = wl.mTimerPartial;
2186 if (t == null) {
Evan Millarc64edde2009-04-18 12:26:32 -07002187 t = new StopwatchTimer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 wl.mTimerPartial = t;
2189 }
2190 return t;
2191 case WAKE_TYPE_FULL:
2192 t = wl.mTimerFull;
2193 if (t == null) {
Evan Millarc64edde2009-04-18 12:26:32 -07002194 t = new StopwatchTimer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002195 wl.mTimerFull = t;
2196 }
2197 return t;
2198 case WAKE_TYPE_WINDOW:
2199 t = wl.mTimerWindow;
2200 if (t == null) {
Evan Millarc64edde2009-04-18 12:26:32 -07002201 t = new StopwatchTimer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002202 wl.mTimerWindow = t;
2203 }
2204 return t;
2205 default:
2206 throw new IllegalArgumentException("type=" + type);
2207 }
2208 }
2209
Evan Millarc64edde2009-04-18 12:26:32 -07002210 public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002211 Sensor se = mSensorStats.get(sensor);
2212 if (se == null) {
2213 if (!create) {
2214 return null;
2215 }
2216 se = new Sensor(sensor);
2217 mSensorStats.put(sensor, se);
2218 }
Evan Millarc64edde2009-04-18 12:26:32 -07002219 StopwatchTimer t = se.mTimer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002220 if (t != null) {
2221 return t;
2222 }
Evan Millarc64edde2009-04-18 12:26:32 -07002223 ArrayList<StopwatchTimer> timers = mSensorTimers.get(sensor);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002224 if (timers == null) {
Evan Millarc64edde2009-04-18 12:26:32 -07002225 timers = new ArrayList<StopwatchTimer>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002226 mSensorTimers.put(sensor, timers);
2227 }
Evan Millarc64edde2009-04-18 12:26:32 -07002228 t = new StopwatchTimer(BatteryStats.SENSOR, timers, mUnpluggables);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002229 se.mTimer = t;
2230 return t;
2231 }
2232
2233 public void noteStartWakeLocked(String name, int type) {
Evan Millarc64edde2009-04-18 12:26:32 -07002234 StopwatchTimer t = getWakeTimerLocked(name, type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002235 if (t != null) {
2236 t.startRunningLocked(BatteryStatsImpl.this);
2237 }
2238 }
2239
2240 public void noteStopWakeLocked(String name, int type) {
Evan Millarc64edde2009-04-18 12:26:32 -07002241 StopwatchTimer t = getWakeTimerLocked(name, type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002242 if (t != null) {
2243 t.stopRunningLocked(BatteryStatsImpl.this);
2244 }
2245 }
2246
2247 public void noteStartSensor(int sensor) {
Evan Millarc64edde2009-04-18 12:26:32 -07002248 StopwatchTimer t = getSensorTimerLocked(sensor, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002249 if (t != null) {
2250 t.startRunningLocked(BatteryStatsImpl.this);
2251 }
2252 }
2253
2254 public void noteStopSensor(int sensor) {
2255 // Don't create a timer if one doesn't already exist
Evan Millarc64edde2009-04-18 12:26:32 -07002256 StopwatchTimer t = getSensorTimerLocked(sensor, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 if (t != null) {
2258 t.stopRunningLocked(BatteryStatsImpl.this);
2259 }
2260 }
2261
2262 public void noteStartGps() {
Evan Millarc64edde2009-04-18 12:26:32 -07002263 StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002264 if (t != null) {
2265 t.startRunningLocked(BatteryStatsImpl.this);
2266 }
2267 }
2268
2269 public void noteStopGps() {
Evan Millarc64edde2009-04-18 12:26:32 -07002270 StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002271 if (t != null) {
2272 t.stopRunningLocked(BatteryStatsImpl.this);
2273 }
2274 }
2275
2276 public BatteryStatsImpl getBatteryStats() {
2277 return BatteryStatsImpl.this;
2278 }
2279 }
2280
2281 public BatteryStatsImpl(String filename) {
2282 mFile = new File(filename);
2283 mBackupFile = new File(filename + ".bak");
2284 mStartCount++;
Evan Millarc64edde2009-04-18 12:26:32 -07002285 mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables);
Dianne Hackborn617f8772009-03-31 15:04:46 -07002286 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
Evan Millarc64edde2009-04-18 12:26:32 -07002287 mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables);
Dianne Hackborn617f8772009-03-31 15:04:46 -07002288 }
2289 mInputEventCounter = new Counter(mUnpluggables);
Evan Millarc64edde2009-04-18 12:26:32 -07002290 mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables);
Dianne Hackborn627bba72009-03-24 22:32:56 -07002291 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
Evan Millarc64edde2009-04-18 12:26:32 -07002292 mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables);
Dianne Hackborn627bba72009-03-24 22:32:56 -07002293 }
2294 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
Evan Millarc64edde2009-04-18 12:26:32 -07002295 mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables);
Dianne Hackborn627bba72009-03-24 22:32:56 -07002296 }
Evan Millarc64edde2009-04-18 12:26:32 -07002297 mWifiOnTimer = new StopwatchTimer(-3, null, mUnpluggables);
2298 mWifiRunningTimer = new StopwatchTimer(-4, null, mUnpluggables);
2299 mBluetoothOnTimer = new StopwatchTimer(-5, null, mUnpluggables);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002300 mOnBattery = mOnBatteryInternal = false;
2301 mTrackBatteryPastUptime = 0;
2302 mTrackBatteryPastRealtime = 0;
2303 mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000;
2304 mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000;
2305 mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart);
2306 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart);
Evan Millar633a1742009-04-02 16:36:33 -07002307 mDischargeStartLevel = 0;
2308 mDischargeCurrentLevel = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 }
2310
2311 public BatteryStatsImpl(Parcel p) {
2312 mFile = mBackupFile = null;
2313 readFromParcel(p);
2314 }
2315
2316 @Override
2317 public int getStartCount() {
2318 return mStartCount;
2319 }
2320
2321 public boolean isOnBattery() {
2322 return mOnBattery;
2323 }
2324
The Android Open Source Project10592532009-03-18 17:39:46 -07002325 public void setOnBattery(boolean onBattery, int level) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002326 synchronized(this) {
Evan Millarc64edde2009-04-18 12:26:32 -07002327 updateKernelWakelocksLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002328 if (mOnBattery != onBattery) {
2329 mOnBattery = mOnBatteryInternal = onBattery;
2330
2331 long uptime = SystemClock.uptimeMillis() * 1000;
2332 long mSecRealtime = SystemClock.elapsedRealtime();
2333 long realtime = mSecRealtime * 1000;
2334 if (onBattery) {
2335 mTrackBatteryUptimeStart = uptime;
2336 mTrackBatteryRealtimeStart = realtime;
2337 mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime);
2338 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime);
Evan Millar633a1742009-04-02 16:36:33 -07002339 mDischargeCurrentLevel = mDischargeStartLevel = level;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002340 doUnplug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
2341 } else {
2342 mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart;
2343 mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart;
Evan Millar633a1742009-04-02 16:36:33 -07002344 mDischargeCurrentLevel = level;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002345 doPlug(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime));
2346 }
2347 if ((mLastWriteTime + (60 * 1000)) < mSecRealtime) {
2348 if (mFile != null) {
2349 writeLocked();
2350 }
2351 }
2352 }
2353 }
2354 }
Evan Millar633a1742009-04-02 16:36:33 -07002355
2356 public void recordCurrentLevel(int level) {
2357 mDischargeCurrentLevel = level;
2358 }
Evan Millarc64edde2009-04-18 12:26:32 -07002359
2360 public void updateKernelWakelocksLocked() {
2361 Map<String, KernelWakelockStats> m = readKernelWakelockStats();
2362
2363 for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) {
2364 String name = ent.getKey();
2365 KernelWakelockStats kws = ent.getValue();
2366
2367 SamplingTimer kwlt = mKernelWakelockStats.get(name);
2368 if (kwlt == null) {
2369 kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal,
2370 true /* track reported values */);
2371 mKernelWakelockStats.put(name, kwlt);
2372 }
2373 kwlt.updateCurrentReportedCount(kws.mCount);
2374 kwlt.updateCurrentReportedTotalTime(kws.mTotalTime);
2375 kwlt.setUpdateVersion(sKernelWakelockUpdateVersion);
2376 }
2377
2378 if (m.size() != mKernelWakelockStats.size()) {
2379 // Set timers to stale if they didn't appear in /proc/wakelocks this time.
2380 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
2381 SamplingTimer st = ent.getValue();
2382 if (st.getUpdateVersion() != sKernelWakelockUpdateVersion) {
2383 st.setStale();
2384 }
2385 }
2386 }
2387 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002388
2389 public long getAwakeTimeBattery() {
2390 return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
2391 }
2392
2393 public long getAwakeTimePlugged() {
2394 return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery();
2395 }
2396
2397 @Override
2398 public long computeUptime(long curTime, int which) {
2399 switch (which) {
2400 case STATS_TOTAL: return mUptime + (curTime-mUptimeStart);
2401 case STATS_LAST: return mLastUptime;
2402 case STATS_CURRENT: return (curTime-mUptimeStart);
2403 case STATS_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart);
2404 }
2405 return 0;
2406 }
2407
2408 @Override
2409 public long computeRealtime(long curTime, int which) {
2410 switch (which) {
2411 case STATS_TOTAL: return mRealtime + (curTime-mRealtimeStart);
2412 case STATS_LAST: return mLastRealtime;
2413 case STATS_CURRENT: return (curTime-mRealtimeStart);
2414 case STATS_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart);
2415 }
2416 return 0;
2417 }
2418
2419 @Override
2420 public long computeBatteryUptime(long curTime, int which) {
2421 switch (which) {
2422 case STATS_TOTAL:
2423 return mBatteryUptime + getBatteryUptime(curTime);
2424 case STATS_LAST:
2425 return mBatteryLastUptime;
2426 case STATS_CURRENT:
2427 return getBatteryUptime(curTime);
2428 case STATS_UNPLUGGED:
2429 return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime;
2430 }
2431 return 0;
2432 }
2433
2434 @Override
2435 public long computeBatteryRealtime(long curTime, int which) {
2436 switch (which) {
2437 case STATS_TOTAL:
2438 return mBatteryRealtime + getBatteryRealtimeLocked(curTime);
2439 case STATS_LAST:
2440 return mBatteryLastRealtime;
2441 case STATS_CURRENT:
2442 return getBatteryRealtimeLocked(curTime);
2443 case STATS_UNPLUGGED:
2444 return getBatteryRealtimeLocked(curTime) - mUnpluggedBatteryRealtime;
2445 }
2446 return 0;
2447 }
2448
2449 long getBatteryUptimeLocked(long curTime) {
2450 long time = mTrackBatteryPastUptime;
2451 if (mOnBatteryInternal) {
2452 time += curTime - mTrackBatteryUptimeStart;
2453 }
2454 return time;
2455 }
2456
2457 long getBatteryUptimeLocked() {
2458 return getBatteryUptime(SystemClock.uptimeMillis() * 1000);
2459 }
2460
2461 @Override
2462 public long getBatteryUptime(long curTime) {
2463 return getBatteryUptimeLocked(curTime);
2464 }
2465
2466 long getBatteryRealtimeLocked(long curTime) {
2467 long time = mTrackBatteryPastRealtime;
2468 if (mOnBatteryInternal) {
2469 time += curTime - mTrackBatteryRealtimeStart;
2470 }
2471 return time;
2472 }
2473
2474 @Override
2475 public long getBatteryRealtime(long curTime) {
2476 return getBatteryRealtimeLocked(curTime);
2477 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002478
2479 @Override
Evan Millar633a1742009-04-02 16:36:33 -07002480 public int getDischargeStartLevel() {
The Android Open Source Project10592532009-03-18 17:39:46 -07002481 synchronized(this) {
Evan Millar633a1742009-04-02 16:36:33 -07002482 return getDischargeStartLevelLocked();
The Android Open Source Project10592532009-03-18 17:39:46 -07002483 }
2484 }
2485
Evan Millar633a1742009-04-02 16:36:33 -07002486 public int getDischargeStartLevelLocked() {
2487 return mDischargeStartLevel;
The Android Open Source Project10592532009-03-18 17:39:46 -07002488 }
2489
2490 @Override
Evan Millar633a1742009-04-02 16:36:33 -07002491 public int getDischargeCurrentLevel() {
The Android Open Source Project10592532009-03-18 17:39:46 -07002492 synchronized(this) {
Evan Millar633a1742009-04-02 16:36:33 -07002493 return getDischargeCurrentLevelLocked();
The Android Open Source Project10592532009-03-18 17:39:46 -07002494 }
2495 }
2496
Evan Millar633a1742009-04-02 16:36:33 -07002497 public int getDischargeCurrentLevelLocked() {
2498 return mDischargeCurrentLevel;
The Android Open Source Project10592532009-03-18 17:39:46 -07002499 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500
2501 /**
2502 * Retrieve the statistics object for a particular uid, creating if needed.
2503 */
2504 public Uid getUidStatsLocked(int uid) {
2505 Uid u = mUidStats.get(uid);
2506 if (u == null) {
2507 u = new Uid(uid);
2508 mUidStats.put(uid, u);
2509 }
2510 return u;
2511 }
2512
2513 /**
2514 * Remove the statistics object for a particular uid.
2515 */
2516 public void removeUidStatsLocked(int uid) {
2517 mUidStats.remove(uid);
2518 }
2519
2520 /**
2521 * Retrieve the statistics object for a particular process, creating
2522 * if needed.
2523 */
2524 public Uid.Proc getProcessStatsLocked(int uid, String name) {
2525 Uid u = getUidStatsLocked(uid);
2526 return u.getProcessStatsLocked(name);
2527 }
2528
2529 /**
2530 * Retrieve the statistics object for a particular process, creating
2531 * if needed.
2532 */
2533 public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
2534 Uid u = getUidStatsLocked(uid);
2535 return u.getPackageStatsLocked(pkg);
2536 }
2537
2538 /**
2539 * Retrieve the statistics object for a particular service, creating
2540 * if needed.
2541 */
2542 public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
2543 Uid u = getUidStatsLocked(uid);
2544 return u.getServiceStatsLocked(pkg, name);
2545 }
2546
2547 public void writeLocked() {
2548 if ((mFile == null) || (mBackupFile == null)) {
2549 Log.w("BatteryStats", "writeLocked: no file associated with this instance");
2550 return;
2551 }
2552
2553 // Keep the old file around until we know the new one has
2554 // been successfully written.
2555 if (mFile.exists()) {
2556 if (mBackupFile.exists()) {
2557 mBackupFile.delete();
2558 }
2559 mFile.renameTo(mBackupFile);
2560 }
2561
2562 try {
2563 FileOutputStream stream = new FileOutputStream(mFile);
2564 Parcel out = Parcel.obtain();
2565 writeSummaryToParcel(out);
2566 stream.write(out.marshall());
2567 out.recycle();
2568
2569 stream.flush();
2570 stream.close();
2571 mBackupFile.delete();
2572
2573 mLastWriteTime = SystemClock.elapsedRealtime();
2574 } catch (IOException e) {
2575 Log.e("BatteryStats", "Error writing battery statistics", e);
2576 }
2577 }
2578
2579 static byte[] readFully(FileInputStream stream) throws java.io.IOException {
2580 int pos = 0;
2581 int avail = stream.available();
2582 byte[] data = new byte[avail];
2583 while (true) {
2584 int amt = stream.read(data, pos, data.length-pos);
2585 //Log.i("foo", "Read " + amt + " bytes at " + pos
2586 // + " of avail " + data.length);
2587 if (amt <= 0) {
2588 //Log.i("foo", "**** FINISHED READING: pos=" + pos
2589 // + " len=" + data.length);
2590 return data;
2591 }
2592 pos += amt;
2593 avail = stream.available();
2594 if (avail > data.length-pos) {
2595 byte[] newData = new byte[pos+avail];
2596 System.arraycopy(data, 0, newData, 0, pos);
2597 data = newData;
2598 }
2599 }
2600 }
2601
2602 public void readLocked() {
2603 if ((mFile == null) || (mBackupFile == null)) {
2604 Log.w("BatteryStats", "readLocked: no file associated with this instance");
2605 return;
2606 }
2607
2608 mUidStats.clear();
2609
2610 FileInputStream stream = null;
2611 if (mBackupFile.exists()) {
2612 try {
2613 stream = new FileInputStream(mBackupFile);
2614 } catch (java.io.IOException e) {
2615 // We'll try for the normal settings file.
2616 }
2617 }
2618
2619 try {
2620 if (stream == null) {
2621 if (!mFile.exists()) {
2622 return;
2623 }
2624 stream = new FileInputStream(mFile);
2625 }
2626
2627 byte[] raw = readFully(stream);
2628 Parcel in = Parcel.obtain();
2629 in.unmarshall(raw, 0, raw.length);
2630 in.setDataPosition(0);
2631 stream.close();
2632
2633 readSummaryFromParcel(in);
2634 } catch(java.io.IOException e) {
2635 Log.e("BatteryStats", "Error reading battery statistics", e);
2636 }
2637 }
2638
2639 public int describeContents() {
2640 return 0;
2641 }
2642
2643 private void readSummaryFromParcel(Parcel in) {
2644 final int version = in.readInt();
2645 if (version != VERSION) {
2646 Log.w("BatteryStats", "readFromParcel: version got " + version
2647 + ", expected " + VERSION + "; erasing old stats");
2648 return;
2649 }
2650
2651 mStartCount = in.readInt();
2652 mBatteryUptime = in.readLong();
2653 mBatteryLastUptime = in.readLong();
2654 mBatteryRealtime = in.readLong();
2655 mBatteryLastRealtime = in.readLong();
2656 mUptime = in.readLong();
2657 mLastUptime = in.readLong();
2658 mRealtime = in.readLong();
2659 mLastRealtime = in.readLong();
Evan Millar633a1742009-04-02 16:36:33 -07002660 mDischargeStartLevel = in.readInt();
2661 mDischargeCurrentLevel = in.readInt();
The Android Open Source Project10592532009-03-18 17:39:46 -07002662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002663 mStartCount++;
2664
2665 mScreenOn = false;
2666 mScreenOnTimer.readSummaryFromParcelLocked(in);
Dianne Hackborn617f8772009-03-31 15:04:46 -07002667 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
2668 mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
2669 }
2670 mInputEventCounter.readSummaryFromParcelLocked(in);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002671 mPhoneOn = false;
2672 mPhoneOnTimer.readSummaryFromParcelLocked(in);
Dianne Hackborn627bba72009-03-24 22:32:56 -07002673 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
2674 mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
2675 }
2676 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
2677 mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
2678 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002679 mWifiOn = false;
2680 mWifiOnTimer.readSummaryFromParcelLocked(in);
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07002681 mWifiRunning = false;
2682 mWifiRunningTimer.readSummaryFromParcelLocked(in);
The Android Open Source Project10592532009-03-18 17:39:46 -07002683 mBluetoothOn = false;
2684 mBluetoothOnTimer.readSummaryFromParcelLocked(in);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002685
Evan Millarc64edde2009-04-18 12:26:32 -07002686 int NKW = in.readInt();
2687 for (int ikw = 0; ikw < NKW; ikw++) {
2688 if (in.readInt() != 0) {
2689 String kwltName = in.readString();
2690 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
2691 }
2692 }
2693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002694 final int NU = in.readInt();
2695 for (int iu = 0; iu < NU; iu++) {
2696 int uid = in.readInt();
2697 Uid u = new Uid(uid);
2698 mUidStats.put(uid, u);
2699
Dianne Hackborn617f8772009-03-31 15:04:46 -07002700 u.mWifiTurnedOn = false;
2701 u.mWifiTurnedOnTimer.readSummaryFromParcelLocked(in);
The Android Open Source Project10592532009-03-18 17:39:46 -07002702 u.mFullWifiLockOut = false;
2703 u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
2704 u.mScanWifiLockOut = false;
2705 u.mScanWifiLockTimer.readSummaryFromParcelLocked(in);
2706
Dianne Hackborn617f8772009-03-31 15:04:46 -07002707 if (in.readInt() != 0) {
2708 if (u.mUserActivityCounters == null) {
2709 u.initUserActivityLocked();
2710 }
2711 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
2712 u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
2713 }
2714 }
2715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002716 int NW = in.readInt();
2717 for (int iw = 0; iw < NW; iw++) {
2718 String wlName = in.readString();
2719 if (in.readInt() != 0) {
2720 u.getWakeTimerLocked(wlName, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
2721 }
2722 if (in.readInt() != 0) {
2723 u.getWakeTimerLocked(wlName, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
2724 }
2725 if (in.readInt() != 0) {
2726 u.getWakeTimerLocked(wlName, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
2727 }
2728 }
2729
2730 int NP = in.readInt();
2731 for (int is = 0; is < NP; is++) {
2732 int seNumber = in.readInt();
2733 if (in.readInt() != 0) {
2734 u.getSensorTimerLocked(seNumber, true)
2735 .readSummaryFromParcelLocked(in);
2736 }
2737 }
2738
2739 NP = in.readInt();
2740 for (int ip = 0; ip < NP; ip++) {
2741 String procName = in.readString();
2742 Uid.Proc p = u.getProcessStatsLocked(procName);
2743 p.mUserTime = p.mLoadedUserTime = in.readLong();
2744 p.mLastUserTime = in.readLong();
2745 p.mSystemTime = p.mLoadedSystemTime = in.readLong();
2746 p.mLastSystemTime = in.readLong();
2747 p.mStarts = p.mLoadedStarts = in.readInt();
2748 p.mLastStarts = in.readInt();
2749 }
2750
2751 NP = in.readInt();
2752 for (int ip = 0; ip < NP; ip++) {
2753 String pkgName = in.readString();
2754 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
2755 p.mWakeups = p.mLoadedWakeups = in.readInt();
2756 p.mLastWakeups = in.readInt();
2757 final int NS = in.readInt();
2758 for (int is = 0; is < NS; is++) {
2759 String servName = in.readString();
2760 Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
2761 s.mStartTime = s.mLoadedStartTime = in.readLong();
2762 s.mLastStartTime = in.readLong();
2763 s.mStarts = s.mLoadedStarts = in.readInt();
2764 s.mLastStarts = in.readInt();
2765 s.mLaunches = s.mLoadedLaunches = in.readInt();
2766 s.mLastLaunches = in.readInt();
2767 }
2768 }
2769
2770 u.mLoadedTcpBytesReceived = in.readLong();
2771 u.mLoadedTcpBytesSent = in.readLong();
2772 }
2773 }
2774
2775 /**
2776 * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
2777 * disk. This format does not allow a lossless round-trip.
2778 *
2779 * @param out the Parcel to be written to.
2780 */
2781 public void writeSummaryToParcel(Parcel out) {
2782 final long NOW_SYS = SystemClock.uptimeMillis() * 1000;
2783 final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000;
2784 final long NOW = getBatteryUptimeLocked(NOW_SYS);
2785 final long NOWREAL = getBatteryRealtimeLocked(NOWREAL_SYS);
2786
2787 out.writeInt(VERSION);
2788
2789 out.writeInt(mStartCount);
2790 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_TOTAL));
2791 out.writeLong(computeBatteryUptime(NOW_SYS, STATS_CURRENT));
2792 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_TOTAL));
2793 out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_CURRENT));
2794 out.writeLong(computeUptime(NOW_SYS, STATS_TOTAL));
2795 out.writeLong(computeUptime(NOW_SYS, STATS_CURRENT));
2796 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_TOTAL));
2797 out.writeLong(computeRealtime(NOWREAL_SYS, STATS_CURRENT));
Evan Millar633a1742009-04-02 16:36:33 -07002798 out.writeInt(mDischargeStartLevel);
2799 out.writeInt(mDischargeCurrentLevel);
The Android Open Source Project10592532009-03-18 17:39:46 -07002800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002801
2802 mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
Dianne Hackborn617f8772009-03-31 15:04:46 -07002803 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
2804 mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
2805 }
2806 mInputEventCounter.writeSummaryFromParcelLocked(out);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002807 mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
Dianne Hackborn627bba72009-03-24 22:32:56 -07002808 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
2809 mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
2810 }
2811 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
2812 mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
2813 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002814 mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07002815 mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
The Android Open Source Project10592532009-03-18 17:39:46 -07002816 mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002817
Evan Millarc64edde2009-04-18 12:26:32 -07002818 out.writeInt(mKernelWakelockStats.size());
2819 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
2820 Timer kwlt = ent.getValue();
2821 if (kwlt != null) {
2822 out.writeInt(1);
2823 out.writeString(ent.getKey());
2824 ent.getValue().writeSummaryFromParcelLocked(out, NOWREAL);
2825 } else {
2826 out.writeInt(0);
2827 }
2828 }
2829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002830 final int NU = mUidStats.size();
2831 out.writeInt(NU);
2832 for (int iu = 0; iu < NU; iu++) {
2833 out.writeInt(mUidStats.keyAt(iu));
2834 Uid u = mUidStats.valueAt(iu);
The Android Open Source Project10592532009-03-18 17:39:46 -07002835
Dianne Hackborn617f8772009-03-31 15:04:46 -07002836 u.mWifiTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
The Android Open Source Project10592532009-03-18 17:39:46 -07002837 u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
2838 u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002839
Dianne Hackborn617f8772009-03-31 15:04:46 -07002840 if (u.mUserActivityCounters == null) {
2841 out.writeInt(0);
2842 } else {
2843 out.writeInt(1);
2844 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
2845 u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
2846 }
2847 }
2848
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002849 int NW = u.mWakelockStats.size();
2850 out.writeInt(NW);
2851 if (NW > 0) {
2852 for (Map.Entry<String, BatteryStatsImpl.Uid.Wakelock> ent
2853 : u.mWakelockStats.entrySet()) {
2854 out.writeString(ent.getKey());
2855 Uid.Wakelock wl = ent.getValue();
2856 if (wl.mTimerFull != null) {
2857 out.writeInt(1);
2858 wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL);
2859 } else {
2860 out.writeInt(0);
2861 }
2862 if (wl.mTimerPartial != null) {
2863 out.writeInt(1);
2864 wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL);
2865 } else {
2866 out.writeInt(0);
2867 }
2868 if (wl.mTimerWindow != null) {
2869 out.writeInt(1);
2870 wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL);
2871 } else {
2872 out.writeInt(0);
2873 }
2874 }
2875 }
2876
2877 int NSE = u.mSensorStats.size();
2878 out.writeInt(NSE);
2879 if (NSE > 0) {
2880 for (Map.Entry<Integer, BatteryStatsImpl.Uid.Sensor> ent
2881 : u.mSensorStats.entrySet()) {
2882 out.writeInt(ent.getKey());
2883 Uid.Sensor se = ent.getValue();
2884 if (se.mTimer != null) {
2885 out.writeInt(1);
2886 se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL);
2887 } else {
2888 out.writeInt(0);
2889 }
2890 }
2891 }
2892
2893 int NP = u.mProcessStats.size();
2894 out.writeInt(NP);
2895 if (NP > 0) {
2896 for (Map.Entry<String, BatteryStatsImpl.Uid.Proc> ent
2897 : u.mProcessStats.entrySet()) {
2898 out.writeString(ent.getKey());
2899 Uid.Proc ps = ent.getValue();
2900 out.writeLong(ps.mUserTime);
2901 out.writeLong(ps.mUserTime - ps.mLoadedUserTime);
2902 out.writeLong(ps.mSystemTime);
2903 out.writeLong(ps.mSystemTime - ps.mLoadedSystemTime);
2904 out.writeInt(ps.mStarts);
2905 out.writeInt(ps.mStarts - ps.mLoadedStarts);
2906 }
2907 }
2908
2909 NP = u.mPackageStats.size();
2910 out.writeInt(NP);
2911 if (NP > 0) {
2912 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
2913 : u.mPackageStats.entrySet()) {
2914 out.writeString(ent.getKey());
2915 Uid.Pkg ps = ent.getValue();
2916 out.writeInt(ps.mWakeups);
2917 out.writeInt(ps.mWakeups - ps.mLoadedWakeups);
2918 final int NS = ps.mServiceStats.size();
2919 out.writeInt(NS);
2920 if (NS > 0) {
2921 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent
2922 : ps.mServiceStats.entrySet()) {
2923 out.writeString(sent.getKey());
2924 BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue();
2925 long time = ss.getStartTimeToNowLocked(NOW);
2926 out.writeLong(time);
2927 out.writeLong(time - ss.mLoadedStartTime);
2928 out.writeInt(ss.mStarts);
2929 out.writeInt(ss.mStarts - ss.mLoadedStarts);
2930 out.writeInt(ss.mLaunches);
2931 out.writeInt(ss.mLaunches - ss.mLoadedLaunches);
2932 }
2933 }
2934 }
2935 }
2936
2937 out.writeLong(u.getTcpBytesReceived(STATS_TOTAL));
2938 out.writeLong(u.getTcpBytesSent(STATS_TOTAL));
2939 }
2940 }
2941
2942 public void readFromParcel(Parcel in) {
2943 readFromParcelLocked(in);
2944 }
2945
2946 void readFromParcelLocked(Parcel in) {
2947 int magic = in.readInt();
2948 if (magic != MAGIC) {
2949 throw new ParcelFormatException("Bad magic number");
2950 }
2951
2952 mStartCount = in.readInt();
2953 mBatteryUptime = in.readLong();
2954 mBatteryLastUptime = in.readLong();
2955 mBatteryRealtime = in.readLong();
2956 mBatteryLastRealtime = in.readLong();
2957 mScreenOn = false;
Evan Millarc64edde2009-04-18 12:26:32 -07002958 mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables, in);
Dianne Hackborn617f8772009-03-31 15:04:46 -07002959 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
Evan Millarc64edde2009-04-18 12:26:32 -07002960 mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables, in);
Dianne Hackborn617f8772009-03-31 15:04:46 -07002961 }
2962 mInputEventCounter = new Counter(mUnpluggables, in);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002963 mPhoneOn = false;
Evan Millarc64edde2009-04-18 12:26:32 -07002964 mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
Dianne Hackborn627bba72009-03-24 22:32:56 -07002965 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
Evan Millarc64edde2009-04-18 12:26:32 -07002966 mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables, in);
Dianne Hackborn627bba72009-03-24 22:32:56 -07002967 }
2968 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
Evan Millarc64edde2009-04-18 12:26:32 -07002969 mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables, in);
Dianne Hackborn627bba72009-03-24 22:32:56 -07002970 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002971 mWifiOn = false;
Evan Millarc64edde2009-04-18 12:26:32 -07002972 mWifiOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07002973 mWifiRunning = false;
Evan Millarc64edde2009-04-18 12:26:32 -07002974 mWifiRunningTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
The Android Open Source Project10592532009-03-18 17:39:46 -07002975 mBluetoothOn = false;
Evan Millarc64edde2009-04-18 12:26:32 -07002976 mBluetoothOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002977 mUptime = in.readLong();
2978 mUptimeStart = in.readLong();
2979 mLastUptime = in.readLong();
2980 mRealtime = in.readLong();
2981 mRealtimeStart = in.readLong();
2982 mLastRealtime = in.readLong();
2983 mOnBattery = in.readInt() != 0;
2984 mOnBatteryInternal = false; // we are no longer really running.
2985 mTrackBatteryPastUptime = in.readLong();
2986 mTrackBatteryUptimeStart = in.readLong();
2987 mTrackBatteryPastRealtime = in.readLong();
2988 mTrackBatteryRealtimeStart = in.readLong();
2989 mUnpluggedBatteryUptime = in.readLong();
2990 mUnpluggedBatteryRealtime = in.readLong();
Evan Millar633a1742009-04-02 16:36:33 -07002991 mDischargeStartLevel = in.readInt();
2992 mDischargeCurrentLevel = in.readInt();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002993 mLastWriteTime = in.readLong();
2994
Evan Millarc64edde2009-04-18 12:26:32 -07002995 mKernelWakelockStats.clear();
2996 int NKW = in.readInt();
2997 for (int ikw = 0; ikw < NKW; ikw++) {
2998 if (in.readInt() != 0) {
2999 String wakelockName = in.readString();
3000 SamplingTimer kwlt = new SamplingTimer(mUnpluggables, mOnBattery, in);
3001 mKernelWakelockStats.put(wakelockName, kwlt);
3002 }
3003 }
3004
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003005 mPartialTimers.clear();
3006 mFullTimers.clear();
3007 mWindowTimers.clear();
3008
3009 int numUids = in.readInt();
3010 mUidStats.clear();
3011 for (int i = 0; i < numUids; i++) {
3012 int uid = in.readInt();
3013 Uid u = new Uid(uid);
3014 u.readFromParcelLocked(mUnpluggables, in);
3015 mUidStats.append(uid, u);
3016 }
3017 }
3018
3019 public void writeToParcel(Parcel out, int flags) {
3020 writeToParcelLocked(out, flags);
3021 }
3022
3023 @SuppressWarnings("unused")
3024 void writeToParcelLocked(Parcel out, int flags) {
3025 final long uSecUptime = SystemClock.uptimeMillis() * 1000;
3026 final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
3027 final long batteryUptime = getBatteryUptimeLocked(uSecUptime);
3028 final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime);
3029
3030 out.writeInt(MAGIC);
3031 out.writeInt(mStartCount);
3032 out.writeLong(mBatteryUptime);
3033 out.writeLong(mBatteryLastUptime);
3034 out.writeLong(mBatteryRealtime);
3035 out.writeLong(mBatteryLastRealtime);
3036 mScreenOnTimer.writeToParcel(out, batteryRealtime);
Dianne Hackborn617f8772009-03-31 15:04:46 -07003037 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
3038 mScreenBrightnessTimer[i].writeToParcel(out, batteryRealtime);
3039 }
3040 mInputEventCounter.writeToParcel(out);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003041 mPhoneOnTimer.writeToParcel(out, batteryRealtime);
Dianne Hackborn627bba72009-03-24 22:32:56 -07003042 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
3043 mPhoneSignalStrengthsTimer[i].writeToParcel(out, batteryRealtime);
3044 }
3045 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
3046 mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime);
3047 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003048 mWifiOnTimer.writeToParcel(out, batteryRealtime);
Eric Shienbroodd4c5f892009-03-24 18:13:20 -07003049 mWifiRunningTimer.writeToParcel(out, batteryRealtime);
The Android Open Source Project10592532009-03-18 17:39:46 -07003050 mBluetoothOnTimer.writeToParcel(out, batteryRealtime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 out.writeLong(mUptime);
3052 out.writeLong(mUptimeStart);
3053 out.writeLong(mLastUptime);
3054 out.writeLong(mRealtime);
3055 out.writeLong(mRealtimeStart);
3056 out.writeLong(mLastRealtime);
3057 out.writeInt(mOnBattery ? 1 : 0);
3058 out.writeLong(batteryUptime);
3059 out.writeLong(mTrackBatteryUptimeStart);
3060 out.writeLong(batteryRealtime);
3061 out.writeLong(mTrackBatteryRealtimeStart);
3062 out.writeLong(mUnpluggedBatteryUptime);
3063 out.writeLong(mUnpluggedBatteryRealtime);
Evan Millar633a1742009-04-02 16:36:33 -07003064 out.writeInt(mDischargeStartLevel);
3065 out.writeInt(mDischargeCurrentLevel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 out.writeLong(mLastWriteTime);
3067
Evan Millarc64edde2009-04-18 12:26:32 -07003068 out.writeInt(mKernelWakelockStats.size());
3069 for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
3070 SamplingTimer kwlt = ent.getValue();
3071 if (kwlt != null) {
3072 out.writeInt(1);
3073 out.writeString(ent.getKey());
3074 Timer.writeTimerToParcel(out, kwlt, batteryRealtime);
3075 } else {
3076 out.writeInt(0);
3077 }
3078 }
3079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003080 int size = mUidStats.size();
3081 out.writeInt(size);
3082 for (int i = 0; i < size; i++) {
3083 out.writeInt(mUidStats.keyAt(i));
3084 Uid uid = mUidStats.valueAt(i);
3085
3086 uid.writeToParcelLocked(out, batteryRealtime);
3087 }
3088 }
3089
3090 public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
3091 new Parcelable.Creator<BatteryStatsImpl>() {
3092 public BatteryStatsImpl createFromParcel(Parcel in) {
3093 return new BatteryStatsImpl(in);
3094 }
3095
3096 public BatteryStatsImpl[] newArray(int size) {
3097 return new BatteryStatsImpl[size];
3098 }
3099 };
3100
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003101 public void dumpLocked(PrintWriter pw) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003102 if (DEBUG) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003103 Printer pr = new PrintWriterPrinter(pw);
3104 pr.println("*** Screen timer:");
3105 mScreenOnTimer.logState(pr, " ");
Dianne Hackborn617f8772009-03-31 15:04:46 -07003106 for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003107 pr.println("*** Screen brightness #" + i + ":");
3108 mScreenBrightnessTimer[i].logState(pr, " ");
Dianne Hackborn617f8772009-03-31 15:04:46 -07003109 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003110 pr.println("*** Input event counter:");
3111 mInputEventCounter.logState(pr, " ");
3112 pr.println("*** Phone timer:");
3113 mPhoneOnTimer.logState(pr, " ");
Dianne Hackborn627bba72009-03-24 22:32:56 -07003114 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003115 pr.println("*** Signal strength #" + i + ":");
3116 mPhoneSignalStrengthsTimer[i].logState(pr, " ");
Dianne Hackborn627bba72009-03-24 22:32:56 -07003117 }
3118 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003119 pr.println("*** Data connection type #" + i + ":");
3120 mPhoneDataConnectionsTimer[i].logState(pr, " ");
Dianne Hackborn627bba72009-03-24 22:32:56 -07003121 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003122 pr.println("*** Wifi timer:");
3123 mWifiOnTimer.logState(pr, " ");
3124 pr.println("*** WifiRunning timer:");
3125 mWifiRunningTimer.logState(pr, " ");
3126 pr.println("*** Bluetooth timer:");
3127 mBluetoothOnTimer.logState(pr, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003128 }
3129 super.dumpLocked(pw);
3130 }
3131}