summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/os/BatteryStats.java133
-rw-r--r--core/java/com/android/internal/app/IBatteryStats.aidl4
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java226
3 files changed, 348 insertions, 15 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 7fd166059ac4..aab7b1f504ba 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -120,6 +120,16 @@ public abstract class BatteryStats implements Parcelable {
public static final int PROCESS_STATE = 12;
/**
+ * A constant indicating a sync timer
+ */
+ public static final int SYNC = 13;
+
+ /**
+ * A constant indicating a job timer
+ */
+ public static final int JOB = 14;
+
+ /**
* Include all of the data in the stats, including previously saved data.
*/
public static final int STATS_SINCE_CHARGED = 0;
@@ -157,6 +167,8 @@ public abstract class BatteryStats implements Parcelable {
private static final String FOREGROUND_DATA = "fg";
private static final String STATE_TIME_DATA = "st";
private static final String WAKELOCK_DATA = "wl";
+ private static final String SYNC_DATA = "sy";
+ private static final String JOB_DATA = "jb";
private static final String KERNEL_WAKELOCK_DATA = "kwl";
private static final String WAKEUP_REASON_DATA = "wr";
private static final String NETWORK_DATA = "nt";
@@ -273,6 +285,20 @@ public abstract class BatteryStats implements Parcelable {
public abstract Map<String, ? extends Wakelock> getWakelockStats();
/**
+ * Returns a mapping containing sync statistics.
+ *
+ * @return a Map from Strings to Timer objects.
+ */
+ public abstract Map<String, ? extends Timer> getSyncStats();
+
+ /**
+ * Returns a mapping containing scheduled job statistics.
+ *
+ * @return a Map from Strings to Timer objects.
+ */
+ public abstract Map<String, ? extends Timer> getJobStats();
+
+ /**
* The statistics associated with a particular wake lock.
*/
public static abstract class Wakelock {
@@ -660,13 +686,19 @@ public abstract class BatteryStats implements Parcelable {
public static final int EVENT_FOREGROUND = 0x0002;
// Event is about an application package that is at the top of the screen.
public static final int EVENT_TOP = 0x0003;
- // Event is about an application package that is at the top of the screen.
+ // Event is about active sync operations.
public static final int EVENT_SYNC = 0x0004;
// Events for all additional wake locks aquired/release within a wake block.
// These are not generated by default.
public static final int EVENT_WAKE_LOCK = 0x0005;
+ // Event is about an application executing a scheduled job.
+ public static final int EVENT_JOB = 0x0006;
+ // Events for users running.
+ public static final int EVENT_USER_RUNNING = 0x0007;
+ // Events for foreground user.
+ public static final int EVENT_USER_FOREGROUND = 0x0008;
// Number of event types.
- public static final int EVENT_COUNT = 0x0006;
+ public static final int EVENT_COUNT = 0x0009;
// Mask to extract out only the type part of the event.
public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
@@ -680,6 +712,14 @@ public abstract class BatteryStats implements Parcelable {
public static final int EVENT_SYNC_FINISH = EVENT_SYNC | EVENT_FLAG_FINISH;
public static final int EVENT_WAKE_LOCK_START = EVENT_WAKE_LOCK | EVENT_FLAG_START;
public static final int EVENT_WAKE_LOCK_FINISH = EVENT_WAKE_LOCK | EVENT_FLAG_FINISH;
+ public static final int EVENT_JOB_START = EVENT_JOB | EVENT_FLAG_START;
+ public static final int EVENT_JOB_FINISH = EVENT_JOB | EVENT_FLAG_FINISH;
+ public static final int EVENT_USER_RUNNING_START = EVENT_USER_RUNNING | EVENT_FLAG_START;
+ public static final int EVENT_USER_RUNNING_FINISH = EVENT_USER_RUNNING | EVENT_FLAG_FINISH;
+ public static final int EVENT_USER_FOREGROUND_START =
+ EVENT_USER_FOREGROUND | EVENT_FLAG_START;
+ public static final int EVENT_USER_FOREGROUND_FINISH =
+ EVENT_USER_FOREGROUND | EVENT_FLAG_FINISH;
// For CMD_EVENT.
public int eventCode;
@@ -1269,11 +1309,11 @@ public abstract class BatteryStats implements Parcelable {
};
public static final String[] HISTORY_EVENT_NAMES = new String[] {
- "null", "proc", "fg", "top", "sync", "wake_lock_in"
+ "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg"
};
public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
- "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl"
+ "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf"
};
/**
@@ -2080,10 +2120,9 @@ public abstract class BatteryStats implements Parcelable {
}
}
- Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
+ Map<String, ? extends Uid.Wakelock> wakelocks = u.getWakelockStats();
if (wakelocks.size() > 0) {
- for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
- : wakelocks.entrySet()) {
+ for (Map.Entry<String, ? extends Uid.Wakelock> ent : wakelocks.entrySet()) {
Uid.Wakelock wl = ent.getValue();
String linePrefix = "";
sb.setLength(0);
@@ -2105,6 +2144,32 @@ public abstract class BatteryStats implements Parcelable {
}
}
+ Map<String, ? extends Timer> syncs = u.getSyncStats();
+ if (syncs.size() > 0) {
+ for (Map.Entry<String, ? extends Timer> ent : syncs.entrySet()) {
+ Timer timer = ent.getValue();
+ // Convert from microseconds to milliseconds with rounding
+ long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+ int count = timer.getCountLocked(which);
+ if (totalTime != 0) {
+ dumpLine(pw, uid, category, SYNC_DATA, ent.getKey(), totalTime, count);
+ }
+ }
+ }
+
+ Map<String, ? extends Timer> jobs = u.getJobStats();
+ if (jobs.size() > 0) {
+ for (Map.Entry<String, ? extends Timer> ent : jobs.entrySet()) {
+ Timer timer = ent.getValue();
+ // Convert from microseconds to milliseconds with rounding
+ long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+ int count = timer.getCountLocked(which);
+ if (totalTime != 0) {
+ dumpLine(pw, uid, category, JOB_DATA, ent.getKey(), totalTime, count);
+ }
+ }
+ }
+
SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
int NSE = sensors.size();
for (int ise=0; ise<NSE; ise++) {
@@ -2937,8 +3002,7 @@ public abstract class BatteryStats implements Parcelable {
if (wakelocks.size() > 0) {
long totalFull = 0, totalPartial = 0, totalWindow = 0;
int count = 0;
- for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
- : wakelocks.entrySet()) {
+ for (Map.Entry<String, ? extends Uid.Wakelock> ent : wakelocks.entrySet()) {
Uid.Wakelock wl = ent.getValue();
String linePrefix = ": ";
sb.setLength(0);
@@ -2998,6 +3062,56 @@ public abstract class BatteryStats implements Parcelable {
}
}
+ Map<String, ? extends Timer> syncs = u.getSyncStats();
+ if (syncs.size() > 0) {
+ for (Map.Entry<String, ? extends Timer> ent : syncs.entrySet()) {
+ Timer timer = ent.getValue();
+ // Convert from microseconds to milliseconds with rounding
+ long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+ int count = timer.getCountLocked(which);
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Sync ");
+ sb.append(ent.getKey());
+ sb.append(": ");
+ if (totalTime != 0) {
+ formatTimeMs(sb, totalTime);
+ sb.append("realtime (");
+ sb.append(count);
+ sb.append(" times)");
+ } else {
+ sb.append("(not used)");
+ }
+ pw.println(sb.toString());
+ uidActivity = true;
+ }
+ }
+
+ Map<String, ? extends Timer> jobs = u.getJobStats();
+ if (syncs.size() > 0) {
+ for (Map.Entry<String, ? extends Timer> ent : jobs.entrySet()) {
+ Timer timer = ent.getValue();
+ // Convert from microseconds to milliseconds with rounding
+ long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+ int count = timer.getCountLocked(which);
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Job ");
+ sb.append(ent.getKey());
+ sb.append(": ");
+ if (totalTime != 0) {
+ formatTimeMs(sb, totalTime);
+ sb.append("realtime (");
+ sb.append(count);
+ sb.append(" times)");
+ } else {
+ sb.append("(not used)");
+ }
+ pw.println(sb.toString());
+ uidActivity = true;
+ }
+ }
+
SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
int NSE = sensors.size();
for (int ise=0; ise<NSE; ise++) {
@@ -3260,7 +3374,6 @@ public abstract class BatteryStats implements Parcelable {
int oldTemp = -1;
int oldVolt = -1;
long lastTime = -1;
- long firstTime = -1;
void reset() {
oldState = oldState2 = 0;
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 98a58430ea8e..901d6e67180e 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -47,6 +47,10 @@ interface IBatteryStats {
void noteProcessStart(String name, int uid);
void noteProcessState(String name, int uid, int state);
void noteProcessFinish(String name, int uid);
+ void noteSyncStart(String name, int uid);
+ void noteSyncFinish(String name, int uid);
+ void noteJobStart(String name, int uid);
+ void noteJobFinish(String name, int uid);
void noteStartWakelock(int uid, int pid, String name, String historyName,
int type, boolean unimportantForLogging);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 6ca048ed3844..dec94f22a719 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -91,7 +91,7 @@ public final class BatteryStatsImpl extends BatteryStats {
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 109 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 112 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -2109,6 +2109,11 @@ public final class BatteryStatsImpl extends BatteryStats {
return;
}
+ if (dataSize == 0) {
+ // The history is currently empty; we need it to start with a time stamp.
+ cur.currentTime = System.currentTimeMillis();
+ addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_RESET, cur);
+ }
addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
}
@@ -2362,6 +2367,50 @@ public final class BatteryStatsImpl extends BatteryStats {
elapsedRealtime);
}
+ public void noteSyncStartLocked(String name, int uid) {
+ uid = mapUid(uid);
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime);
+ if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
+ return;
+ }
+ addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_START, name, uid);
+ }
+
+ public void noteSyncFinishLocked(String name, int uid) {
+ uid = mapUid(uid);
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime);
+ if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
+ return;
+ }
+ addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_FINISH, name, uid);
+ }
+
+ public void noteJobStartLocked(String name, int uid) {
+ uid = mapUid(uid);
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime);
+ if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
+ return;
+ }
+ addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid);
+ }
+
+ public void noteJobFinishLocked(String name, int uid) {
+ uid = mapUid(uid);
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime);
+ if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
+ return;
+ }
+ addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
+ }
+
private void requestWakelockCpuUpdate() {
if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
@@ -3833,6 +3882,16 @@ public final class BatteryStatsImpl extends BatteryStats {
final ArrayMap<String, Wakelock> mWakelockStats = new ArrayMap<String, Wakelock>();
/**
+ * The statistics we have collected for this uid's syncs.
+ */
+ final ArrayMap<String, StopwatchTimer> mSyncStats = new ArrayMap<String, StopwatchTimer>();
+
+ /**
+ * The statistics we have collected for this uid's jobs.
+ */
+ final ArrayMap<String, StopwatchTimer> mJobStats = new ArrayMap<String, StopwatchTimer>();
+
+ /**
* The statistics we have collected for this uid's sensor activations.
*/
final SparseArray<Sensor> mSensorStats = new SparseArray<Sensor>();
@@ -3872,6 +3931,16 @@ public final class BatteryStatsImpl extends BatteryStats {
}
@Override
+ public Map<String, ? extends BatteryStats.Timer> getSyncStats() {
+ return mSyncStats;
+ }
+
+ @Override
+ public Map<String, ? extends BatteryStats.Timer> getJobStats() {
+ return mJobStats;
+ }
+
+ @Override
public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
return mSensorStats;
}
@@ -4396,6 +4465,24 @@ public final class BatteryStatsImpl extends BatteryStats {
active = true;
}
}
+ for (int is=mSyncStats.size()-1; is>=0; is--) {
+ StopwatchTimer timer = mSyncStats.valueAt(is);
+ if (timer.reset(false)) {
+ mSyncStats.removeAt(is);
+ timer.detach();
+ } else {
+ active = true;
+ }
+ }
+ for (int ij=mJobStats.size()-1; ij>=0; ij--) {
+ StopwatchTimer timer = mJobStats.valueAt(ij);
+ if (timer.reset(false)) {
+ mJobStats.removeAt(ij);
+ timer.detach();
+ } else {
+ active = true;
+ }
+ }
for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
Sensor s = mSensorStats.valueAt(ise);
if (s.reset()) {
@@ -4497,6 +4584,22 @@ public final class BatteryStatsImpl extends BatteryStats {
wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
}
+ int NS = mSyncStats.size();
+ out.writeInt(NS);
+ for (int is=0; is<NS; is++) {
+ out.writeString(mSyncStats.keyAt(is));
+ StopwatchTimer timer = mSyncStats.valueAt(is);
+ Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
+ }
+
+ int NJ = mJobStats.size();
+ out.writeInt(NJ);
+ for (int ij=0; ij<NJ; ij++) {
+ out.writeString(mJobStats.keyAt(ij));
+ StopwatchTimer timer = mJobStats.valueAt(ij);
+ Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
+ }
+
int NSE = mSensorStats.size();
out.writeInt(NSE);
for (int ise=0; ise<NSE; ise++) {
@@ -4618,6 +4721,25 @@ public final class BatteryStatsImpl extends BatteryStats {
mWakelockStats.put(wakelockName, wakelock);
}
+ int numSyncs = in.readInt();
+ mSyncStats.clear();
+ for (int j = 0; j < numSyncs; j++) {
+ String syncName = in.readString();
+ if (in.readInt() != 0) {
+ mSyncStats.put(syncName,
+ new StopwatchTimer(Uid.this, SYNC, null, timeBase, in));
+ }
+ }
+
+ int numJobs = in.readInt();
+ mJobStats.clear();
+ for (int j = 0; j < numJobs; j++) {
+ String jobName = in.readString();
+ if (in.readInt() != 0) {
+ mJobStats.put(jobName, new StopwatchTimer(Uid.this, JOB, null, timeBase, in));
+ }
+ }
+
int numSensors = in.readInt();
mSensorStats.clear();
for (int k = 0; k < numSensors; k++) {
@@ -5670,6 +5792,38 @@ public final class BatteryStatsImpl extends BatteryStats {
return ss;
}
+ public StopwatchTimer getSyncTimerLocked(String name) {
+ StopwatchTimer t = mSyncStats.get(name);
+ if (t == null) {
+ final int N = mSyncStats.size();
+ if (N > MAX_WAKELOCKS_PER_UID) {
+ name = BATCHED_WAKELOCK_NAME;
+ t = mSyncStats.get(name);
+ }
+ if (t == null) {
+ t = new StopwatchTimer(Uid.this, SYNC, null, mOnBatteryTimeBase);
+ mSyncStats.put(name, t);
+ }
+ }
+ return t;
+ }
+
+ public StopwatchTimer getJobTimerLocked(String name) {
+ StopwatchTimer t = mJobStats.get(name);
+ if (t == null) {
+ final int N = mJobStats.size();
+ if (N > MAX_WAKELOCKS_PER_UID) {
+ name = BATCHED_WAKELOCK_NAME;
+ t = mJobStats.get(name);
+ }
+ if (t == null) {
+ t = new StopwatchTimer(Uid.this, JOB, null, mOnBatteryTimeBase);
+ mJobStats.put(name, t);
+ }
+ }
+ return t;
+ }
+
public StopwatchTimer getWakeTimerLocked(String name, int type) {
Wakelock wl = mWakelockStats.get(name);
if (wl == null) {
@@ -5737,6 +5891,34 @@ public final class BatteryStatsImpl extends BatteryStats {
return t;
}
+ public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
+ StopwatchTimer t = getSyncTimerLocked(name);
+ if (t != null) {
+ t.startRunningLocked(elapsedRealtimeMs);
+ }
+ }
+
+ public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
+ StopwatchTimer t = getSyncTimerLocked(name);
+ if (t != null) {
+ t.stopRunningLocked(elapsedRealtimeMs);
+ }
+ }
+
+ public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
+ StopwatchTimer t = getJobTimerLocked(name);
+ if (t != null) {
+ t.startRunningLocked(elapsedRealtimeMs);
+ }
+ }
+
+ public void noteStopJobLocked(String name, long elapsedRealtimeMs) {
+ StopwatchTimer t = getJobTimerLocked(name);
+ if (t != null) {
+ t.stopRunningLocked(elapsedRealtimeMs);
+ }
+ }
+
public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
StopwatchTimer t = getWakeTimerLocked(name, type);
if (t != null) {
@@ -7170,7 +7352,7 @@ public final class BatteryStatsImpl extends BatteryStats {
// the last run until samples in this run.
if (mHistoryBaseTime > 0) {
long oldnow = SystemClock.elapsedRealtime();
- mHistoryBaseTime = (mHistoryBaseTime - oldnow) + 60*1000;
+ mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
if (DEBUG_HISTORY) {
StringBuilder sb = new StringBuilder(128);
sb.append("****************** ADJUSTED mHistoryBaseTime: ");
@@ -7433,6 +7615,26 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ int NS = in.readInt();
+ if (NS > 100) {
+ Slog.w(TAG, "File corrupt: too many syncs " + NS);
+ return;
+ }
+ for (int is = 0; is < NS; is++) {
+ String name = in.readString();
+ u.getSyncTimerLocked(name).readSummaryFromParcelLocked(in);
+ }
+
+ int NJ = in.readInt();
+ if (NJ > 100) {
+ Slog.w(TAG, "File corrupt: too many job timers " + NJ);
+ return;
+ }
+ for (int ij = 0; ij < NJ; ij++) {
+ String name = in.readString();
+ u.getJobTimerLocked(name).readSummaryFromParcelLocked(in);
+ }
+
int NP = in.readInt();
if (NP > 1000) {
Slog.w(TAG, "File corrupt: too many sensors " + NP);
@@ -7484,7 +7686,7 @@ public final class BatteryStatsImpl extends BatteryStats {
String pkgName = in.readString();
Uid.Pkg p = u.getPackageStatsLocked(pkgName);
p.mWakeups = p.mLoadedWakeups = in.readInt();
- final int NS = in.readInt();
+ NS = in.readInt();
if (NS > 1000) {
Slog.w(TAG, "File corrupt: too many services " + NS);
return;
@@ -7717,6 +7919,20 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ int NS = u.mSyncStats.size();
+ out.writeInt(NS);
+ for (int is=0; is<NS; is++) {
+ out.writeString(u.mSyncStats.keyAt(is));
+ u.mSyncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+ }
+
+ int NJ = u.mJobStats.size();
+ out.writeInt(NJ);
+ for (int ij=0; ij<NJ; ij++) {
+ out.writeString(u.mJobStats.keyAt(ij));
+ u.mJobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+ }
+
int NSE = u.mSensorStats.size();
out.writeInt(NSE);
for (int ise=0; ise<NSE; ise++) {
@@ -7760,7 +7976,7 @@ public final class BatteryStatsImpl extends BatteryStats {
out.writeString(ent.getKey());
Uid.Pkg ps = ent.getValue();
out.writeInt(ps.mWakeups);
- final int NS = ps.mServiceStats.size();
+ NS = ps.mServiceStats.size();
out.writeInt(NS);
if (NS > 0) {
for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent
@@ -7786,7 +8002,7 @@ public final class BatteryStatsImpl extends BatteryStats {
void readFromParcelLocked(Parcel in) {
int magic = in.readInt();
if (magic != MAGIC) {
- throw new ParcelFormatException("Bad magic number");
+ throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
}
readHistory(in, false);