Merge changes If6611d64,Ie55c3ac1

* changes:
  init: remove unneeded special cases from FscryptInferAction
  init: fix mkdir to reliably detect top-level /data directories
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 967b942..e3ea455 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -51,12 +51,9 @@
 #define ATRACE_TAG ATRACE_TAG_BIONIC
 #include <utils/Trace.h>
 
-#include <unwindstack/DexFiles.h>
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
+#include <unwindstack/AndroidUnwinder.h>
+#include <unwindstack/Error.h>
 #include <unwindstack/Regs.h>
-#include <unwindstack/Unwinder.h>
 
 #include "libdebuggerd/backtrace.h"
 #include "libdebuggerd/tombstone.h"
@@ -623,9 +620,12 @@
   }
 
   // TODO: Use seccomp to lock ourselves down.
-  unwindstack::UnwinderFromPid unwinder(256, vm_pid, unwindstack::Regs::CurrentArch());
-  if (!unwinder.Init()) {
-    LOG(FATAL) << "Failed to init unwinder object.";
+
+  unwindstack::AndroidRemoteUnwinder unwinder(vm_pid, unwindstack::Regs::CurrentArch());
+  unwindstack::ErrorData error_data;
+  if (!unwinder.Initialize(error_data)) {
+    LOG(FATAL) << "Failed to initialize unwinder object: "
+               << unwindstack::GetErrorCodeString(error_data.code);
   }
 
   std::string amfd_data;
diff --git a/debuggerd/handler/debuggerd_fallback.cpp b/debuggerd/handler/debuggerd_fallback.cpp
index c8b25ae..70e3022 100644
--- a/debuggerd/handler/debuggerd_fallback.cpp
+++ b/debuggerd/handler/debuggerd_fallback.cpp
@@ -31,12 +31,9 @@
 #include <android-base/unique_fd.h>
 #include <async_safe/log.h>
 #include <bionic/reserved_signals.h>
-#include <unwindstack/DexFiles.h>
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/Maps.h>
+#include <unwindstack/AndroidUnwinder.h>
 #include <unwindstack/Memory.h>
 #include <unwindstack/Regs.h>
-#include <unwindstack/Unwinder.h>
 
 #include "debuggerd/handler.h"
 #include "handler/fallback.h"
@@ -75,11 +72,11 @@
 
     // Do not use the thread cache here because it will call pthread_key_create
     // which doesn't work in linker code. See b/189803009.
-    // Use a normal cached object because the process is stopped, and there
+    // Use a normal cached object because the thread is stopped, and there
     // is no chance of data changing between reads.
     auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(getpid());
     // TODO: Create this once and store it in a global?
-    unwindstack::UnwinderFromPid unwinder(kMaxFrames, getpid(), process_memory);
+    unwindstack::AndroidLocalUnwinder unwinder(process_memory);
     dump_backtrace_thread(output_fd, &unwinder, thread);
   }
   __linker_disable_fallback_allocator();
diff --git a/debuggerd/libdebuggerd/backtrace.cpp b/debuggerd/libdebuggerd/backtrace.cpp
index fd91038..3ff9710 100644
--- a/debuggerd/libdebuggerd/backtrace.cpp
+++ b/debuggerd/libdebuggerd/backtrace.cpp
@@ -37,6 +37,7 @@
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <log/log.h>
+#include <unwindstack/AndroidUnwinder.h>
 #include <unwindstack/Unwinder.h>
 
 #include "libdebuggerd/types.h"
@@ -57,7 +58,7 @@
   _LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid);
 }
 
