Merge changes from topic "read-bootstrap-apex" into main

* changes:
  Skip bootstrap APEX RC files for the second round
  Read .rc files from bootstrap apexes
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 52c1c25..19ff7eb 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -2264,10 +2264,14 @@
 
   ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)");
 
-  // Assumes that the open files section comes after the map section.
-  // If that assumption changes, the regex below needs to change.
+  // Verifies that the fault address error message is at the end of the
+  // maps section. To do this, the check below looks for the start of the
+  // open files section or the start of the log file section. It's possible
+  // for either of these sections to be present after the maps section right
+  // now.
+  // If the sections move around, this check might need to be modified.
   match_str = android::base::StringPrintf(
-      R"(\n--->Fault address falls at %s after any mapped regions\n\nopen files:)",
+      R"(\n--->Fault address falls at %s after any mapped regions\n(---------|\nopen files:))",
       format_pointer(crash_uptr).c_str());
   ASSERT_MATCH(result, match_str);
 }
diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index 7b2e068..744bfab 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -493,27 +493,48 @@
   }
 }
 
+// This creates a fake log message that indicates an error occurred when
+// reading the log.
+static void add_error_log_msg(Tombstone* tombstone, const std::string&& error_msg) {
+  LogBuffer buffer;
+  buffer.set_name("ERROR");
+
+  LogMessage* log_msg = buffer.add_logs();
+  log_msg->set_timestamp("00-00 00:00:00.000");
+  log_msg->set_pid(0);
+  log_msg->set_tid(0);
+  log_msg->set_priority(ANDROID_LOG_ERROR);
+  log_msg->set_tag("");
+  log_msg->set_message(error_msg);
+
+  *tombstone->add_log_buffers() = std::move(buffer);
+
+  async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "%s", error_msg.c_str());
+}
+
 static void dump_log_file(Tombstone* tombstone, const char* logger, pid_t pid) {
   logger_list* logger_list = android_logger_list_open(android_name_to_log_id(logger),
                                                       ANDROID_LOG_NONBLOCK, kMaxLogMessages, pid);
+  if (logger_list == nullptr) {
+    add_error_log_msg(tombstone, android::base::StringPrintf("Cannot open log file %s", logger));
+    return;
+  }
 
   LogBuffer buffer;
-
   while (true) {
     log_msg log_entry;
     ssize_t actual = android_logger_list_read(logger_list, &log_entry);
-
     if (actual < 0) {
       if (actual == -EINTR) {
         // interrupted by signal, retry
         continue;
       }
-      if (actual == -EAGAIN) {
-        // non-blocking EOF; we're done
-        break;
-      } else {
-        break;
+      // Don't consider EAGAIN an error since this is a non-blocking call.
+      if (actual != -EAGAIN) {
+        add_error_log_msg(tombstone, android::base::StringPrintf("reading log %s failed (%s)",
+                                                                 logger, strerror(-actual)));
       }
+      break;
     } else if (actual == 0) {
       break;
     }
diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
index 8e6abdf..eed81fc 100644
--- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
@@ -81,6 +81,8 @@
   if (!tombstone.command_line().empty()) {
     process_name = tombstone.command_line()[0].c_str();
     CB(should_log, "Cmdline: %s", android::base::Join(tombstone.command_line(), " ").c_str());
+  } else {
+    CB(should_log, "Cmdline: <unknown>");
   }
   CB(should_log, "pid: %d, tid: %d, name: %s  >>> %s <<<", tombstone.pid(), thread.id(),
      thread.name().c_str(), process_name);
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 86ff5f7..51389a0 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -729,6 +729,14 @@
         LOG(ERROR) << "Failed to remove status file " << file_path << ": " << error;
         return false;
     }
+
+    // This path may never exist. If it is present, then it's a stale
+    // snapshot status file. Just remove the file and log the message.
+    const std::string tmp_path = file_path + ".tmp";
+    if (!android::base::RemoveFileIfExists(tmp_path, &error)) {
+        LOG(ERROR) << "Failed to remove stale snapshot file " << tmp_path;
+    }
+
     return true;
 }
 
@@ -754,10 +762,10 @@
         return false;
     }
 
