Implement user-settable power save whitelist.

The whitelist is now maintained by DeviceIdleController,
which is moving out into its own independent system service.
Network stats now queries it for the whitelist, instead of
collecting that itself.

Also did a few improvements in alarm manager -- made the
code for moving alarms out of the pending list more robust,
and fixed the debug output to always print the contents of
the pending list even if we aren't in a pending state.  (That
would have helped me identify the problem much earlier.)

Change-Id: I0f7119d4c553c3af4d77b2f71246fa6e2c13c561
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 0e3867d..745c190 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -461,7 +461,7 @@
     // to run during this time are placed in mPendingWhileIdleAlarms
     Alarm mPendingIdleUntil = null;
     Alarm mNextWakeFromIdle = null;
-    final ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>();
+    ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>();
 
     public AlarmManagerService(Context context) {
         super(context);
@@ -567,10 +567,14 @@
 
     void restorePendingWhileIdleAlarmsLocked() {
         // Bring pending alarms back into the main list.
-        final long nowElapsed = SystemClock.elapsedRealtime();
-        for (int i=mPendingWhileIdleAlarms.size() - 1; i >= 0 && mPendingIdleUntil == null; i--) {
-            Alarm a = mPendingWhileIdleAlarms.remove(i);
-            reAddAlarmLocked(a, nowElapsed, false);
+        if (mPendingWhileIdleAlarms.size() > 0) {
+            ArrayList<Alarm> alarms = mPendingWhileIdleAlarms;
+            mPendingWhileIdleAlarms = new ArrayList<>();
+            final long nowElapsed = SystemClock.elapsedRealtime();
+            for (int i=alarms.size() - 1; i >= 0; i--) {
+                Alarm a = alarms.get(i);
+                reAddAlarmLocked(a, nowElapsed, false);
+            }
         }
 
         // Reschedule everything.
@@ -1053,11 +1057,16 @@
                     dumpAlarmList(pw, b.alarms, "  ", nowELAPSED, nowRTC, sdf);
                 }
             }
-            if (mPendingIdleUntil != null) {
+            if (mPendingIdleUntil != null || mPendingWhileIdleAlarms.size() > 0) {
                 pw.println();
                 pw.println("Idle mode state:");
-                pw.print("  Idling until: "); pw.println(mPendingIdleUntil);
-                mPendingIdleUntil.dump(pw, "    ", nowRTC, nowELAPSED, sdf);
+                pw.print("  Idling until: ");
+                if (mPendingIdleUntil != null) {
+                    pw.println(mPendingIdleUntil);
+                    mPendingIdleUntil.dump(pw, "    ", nowRTC, nowELAPSED, sdf);
+                } else {
+                    pw.println("null");
+                }
                 pw.println("  Pending alarms:");
                 dumpAlarmList(pw, mPendingWhileIdleAlarms, "    ", nowELAPSED, nowRTC, sdf);
             }