Merge "adb: setsid() for adb host server."
diff --git a/bootstat/Android.mk b/bootstat/Android.mk
index bbb903d..c6349c1 100644
--- a/bootstat/Android.mk
+++ b/bootstat/Android.mk
@@ -32,6 +32,7 @@
 
 bootstat_shared_libs := \
         libbase \
+        libcutils \
         liblog
 
 bootstat_cflags := \
diff --git a/bootstat/README.md b/bootstat/README.md
index 1b4bf7f..b3964ce 100644
--- a/bootstat/README.md
+++ b/bootstat/README.md
@@ -7,10 +7,11 @@
 
     Usage: bootstat [options]
     options include:
-      -d              Dump the boot event records to the console.
-      -h              Show this help.
-      -l              Log all metrics to logstorage.
-      -r              Record the relative time of a named boot event.
+      -h, --help            Show this help
+      -l, --log             Log all metrics to logstorage
+      -p, --print           Dump the boot event records to the console
+      -r, --record          Record the timestamp of a named boot event
+      --record_boot_reason  Record the reason why the device booted
 
 ## Relative time ##
 
diff --git a/bootstat/boot_event_record_store.cpp b/bootstat/boot_event_record_store.cpp
index 1bdcf2b..22a67bb 100644
--- a/bootstat/boot_event_record_store.cpp
+++ b/bootstat/boot_event_record_store.cpp
@@ -56,19 +56,31 @@
     LOG(ERROR) << "Failed to read /proc/uptime";
   }
 
+  // Cast intentionally rounds down.
+  int32_t uptime = static_cast<int32_t>(strtod(uptime_str.c_str(), NULL));
+  AddBootEventWithValue(name, uptime);
+}
+
+// The implementation of AddBootEventValue makes use of the mtime file
+// attribute to store the value associated with a boot event in order to
+// optimize on-disk size requirements and small-file thrashing.
+void BootEventRecordStore::AddBootEventWithValue(
+    const std::string& name, int32_t value) {
   std::string record_path = GetBootEventPath(name);
   if (creat(record_path.c_str(), S_IRUSR | S_IWUSR) == -1) {
     PLOG(ERROR) << "Failed to create " << record_path;
   }
 
+  // Fill out the stat structure for |record_path| in order to get the atime to
+  // set in the utime() call.
   struct stat file_stat;
   if (stat(record_path.c_str(), &file_stat) == -1) {
     PLOG(ERROR) << "Failed to read " << record_path;
   }
 
-  // Cast intentionally rounds down.
-  time_t uptime = static_cast<time_t>(strtod(uptime_str.c_str(), NULL));
-  struct utimbuf times = {file_stat.st_atime, uptime};
+  // Set the |modtime| of the file to store the value of the boot event while
+  // preserving the |actime| (as read by stat).
+  struct utimbuf times = {/* actime */ file_stat.st_atime, /* modtime */ value};
   if (utime(record_path.c_str(), &times) == -1) {
     PLOG(ERROR) << "Failed to set mtime for " << record_path;
   }
diff --git a/bootstat/boot_event_record_store.h b/bootstat/boot_event_record_store.h
index 77978ef..d1b7835 100644
--- a/bootstat/boot_event_record_store.h
+++ b/bootstat/boot_event_record_store.h
@@ -37,6 +37,10 @@
   // Persists the boot event named |name| in the record store.
   void AddBootEvent(const std::string& name);
 
+  // Persists the boot event named |name| with the associated |value| in the
+  // record store.
+  void AddBootEventWithValue(const std::string& name, int32_t value);
+
   // Returns a list of all of the boot events persisted in the record store.
   std::vector<BootEventRecord> GetAllBootEvents() const;
 
@@ -45,6 +49,7 @@
   // more test-friendly path.
   FRIEND_TEST(BootEventRecordStoreTest, AddSingleBootEvent);
   FRIEND_TEST(BootEventRecordStoreTest, AddMultipleBootEvents);
+  FRIEND_TEST(BootEventRecordStoreTest, AddBootEventWithValue);
 
   // Sets the filesystem path of the record store.
   void SetStorePath(const std::string& path);
diff --git a/bootstat/boot_event_record_store_test.cpp b/bootstat/boot_event_record_store_test.cpp
index 384f84d..3e6d706 100644
--- a/bootstat/boot_event_record_store_test.cpp
+++ b/bootstat/boot_event_record_store_test.cpp
@@ -154,3 +154,15 @@
     EXPECT_TRUE(FuzzUptimeEquals(uptime, *i));
   }
 }
+
+TEST_F(BootEventRecordStoreTest, AddBootEventWithValue) {
+  BootEventRecordStore store;
+  store.SetStorePath(GetStorePathForTesting());
+
+  store.AddBootEventWithValue("permian", 42);
+
+  auto events = store.GetAllBootEvents();
+  ASSERT_EQ(1U, events.size());
+  EXPECT_EQ("permian", events[0].first);
+  EXPECT_EQ(42, events[0].second);
+}
\ No newline at end of file
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index a83f8ad..31c84c7 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -18,14 +18,15 @@
 // timestamp, dump the persisted events, and log all events to EventLog to be
 // uploaded to Android log storage via Tron.
 
