Merge changes I1539580e,I8452e799 into pi-dev

* changes:
  Volume dialog mulit-streams have 8dp padding
  Check if alarm and now times are in schedule
diff --git a/cmds/incidentd/src/Reporter.cpp b/cmds/incidentd/src/Reporter.cpp
index 297a071..b3bab0c 100644
--- a/cmds/incidentd/src/Reporter.cpp
+++ b/cmds/incidentd/src/Reporter.cpp
@@ -22,6 +22,7 @@
 #include "report_directory.h"
 #include "section_list.h"
 
+#include <android-base/properties.h>
 #include <android/os/DropBoxManager.h>
 #include <private/android_filesystem_config.h>
 #include <utils/SystemClock.h>
@@ -31,6 +32,7 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <string>
 
 /**
  * The directory where the incident reports are stored.
@@ -129,6 +131,8 @@
     int mainDest = -1;
     HeaderSection headers;
     MetadataSection metadataSection;
+    std::string buildType = android::base::GetProperty("ro.build.type", "");
+    const bool isUserdebugOrEng = buildType == "userdebug" || buildType == "eng";
 
     // See if we need the main file
     for (ReportRequestSet::iterator it = batch.begin(); it != batch.end(); it++) {
@@ -175,6 +179,11 @@
     // and report to those that care that we're doing it.
     for (const Section** section = SECTION_LIST; *section; section++) {
         const int id = (*section)->id;
+        if ((*section)->userdebugAndEngOnly && !isUserdebugOrEng) {
+            ALOGD("Skipping incident report section %d '%s' because it's limited to userdebug/eng",
+                  id, (*section)->name.string());
+            continue;
+        }
         if (this->batch.containsSection(id)) {
             ALOGD("Taking incident report section %d '%s'", id, (*section)->name.string());
             for (ReportRequestSet::iterator it = batch.begin(); it != batch.end(); it++) {
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index e5bde0d..4bbe042 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -151,8 +151,11 @@
 }
 
 // ================================================================================
-Section::Section(int i, int64_t timeoutMs, bool deviceSpecific)
-    : id(i), timeoutMs(timeoutMs), deviceSpecific(deviceSpecific) {}
+Section::Section(int i, int64_t timeoutMs, bool userdebugAndEngOnly, bool deviceSpecific)
+    : id(i),
+      timeoutMs(timeoutMs),
+      userdebugAndEngOnly(userdebugAndEngOnly),
+      deviceSpecific(deviceSpecific) {}
 
 Section::~Section() {}
 
@@ -239,7 +242,7 @@
 
 FileSection::FileSection(int id, const char* filename, const bool deviceSpecific,
                          const int64_t timeoutMs)
-    : Section(id, timeoutMs, deviceSpecific), mFilename(filename) {
+    : Section(id, timeoutMs, false, deviceSpecific), mFilename(filename) {
     name = filename;
     mIsSysfs = isSysfs(filename);
 }
@@ -417,8 +420,8 @@
 WorkerThreadData::~WorkerThreadData() {}
 
 // ================================================================================
-WorkerThreadSection::WorkerThreadSection(int id, const int64_t timeoutMs)
-    : Section(id, timeoutMs) {}
+WorkerThreadSection::WorkerThreadSection(int id, const int64_t timeoutMs, bool userdebugAndEngOnly)
+    : Section(id, timeoutMs, userdebugAndEngOnly) {}
 
 WorkerThreadSection::~WorkerThreadSection() {}
 
@@ -615,8 +618,8 @@
 }
 
 // ================================================================================
-DumpsysSection::DumpsysSection(int id, const char* service, ...)
-    : WorkerThreadSection(id), mService(service) {
+DumpsysSection::DumpsysSection(int id, bool userdebugAndEngOnly, const char* service, ...)
+    : WorkerThreadSection(id, REMOTE_CALL_TIMEOUT_MS, userdebugAndEngOnly), mService(service) {
     name = "dumpsys ";
     name += service;
 
diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h
index 577892e..a031a15 100644
--- a/cmds/incidentd/src/Section.h
+++ b/cmds/incidentd/src/Section.h
@@ -40,10 +40,12 @@
 public:
     const int id;
     const int64_t timeoutMs;  // each section must have a timeout
+    const bool userdebugAndEngOnly;
     const bool deviceSpecific;
     String8 name;
 
-    Section(int id, int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS, bool deviceSpecific = false);
+    Section(int id, int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS, bool userdebugAndEngOnly = false,
+            bool deviceSpecific = false);
     virtual ~Section();
 
     virtual status_t Execute(ReportRequestSet* requests) const = 0;
@@ -107,7 +109,8 @@
  */
 class WorkerThreadSection : public Section {
 public:
-    WorkerThreadSection(int id, int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS);
+    WorkerThreadSection(int id, int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS,
+                        bool userdebugAndEngOnly = false);
     virtual ~WorkerThreadSection();
 
     virtual status_t Execute(ReportRequestSet* requests) const;
@@ -137,7 +140,7 @@
  */
 class DumpsysSection : public WorkerThreadSection {
 public:
-    DumpsysSection(int id, const char* service, ...);
+    DumpsysSection(int id, bool userdebugAndEngOnly, const char* service, ...);
     virtual ~DumpsysSection();
 
     virtual status_t BlockingCall(int pipeWriteFd) const;
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 1418012..9b695f9 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -366,8 +366,12 @@
 Landroid/app/job/IJobService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/job/IJobService;
 Landroid/app/job/IJobService;->startJob(Landroid/app/job/JobParameters;)V
 Landroid/app/job/IJobService;->stopJob(Landroid/app/job/JobParameters;)V
+Landroid/app/job/JobInfo$Builder;->setFlags(I)Landroid/app/job/JobInfo$Builder;
+Landroid/app/job/JobInfo$Builder;->setPriority(I)Landroid/app/job/JobInfo$Builder;
 Landroid/app/job/JobInfo;->flags:I
+Landroid/app/job/JobInfo;->FLAG_WILL_BE_FOREGROUND:I
 Landroid/app/job/JobInfo;->jobId:I
+Landroid/app/job/JobInfo;->PRIORITY_FOREGROUND_APP:I
 Landroid/app/job/JobInfo;->service:Landroid/content/ComponentName;
 Landroid/app/job/JobParameters;->callback:Landroid/os/IBinder;
 Landroid/app/job/JobParameters;->jobId:I
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 0b4b921..619ec23 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.server.ServerProtoEnums;
+import android.service.batterystats.BatteryStatsServiceDumpHistoryProto;
 import android.service.batterystats.BatteryStatsServiceDumpProto;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
@@ -6030,51 +6031,51 @@
         }
     }
 
