Battery stats more wake history, power save mode.

Add new option for battery stats to record the full wake
lock history, and recording the current power save mode.

Also add in some additional error constants when generating
Binder error exceptions.

And fix issue #14974572: Avoid repeating wakeup_reason at
the beginning of history

Change-Id: I7c1a2ab9569de216634f63d8ad69f1294ef1d235
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 4857533..cf0caed 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -31,7 +31,6 @@
 import android.text.format.DateFormat;
 import android.util.Printer;
 import android.util.SparseArray;
-import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 import android.util.TimeUtils;
 import com.android.internal.os.BatterySipper;
@@ -601,6 +600,7 @@
         public int states;
 
         public static final int STATE2_VIDEO_ON_FLAG = 1<<0;
+        public static final int STATE2_LOW_POWER_FLAG = 1<<1;
         public int states2;
 
         // The wake lock that was acquired at this point.
@@ -622,8 +622,11 @@
         public static final int EVENT_TOP = 0x0003;
         // Event is about an application package that is at the top of the screen.
         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;
         // Number of event types.
-        public static final int EVENT_COUNT = 0x0005;
+        public static final int EVENT_COUNT = 0x0006;
         // Mask to extract out only the type part of the event.
         public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
 
@@ -635,6 +638,8 @@
         public static final int EVENT_TOP_FINISH = EVENT_TOP | EVENT_FLAG_FINISH;
         public static final int EVENT_SYNC_START = EVENT_SYNC | EVENT_FLAG_START;
         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;
 
         // For CMD_EVENT.
         public int eventCode;
@@ -887,6 +892,11 @@
             return true;
         }
 
+        public void removeEvents(int code) {
+            int idx = code&HistoryItem.EVENT_TYPE_MASK;
+            mActiveEvents[idx] = null;
+        }
+
         public HashMap<String, SparseIntArray> getStateForEvent(int code) {
             return mActiveEvents[code];
         }
@@ -997,6 +1007,21 @@
             long elapsedRealtimeUs, int which);
 
     /**
+     * Returns the time in microseconds that low power mode has been enabled while the device was
+     * running on battery.
+     *
+     * {@hide}
+     */
+    public abstract long getLowPowerModeEnabledTime(long elapsedRealtimeUs, int which);
+
+    /**
+     * Returns the number of times that low power mode was enabled.
+     *
+     * {@hide}
+     */
+    public abstract int getLowPowerModeEnabledCount(int which);
+
+    /**
      * Returns the time in microseconds that the phone has been on while the device was
      * running on battery.
      * 
@@ -1157,14 +1182,15 @@
     public static final BitDescription[] HISTORY_STATE2_DESCRIPTIONS
             = new BitDescription[] {
         new BitDescription(HistoryItem.STATE2_VIDEO_ON_FLAG, "video", "v"),
+        new BitDescription(HistoryItem.STATE2_LOW_POWER_FLAG, "low_power", "lp"),
     };
 
     public static final String[] HISTORY_EVENT_NAMES = new String[] {
-            "null", "proc", "fg", "top", "sync"
+            "null", "proc", "fg", "top", "sync", "wake_lock_in"
     };
 
     public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
-            "Enl", "Epr", "Efg", "Etp", "Esy"
+            "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl"
     };
 
     /**
@@ -1630,11 +1656,12 @@
         final long totalUptime = computeUptime(rawUptime, which);
         final long screenOnTime = getScreenOnTime(rawRealtime, which);
         final long interactiveTime = getInteractiveTime(rawRealtime, which);
+        final long lowPowerModeEnabledTime = getLowPowerModeEnabledTime(rawRealtime, which);
         final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
         final long wifiOnTime = getWifiOnTime(rawRealtime, which);
         final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
         final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which);
-       
+
         StringBuilder sb = new StringBuilder(128);
         
         SparseArray<? extends Uid> uidStats = getUidStats();
@@ -1699,7 +1726,8 @@
                 mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
                 fullWakeLockTimeTotal, partialWakeLockTimeTotal,
                 0 /*legacy input event count*/, getMobileRadioActiveTime(rawRealtime, which),
-                getMobileRadioActiveAdjustedTime(which), interactiveTime / 1000);
+                getMobileRadioActiveAdjustedTime(which), interactiveTime / 1000,
+                lowPowerModeEnabledTime / 1000);
         
         // Dump screen brightness stats
         Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
@@ -2092,32 +2120,20 @@
 
         final long screenOnTime = getScreenOnTime(rawRealtime, which);
         final long interactiveTime = getInteractiveTime(rawRealtime, which);
+        final long lowPowerModeEnabledTime = getLowPowerModeEnabledTime(rawRealtime, which);
         final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
         final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
         final long wifiOnTime = getWifiOnTime(rawRealtime, which);
         final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which);
         sb.setLength(0);
         sb.append(prefix);