-//#define LOG_TAG "bootstat"
-
+#include <getopt.h>
 #include <unistd.h>
 #include <cstddef>
 #include <cstdio>
+#include <map>
 #include <memory>
 #include <string>
 #include <android-base/logging.h>
+#include <cutils/properties.h>
 #include <log/log.h>
 #include "boot_event_record_store.h"
 #include "event_log_list_builder.h"
@@ -35,7 +36,7 @@
 // Builds an EventLog buffer named |event| containing |data| and writes
 // the log into the Tron histogram logs.
 void LogBootEvent(const std::string& event, int32_t data) {
-  LOG(INFO) << "Logging boot time: " << event << " " << data;
+  LOG(INFO) << "Logging boot metric: " << event << " " << data;
 
   EventLogListBuilder log_builder;
   log_builder.Append(event);
@@ -74,10 +75,11 @@
   fprintf(stderr, "Usage: %s [options]\n", cmd);
   fprintf(stderr,
           "options include:\n"
-          "  -d              Dump the boot event records to the console.\n"
-          "  -h              Show this help.\n"
-          "  -l              Log all metrics to logstorage.\n"
-          "  -r              Record the timestamp of a named boot event.\n");
+          "  -h, --help            Show this help\n"
+          "  -l, --log             Log all metrics to logstorage\n"
+          "  -p, --print           Dump the boot event records to the console\n"
+          "  -r, --record          Record the timestamp of a named boot event\n"
+          "  --record_boot_reason  Record the reason why the device booted\n");
 }
 
 // Constructs a readable, printable string from the givencommand line
@@ -92,6 +94,61 @@
   return cmd;
 }
 