-    auto other_suffix = device_->GetOtherSlotSuffix();
+    auto current_slot_suffix = device_->GetSlotSuffix();
 
     for (const auto& snapshot : snapshots) {
-        if (android::base::EndsWith(snapshot, other_suffix)) {
+        if (!android::base::EndsWith(snapshot, current_slot_suffix)) {
             // Allow the merge to continue, but log this unexpected case.
             LOG(ERROR) << "Unexpected snapshot found during merge: " << snapshot;
             continue;
@@ -1123,7 +1131,7 @@
         return MergeResult(UpdateState::MergeFailed, MergeFailureCode::ListSnapshots);
     }
 
-    auto other_suffix = device_->GetOtherSlotSuffix();
+    auto current_slot_suffix = device_->GetSlotSuffix();
 
     bool cancelled = false;
     bool merging = false;
@@ -1131,9 +1139,9 @@
     bool wrong_phase = false;
     MergeFailureCode failure_code = MergeFailureCode::Ok;
     for (const auto& snapshot : snapshots) {
-        if (android::base::EndsWith(snapshot, other_suffix)) {
+        if (!android::base::EndsWith(snapshot, current_slot_suffix)) {
             // This will have triggered an error message in InitiateMerge already.
-            LOG(INFO) << "Skipping merge validation of unexpected snapshot: " << snapshot;
+            LOG(ERROR) << "Skipping merge validation of unexpected snapshot: " << snapshot;
             continue;
         }
 
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 0a85489..3b6d26a 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -685,6 +685,17 @@
     }
     ASSERT_TRUE(sm->InitiateMerge());
 
+    // Create stale files in snapshot directory. Merge should skip these files
+    // as the suffix doesn't match the current slot.
+    auto tmp_path = test_device->GetMetadataDir() + "/snapshots/test_partition_b.tmp";
+    auto other_slot = test_device->GetMetadataDir() + "/snapshots/test_partition_a";
+
+    unique_fd fd(open(tmp_path.c_str(), O_RDWR | O_CLOEXEC | O_CREAT, 0644));
+    ASSERT_GE(fd, 0);
+
+    fd.reset(open(other_slot.c_str(), O_RDWR | O_CLOEXEC | O_CREAT, 0644));
+    ASSERT_GE(fd, 0);
+
     // The device should have been switched to a snapshot-merge target.
     DeviceMapper::TargetInfo target;
     ASSERT_TRUE(sm->IsSnapshotDevice("test_partition_b", &target));
@@ -700,13 +711,23 @@
     ASSERT_EQ(sm->ProcessUpdateState(), UpdateState::MergeCompleted);
     ASSERT_EQ(sm->GetUpdateState(), UpdateState::None);
 
+    // Make sure that snapshot states are cleared and all stale files
+    // are deleted
+    {
+        ASSERT_TRUE(AcquireLock());
+        auto local_lock = std::move(lock_);
+        std::vector<std::string> snapshots;
+        ASSERT_TRUE(sm->ListSnapshots(local_lock.get(), &snapshots));
+        ASSERT_TRUE(snapshots.empty());
+    }
+
     // The device should no longer be a snapshot or snapshot-merge.
     ASSERT_FALSE(sm->IsSnapshotDevice("test_partition_b"));
 
     // Test that we can read back the string we wrote to the snapshot. Note
     // that the base device is gone now. |snap_device| contains the correct
     // partition.
-    unique_fd fd(open("/dev/block/mapper/test_partition_b", O_RDONLY | O_CLOEXEC));
+    fd.reset(open("/dev/block/mapper/test_partition_b", O_RDONLY | O_CLOEXEC));
     ASSERT_GE(fd, 0);
 
     std::string buffer(test_string.size(), '\0');
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 92486e3..55a8694 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -162,7 +162,6 @@
         "properties.cpp",
         "record_stream.cpp",
         "strlcpy.c",
-        "threads.cpp",
     ],
 
     target: {
diff --git a/libcutils/threads.cpp b/libcutils/threads.cpp
deleted file mode 100644
index cca50c1..0000000
--- a/libcutils/threads.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-** Copyright (C) 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <sys/types.h>
-
-#if defined(__APPLE__)
-#include <pthread.h>
-#include <stdint.h>
-#elif defined(__linux__)
-#include <pthread.h>
-#include <syscall.h>
-#include <unistd.h>
-#elif defined(_WIN32)
-#include <windows.h>
-#endif
-
-#if defined(__BIONIC__) || defined(__GLIBC__) && __GLIBC_MINOR__ >= 30
-// No definition needed for Android because we'll just pick up bionic's copy.
-// No definition needed for Glibc >= 2.30 because it exposes its own copy.
-#else
-extern "C" pid_t gettid() {
-#if defined(__APPLE__)
-  uint64_t tid;
-  pthread_threadid_np(NULL, &tid);
-  return tid;
-#elif defined(__linux__)
-  return syscall(__NR_gettid);
-#elif defined(_WIN32)
-  return GetCurrentThreadId();
-#endif
-}
-#endif