-                sb.append("  Interactive: "); formatTimeMs(sb, interactiveTime / 1000);
-                sb.append("("); sb.append(formatRatioLocked(interactiveTime, whichBatteryRealtime));
-                sb.append(")");
-        pw.println(sb.toString());
-        sb.setLength(0);
-        sb.append(prefix);
                 sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
                 sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
                 sb.append(") "); sb.append(getScreenOnCount(which));
-                sb.append("x, Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
-                sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
+                sb.append("x, Interactive: "); formatTimeMs(sb, interactiveTime / 1000);
+                sb.append("("); sb.append(formatRatioLocked(interactiveTime, whichBatteryRealtime));
                 sb.append(")");
         pw.println(sb.toString());
-        if (phoneOnTime != 0) {
-            sb.setLength(0);
-            sb.append(prefix);
-                    sb.append("  Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
-                    sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
-                    sb.append(") "); sb.append(getPhoneOnCount(which));
-        }
         sb.setLength(0);
         sb.append(prefix);
         sb.append("  Screen brightnesses:");
@@ -2139,7 +2155,24 @@
         }
         if (!didOne) sb.append(" (no activity)");
         pw.println(sb.toString());
-        
+        if (lowPowerModeEnabledTime != 0) {
+            sb.setLength(0);
+            sb.append(prefix);
+                    sb.append("  Low power mode enabled: ");
+                    formatTimeMs(sb, lowPowerModeEnabledTime / 1000);
+                    sb.append("(");
+                    sb.append(formatRatioLocked(lowPowerModeEnabledTime, whichBatteryRealtime));
+                    sb.append(")");
+            pw.println(sb.toString());
+        }
+        if (phoneOnTime != 0) {
+            sb.setLength(0);
+            sb.append(prefix);
+                    sb.append("  Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
+                    sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
+                    sb.append(") "); sb.append(getPhoneOnCount(which));
+        }
+
         // Calculate wakelock times across all uids.
         long fullWakeLockTimeTotalMicros = 0;
         long partialWakeLockTimeTotalMicros = 0;
@@ -3004,6 +3037,8 @@
                 pw.print(rec.numReadInts);
                 pw.print(") ");
             } else {
+                pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+                pw.print(HISTORY_DATA); pw.print(',');
                 if (lastTime < 0) {
                     pw.print(rec.time - baseTime);
                 } else {
@@ -3190,6 +3225,7 @@
                 }
                 pw.println();
                 oldState = rec.states;
+                oldState2 = rec.states2;
             }
         }
     }
@@ -3266,21 +3302,25 @@
                     if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
                             || rec.cmd == HistoryItem.CMD_RESET) {
                         printed = true;
+                        hprinter.printNextItem(pw, rec, baseTime, checkin,
+                                (flags&DUMP_VERBOSE) != 0);
+                        rec.cmd = HistoryItem.CMD_UPDATE;
                     } else if (rec.currentTime != 0) {
                         printed = true;
                         byte cmd = rec.cmd;
                         rec.cmd = HistoryItem.CMD_CURRENT_TIME;
-                        if (checkin) {
-                            pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
-                            pw.print(HISTORY_DATA); pw.print(',');
-                        }
                         hprinter.printNextItem(pw, rec, baseTime, checkin,
                                 (flags&DUMP_VERBOSE) != 0);
                         rec.cmd = cmd;
                     }
                     if (tracker != null) {
-                        int oldCode = rec.eventCode;
-                        HistoryTag oldTag = rec.eventTag;
+                        if (rec.cmd != HistoryItem.CMD_UPDATE) {
+                            hprinter.printNextItem(pw, rec, baseTime, checkin,
+                                    (flags&DUMP_VERBOSE) != 0);
+                            rec.cmd = HistoryItem.CMD_UPDATE;
+                        }
+                        int oldEventCode = rec.eventCode;
+                        HistoryTag oldEventTag = rec.eventTag;
                         rec.eventTag = new HistoryTag();
                         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
                             HashMap<String, SparseIntArray> active
@@ -3296,24 +3336,18 @@
                                     rec.eventTag.string = ent.getKey();
                                     rec.eventTag.uid = uids.keyAt(j);
                                     rec.eventTag.poolIdx = uids.valueAt(j);
-                                    if (checkin) {
-                                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
-                                        pw.print(HISTORY_DATA); pw.print(',');
-                                    }
                                     hprinter.printNextItem(pw, rec, baseTime, checkin,
                                             (flags&DUMP_VERBOSE) != 0);
+                                    rec.wakeReasonTag = null;
+                                    rec.wakelockTag = null;
                                 }
                             }
                         }
-                        rec.eventCode = oldCode;
-                        rec.eventTag = oldTag;
+                        rec.eventCode = oldEventCode;
+                        rec.eventTag = oldEventTag;
                         tracker = null;
                     }
                 }
-                if (checkin) {
-                    pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
-                    pw.print(HISTORY_DATA); pw.print(',');
-                }
                 hprinter.printNextItem(pw, rec, baseTime, checkin,
                         (flags&DUMP_VERBOSE) != 0);
             } else if (rec.eventCode != HistoryItem.EVENT_NONE) {