Merge "Set IFA_BROADCAST during IPv4 RTM_NEWADDRs"
diff --git a/adb/shell_service.cpp b/adb/shell_service.cpp
index ce10708..3eeed34 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -246,7 +246,7 @@
         char** current = environ;
         while (char* env_cstr = *current++) {
             std::string env_string = env_cstr;
-            char* delimiter = strchr(env_string.c_str(), '=');
+            char* delimiter = strchr(&env_string[0], '=');
 
             // Drop any values that don't contain '='.
             if (delimiter) {
diff --git a/adb/socket.h b/adb/socket.h
index 9eb1b19..4acdf4a 100644
--- a/adb/socket.h
+++ b/adb/socket.h
@@ -118,7 +118,7 @@
 namespace internal {
 
 #if ADB_HOST
-char* skip_host_serial(const char* service);
+char* skip_host_serial(char* service);
 #endif
 
 }  // namespace internal
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index 5cbef6d..20a3bbb 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -275,8 +275,8 @@
 
 // Checks that skip_host_serial(serial) returns a pointer to the part of |serial| which matches
 // |expected|, otherwise logs the failure to gtest.
-void VerifySkipHostSerial(const std::string& serial, const char* expected) {
-    const char* result = internal::skip_host_serial(serial.c_str());
+void VerifySkipHostSerial(std::string serial, const char* expected) {
+    char* result = internal::skip_host_serial(&serial[0]);
     if (expected == nullptr) {
         EXPECT_EQ(nullptr, result);
     } else {
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index c083ee1..aecaba2 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -634,7 +634,7 @@
 // Where <port> must be a base-10 number and <prefix> may be any of {usb,product,model,device}.
 //
 // The returned pointer will point to the ':' just before <command>, or nullptr if not found.
-char* skip_host_serial(const char* service) {
+char* skip_host_serial(char* service) {
     static const std::vector<std::string>& prefixes =
         *(new std::vector<std::string>{"usb:", "product:", "model:", "device:"});
 
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 2639d05..b819797 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -224,13 +224,23 @@
 
   time_t current_time_utc = time(nullptr);
 
-  static const char* factory_reset_current_time = "factory_reset_current_time";
   if (current_time_utc < 0) {
     // UMA does not display negative values in buckets, so convert to positive.
-    bootstat::LogHistogram(factory_reset_current_time, std::abs(current_time_utc));
+    bootstat::LogHistogram(
+        "factory_reset_current_time_failure", std::abs(current_time_utc));
+
+    // Logging via BootEventRecordStore to see if using bootstat::LogHistogram
+    // is losing records somehow.
+    boot_event_store.AddBootEventWithValue(
+        "factory_reset_current_time_failure", std::abs(current_time_utc));
     return;
   } else {
-    bootstat::LogHistogram(factory_reset_current_time, current_time_utc);
+    bootstat::LogHistogram("factory_reset_current_time", current_time_utc);
+
+    // Logging via BootEventRecordStore to see if using bootstat::LogHistogram
+    // is losing records somehow.
+    boot_event_store.AddBootEventWithValue(
+        "factory_reset_current_time", current_time_utc);
   }
 
   // The factory_reset boot event does not exist after the device is reset, so
@@ -247,6 +257,12 @@
   // factory_reset time.
   time_t factory_reset_utc = record.second;
   bootstat::LogHistogram("factory_reset_record_value", factory_reset_utc);
+
+  // Logging via BootEventRecordStore to see if using bootstat::LogHistogram
+  // is losing records somehow.
+  boot_event_store.AddBootEventWithValue(
+      "factory_reset_record_value", factory_reset_utc);
+
   time_t time_since_factory_reset = difftime(current_time_utc,
                                              factory_reset_utc);
   boot_event_store.AddBootEventWithValue("time_since_factory_reset",
diff --git a/debuggerd/signal_sender.cpp b/debuggerd/signal_sender.cpp
index 1cfb704..4be7e6e 100644
--- a/debuggerd/signal_sender.cpp
+++ b/debuggerd/signal_sender.cpp
@@ -16,6 +16,7 @@
 
 #include <errno.h>
 #include <signal.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
 #include <sys/syscall.h>
@@ -35,6 +36,31 @@
   int signal;
 };
 
+static void set_signal_sender_process_name() {
+#if defined(__LP64__)
+  static constexpr char long_process_name[] = "debuggerd64:signaller";
+  static constexpr char short_process_name[] = "debuggerd64:sig";
+  static_assert(sizeof(long_process_name) <= sizeof("/system/bin/debuggerd64"), "");
+#else
+  static constexpr char long_process_name[] = "debuggerd:signaller";
+  static constexpr char short_process_name[] = "debuggerd:sig";
+  static_assert(sizeof(long_process_name) <= sizeof("/system/bin/debuggerd"), "");
+#endif
+
+  // pthread_setname_np has a maximum length of 16 chars, including null terminator.
+  static_assert(sizeof(short_process_name) <= 16, "");
+  pthread_setname_np(pthread_self(), short_process_name);
+
+  char* progname = const_cast<char*>(getprogname());
+  if (strlen(progname) <= strlen(long_process_name)) {
+    ALOGE("debuggerd: unexpected progname %s", progname);
+    return;
+  }
+
+  memset(progname, 0, strlen(progname));
+  strcpy(progname, long_process_name);
+}
+
 // Fork a process to send signals for the worker processes to use after they've dropped privileges.
 bool start_signal_sender() {
   if (signal_pid != 0) {
@@ -56,6 +82,8 @@
   } else if (fork_pid == 0) {
     close(sfd[1]);
 
+    set_signal_sender_process_name();
+
     while (true) {
       signal_message msg;
       int rc = TEMP_FAILURE_RETRY(read(sfd[0], &msg, sizeof(msg)));
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index cc3333c..b7980d9 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -69,20 +69,22 @@
 
 /* Global Variables */
 
-static const char * g_outputFileName = NULL;
+static const char * g_outputFileName;
 // 0 means "no log rotation"
-static size_t g_logRotateSizeKBytes = 0;
+static size_t g_logRotateSizeKBytes;
 // 0 means "unbounded"
 static size_t g_maxRotatedLogs = DEFAULT_MAX_ROTATED_LOGS;
 static int g_outFD = -1;
-static size_t g_outByteCount = 0;
-static int g_printBinary = 0;
-static int g_devCount = 0;                              // >1 means multiple
+static size_t g_outByteCount;
+static int g_printBinary;
+static int g_devCount;                              // >1 means multiple
 static pcrecpp::RE* g_regex;
 // 0 means "infinite"
-static size_t g_maxCount = 0;
-static size_t g_printCount = 0;
+static size_t g_maxCount;
+static size_t g_printCount;
+static bool g_printItAnyways;
 
+// if showHelp is set, newline required in fmt statement to transition to usage
 __noreturn static void logcat_panic(bool showHelp, const char *fmt, ...) __printflike(2,3);
 
 static int openLogFile (const char *pathname)
@@ -149,16 +151,12 @@
     TEMP_FAILURE_RETRY(write(g_outFD, buf, size));
 }
 
-static bool regexOk(const AndroidLogEntry& entry, log_id_t id)
+static bool regexOk(const AndroidLogEntry& entry)
 {
-    if (! g_regex) {
+    if (!g_regex) {
         return true;
     }
 
-    if (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) {
-        return false;
-    }
-
     std::string messageString(entry.message, entry.messageLen);
 
     return g_regex->PartialMatch(messageString);
@@ -192,14 +190,16 @@
         goto error;
     }
 
-    if (android_log_shouldPrintLine(g_logformat, entry.tag, entry.priority) &&
-        regexOk(entry, buf->id())) {
-        bytesWritten = android_log_printLogLine(g_logformat, g_outFD, &entry);
+    if (android_log_shouldPrintLine(g_logformat, entry.tag, entry.priority)) {
+        bool match = regexOk(entry);
 
-        g_printCount++;
+        g_printCount += match;
+        if (match || g_printItAnyways) {
+            bytesWritten = android_log_printLogLine(g_logformat, g_outFD, &entry);
 
-        if (bytesWritten < 0) {
-            logcat_panic(false, "output error");
+            if (bytesWritten < 0) {
+                logcat_panic(false, "output error");
+            }
         }
     }
 
@@ -283,9 +283,9 @@
                     "  -f <filename>   Log to file. Default is stdout\n"
                     "  --file=<filename>\n"
                     "  -r <kbytes>     Rotate log every kbytes. Requires -f\n"
-                    "  --rotate_kbytes=<kbytes>\n"
+                    "  --rotate-kbytes=<kbytes>\n"
                     "  -n <count>      Sets max number of rotated logs to <count>, default 4\n"
-                    "  --rotate_count=<count>\n"
+                    "  --rotate-count=<count>\n"
                     "  -v <format>     Sets the log print format, where <format> is:\n"
                     "  --format=<format>\n"
                     "                      brief color epoch long monotonic printable process raw\n"
@@ -299,6 +299,8 @@
                     "  --regex <expr>  where <expr> is a regular expression\n"
                     "  -m <count>      quit after printing <count> lines. This is meant to be\n"
                     "  --max-count=<count> paired with --regex, but will work on its own.\n"
+                    "  --print         paired with --regex and --max-count to let content bypass\n"
+                    "                  regex filter but still stop at number of matches.\n"
                     "  -t <count>      print only the most recent <count> lines (implies -d)\n"
                     "  -t '<time>'     print most recent lines since specified time (implies -d)\n"
                     "  -T <count>      print only the most recent <count> lines (does not imply -d)\n"
@@ -306,9 +308,9 @@
                     "                  count is pure numerical, time is 'MM-DD hh:mm:ss.mmm...'\n"
                     "                  'YYYY-MM-DD hh:mm:ss.mmm...' or 'sssss.mmm...' format\n"
                     "  -g              get the size of the log's ring buffer and exit\n"
-                    "  --buffer_size\n"
+                    "  --buffer-size\n"
                     "  -G <size>       set size of log ring buffer, may suffix with K or M.\n"
-                    "  --buffer_size=<size>\n"
+                    "  --buffer-size=<size>\n"
                     "  -L              dump logs from prior to last reboot\n"
                     "  --last\n"
                     // Leave security (Device Owner only installations) and
@@ -564,24 +566,31 @@
         int ret;
 
         int option_index = 0;
+        // list of long-argument only strings for later comparison
         static const char pid_str[] = "pid";
         static const char wrap_str[] = "wrap";
+        static const char print_str[] = "print";
         static const struct option long_options[] = {
           { "binary",        no_argument,       NULL,   'B' },
           { "buffer",        required_argument, NULL,   'b' },
-          { "buffer_size",   optional_argument, NULL,   'g' },
+          { "buffer-size",   optional_argument, NULL,   'g' },
           { "clear",         no_argument,       NULL,   'c' },
           { "dividers",      no_argument,       NULL,   'D' },
           { "file",          required_argument, NULL,   'f' },
           { "format",        required_argument, NULL,   'v' },
+          // hidden and undocumented reserved alias for --max-count
+          { "head",          required_argument, NULL,   'm' },
           { "last",          no_argument,       NULL,   'L' },
           { pid_str,         required_argument, NULL,   0 },
           { "max-count",     required_argument, NULL,   'm' },
+          { print_str,       no_argument,       NULL,   0 },
           { "prune",         optional_argument, NULL,   'p' },
           { "regex",         required_argument, NULL,   'e' },
-          { "rotate_count",  required_argument, NULL,   'n' },
-          { "rotate_kbytes", required_argument, NULL,   'r' },
+          { "rotate-count",  required_argument, NULL,   'n' },
+          { "rotate-kbytes", required_argument, NULL,   'r' },
           { "statistics",    no_argument,       NULL,   'S' },
+          // hidden and undocumented reserved alias for -t
+          { "tail",          required_argument, NULL,   't' },
           // support, but ignore and do not document, the optional argument
           { wrap_str,        optional_argument, NULL,   0 },
           { NULL,            0,                 NULL,   0 }
@@ -623,6 +632,10 @@
                     }
                     break;
                 }
+                if (long_options[option_index].name == print_str) {
+                    g_printItAnyways = true;
+                    break;
+                }
             break;
 
             case 's':
@@ -966,7 +979,16 @@
     }
 
     if (g_maxCount && got_t) {
-        logcat_panic(true, "Cannot use -m (--max-count) and -t together");
+        logcat_panic(true, "Cannot use -m (--max-count) and -t together\n");
+    }
+    if (g_printItAnyways && (!g_regex || !g_maxCount)) {
+        // One day it would be nice if --print -v color and --regex <expr>
+        // could play with each other and show regex highlighted content.
+        fprintf(stderr, "WARNING: "
+                            "--print ignored, to be used in combination with\n"
+                        "         "
+                            "--regex <expr> and --max-count <N>\n");
+        g_printItAnyways = false;
     }
 
     if (!devices) {
@@ -1185,7 +1207,7 @@
     dev = NULL;
     log_device_t unexpected("unexpected", false);
 
-    while (!g_maxCount || g_printCount < g_maxCount) {
+    while (!g_maxCount || (g_printCount < g_maxCount)) {
         struct log_msg log_msg;
         log_device_t* d;
         int ret = android_logger_list_read(logger_list, &log_msg);