-    static void printBitDescriptions(PrintWriter pw, int oldval, int newval, HistoryTag wakelockTag,
-            BitDescription[] descriptions, boolean longNames) {
+    static void printBitDescriptions(StringBuilder sb, int oldval, int newval,
+            HistoryTag wakelockTag, BitDescription[] descriptions, boolean longNames) {
         int diff = oldval ^ newval;
         if (diff == 0) return;
         boolean didWake = false;
         for (int i=0; i<descriptions.length; i++) {
             BitDescription bd = descriptions[i];
             if ((diff&bd.mask) != 0) {
-                pw.print(longNames ? " " : ",");
+                sb.append(longNames ? " " : ",");
                 if (bd.shift < 0) {
-                    pw.print((newval&bd.mask) != 0 ? "+" : "-");
-                    pw.print(longNames ? bd.name : bd.shortName);
+                    sb.append((newval & bd.mask) != 0 ? "+" : "-");
+                    sb.append(longNames ? bd.name : bd.shortName);
                     if (bd.mask == HistoryItem.STATE_WAKE_LOCK_FLAG && wakelockTag != null) {
                         didWake = true;
-                        pw.print("=");
+                        sb.append("=");
                         if (longNames) {
-                            UserHandle.formatUid(pw, wakelockTag.uid);
-                            pw.print(":\"");
-                            pw.print(wakelockTag.string);
-                            pw.print("\"");
+                            UserHandle.formatUid(sb, wakelockTag.uid);
+                            sb.append(":\"");
+                            sb.append(wakelockTag.string);
+                            sb.append("\"");
                         } else {
-                            pw.print(wakelockTag.poolIdx);
+                            sb.append(wakelockTag.poolIdx);
                         }
                     }
                 } else {
-                    pw.print(longNames ? bd.name : bd.shortName);
-                    pw.print("=");
+                    sb.append(longNames ? bd.name : bd.shortName);
+                    sb.append("=");
                     int val = (newval&bd.mask)>>bd.shift;
                     if (bd.values != null && val >= 0 && val < bd.values.length) {
-                        pw.print(longNames? bd.values[val] : bd.shortValues[val]);
+                        sb.append(longNames ? bd.values[val] : bd.shortValues[val]);
                     } else {
-                        pw.print(val);
+                        sb.append(val);
                     }
                 }
             }
         }
         if (!didWake && wakelockTag != null) {
-            pw.print(longNames ? " wake_lock=" : ",w=");
+            sb.append(longNames ? " wake_lock=" : ",w=");
             if (longNames) {
-                UserHandle.formatUid(pw, wakelockTag.uid);
-                pw.print(":\"");
-                pw.print(wakelockTag.string);
-                pw.print("\"");
+                UserHandle.formatUid(sb, wakelockTag.uid);
+                sb.append(":\"");
+                sb.append(wakelockTag.string);
+                sb.append("\"");
             } else {
-                pw.print(wakelockTag.poolIdx);
+                sb.append(wakelockTag.poolIdx);
             }
         }
     }
@@ -6108,339 +6109,360 @@
 
         public void printNextItem(PrintWriter pw, HistoryItem rec, long baseTime, boolean checkin,
                 boolean verbose) {
+            pw.print(printNextItem(rec, baseTime, checkin, verbose));
+        }
+
+        /** Print the next history item to proto. */
+        public void printNextItem(ProtoOutputStream proto, HistoryItem rec, long baseTime,
+                boolean verbose) {
+            String item = printNextItem(rec, baseTime, true, verbose);
+            for (String line : item.split("\n")) {
+                proto.write(BatteryStatsServiceDumpHistoryProto.CSV_LINES, line);
+            }
+        }
+
+        private String printNextItem(HistoryItem rec, long baseTime, boolean checkin,
+                boolean verbose) {
+            StringBuilder item = new StringBuilder();
             if (!checkin) {
-                pw.print("  ");
-                TimeUtils.formatDuration(rec.time - baseTime, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
-                pw.print(" (");
-                pw.print(rec.numReadInts);
-                pw.print(") ");
+                item.append("  ");
+                TimeUtils.formatDuration(
+                        rec.time - baseTime, item, TimeUtils.HUNDRED_DAY_FIELD_LEN);
+                item.append(" (");
+                item.append(rec.numReadInts);
+                item.append(") ");
             } else {
-                pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
-                pw.print(HISTORY_DATA); pw.print(',');
+                item.append(BATTERY_STATS_CHECKIN_VERSION); item.append(',');
+                item.append(HISTORY_DATA); item.append(',');
                 if (lastTime < 0) {
-                    pw.print(rec.time - baseTime);
+                    item.append(rec.time - baseTime);
                 } else {
-                    pw.print(rec.time - lastTime);
+                    item.append(rec.time - lastTime);
                 }
                 lastTime = rec.time;
             }
             if (rec.cmd == HistoryItem.CMD_START) {
                 if (checkin) {
-                    pw.print(":");
+                    item.append(":");
                 }
-                pw.println("START");
+                item.append("START\n");
                 reset();
             } else if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
                     || rec.cmd == HistoryItem.CMD_RESET) {
                 if (checkin) {
-                    pw.print(":");
+                    item.append(":");
                 }
                 if (rec.cmd == HistoryItem.CMD_RESET) {
-                    pw.print("RESET:");
+                    item.append("RESET:");
                     reset();
                 }
-                pw.print("TIME:");
+                item.append("TIME:");
                 if (checkin) {
-                    pw.println(rec.currentTime);
+                    item.append(rec.currentTime);
+                    item.append("\n");
                 } else {
-                    pw.print(" ");
-                    pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
+                    item.append(" ");
+                    item.append(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
                             rec.currentTime).toString());
+                    item.append("\n");
                 }
             } else if (rec.cmd == HistoryItem.CMD_SHUTDOWN) {
                 if (checkin) {
-                    pw.print(":");
+                    item.append(":");
                 }
-                pw.println("SHUTDOWN");
+                item.append("SHUTDOWN\n");
             } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
                 if (checkin) {
-                    pw.print(":");
+                    item.append(":");
                 }
-                pw.println("*OVERFLOW*");
+                item.append("*OVERFLOW*\n");
             } else {
                 if (!checkin) {
-                    if (rec.batteryLevel < 10) pw.print("00");
-                    else if (rec.batteryLevel < 100) pw.print("0");
-                    pw.print(rec.batteryLevel);
+                    if (rec.batteryLevel < 10) item.append("00");
+                    else if (rec.batteryLevel < 100) item.append("0");
+                    item.append(rec.batteryLevel);
                     if (verbose) {
-                        pw.print(" ");
+                        item.append(" ");
                         if (rec.states < 0) ;
-                        else if (rec.states < 0x10) pw.print("0000000");
-                        else if (rec.states < 0x100) pw.print("000000");
-                        else if (rec.states < 0x1000) pw.print("00000");
-                        else if (rec.states < 0x10000) pw.print("0000");
-                        else if (rec.states < 0x100000) pw.print("000");
-                        else if (rec.states < 0x1000000) pw.print("00");
-                        else if (rec.states < 0x10000000) pw.print("0");
-                        pw.print(Integer.toHexString(rec.states));
+                        else if (rec.states < 0x10) item.append("0000000");
+                        else if (rec.states < 0x100) item.append("000000");
+                        else if (rec.states < 0x1000) item.append("00000");
+                        else if (rec.states < 0x10000) item.append("0000");
+                        else if (rec.states < 0x100000) item.append("000");
+                        else if (rec.states < 0x1000000) item.append("00");
+                        else if (rec.states < 0x10000000) item.append("0");
+                        item.append(Integer.toHexString(rec.states));
                     }
                 } else {
                     if (oldLevel != rec.batteryLevel) {
                         oldLevel = rec.batteryLevel;
-                        pw.print(",Bl="); pw.print(rec.batteryLevel);
+                        item.append(",Bl="); item.append(rec.batteryLevel);
                     }
                 }
                 if (oldStatus != rec.batteryStatus) {
                     oldStatus = rec.batteryStatus;
-                    pw.print(checkin ? ",Bs=" : " status=");
+                    item.append(checkin ? ",Bs=" : " status=");
                     switch (oldStatus) {
                         case BatteryManager.BATTERY_STATUS_UNKNOWN:
-                            pw.print(checkin ? "?" : "unknown");
+                            item.append(checkin ? "?" : "unknown");
                             break;
                         case BatteryManager.BATTERY_STATUS_CHARGING:
-                            pw.print(checkin ? "c" : "charging");
+                            item.append(checkin ? "c" : "charging");
                             break;
                         case BatteryManager.BATTERY_STATUS_DISCHARGING:
-                            pw.print(checkin ? "d" : "discharging");
+                            item.append(checkin ? "d" : "discharging");
                             break;
                         case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
-                            pw.print(checkin ? "n" : "not-charging");
+                            item.append(checkin ? "n" : "not-charging");
                             break;
                         case BatteryManager.BATTERY_STATUS_FULL:
-                            pw.print(checkin ? "f" : "full");
+                            item.append(checkin ? "f" : "full");
                             break;
                         default:
-                            pw.print(oldStatus);
+                            item.append(oldStatus);
                             break;
                     }
                 }
                 if (oldHealth != rec.batteryHealth) {
                     oldHealth = rec.batteryHealth;
-                    pw.print(checkin ? ",Bh=" : " health=");
+                    item.append(checkin ? ",Bh=" : " health=");
                     switch (oldHealth) {
                         case BatteryManager.BATTERY_HEALTH_UNKNOWN:
-                            pw.print(checkin ? "?" : "unknown");
+                            item.append(checkin ? "?" : "unknown");
                             break;
                         case BatteryManager.BATTERY_HEALTH_GOOD:
-                            pw.print(checkin ? "g" : "good");
+                            item.append(checkin ? "g" : "good");
                             break;
                         case BatteryManager.BATTERY_HEALTH_OVERHEAT:
-                            pw.print(checkin ? "h" : "overheat");
+                            item.append(checkin ? "h" : "overheat");
                             break;
                         case BatteryManager.BATTERY_HEALTH_DEAD:
-                            pw.print(checkin ? "d" : "dead");
+                            item.append(checkin ? "d" : "dead");
                             break;
                         case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
-                            pw.print(checkin ? "v" : "over-voltage");
+                            item.append(checkin ? "v" : "over-voltage");
                             break;
                         case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
-                            pw.print(checkin ? "f" : "failure");
+                            item.append(checkin ? "f" : "failure");
                             break;
                         case BatteryManager.BATTERY_HEALTH_COLD:
-                            pw.print(checkin ? "c" : "cold");
+                            item.append(checkin ? "c" : "cold");
                             break;
                         default:
-                            pw.print(oldHealth);
+                            item.append(oldHealth);
                             break;
                     }
                 }
                 if (oldPlug != rec.batteryPlugType) {
                     oldPlug = rec.batteryPlugType;
-                    pw.print(checkin ? ",Bp=" : " plug=");
+                    item.append(checkin ? ",Bp=" : " plug=");
                     switch (oldPlug) {
                         case 0:
-                            pw.print(checkin ? "n" : "none");
+                            item.append(checkin ? "n" : "none");
                             break;
                         case BatteryManager.BATTERY_PLUGGED_AC:
-                            pw.print(checkin ? "a" : "ac");
+                            item.append(checkin ? "a" : "ac");
                             break;
                         case BatteryManager.BATTERY_PLUGGED_USB:
-                            pw.print(checkin ? "u" : "usb");
+                            item.append(checkin ? "u" : "usb");
                             break;
                         case BatteryManager.BATTERY_PLUGGED_WIRELESS:
-                            pw.print(checkin ? "w" : "wireless");
+                            item.append(checkin ? "w" : "wireless");
                             break;
                         default:
-                            pw.print(oldPlug);
+                            item.append(oldPlug);
                             break;
                     }
                 }
                 if (oldTemp != rec.batteryTemperature) {
                     oldTemp = rec.batteryTemperature;
-                    pw.print(checkin ? ",Bt=" : " temp=");
-                    pw.print(oldTemp);
+                    item.append(checkin ? ",Bt=" : " temp=");
+                    item.append(oldTemp);
                 }
                 if (oldVolt != rec.batteryVoltage) {
                     oldVolt = rec.batteryVoltage;
-                    pw.print(checkin ? ",Bv=" : " volt=");
-                    pw.print(oldVolt);
+                    item.append(checkin ? ",Bv=" : " volt=");
+                    item.append(oldVolt);
                 }
                 final int chargeMAh = rec.batteryChargeUAh / 1000;
                 if (oldChargeMAh != chargeMAh) {
                     oldChargeMAh = chargeMAh;
-                    pw.print(checkin ? ",Bcc=" : " charge=");
-                    pw.print(oldChargeMAh);
+                    item.append(checkin ? ",Bcc=" : " charge=");
+                    item.append(oldChargeMAh);
                 }
-                printBitDescriptions(pw, oldState, rec.states, rec.wakelockTag,
+                printBitDescriptions(item, oldState, rec.states, rec.wakelockTag,
                         HISTORY_STATE_DESCRIPTIONS, !checkin);
-                printBitDescriptions(pw, oldState2, rec.states2, null,
+                printBitDescriptions(item, oldState2, rec.states2, null,
                         HISTORY_STATE2_DESCRIPTIONS, !checkin);
                 if (rec.wakeReasonTag != null) {
                     if (checkin) {
-                        pw.print(",wr=");
-                        pw.print(rec.wakeReasonTag.poolIdx);
+                        item.append(",wr=");
+                        item.append(rec.wakeReasonTag.poolIdx);
                     } else {
-                        pw.print(" wake_reason=");
-                        pw.print(rec.wakeReasonTag.uid);
-                        pw.print(":\"");
-                        pw.print(rec.wakeReasonTag.string);
-                        pw.print("\"");
+                        item.append(" wake_reason=");
+                        item.append(rec.wakeReasonTag.uid);
+                        item.append(":\"");
+                        item.append(rec.wakeReasonTag.string);
+                        item.append("\"");
                     }
                 }
                 if (rec.eventCode != HistoryItem.EVENT_NONE) {
-                    pw.print(checkin ? "," : " ");
+                    item.append(checkin ? "," : " ");
                     if ((rec.eventCode&HistoryItem.EVENT_FLAG_START) != 0) {
-                        pw.print("+");
+                        item.append("+");
                     } else if ((rec.eventCode&HistoryItem.EVENT_FLAG_FINISH) != 0) {
-                        pw.print("-");
+                        item.append("-");
                     }
                     String[] eventNames = checkin ? HISTORY_EVENT_CHECKIN_NAMES
                             : HISTORY_EVENT_NAMES;
                     int idx = rec.eventCode & ~(HistoryItem.EVENT_FLAG_START
                             | HistoryItem.EVENT_FLAG_FINISH);
                     if (idx >= 0 && idx < eventNames.length) {
-                        pw.print(eventNames[idx]);
+                        item.append(eventNames[idx]);
                     } else {
-                        pw.print(checkin ? "Ev" : "event");
-                        pw.print(idx);
+                        item.append(checkin ? "Ev" : "event");
+                        item.append(idx);
                     }
-                    pw.print("=");
+                    item.append("=");
                     if (checkin) {
-                        pw.print(rec.eventTag.poolIdx);
+                        item.append(rec.eventTag.poolIdx);
                     } else {
-                        pw.append(HISTORY_EVENT_INT_FORMATTERS[idx]
+                        item.append(HISTORY_EVENT_INT_FORMATTERS[idx]
                                 .applyAsString(rec.eventTag.uid));
-                        pw.print(":\"");
-                        pw.print(rec.eventTag.string);
-                        pw.print("\"");
+                        item.append(":\"");
+                        item.append(rec.eventTag.string);
+                        item.append("\"");
                     }
                 }
-                pw.println();
+                item.append("\n");
                 if (rec.stepDetails != null) {
                     if (!checkin) {
-                        pw.print("                 Details: cpu=");
-                        pw.print(rec.stepDetails.userTime);
-                        pw.print("u+");
-                        pw.print(rec.stepDetails.systemTime);
-                        pw.print("s");
+                        item.append("                 Details: cpu=");
+                        item.append(rec.stepDetails.userTime);
+                        item.append("u+");
+                        item.append(rec.stepDetails.systemTime);
+                        item.append("s");
                         if (rec.stepDetails.appCpuUid1 >= 0) {
-                            pw.print(" (");
-                            printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid1,
+                            item.append(" (");
+                            printStepCpuUidDetails(item, rec.stepDetails.appCpuUid1,
                                     rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
                             if (rec.stepDetails.appCpuUid2 >= 0) {
-                                pw.print(", ");
-                                printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid2,
+                                item.append(", ");
+                                printStepCpuUidDetails(item, rec.stepDetails.appCpuUid2,
                                         rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
                             }
                             if (rec.stepDetails.appCpuUid3 >= 0) {
-                                pw.print(", ");
-                                printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid3,
+                                item.append(", ");
+                                printStepCpuUidDetails(item, rec.stepDetails.appCpuUid3,
                                         rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
                             }
-                            pw.print(')');
+                            item.append(')');
                         }
-                        pw.println();
-                        pw.print("                          /proc/stat=");
-                        pw.print(rec.stepDetails.statUserTime);
-                        pw.print(" usr, ");
-                        pw.print(rec.stepDetails.statSystemTime);
-                        pw.print(" sys, ");
-                        pw.print(rec.stepDetails.statIOWaitTime);
-                        pw.print(" io, ");
-                        pw.print(rec.stepDetails.statIrqTime);
-                        pw.print(" irq, ");
-                        pw.print(rec.stepDetails.statSoftIrqTime);
-                        pw.print(" sirq, ");
-                        pw.print(rec.stepDetails.statIdlTime);
-                        pw.print(" idle");
+                        item.append("\n");
+                        item.append("                          /proc/stat=");
+                        item.append(rec.stepDetails.statUserTime);
+                        item.append(" usr, ");
+                        item.append(rec.stepDetails.statSystemTime);
+                        item.append(" sys, ");
+                        item.append(rec.stepDetails.statIOWaitTime);
+                        item.append(" io, ");
+                        item.append(rec.stepDetails.statIrqTime);
+                        item.append(" irq, ");
+                        item.append(rec.stepDetails.statSoftIrqTime);
+                        item.append(" sirq, ");
+                        item.append(rec.stepDetails.statIdlTime);
+                        item.append(" idle");
                         int totalRun = rec.stepDetails.statUserTime + rec.stepDetails.statSystemTime
                                 + rec.stepDetails.statIOWaitTime + rec.stepDetails.statIrqTime
                                 + rec.stepDetails.statSoftIrqTime;
                         int total = totalRun + rec.stepDetails.statIdlTime;
                         if (total > 0) {
-                            pw.print(" (");
+                            item.append(" (");
                             float perc = ((float)totalRun) / ((float)total) * 100;
-                            pw.print(String.format("%.1f%%", perc));
-                            pw.print(" of ");
+                            item.append(String.format("%.1f%%", perc));
+                            item.append(" of ");
                             StringBuilder sb = new StringBuilder(64);
                             formatTimeMsNoSpace(sb, total*10);
-                            pw.print(sb);
-                            pw.print(")");
+                            item.append(sb);
+                            item.append(")");
                         }
-                        pw.print(", PlatformIdleStat ");
-                        pw.print(rec.stepDetails.statPlatformIdleState);
-                        pw.println();
+                        item.append(", PlatformIdleStat ");
+                        item.append(rec.stepDetails.statPlatformIdleState);
+                        item.append("\n");
 
-                        pw.print(", SubsystemPowerState ");
-                        pw.print(rec.stepDetails.statSubsystemPowerState);
-                        pw.println();
+                        item.append(", SubsystemPowerState ");
+                        item.append(rec.stepDetails.statSubsystemPowerState);
+                        item.append("\n");
                     } else {
-                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
-                        pw.print(HISTORY_DATA); pw.print(",0,Dcpu=");
-                        pw.print(rec.stepDetails.userTime);
-                        pw.print(":");
-                        pw.print(rec.stepDetails.systemTime);
+                        item.append(BATTERY_STATS_CHECKIN_VERSION); item.append(',');
+                        item.append(HISTORY_DATA); item.append(",0,Dcpu=");
+                        item.append(rec.stepDetails.userTime);
+                        item.append(":");
+                        item.append(rec.stepDetails.systemTime);
                         if (rec.stepDetails.appCpuUid1 >= 0) {
-                            printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid1,
+                            printStepCpuUidCheckinDetails(item, rec.stepDetails.appCpuUid1,
                                     rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
                             if (rec.stepDetails.appCpuUid2 >= 0) {
-                                printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid2,
+                                printStepCpuUidCheckinDetails(item, rec.stepDetails.appCpuUid2,
                                         rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
                             }
                             if (rec.stepDetails.appCpuUid3 >= 0) {
-                                printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid3,
+                                printStepCpuUidCheckinDetails(item, rec.stepDetails.appCpuUid3,
                                         rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
                             }
                         }
-                        pw.println();
-                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
-                        pw.print(HISTORY_DATA); pw.print(",0,Dpst=");
-                        pw.print(rec.stepDetails.statUserTime);
-                        pw.print(',');
-                        pw.print(rec.stepDetails.statSystemTime);
-                        pw.print(',');
-                        pw.print(rec.stepDetails.statIOWaitTime);
-                        pw.print(',');
-                        pw.print(rec.stepDetails.statIrqTime);
-                        pw.print(',');
-                        pw.print(rec.stepDetails.statSoftIrqTime);
-                        pw.print(',');
-                        pw.print(rec.stepDetails.statIdlTime);
-                        pw.print(',');
+                        item.append("\n");
+                        item.append(BATTERY_STATS_CHECKIN_VERSION); item.append(',');
+                        item.append(HISTORY_DATA); item.append(",0,Dpst=");
+                        item.append(rec.stepDetails.statUserTime);
+                        item.append(',');
+                        item.append(rec.stepDetails.statSystemTime);
+                        item.append(',');
+                        item.append(rec.stepDetails.statIOWaitTime);
+                        item.append(',');
+                        item.append(rec.stepDetails.statIrqTime);
+                        item.append(',');
+                        item.append(rec.stepDetails.statSoftIrqTime);
+                        item.append(',');
+                        item.append(rec.stepDetails.statIdlTime);
+                        item.append(',');
                         if (rec.stepDetails.statPlatformIdleState != null) {
-                            pw.print(rec.stepDetails.statPlatformIdleState);
+                            item.append(rec.stepDetails.statPlatformIdleState);
                             if (rec.stepDetails.statSubsystemPowerState != null) {
-                                pw.print(',');
+                                item.append(',');
                             }
                         }
 
                         if (rec.stepDetails.statSubsystemPowerState != null) {
-                            pw.print(rec.stepDetails.statSubsystemPowerState);
+                            item.append(rec.stepDetails.statSubsystemPowerState);
                         }
-                        pw.println();
+                        item.append("\n");
                     }
                 }
                 oldState = rec.states;
                 oldState2 = rec.states2;
             }
+
+            return item.toString();
         }
 
-        private void printStepCpuUidDetails(PrintWriter pw, int uid, int utime, int stime) {
-            UserHandle.formatUid(pw, uid);
-            pw.print("=");
-            pw.print(utime);
-            pw.print("u+");
-            pw.print(stime);
-            pw.print("s");
+        private void printStepCpuUidDetails(StringBuilder sb, int uid, int utime, int stime) {
+            UserHandle.formatUid(sb, uid);
+            sb.append("=");
+            sb.append(utime);
+            sb.append("u+");
+            sb.append(stime);
+            sb.append("s");
         }
 
-        private void printStepCpuUidCheckinDetails(PrintWriter pw, int uid, int utime, int stime) {
-            pw.print('/');
-            pw.print(uid);
-            pw.print(":");
-            pw.print(utime);
-            pw.print(":");
-            pw.print(stime);
+        private void printStepCpuUidCheckinDetails(StringBuilder sb, int uid, int utime,
+                int stime) {
+            sb.append('/');
+            sb.append(uid);
+            sb.append(":");
+            sb.append(utime);
+            sb.append(":");
+            sb.append(stime);
         }
     }
 
@@ -7046,21 +7068,30 @@
         }
     }
 
-    /** Dump #STATS_SINCE_CHARGED batterystats data to a proto. @hide */
+    /**
+     * Dump #STATS_SINCE_CHARGED batterystats data to a proto. If the flags include
+     * DUMP_INCLUDE_HISTORY or DUMP_HISTORY_ONLY, only the history will be dumped.
+     * @hide
+     */
     public void dumpProtoLocked(Context context, FileDescriptor fd, List<ApplicationInfo> apps,
-            int flags) {
+            int flags, long histStart) {
         final ProtoOutputStream proto = new ProtoOutputStream(fd);
-        final long bToken = proto.start(BatteryStatsServiceDumpProto.BATTERYSTATS);
         prepareForDumpLocked();
 
+        if ((flags & (DUMP_INCLUDE_HISTORY | DUMP_HISTORY_ONLY)) != 0) {
+            dumpProtoHistoryLocked(proto, flags, histStart);
+            proto.flush();
+            return;
+        }
+
+        final long bToken = proto.start(BatteryStatsServiceDumpProto.BATTERYSTATS);
+
         proto.write(BatteryStatsProto.REPORT_VERSION, CHECKIN_VERSION);
         proto.write(BatteryStatsProto.PARCEL_VERSION, getParcelVersion());
         proto.write(BatteryStatsProto.START_PLATFORM_VERSION, getStartPlatformVersion());
         proto.write(BatteryStatsProto.END_PLATFORM_VERSION, getEndPlatformVersion());
 
-        // History intentionally not included in proto dump.
-
-        if ((flags & (DUMP_HISTORY_ONLY | DUMP_DAILY_ONLY)) == 0) {
+        if ((flags & DUMP_DAILY_ONLY) == 0) {
             final BatteryStatsHelper helper = new BatteryStatsHelper(context, false,
                     (flags & DUMP_DEVICE_WIFI_ONLY) != 0);
             helper.create(this);
@@ -7530,6 +7561,108 @@
         }
     }
 
+    private void dumpProtoHistoryLocked(ProtoOutputStream proto, int flags, long histStart) {
+        if (!startIteratingHistoryLocked()) {
+            return;
+        }
+
+        proto.write(BatteryStatsServiceDumpHistoryProto.REPORT_VERSION, CHECKIN_VERSION);
+        proto.write(BatteryStatsServiceDumpHistoryProto.PARCEL_VERSION, getParcelVersion());
+        proto.write(BatteryStatsServiceDumpHistoryProto.START_PLATFORM_VERSION,
+                getStartPlatformVersion());
+        proto.write(BatteryStatsServiceDumpHistoryProto.END_PLATFORM_VERSION,
+                getEndPlatformVersion());
+        try {
+            long token;
+            // History string pool (HISTORY_STRING_POOL)
+            for (int i = 0; i < getHistoryStringPoolSize(); ++i) {
+                token = proto.start(BatteryStatsServiceDumpHistoryProto.KEYS);
+                proto.write(BatteryStatsServiceDumpHistoryProto.Key.INDEX, i);
+                proto.write(BatteryStatsServiceDumpHistoryProto.Key.UID, getHistoryTagPoolUid(i));
+                proto.write(BatteryStatsServiceDumpHistoryProto.Key.TAG,
+                        getHistoryTagPoolString(i));
+                proto.end(token);
+            }
+
+            // History data (HISTORY_DATA)
+            final HistoryPrinter hprinter = new HistoryPrinter();
+            final HistoryItem rec = new HistoryItem();
+            long lastTime = -1;
+            long baseTime = -1;
+            boolean printed = false;
+            HistoryEventTracker tracker = null;
+            while (getNextHistoryLocked(rec)) {
+                lastTime = rec.time;
+                if (baseTime < 0) {
+                    baseTime = lastTime;
+                }
+                if (rec.time >= histStart) {
+                    if (histStart >= 0 && !printed) {
+                        if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
+                                || rec.cmd == HistoryItem.CMD_RESET
+                                || rec.cmd == HistoryItem.CMD_START
+                                || rec.cmd == HistoryItem.CMD_SHUTDOWN) {
+                            printed = true;
+                            hprinter.printNextItem(proto, rec, baseTime,
+                                    (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;
+                            hprinter.printNextItem(proto, rec, baseTime,
+                                    (flags & DUMP_VERBOSE) != 0);
+                            rec.cmd = cmd;
+                        }
+                        if (tracker != null) {
+                            if (rec.cmd != HistoryItem.CMD_UPDATE) {
+                                hprinter.printNextItem(proto, rec, baseTime,
+                                        (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 =
+                                        tracker.getStateForEvent(i);
+                                if (active == null) {
+                                    continue;
+                                }
+                                for (HashMap.Entry<String, SparseIntArray> ent
+                                        : active.entrySet()) {
+                                    SparseIntArray uids = ent.getValue();
+                                    for (int j = 0; j < uids.size(); j++) {
+                                        rec.eventCode = i;
+                                        rec.eventTag.string = ent.getKey();
+                                        rec.eventTag.uid = uids.keyAt(j);
+                                        rec.eventTag.poolIdx = uids.valueAt(j);
+                                        hprinter.printNextItem(proto, rec, baseTime,
+                                                (flags & DUMP_VERBOSE) != 0);
+                                        rec.wakeReasonTag = null;
+                                        rec.wakelockTag = null;
+                                    }
+                                }
+                            }
+                            rec.eventCode = oldEventCode;
+                            rec.eventTag = oldEventTag;
+                            tracker = null;
+                        }
+                    }
+                    hprinter.printNextItem(proto, rec, baseTime,
+                            (flags & DUMP_VERBOSE) != 0);
+                }
+            }
+            if (histStart >= 0) {
+                commitCurrentHistoryBatchLocked();
+                proto.write(BatteryStatsServiceDumpHistoryProto.CSV_LINES,
+                        "NEXT: " + (lastTime + 1));
+            }
+        } finally {
+            finishIteratingHistoryLocked();
+        }
+    }
+
     private void dumpProtoSystemLocked(ProtoOutputStream proto, BatteryStatsHelper helper) {
         final long sToken = proto.start(BatteryStatsProto.SYSTEM);
         final long rawUptimeUs = SystemClock.uptimeMillis() * 1000;
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 84ae20b..05b613c 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -240,6 +240,14 @@
     }
 
     /** @hide Just for debugging; not internationalized. */
+    public static void formatDuration(long duration, StringBuilder builder, int fieldLen) {
+        synchronized (sFormatSync) {
+            int len = formatDurationLocked(duration, fieldLen);
+            builder.append(sFormatStr, 0, len);
+        }
+    }
+
+    /** @hide Just for debugging; not internationalized. */
     public static void formatDuration(long duration, PrintWriter pw, int fieldLen) {
         synchronized (sFormatSync) {
             int len = formatDurationLocked(duration, fieldLen);
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 64e1239..3aea3a7 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -18,6 +18,7 @@
 option java_multiple_files = true;
 
 import "frameworks/base/core/proto/android/os/backtrace.proto";
+import "frameworks/base/core/proto/android/os/batterystats.proto";
 import "frameworks/base/core/proto/android/os/batterytype.proto";
 import "frameworks/base/core/proto/android/os/cpufreq.proto";
 import "frameworks/base/core/proto/android/os/cpuinfo.proto";
@@ -289,6 +290,14 @@
         (section).args = "usb --proto"
     ];
 
+    // The history can be large and may cause issues in consumers, so put the
+    // history in a separate section to compensate.
+    optional android.service.batterystats.BatteryStatsServiceDumpHistoryProto battery_history = 3022 [
+        (section).type = SECTION_DUMPSYS,
+        (section).args = "batterystats --proto --history",
+        (section).userdebug_and_eng_only = true
+    ];
+
     // Reserved for OEMs.
     extensions 50000 to 100000;
 }
diff --git a/core/proto/android/service/batterystats.proto b/core/proto/android/service/batterystats.proto
index 5586263..25b47d3 100644
--- a/core/proto/android/service/batterystats.proto
+++ b/core/proto/android/service/batterystats.proto
@@ -23,8 +23,34 @@
 import "frameworks/base/core/proto/android/os/batterystats.proto";
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
+// Dump of batterystats aggregate data (dumpsys batterystats --proto).
 message BatteryStatsServiceDumpProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional android.os.BatteryStatsProto batterystats = 1;
 }
+
+// Dump of batterystats history data (dumpsys batterystats --proto --history).
+message BatteryStatsServiceDumpHistoryProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional int32 report_version = 1;
+    optional int64 parcel_version = 2;
+    optional string start_platform_version = 3;
+    optional string end_platform_version = 4;
+
+    // HistoryStringPool data
+    message Key {
+        option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+        optional int32 index = 1;
+        // Not valid for all keys.
+        optional int32 uid = 2;
+        optional string tag = 3;
+    }
+    repeated Key keys = 5;
+
+    // Dump of battery history in csv format (equivalent of
+    // 'batterystats -c --history', with the hsp lines extracted).
+    repeated string csv_lines = 6;
+}
diff --git a/libs/incident/proto/android/section.proto b/libs/incident/proto/android/section.proto
index e8280ed..45f3c91 100644
--- a/libs/incident/proto/android/section.proto
+++ b/libs/incident/proto/android/section.proto
@@ -52,6 +52,9 @@
   optional SectionType type = 1 [default = SECTION_NONE];
   optional string args = 2;
   optional bool device_specific = 3 [default = false];
+  // If true, then the section will only be generated for userdebug and eng
+  // builds.
+  optional bool userdebug_and_eng_only = 4 [default = false];
 }
 
 extend google.protobuf.FieldOptions {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 8a8bafa..38a90cf 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -207,8 +207,12 @@
         boolean structureEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
                 Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
 
-        final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                .getAssistIntent(structureEnabled);
+        final SearchManager searchManager =
+            (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
+        if (searchManager == null) {
+            return;
+        }
+        final Intent intent = searchManager.getAssistIntent(structureEnabled);
         if (intent == null) {
             return;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index c6bb17c..065e9cc 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -198,7 +198,13 @@
             showWarningNotification();
             mShowing = SHOWING_WARNING;
         } else if (mShowAutoSaverSuggestion) {
-            showAutoSaverSuggestionNotification();
+            // Once we showed the notification, don't show it again until it goes SHOWING_NOTHING.
+            // This shouldn't be needed, because we have a delete intent on this notification
+            // so when it's dismissed we should notice it and clear mShowAutoSaverSuggestion,
+            // However we double check here just in case the dismiss intent broadcast is delayed.
+            if (mShowing != SHOWING_AUTO_SAVER_SUGGESTION) {
+                showAutoSaverSuggestionNotification();
+            }
             mShowing = SHOWING_AUTO_SAVER_SUGGESTION;
         } else {
             mNoMan.cancelAsUser(TAG_BATTERY, SystemMessage.NOTE_BAD_CHARGER, UserHandle.ALL);
@@ -303,7 +309,9 @@
 
     private PendingIntent pendingBroadcast(String action) {
         return PendingIntent.getBroadcastAsUser(mContext, 0,
-                new Intent(action).setPackage(mContext.getPackageName()), 0, UserHandle.CURRENT);
+                new Intent(action).setPackage(mContext.getPackageName())
+                    .setFlags(Intent.FLAG_RECEIVER_FOREGROUND),
+                0, UserHandle.CURRENT);
     }
 
     private static Intent settings(String action) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 227f2d2..8a0d7e3 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -129,13 +129,6 @@
     private final int mImageWidth;
     private final int mImageHeight;
 
-    // WORKAROUND: We want the same notification across screenshots that we update so that we don't
-    // spam a user's notification drawer.  However, we only show the ticker for the saving state
-    // and if the ticker text is the same as the previous notification, then it will not show. So
-    // for now, we just add and remove a space from the ticker text to trigger the animation when
-    // necessary.
-    private static boolean mTickerAddSpace;
-
     SaveImageInBackgroundTask(Context context, SaveImageInBackgroundData data,
             NotificationManager nManager) {
         Resources r = context.getResources();
@@ -176,8 +169,6 @@
         Bitmap icon = generateAdjustedHwBitmap(data.image, iconSize, iconSize, matrix, paint,
                 overlayColor);
 
-        // Show the intermediate notification
-        mTickerAddSpace = !mTickerAddSpace;
         mNotificationManager = nManager;
         final long now = System.currentTimeMillis();
 
@@ -199,8 +190,6 @@
 
         mNotificationBuilder = new Notification.Builder(context,
                 NotificationChannels.SCREENSHOTS_HEADSUP)
-            .setTicker(r.getString(R.string.screenshot_saving_ticker)
-                    + (mTickerAddSpace ? " " : ""))
             .setContentTitle(r.getString(R.string.screenshot_saving_title))
             .setSmallIcon(R.drawable.stat_notify_image)
             .setWhen(now)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 27fa48a..8adf4bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -2599,6 +2599,9 @@
 
     @Override
     protected boolean disallowSingleClick(MotionEvent event) {
+        if (areGutsExposed()) {
+            return false;
+        }
         float x = event.getX();
         float y = event.getY();
         NotificationHeaderView header = getVisibleNotificationHeader();
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 0f42103..27eae57 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -78,9 +78,13 @@
     int mDisplayId;
     Display mDisplay;
 
-    /** All of the stacks on this display. Order matters, topmost stack is in front of all other
-     * stacks, bottommost behind. Accessed directly by ActivityManager package classes */
+    /**
+     * All of the stacks on this display. Order matters, topmost stack is in front of all other
+     * stacks, bottommost behind. Accessed directly by ActivityManager package classes. Any calls
+     * changing the list should also call {@link #onStackOrderChanged()}.
+     */
     private final ArrayList<ActivityStack> mStacks = new ArrayList<>();
+    private ArrayList<OnStackOrderChangedListener> mStackOrderChangedCallbacks = new ArrayList<>();
 
     /** Array of all UIDs that are present on the display. */
     private IntArray mDisplayAccessUIDs = new IntArray();
@@ -145,6 +149,7 @@
         mStacks.remove(stack);
         removeStackReferenceIfNeeded(stack);
         mSupervisor.mService.updateSleepIfNeededLocked();
+        onStackOrderChanged();
     }
 
     void positionChildAtTop(ActivityStack stack) {
@@ -163,6 +168,7 @@
         mStacks.add(insertPosition, stack);
         mWindowContainerController.positionChildAt(stack.getWindowContainerController(),
                 insertPosition);
+        onStackOrderChanged();
     }
 
     private int getTopInsertPosition(ActivityStack stack, int candidatePosition) {
@@ -770,6 +776,30 @@
         mSleeping = asleep;
     }
 
+    /**
+     * Adds a listener to be notified whenever the stack order in the display changes. Currently
+     * only used by the {@link RecentsAnimation} to determine whether to interrupt and cancel the
+     * current animation when the system state changes.
+     */
+    void registerStackOrderChangedListener(OnStackOrderChangedListener listener) {
+        if (!mStackOrderChangedCallbacks.contains(listener)) {
+            mStackOrderChangedCallbacks.add(listener);
+        }
+    }
+
+    /**
+     * Removes a previously registered stack order change listener.
+     */
+    void unregisterStackOrderChangedListener(OnStackOrderChangedListener listener) {
+        mStackOrderChangedCallbacks.remove(listener);
+    }
+
+    private void onStackOrderChanged() {
+        for (int i = mStackOrderChangedCallbacks.size() - 1; i >= 0; i--) {
+            mStackOrderChangedCallbacks.get(i).onStackOrderChanged();
+        }
+    }
+
     public void dump(PrintWriter pw, String prefix) {
         pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + mStacks.size());
         final String myPrefix = prefix + " ";
@@ -806,4 +836,11 @@
         }
         proto.end(token);
     }
+
+    /**
+     * Callback for when the order of the stacks in the display changes.
+     */
+    interface OnStackOrderChangedListener {
+        void onStackOrderChanged();
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a8e63f6..9de876e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5291,14 +5291,9 @@
         final int callingPid = Binder.getCallingPid();
         final long origId = Binder.clearCallingIdentity();
         try {
-            final int recentsUid;
-            final String recentsPackage;
-            final List<IBinder> topVisibleActivities;
             synchronized (this) {
                 final ComponentName recentsComponent = mRecentTasks.getRecentsComponent();
-                recentsPackage = recentsComponent.getPackageName();
-                recentsUid = mRecentTasks.getRecentsComponentUid();
-                topVisibleActivities = mStackSupervisor.getTopVisibleActivities();
+                final int recentsUid = mRecentTasks.getRecentsComponentUid();
 
                 // Start a new recents animation
                 final RecentsAnimation anim = new RecentsAnimation(this, mStackSupervisor,
@@ -5314,13 +5309,14 @@
     @Override
     public void cancelRecentsAnimation(boolean restoreHomeStackPosition) {
         enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "cancelRecentsAnimation()");
+        final long callingUid = Binder.getCallingUid();
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
                 // Cancel the recents animation synchronously (do not hold the WM lock)
                 mWindowManager.cancelRecentsAnimationSynchronously(restoreHomeStackPosition
                         ? REORDER_MOVE_TO_ORIGINAL_POSITION
-                        : REORDER_KEEP_IN_PLACE, "cancelRecentsAnimation");
+                        : REORDER_KEEP_IN_PLACE, "cancelRecentsAnimation/uid=" + callingUid);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 0c328a8..ef23a83 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -1214,11 +1214,12 @@
 
     private void dumpHelp(PrintWriter pw) {
         pw.println("Battery stats (batterystats) dump options:");
-        pw.println("  [--checkin] [--history] [--history-start] [--charged] [-c]");
+        pw.println("  [--checkin] [--proto] [--history] [--history-start] [--charged] [-c]");
         pw.println("  [--daily] [--reset] [--write] [--new-daily] [--read-daily] [-h] [<package.name>]");
         pw.println("  --checkin: generate output for a checkin report; will write (and clear) the");
         pw.println("             last old completed stats when they had been reset.");
         pw.println("  -c: write the current stats in checkin format.");
+        pw.println("  --proto: write the current aggregate stats (without history) in proto format.");
         pw.println("  --history: show only history data.");
         pw.println("  --history-start <num>: show only history data starting at given time offset.");
         pw.println("  --charged: only output data since last charged.");
@@ -1431,7 +1432,8 @@
                                         null, mStats.mHandler, null, mUserManagerUserInfoProvider);
                                 checkinStats.readSummaryFromParcel(in);
                                 in.recycle();
-                                checkinStats.dumpProtoLocked(mContext, fd, apps, flags);
+                                checkinStats.dumpProtoLocked(
+                                        mContext, fd, apps, flags, historyStart);
                                 mStats.mCheckinFile.delete();
                                 return;
                             }
@@ -1444,7 +1446,7 @@
             }
             if (DBG) Slog.d(TAG, "begin dumpProtoLocked from UID " + Binder.getCallingUid());
             synchronized (mStats) {
-                mStats.dumpProtoLocked(mContext, fd, apps, flags);
+                mStats.dumpProtoLocked(mContext, fd, apps, flags, historyStart);
                 if (writeData) {
                     mStats.writeAsyncLocked();
                 }
diff --git a/services/core/java/com/android/server/am/RecentsAnimation.java b/services/core/java/com/android/server/am/RecentsAnimation.java
index a88f408..a3d2173 100644
--- a/services/core/java/com/android/server/am/RecentsAnimation.java
+++ b/services/core/java/com/android/server/am/RecentsAnimation.java
@@ -49,7 +49,8 @@
  * Manages the recents animation, including the reordering of the stacks for the transition and
  * cleanup. See {@link com.android.server.wm.RecentsAnimationController}.
  */
-class RecentsAnimation implements RecentsAnimationCallbacks {
+class RecentsAnimation implements RecentsAnimationCallbacks,
+        ActivityDisplay.OnStackOrderChangedListener {
     private static final String TAG = RecentsAnimation.class.getSimpleName();
     // TODO (b/73188263): Reset debugging flags
     private static final boolean DEBUG = true;
@@ -140,13 +141,11 @@
                         recentsUid, recentsComponent.getPackageName());
             }
 
-            final ActivityDisplay display;
             if (hasExistingActivity) {
                 // Move the recents activity into place for the animation if it is not top most
-                display = targetActivity.getDisplay();
-                display.moveStackBehindBottomMostVisibleStack(targetStack);
+                mDefaultDisplay.moveStackBehindBottomMostVisibleStack(targetStack);
                 if (DEBUG) Slog.d(TAG, "Moved stack=" + targetStack + " behind stack="
-                            + display.getStackAbove(targetStack));
+                            + mDefaultDisplay.getStackAbove(targetStack));
 
                 // If there are multiple tasks in the target stack (ie. the home stack, with 3p
                 // and default launchers coexisting), then move the task to the top as a part of
@@ -173,7 +172,6 @@
 
                 targetActivity = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
                         mTargetActivityType).getTopActivity();
-                display = targetActivity.getDisplay();
 
                 // TODO: Maybe wait for app to draw in this particular case?
 
@@ -190,7 +188,8 @@
             mWindowManager.cancelRecentsAnimationSynchronously(REORDER_MOVE_TO_ORIGINAL_POSITION,
                     "startRecentsActivity");
             mWindowManager.initializeRecentsAnimation(mTargetActivityType, recentsAnimationRunner,
-                    this, display.mDisplayId, mStackSupervisor.mRecentTasks.getRecentTaskIds());
+                    this, mDefaultDisplay.mDisplayId,
+                    mStackSupervisor.mRecentTasks.getRecentTaskIds());
 
             // If we updated the launch-behind state, update the visibility of the activities after
             // we fetch the visible tasks to be controlled by the animation
@@ -198,6 +197,9 @@
 
             mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunched(START_TASK_TO_FRONT,
                     targetActivity);
+
+            // Register for stack order changes
+            mDefaultDisplay.registerStackOrderChangedListener(this);
         } catch (Exception e) {
             Slog.e(TAG, "Failed to start recents activity", e);
             throw e;
@@ -219,6 +221,9 @@
                 mAssistDataRequester = null;
             }
 
+            // Unregister for stack order changes
+            mDefaultDisplay.unregisterStackOrderChangedListener(this);
+
             if (mWindowManager.getRecentsAnimationController() == null) return;
 
             // Just to be sure end the launch hint in case the target activity was never launched.
@@ -316,6 +321,14 @@
         }
     }
 
+    @Override
+    public void onStackOrderChanged() {
+        // If the activity display stack order changes, cancel any running recents animation in
+        // place
+        mWindowManager.cancelRecentsAnimationSynchronously(REORDER_KEEP_IN_PLACE,
+                "stackOrderChanged");
+    }
+
     /**
      * Called only when the animation should be canceled prior to starting.
      */
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 8bf0945..c276938 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -9444,6 +9444,17 @@
         mPackageUsage.writeNow(mPackages);
         mCompilerStats.writeNow();
         mDexManager.writePackageDexUsageNow();
+
+        // This is the last chance to write out pending restriction settings
+        synchronized (mPackages) {
+            if (mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
+                mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS);
+                for (int userId : mDirtyUsers) {
+                    mSettings.writePackageRestrictionsLPr(userId);
+                }
+                mDirtyUsers.clear();
+            }
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 18f3434..e6d851b 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -6092,14 +6092,6 @@
                 && (!isNavBarVirtKey || mNavBarVirtualKeyHapticFeedbackEnabled)
                 && event.getRepeatCount() == 0;
 
-        // Cancel any pending remote recents animations before handling the button itself. In the
-        // case where we are going home and the recents animation has already started, just cancel
-        // the recents animation, leaving the home stack in place for the pending start activity
-        if (isNavBarVirtKey && !down && !canceled) {
-            boolean isHomeKey = keyCode == KeyEvent.KEYCODE_HOME;
-            mActivityManagerInternal.cancelRecentsAnimation(!isHomeKey);
-        }
-
         // Handle special keys.
         switch (keyCode) {
             case KeyEvent.KEYCODE_BACK: {
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index 4b8dcc1..01425ed 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -565,6 +565,47 @@
                 false /* displaySleeping */, false /* expected*/);
     }
 
+    @Test
+    public void testStackOrderChangedOnRemoveStack() throws Exception {
+        StackOrderChangedListener listener = new StackOrderChangedListener();
+        mDefaultDisplay.registerStackOrderChangedListener(listener);
+        try {
+            mDefaultDisplay.removeChild(mStack);
+        } finally {
+            mDefaultDisplay.unregisterStackOrderChangedListener(listener);
+        }
+        assertTrue(listener.changed);
+    }
+
+    @Test
+    public void testStackOrderChangedOnAddPositionStack() throws Exception {
+        mDefaultDisplay.removeChild(mStack);
+
+        StackOrderChangedListener listener = new StackOrderChangedListener();
+        mDefaultDisplay.registerStackOrderChangedListener(listener);
+        try {
+            mDefaultDisplay.addChild(mStack, 0);
+        } finally {
+            mDefaultDisplay.unregisterStackOrderChangedListener(listener);
+        }
+        assertTrue(listener.changed);
+    }
+
+    @Test
+    public void testStackOrderChangedOnPositionStack() throws Exception {
+        StackOrderChangedListener listener = new StackOrderChangedListener();
+        try {
+            final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
+                    mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                    true /* onTop */);
+            mDefaultDisplay.registerStackOrderChangedListener(listener);
+            mDefaultDisplay.positionChildAtBottom(fullscreenStack1);
+        } finally {
+            mDefaultDisplay.unregisterStackOrderChangedListener(listener);
+        }
+        assertTrue(listener.changed);
+    }
+
     private void verifyShouldSleepActivities(boolean focusedStack,
             boolean keyguardGoingAway, boolean displaySleeping, boolean expected) {
         mSupervisor.mFocusedStack = focusedStack ? mStack : null;
@@ -578,4 +619,13 @@
 
         assertEquals(expected, mStack.shouldSleepActivities());
     }
+
+    private class StackOrderChangedListener implements ActivityDisplay.OnStackOrderChangedListener {
+        boolean changed = false;
+
+        @Override
+        public void onStackOrderChanged() {
+            changed = true;
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java b/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java
new file mode 100644
index 0000000..eefd973
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.IRecentsAnimationRunner;
+import com.android.server.AttributeCache;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * atest FrameworksServicesTests:RecentsAnimationTest
+ */
+@MediumTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class RecentsAnimationTest extends ActivityTestsBase {
+    private static final int TEST_CALLING_PID = 3;
+
+    private Context mContext = InstrumentationRegistry.getContext();
+    private ActivityManagerService mService;
+    private ComponentName mRecentsComponent;
+
+    @Before
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        mRecentsComponent = new ComponentName(mContext.getPackageName(), "RecentsActivity");
+        mService = setupActivityManagerService(new MyTestActivityManagerService(mContext));
+        AttributeCache.init(mContext);
+    }
+
+    @Test
+    public void testCancelAnimationOnStackOrderChange() throws Exception {
+        ActivityStack fullscreenStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        ActivityStack recentsStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS, true /* onTop */);
+        ActivityRecord recentsActivity = new ActivityBuilder(mService)
+                .setComponent(mRecentsComponent)
+                .setCreateTask(true)
+                .setStack(recentsStack)
+                .build();
+        ActivityStack fullscreenStack2 = mService.mStackSupervisor.getDefaultDisplay().createStack(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        ActivityRecord fsActivity = new ActivityBuilder(mService)
+                .setComponent(new ComponentName(mContext.getPackageName(), "App1"))
+                .setCreateTask(true)
+                .setStack(fullscreenStack2)
+                .build();
+        doReturn(true).when(mService.mWindowManager).canStartRecentsAnimation();
+
+        // Start the recents animation
+        Intent recentsIntent = new Intent();
+        recentsIntent.setComponent(mRecentsComponent);
+        mService.startRecentsActivity(recentsIntent, null, mock(IRecentsAnimationRunner.class));
+
+        fullscreenStack.moveToFront("Activity start");
+
+        // Ensure that the recents animation was canceled
+        verify(mService.mWindowManager, times(1)).cancelRecentsAnimationSynchronously(
+                eq(REORDER_KEEP_IN_PLACE), any());
+    }
+
+    private class MyTestActivityManagerService extends TestActivityManagerService {
+        MyTestActivityManagerService(Context context) {
+            super(context);
+        }
+
+        @Override
+        protected RecentTasks createRecentTasks() {
+            RecentTasks recents = mock(RecentTasks.class);
+            doReturn(mRecentsComponent).when(recents).getRecentsComponent();
+            System.out.println(mRecentsComponent);
+            return recents;
+        }
+    }
+}
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index 3f9588a..4e202df 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-
 #include <frameworks/base/core/proto/android/os/incident.pb.h>
 
 #include <map>
 #include <set>
-#include <string>
 #include <sstream>
+#include <string>
 
 using namespace android;
 using namespace android::os;
@@ -422,7 +421,8 @@
                 printf(" NULL),\n");
                 break;
             case SECTION_DUMPSYS:
-                printf("    new DumpsysSection(%d,", field->number());
+                printf("    new DumpsysSection(%d, \"%s\",", field->number(),
+                       s.userdebug_and_eng_only() ? "true" : "false");
                 splitAndPrint(s.args());
                 printf(" NULL),\n");
                 break;