Fix issue #17323751: Additional items in aggregated battery stats

- Now aggregate number of times each process has crashed and ANRed.
- Now aggregate total number of connectivity changes.
- Now record connectivity changes in the history.

Crash and ANR counts are new entries at the end of "pr" in checkin.

Connectivity change counts is a new entry at the end of "m" in checkin.

Connectivity changes in the history checkin are Ecn and include the
type of connection and its state.

Change-Id: I0c01186446034cf6c3fb97d45f5e3b5c69a0438a
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 11fc69e..5fd697a 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -459,6 +459,20 @@
             public abstract int getStarts(int which);
 
             /**
+             * Returns the number of times the process has crashed.
+             *
+             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
+             */
+            public abstract int getNumCrashes(int which);
+
+            /**
+             * Returns the number of times the process has ANRed.
+             *
+             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
+             */
+            public abstract int getNumAnrs(int which);
+
+            /**
              * Returns the cpu time spent in microseconds while the process was in the foreground.
              * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
              * @return foreground cpu time in microseconds
@@ -694,8 +708,10 @@
         public static final int EVENT_USER_RUNNING = 0x0007;
         // Events for foreground user.
         public static final int EVENT_USER_FOREGROUND = 0x0008;
+        // Events for connectivity changed.
+        public static final int EVENT_CONNECTIVITY_CHANGED = 0x0009;
         // Number of event types.
-        public static final int EVENT_COUNT = 0x0009;
+        public static final int EVENT_COUNT = 0x000a;
         // Mask to extract out only the type part of the event.
         public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
 
@@ -1107,6 +1123,13 @@
     public abstract int getLowPowerModeEnabledCount(int which);
 
     /**
+     * Returns the number of times that connectivity state changed.
+     *
+     * {@hide}
+     */
+    public abstract int getNumConnectivityChange(int which);
+
+    /**
      * Returns the time in microseconds that the phone has been on while the device was
      * running on battery.
      * 
@@ -1306,11 +1329,11 @@
     };
 
     public static final String[] HISTORY_EVENT_NAMES = new String[] {
-            "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg"
+            "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn"
     };
 
     public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
-            "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf"
+            "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn"
     };
 
     /**
@@ -1871,6 +1894,7 @@
         final long screenOnTime = getScreenOnTime(rawRealtime, which);
         final long interactiveTime = getInteractiveTime(rawRealtime, which);
         final long lowPowerModeEnabledTime = getLowPowerModeEnabledTime(rawRealtime, which);
+        final int connChanges = getNumConnectivityChange(which);
         final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
         final long wifiOnTime = getWifiOnTime(rawRealtime, which);
         final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
@@ -1941,7 +1965,7 @@
                 fullWakeLockTimeTotal / 1000, partialWakeLockTimeTotal / 1000,
                 0 /*legacy input event count*/, getMobileRadioActiveTime(rawRealtime, which) / 1000,
                 getMobileRadioActiveAdjustedTime(which) / 1000, interactiveTime / 1000,
-                lowPowerModeEnabledTime / 1000);
+                lowPowerModeEnabledTime / 1000, connChanges);
         
         // Dump screen brightness stats
         Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
@@ -2271,12 +2295,14 @@
                     final long userMillis = ps.getUserTime(which) * 10;
                     final long systemMillis = ps.getSystemTime(which) * 10;
                     final long foregroundMillis = ps.getForegroundTime(which) * 10;
-                    final long starts = ps.getStarts(which);
+                    final int starts = ps.getStarts(which);
+                    final int numCrashes = ps.getNumCrashes(which);
+                    final int numAnrs = ps.getNumAnrs(which);
 
                     if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0
-                            || starts != 0) {
+                            || starts != 0 || numAnrs != 0 || numCrashes != 0) {
                         dumpLine(pw, uid, category, PROCESS_DATA, ent.getKey(), userMillis,
-                                systemMillis, foregroundMillis, starts);
+                                systemMillis, foregroundMillis, starts, numAnrs, numCrashes);
                     }
                 }
             }
@@ -2457,6 +2483,11 @@
                     sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
                     sb.append(") "); sb.append(getPhoneOnCount(which));
         }
+        int connChanges = getNumConnectivityChange(which);
+        if (connChanges != 0) {
+            pw.print(prefix);
+            pw.print("  Connectivity changes: "); pw.println(connChanges);
+        }
 
         // Calculate wakelock times across all uids.
         long fullWakeLockTimeTotalMicros = 0;
@@ -3273,11 +3304,13 @@
                     systemTime = ps.getSystemTime(which);
                     foregroundTime = ps.getForegroundTime(which);
                     starts = ps.getStarts(which);
+                    final int numCrashes = ps.getNumCrashes(which);
+                    final int numAnrs = ps.getNumAnrs(which);
                     numExcessive = which == STATS_SINCE_CHARGED
                             ? ps.countExcessivePowers() : 0;
 
                     if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0
-                            || numExcessive != 0) {
+                            || numExcessive != 0 || numCrashes != 0 || numAnrs != 0) {
                         sb.setLength(0);
                         sb.append(prefix); sb.append("    Proc ");
                                 sb.append(ent.getKey()); sb.append(":\n");
@@ -3285,9 +3318,26 @@
                                 formatTime(sb, userTime); sb.append("usr + ");
                                 formatTime(sb, systemTime); sb.append("krn ; ");
                                 formatTime(sb, foregroundTime); sb.append("fg");
-                        if (starts != 0) {
+                        if (starts != 0 || numCrashes != 0 || numAnrs != 0) {
                             sb.append("\n"); sb.append(prefix); sb.append("      ");
-                                    sb.append(starts); sb.append(" proc starts");
+                            boolean hasOne = false;
+                            if (starts != 0) {
+                                hasOne = true;
+                                sb.append(starts); sb.append(" starts");
+                            }
+                            if (numCrashes != 0) {
+                                if (hasOne) {
+                                    sb.append(", ");
+                                }
+                                hasOne = true;
+                                sb.append(numCrashes); sb.append(" crashes");
+                            }
+                            if (numAnrs != 0) {
+                                if (hasOne) {
+                                    sb.append(", ");
+                                }
+                                sb.append(numAnrs); sb.append(" anrs");
+                            }
                         }
                         pw.println(sb.toString());
                         for (int e=0; e<numExcessive; e++) {