Add dumpsys of recent wakeup patterns, for analysis
Keeps one day of alarm history, and for each one puts a line in dumpsys:
RTC timestamp, millis since previous wakeup alarm, uid, and intent action
Bug 9532215
Change-Id: Ib4fb41aa6291a4cf8f3301bfebf7974e99a9d52c
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index bc06561..0be9ca5 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -53,7 +53,7 @@
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
-import java.util.Iterator;
+import java.util.LinkedList;
import java.util.Map;
import java.util.TimeZone;
@@ -69,6 +69,7 @@
private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << AlarmManager.ELAPSED_REALTIME_WAKEUP;
private static final int ELAPSED_REALTIME_MASK = 1 << AlarmManager.ELAPSED_REALTIME;
private static final int TIME_CHANGED_MASK = 1 << 16;
+ private static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK;
// Alignment quantum for inexact repeating alarms
private static final long QUANTUM = AlarmManager.INTERVAL_FIFTEEN_MINUTES;
@@ -82,6 +83,8 @@
private static final Intent mBackgroundIntent
= new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND);
+ private static final boolean WAKEUP_STATS = true;
+
private final Context mContext;
private final LocalLog mLog = new LocalLog(TAG);
@@ -106,6 +109,21 @@
private final PendingIntent mTimeTickSender;
private final PendingIntent mDateChangeSender;
+ class WakeupEvent {
+ public long when;
+ public int uid;
+ public String action;
+
+ public WakeupEvent(long theTime, int theUid, String theAction) {
+ when = theTime;
+ uid = theUid;
+ action = theAction;
+ }
+ }
+
+ private final LinkedList<WakeupEvent> mRecentWakeups = new LinkedList<WakeupEvent>();
+ private final long RECENT_WAKEUP_PERIOD = 1000L * 60 * 60 * 24; // one day
+
private static final class InFlight extends Intent {
final PendingIntent mPendingIntent;
final Pair<String, ComponentName> mTarget;
@@ -640,6 +658,27 @@
pw.println();
}
}
+
+ if (WAKEUP_STATS) {
+ pw.println();
+ pw.println(" Recent Wakeup History:");
+ final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss.SSS");
+ long last = -1;
+ for (WakeupEvent event : mRecentWakeups) {
+ pw.print(" "); pw.print(sdf.format(new Date(event.when)));
+ pw.print('|');
+ if (last < 0) {
+ pw.print('0');
+ } else {
+ pw.print(event.when - last);
+ }
+ last = event.when;
+ pw.print('|'); pw.print(event.uid);
+ pw.print('|'); pw.print(event.action);
+ pw.println();
+ }
+ pw.println();
+ }
}
}
@@ -775,7 +814,20 @@
pw.print(prefix); pw.print("operation="); pw.println(operation);
}
}
-
+
+ void recordWakeupAlarms(ArrayList<Alarm> alarms, long now, long skewToRTC) {
+ for (Alarm a : alarms) {
+ if (a.when > now) {
+ break;
+ }
+
+ WakeupEvent e = new WakeupEvent(now + skewToRTC,
+ a.operation.getCreatorUid(),
+ a.operation.getIntent().getAction());
+ mRecentWakeups.add(e);
+ }
+ }
+
private class AlarmThread extends Thread
{
public AlarmThread()
@@ -809,6 +861,27 @@
TAG, "Checking for alarms... rtc=" + nowRTC
+ ", elapsed=" + nowELAPSED);
+ if (WAKEUP_STATS) {
+ if ((result & IS_WAKEUP_MASK) != 0) {
+ long newEarliest = nowRTC - RECENT_WAKEUP_PERIOD;
+ int n = 0;
+ for (WakeupEvent event : mRecentWakeups) {
+ if (event.when > newEarliest) break;
+ n++; // number of now-stale entries at the list head
+ }
+ for (int i = 0; i < n; i++) {
+ mRecentWakeups.remove();
+ }
+
+ recordWakeupAlarms(mRtcWakeupAlarms,
+ nowRTC,
+ 0);
+ recordWakeupAlarms(mElapsedRealtimeWakeupAlarms,
+ nowELAPSED,
+ nowRTC - nowELAPSED);
+ }
+ }
+
if ((result & RTC_WAKEUP_MASK) != 0)
triggerAlarmsLocked(mRtcWakeupAlarms, triggerList, nowRTC);