Merge changes I5fe02059,Iea8bf298,I0630c302,Ifc4b8fe9,I29319bda

* changes:
  adb: bump the local socket backlog to the maximum.
  adb: fix unicode file path test.
  adb: delete vestigial SHELL_EXIT_NOTIFY_FD.
  adb: don't immediately close a socket when write fails.
  adb: make fdevent_run_on_main_thread's fd nonblocking.
diff --git a/bootstat/boot_reason_test.sh b/bootstat/boot_reason_test.sh
index 86e8789..1043df1 100755
--- a/bootstat/boot_reason_test.sh
+++ b/bootstat/boot_reason_test.sh
@@ -239,6 +239,8 @@
   return 0
 }
 
+BAD_BOOTLOADER_REASON=
+
 [ "USAGE: EXPECT_PROPERTY <prop> <value> [--allow_failure]
 
 Returns true (0) if current return (regex) value is true and the result matches
@@ -249,9 +251,20 @@
   value="${2}"
   shift 2
   val=`adb shell getprop ${property} 2>&1`
-  EXPECT_EQ "${value}" "${val}" for Android property ${property} ||
-    [ -n "${1}" ] ||
-    save_ret=${?}
+  EXPECT_EQ "${value}" "${val}" for Android property ${property}
+  local_ret=${?}
+  if [ 0 != ${local_ret} -a "ro.boot.bootreason" = "${property}" ]; then
+    if [ -z "${BAD_BOOTLOADER_REASON}" ]; then
+      BAD_BOOTLOADER_REASON=${val}
+    elif [ X"${BAD_BOOTLOADER_REASON}" = X"${val}" ]; then
+      local_ret=0
+    fi
+  fi
+  if [ 0 != ${local_ret} ]; then
+    if [ -z "${1}" ] ; then
+      save_ret=${local_ret}
+    fi
+  fi
   return ${save_ret}
 }
 
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index cfea6ee..29988c8 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -291,6 +291,10 @@
     {"software_master", 147},
     {"cold,charger", 148},
     {"cold,rtc", 149},
+    {"cold,rtc,2sec", 150},
+    {"reboot,tool", 151},
+    {"reboot,wdt", 152},
+    {"reboot,unknown", 153},
 };
 
 // Converts a string value representing the reason the system booted to an
@@ -467,6 +471,8 @@
     }
     return std::string::npos;
   }
+
+  operator const std::string&() const { return console; }
 };
 
 // If bit error match to needle, correct it.
@@ -503,12 +509,60 @@
   return corrected;
 }
 