-void dump_backtrace_thread(int output_fd, unwindstack::Unwinder* unwinder,
+void dump_backtrace_thread(int output_fd, unwindstack::AndroidUnwinder* unwinder,
                            const ThreadInfo& thread) {
   log_t log;
   log.tfd = output_fd;
@@ -65,21 +66,17 @@
 
   _LOG(&log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", thread.thread_name.c_str(), thread.tid);
 
-  unwinder->SetRegs(thread.registers.get());
-  unwinder->Unwind();
-  if (unwinder->NumFrames() == 0) {
-    _LOG(&log, logtype::THREAD, "Unwind failed: tid = %d\n", thread.tid);
-    if (unwinder->LastErrorCode() != unwindstack::ERROR_NONE) {
-      _LOG(&log, logtype::THREAD, "  Error code: %s\n", unwinder->LastErrorCodeString());
-      _LOG(&log, logtype::THREAD, "  Error address: 0x%" PRIx64 "\n", unwinder->LastErrorAddress());
-    }
+  unwindstack::AndroidUnwinderData data;
+  if (!unwinder->Unwind(thread.registers.get(), data)) {
+    _LOG(&log, logtype::THREAD, "Unwind failed: tid = %d: Error %s\n", thread.tid,
+         data.GetErrorString().c_str());
     return;
   }
 
-  log_backtrace(&log, unwinder, "  ");
+  log_backtrace(&log, unwinder, data, "  ");
 }
 
-void dump_backtrace(android::base::unique_fd output_fd, unwindstack::Unwinder* unwinder,
+void dump_backtrace(android::base::unique_fd output_fd, unwindstack::AndroidUnwinder* unwinder,
                     const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread) {
   log_t log;
   log.tfd = output_fd.get();
diff --git a/debuggerd/libdebuggerd/gwp_asan.cpp b/debuggerd/libdebuggerd/gwp_asan.cpp
index 3d96627..d8f74e0 100644
--- a/debuggerd/libdebuggerd/gwp_asan.cpp
+++ b/debuggerd/libdebuggerd/gwp_asan.cpp
@@ -21,9 +21,8 @@
 #include "gwp_asan/common.h"
 #include "gwp_asan/crash_handler.h"
 
-#include <unwindstack/Maps.h>
+#include <unwindstack/AndroidUnwinder.h>
 #include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
 #include <unwindstack/Unwinder.h>
 
 #include "tombstone.pb.h"
@@ -106,7 +105,8 @@
 
 constexpr size_t kMaxTraceLength = gwp_asan::AllocationMetadata::kMaxTraceLengthToCollect;
 
-void GwpAsanCrashData::AddCauseProtos(Tombstone* tombstone, unwindstack::Unwinder* unwinder) const {
+void GwpAsanCrashData::AddCauseProtos(Tombstone* tombstone,
+                                      unwindstack::AndroidUnwinder* unwinder) const {
   if (!CrashIsMine()) {
     ALOGE("Internal Error: AddCauseProtos() on a non-GWP-ASan crash.");
     return;
@@ -140,7 +140,6 @@
 
   heap_object->set_address(__gwp_asan_get_allocation_address(responsible_allocation_));
   heap_object->set_size(__gwp_asan_get_allocation_size(responsible_allocation_));
-  unwinder->SetDisplayBuildID(true);
 
   std::unique_ptr<uintptr_t[]> frames(new uintptr_t[kMaxTraceLength]);
 
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/backtrace.h b/debuggerd/libdebuggerd/include/libdebuggerd/backtrace.h
index c20d090..531afea 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/backtrace.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/backtrace.h
@@ -30,16 +30,16 @@
 
 // Forward delcaration
 namespace unwindstack {
-class Unwinder;
+class AndroidUnwinder;
 }
 
 // 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(android::base::unique_fd output_fd, unwindstack::Unwinder* unwinder,
+void dump_backtrace(android::base::unique_fd output_fd, unwindstack::AndroidUnwinder* unwinder,
                     const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread);
 
 void dump_backtrace_header(int output_fd);
-void dump_backtrace_thread(int output_fd, unwindstack::Unwinder* unwinder,
+void dump_backtrace_thread(int output_fd, unwindstack::AndroidUnwinder* unwinder,
                            const ThreadInfo& thread);
 void dump_backtrace_footer(int output_fd);
 
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/gwp_asan.h b/debuggerd/libdebuggerd/include/libdebuggerd/gwp_asan.h
index a979370..0429643 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/gwp_asan.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/gwp_asan.h
@@ -26,9 +26,15 @@
 #include "types.h"
 #include "utility.h"
 
+// Forward delcarations
 class Cause;
 class Tombstone;
 
+namespace unwindstack {
+class AndroidUnwinder;
+class Memory;
+}  // namespace unwindstack
+
 class GwpAsanCrashData {
  public:
   GwpAsanCrashData() = delete;
@@ -52,7 +58,7 @@
   // allocator crash state.
   uintptr_t GetFaultAddress() const;
 
-  void AddCauseProtos(Tombstone* tombstone, unwindstack::Unwinder* unwinder) const;
+  void AddCauseProtos(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder) const;
 
  protected:
   // Is GWP-ASan responsible for this crash.
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/scudo.h b/debuggerd/libdebuggerd/include/libdebuggerd/scudo.h
index 172ffe9..a506859 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/scudo.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/scudo.h
@@ -23,9 +23,15 @@
 
 #include "scudo/interface.h"
 
+// Forward delcarations
 class Cause;
 class Tombstone;
 
+namespace unwindstack {
+class AndroidUnwinder;
+class Memory;
+}  // namespace unwindstack
+
 class ScudoCrashData {
  public:
   ScudoCrashData() = delete;
@@ -34,12 +40,12 @@
 
   bool CrashIsMine() const;
 
-  void AddCauseProtos(Tombstone* tombstone, unwindstack::Unwinder* unwinder) const;
+  void AddCauseProtos(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder) const;
 
  private:
   scudo_error_info error_info_ = {};
   uintptr_t untagged_fault_addr_;
 
   void FillInCause(Cause* cause, const scudo_error_report* report,
-                   unwindstack::Unwinder* unwinder) const;
+                   unwindstack::AndroidUnwinder* unwinder) const;
 };
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h b/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
index 7bf1688..be999e0 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
@@ -37,7 +37,7 @@
 
 namespace unwindstack {
 struct FrameData;
-class Unwinder;
+class AndroidUnwinder;
 }
 
 // The maximum number of frames to save when unwinding.
@@ -51,7 +51,7 @@
 
 /* Creates a tombstone file and writes the crash dump to it. */
 void engrave_tombstone(android::base::unique_fd output_fd, android::base::unique_fd proto_fd,
-                       unwindstack::Unwinder* unwinder,
+                       unwindstack::AndroidUnwinder* unwinder,
                        const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread,
                        const ProcessInfo& process_info, OpenFilesList* open_files,
                        std::string* amfd_data);
@@ -59,7 +59,7 @@
 void engrave_tombstone_ucontext(int tombstone_fd, int proto_fd, uint64_t abort_msg_address,
                                 siginfo_t* siginfo, ucontext_t* ucontext);
 
-void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
+void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
                              const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
                              const ProcessInfo& process_info, const OpenFilesList* open_files);
 
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
index 63e142f..25b03af 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
@@ -73,11 +73,13 @@
 void _VLOG(log_t* log, logtype ltype, const char* fmt, va_list ap);
 
 namespace unwindstack {
-class Unwinder;
+class AndroidUnwinder;
 class Memory;
+struct AndroidUnwinderData;
 }
 
-void log_backtrace(log_t* log, unwindstack::Unwinder* unwinder, const char* prefix);
+void log_backtrace(log_t* log, unwindstack::AndroidUnwinder* unwinder,
+                   unwindstack::AndroidUnwinderData& data, const char* prefix);
 
 ssize_t dump_memory(void* out, size_t len, uint8_t* tags, size_t tags_len, uint64_t* addr,
                     unwindstack::Memory* memory);
diff --git a/debuggerd/libdebuggerd/scudo.cpp b/debuggerd/libdebuggerd/scudo.cpp
index a4836d7..27fae25 100644
--- a/debuggerd/libdebuggerd/scudo.cpp
+++ b/debuggerd/libdebuggerd/scudo.cpp
@@ -17,8 +17,8 @@
 #include "libdebuggerd/scudo.h"
 #include "libdebuggerd/tombstone.h"
 
+#include "unwindstack/AndroidUnwinder.h"
 #include "unwindstack/Memory.h"
-#include "unwindstack/Unwinder.h"
 
 #include <android-base/macros.h>
 #include <bionic/macros.h>
@@ -80,7 +80,7 @@
 }
 
 void ScudoCrashData::FillInCause(Cause* cause, const scudo_error_report* report,
-                                 unwindstack::Unwinder* unwinder) const {
+                                 unwindstack::AndroidUnwinder* unwinder) const {
   MemoryError* memory_error = cause->mutable_memory_error();
   HeapObject* heap_object = memory_error->mutable_heap();
 
@@ -102,7 +102,6 @@
 
   heap_object->set_address(report->allocation_address);
   heap_object->set_size(report->allocation_size);
-  unwinder->SetDisplayBuildID(true);
 
   heap_object->set_allocation_tid(report->allocation_tid);
   for (size_t i = 0; i < arraysize(report->allocation_trace) && report->allocation_trace[i]; ++i) {
@@ -123,7 +122,8 @@
   set_human_readable_cause(cause, untagged_fault_addr_);
 }
 
-void ScudoCrashData::AddCauseProtos(Tombstone* tombstone, unwindstack::Unwinder* unwinder) const {
+void ScudoCrashData::AddCauseProtos(Tombstone* tombstone,
+                                    unwindstack::AndroidUnwinder* unwinder) const {
   size_t report_num = 0;
   while (report_num < sizeof(error_info_.reports) / sizeof(error_info_.reports[0]) &&
          error_info_.reports[report_num].error_type != UNKNOWN) {
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index eda7182..5ca2c00 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -36,9 +36,9 @@
 #include <async_safe/log.h>
 #include <log/log.h>
 #include <private/android_filesystem_config.h>
-#include <unwindstack/Memory.h>
+#include <unwindstack/AndroidUnwinder.h>
+#include <unwindstack/Error.h>
 #include <unwindstack/Regs.h>
-#include <unwindstack/Unwinder.h>
 
 #include "libdebuggerd/backtrace.h"
 #include "libdebuggerd/open_files_list.h"
@@ -101,12 +101,16 @@
     }
   }
 
-  auto process_memory =
-      unwindstack::Memory::CreateProcessMemoryCached(getpid());
-  unwindstack::UnwinderFromPid unwinder(kMaxFrames, pid, unwindstack::Regs::CurrentArch(), nullptr,
-                                        process_memory);
-  if (!unwinder.Init()) {
-    async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to init unwinder object");
+  // Do not use the thread cache here because it will call pthread_key_create
+  // which doesn't work in linker code. See b/189803009.
+  // Use a normal cached object because the thread is stopped, and there
+  // is no chance of data changing between reads.
+  auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(getpid());
+  unwindstack::AndroidLocalUnwinder unwinder(process_memory);
+  unwindstack::ErrorData error;
+  if (!unwinder.Initialize(error)) {
+    async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to init unwinder object: %s",
+                          unwindstack::GetErrorCodeString(error.code));
     return;
   }
 
@@ -116,7 +120,8 @@
                     process_info, nullptr, nullptr);
 }
 
-void engrave_tombstone(unique_fd output_fd, unique_fd proto_fd, unwindstack::Unwinder* unwinder,
+void engrave_tombstone(unique_fd output_fd, unique_fd proto_fd,
+                       unwindstack::AndroidUnwinder* unwinder,
                        const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
                        const ProcessInfo& process_info, OpenFilesList* open_files,
                        std::string* amfd_data) {
diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index bee4a67..159ebc8 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -56,10 +56,11 @@
 #include <private/android_filesystem_config.h>
 
 #include <procinfo/process.h>
+#include <unwindstack/AndroidUnwinder.h>
+#include <unwindstack/Error.h>
+#include <unwindstack/MapInfo.h>
 #include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
 #include <unwindstack/Regs.h>
-#include <unwindstack/Unwinder.h>
 
 #include "libdebuggerd/open_files_list.h"
 #include "libdebuggerd/utility.h"
@@ -189,7 +190,7 @@
       error_type_str, diff, byte_suffix, location_str, heap_object.size(), heap_object.address()));
 }
 
-static void dump_probable_cause(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
+static void dump_probable_cause(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
                                 const ProcessInfo& process_info, const ThreadInfo& main_thread) {
 #if defined(USE_SCUDO)
   ScudoCrashData scudo_crash_data(unwinder->GetProcessMemory().get(), process_info);
@@ -245,9 +246,9 @@
   }
 }
 
-static void dump_abort_message(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
+static void dump_abort_message(Tombstone* tombstone,
+                               std::shared_ptr<unwindstack::Memory>& process_memory,
                                const ProcessInfo& process_info) {
-  std::shared_ptr<unwindstack::Memory> process_memory = unwinder->GetProcessMemory();
   uintptr_t address = process_info.abort_msg_address;
   if (address == 0) {
     return;
@@ -348,7 +349,7 @@
   f->set_build_id(frame.map_info->GetPrintableBuildID());
 }
 
-static void dump_registers(unwindstack::Unwinder* unwinder,
+static void dump_registers(unwindstack::AndroidUnwinder* unwinder,
                            const std::unique_ptr<unwindstack::Regs>& regs, Thread& thread,
                            bool memory_dump) {
   if (regs == nullptr) {
@@ -402,27 +403,9 @@
   });
 }
 
-static void log_unwinder_error(unwindstack::Unwinder* unwinder) {
-  if (unwinder->LastErrorCode() == unwindstack::ERROR_NONE) {
-    return;
-  }
-
-  async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "  error code: %s",
-                        unwinder->LastErrorCodeString());
-  async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "  error address: 0x%" PRIx64,
-                        unwinder->LastErrorAddress());
-}
-
-static void dump_thread_backtrace(unwindstack::Unwinder* unwinder, Thread& thread) {
-  if (unwinder->NumFrames() == 0) {
-    async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to unwind");
-    log_unwinder_error(unwinder);
-    return;
-  }
-
-  unwinder->SetDisplayBuildID(true);
+static void dump_thread_backtrace(std::vector<unwindstack::FrameData>& frames, Thread& thread) {
   std::set<std::string> unreadable_elf_files;
-  for (const auto& frame : unwinder->frames()) {
+  for (const auto& frame : frames) {
     BacktraceFrame* f = thread.add_current_backtrace();
     fill_in_backtrace_frame(f, frame);
     if (frame.map_info != nullptr && frame.map_info->ElfFileNotReadable()) {
@@ -446,7 +429,7 @@
   }
 }
 
-static void dump_thread(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
+static void dump_thread(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
                         const ThreadInfo& thread_info, bool memory_dump = false) {
   Thread thread;
 
@@ -455,36 +438,29 @@
   thread.set_tagged_addr_ctrl(thread_info.tagged_addr_ctrl);
   thread.set_pac_enabled_keys(thread_info.pac_enabled_keys);
 
-  if (thread_info.pid == getpid() && thread_info.pid != thread_info.tid) {
-    // Fallback path for non-main thread, doing unwind from running process.
-    unwindstack::ThreadUnwinder thread_unwinder(kMaxFrames, unwinder->GetMaps());
-    if (!thread_unwinder.Init()) {
-      async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
-                            "Unable to initialize ThreadUnwinder object.");
-      log_unwinder_error(&thread_unwinder);
-      return;
-    }
-
-    std::unique_ptr<unwindstack::Regs> initial_regs;
-    thread_unwinder.UnwindWithSignal(BIONIC_SIGNAL_BACKTRACE, thread_info.tid, &initial_regs);
-    dump_registers(&thread_unwinder, initial_regs, thread, memory_dump);
-    dump_thread_backtrace(&thread_unwinder, thread);
+  unwindstack::AndroidUnwinderData data;
+  // Indicate we want a copy of the initial registers.
+  data.saved_initial_regs = std::make_optional<std::unique_ptr<unwindstack::Regs>>();
+  bool unwind_ret;
+  if (thread_info.registers != nullptr) {
+    unwind_ret = unwinder->Unwind(thread_info.registers.get(), data);
   } else {
-    dump_registers(unwinder, thread_info.registers, thread, memory_dump);
-    std::unique_ptr<unwindstack::Regs> regs_copy(thread_info.registers->Clone());
-    unwinder->SetRegs(regs_copy.get());
-    unwinder->Unwind();
-    dump_thread_backtrace(unwinder, thread);
+    unwind_ret = unwinder->Unwind(thread_info.tid, data);
   }
+  if (!unwind_ret) {
+    async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "Unwind failed for tid %d: Error %s",
+                          thread_info.tid, data.GetErrorString().c_str());
+  } else {
+    dump_thread_backtrace(data.frames, thread);
+  }
+  dump_registers(unwinder, *data.saved_initial_regs, thread, memory_dump);
 
   auto& threads = *tombstone->mutable_threads();
   threads[thread_info.tid] = thread;
 }
 
-static void dump_mappings(Tombstone* tombstone, unwindstack::Unwinder* unwinder) {
-  unwindstack::Maps* maps = unwinder->GetMaps();
-  std::shared_ptr<unwindstack::Memory> process_memory = unwinder->GetProcessMemory();
-
+static void dump_mappings(Tombstone* tombstone, unwindstack::Maps* maps,
+                          std::shared_ptr<unwindstack::Memory>& process_memory) {
   for (const auto& map_info : *maps) {
     auto* map = tombstone->add_memory_mappings();
     map->set_begin_address(map_info->start());
@@ -593,7 +569,8 @@
 }
 
 static void dump_tags_around_fault_addr(Signal* signal, const Tombstone& tombstone,
-                                        unwindstack::Unwinder* unwinder, uintptr_t fault_addr) {
+                                        std::shared_ptr<unwindstack::Memory>& process_memory,
+                                        uintptr_t fault_addr) {
   if (tombstone.arch() != Architecture::ARM64) return;
 
   fault_addr = untag_address(fault_addr);
@@ -604,8 +581,6 @@
   // a valid address for us to dump tags from.
   if (fault_addr < kBytesToRead / 2) return;
 
-  unwindstack::Memory* memory = unwinder->GetProcessMemory().get();
-
   constexpr uintptr_t kRowStartMask = ~(kNumTagColumns * kTagGranuleSize - 1);
   size_t start_address = (fault_addr & kRowStartMask) - kBytesToRead / 2;
   MemoryDump tag_dump;
@@ -614,7 +589,7 @@
   // Attempt to read the first tag. If reading fails, this likely indicates the
   // lowest touched page is inaccessible or not marked with PROT_MTE.
   // Fast-forward over pages until one has tags, or we exhaust the search range.
-  while (memory->ReadTag(start_address) < 0) {
+  while (process_memory->ReadTag(start_address) < 0) {
     size_t page_size = sysconf(_SC_PAGE_SIZE);
     size_t bytes_to_next_page = page_size - (start_address % page_size);
     if (bytes_to_next_page >= granules_to_read * kTagGranuleSize) return;
@@ -626,7 +601,7 @@
   std::string* mte_tags = tag_dump.mutable_arm_mte_metadata()->mutable_memory_tags();
 
   for (size_t i = 0; i < granules_to_read; ++i) {
-    long tag = memory->ReadTag(start_address + i * kTagGranuleSize);
+    long tag = process_memory->ReadTag(start_address + i * kTagGranuleSize);
     if (tag < 0) break;
     mte_tags->push_back(static_cast<uint8_t>(tag));
   }
@@ -636,7 +611,7 @@
   }
 }
 
-void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
+void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
                              const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
                              const ProcessInfo& process_info, const OpenFilesList* open_files) {
   Tombstone result;
@@ -691,12 +666,12 @@
     sig.set_has_fault_address(true);
     uintptr_t fault_addr = process_info.maybe_tagged_fault_address;
     sig.set_fault_address(fault_addr);
-    dump_tags_around_fault_addr(&sig, result, unwinder, fault_addr);
+    dump_tags_around_fault_addr(&sig, result, unwinder->GetProcessMemory(), fault_addr);
   }
 
   *result.mutable_signal_info() = sig;
 
-  dump_abort_message(&result, unwinder, process_info);
+  dump_abort_message(&result, unwinder->GetProcessMemory(), process_info);
 
   // Dump the main thread, but save the memory around the registers.
   dump_thread(&result, unwinder, main_thread, /* memory_dump */ true);
@@ -709,7 +684,7 @@
 
   dump_probable_cause(&result, unwinder, process_info, main_thread);
 
-  dump_mappings(&result, unwinder);
+  dump_mappings(&result, unwinder->GetMaps(), unwinder->GetProcessMemory());
 
   // Only dump logs on debuggable devices.
   if (android::base::GetBoolProperty("ro.debuggable", false)) {
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index ecd98a4..74a1423 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -39,6 +39,7 @@
 #include <bionic/reserved_signals.h>
 #include <debuggerd/handler.h>
 #include <log/log.h>
+#include <unwindstack/AndroidUnwinder.h>
 #include <unwindstack/Memory.h>
 #include <unwindstack/Unwinder.h>
 
@@ -483,10 +484,10 @@
   return describe_end(value, desc);
 }
 
-void log_backtrace(log_t* log, unwindstack::Unwinder* unwinder, const char* prefix) {
+void log_backtrace(log_t* log, unwindstack::AndroidUnwinder* unwinder,
+                   unwindstack::AndroidUnwinderData& data, const char* prefix) {
   std::set<std::string> unreadable_elf_files;
-  unwinder->SetDisplayBuildID(true);
-  for (const auto& frame : unwinder->frames()) {
+  for (const auto& frame : data.frames) {
     if (frame.map_info != nullptr && frame.map_info->ElfFileNotReadable()) {
       unreadable_elf_files.emplace(frame.map_info->name());
     }
@@ -509,7 +510,7 @@
     }
   }
 
-  for (const auto& frame : unwinder->frames()) {
+  for (const auto& frame : data.frames) {
     _LOG(log, logtype::BACKTRACE, "%s%s\n", prefix, unwinder->FormatFrame(frame).c_str());
   }
 }
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 7639ce5..396bcb8 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -266,24 +266,30 @@
         const char* f2fs_fsck_forced_argv[] = {
                 F2FS_FSCK_BIN, "-f", "-c", "10000", "--debug-cache", blk_device.c_str()};
 
-        if (should_force_check(*fs_stat)) {
-            LINFO << "Running " << F2FS_FSCK_BIN << " -f -c 10000 --debug-cache "
-                  << realpath(blk_device);
-            ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_forced_argv), f2fs_fsck_forced_argv,
-                                      &status, false, LOG_KLOG | LOG_FILE, false, FSCK_LOG_FILE);
+        if (access(F2FS_FSCK_BIN, X_OK)) {
+            LINFO << "Not running " << F2FS_FSCK_BIN << " on " << realpath(blk_device)
+                  << " (executable not in system image)";
         } else {
-            LINFO << "Running " << F2FS_FSCK_BIN << " -a -c 10000 --debug-cache "
-                  << realpath(blk_device);
-            ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv, &status, false,
-                                      LOG_KLOG | LOG_FILE, false, FSCK_LOG_FILE);
-        }
-        if (ret < 0) {
-            /* No need to check for error in fork, we can't really handle it now */
-            LERROR << "Failed trying to run " << F2FS_FSCK_BIN;
-            *fs_stat |= FS_STAT_FSCK_FAILED;
-        } else if (status != 0) {
-            LINFO << F2FS_FSCK_BIN << " returned status 0x" << std::hex << status;
-            *fs_stat |= FS_STAT_FSCK_FS_FIXED;
+            if (should_force_check(*fs_stat)) {
+                LINFO << "Running " << F2FS_FSCK_BIN << " -f -c 10000 --debug-cache "
+                      << realpath(blk_device);
+                ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_forced_argv), f2fs_fsck_forced_argv,
+                                          &status, false, LOG_KLOG | LOG_FILE, false,
+                                          FSCK_LOG_FILE);
+            } else {
+                LINFO << "Running " << F2FS_FSCK_BIN << " -a -c 10000 --debug-cache "
+                      << realpath(blk_device);
+                ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv, &status,
+                                          false, LOG_KLOG | LOG_FILE, false, FSCK_LOG_FILE);
+            }
+            if (ret < 0) {
+                /* No need to check for error in fork, we can't really handle it now */
+                LERROR << "Failed trying to run " << F2FS_FSCK_BIN;
+                *fs_stat |= FS_STAT_FSCK_FAILED;
+            } else if (status != 0) {
+                LINFO << F2FS_FSCK_BIN << " returned status 0x" << std::hex << status;
+                *fs_stat |= FS_STAT_FSCK_FS_FIXED;
+            }
         }
     }
     android::base::SetProperty("ro.boottime.init.fsck." + Basename(target),
diff --git a/libprocessgroup/profiles/task_profiles.json b/libprocessgroup/profiles/task_profiles.json
index f5533c2..4092c1a 100644
--- a/libprocessgroup/profiles/task_profiles.json
+++ b/libprocessgroup/profiles/task_profiles.json
@@ -224,19 +224,6 @@
       ]
     },
     {
-      "Name": "VMCompilationPerformance",
-      "Actions": [
-        {
-          "Name": "JoinCgroup",
-          "Params":
-          {
-            "Controller": "cpu",
-            "Path": "system"
-          }
-        }
-      ]
-    },
-    {
       "Name": "CpuPolicySpread",
       "Actions": [
         {
@@ -660,6 +647,10 @@
       "Profiles": [ "ServicePerformance", "LowIoPriority", "TimerSlackNormal" ]
     },
     {
+      "Name": "VMCompilationPerformance",
+      "Profiles": [ "HighPerformance", "ProcessCapacityHigh", "LowIoPriority", "TimerSlackNormal" ]
+    },
+    {
       "Name": "SCHED_SP_RT_APP",
       "Profiles": [ "RealtimePerformance", "MaxIoPriority", "TimerSlackNormal" ]
     },
diff --git a/libsparse/img2simg.cpp b/libsparse/img2simg.cpp
index 3e24cc0..51580f7 100644
--- a/libsparse/img2simg.cpp
+++ b/libsparse/img2simg.cpp
@@ -38,24 +38,41 @@
 #endif
 
 void usage() {
-  fprintf(stderr, "Usage: img2simg <raw_image_file> <sparse_image_file> [<block_size>]\n");
+  fprintf(stderr, "Usage: img2simg [-s] <raw_image_file> <sparse_image_file> [<block_size>]\n");
 }
 
 int main(int argc, char* argv[]) {
+  char *arg_in;
+  char *arg_out;
+  enum sparse_read_mode mode = SPARSE_READ_MODE_NORMAL;
+  int extra;
   int in;
+  int opt;
   int out;
   int ret;
   struct sparse_file* s;
   unsigned int block_size = 4096;
   off64_t len;
 
-  if (argc < 3 || argc > 4) {
+  while ((opt = getopt(argc, argv, "s")) != -1) {
+    switch (opt) {
+      case 's':
+        mode = SPARSE_READ_MODE_HOLE;
+        break;
+      default:
+        usage();
+        exit(-1);
+    }
+  }
+
+  extra = argc - optind;
+  if (extra < 2 || extra > 3) {
     usage();
     exit(-1);
   }
 
-  if (argc == 4) {
-    block_size = atoi(argv[3]);
+  if (extra == 3) {
+    block_size = atoi(argv[optind + 2]);
   }
 
   if (block_size < 1024 || block_size % 4 != 0) {
@@ -63,22 +80,24 @@
     exit(-1);
   }
 
-  if (strcmp(argv[1], "-") == 0) {
+  arg_in = argv[optind];
+  if (strcmp(arg_in, "-") == 0) {
     in = STDIN_FILENO;
   } else {
-    in = open(argv[1], O_RDONLY | O_BINARY);
+    in = open(arg_in, O_RDONLY | O_BINARY);
     if (in < 0) {
-      fprintf(stderr, "Cannot open input file %s\n", argv[1]);
+      fprintf(stderr, "Cannot open input file %s\n", arg_in);
       exit(-1);
     }
   }
 
-  if (strcmp(argv[2], "-") == 0) {
+  arg_out = argv[optind + 1];
+  if (strcmp(arg_out, "-") == 0) {
     out = STDOUT_FILENO;
   } else {
-    out = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0664);
+    out = open(arg_out, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0664);
     if (out < 0) {
-      fprintf(stderr, "Cannot open output file %s\n", argv[2]);
+      fprintf(stderr, "Cannot open output file %s\n", arg_out);
       exit(-1);
     }
   }
@@ -93,7 +112,7 @@
   }
 
   sparse_file_verbose(s);
-  ret = sparse_file_read(s, in, SPARSE_READ_MODE_NORMAL, false);
+  ret = sparse_file_read(s, in, mode, false);
   if (ret) {
     fprintf(stderr, "Failed to read file\n");
     exit(-1);
diff --git a/rootdir/init.rc b/rootdir/init.rc
index caed4e1..2746314 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -688,8 +688,6 @@
     copy /data/system/entropy.dat /dev/urandom
 
     mkdir /data/vendor 0771 root root encryption=Require
-    mkdir /data/vendor_ce 0771 root root encryption=None
-    mkdir /data/vendor_de 0771 root root encryption=None
     mkdir /data/vendor/hardware 0771 root root
 
     # Start tombstoned early to be able to store tombstones.
@@ -738,6 +736,13 @@
     # To handle userspace reboots as well as devices that use FDE, make sure
     # that apexd is started cleanly here (set apexd.status="") and that it is
     # restarted if it's already running.
+    #
+    # /data/apex uses encryption=None because direct I/O support is needed on
+    # APEX files, but some devices don't support direct I/O on encrypted files.
+    # Also, APEXes are public information, similar to the system image.
+    # /data/apex/decompressed and /data/apex/ota_reserved override this setting;
+    # they are encrypted so that files in them can be hard-linked into
+    # /data/rollback which is encrypted.
     mkdir /data/apex 0755 root system encryption=None
     mkdir /data/apex/active 0755 root system
     mkdir /data/apex/backup 0700 root system
@@ -834,6 +839,8 @@
     exec - virtualizationservice system -- /bin/rm -rf /data/misc/virtualizationservice
     mkdir /data/misc/virtualizationservice 0770 system system
 
+    # /data/preloads uses encryption=None because it only contains preloaded
+    # files that are public information, similar to the system image.
     mkdir /data/preloads 0775 system system encryption=None
 
     # For security reasons, /data/local/tmp should always be empty.
@@ -877,7 +884,10 @@
     chown system system /data/resource-cache
     chmod 0771 /data/resource-cache
 
-    # create the lost+found directories, so as to enforce our permissions
+    # Ensure that lost+found exists and has the correct permissions.  Linux
+    # filesystems expect this directory to exist; it's where the fsck tool puts
+    # any recovered files that weren't present in any directory.  It must be
+    # unencrypted, as fsck must be able to write to it.
     mkdir /data/lost+found 0770 root root encryption=None
 
     # create directory for DRM plug-ins - give drm the read/write access to
@@ -905,14 +915,22 @@
     mkdir /data/system/heapdump 0700 system system
     mkdir /data/system/users 0775 system system
 
-    mkdir /data/system_de 0770 system system encryption=None
-    mkdir /data/system_ce 0770 system system encryption=None
-
-    mkdir /data/misc_de 01771 system misc encryption=None
+    # Create the parent directories of the user CE and DE storage directories.
+    # These parent directories must use encryption=None, since each of their
+    # subdirectories uses a different encryption policy (a per-user one), and
+    # encryption policies apply recursively.  These directories should never
+    # contain any subdirectories other than the per-user ones.  /data/media/obb
+    # is an exception that exists for legacy reasons.
+    mkdir /data/media 0770 media_rw media_rw encryption=None
+    exec - media_rw media_rw -- /system/bin/chattr +F /data/media
     mkdir /data/misc_ce 01771 system misc encryption=None
-
+    mkdir /data/misc_de 01771 system misc encryption=None
+    mkdir /data/system_ce 0770 system system encryption=None
+    mkdir /data/system_de 0770 system system encryption=None
     mkdir /data/user 0711 system system encryption=None
     mkdir /data/user_de 0711 system system encryption=None
+    mkdir /data/vendor_ce 0771 root root encryption=None
+    mkdir /data/vendor_de 0771 root root encryption=None
 
     # A tmpfs directory, which will contain all apps CE DE data directory that
     # bind mount from the original source.
@@ -961,11 +979,8 @@
     wait_for_prop apexd.status activated
     perform_apex_config
 
-    mkdir /data/media 0770 media_rw media_rw encryption=None
-    exec - media_rw media_rw -- /system/bin/chattr +F /data/media
-
     # Create directories for boot animation.
-    mkdir /data/bootanim 0755 system system encryption=None
+    mkdir /data/bootanim 0755 system system encryption=DeleteIfNecessary
 
     exec_start derive_sdk