Merge "libprocinfo: provide MapInfo structure for reading maps."
diff --git a/adb/client/console.cpp b/adb/client/console.cpp
index 9563eac..4e8a3f8 100644
--- a/adb/client/console.cpp
+++ b/adb/client/console.cpp
@@ -135,6 +135,7 @@
     // preventing the emulator from reading the command that adb has sent.
     // https://code.google.com/p/android/issues/detail?id=21021
     int result;
+    std::string emulator_output;
     do {
         char buf[BUFSIZ];
         result = adb_read(fd, buf, sizeof(buf));
@@ -146,8 +147,37 @@
         // appended above, and that causes the emulator to close the socket
         // which should cause zero bytes (orderly/graceful shutdown) to be
         // returned.
+        if (result > 0) emulator_output.append(buf, result);
     } while (result > 0);
 
+    // Note: the following messages are expected to be quite stable from emulator.
+    //
+    // Emulator console will send the following message upon connection:
+    //
+    // Android Console: Authentication required
+    // Android Console: type 'auth <auth_token>' to authenticate
+    // Android Console: you can find your <auth_token> in
+    // '/<path-to-home>/.emulator_console_auth_token'
+    // OK\r\n
+    //
+    // and the following after authentication:
+    // Android Console: type 'help' for a list of commands
+    // OK\r\n
+    //
+    // So try search and skip first two "OK\r\n", print the rest.
+    //
+    const std::string delims = "OK\r\n";
+    size_t found = 0;
+    for (int i = 0; i < 2; ++i) {
+        const size_t result = emulator_output.find(delims, found);
+        if (result == std::string::npos) {
+            break;
+        } else {
+            found = result + delims.size();
+        }
+    }
+
+    printf("%s", emulator_output.c_str() + found);
     adb_close(fd);
 
     return 0;
diff --git a/base/include/android-base/strings.h b/base/include/android-base/strings.h
index 9c35560..fc5c1ce 100644
--- a/base/include/android-base/strings.h
+++ b/base/include/android-base/strings.h
@@ -61,6 +61,7 @@
 bool StartsWithIgnoreCase(const std::string& s, const char* prefix);
 bool StartsWith(const std::string& s, const std::string& prefix);
 bool StartsWithIgnoreCase(const std::string& s, const std::string& prefix);
+bool StartsWith(const std::string& s, char prefix);
 
 // Tests whether 's' ends with 'suffix'.
 // TODO: string_view
@@ -68,6 +69,7 @@
 bool EndsWithIgnoreCase(const std::string& s, const char* suffix);
 bool EndsWith(const std::string& s, const std::string& suffix);
 bool EndsWithIgnoreCase(const std::string& s, const std::string& suffix);
+bool EndsWith(const std::string& s, char suffix);
 
 // Tests whether 'lhs' equals 'rhs', ignoring case.
 bool EqualsIgnoreCase(const std::string& lhs, const std::string& rhs);
diff --git a/base/strings.cpp b/base/strings.cpp
index a8bb2a9..2d6eef0 100644
--- a/base/strings.cpp
+++ b/base/strings.cpp
@@ -95,6 +95,10 @@
   return strncmp(s.c_str(), prefix.c_str(), prefix.size()) == 0;
 }
 
+bool StartsWith(const std::string& s, char prefix) {
+  return *s.c_str() == prefix;  // Use c_str() to guarantee there is at least a '\0'.
+}
+
 bool StartsWithIgnoreCase(const std::string& s, const char* prefix) {
   return strncasecmp(s.c_str(), prefix, strlen(prefix)) == 0;
 }
@@ -121,6 +125,10 @@
   return EndsWith(s, suffix.c_str(), suffix.size(), true);
 }
 
+bool EndsWith(const std::string& s, char suffix) {
+  return EndsWith(s, &suffix, 1, true);
+}
+
 bool EndsWithIgnoreCase(const std::string& s, const char* suffix) {
   return EndsWith(s, suffix, strlen(suffix), false);
 }
diff --git a/base/strings_test.cpp b/base/strings_test.cpp
index b8639ea..9d74094 100644
--- a/base/strings_test.cpp
+++ b/base/strings_test.cpp
@@ -198,6 +198,12 @@
   ASSERT_FALSE(android::base::StartsWithIgnoreCase("foobar", "BAR"));
 }
 
+TEST(strings, StartsWith_char) {
+  ASSERT_FALSE(android::base::StartsWith("", 'f'));
+  ASSERT_TRUE(android::base::StartsWith("foo", 'f'));
+  ASSERT_FALSE(android::base::StartsWith("foo", 'o'));
+}
+
 TEST(strings, EndsWith_empty) {
   ASSERT_FALSE(android::base::EndsWith("", "foo"));
   ASSERT_TRUE(android::base::EndsWith("", ""));
@@ -273,6 +279,12 @@
   ASSERT_FALSE(android::base::EndsWithIgnoreCase("GoOdByE", std::string{"lo"}));
 }
 