+// Converts a string value representing the reason the system booted to a
+// string complying with Android system standard reason.
+void transformReason(std::string& reason) {
+  std::transform(reason.begin(), reason.end(), reason.begin(), ::tolower);
+  std::transform(reason.begin(), reason.end(), reason.begin(),
+                 [](char c) { return ::isblank(c) ? '_' : c; });
+  std::transform(reason.begin(), reason.end(), reason.begin(),
+                 [](char c) { return ::isprint(c) ? c : '?'; });
+}
+
+// Pull out and correct quoted (') subreason, pos just beyond first quote.
+// Check subreasons for reboot,<subreason> and kernel_panic,sysrq,<subreason>
+std::string getSubreason(const std::string& content, size_t pos) {
+  static constexpr size_t max_reason_length = 256;
+
+  std::string subReason(content.substr(pos, max_reason_length));
+  // Correct against any known strings that Bit Error Match
+  for (const auto& s : knownReasons) {
+    correctForBitErrorOrUnderline(subReason, s);
+  }
+  for (const auto& m : kBootReasonMap) {
+    if (m.first.length() <= strlen("cold")) continue;  // too short?
+    if (correctForBitErrorOrUnderline(subReason, m.first + "'")) continue;
+    if (m.first.length() <= strlen("reboot,cold")) continue;  // short?
+    if (android::base::StartsWith(m.first, "reboot,")) {
+      correctForBitErrorOrUnderline(subReason, m.first.substr(strlen("reboot,")) + "'");
+    } else if (android::base::StartsWith(m.first, "kernel_panic,sysrq,")) {
+      correctForBitErrorOrUnderline(subReason, m.first.substr(strlen("kernel_panic,sysrq,")) + "'");
+    }
+  }
+  for (pos = 0; pos < subReason.length(); ++pos) {
+    char c = subReason[pos];
+    // #, &, %, / are common single bit error for ' that we can block
+    if (!::isprint(c) || (c == '\'') || (c == '#') || (c == '&') || (c == '%') || (c == '/')) {
+      subReason.erase(pos);
+      break;
+    }
+  }
+  transformReason(subReason);
+  return subReason;
+}
+
 bool addKernelPanicSubReason(const pstoreConsole& console, std::string& ret) {
   // Check for kernel panic types to refine information
   if ((console.rfind("SysRq : Trigger a crash") != std::string::npos) ||
       (console.rfind("PC is at sysrq_handle_crash+") != std::string::npos)) {
-    // Can not happen, except on userdebug, during testing/debugging.
     ret = "kernel_panic,sysrq";
+    // Invented for Android to allow daemons that specifically trigger sysrq
+    // to communicate more accurate boot subreasons via last console messages.
+    static constexpr char sysrqSubreason[] = "SysRq : Trigger a crash : '";
+    auto pos = console.rfind(sysrqSubreason);
+    if (pos != std::string::npos) {
+      ret += "," + getSubreason(console, pos + strlen(sysrqSubreason));
+    }
     return true;
   }
   if (console.rfind("Unable to handle kernel NULL pointer dereference at virtual address") !=
@@ -527,24 +581,12 @@
   return addKernelPanicSubReason(pstoreConsole(content), ret);
 }
 
-// Converts a string value representing the reason the system booted to a
-// string complying with Android system standard reason.
-void transformReason(std::string& reason) {
-  std::transform(reason.begin(), reason.end(), reason.begin(), ::tolower);
-  std::transform(reason.begin(), reason.end(), reason.begin(),
-                 [](char c) { return ::isblank(c) ? '_' : c; });
-  std::transform(reason.begin(), reason.end(), reason.begin(),
-                 [](char c) { return ::isprint(c) ? c : '?'; });
-}
-
 const char system_reboot_reason_property[] = "sys.boot.reason";
 const char last_reboot_reason_property[] = LAST_REBOOT_REASON_PROPERTY;
 const char bootloader_reboot_reason_property[] = "ro.boot.bootreason";
 
 // Scrub, Sanitize, Standardize and Enhance the boot reason string supplied.
 std::string BootReasonStrToReason(const std::string& boot_reason) {
-  static const size_t max_reason_length = 256;
-
   std::string ret(GetProperty(system_reboot_reason_property));
   std::string reason(boot_reason);
   // If sys.boot.reason == ro.boot.bootreason, let's re-evaluate
@@ -647,28 +689,7 @@
       static const char cmd[] = "reboot: Restarting system with command '";
       size_t pos = console.rfind(cmd);
       if (pos != std::string::npos) {
-        pos += strlen(cmd);
-        std::string subReason(content.substr(pos, max_reason_length));
-        // Correct against any known strings that Bit Error Match
-        for (const auto& s : knownReasons) {
-          correctForBitErrorOrUnderline(subReason, s);
-        }
-        for (const auto& m : kBootReasonMap) {
-          if (m.first.length() <= strlen("cold")) continue;  // too short?
-          if (correctForBitErrorOrUnderline(subReason, m.first + "'")) continue;
-          if (m.first.length() <= strlen("reboot,cold")) continue;  // short?
-          if (!android::base::StartsWith(m.first, "reboot,")) continue;
-          correctForBitErrorOrUnderline(subReason, m.first.substr(strlen("reboot,")) + "'");
-        }
-        for (pos = 0; pos < subReason.length(); ++pos) {
-          char c = subReason[pos];
-          // #, &, %, / are common single bit error for ' that we can block
-          if (!::isprint(c) || (c == '\'') || (c == '#') || (c == '&') || (c == '%') || (c == '/')) {
-            subReason.erase(pos);
-            break;
-          }
-        }
-        transformReason(subReason);
+        std::string subReason(getSubreason(content, pos + strlen(cmd)));
         if (subReason != "") {  // Will not land "reboot" as that is too blunt.
           if (isKernelRebootReason(subReason)) {
             ret = "reboot," + subReason;  // User space can't talk kernel reasons.
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 45fa863..72f9f7b 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -18,8 +18,10 @@
 
 #include <errno.h>
 #include <inttypes.h>
+#include <pwd.h>
 #include <sched.h>
 #include <signal.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/cdefs.h>
@@ -71,6 +73,9 @@
 #define ARRAY_SIZE(x)   (sizeof(x) / sizeof(*(x)))
 #define EIGHT_MEGA (1 << 23)
 
+/* Defined as ProcessList.SYSTEM_ADJ in ProcessList.java */
+#define SYSTEM_ADJ (-900)
+
 /* default to old in-kernel interface if no memory pressure events */
 static int use_inkernel_interface = 1;
 static bool has_inkernel_module;
@@ -267,24 +272,32 @@
     return 0;
 }
 
-static void writefilestring(const char *path, char *s) {
+/*
+ * Write a string to a file.
+ * Returns false if the file does not exist.
+ */
+static bool writefilestring(const char *path, const char *s,
+                            bool err_if_missing) {
     int fd = open(path, O_WRONLY | O_CLOEXEC);
-    int len = strlen(s);
-    int ret;
+    ssize_t len = strlen(s);
+    ssize_t ret;
 
     if (fd < 0) {
-        ALOGE("Error opening %s; errno=%d", path, errno);
-        return;
+        if (err_if_missing) {
+            ALOGE("Error opening %s; errno=%d", path, errno);
+        }
+        return false;
     }
 
-    ret = write(fd, s, len);
+    ret = TEMP_FAILURE_RETRY(write(fd, s, len));
     if (ret < 0) {
         ALOGE("Error writing %s; errno=%d", path, errno);
     } else if (ret < len) {
-        ALOGE("Short write on %s; length=%d", path, ret);
+        ALOGE("Short write on %s; length=%zd", path, ret);
     }
 
     close(fd);
+    return true;
 }
 
 static void cmd_procprio(LMKD_CTRL_PACKET packet) {
@@ -293,6 +306,8 @@
     char val[20];
     int soft_limit_mult;
     struct lmk_procprio params;
+    bool is_system_server;
+    struct passwd *pwdrec;
 
     lmkd_pack_get_procprio(packet, &params);
 
@@ -304,7 +319,12 @@
 
     snprintf(path, sizeof(path), "/proc/%d/oom_score_adj", params.pid);
     snprintf(val, sizeof(val), "%d", params.oomadj);
-    writefilestring(path, val);
+    if (!writefilestring(path, val, false)) {
+        ALOGW("Failed to open %s; errno=%d: process %d might have been killed",
+              path, errno, params.pid);
+        /* If this file does not exist the process is dead. */
+        return;
+    }
 
     if (use_inkernel_interface)
         return;
@@ -341,7 +361,15 @@
              "/dev/memcg/apps/uid_%d/pid_%d/memory.soft_limit_in_bytes",
              params.uid, params.pid);
     snprintf(val, sizeof(val), "%d", soft_limit_mult * EIGHT_MEGA);
-    writefilestring(path, val);
+
+    /*
+     * system_server process has no memcg under /dev/memcg/apps but should be
+     * registered with lmkd. This is the best way so far to identify it.
+     */
+    is_system_server = (params.oomadj == SYSTEM_ADJ &&
+                        (pwdrec = getpwnam("system")) != NULL &&
+                        params.uid == pwdrec->pw_uid);
+    writefilestring(path, val, !is_system_server);
 
     procp = pid_lookup(params.pid);
     if (!procp) {
@@ -408,8 +436,8 @@
             strlcat(killpriostr, val, sizeof(killpriostr));
         }
 
-        writefilestring(INKERNEL_MINFREE_PATH, minfreestr);
-        writefilestring(INKERNEL_ADJ_PATH, killpriostr);
+        writefilestring(INKERNEL_MINFREE_PATH, minfreestr, true);
+        writefilestring(INKERNEL_ADJ_PATH, killpriostr, true);
     }
 }
 
@@ -727,7 +755,7 @@
     r = kill(pid, SIGKILL);
     ALOGI(
         "Killing '%s' (%d), uid %d, adj %d\n"
-        "   to free %ldkB because system is under %s memory pressure oom_adj %d\n",
+        "   to free %ldkB because system is under %s memory pressure (min_oom_adj=%d)\n",
         taskname, pid, uid, procp->oomadj, tasksize * page_k,
         level_name[level], min_score_adj);
     pid_remove(pid);