Battery stats improvements.
- Adjust total power use when there is unaccounted power so that our
percentages don't end up > 100%.
- Fix accounting of isolated uids to be against the owning real app
uids.
- Rework how we put cpu use into the battery stats to no longer need
this uid name cache that can confuse the uid it is associated with.
- Finish implementing events in the history, adding a string pool and
reading/writing/dumping them.
- Add first two events: processes starting and finishing.
- Fix alarm manager reporting of wakeup alarms to be adjusted by the
WorkSource associated with the alarm, so they are blamed on the
correct app.
- New "--history" dump option allows you to perform a checkin of
only the history data.
- Fixed BitDescription bug that would cause incorrect printing of
changes in some states.
Change-Id: Ifbdd0740132ed178033851c58f165adc0d50f716
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 3cdf170..cb5ae96 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1258,8 +1258,16 @@
|| alarm.type == RTC_WAKEUP) {
bs.numWakeup++;
fs.numWakeup++;
- ActivityManagerNative.noteWakeupAlarm(
- alarm.operation);
+ if (alarm.workSource != null && alarm.workSource.size() > 0) {
+ for (int wi=0; wi<alarm.workSource.size(); wi++) {
+ ActivityManagerNative.noteWakeupAlarm(
+ alarm.operation, alarm.workSource.get(wi),
+ alarm.workSource.getName(wi));
+ }
+ } else {
+ ActivityManagerNative.noteWakeupAlarm(
+ alarm.operation, -1, null);
+ }
}
} catch (PendingIntent.CanceledException e) {
if (alarm.repeatInterval > 0) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 77ffeca..19efa9c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -32,6 +32,7 @@
import android.app.IActivityContainerCallback;
import android.appwidget.AppWidgetManager;
import android.graphics.Rect;
+import android.os.BatteryStats;
import android.util.ArrayMap;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -2107,29 +2108,24 @@
totalUTime += otherUTime;
totalSTime += otherSTime;
if (pr != null) {
- BatteryStatsImpl.Uid.Proc ps = bstats.getProcessStatsLocked(
- st.name, st.pid);
+ BatteryStatsImpl.Uid.Proc ps = pr.curProcBatteryStats;
+ if (ps == null || !ps.isActive()) {
+ pr.curProcBatteryStats = ps = bstats.getProcessStatsLocked(
+ pr.info.uid, pr.processName);
+ }
ps.addCpuTimeLocked(st.rel_utime-otherUTime,
st.rel_stime-otherSTime);
ps.addSpeedStepTimes(cpuSpeedTimes);
pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
- } else if (st.uid >= Process.FIRST_APPLICATION_UID) {
+ } else {
BatteryStatsImpl.Uid.Proc ps = st.batteryStats;
- if (ps == null) {
- st.batteryStats = ps = bstats.getProcessStatsLocked(st.uid,
- "(Unknown)");
+ if (ps == null || !ps.isActive()) {
+ st.batteryStats = ps = bstats.getProcessStatsLocked(
+ bstats.mapUid(st.uid), st.name);
}
ps.addCpuTimeLocked(st.rel_utime-otherUTime,
st.rel_stime-otherSTime);
ps.addSpeedStepTimes(cpuSpeedTimes);
- } else {
- BatteryStatsImpl.Uid.Proc ps =
- bstats.getProcessStatsLocked(st.name, st.pid);
- if (ps != null) {
- ps.addCpuTimeLocked(st.rel_utime-otherUTime,
- st.rel_stime-otherSTime);
- ps.addSpeedStepTimes(cpuSpeedTimes);
- }
}
}
bstats.finishAddingCpuLocked(perc, totalUTime,
@@ -2778,6 +2774,11 @@
mHandler.sendMessageDelayed(msg, startResult.usingWrapper
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
+ mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_PROC_STARTED,
+ app.processName, app.info.uid);
+ if (app.isolated) {
+ mBatteryStatsService.addIsolatedUid(app.uid, app.info.uid);
+ }
} catch (RuntimeException e) {
// XXX do better error recovery.
app.setPid(0);
@@ -4732,6 +4733,11 @@
mPidsSelfLocked.remove(pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
+ mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_PROC_FINISHED,
+ app.processName, app.info.uid);
+ if (app.isolated) {
+ mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
+ }
killUnneededProcessLocked(app, reason);
handleAppDiedLocked(app, true, allowRestart);
removeLruProcessLocked(app);
@@ -4772,6 +4778,11 @@
mHeavyWeightProcess.userId, 0));
mHeavyWeightProcess = null;
}
+ mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_PROC_FINISHED,
+ app.processName, app.info.uid);
+ if (app.isolated) {
+ mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
+ }
// Take care of any launching providers waiting for this process.
checkAppInLaunchingProvidersLocked(app, true);
// Take care of any services that are waiting for the process.
@@ -8726,7 +8737,7 @@
Context.WINDOW_SERVICE)).addView(v, lp);
}
- public void noteWakeupAlarm(IIntentSender sender) {
+ public void noteWakeupAlarm(IIntentSender sender, int sourceUid, String sourcePkg) {
if (!(sender instanceof PendingIntentRecord)) {
return;
}
@@ -8738,7 +8749,8 @@
int MY_UID = Binder.getCallingUid();
int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
BatteryStatsImpl.Uid.Pkg pkg =
- stats.getPackageStatsLocked(uid, rec.key.packageName);
+ stats.getPackageStatsLocked(sourceUid >= 0 ? sourceUid : uid,
+ sourcePkg != null ? sourcePkg : rec.key.packageName);
pkg.incWakeupsLocked();
}
}
@@ -12453,10 +12465,16 @@
startProcessLocked(app, "restart", app.processName);
} else if (app.pid > 0 && app.pid != MY_PID) {
// Goodbye!
+ boolean removed;
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
+ mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_PROC_FINISHED,
+ app.processName, app.info.uid);
+ if (app.isolated) {
+ mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
+ }
app.setPid(0);
}
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index d2dfb0d..eda08a9 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -105,6 +105,27 @@
return data;
}
+ public void addIsolatedUid(int isolatedUid, int appUid) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.addIsolatedUidLocked(isolatedUid, appUid);
+ }
+ }
+
+ public void removeIsolatedUid(int isolatedUid, int appUid) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.removeIsolatedUidLocked(isolatedUid, appUid);
+ }
+ }
+
+ public void noteEvent(int code, String name, int uid) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.noteEventLocked(code, name, uid);
+ }
+ }
+
public void noteStartWakelock(int uid, int pid, String name, int type) {
enforceCallingPermission();
synchronized (mStats) {
@@ -496,8 +517,10 @@
private void dumpHelp(PrintWriter pw) {
pw.println("Battery stats (batterystats) dump options:");
- pw.println(" [--checkin] [-c] [--unplugged] [--reset] [--write] [-h] [<package.name>]");
+ pw.println(" [--checkin] [--history] [-c] [--unplugged] [--reset] [--write]");
+ pw.println(" [-h] [<package.name>]");
pw.println(" --checkin: format output for a checkin report.");
+ pw.println(" --history: show only history data.");
pw.println(" --unplugged: only output data since last unplugged.");
pw.println(" --reset: reset the stats, clearing all current data.");
pw.println(" --write: force write current collected stats to disk.");
@@ -517,6 +540,7 @@
boolean isCheckin = false;
boolean includeHistory = false;
+ boolean historyOnly = false;
boolean isUnpluggedOnly = false;
boolean noOutput = false;
int reqUid = -1;
@@ -524,6 +548,8 @@
for (String arg : args) {
if ("--checkin".equals(arg)) {
isCheckin = true;
+ } else if ("--history".equals(arg)) {
+ historyOnly = true;
} else if ("-c".equals(arg)) {
isCheckin = true;
includeHistory = true;
@@ -569,11 +595,12 @@
if (isCheckin) {
List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0);
synchronized (mStats) {
- mStats.dumpCheckinLocked(mContext, pw, apps, isUnpluggedOnly, includeHistory);
+ mStats.dumpCheckinLocked(mContext, pw, apps, isUnpluggedOnly, includeHistory,
+ historyOnly);
}
} else {
synchronized (mStats) {
- mStats.dumpLocked(mContext, pw, isUnpluggedOnly, reqUid);
+ mStats.dumpLocked(mContext, pw, isUnpluggedOnly, reqUid, historyOnly);
}
}
}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 217a8d61..1f0fc3a0 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -59,6 +59,7 @@
// 'persistent' is true (in which case we
// are in the process of launching the app)
ProcessStats.ProcessState baseProcessTracker;
+ BatteryStatsImpl.Uid.Proc curProcBatteryStats;
int pid; // The process of this application; 0 if none
boolean starting; // True if the process is being started
long lastActivityTime; // For managing the LRU list