+// Convenience wrapper over the property API that returns an
+// std::string.
+std::string GetProperty(const char* key) {
+  std::vector<char> temp(PROPERTY_VALUE_MAX);
+  const int len = property_get(key, &temp[0], nullptr);
+  if (len < 0) {
+    return "";
+  }
+  return std::string(&temp[0], len);
+}
+
+// A mapping from boot reason string, as read from the ro.boot.bootreason
+// system property, to a unique integer ID. Viewers of log data dashboards for
+// the boot_reason metric may refer to this mapping to discern the histogram
+// values.
+const std::map<std::string, int> kBootReasonMap = {
+  {"normal", 0},
+  {"recovery", 1},
+  {"reboot", 2},
+  {"PowerKey", 3},
+  {"hard_reset", 4},
+  {"kernel_panic", 5},
+  {"rpm_err", 6},
+  {"hw_reset", 7},
+  {"tz_err", 8},
+  {"adsp_err", 9},
+  {"modem_err", 10},
+  {"mba_err", 11},
+  {"Watchdog", 12},
+  {"Panic", 13},
+};
+
+// Converts a string value representing the reason the system booted to an
+// integer representation. This is necessary for logging the boot_reason metric
+// via Tron, which does not accept non-integer buckets in histograms.
+int32_t BootReasonStrToEnum(const std::string& boot_reason) {
+  static const int32_t kUnknownBootReason = -1;
+
+  auto mapping = kBootReasonMap.find(boot_reason);
+  if (mapping != kBootReasonMap.end()) {
+    return mapping->second;
+  }
+
+  LOG(INFO) << "Unknown boot reason: " << boot_reason;
+  return kUnknownBootReason;
+}
+
+// Records the boot_reason metric by querying the ro.boot.bootreason system
+// property.
+void RecordBootReason() {
+  int32_t boot_reason = BootReasonStrToEnum(GetProperty("ro.boot.bootreason"));
+  BootEventRecordStore boot_event_store;
+  boot_event_store.AddBootEventWithValue("boot_reason", boot_reason);
+}
+
 }  // namespace
 
 int main(int argc, char **argv) {
@@ -100,9 +157,31 @@
   const std::string cmd_line = GetCommandLine(argc, argv);
   LOG(INFO) << "Service started: " << cmd_line;
 
+  int option_index = 0;
+  static const char boot_reason_str[] = "record_boot_reason";
+  static const struct option long_options[] = {
+    { "help",            no_argument,       NULL,   'h' },
+    { "log",             no_argument,       NULL,   'l' },
+    { "print",           no_argument,       NULL,   'p' },
+    { "record",          required_argument, NULL,   'r' },
+    { boot_reason_str,   no_argument,       NULL,   0 },
+    { NULL,              0,                 NULL,   0 }
+  };
+
   int opt = 0;
-  while ((opt = getopt(argc, argv, "hlpr:")) != -1) {
+  while ((opt = getopt_long(argc, argv, "hlpr:", long_options, &option_index)) != -1) {
     switch (opt) {
+      // This case handles long options which have no single-character mapping.
+      case 0: {
+        const std::string option_name = long_options[option_index].name;
+        if (option_name == boot_reason_str) {
+          RecordBootReason();
+        } else {
+          LOG(ERROR) << "Invalid option: " << option_name;
+        }
+        break;
+      }
+
       case 'h': {
         ShowHelp(argv[0]);
         break;
diff --git a/bootstat/bootstat.rc b/bootstat/bootstat.rc
index 2c37dd2..218b9f8 100644
--- a/bootstat/bootstat.rc
+++ b/bootstat/bootstat.rc
@@ -10,5 +10,8 @@
     # Record boot_complete timing event.
     exec - root root -- /system/bin/bootstat -r boot_complete
 
+    # Record the boot reason.
+    exec - root root -- /system/bin/bootstat --record_boot_reason
+
     # Log all boot events.
     exec - root root -- /system/bin/bootstat -l
diff --git a/logd/LogUtils.h b/logd/LogUtils.h
index fd4800e..aa4b6e1 100644
--- a/logd/LogUtils.h
+++ b/logd/LogUtils.h
@@ -17,6 +17,7 @@
 #ifndef _LOGD_LOG_UTILS_H__
 #define _LOGD_LOG_UTILS_H__
 
+#include <sys/cdefs.h>
 #include <sys/types.h>
 
 #include <log/log.h>
@@ -29,6 +30,7 @@
 
 // Furnished in main.cpp. Caller must own and free returned value
 char *uidToName(uid_t uid);
+void prdebug(const char *fmt, ...) __printflike(1, 2);
 
 // Furnished in LogStatistics.cpp. Caller must own and free returned value
 char *pidToName(pid_t pid);
diff --git a/logd/main.cpp b/logd/main.cpp
index ba56e57..9cec313 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -211,10 +211,32 @@
     return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
 }
 
-// Remove the static, and use this variable
-// globally for debugging if necessary. eg:
-//   write(fdDmesg, "I am here\n", 10);
 static int fdDmesg = -1;
+void inline android::prdebug(const char *fmt, ...) {
+    if (fdDmesg < 0) {
+        return;
+    }
+
+    static const char message[] = {
+        KMSG_PRIORITY(LOG_DEBUG), 'l', 'o', 'g', 'd', ':', ' '
+    };
+    char buffer[256];
+    memcpy(buffer, message, sizeof(message));
+
+    va_list ap;
+    va_start(ap, fmt);
+    int n = vsnprintf(buffer + sizeof(message),
+                      sizeof(buffer) - sizeof(message), fmt, ap);
+    va_end(ap);
+    if (n > 0) {
+        buffer[sizeof(buffer) - 1] = '\0';
+        if (!strchr(buffer, '\n')) {
+            buffer[sizeof(buffer) - 2] = '\0';
+            strlcat(buffer, "\n", sizeof(buffer));
+        }
+        write(fdDmesg, buffer, strlen(buffer));
+    }
+}
 
 static sem_t uidName;
 static uid_t uid;
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 52716e9..9ade759 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -80,10 +80,16 @@
 
 $(LOCAL_PATH)/getevent.c: $(intermediates)/input.h-labels.h
 
+UAPI_INPUT_EVENT_CODES_H := bionic/libc/kernel/uapi/linux/input-event-codes.h
 INPUT_H_LABELS_H := $(intermediates)/input.h-labels.h
 $(INPUT_H_LABELS_H): PRIVATE_LOCAL_PATH := $(LOCAL_PATH)
-$(INPUT_H_LABELS_H): PRIVATE_CUSTOM_TOOL = $(PRIVATE_LOCAL_PATH)/generate-input.h-labels.py > $@
-$(INPUT_H_LABELS_H): $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/generate-input.h-labels.py
+# The PRIVATE_CUSTOM_TOOL line uses = to evaluate the output path late.
+# We copy the input path so it can't be accidentally modified later.
+$(INPUT_H_LABELS_H): PRIVATE_UAPI_INPUT_EVENT_CODES_H := $(UAPI_INPUT_EVENT_CODES_H)
+$(INPUT_H_LABELS_H): PRIVATE_CUSTOM_TOOL = $(PRIVATE_LOCAL_PATH)/generate-input.h-labels.py $(PRIVATE_UAPI_INPUT_EVENT_CODES_H) > $@
+# The dependency line though gets evaluated now, so the PRIVATE_ copy doesn't exist yet,
+# and the original can't yet have been modified, so this is both sufficient and necessary.
+$(INPUT_H_LABELS_H): $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/generate-input.h-labels.py $(UAPI_INPUT_EVENT_CODES_H)
 $(INPUT_H_LABELS_H):
 	$(transform-generated-source)
 
diff --git a/toolbox/generate-input.h-labels.py b/toolbox/generate-input.h-labels.py
index ebb9588..30485a0 100755
--- a/toolbox/generate-input.h-labels.py
+++ b/toolbox/generate-input.h-labels.py
@@ -18,6 +18,7 @@
 
 import os
 import re
+import sys
 
 input_prop_list = []
 ev_list = []
@@ -36,7 +37,7 @@
 
 r = re.compile(r'#define\s+(\S+)\s+((?:0x)?\d+)')
 
-with open('bionic/libc/kernel/uapi/linux/input.h', 'r') as f:
+with open(sys.argv[1], 'r') as f:
   for line in f:
     m = r.match(line)
     if m: