Merge "Zero-length packet send bug resolution for fastboot."
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 2a769c7..70f333e 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -303,6 +303,7 @@
       process_info->scudo_stack_depot = crash_info->data.d.scudo_stack_depot;
       process_info->scudo_region_info = crash_info->data.d.scudo_region_info;
       process_info->scudo_ring_buffer = crash_info->data.d.scudo_ring_buffer;
+      process_info->scudo_ring_buffer_size = crash_info->data.d.scudo_ring_buffer_size;
       FALLTHROUGH_INTENDED;
     case 1:
     case 2:
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index c64de0e..7120d73 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -187,27 +187,29 @@
  * mutex is being held, so we don't want to use any libc functions that
  * could allocate memory or hold a lock.
  */
-static void log_signal_summary(const siginfo_t* info) {
+static void log_signal_summary(const siginfo_t* si) {
   char main_thread_name[MAX_TASK_NAME_LEN + 1];
   if (!get_main_thread_name(main_thread_name, sizeof(main_thread_name))) {
     strncpy(main_thread_name, "<unknown>", sizeof(main_thread_name));
   }
 
-  if (info->si_signo == BIONIC_SIGNAL_DEBUGGER) {
+  if (si->si_signo == BIONIC_SIGNAL_DEBUGGER) {
     async_safe_format_log(ANDROID_LOG_INFO, "libc", "Requested dump for pid %d (%s)", __getpid(),
                           main_thread_name);
     return;
   }
 
-  // Many signals don't have an address or sender.
-  char addr_desc[32] = "";  // ", fault addr 0x1234"
-  if (signal_has_si_addr(info)) {
-    async_safe_format_buffer(addr_desc, sizeof(addr_desc), ", fault addr %p", info->si_addr);
-  }
+  // Many signals don't have a sender or extra detail, but some do...
   pid_t self_pid = __getpid();
   char sender_desc[32] = {};  // " from pid 1234, uid 666"
-  if (signal_has_sender(info, self_pid)) {
-    get_signal_sender(sender_desc, sizeof(sender_desc), info);
+  if (signal_has_sender(si, self_pid)) {
+    get_signal_sender(sender_desc, sizeof(sender_desc), si);
+  }
+  char extra_desc[32] = {};  // ", fault addr 0x1234" or ", syscall 1234"
+  if (si->si_signo == SIGSYS && si->si_code == SYS_SECCOMP) {
+    async_safe_format_buffer(extra_desc, sizeof(extra_desc), ", syscall %d", si->si_syscall);
+  } else if (signal_has_si_addr(si)) {
+    async_safe_format_buffer(extra_desc, sizeof(extra_desc), ", fault addr %p", si->si_addr);
   }
 
   char thread_name[MAX_TASK_NAME_LEN + 1];  // one more for termination
@@ -221,8 +223,8 @@
 
   async_safe_format_log(ANDROID_LOG_FATAL, "libc",
                         "Fatal signal %d (%s), code %d (%s%s)%s in tid %d (%s), pid %d (%s)",
-                        info->si_signo, get_signame(info), info->si_code, get_sigcode(info),
-                        sender_desc, addr_desc, __gettid(), thread_name, self_pid, main_thread_name);
+                        si->si_signo, get_signame(si), si->si_code, get_sigcode(si), sender_desc,
+                        extra_desc, __gettid(), thread_name, self_pid, main_thread_name);
 }
 
 /*
@@ -371,12 +373,30 @@
       {.iov_base = thread_info->ucontext, .iov_len = sizeof(ucontext_t)},
   };
 
+  constexpr size_t kHeaderSize = sizeof(version) + sizeof(siginfo_t) + sizeof(ucontext_t);
+
   if (thread_info->process_info.fdsan_table) {
     // Dynamic executables always use version 4. There is no need to increment the version number if
     // the format changes, because the sender (linker) and receiver (crash_dump) are version locked.
     version = 4;
     expected = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataDynamic);
 
+    static_assert(sizeof(CrashInfoHeader) + sizeof(CrashInfoDataDynamic) ==
+                      kHeaderSize + sizeof(thread_info->process_info),
+                  "Wire protocol structs do not match the data sent.");
+#define ASSERT_SAME_OFFSET(MEMBER1, MEMBER2) \
+    static_assert(sizeof(CrashInfoHeader) + offsetof(CrashInfoDataDynamic, MEMBER1) == \
+                      kHeaderSize + offsetof(debugger_process_info, MEMBER2), \
+                  "Wire protocol offset does not match data sent: " #MEMBER1);
+    ASSERT_SAME_OFFSET(fdsan_table_address, fdsan_table);
+    ASSERT_SAME_OFFSET(gwp_asan_state, gwp_asan_state);
+    ASSERT_SAME_OFFSET(gwp_asan_metadata, gwp_asan_metadata);
+    ASSERT_SAME_OFFSET(scudo_stack_depot, scudo_stack_depot);
+    ASSERT_SAME_OFFSET(scudo_region_info, scudo_region_info);
+    ASSERT_SAME_OFFSET(scudo_ring_buffer, scudo_ring_buffer);
+    ASSERT_SAME_OFFSET(scudo_ring_buffer_size, scudo_ring_buffer_size);
+#undef ASSERT_SAME_OFFSET
+
     iovs[3] = {.iov_base = &thread_info->process_info,
                .iov_len = sizeof(thread_info->process_info)};
   } else {
@@ -384,6 +404,10 @@
     version = 1;
     expected = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataStatic);
 
+    static_assert(
+        sizeof(CrashInfoHeader) + sizeof(CrashInfoDataStatic) == kHeaderSize + sizeof(uintptr_t),
+        "Wire protocol structs do not match the data sent.");
+
     iovs[3] = {.iov_base = &thread_info->process_info.abort_msg, .iov_len = sizeof(uintptr_t)};
   }
   errno = 0;
diff --git a/debuggerd/include/debuggerd/handler.h b/debuggerd/include/debuggerd/handler.h
index 68b2e67..1f9f4e2 100644
--- a/debuggerd/include/debuggerd/handler.h
+++ b/debuggerd/include/debuggerd/handler.h
@@ -43,6 +43,7 @@
   const char* scudo_stack_depot;
   const char* scudo_region_info;
   const char* scudo_ring_buffer;
+  size_t scudo_ring_buffer_size;
 };
 
 // These callbacks are called in a signal handler, and thus must be async signal safe.
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/types.h b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
index a51e276..5a2a7ab 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/types.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
@@ -50,6 +50,7 @@
   uintptr_t scudo_stack_depot = 0;
   uintptr_t scudo_region_info = 0;
   uintptr_t scudo_ring_buffer = 0;
+  size_t scudo_ring_buffer_size = 0;
 
   bool has_fault_address = false;
   uintptr_t untagged_fault_address = 0;
diff --git a/debuggerd/libdebuggerd/scudo.cpp b/debuggerd/libdebuggerd/scudo.cpp
index 5d861f8..37e390b 100644
--- a/debuggerd/libdebuggerd/scudo.cpp
+++ b/debuggerd/libdebuggerd/scudo.cpp
@@ -45,7 +45,7 @@
   auto region_info = AllocAndReadFully(process_memory, process_info.scudo_region_info,
                                        __scudo_get_region_info_size());
   auto ring_buffer = AllocAndReadFully(process_memory, process_info.scudo_ring_buffer,
-                                       __scudo_get_ring_buffer_size());
+                                       process_info.scudo_ring_buffer_size);
   if (!stack_depot || !region_info || !ring_buffer) {
     return;
   }
diff --git a/debuggerd/protocol.h b/debuggerd/protocol.h
index f33b2f0..e7cb218 100644
--- a/debuggerd/protocol.h
+++ b/debuggerd/protocol.h
@@ -98,6 +98,7 @@
   uintptr_t scudo_stack_depot;
   uintptr_t scudo_region_info;
   uintptr_t scudo_ring_buffer;
+  size_t scudo_ring_buffer_size;
 };
 
 struct __attribute__((__packed__)) CrashInfo {
diff --git a/debuggerd/test_permissive_mte/Android.bp b/debuggerd/test_permissive_mte/Android.bp
index 1c09240..d3f7520 100644
--- a/debuggerd/test_permissive_mte/Android.bp
+++ b/debuggerd/test_permissive_mte/Android.bp
@@ -18,6 +18,7 @@
 
 cc_binary {
   name: "mte_crash",
+  tidy: false,
   srcs: ["mte_crash.cpp"],
   sanitize: {
     memtag_heap: true,
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index cdff06e..9eb89b6 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -395,6 +395,10 @@
     // first-stage to decide whether to launch snapuserd.
     bool IsSnapuserdRequired();
 
+    // This is primarily used to device reboot. If OTA update is in progress,
+    // init will avoid killing processes
+    bool IsUserspaceSnapshotUpdateInProgress();
+
     enum class SnapshotDriver {
         DM_SNAPSHOT,
         DM_USER,
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 6fed09c..10d2f18 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -4349,5 +4349,16 @@
     return status.source_build_fingerprint();
 }
 
+bool SnapshotManager::IsUserspaceSnapshotUpdateInProgress() {
+    auto slot = GetCurrentSlot();
+    if (slot == Slot::Target) {
+        if (IsSnapuserdRequired()) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 }  // namespace snapshot
 }  // namespace android
diff --git a/healthd/Android.bp b/healthd/Android.bp
index a090b74..76b6ad0 100644
--- a/healthd/Android.bp
+++ b/healthd/Android.bp
@@ -2,17 +2,8 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-cc_library_headers {
-    name: "libhealthd_headers",
-    vendor_available: true,
-    recovery_available: true,
-    export_include_dirs: ["include"],
-    header_libs: ["libbatteryservice_headers"],
-    export_header_lib_headers: ["libbatteryservice_headers"],
-}
-
-cc_library_static {
-    name: "libbatterymonitor",
+cc_defaults {
+    name: "libbatterymonitor_defaults",
     srcs: ["BatteryMonitor.cpp"],
     cflags: ["-Wall", "-Werror"],
     vendor_available: true,
@@ -25,6 +16,66 @@
         // Need HealthInfo definition from headers of these shared
         // libraries. Clients don't need to link to these.
         "android.hardware.health@2.1",
+    ],
+    header_libs: ["libhealthd_headers"],
+    export_header_lib_headers: ["libhealthd_headers"],
+}
+
+cc_defaults {
+    name: "libhealthd_charger_ui_defaults",
+    vendor_available: true,
+    export_include_dirs: [
+        "include",
+        "include_charger",
+    ],
+
+    static_libs: [
+        "libcharger_sysprop",
+        "libhealthd_draw",
+        "libhealthloop",
+        "libminui",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+        "libpng",
+        "libsuspend",
+        "libutils",
+    ],
+
+    header_libs: [
+        "libhealthd_headers",
+    ],
+
+    srcs: [
+        "healthd_mode_charger.cpp",
+        "AnimationParser.cpp",
+    ],
+
+    target: {
+        vendor: {
+            exclude_static_libs: [
+                "libcharger_sysprop",
+            ],
+        },
+    },
+}
+
+cc_library_headers {
+    name: "libhealthd_headers",
+    vendor_available: true,
+    recovery_available: true,
+    export_include_dirs: ["include"],
+    header_libs: ["libbatteryservice_headers"],
+    export_header_lib_headers: ["libbatteryservice_headers"],
+}
+
+cc_library_static {
+    name: "libbatterymonitor",
+    defaults: ["libbatterymonitor_defaults"],
+    static_libs: [
         "android.hardware.health-V1-ndk",
     ],
     whole_static_libs: [
@@ -32,8 +83,20 @@
         // BatteryMonitor.
         "android.hardware.health-translate-ndk",
     ],
-    header_libs: ["libhealthd_headers"],
-    export_header_lib_headers: ["libhealthd_headers"],
+}
+
+// TODO(b/251425963): remove when android.hardware.health is upgraded to V2.
+cc_library_static {
+    name: "libbatterymonitor-V1",
+    defaults: ["libbatterymonitor_defaults"],
+    static_libs: [
+        "android.hardware.health-V1-ndk",
+    ],
+    whole_static_libs: [
+        // Need to translate HIDL to AIDL to support legacy APIs in
+        // BatteryMonitor.
+        "android.hardware.health-translate-V1-ndk",
+    ],
 }
 
 cc_defaults {
@@ -136,50 +199,31 @@
 
 cc_library_static {
     name: "libhealthd_charger_ui",
-    vendor_available: true,
-    export_include_dirs: [
-        "include",
-        "include_charger",
-    ],
+    defaults: ["libhealthd_charger_ui_defaults"],
 
     static_libs: [
         "android.hardware.health-V1-ndk",
         "android.hardware.health-translate-ndk",
-        "libcharger_sysprop",
-        "libhealthd_draw",
-        "libhealthloop",
-        "libminui",
-    ],
-
-    shared_libs: [
-        "libbase",
-        "libcutils",
-        "liblog",
-        "libpng",
-        "libsuspend",
-        "libutils",
-    ],
-
-    header_libs: [
-        "libhealthd_headers",
     ],
 
     export_static_lib_headers: [
         "android.hardware.health-V1-ndk",
     ],
+}
 
-    srcs: [
-        "healthd_mode_charger.cpp",
-        "AnimationParser.cpp",
+// TODO(b/251425963): remove when android.hardware.health is upgraded to V2.
+cc_library_static {
+    name: "libhealthd_charger_ui-V1",
+    defaults: ["libhealthd_charger_ui_defaults"],
+
+    static_libs: [
+        "android.hardware.health-V1-ndk",
+        "android.hardware.health-translate-V1-ndk",
     ],
 
-    target: {
-        vendor: {
-            exclude_static_libs: [
-                "libcharger_sysprop",
-            ],
-        },
-    },
+    export_static_lib_headers: [
+        "android.hardware.health-V1-ndk",
+    ],
 }
 
 cc_library_static {
diff --git a/init/apex_init_util.cpp b/init/apex_init_util.cpp
index d618a6e..c818f8f 100644
--- a/init/apex_init_util.cpp
+++ b/init/apex_init_util.cpp
@@ -18,7 +18,6 @@
 
 #include <glob.h>
 
-#include <map>
 #include <vector>
 
 #include <android-base/logging.h>
@@ -66,18 +65,20 @@
 }
 
 static Result<void> ParseConfigs(const std::vector<std::string>& configs) {
-    Parser parser = CreateApexConfigParser(ActionManager::GetInstance(),
-                     ServiceList::GetInstance());
-    bool success = true;
+    Parser parser =
+            CreateApexConfigParser(ActionManager::GetInstance(), ServiceList::GetInstance());
+    std::vector<std::string> errors;
     for (const auto& c : configs) {
-        success &= parser.ParseConfigFile(c);
+        auto result = parser.ParseConfigFile(c);
+        // We should handle other config files even when there's an error.
+        if (!result.ok()) {
+            errors.push_back(result.error().message());
+        }
     }
-
-    if (success) {
-        return {};
-    } else {
-        return Error() << "Unable to parse apex configs";
+    if (!errors.empty()) {
+        return Error() << "Unable to parse apex configs: " << base::Join(errors, "|");
     }
+    return {};
 }
 
 Result<void> ParseApexConfigs(const std::string& apex_name) {
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 584c04e..1ab69ac 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -21,8 +21,10 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
+#include <android/api-level.h>
 #include <gtest/gtest.h>
 #include <selinux/selinux.h>
+#include <sys/resource.h>
 
 #include "action.h"
 #include "action_manager.h"
@@ -194,6 +196,10 @@
 }
 
 TEST(init, StartConsole) {
+    if (GetProperty("ro.build.type", "") == "user") {
+        GTEST_SKIP() << "Must run on userdebug/eng builds. b/262090304";
+        return;
+    }
     std::string init_script = R"init(
 service console /system/bin/sh
     class core
@@ -622,6 +628,20 @@
     ASSERT_EQ(1u, parser.parse_error_count());
 }
 
+TEST(init, MemLockLimit) {
+    // Test is enforced only for U+ devices
+    if (android::base::GetIntProperty("ro.vendor.api_level", 0) < __ANDROID_API_U__) {
+        GTEST_SKIP();
+    }
+
+    // Verify we are running memlock at, or under, 64KB
+    const unsigned long max_limit = 65536;
+    struct rlimit curr_limit;
+    ASSERT_EQ(getrlimit(RLIMIT_MEMLOCK, &curr_limit), 0);
+    ASSERT_LE(curr_limit.rlim_cur, max_limit);
+    ASSERT_LE(curr_limit.rlim_max, max_limit);
+}
+
 class TestCaseLogger : public ::testing::EmptyTestEventListener {
     void OnTestStart(const ::testing::TestInfo& test_info) override {
 #ifdef __ANDROID__
diff --git a/init/parser.cpp b/init/parser.cpp
index 0a388db..adb41ad 100644
--- a/init/parser.cpp
+++ b/init/parser.cpp
@@ -141,19 +141,19 @@
     return true;
 }
 
-bool Parser::ParseConfigFile(const std::string& path) {
+Result<void> Parser::ParseConfigFile(const std::string& path) {
     LOG(INFO) << "Parsing file " << path << "...";
     android::base::Timer t;
     auto config_contents = ReadFile(path);
     if (!config_contents.ok()) {
-        LOG(INFO) << "Unable to read config file '" << path << "': " << config_contents.error();
-        return false;
+        return Error() << "Unable to read config file '" << path
+                       << "': " << config_contents.error();
     }
 
     ParseData(path, &config_contents.value());
 
     LOG(VERBOSE) << "(Parsing " << path << " took " << t << ".)";
-    return true;
+    return {};
 }
 
 bool Parser::ParseConfigDir(const std::string& path) {
@@ -176,8 +176,8 @@
     // Sort first so we load files in a consistent order (bug 31996208)
     std::sort(files.begin(), files.end());
     for (const auto& file : files) {
-        if (!ParseConfigFile(file)) {
-            LOG(ERROR) << "could not import file '" << file << "'";
+        if (auto result = ParseConfigFile(file); !result.ok()) {
+            LOG(ERROR) << "could not import file '" << file << "': " << result.error();
         }
     }
     return true;
@@ -187,7 +187,11 @@
     if (is_dir(path.c_str())) {
         return ParseConfigDir(path);
     }
-    return ParseConfigFile(path);
+    auto result = ParseConfigFile(path);
+    if (!result.ok()) {
+        LOG(INFO) << result.error();
+    }
+    return result.ok();
 }
 
 }  // namespace init
diff --git a/init/parser.h b/init/parser.h
index 95b0cd7..980ae0c 100644
--- a/init/parser.h
+++ b/init/parser.h
@@ -72,7 +72,7 @@
     Parser();
 
     bool ParseConfig(const std::string& path);
-    bool ParseConfigFile(const std::string& path);
+    Result<void> ParseConfigFile(const std::string& path);
     void AddSectionParser(const std::string& name, std::unique_ptr<SectionParser> parser);
     void AddSingleLineParser(const std::string& prefix, LineCallback callback);
 
diff --git a/init/reboot.cpp b/init/reboot.cpp
index a3fc534..27a7876 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -51,6 +51,7 @@
 #include <bootloader_message/bootloader_message.h>
 #include <cutils/android_reboot.h>
 #include <fs_mgr.h>
+#include <libsnapshot/snapshot.h>
 #include <logwrap/logwrap.h>
 #include <private/android_filesystem_config.h>
 #include <selinux/selinux.h>
@@ -422,11 +423,31 @@
     if (run_fsck && !FindPartitionsToUmount(&block_devices, &emulated_devices, false)) {
         return UMOUNT_STAT_ERROR;
     }
-
+    auto sm = snapshot::SnapshotManager::New();
+    bool ota_update_in_progress = false;
+    if (sm->IsUserspaceSnapshotUpdateInProgress()) {
+        LOG(INFO) << "OTA update in progress";
+        ota_update_in_progress = true;
+    }
     UmountStat stat = UmountPartitions(timeout - t.duration());
     if (stat != UMOUNT_STAT_SUCCESS) {
         LOG(INFO) << "umount timeout, last resort, kill all and try";
         if (DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo();
+        // Since umount timedout, we will try to kill all processes
+        // and do one more attempt to umount the partitions.
+        //
+        // However, if OTA update is in progress, we don't want
+        // to kill the snapuserd daemon as the daemon will
+        // be serving I/O requests. Killing the daemon will
+        // end up with I/O failures. If the update is in progress,
+        // we will just return the umount failure status immediately.
+        // This is ok, given the fact that killing the processes
+        // and doing an umount is just a last effort. We are
+        // still not doing fsck when all processes are killed.
+        //
+        if (ota_update_in_progress) {
+            return stat;
+        }
         KillAllProcesses();
         // even if it succeeds, still it is timeout and do not run fsck with all processes killed
         UmountStat st = UmountPartitions(0ms);
diff --git a/init/service.cpp b/init/service.cpp
index d495b91..b9b3309 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -700,8 +700,9 @@
             if (!result.ok()) {
                 return Error() << "Sending notification failed: " << result.error();
             }
-            return Error() << "createProcessGroup(" << proc_attr_.uid << ", " << pid_
-                           << ") failed for service '" << name_ << "'";
+            return Error() << "createProcessGroup(" << proc_attr_.uid << ", " << pid_ << ", "
+                           << use_memcg << ") failed for service '" << name_
+                           << "': " << strerror(errno);
         }
 
         // When the blkio controller is mounted in the v1 hierarchy, NormalIoPriority is
diff --git a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
index 3188337..6728cc6 100644
--- a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
+++ b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
@@ -60,6 +60,10 @@
         if (prctl(PR_SET_TAGGED_ADDR_CTRL, res & ~PR_MTE_TCF_SYNC, 0, 0, 0) == -1) abort();
     }
     std::unique_ptr<volatile char[]> f(new char[1]);
+    // This out-of-bounds is on purpose: we are testing MTE, which is designed to turn
+    // out-of-bound errors into segfaults.
+    // This binary gets run by src/com/android/tests/init/MteUpgradeTest.java, which
+    // asserts that it crashes as expected.
     f[17] = 'x';
     char buf[1];
     read(1, buf, 1);
diff --git a/libcutils/ashmem_test.cpp b/libcutils/ashmem_test.cpp
index fb657f6..d158427 100644
--- a/libcutils/ashmem_test.cpp
+++ b/libcutils/ashmem_test.cpp
@@ -75,7 +75,7 @@
     unique_fd fd;
     ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
 
-    void *region1;
+    void* region1 = nullptr;
     ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ | PROT_WRITE, &region1));
 
     memcpy(region1, &data, size);
@@ -97,7 +97,7 @@
     unique_fd fd;
     ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
 
-    void *region1;
+    void* region1 = nullptr;
     ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ | PROT_WRITE, &region1));
 
     memcpy(region1, &data, size);
@@ -131,7 +131,7 @@
 
 TEST(AshmemTest, FileOperationsTest) {
     unique_fd fd;
-    void* region;
+    void* region = nullptr;
 
     // Allocate a 4-page buffer, but leave page-sized holes on either side
     constexpr size_t size = PAGE_SIZE * 4;
@@ -246,7 +246,7 @@
     unique_fd fd[nRegions];
     for (int i = 0; i < nRegions; i++) {
         ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd[i], PROT_READ | PROT_WRITE));
-        void *region;
+        void* region = nullptr;
         ASSERT_NO_FATAL_FAILURE(TestMmap(fd[i], size, PROT_READ | PROT_WRITE, &region));
         memcpy(region, &data, size);
         ASSERT_EQ(0, memcmp(region, &data, size));
diff --git a/libcutils/include/cutils/qtaguid.h b/libcutils/include/cutils/qtaguid.h
index a5ffb03..8902c2b 100644
--- a/libcutils/include/cutils/qtaguid.h
+++ b/libcutils/include/cutils/qtaguid.h
@@ -33,12 +33,6 @@
  */
 extern int qtaguid_untagSocket(int sockfd);
 
-/*
- * Enable/disable qtaguid functionnality at a lower level.
- * When pacified, the kernel will accept commands but do nothing.
- */
-extern int qtaguid_setPacifier(int on);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/libdiskconfig/diskconfig.c b/libdiskconfig/diskconfig.c
index c7e1b43..5f34748 100644
--- a/libdiskconfig/diskconfig.c
+++ b/libdiskconfig/diskconfig.c
@@ -398,7 +398,7 @@
         case PART_SCHEME_GPT:
             /* not supported yet */
         default:
-            ALOGE("Uknown partition scheme.");
+            ALOGE("Unknown partition scheme.");
             break;
     }
 
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index 8c00326..468d796 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -49,7 +49,7 @@
 
 static constexpr const char* CGROUP_PROCS_FILE = "/cgroup.procs";
 static constexpr const char* CGROUP_TASKS_FILE = "/tasks";
-static constexpr const char* CGROUP_TASKS_FILE_V2 = "/cgroup.tasks";
+static constexpr const char* CGROUP_TASKS_FILE_V2 = "/cgroup.threads";
 
 uint32_t CgroupController::version() const {
     CHECK(HasValue());
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 45ac99c..1da69ba 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -471,6 +471,11 @@
             *max_processes = processes;
         }
         LOG(VERBOSE) << "Killed " << processes << " processes for processgroup " << initialPid;
+        if (!CgroupsAvailable()) {
+            // makes no sense to retry, because there are no cgroup_procs file
+            processes = 0;  // no remaining processes
+            break;
+        }
         if (retry > 0) {
             std::this_thread::sleep_for(5ms);
             --retry;
diff --git a/libprocessgroup/profiles/task_profiles.json b/libprocessgroup/profiles/task_profiles.json
index c485097..e44d3bf 100644
--- a/libprocessgroup/profiles/task_profiles.json
+++ b/libprocessgroup/profiles/task_profiles.json
@@ -80,17 +80,20 @@
     {
       "Name": "BfqWeight",
       "Controller": "io",
-      "File": "io.bfq.weight"
+      "File": "blkio.bfq.weight",
+      "FileV2": "io.bfq.weight"
     },
     {
       "Name": "CfqGroupIdle",
       "Controller": "io",
-      "File": "io.group_idle"
+      "File": "blkio.group_idle",
+      "FileV2": "io.group_idle"
     },
     {
       "Name": "CfqWeight",
       "Controller": "io",
-      "File": "io.weight"
+      "File": "blkio.weight",
+      "FileV2": "io.weight"
     }
   ],
 
@@ -459,7 +462,7 @@
           {
             "Controller": "blkio",
             "Path": "background"
-	  }
+          }
         },
         {
           "Name": "SetAttribute",
@@ -499,7 +502,7 @@
           {
             "Controller": "blkio",
             "Path": ""
-	  }
+          }
         },
         {
           "Name": "SetAttribute",
@@ -539,7 +542,7 @@
           {
             "Controller": "blkio",
             "Path": ""
-	  }
+          }
         },
         {
           "Name": "SetAttribute",
@@ -579,7 +582,7 @@
           {
             "Controller": "blkio",
             "Path": ""
-	  }
+          }
         },
         {
           "Name": "SetAttribute",
diff --git a/libutils/Android.bp b/libutils/Android.bp
index b07058a..162f0f4 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -21,11 +21,13 @@
     vendor_ramdisk_available: true,
     host_supported: true,
     native_bridge_supported: true,
+    defaults: [
+        "apex-lowest-min-sdk-version",
+    ],
     apex_available: [
         "//apex_available:platform",
         "//apex_available:anyapex",
     ],
-    min_sdk_version: "apex_inherit",
 
     header_libs: [
         "libbase_headers",
@@ -124,7 +126,10 @@
 
 cc_defaults {
     name: "libutils_impl_defaults",
-    defaults: ["libutils_defaults"],
+    defaults: [
+        "libutils_defaults",
+        "apex-lowest-min-sdk-version",
+    ],
     native_bridge_supported: true,
 
     srcs: [
@@ -167,7 +172,6 @@
         "//apex_available:anyapex",
         "//apex_available:platform",
     ],
-    min_sdk_version: "apex_inherit",
 
     afdo: true,
 }
diff --git a/mkbootfs/mkbootfs.c b/mkbootfs/mkbootfs.c
index 05d1940..64e5a8c 100644
--- a/mkbootfs/mkbootfs.c
+++ b/mkbootfs/mkbootfs.c
@@ -1,17 +1,23 @@
 
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <unistd.h>
 #include <string.h>
-#include <ctype.h>
+#include <unistd.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/sysmacros.h>
 #include <dirent.h>
 
 #include <stdarg.h>
 #include <fcntl.h>
 
+#include <linux/kdev_t.h>
+
 #include <private/android_filesystem_config.h>
 #include <private/fs_config.h>
 
@@ -21,7 +27,6 @@
 **   an explanation of this file format
 ** - dotfiles are ignored
 ** - directories named 'root' are ignored
-** - device notes, pipes, etc are not supported (error)
 */
 
 static void die(const char* why, ...) {
@@ -86,6 +91,10 @@
         fs_config(path, is_dir, target_out_path, &s->st_uid, &s->st_gid, &st_mode, &capabilities);
         s->st_mode = (typeof(s->st_mode)) st_mode;
     }
+
+    if (S_ISREG(s->st_mode) || S_ISDIR(s->st_mode) || S_ISLNK(s->st_mode)) {
+        s->st_rdev = 0;
+    }
 }
 
 static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize)
@@ -115,8 +124,8 @@
            datasize,
            0, // volmajor
            0, // volminor
-           0, // devmajor
-           0, // devminor,
+           major(s->st_rdev),
+           minor(s->st_rdev),
            olen + 1,
            0,
            out,
@@ -267,6 +276,9 @@
         size = readlink(in, buf, 1024);
         if(size < 0) die("cannot read symlink '%s'", in);
         _eject(&s, out, olen, buf, size);
+    } else if(S_ISBLK(s.st_mode) || S_ISCHR(s.st_mode) ||
+              S_ISFIFO(s.st_mode) || S_ISSOCK(s.st_mode)) {
+        _eject(&s, out, olen, NULL, 0);
     } else {
         die("Unknown '%s' (mode %d)?\n", in, s.st_mode);
     }
@@ -327,34 +339,157 @@
     fclose(f);
 }
 
+static void devnodes_desc_error(const char* filename, unsigned long line_num,
+                              const char* msg)
+{
+    errx(EXIT_FAILURE, "failed to read nodes desc file '%s' line %lu: %s", filename, line_num, msg);
+}
+
+static int append_devnodes_desc_dir(char* path, char* args)
+{
+    struct stat s;
+
+    if (sscanf(args, "%o %d %d", &s.st_mode, &s.st_uid, &s.st_gid) != 3) return -1;
+
+    s.st_mode |= S_IFDIR;
+
+    _eject(&s, path, strlen(path), NULL, 0);
+
+    return 0;
+}
+
+static int append_devnodes_desc_nod(char* path, char* args)
+{
+    int minor, major;
+    struct stat s;
+    char dev;
+
+    if (sscanf(args, "%o %d %d %c %d %d", &s.st_mode, &s.st_uid, &s.st_gid,
+               &dev, &major, &minor) != 6) return -1;
+
+    s.st_rdev = MKDEV(major, minor);
+    switch (dev) {
+    case 'b':
+        s.st_mode |= S_IFBLK;
+        break;
+    case 'c':
+        s.st_mode |= S_IFCHR;
+        break;
+    default:
+        return -1;
+    }
+
+    _eject(&s, path, strlen(path), NULL, 0);
+
+    return 0;
+}
+
+static void append_devnodes_desc(const char* filename)
+{
+    FILE* f = fopen(filename, "re");
+    if (!f) err(EXIT_FAILURE, "failed to open nodes description file '%s'", filename);
+
+    char *line, *args, *type, *path;
+    unsigned long line_num = 0;
+    size_t allocated_len;
+
+    while (getline(&line, &allocated_len, f) != -1) {
+        char* type;
+
+        line_num++;
+
+        if (*line == '#') continue;
+
+        if (!(type = strtok(line, " \t"))) {
+            devnodes_desc_error(filename, line_num, "a type is missing");
+        }
+
+        if (*type == '\n') continue;
+
+        if (!(path = strtok(NULL, " \t"))) {
+            devnodes_desc_error(filename, line_num, "a path is missing");
+        }
+
+        if (!(args = strtok(NULL, "\n"))) {
+            devnodes_desc_error(filename, line_num, "args are missing");
+        }
+
+        if (!strcmp(type, "dir")) {
+            if (append_devnodes_desc_dir(path, args)) {
+                devnodes_desc_error(filename, line_num, "bad arguments for dir");
+            }
+        } else if (!strcmp(type, "nod")) {
+            if (append_devnodes_desc_nod(path, args)) {
+                devnodes_desc_error(filename, line_num, "bad arguments for nod");
+            }
+        } else {
+            devnodes_desc_error(filename, line_num, "type unknown");
+        }
+    }
+
+    free(line);
+    fclose(f);
+}
+
+static const struct option long_options[] = {
+    { "dirname",    required_argument,  NULL,   'd' },
+    { "file",       required_argument,  NULL,   'f' },
+    { "help",       no_argument,        NULL,   'h' },
+    { "nodes",      required_argument,  NULL,   'n' },
+    { NULL,         0,                  NULL,   0   },
+};
+
+static void usage(void)
+{
+    fprintf(stderr,
+            "Usage: mkbootfs [-n FILE] [-d DIR|-F FILE] DIR...\n"
+            "\n"
+            "\t-d, --dirname=DIR: fs-config directory\n"
+            "\t-f, --file=FILE: Canned configuration file\n"
+            "\t-h, --help: Print this help\n"
+            "\t-n, --nodes=FILE: Dev nodes description file\n"
+            "\nDev nodes description:\n"
+            "\t[dir|nod] [perms] [uid] [gid] [c|b] [minor] [major]\n"
+            "\tExample:\n"
+            "\t\t# My device nodes\n"
+            "\t\tdir dev 0755 0 0\n"
+            "\t\tnod dev/null 0600 0 0 c 1 5\n"
+    );
+}
 
 int main(int argc, char *argv[])
 {
-    if (argc == 1) {
-        fprintf(stderr,
-                "usage: %s [-d TARGET_OUTPUT_PATH] [-f CANNED_CONFIGURATION_PATH] DIRECTORIES...\n",
-                argv[0]);
-        exit(1);
+    int opt, unused;
+
+    while ((opt = getopt_long(argc, argv, "hd:f:n:", long_options, &unused)) != -1) {
+        switch (opt) {
+        case 'd':
+            target_out_path = argv[optind - 1];
+            break;
+        case 'f':
+            read_canned_config(argv[optind - 1]);
+            break;
+        case 'h':
+            usage();
+            return 0;
+        case 'n':
+            append_devnodes_desc(argv[optind - 1]);
+            break;
+        default:
+            usage();
+            die("Unknown option %s", argv[optind - 1]);
+        }
     }
 
-    argc--;
-    argv++;
+    int num_dirs = argc - optind;
+    argv += optind;
 
-    if (argc > 1 && strcmp(argv[0], "-d") == 0) {
-        target_out_path = argv[1];
-        argc -= 2;
-        argv += 2;
+    if (num_dirs <= 0) {
+        usage();
+        die("no directories to process?!");
     }
 
-    if (argc > 1 && strcmp(argv[0], "-f") == 0) {
-        read_canned_config(argv[1]);
-        argc -= 2;
-        argv += 2;
-    }
-
-    if(argc == 0) die("no directories to process?!");
-
-    while(argc-- > 0){
+    while(num_dirs-- > 0){
         char *x = strchr(*argv, '=');
         if(x != 0) {
             *x++ = 0;
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 55be31a..efad37c 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -47,6 +47,9 @@
     # Allow up to 32K FDs per process
     setrlimit nofile 32768 32768
 
+    # set RLIMIT_MEMLOCK to 64KB
+    setrlimit memlock 65536 65536
+
     # Set up linker config subdirectories based on mount namespaces
     mkdir /linkerconfig/bootstrap 0755
     mkdir /linkerconfig/default 0755
@@ -490,18 +493,26 @@
 service boringssl_self_test32 /system/bin/boringssl_self_test32
     reboot_on_failure reboot,boringssl-self-check-failed
     stdio_to_kmsg
+    # Explicitly specify that boringssl_self_test32 doesn't require any capabilities
+    capabilities
 
 service boringssl_self_test64 /system/bin/boringssl_self_test64
     reboot_on_failure reboot,boringssl-self-check-failed
     stdio_to_kmsg
+    # Explicitly specify that boringssl_self_test64 doesn't require any capabilities
+    capabilities
 
 service boringssl_self_test_apex32 /apex/com.android.conscrypt/bin/boringssl_self_test32
     reboot_on_failure reboot,boringssl-self-check-failed
     stdio_to_kmsg
+    # Explicitly specify that boringssl_self_test_apex32 doesn't require any capabilities
+    capabilities
 
 service boringssl_self_test_apex64 /apex/com.android.conscrypt/bin/boringssl_self_test64
     reboot_on_failure reboot,boringssl-self-check-failed
     stdio_to_kmsg
+    # Explicitly specify that boringssl_self_test_apex64 doesn't require any capabilities
+    capabilities
 
 
 # Healthd can trigger a full boot from charger mode by signaling this
@@ -839,7 +850,7 @@
     # Delete any stale files owned by the old virtualizationservice uid (b/230056726).
     chmod 0770 /data/misc/virtualizationservice
     exec - virtualizationservice system -- /bin/rm -rf /data/misc/virtualizationservice
-    mkdir /data/misc/virtualizationservice 0770 system system
+    mkdir /data/misc/virtualizationservice 0771 system system
 
     # /data/preloads uses encryption=None because it only contains preloaded
     # files that are public information, similar to the system image.
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index 63b09c0..2f0ec8a 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -7,6 +7,9 @@
     socket usap_pool_primary stream 660 root system
     onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
     onrestart write /sys/power/state on
+    # NOTE: If the wakelock name here is changed, then also
+    # update it in SystemSuspend.cpp
+    onrestart write /sys/power/wake_lock zygote_kwl
     onrestart restart audioserver
     onrestart restart cameraserver
     onrestart restart media
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index b6ca5c0..74a64c8 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -7,6 +7,9 @@
     socket usap_pool_primary stream 660 root system
     onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
     onrestart write /sys/power/state on
+    # NOTE: If the wakelock name here is changed, then also
+    # update it in SystemSuspend.cpp
+    onrestart write /sys/power/wake_lock zygote_kwl
     onrestart restart audioserver
     onrestart restart cameraserver
     onrestart restart media
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index 4ec59af..0b7ffb8 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -69,8 +69,8 @@
 # CDMA radio interface MUX
 /dev/ppp                  0660   radio      vpn
 
-/dev/kvm                  0600   system     system
-/dev/vhost-vsock          0600   system	    system
+/dev/kvm                  0666   root       root
+/dev/vhost-vsock          0666   root       root
 
 # sysfs properties
 /sys/devices/platform/trusty.*      trusty_version        0440  root   log
diff --git a/trusty/trusty-base.mk b/trusty/trusty-base.mk
index 0609709..7b4aa26 100644
--- a/trusty/trusty-base.mk
+++ b/trusty/trusty-base.mk
@@ -22,8 +22,21 @@
 # For gatekeeper, we include the generic -service and -impl to use legacy
 # HAL loading of gatekeeper.trusty.
 
+# Allow the KeyMint HAL service implementation to be selected at build time.  This needs to be
+# done in sync with the TA implementation included in Trusty.  Possible values are:
+#
+# - Rust implementation:   export TRUSTY_KEYMINT_IMPL=rust
+# - C++ implementation:    (any other value of TRUSTY_KEYMINT_IMPL)
+
+ifeq ($(TRUSTY_KEYMINT_IMPL),rust)
+    LOCAL_KEYMINT_PRODUCT_PACKAGE := android.hardware.security.keymint-service.rust.trusty
+else
+    # Default to the C++ implementation
+    LOCAL_KEYMINT_PRODUCT_PACKAGE := android.hardware.security.keymint-service.trusty
+endif
+
 PRODUCT_PACKAGES += \
-	android.hardware.security.keymint-service.trusty \
+	$(LOCAL_KEYMINT_PRODUCT_PACKAGE) \
 	android.hardware.gatekeeper@1.0-service.trusty \
 	trusty_apploader \
 	RemoteProvisioner