Merge "fs_mgr: change the log level in fs_mgr_read_fstab_dt()"
diff --git a/base/file.cpp b/base/file.cpp
index 81b04d7..378a405 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -212,6 +212,20 @@
 }
 #endif
 
+#if !defined(_WIN32)
+bool Realpath(const std::string& path, std::string* result) {
+  result->clear();
+
+  char* realpath_buf = realpath(path.c_str(), nullptr);
+  if (realpath_buf == nullptr) {
+    return false;
+  }
+  result->assign(realpath_buf);
+  free(realpath_buf);
+  return true;
+}
+#endif
+
 std::string GetExecutablePath() {
 #if defined(__linux__)
   std::string path;
diff --git a/base/file_test.cpp b/base/file_test.cpp
index 1021326..266131e 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -159,6 +159,38 @@
 #endif
 }
 
+TEST(file, Realpath) {
+#if !defined(_WIN32)
+  TemporaryDir td;
+  std::string basename = android::base::Basename(td.path);
+  std::string dir_name = android::base::Dirname(td.path);
+  std::string base_dir_name = android::base::Basename(dir_name);
+
+  {
+    std::string path = dir_name + "/../" + base_dir_name + "/" + basename;
+    std::string result;
+    ASSERT_TRUE(android::base::Realpath(path, &result));
+    ASSERT_EQ(td.path, result);
+  }
+
+  {
+    std::string path = std::string(td.path) + "/..";
+    std::string result;
+    ASSERT_TRUE(android::base::Realpath(path, &result));
+    ASSERT_EQ(dir_name, result);
+  }
+
+  {
+    errno = 0;
+    std::string path = std::string(td.path) + "/foo.noent";
+    std::string result = "wrong";
+    ASSERT_TRUE(!android::base::Realpath(path, &result));
+    ASSERT_TRUE(result.empty());
+    ASSERT_EQ(ENOENT, errno);
+  }
+#endif
+}
+
 TEST(file, GetExecutableDirectory) {
   std::string path = android::base::GetExecutableDirectory();
   ASSERT_NE("", path);
diff --git a/base/include/android-base/file.h b/base/include/android-base/file.h
index 33d1ab3..651f529 100644
--- a/base/include/android-base/file.h
+++ b/base/include/android-base/file.h
@@ -47,6 +47,7 @@
 bool RemoveFileIfExists(const std::string& path, std::string* err = nullptr);
 
 #if !defined(_WIN32)
+bool Realpath(const std::string& path, std::string* result);
 bool Readlink(const std::string& path, std::string* result);
 #endif
 
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index b385ea5..2d6c7f5 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -1,5 +1,6 @@
 cc_defaults {
     name: "debuggerd_defaults",
+    defaults: ["linux_bionic_supported"],
     cflags: [
         "-Wall",
         "-Wextra",
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 38b711f..88f390b 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -27,6 +27,7 @@
 #include <unistd.h>
 
 #include <limits>
+#include <map>
 #include <memory>
 #include <set>
 #include <vector>
@@ -36,6 +37,7 @@
 #include <android-base/parseint.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <cutils/sockets.h>
 #include <log/log.h>
@@ -52,7 +54,21 @@
 #include "debuggerd/util.h"
 
 using android::base::unique_fd;
+using android::base::ReadFileToString;
 using android::base::StringPrintf;
+using android::base::Trim;
+
+static std::string get_process_name(pid_t pid) {
+  std::string result = "<unknown>";
+  ReadFileToString(StringPrintf("/proc/%d/cmdline", pid), &result);
+  return result;
+}
+
+static std::string get_thread_name(pid_t tid) {
+  std::string result = "<unknown>";
+  ReadFileToString(StringPrintf("/proc/%d/comm", tid), &result);
+  return Trim(result);
+}
 
 static bool pid_contains_tid(int pid_proc_fd, pid_t tid) {
   struct stat st;
@@ -253,7 +269,7 @@
   }
 
   // Seize the siblings.
-  std::set<pid_t> attached_siblings;
+  std::map<pid_t, std::string> threads;
   {
     std::set<pid_t> siblings;
     if (!android::procinfo::GetProcessTids(target, &siblings)) {
@@ -269,12 +285,12 @@
       if (!ptrace_seize_thread(target_proc_fd, sibling_tid, &attach_error)) {
         LOG(WARNING) << attach_error;
       } else {
-        attached_siblings.insert(sibling_tid);
+        threads.emplace(sibling_tid, get_thread_name(sibling_tid));
       }
     }
   }
 
-  // Collect the backtrace map and open files, while the process still has PR_GET_DUMPABLE=1
+  // Collect the backtrace map, open files, and process/thread names, while we still have caps.
   std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(main_tid));
   if (!backtrace_map) {
     LOG(FATAL) << "failed to create backtrace map";
@@ -284,6 +300,9 @@
   OpenFilesList open_files;
   populate_open_files_list(target, &open_files);
 
+  std::string process_name = get_process_name(main_tid);
+  threads.emplace(main_tid, get_thread_name(main_tid));
+
   // Drop our capabilities now that we've attached to the threads we care about.
   drop_capabilities();
 
@@ -341,10 +360,10 @@
 
   std::string amfd_data;
   if (backtrace) {
-    dump_backtrace(output_fd.get(), backtrace_map.get(), target, main_tid, attached_siblings, 0);
+    dump_backtrace(output_fd.get(), backtrace_map.get(), target, main_tid, process_name, threads, 0);
   } else {
     engrave_tombstone(output_fd.get(), backtrace_map.get(), &open_files, target, main_tid,
-                      &attached_siblings, abort_address, fatal_signal ? &amfd_data : nullptr);
+                      process_name, threads, abort_address, fatal_signal ? &amfd_data : nullptr);
   }
 
   // We don't actually need to PTRACE_DETACH, as long as our tracees aren't in
diff --git a/debuggerd/libdebuggerd/backtrace.cpp b/debuggerd/libdebuggerd/backtrace.cpp
index df49aef..334d97f 100644
--- a/debuggerd/libdebuggerd/backtrace.cpp
+++ b/debuggerd/libdebuggerd/backtrace.cpp
@@ -38,18 +38,7 @@
 
 #include "utility.h"
 
-static void dump_process_header(log_t* log, pid_t pid) {
-  char path[PATH_MAX];
-  char procnamebuf[1024];
-  char* procname = NULL;
-  FILE* fp;
-
-  snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
-  if ((fp = fopen(path, "r"))) {
-    procname = fgets(procnamebuf, sizeof(procnamebuf), fp);
-    fclose(fp);
-  }
-
+static void dump_process_header(log_t* log, pid_t pid, const char* process_name) {
   time_t t = time(NULL);
   struct tm tm;
   localtime_r(&t, &tm);
@@ -57,8 +46,8 @@
   strftime(timestr, sizeof(timestr), "%F %T", &tm);
   _LOG(log, logtype::BACKTRACE, "\n\n----- pid %d at %s -----\n", pid, timestr);
 
-  if (procname) {
-    _LOG(log, logtype::BACKTRACE, "Cmd line: %s\n", procname);
+  if (process_name) {
+    _LOG(log, logtype::BACKTRACE, "Cmd line: %s\n", process_name);
   }
   _LOG(log, logtype::BACKTRACE, "ABI: '%s'\n", ABI_STRING);
 }
@@ -67,28 +56,13 @@
   _LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid);
 }
 
-static void log_thread_name(log_t* log, pid_t tid) {
-  FILE* fp;
-  char buf[1024];
-  char path[PATH_MAX];
-  char* threadname = NULL;
-
-  snprintf(path, sizeof(path), "/proc/%d/comm", tid);
-  if ((fp = fopen(path, "r"))) {
-    threadname = fgets(buf, sizeof(buf), fp);
-    fclose(fp);
-    if (threadname) {
-      size_t len = strlen(threadname);
-      if (len && threadname[len - 1] == '\n') {
-          threadname[len - 1] = '\0';
-      }
-    }
-  }
-  _LOG(log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", threadname ? threadname : "<unknown>", tid);
+static void log_thread_name(log_t* log, pid_t tid, const char* thread_name) {
+  _LOG(log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", thread_name, tid);
 }
 
-static void dump_thread(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid) {
-  log_thread_name(log, tid);
+static void dump_thread(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid,
+                        const std::string& thread_name) {
+  log_thread_name(log, tid, thread_name.c_str());
 
   std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map));
   if (backtrace->Unwind(0)) {
@@ -99,17 +73,21 @@
   }
 }
 
-void dump_backtrace(int fd, BacktraceMap* map, pid_t pid, pid_t tid,
-                    const std::set<pid_t>& siblings, std::string* amfd_data) {
+void dump_backtrace(int fd, BacktraceMap* map, pid_t pid, pid_t tid, const std::string& process_name,
+                    const std::map<pid_t, std::string>& threads, std::string* amfd_data) {
   log_t log;
   log.tfd = fd;
   log.amfd_data = amfd_data;
 
-  dump_process_header(&log, pid);
-  dump_thread(&log, map, pid, tid);
+  dump_process_header(&log, pid, process_name.c_str());
+  dump_thread(&log, map, pid, tid, threads.find(tid)->second.c_str());
 
-  for (pid_t sibling : siblings) {
-    dump_thread(&log, map, pid, sibling);
+  for (const auto& it : threads) {
+    pid_t thread_tid = it.first;
+    const std::string& thread_name = it.second;
+    if (thread_tid != tid) {
+      dump_thread(&log, map, pid, thread_tid, thread_name.c_str());
+    }
   }
 
   dump_process_footer(&log, pid);
@@ -123,7 +101,9 @@
   log.tfd = output_fd;
   log.amfd_data = nullptr;
 
-  log_thread_name(&log, tid);
+  char thread_name[16];
+  read_with_default("/proc/self/comm", thread_name, sizeof(thread_name), "<unknown>");
+  log_thread_name(&log, tid, thread_name);
 
   std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid));
   if (backtrace->Unwind(0, ucontext)) {
@@ -139,7 +119,9 @@
   log.tfd = output_fd;
   log.amfd_data = nullptr;
 
-  dump_process_header(&log, getpid());
+  char process_name[128];
+  read_with_default("/proc/self/cmdline", process_name, sizeof(process_name), "<unknown>");
+  dump_process_header(&log, getpid(), process_name);
 }
 
 void dump_backtrace_footer(int output_fd) {
diff --git a/debuggerd/libdebuggerd/include/backtrace.h b/debuggerd/libdebuggerd/include/backtrace.h
index 5bfdac8..fe738f1 100644
--- a/debuggerd/libdebuggerd/include/backtrace.h
+++ b/debuggerd/libdebuggerd/include/backtrace.h
@@ -20,7 +20,7 @@
 #include <sys/types.h>
 #include <sys/ucontext.h>
 
-#include <set>
+#include <map>
 #include <string>
 
 #include "utility.h"
@@ -30,8 +30,8 @@
 
 // Dumps a backtrace using a format similar to what Dalvik uses so that the result
 // can be intermixed in a bug report.
-void dump_backtrace(int fd, BacktraceMap* map, pid_t pid, pid_t tid,
-                    const std::set<pid_t>& siblings, std::string* amfd_data);
+void dump_backtrace(int fd, BacktraceMap* map, pid_t pid, pid_t tid, const std::string& process_name,
+                    const std::map<pid_t, std::string>& threads, std::string* amfd_data);
 
 /* Dumps the backtrace in the backtrace data structure to the log. */
 void dump_backtrace_to_log(Backtrace* backtrace, log_t* log, const char* prefix);
diff --git a/debuggerd/libdebuggerd/include/tombstone.h b/debuggerd/libdebuggerd/include/tombstone.h
index d2a4a4b..79743b6 100644
--- a/debuggerd/libdebuggerd/include/tombstone.h
+++ b/debuggerd/libdebuggerd/include/tombstone.h
@@ -20,7 +20,8 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <sys/types.h>
-#include <set>
+
+#include <map>
 #include <string>
 
 #include "open_files_list.h"
@@ -34,9 +35,9 @@
 int open_tombstone(std::string* path);
 
 /* Creates a tombstone file and writes the crash dump to it. */
-void engrave_tombstone(int tombstone_fd, BacktraceMap* map,
-                       const OpenFilesList* open_files, pid_t pid, pid_t tid,
-                       const std::set<pid_t>* siblings, uintptr_t abort_msg_address,
+void engrave_tombstone(int tombstone_fd, BacktraceMap* map, const OpenFilesList* open_files,
+                       pid_t pid, pid_t tid, const std::string& process_name,
+                       const std::map<pid_t, std::string>& threads, uintptr_t abort_msg_address,
                        std::string* amfd_data);
 
 void engrave_tombstone_ucontext(int tombstone_fd, uintptr_t abort_msg_address, siginfo_t* siginfo,
diff --git a/debuggerd/libdebuggerd/include/utility.h b/debuggerd/libdebuggerd/include/utility.h
index bbc4546..e5e5106 100644
--- a/debuggerd/libdebuggerd/include/utility.h
+++ b/debuggerd/libdebuggerd/include/utility.h
@@ -83,4 +83,6 @@
 
 void dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* fmt, ...);
 
+void read_with_default(const char* path, char* buf, size_t len, const char* default_value);
+
 #endif // _DEBUGGERD_UTILITY_H
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index c05ccc3..c23da44 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -32,8 +32,10 @@
 #include <memory>
 #include <string>
 
-#include <android/log.h>
+#include <android-base/file.h>
 #include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <android/log.h>
 #include <backtrace/Backtrace.h>
 #include <backtrace/BacktraceMap.h>
 #include <cutils/properties.h>
@@ -247,41 +249,16 @@
   dump_signal_info(log, &si);
 }
 
-static void dump_thread_info(log_t* log, pid_t pid, pid_t tid) {
-  char path[64];
-  char threadnamebuf[1024];
-  char* threadname = nullptr;
-  FILE *fp;
-
-  snprintf(path, sizeof(path), "/proc/%d/comm", tid);
-  if ((fp = fopen(path, "r"))) {
-    threadname = fgets(threadnamebuf, sizeof(threadnamebuf), fp);
-    fclose(fp);
-    if (threadname) {
-      size_t len = strlen(threadname);
-      if (len && threadname[len - 1] == '\n') {
-        threadname[len - 1] = '\0';
-      }
-    }
-  }
+static void dump_thread_info(log_t* log, pid_t pid, pid_t tid, const char* process_name,
+                             const char* thread_name) {
   // Blacklist logd, logd.reader, logd.writer, logd.auditd, logd.control ...
-  static const char logd[] = "logd";
-  if (threadname != nullptr && !strncmp(threadname, logd, sizeof(logd) - 1)
-      && (!threadname[sizeof(logd) - 1] || (threadname[sizeof(logd) - 1] == '.'))) {
+  // TODO: Why is this controlled by thread name?
+  if (strcmp(thread_name, "logd") == 0 || strncmp(thread_name, "logd.", 4) == 0) {
     log->should_retrieve_logcat = false;
   }
 
-  char procnamebuf[1024];
-  char* procname = nullptr;
-
-  snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
-  if ((fp = fopen(path, "r"))) {
-    procname = fgets(procnamebuf, sizeof(procnamebuf), fp);
-    fclose(fp);
-  }
-
-  _LOG(log, logtype::HEADER, "pid: %d, tid: %d, name: %s  >>> %s <<<\n", pid, tid,
-       threadname ? threadname : "UNKNOWN", procname ? procname : "UNKNOWN");
+  _LOG(log, logtype::HEADER, "pid: %d, tid: %d, name: %s  >>> %s <<<\n", pid, tid, thread_name,
+       process_name);
 }
 
 static void dump_stack_segment(
@@ -493,13 +470,14 @@
   }
 }
 
-static void dump_thread(log_t* log, pid_t pid, pid_t tid, BacktraceMap* map,
+static void dump_thread(log_t* log, pid_t pid, pid_t tid, const std::string& process_name,
+                        const std::string& thread_name, BacktraceMap* map,
                         uintptr_t abort_msg_address, bool primary_thread) {
   log->current_tid = tid;
   if (!primary_thread) {
     _LOG(log, logtype::THREAD, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
   }
-  dump_thread_info(log, pid, tid);
+  dump_thread_info(log, pid, tid, process_name.c_str(), thread_name.c_str());
   dump_signal_info(log, tid);
 
   std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map));
@@ -654,9 +632,9 @@
 }
 
 // Dumps all information about the specified pid to the tombstone.
-static void dump_crash(log_t* log, BacktraceMap* map,
-                       const OpenFilesList* open_files, pid_t pid, pid_t tid,
-                       const std::set<pid_t>* siblings, uintptr_t abort_msg_address) {
+static void dump_crash(log_t* log, BacktraceMap* map, const OpenFilesList* open_files, pid_t pid,
+                       pid_t tid, const std::string& process_name,
+                       const std::map<pid_t, std::string>& threads, uintptr_t abort_msg_address) {
   // don't copy log messages to tombstone unless this is a dev device
   char value[PROPERTY_VALUE_MAX];
   property_get("ro.debuggable", value, "0");
@@ -665,14 +643,17 @@
   _LOG(log, logtype::HEADER,
        "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
   dump_header_info(log);
-  dump_thread(log, pid, tid, map, abort_msg_address, true);
+  dump_thread(log, pid, tid, process_name, threads.find(tid)->second, map, abort_msg_address, true);
   if (want_logs) {
     dump_logs(log, pid, 5);
   }
 
-  if (siblings && !siblings->empty()) {
-    for (pid_t sibling : *siblings) {
-      dump_thread(log, pid, sibling, map, 0, false);
+  for (const auto& it : threads) {
+    pid_t thread_tid = it.first;
+    const std::string& thread_name = it.second;
+
+    if (thread_tid != tid) {
+      dump_thread(log, pid, thread_tid, process_name, thread_name, map, 0, false);
     }
   }
 
@@ -739,16 +720,16 @@
   return fd;
 }
 
-void engrave_tombstone(int tombstone_fd, BacktraceMap* map,
-                       const OpenFilesList* open_files, pid_t pid, pid_t tid,
-                       const std::set<pid_t>* siblings, uintptr_t abort_msg_address,
+void engrave_tombstone(int tombstone_fd, BacktraceMap* map, const OpenFilesList* open_files,
+                       pid_t pid, pid_t tid, const std::string& process_name,
+                       const std::map<pid_t, std::string>& threads, uintptr_t abort_msg_address,
                        std::string* amfd_data) {
   log_t log;
   log.current_tid = tid;
   log.crashed_tid = tid;
   log.tfd = tombstone_fd;
   log.amfd_data = amfd_data;
-  dump_crash(&log, map, open_files, pid, tid, siblings, abort_msg_address);
+  dump_crash(&log, map, open_files, pid, tid, process_name, threads, abort_msg_address);
 }
 
 void engrave_tombstone_ucontext(int tombstone_fd, uintptr_t abort_msg_address, siginfo_t* siginfo,
@@ -762,7 +743,13 @@
   log.tfd = tombstone_fd;
   log.amfd_data = nullptr;
 
-  dump_thread_info(&log, pid, tid);
+  char thread_name[16];
+  char process_name[128];
+
+  read_with_default("/proc/self/comm", thread_name, sizeof(thread_name), "<unknown>");
+  read_with_default("/proc/self/cmdline", process_name, sizeof(process_name), "<unknown>");
+
+  dump_thread_info(&log, pid, tid, thread_name, process_name);
   dump_signal_info(&log, siginfo);
 
   std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid));
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index 744cd72..22fde5e 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -28,6 +28,7 @@
 #include <string>
 
 #include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
 #include <backtrace/Backtrace.h>
 #include <log/log.h>
 
@@ -202,3 +203,20 @@
     _LOG(log, logtype::MEMORY, "%s  %s\n", logline.c_str(), ascii.c_str());
   }
 }
+
+void read_with_default(const char* path, char* buf, size_t len, const char* default_value) {
+  android::base::unique_fd fd(open(path, O_RDONLY));
+  if (fd != -1) {
+    int rc = TEMP_FAILURE_RETRY(read(fd.get(), buf, len - 1));
+    if (rc != -1) {
+      buf[rc] = '\0';
+
+      // Trim trailing newlines.
+      if (rc > 0 && buf[rc - 1] == '\n') {
+        buf[rc - 1] = '\0';
+      }
+      return;
+    }
+  }
+  strcpy(buf, default_value);
+}
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 8e2bc1c..48a0e61 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -123,11 +123,12 @@
 #define AID_DNS_TETHER    1052  /* DNS resolution daemon (tether: dnsmasq) */
 #define AID_WEBVIEW_ZYGOTE 1053 /* WebView zygote process */
 #define AID_VEHICLE_NETWORK 1054 /* Vehicle network service */
-#define AID_MEDIA_AUDIO   1055 /* GID for audio files on internal media storage */
-#define AID_MEDIA_VIDEO   1056 /* GID for video files on internal media storage */
-#define AID_MEDIA_IMAGE   1057 /* GID for image files on internal media storage */
+#define AID_MEDIA_AUDIO   1055  /* GID for audio files on internal media storage */
+#define AID_MEDIA_VIDEO   1056  /* GID for video files on internal media storage */
+#define AID_MEDIA_IMAGE   1057  /* GID for image files on internal media storage */
 #define AID_TOMBSTONED    1058  /* tombstoned user */
-#define AID_MEDIA_OBB     1059 /* GID for OBB files on internal media storage */
+#define AID_MEDIA_OBB     1059  /* GID for OBB files on internal media storage */
+#define AID_ESE           1060  /* embedded secure element (eSE) subsystem */
 /* Changes to this file must be made in AOSP, *not* in internal branches. */
 
 #define AID_SHELL         2000  /* adb and debug shell user */
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index 5b31ecb..0e7c6f3 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -80,6 +80,18 @@
             static_libs: ["libcutils"],
             host_ldlibs: ["-lrt"],
         },
+        linux_bionic: {
+            enabled: true,
+            srcs: libbacktrace_sources,
+
+            shared_libs: [
+                "libbase",
+                "liblog",
+                "libunwind",
+            ],
+
+            static_libs: ["libcutils"],
+        },
         android: {
             srcs: libbacktrace_sources,
 
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index cf31195..f668f18 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -41,9 +41,12 @@
     host_supported: true,
     export_include_dirs: ["include"],
     target: {
-       windows: {
-          enabled: true,
-       },
+        linux_bionic: {
+            enabled: true,
+        },
+        windows: {
+            enabled: true,
+        },
     },
 }
 
@@ -68,11 +71,14 @@
         "threads.c",
     ],
 
-
     target: {
         host: {
             srcs: ["dlmalloc_stubs.c"],
         },
+        linux_bionic: {
+            enabled: true,
+            exclude_srcs: ["dlmalloc_stubs.c"],
+        },
         not_windows: {
             srcs: libcutils_nonwindows_sources + [
                 "ashmem-host.c",
diff --git a/libprocinfo/Android.bp b/libprocinfo/Android.bp
index 8e17f1b..c13ffe9 100644
--- a/libprocinfo/Android.bp
+++ b/libprocinfo/Android.bp
@@ -35,6 +35,9 @@
         darwin: {
             enabled: false,
         },
+        linux_bionic: {
+            enabled: true,
+        },
         windows: {
             enabled: false,
         },
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 0c777b1..2b98fef 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -17,9 +17,12 @@
     host_supported: true,
     export_include_dirs: ["include"],
     target: {
+        linux_bionic: {
+            enabled: true,
+        },
         windows: {
-           enabled: true,
-      },
+            enabled: true,
+        },
     },
 }
 
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
index 5a5c0d9..ff6bff8 100644
--- a/logd/FlushCommand.cpp
+++ b/logd/FlushCommand.cpp
@@ -27,7 +27,7 @@
 #include "LogUtils.h"
 
 FlushCommand::FlushCommand(LogReader& reader, bool nonBlock, unsigned long tail,
-                           unsigned int logMask, pid_t pid, uint64_t start,
+                           unsigned int logMask, pid_t pid, log_time start,
                            uint64_t timeout)
     : mReader(reader),
       mNonBlock(nonBlock),
@@ -35,7 +35,7 @@
       mLogMask(logMask),
       mPid(pid),
       mStart(start),
-      mTimeout((start > 1) ? timeout : 0) {
+      mTimeout((start != log_time::EPOCH) ? timeout : 0) {
 }
 
 // runSocketCommand is called once for every open client on the
diff --git a/logd/FlushCommand.h b/logd/FlushCommand.h
index 45cb9c5..7cdd03f 100644
--- a/logd/FlushCommand.h
+++ b/logd/FlushCommand.h
@@ -16,7 +16,7 @@
 #ifndef _FLUSH_COMMAND_H
 #define _FLUSH_COMMAND_H
 
-#include <android/log.h>
+#include <private/android_logger.h>
 #include <sysutils/SocketClientCommand.h>
 
 class LogBufferElement;
@@ -31,13 +31,13 @@
     unsigned long mTail;
     unsigned int mLogMask;
     pid_t mPid;
-    uint64_t mStart;
+    log_time mStart;
     uint64_t mTimeout;
 
    public:
     explicit FlushCommand(LogReader& mReader, bool nonBlock = false,
                           unsigned long tail = -1, unsigned int logMask = -1,
-                          pid_t pid = 0, uint64_t start = 1,
+                          pid_t pid = 0, log_time start = log_time::EPOCH,
                           uint64_t timeout = 0);
     virtual void runSocketCommand(SocketClient* client);
 
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 2b6c276..1b79e89 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -181,7 +181,7 @@
     lenr -= avcr - msgr;
     if (lenl != lenr) return DIFFERENT;
     // TODO: After b/35468874 is addressed, revisit "lenl > strlen(avc)"
-    // condition, it might become superflous.
+    // condition, it might become superfluous.
     if (lenl > strlen(avc) &&
         fastcmp<memcmp>(avcl + strlen(avc), avcr + strlen(avc),
                         lenl - strlen(avc))) {
@@ -374,18 +374,12 @@
     //  NB: if end is region locked, place element at end of list
     LogBufferElementCollection::iterator it = mLogElements.end();
     LogBufferElementCollection::iterator last = it;
-    while (last != mLogElements.begin()) {
-        --it;
-        if ((*it)->getRealTime() <= elem->getRealTime()) {
-            break;
-        }
-        last = it;
-    }
-
-    if (last == mLogElements.end()) {
+    if (__predict_true(it != mLogElements.begin())) --it;
+    if (__predict_false(it == mLogElements.begin()) ||
+        __predict_true((*it)->getRealTime() <= elem->getRealTime())) {
         mLogElements.push_back(elem);
     } else {
-        uint64_t end = 1;
+        log_time end = log_time::EPOCH;
         bool end_set = false;
         bool end_always = false;
 
@@ -399,6 +393,7 @@
                     end_always = true;
                     break;
                 }
+                // it passing mEnd is blocked by the following checks.
                 if (!end_set || (end <= entry->mEnd)) {
                     end = entry->mEnd;
                     end_set = true;
@@ -407,12 +402,20 @@
             times++;
         }
 
-        if (end_always || (end_set && (end >= (*last)->getSequence()))) {
+        if (end_always || (end_set && (end > (*it)->getRealTime()))) {
             mLogElements.push_back(elem);
         } else {
+            // should be short as timestamps are localized near end()
+            do {
+                last = it;
+                if (__predict_false(it == mLogElements.begin())) {
+                    break;
+                }
+                --it;
+            } while (((*it)->getRealTime() > elem->getRealTime()) &&
+                     (!end_set || (end <= (*it)->getRealTime())));
             mLogElements.insert(last, elem);
         }
-
         LogTimeEntry::unlock();
     }
 
@@ -587,12 +590,12 @@
     }
 
     void clear(LogBufferElement* element) {
-        uint64_t current =
-            element->getRealTime().nsec() - (EXPIRE_RATELIMIT * NS_PER_SEC);
+        log_time current =
+            element->getRealTime() - log_time(EXPIRE_RATELIMIT, 0);
         for (LogBufferElementMap::iterator it = map.begin(); it != map.end();) {
             LogBufferElement* mapElement = it->second;
             if ((mapElement->getDropped() >= EXPIRE_THRESHOLD) &&
-                (current > mapElement->getRealTime().nsec())) {
+                (current > mapElement->getRealTime())) {
                 it = map.erase(it);
             } else {
                 ++it;
@@ -688,7 +691,7 @@
                 mLastSet[id] = true;
             }
 
-            if (oldest && (oldest->mStart <= element->getSequence())) {
+            if (oldest && (oldest->mStart <= element->getRealTime().nsec())) {
                 busy = true;
                 if (oldest->mTimeout.tv_sec || oldest->mTimeout.tv_nsec) {
                     oldest->triggerReader_Locked();
@@ -780,7 +783,7 @@
         while (it != mLogElements.end()) {
             LogBufferElement* element = *it;
 
-            if (oldest && (oldest->mStart <= element->getSequence())) {
+            if (oldest && (oldest->mStart <= element->getRealTime().nsec())) {
                 busy = true;
                 if (oldest->mTimeout.tv_sec || oldest->mTimeout.tv_nsec) {
                     oldest->triggerReader_Locked();
@@ -934,7 +937,7 @@
             mLastSet[id] = true;
         }
 
-        if (oldest && (oldest->mStart <= element->getSequence())) {
+        if (oldest && (oldest->mStart <= element->getRealTime().nsec())) {
             busy = true;
             if (whitelist) {
                 break;
@@ -978,7 +981,7 @@
                 mLastSet[id] = true;
             }
 
-            if (oldest && (oldest->mStart <= element->getSequence())) {
+            if (oldest && (oldest->mStart <= element->getRealTime().nsec())) {
                 busy = true;
                 if (stats.sizes(id) > (2 * log_buffer_size(id))) {
                     // kick a misbehaving log reader client off the island
@@ -1071,32 +1074,37 @@
     return retval;
 }
 
-uint64_t LogBuffer::flushTo(
-    SocketClient* reader, const uint64_t start, bool privileged, bool security,
+log_time LogBuffer::flushTo(
+    SocketClient* reader, const log_time& start, bool privileged, bool security,
     int (*filter)(const LogBufferElement* element, void* arg), void* arg) {
     LogBufferElementCollection::iterator it;
-    uint64_t max = start;
     uid_t uid = reader->getUid();
 
     pthread_mutex_lock(&mLogElementsLock);
 
-    if (start <= 1) {
+    if (start == log_time::EPOCH) {
         // client wants to start from the beginning
         it = mLogElements.begin();
     } else {
+        LogBufferElementCollection::iterator last = mLogElements.begin();
+        // 30 second limit to continue search for out-of-order entries.
+        log_time min = start - log_time(30, 0);
         // Client wants to start from some specified time. Chances are
         // we are better off starting from the end of the time sorted list.
         for (it = mLogElements.end(); it != mLogElements.begin();
              /* do nothing */) {
             --it;
             LogBufferElement* element = *it;
-            if (element->getSequence() <= start) {
-                it++;
+            if (element->getRealTime() > start) {
+                last = it;
+            } else if (element->getRealTime() < min) {
                 break;
             }
         }
+        it = last;
     }
 
+    log_time max = start;
     // Help detect if the valid message before is from the same source so
     // we can differentiate chatty filter types.
     pid_t lastTid[LOG_ID_MAX] = { 0 };
@@ -1112,7 +1120,7 @@
             continue;
         }
 
-        if (element->getSequence() <= start) {
+        if (element->getRealTime() <= start) {
             continue;
         }
 
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index 92b0297..fcf6b9a 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -115,7 +115,7 @@
 
     int log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid,
             const char* msg, unsigned short len);
-    uint64_t flushTo(SocketClient* writer, const uint64_t start,
+    log_time flushTo(SocketClient* writer, const log_time& start,
                      bool privileged, bool security,
                      int (*filter)(const LogBufferElement* element,
                                    void* arg) = NULL,
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index 5ba3a15..81356fe 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -30,7 +30,7 @@
 #include "LogReader.h"
 #include "LogUtils.h"
 
-const uint64_t LogBufferElement::FLUSH_ERROR(0);
+const log_time LogBufferElement::FLUSH_ERROR((uint32_t)-1, (uint32_t)-1);
 atomic_int_fast64_t LogBufferElement::sequence(1);
 
 LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime,
@@ -39,7 +39,6 @@
     : mUid(uid),
       mPid(pid),
       mTid(tid),
-      mSequence(sequence.fetch_add(1, memory_order_relaxed)),
       mRealTime(realtime),
       mMsgLen(len),
       mLogId(log_id) {
@@ -55,7 +54,6 @@
       mUid(elem.mUid),
       mPid(elem.mPid),
       mTid(elem.mTid),
-      mSequence(elem.mSequence),
       mRealTime(elem.mRealTime),
       mMsgLen(elem.mMsgLen),
       mLogId(elem.mLogId) {
@@ -206,7 +204,7 @@
     return retval;
 }
 
-uint64_t LogBufferElement::flushTo(SocketClient* reader, LogBuffer* parent,
+log_time LogBufferElement::flushTo(SocketClient* reader, LogBuffer* parent,
                                    bool privileged, bool lastSame) {
     struct logger_entry_v4 entry;
 
@@ -229,7 +227,7 @@
 
     if (!mMsg) {
         entry.len = populateDroppedMessage(buffer, parent, lastSame);
-        if (!entry.len) return mSequence;
+        if (!entry.len) return mRealTime;
         iovec[1].iov_base = buffer;
     } else {
         entry.len = mMsgLen;
@@ -237,7 +235,7 @@
     }
     iovec[1].iov_len = entry.len;
 
-    uint64_t retval = reader->sendDatav(iovec, 2) ? FLUSH_ERROR : mSequence;
+    log_time retval = reader->sendDatav(iovec, 2) ? FLUSH_ERROR : mRealTime;
 
     if (buffer) free(buffer);
 
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index 43990e8..814ec87 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -40,7 +40,6 @@
     const uint32_t mUid;
     const uint32_t mPid;
     const uint32_t mTid;
-    const uint64_t mSequence;
     log_time mRealTime;
     char* mMsg;
     union {
@@ -96,18 +95,12 @@
     const char* getMsg() const {
         return mMsg;
     }
-    uint64_t getSequence(void) const {
-        return mSequence;
-    }
-    static uint64_t getCurrentSequence(void) {
-        return sequence.load(memory_order_relaxed);
-    }
     log_time getRealTime(void) const {
         return mRealTime;
     }
 
-    static const uint64_t FLUSH_ERROR;
-    uint64_t flushTo(SocketClient* writer, LogBuffer* parent, bool privileged,
+    static const log_time FLUSH_ERROR;
+    log_time flushTo(SocketClient* writer, LogBuffer* parent, bool privileged,
                      bool lastSame);
 };
 
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index 76f5798..620d4d0 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -116,57 +116,70 @@
         nonBlock = true;
     }
 
-    uint64_t sequence = 1;
-    // Convert realtime to sequence number
-    if (start != log_time::EPOCH) {
-        class LogFindStart {
+    log_time sequence = start;
+    //
+    // This somewhat expensive data validation operation is required
+    // for non-blocking, with timeout.  The incoming timestamp must be
+    // in range of the list, if not, return immediately.  This is
+    // used to prevent us from from getting stuck in timeout processing
+    // with an invalid time.
+    //
+    // Find if time is really present in the logs, monotonic or real, implicit
+    // conversion from monotonic or real as necessary to perform the check.
+    // Exit in the check loop ASAP as you find a transition from older to
+    // newer, but use the last entry found to ensure overlap.
+    //
+    if (nonBlock && (sequence != log_time::EPOCH) && timeout) {
+        class LogFindStart {  // A lambda by another name
+           private:
             const pid_t mPid;
             const unsigned mLogMask;
-            bool startTimeSet;
-            log_time& start;
-            uint64_t& sequence;
-            uint64_t last;
-            bool isMonotonic;
+            bool mStartTimeSet;
+            log_time mStart;
+            log_time& mSequence;
+            log_time mLast;
+            bool mIsMonotonic;
 
            public:
-            LogFindStart(unsigned logMask, pid_t pid, log_time& start,
-                         uint64_t& sequence, bool isMonotonic)
+            LogFindStart(pid_t pid, unsigned logMask, log_time& sequence,
+                         bool isMonotonic)
                 : mPid(pid),
                   mLogMask(logMask),
-                  startTimeSet(false),
-                  start(start),
-                  sequence(sequence),
-                  last(sequence),
-                  isMonotonic(isMonotonic) {
+                  mStartTimeSet(false),
+                  mStart(sequence),
+                  mSequence(sequence),
+                  mLast(sequence),
+                  mIsMonotonic(isMonotonic) {
             }
 
             static int callback(const LogBufferElement* element, void* obj) {
                 LogFindStart* me = reinterpret_cast<LogFindStart*>(obj);
                 if ((!me->mPid || (me->mPid == element->getPid())) &&
                     (me->mLogMask & (1 << element->getLogId()))) {
-                    if (me->start == element->getRealTime()) {
-                        me->sequence = element->getSequence();
-                        me->startTimeSet = true;
+                    log_time real = element->getRealTime();
+                    if (me->mStart == real) {
+                        me->mSequence = real;
+                        me->mStartTimeSet = true;
                         return -1;
-                    } else if (!me->isMonotonic ||
-                               android::isMonotonic(element->getRealTime())) {
-                        if (me->start < element->getRealTime()) {
-                            me->sequence = me->last;
-                            me->startTimeSet = true;
+                    } else if (!me->mIsMonotonic || android::isMonotonic(real)) {
+                        if (me->mStart < real) {
+                            me->mSequence = me->mLast;
+                            me->mStartTimeSet = true;
                             return -1;
                         }
-                        me->last = element->getSequence();
+                        me->mLast = real;
                     } else {
-                        me->last = element->getSequence();
+                        me->mLast = real;
                     }
                 }
                 return false;
             }
 
             bool found() {
-                return startTimeSet;
+                return mStartTimeSet;
             }
-        } logFindStart(logMask, pid, start, sequence,
+
+        } logFindStart(pid, logMask, sequence,
                        logbuf().isMonotonic() && android::isMonotonic(start));
 
         logbuf().flushTo(cli, sequence, FlushCommand::hasReadLogs(cli),
@@ -174,11 +187,8 @@
                          logFindStart.callback, &logFindStart);
 
         if (!logFindStart.found()) {
-            if (nonBlock) {
-                doSocketDelete(cli);
-                return false;
-            }
-            sequence = LogBufferElement::getCurrentSequence();
+            doSocketDelete(cli);
+            return false;
         }
     }
 
diff --git a/logd/LogTimes.cpp b/logd/LogTimes.cpp
index bdaeb75..04e531f 100644
--- a/logd/LogTimes.cpp
+++ b/logd/LogTimes.cpp
@@ -17,6 +17,8 @@
 #include <errno.h>
 #include <sys/prctl.h>
 
+#include <private/android_logger.h>
+
 #include "FlushCommand.h"
 #include "LogBuffer.h"
 #include "LogReader.h"
@@ -26,7 +28,7 @@
 
 LogTimeEntry::LogTimeEntry(LogReader& reader, SocketClient* client,
                            bool nonBlock, unsigned long tail,
-                           unsigned int logMask, pid_t pid, uint64_t start,
+                           unsigned int logMask, pid_t pid, log_time start,
                            uint64_t timeout)
     : mRefCount(1),
       mRelease(false),
@@ -42,7 +44,7 @@
       mClient(client),
       mStart(start),
       mNonBlock(nonBlock),
-      mEnd(LogBufferElement::getCurrentSequence()) {
+      mEnd(log_time(android_log_clockid())) {
     mTimeout.tv_sec = timeout / NS_PER_SEC;
     mTimeout.tv_nsec = timeout % NS_PER_SEC;
     pthread_cond_init(&threadTriggeredCondition, NULL);
@@ -132,7 +134,7 @@
 
     lock();
 
-    uint64_t start = me->mStart;
+    log_time start = me->mStart;
 
     while (me->threadRunning && !me->isError_Locked()) {
         if (me->mTimeout.tv_sec || me->mTimeout.tv_nsec) {
@@ -163,7 +165,7 @@
             break;
         }
 
-        me->mStart = start + 1;
+        me->mStart = start + log_time(0, 1);
 
         if (me->mNonBlock || !me->threadRunning || me->isError_Locked()) {
             break;
@@ -198,7 +200,7 @@
     }
 
     if (me->mCount == 0) {
-        me->mStart = element->getSequence();
+        me->mStart = element->getRealTime();
     }
 
     if ((!me->mPid || (me->mPid == element->getPid())) &&
@@ -217,7 +219,7 @@
 
     LogTimeEntry::lock();
 
-    me->mStart = element->getSequence();
+    me->mStart = element->getRealTime();
 
     if (me->skipAhead[element->getLogId()]) {
         me->skipAhead[element->getLogId()]--;
diff --git a/logd/LogTimes.h b/logd/LogTimes.h
index 23fdf4e..9a3ddab 100644
--- a/logd/LogTimes.h
+++ b/logd/LogTimes.h
@@ -51,13 +51,13 @@
    public:
     LogTimeEntry(LogReader& reader, SocketClient* client, bool nonBlock,
                  unsigned long tail, unsigned int logMask, pid_t pid,
-                 uint64_t start, uint64_t timeout);
+                 log_time start, uint64_t timeout);
 
     SocketClient* mClient;
-    uint64_t mStart;
+    log_time mStart;
     struct timespec mTimeout;
     const bool mNonBlock;
-    const uint64_t mEnd;  // only relevant if mNonBlock
+    const log_time mEnd;  // only relevant if mNonBlock
 
     // Protect List manipulations
     static void lock(void) {
diff --git a/rootdir/init-debug.rc b/rootdir/init-debug.rc
index 44d34d8..435d4cb 100644
--- a/rootdir/init-debug.rc
+++ b/rootdir/init-debug.rc
@@ -6,6 +6,3 @@
 
 on property:persist.mmc.cache_size=*
     write /sys/block/mmcblk0/cache_size ${persist.mmc.cache_size}
-
-on early-init
-    mount debugfs debugfs /sys/kernel/debug