+TEST(strings, EndsWith_char) {
+  ASSERT_FALSE(android::base::EndsWith("", 'o'));
+  ASSERT_TRUE(android::base::EndsWith("foo", 'o'));
+  ASSERT_FALSE(android::base::EndsWith("foo", "f"));
+}
+
 TEST(strings, EqualsIgnoreCase) {
   ASSERT_TRUE(android::base::EqualsIgnoreCase("foo", "FOO"));
   ASSERT_TRUE(android::base::EqualsIgnoreCase("FOO", "foo"));
diff --git a/debuggerd/handler/debuggerd_fallback.cpp b/debuggerd/handler/debuggerd_fallback.cpp
index ed7423b..15c0265 100644
--- a/debuggerd/handler/debuggerd_fallback.cpp
+++ b/debuggerd/handler/debuggerd_fallback.cpp
@@ -250,11 +250,12 @@
         }
 
         uint64_t expected = pack_thread_fd(-1, -1);
-        if (!trace_output.compare_exchange_strong(expected,
-                                                  pack_thread_fd(tid, pipe_write.release()))) {
+        int sent_fd = pipe_write.release();
+        if (!trace_output.compare_exchange_strong(expected, pack_thread_fd(tid, sent_fd))) {
           auto [tid, fd] = unpack_thread_fd(expected);
           async_safe_format_log(ANDROID_LOG_ERROR, "libc",
                                 "thread %d is already outputting to fd %d?", tid, fd);
+          close(sent_fd);
           return false;
         }
 
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 79957f6..2ac638a 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -61,10 +61,18 @@
     return false;
 }
 
+bool fs_mgr_overlayfs_mount_all(const std::vector<const fstab_rec*>&) {
+    return false;
+}
+
 std::vector<std::string> fs_mgr_overlayfs_required_devices(fstab*) {
     return {};
 }
 
+std::vector<std::string> fs_mgr_overlayfs_required_devices(const std::vector<const fstab_rec*>&) {
+    return {};
+}
+
 bool fs_mgr_overlayfs_setup(const char*, const char*, bool* change) {
     if (change) *change = false;
     return false;
@@ -764,6 +772,13 @@
     return ret;
 }
 
+bool fs_mgr_overlayfs_mount_all(const std::vector<const fstab_rec*>& fsrecs) {
+    std::vector<fstab_rec> recs;
+    for (const auto& rec : fsrecs) recs.push_back(*rec);
+    fstab fstab = {static_cast<int>(fsrecs.size()), &recs[0]};
+    return fs_mgr_overlayfs_mount_all(&fstab);
+}
+
 std::vector<std::string> fs_mgr_overlayfs_required_devices(fstab* fstab) {
     if (fs_mgr_get_entry_for_mount_point(const_cast<struct fstab*>(fstab), kScratchMountPoint)) {
         return {};
@@ -778,6 +793,14 @@
     return {};
 }
 
+std::vector<std::string> fs_mgr_overlayfs_required_devices(
+        const std::vector<const fstab_rec*>& fsrecs) {
+    std::vector<fstab_rec> recs;
+    for (const auto& rec : fsrecs) recs.push_back(*rec);
+    fstab fstab = {static_cast<int>(fsrecs.size()), &recs[0]};
+    return fs_mgr_overlayfs_required_devices(&fstab);
+}
+
 // Returns false if setup not permitted, errno set to last error.
 // If something is altered, set *change.
 bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* change) {
diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h
index 550dd18..9182532 100644
--- a/fs_mgr/include/fs_mgr_overlayfs.h
+++ b/fs_mgr/include/fs_mgr_overlayfs.h
@@ -22,7 +22,10 @@
 #include <vector>
 
 bool fs_mgr_overlayfs_mount_all(fstab* fstab);
+bool fs_mgr_overlayfs_mount_all(const std::vector<const fstab_rec*>& fstab);
 std::vector<std::string> fs_mgr_overlayfs_required_devices(fstab* fstab);
+std::vector<std::string> fs_mgr_overlayfs_required_devices(
+        const std::vector<const fstab_rec*>& fstab);
 bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr,
                             bool* change = nullptr);
 bool fs_mgr_overlayfs_teardown(const char* mount_point = nullptr, bool* change = nullptr);
diff --git a/liblog/pmsg_reader.c b/liblog/pmsg_reader.c
index c3ed8a2..bf0e4fe 100644
--- a/liblog/pmsg_reader.c
+++ b/liblog/pmsg_reader.c
@@ -269,6 +269,14 @@
   }
 }
 
+static void* realloc_or_free(void* ptr, size_t new_size) {
+  void* result = realloc(ptr, new_size);
+  if (!result) {
+    free(ptr);
+  }
+  return result;
+}
+
 LIBLOG_ABI_PRIVATE ssize_t
 __android_log_pmsg_file_read(log_id_t logId, char prio, const char* prefix,
                              __android_log_pmsg_file_read_fn fn, void* arg) {
@@ -541,7 +549,7 @@
       /* Missing sequence numbers */
       while (sequence < content->entry.nsec) {
         /* plus space for enforced nul */
-        buf = realloc(buf, len + sizeof(char) + sizeof(char));
+        buf = realloc_or_free(buf, len + sizeof(char) + sizeof(char));
         if (!buf) {
           break;
         }
@@ -556,7 +564,7 @@
         continue;
       }
       /* plus space for enforced nul */
-      buf = realloc(buf, len + add_len + sizeof(char));
+      buf = realloc_or_free(buf, len + add_len + sizeof(char));
       if (!buf) {
         ret = -ENOMEM;
         list_remove(content_node);