Merge "fastboot: Introduce ParseNetworkSerial unit tests"
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 076d8db..430ff14 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -128,25 +128,6 @@
     int64_t image_size;
 };
 
-enum class ImageType {
-    // Must be flashed for device to boot into the kernel.
-    BootCritical,
-    // Normal partition to be flashed during "flashall".
-    Normal,
-    // Partition that is never flashed during "flashall".
-    Extra
-};
-
-struct Image {
-    std::string nickname;
-    std::string img_name;
-    std::string sig_name;
-    std::string part_name;
-    bool optional_if_no_image;
-    ImageType type;
-    bool IsSecondary() const { return nickname.empty(); }
-};
-
 static std::vector<Image> images = {
         // clang-format off
     { "boot",     "boot.img",         "boot.sig",     "boot",     false, ImageType::BootCritical },
@@ -1583,8 +1564,7 @@
 
 class FlashAllTool {
   public:
-    FlashAllTool(const ImageSource& source, const std::string& slot_override, bool skip_secondary,
-                 bool wipe, bool force_flash);
+    FlashAllTool(FlashingPlan* fp);
 
     void Flash();
 
@@ -1604,25 +1584,12 @@
 
     std::string GetPartitionName(const ImageEntry& entry);
 
-    const ImageSource& source_;
-    std::string slot_override_;
-    bool skip_secondary_;
-    bool wipe_;
-    bool force_flash_;
-    std::string current_slot_;
-    std::string secondary_slot_;
-
     std::vector<ImageEntry> boot_images_;
     std::vector<ImageEntry> os_images_;
+    FlashingPlan* fp_;
 };
 
-FlashAllTool::FlashAllTool(const ImageSource& source, const std::string& slot_override,
-                           bool skip_secondary, bool wipe, bool force_flash)
-    : source_(source),
-      slot_override_(slot_override),
-      skip_secondary_(skip_secondary),
-      wipe_(wipe),
-      force_flash_(force_flash) {}
+FlashAllTool::FlashAllTool(FlashingPlan* fp) : fp_(fp) {}
 
 void FlashAllTool::Flash() {
     DumpInfo();
@@ -1630,10 +1597,10 @@
 
     // Change the slot first, so we boot into the correct recovery image when
     // using fastbootd.
-    if (slot_override_ == "all") {
+    if (fp_->slot == "all") {
         set_active("a");
     } else {
-        set_active(slot_override_);
+        set_active(fp_->slot);
     }
 
     DetermineSlot();
@@ -1670,13 +1637,13 @@
         LOG(VERBOSE) << "Cannot optimize flashing super on non-AB device";
         return false;
     }
-    if (slot_override_ == "all") {
+    if (fp_->slot == "all") {
         LOG(VERBOSE) << "Cannot optimize flashing super for all slots";
         return false;
     }
 
     // Does this device use dynamic partitions at all?
-    unique_fd fd = source_.OpenFile("super_empty.img");
+    unique_fd fd = fp_->source->OpenFile("super_empty.img");
     if (fd < 0) {
         LOG(VERBOSE) << "could not open super_empty.img";
         return false;
@@ -1693,7 +1660,7 @@
         return false;
     }
 
-    SuperFlashHelper helper(source_);
+    SuperFlashHelper helper(*fp_->source);
     if (!helper.Open(fd)) {
         return false;
     }
@@ -1733,43 +1700,43 @@
 
 void FlashAllTool::CheckRequirements() {
     std::vector<char> contents;
-    if (!source_.ReadFile("android-info.txt", &contents)) {
+    if (!fp_->source->ReadFile("android-info.txt", &contents)) {
         die("could not read android-info.txt");
     }
-    ::CheckRequirements({contents.data(), contents.size()}, force_flash_);
+    ::CheckRequirements({contents.data(), contents.size()}, fp_->force_flash);
 }
 
 void FlashAllTool::DetermineSlot() {
-    if (slot_override_.empty()) {
-        current_slot_ = get_current_slot();
+    if (fp_->slot.empty()) {
+        fp_->current_slot = get_current_slot();
     } else {
-        current_slot_ = slot_override_;
+        fp_->current_slot = fp_->slot;
     }
 
-    if (skip_secondary_) {
+    if (fp_->skip_secondary) {
         return;
     }
-    if (slot_override_ != "" && slot_override_ != "all") {
-        secondary_slot_ = get_other_slot(slot_override_);
+    if (fp_->slot != "" && fp_->slot != "all") {
+        fp_->secondary_slot = get_other_slot(fp_->slot);
     } else {
-        secondary_slot_ = get_other_slot();
+        fp_->secondary_slot = get_other_slot();
     }
-    if (secondary_slot_ == "") {
+    if (fp_->secondary_slot == "") {
         if (supports_AB()) {
             fprintf(stderr, "Warning: Could not determine slot for secondary images. Ignoring.\n");
         }
-        skip_secondary_ = true;
+        fp_->skip_secondary = true;
     }
 }
 
 void FlashAllTool::CollectImages() {
     for (size_t i = 0; i < images.size(); ++i) {
-        std::string slot = slot_override_;
+        std::string slot = fp_->slot;
         if (images[i].IsSecondary()) {
-            if (skip_secondary_) {
+            if (fp_->skip_secondary) {
                 continue;
             }
-            slot = secondary_slot_;
+            slot = fp_->secondary_slot;
         }
         if (images[i].type == ImageType::BootCritical) {
             boot_images_.emplace_back(&images[i], slot);
@@ -1782,7 +1749,7 @@
 void FlashAllTool::FlashImages(const std::vector<std::pair<const Image*, std::string>>& images) {
     for (const auto& [image, slot] : images) {
         fastboot_buffer buf;
-        unique_fd fd = source_.OpenFile(image->img_name);
+        unique_fd fd = fp_->source->OpenFile(image->img_name);
         if (fd < 0 || !load_buf_fd(std::move(fd), &buf)) {
             if (image->optional_if_no_image) {
                 continue;
@@ -1796,7 +1763,7 @@
 void FlashAllTool::FlashImage(const Image& image, const std::string& slot, fastboot_buffer* buf) {
     auto flash = [&, this](const std::string& partition_name) {
         std::vector<char> signature_data;
-        if (source_.ReadFile(image.sig_name, &signature_data)) {
+        if (fp_->source->ReadFile(image.sig_name, &signature_data)) {
             fb->Download("signature", signature_data);
             fb->RawCommand("signature", "installing signature");
         }
@@ -1810,7 +1777,7 @@
 }
 
 void FlashAllTool::UpdateSuperPartition() {
-    unique_fd fd = source_.OpenFile("super_empty.img");
+    unique_fd fd = fp_->source->OpenFile("super_empty.img");
     if (fd < 0) {
         return;
     }
@@ -1825,7 +1792,7 @@
     fb->Download(super_name, fd, get_file_size(fd));
 
     std::string command = "update-super:" + super_name;
-    if (wipe_) {
+    if (fp_->wants_wipe) {
         command += ":wipe";
     }
     fb->RawCommand(command, "Updating super partition");
@@ -1847,7 +1814,7 @@
 std::string FlashAllTool::GetPartitionName(const ImageEntry& entry) {
     auto slot = entry.second;
     if (slot.empty()) {
-        slot = current_slot_;
+        slot = fp_->current_slot;
     }
     if (slot.empty()) {
         return entry.first->part_name;
@@ -1876,15 +1843,16 @@
     return unzip_to_file(zip_, name.c_str());
 }
 
-static void do_update(const char* filename, const std::string& slot_override, bool skip_secondary,
-                      bool force_flash) {
+static void do_update(const char* filename, FlashingPlan* fp) {
     ZipArchiveHandle zip;
     int error = OpenArchive(filename, &zip);
     if (error != 0) {
         die("failed to open zip file '%s': %s", filename, ErrorCodeString(error));
     }
-
-    FlashAllTool tool(ZipImageSource(zip), slot_override, skip_secondary, false, force_flash);
+    ZipImageSource zp = ZipImageSource(zip);
+    fp->source = &zp;
+    fp->wants_wipe = false;
+    FlashAllTool tool(fp);
     tool.Flash();
 
     CloseArchive(zip);
@@ -1909,9 +1877,10 @@
     return unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_BINARY)));
 }
 
-static void do_flashall(const std::string& slot_override, bool skip_secondary, bool wipe,
-                        bool force_flash) {
-    FlashAllTool tool(LocalImageSource(), slot_override, skip_secondary, wipe, force_flash);
+static void do_flashall(FlashingPlan* fp) {
+    LocalImageSource s = LocalImageSource();
+    fp->source = &s;
+    FlashAllTool tool(fp);
     tool.Flash();
 }
 
@@ -2146,12 +2115,8 @@
 
 int FastBootTool::Main(int argc, char* argv[]) {
     android::base::InitLogging(argv, FastbootLogger, FastbootAborter);
+    std::unique_ptr<FlashingPlan> fp = std::make_unique<FlashingPlan>();
 
-    bool wants_wipe = false;
-    bool skip_reboot = false;
-    bool wants_set_active = false;
-    bool skip_secondary = false;
-    bool force_flash = false;
     unsigned fs_options = 0;
     int longindex;
     std::string slot_override;
@@ -2204,7 +2169,7 @@
             } else if (name == "disable-verity") {
                 g_disable_verity = true;
             } else if (name == "force") {
-                force_flash = true;
+                fp->force_flash = true;
             } else if (name == "fs-options") {
                 fs_options = ParseFsOption(optarg);
             } else if (name == "header-version") {
@@ -2223,9 +2188,9 @@
             } else if (name == "ramdisk-offset") {
                 g_boot_img_hdr.ramdisk_addr = strtoul(optarg, 0, 16);
             } else if (name == "skip-reboot") {
-                skip_reboot = true;
+                fp->skip_reboot = true;
             } else if (name == "skip-secondary") {
-                skip_secondary = true;
+                fp->skip_secondary = true;
             } else if (name == "slot") {
                 slot_override = optarg;
             } else if (name == "dtb-offset") {
@@ -2246,7 +2211,7 @@
         } else {
             switch (c) {
                 case 'a':
-                    wants_set_active = true;
+                    fp->wants_set_active = true;
                     if (optarg) next_active = optarg;
                     break;
                 case 'h':
@@ -2266,7 +2231,7 @@
                     set_verbose();
                     break;
                 case 'w':
-                    wants_wipe = true;
+                    fp->wants_wipe = true;
                     break;
                 case '?':
                     return 1;
@@ -2279,7 +2244,7 @@
     argc -= optind;
     argv += optind;
 
-    if (argc == 0 && !wants_wipe && !wants_set_active) syntax_error("no command");
+    if (argc == 0 && !fp->wants_wipe && !fp->wants_set_active) syntax_error("no command");
 
     if (argc > 0 && !strcmp(*argv, "devices")) {
         list_devices();
@@ -2315,13 +2280,14 @@
 
     fastboot::FastBootDriver fastboot_driver(transport, driver_callbacks, false);
     fb = &fastboot_driver;
+    fp->fb = &fastboot_driver;
 
     const double start = now();
 
     if (slot_override != "") slot_override = verify_slot(slot_override);
     if (next_active != "") next_active = verify_slot(next_active, false);
 
-    if (wants_set_active) {
+    if (fp->wants_set_active) {
         if (next_active == "") {
             if (slot_override == "") {
                 std::string current_slot;
@@ -2329,7 +2295,7 @@
                     if (current_slot[0] == '_') current_slot.erase(0, 1);
                     next_active = verify_slot(current_slot, false);
                 } else {
-                    wants_set_active = false;
+                    fp->wants_set_active = false;
                 }
             } else {
                 next_active = verify_slot(slot_override, false);
@@ -2390,17 +2356,17 @@
         } else if (command == FB_CMD_REBOOT) {
             if (args.size() == 1) {
                 std::string reboot_target = next_arg(&args);
-                reboot_task = std::make_unique<RebootTask>(fb, reboot_target);
+                reboot_task = std::make_unique<RebootTask>(fp.get(), reboot_target);
             } else {
-                reboot_task = std::make_unique<RebootTask>(fb);
+                reboot_task = std::make_unique<RebootTask>(fp.get());
             }
             if (!args.empty()) syntax_error("junk after reboot command");
         } else if (command == FB_CMD_REBOOT_BOOTLOADER) {
-            reboot_task = std::make_unique<RebootTask>(fb, "bootloader");
+            reboot_task = std::make_unique<RebootTask>(fp.get(), "bootloader");
         } else if (command == FB_CMD_REBOOT_RECOVERY) {
-            reboot_task = std::make_unique<RebootTask>(fb, "recovery");
+            reboot_task = std::make_unique<RebootTask>(fp.get(), "recovery");
         } else if (command == FB_CMD_REBOOT_FASTBOOT) {
-            reboot_task = std::make_unique<RebootTask>(fb, "fastboot");
+            reboot_task = std::make_unique<RebootTask>(fp.get(), "fastboot");
         } else if (command == FB_CMD_CONTINUE) {
             fb->Continue();
         } else if (command == FB_CMD_BOOT) {
@@ -2421,7 +2387,7 @@
                 fname = find_item(pname);
             }
             if (fname.empty()) die("cannot determine image filename for '%s'", pname.c_str());
-            FlashTask task(slot_override, force_flash, pname, fname);
+            FlashTask task(slot_override, pname, fname);
             task.Run();
         } else if (command == "flash:raw") {
             std::string partition = next_arg(&args);
@@ -2440,11 +2406,12 @@
             if (slot_override == "all") {
                 fprintf(stderr,
                         "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
-                do_flashall(slot_override, true, wants_wipe, force_flash);
+                fp->skip_secondary = true;
+                do_flashall(fp.get());
             } else {
-                do_flashall(slot_override, skip_secondary, wants_wipe, force_flash);
+                do_flashall(fp.get());
             }
-            reboot_task = std::make_unique<RebootTask>(fb);
+            reboot_task = std::make_unique<RebootTask>(fp.get());
         } else if (command == "update") {
             bool slot_all = (slot_override == "all");
             if (slot_all) {
@@ -2455,8 +2422,8 @@
             if (!args.empty()) {
                 filename = next_arg(&args);
             }
-            do_update(filename.c_str(), slot_override, skip_secondary || slot_all, force_flash);
-            reboot_task = std::make_unique<RebootTask>(fb);
+            do_update(filename.c_str(), fp.get());
+            reboot_task = std::make_unique<RebootTask>(fp.get());
         } else if (command == FB_CMD_SET_ACTIVE) {
             std::string slot = verify_slot(next_arg(&args), false);
             fb->SetActive(slot);
@@ -2528,8 +2495,8 @@
             syntax_error("unknown command %s", command.c_str());
         }
     }
-    if (wants_wipe) {
-        if (force_flash) {
+    if (fp->wants_wipe) {
+        if (fp->force_flash) {
             CancelSnapshotIfNeeded();
         }
         std::vector<std::string> partitions = {"userdata", "cache", "metadata"};
@@ -2543,10 +2510,10 @@
             fb_perform_format(partition, 1, partition_type, "", fs_options);
         }
     }
-    if (wants_set_active) {
+    if (fp->wants_set_active) {
         fb->SetActive(next_active);
     }
-    if (reboot_task && !skip_reboot) {
+    if (reboot_task && !fp->skip_reboot) {
         reboot_task->Run();
     }
     fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start));
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index c1ae6e4..09666aa 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -28,6 +28,8 @@
 #pragma once
 
 #include <string>
+#include "fastboot_driver.h"
+#include "util.h"
 
 #include <bootimg.h>
 
@@ -44,6 +46,45 @@
     unsigned ParseFsOption(const char*);
 };
 
+enum class ImageType {
+    // Must be flashed for device to boot into the kernel.
+    BootCritical,
+    // Normal partition to be flashed during "flashall".
+    Normal,
+    // Partition that is never flashed during "flashall".
+    Extra
+};
+
+struct Image {
+    std::string nickname;
+    std::string img_name;
+    std::string sig_name;
+    std::string part_name;
+    bool optional_if_no_image;
+    ImageType type;
+    bool IsSecondary() const { return nickname.empty(); }
+};
+
+using ImageEntry = std::pair<const Image*, std::string>;
+
+struct FlashingPlan {
+    // If the image uses the default slot, or the user specified "all", then
+    // the paired string will be empty. If the image requests a specific slot
+    // (for example, system_other) it is specified instead.
+    ImageSource* source;
+    bool wants_wipe = false;
+    bool skip_reboot = false;
+    bool wants_set_active = false;
+    bool skip_secondary = false;
+    bool force_flash = false;
+
+    std::string slot;
+    std::string current_slot;
+    std::string secondary_slot;
+    fastboot::FastBootDriver* fb;
+
+};
+
 bool should_flash_in_userspace(const std::string& partition_name);
 bool is_userspace_fastboot();
 void do_flash(const char* pname, const char* fname);
diff --git a/fastboot/task.cpp b/fastboot/task.cpp
index 94dd5c3..a4aa637 100644
--- a/fastboot/task.cpp
+++ b/fastboot/task.cpp
@@ -20,20 +20,16 @@
 #include "fastboot.h"
 #include "util.h"
 
-FlashTask::FlashTask(const std::string& _slot) : slot_(_slot){};
-FlashTask::FlashTask(const std::string& _slot, bool _force_flash)
-    : slot_(_slot), force_flash_(_force_flash) {}
-FlashTask::FlashTask(const std::string& _slot, bool _force_flash, const std::string& _pname)
-    : pname_(_pname), fname_(find_item(_pname)), slot_(_slot), force_flash_(_force_flash) {
+FlashTask::FlashTask(const std::string& _slot, const std::string& _pname)
+    : pname_(_pname), fname_(find_item(_pname)), slot_(_slot) {
     if (fname_.empty()) die("cannot determine image filename for '%s'", pname_.c_str());
 }
-FlashTask::FlashTask(const std::string& _slot, bool _force_flash, const std::string& _pname,
-                     const std::string& _fname)
-    : pname_(_pname), fname_(_fname), slot_(_slot), force_flash_(_force_flash) {}
+FlashTask::FlashTask(const std::string& _slot, const std::string& _pname, const std::string& _fname)
+    : pname_(_pname), fname_(_fname), slot_(_slot) {}
 
 void FlashTask::Run() {
     auto flash = [&](const std::string& partition) {
-        if (should_flash_in_userspace(partition) && !is_userspace_fastboot() && !force_flash_) {
+        if (should_flash_in_userspace(partition) && !is_userspace_fastboot()) {
             die("The partition you are trying to flash is dynamic, and "
                 "should be flashed via fastbootd. Please run:\n"
                 "\n"
@@ -47,25 +43,25 @@
     do_for_partitions(pname_, slot_, flash, true);
 }
 
-RebootTask::RebootTask(fastboot::FastBootDriver* _fb) : fb_(_fb){};
-RebootTask::RebootTask(fastboot::FastBootDriver* _fb, std::string _reboot_target)
-    : reboot_target_(std::move(_reboot_target)), fb_(_fb){};
+RebootTask::RebootTask(FlashingPlan* _fp) : fp_(_fp){};
+RebootTask::RebootTask(FlashingPlan* _fp, const std::string& _reboot_target)
+    : reboot_target_(_reboot_target), fp_(_fp){};
 
 void RebootTask::Run() {
     if ((reboot_target_ == "userspace" || reboot_target_ == "fastboot")) {
         if (!is_userspace_fastboot()) {
             reboot_to_userspace_fastboot();
-            fb_->WaitForDisconnect();
+            fp_->fb->WaitForDisconnect();
         }
     } else if (reboot_target_ == "recovery") {
-        fb_->RebootTo("recovery");
-        fb_->WaitForDisconnect();
+        fp_->fb->RebootTo("recovery");
+        fp_->fb->WaitForDisconnect();
     } else if (reboot_target_ == "bootloader") {
-        fb_->RebootTo("bootloader");
-        fb_->WaitForDisconnect();
+        fp_->fb->RebootTo("bootloader");
+        fp_->fb->WaitForDisconnect();
     } else if (reboot_target_ == "") {
-        fb_->Reboot();
-        fb_->WaitForDisconnect();
+        fp_->fb->Reboot();
+        fp_->fb->WaitForDisconnect();
     } else {
         syntax_error("unknown reboot target %s", reboot_target_.c_str());
     }
diff --git a/fastboot/task.h b/fastboot/task.h
index 582fa2f..d8b9e21 100644
--- a/fastboot/task.h
+++ b/fastboot/task.h
@@ -18,6 +18,7 @@
 #include <sstream>
 #include <string>
 
+#include "fastboot.h"
 #include "fastboot_driver.h"
 
 class Task {
@@ -29,11 +30,8 @@
 
 class FlashTask : public Task {
   public:
-    FlashTask(const std::string& _slot);
-    FlashTask(const std::string& _slot, bool _force_flash);
-    FlashTask(const std::string& _slot, bool _force_flash, const std::string& _pname);
-    FlashTask(const std::string& _slot, bool _force_flash, const std::string& _pname,
-              const std::string& _fname);
+    FlashTask(const std::string& _slot, const std::string& _pname);
+    FlashTask(const std::string& _slot, const std::string& _pname, const std::string& _fname);
 
     void Run() override;
     ~FlashTask() {}
@@ -42,17 +40,16 @@
     const std::string pname_;
     const std::string fname_;
     const std::string slot_;
-    bool force_flash_ = false;
 };
 
 class RebootTask : public Task {
   public:
-    RebootTask(fastboot::FastBootDriver* _fb);
-    RebootTask(fastboot::FastBootDriver* _fb, const std::string _reboot_target);
+    RebootTask(FlashingPlan* _fp);
+    RebootTask(FlashingPlan* _fp, const std::string& _reboot_target);
     void Run() override;
     ~RebootTask() {}
 
   private:
     const std::string reboot_target_ = "";
-    fastboot::FastBootDriver* fb_;
+    FlashingPlan* fp_;
 };
\ No newline at end of file
diff --git a/init/service.cpp b/init/service.cpp
index cce24c3..8456d1e 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -447,6 +447,15 @@
         return {};
     }
 
+    // On newer kernels, /dev/console will always exist because
+    // "console=ttynull" is hard-coded in CONFIG_CMDLINE. This new boot
+    // property should be set via "androidboot.serialconsole=0" to explicitly
+    // disable services requiring the console. For older kernels and boot
+    // images, not setting this at all will fall back to the old behavior
+    if (GetProperty("ro.boot.serialconsole", "") == "0") {
+        return {};
+    }
+
     if (proc_attr_.console.empty()) {
         proc_attr_.console = "/dev/" + GetProperty("ro.boot.console", "console");
     }
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 384a8f0..38f19ff 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -372,6 +372,7 @@
     std::set<pid_t> pgids;
     pgids.emplace(initialPid);
     std::set<pid_t> pids;
+    int processes = 0;
 
     std::unique_ptr<FILE, decltype(&fclose)> fd(nullptr, fclose);
 
@@ -390,6 +391,7 @@
         pid_t pid;
         bool file_is_empty = true;
         while (fscanf(fd.get(), "%d\n", &pid) == 1 && pid >= 0) {
+            processes++;
             file_is_empty = false;
             if (pid == 0) {
                 // Should never happen...  but if it does, trying to kill this
@@ -419,15 +421,12 @@
         }
     }
 
-    int processes = 0;
     // Kill all process groups.
     for (const auto pgid : pgids) {
         LOG(VERBOSE) << "Killing process group " << -pgid << " in uid " << uid
                      << " as part of process cgroup " << initialPid;
 
-        if (kill(-pgid, signal) == 0) {
-            processes++;
-        } else if (errno != ESRCH) {
+        if (kill(-pgid, signal) == -1 && errno != ESRCH) {
             PLOG(WARNING) << "kill(" << -pgid << ", " << signal << ") failed";
         }
     }
@@ -437,9 +436,7 @@
         LOG(VERBOSE) << "Killing pid " << pid << " in uid " << uid << " as part of process cgroup "
                      << initialPid;
 
-        if (kill(pid, signal) == 0) {
-            processes++;
-        } else if (errno != ESRCH) {
+        if (kill(pid, signal) == -1 && errno != ESRCH) {
             PLOG(WARNING) << "kill(" << pid << ", " << signal << ") failed";
         }
     }
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index 35adf36..4db7372 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -815,11 +815,11 @@
                 profile->EnableResourceCaching(ProfileAction::RCT_PROCESS);
             }
             if (!profile->ExecuteForProcess(uid, pid)) {
-                PLOG(WARNING) << "Failed to apply " << name << " process profile";
+                LOG(WARNING) << "Failed to apply " << name << " process profile";
                 success = false;
             }
         } else {
-            PLOG(WARNING) << "Failed to find " << name << " process profile";
+            LOG(WARNING) << "Failed to find " << name << " process profile";
             success = false;
         }
     }
@@ -836,11 +836,11 @@
                 profile->EnableResourceCaching(ProfileAction::RCT_TASK);
             }
             if (!profile->ExecuteForTask(tid)) {
-                PLOG(WARNING) << "Failed to apply " << name << " task profile";
+                LOG(WARNING) << "Failed to apply " << name << " task profile";
                 success = false;
             }
         } else {
-            PLOG(WARNING) << "Failed to find " << name << " task profile";
+            LOG(WARNING) << "Failed to find " << name << " task profile";
             success = false;
         }
     }
diff --git a/libutils/ProcessCallStack_fuzz.cpp b/libutils/ProcessCallStack_fuzz.cpp
index 30136cd..552a11e 100644
--- a/libutils/ProcessCallStack_fuzz.cpp
+++ b/libutils/ProcessCallStack_fuzz.cpp
@@ -44,7 +44,7 @@
                 dataProvider->ConsumeRandomLengthString(MAX_NAME_SIZE).append(std::to_string(i));
         std::thread th = std::thread(loop);
         pthread_setname_np(th.native_handle(), threadName.c_str());
-        threads.push_back(move(th));
+        threads.push_back(std::move(th));
     }
 
     // Collect thread information
diff --git a/libutils/RefBase_fuzz.cpp b/libutils/RefBase_fuzz.cpp
index 69288b3..8291be9 100644
--- a/libutils/RefBase_fuzz.cpp
+++ b/libutils/RefBase_fuzz.cpp
@@ -177,7 +177,7 @@
         uint8_t opCount = dataProvider->ConsumeIntegralInRange<uint8_t>(1, kMaxOperations);
         std::vector<uint8_t> threadOperations = dataProvider->ConsumeBytes<uint8_t>(opCount);
         std::thread tmpThread = std::thread(loop, threadOperations);
-        threads.push_back(move(tmpThread));
+        threads.push_back(std::move(tmpThread));
     }
 
     for (auto& th : threads) {
diff --git a/shell_and_utilities/README.md b/shell_and_utilities/README.md
index ca522b7..9a733bb 100644
--- a/shell_and_utilities/README.md
+++ b/shell_and_utilities/README.md
@@ -18,8 +18,11 @@
 in Marshmallow we changed direction and started the move to toybox.
 
 Not everything is provided by toybox, though. For the bzip2 command-line tools
-we use the ones that are part of the bzip2 distribution. The awk added in
-Android P is Brian Kernighan's "one true" awk.
+we use the ones that are part of the bzip2 distribution.
+The awk added in Android P is the
+["one true" awk](https://github.com/onetrueawk/awk).
+The bc added in Android Q is
+[Gavin Howard's bc](https://github.com/gavinhoward/bc).
 
 The lists below show what tools were provided and where they came from in
 each release starting with Gingerbread. This doesn't tell the full story,
@@ -34,6 +37,40 @@
 full list for a release by running `toybox` directly.
 
 
+## Android 14 ("U")
+
+BSD: fsck\_msdos newfs\_msdos
+
+bzip2: bzcat bzip2 bunzip2
+
+gavinhoward/bc: bc
+
+one-true-awk: awk
+
+toolbox: getevent getprop setprop start stop
+
+toybox ([0.8.9](http://landley.net/toybox/#10-01-2023)-ish):
+[ acpi base64 basename blkdiscard blkid blockdev **brctl** cal cat chattr
+chcon chgrp chmod chown chroot chrt cksum clear cmp comm cp cpio cut
+date dd devmem df diff dirname dmesg dos2unix du echo egrep env expand
+expr fallocate false fgrep file find flock fmt free freeramdisk fsfreeze
+fsync getconf getenforce getfattr getopt grep groups gunzip gzip head
+help hostname hwclock i2cdetect i2cdump i2cget i2cset iconv id ifconfig
+inotifyd insmod install ionice iorenice iotop kill killall ln load\_policy
+log **logger** logname losetup ls lsattr lsmod lsof lspci lsusb makedevs
+md5sum microcom mkdir mkfifo mknod mkswap mktemp modinfo modprobe
+more mount mountpoint mv nbd-client nc netcat netstat nice nl nohup
+nproc nsenter od partprobe paste patch pgrep pidof ping ping6 pivot\_root
+pkill pmap printenv printf prlimit ps pwd pwdx readelf readlink realpath
+renice restorecon rev rfkill rm rmdir rmmod rtcwake runcon sed sendevent
+seq setenforce setfattr setsid sha1sum sha224sum sha256sum sha384sum
+sha512sum sleep sort split stat strings stty swapoff swapon sync sysctl
+tac tail tar taskset tee test time timeout top touch tr traceroute
+traceroute6 true truncate tty tunctl uclampset ulimit umount uname
+uniq unix2dos unlink unshare uptime usleep uudecode uuencode uuidgen
+vconfig vi vmstat watch wc which whoami xargs xxd yes zcat
+
+
 ## Android 13 ("T")
 
 BSD: fsck\_msdos newfs\_msdos
@@ -46,7 +83,8 @@
 
 toolbox: getevent getprop setprop start stop
 
-toybox (0.8.6-ish): [ acpi base64 basename blkdiscard blkid blockdev cal cat chattr chcon
+toybox ([0.8.6](http://landley.net/toybox/#30-11-2021)-ish):
+[ acpi base64 basename blkdiscard blkid blockdev cal cat chattr chcon
 chgrp chmod chown chroot chrt cksum clear cmp comm cp cpio cut date
 dd devmem df diff dirname dmesg dos2unix du echo egrep env expand
 expr fallocate false fgrep file find flock fmt free freeramdisk fsfreeze
@@ -79,7 +117,8 @@
 
 toolbox: getevent getprop setprop start stop
 
-toybox (0.8.4-ish): **[** acpi base64 basename **blkdiscard** blkid blockdev cal cat chattr chcon
+toybox ([0.8.4](http://landley.net/toybox/#24-10-2020)-ish):
+**[** acpi base64 basename **blkdiscard** blkid blockdev cal cat chattr chcon
 chgrp chmod chown chroot chrt cksum clear cmp comm cp cpio cut date
 dd devmem df diff dirname dmesg dos2unix du echo egrep env expand
 expr fallocate false fgrep file find flock fmt free freeramdisk fsfreeze
@@ -112,7 +151,8 @@
 
 toolbox: getevent getprop setprop start stop
 
-toybox (0.8.3-ish): acpi base64 basename blkid blockdev cal cat chattr chcon chgrp chmod
+toybox ([0.8.3](http://landley.net/toybox/#11-05-2020)-ish):
+acpi base64 basename blkid blockdev cal cat chattr chcon chgrp chmod
 chown chroot chrt cksum clear cmp comm cp cpio cut date dd **devmem**
 df diff dirname dmesg dos2unix du echo egrep env expand expr fallocate
 false fgrep file find flock fmt free freeramdisk fsfreeze **fsync** getconf
@@ -143,7 +183,8 @@
 
 toolbox: getevent getprop
 
-toybox (0.8.0-ish): acpi base64 basename **bc** **blkid** blockdev cal cat **chattr** chcon chgrp
+toybox ([0.8.0](http://landley.net/toybox/#08-02-2019)-ish):
+acpi base64 basename **bc** **blkid** blockdev cal cat **chattr** chcon chgrp
 chmod chown chroot chrt cksum clear cmp comm cp cpio cut date dd df
 diff dirname dmesg dos2unix du echo **egrep** env expand expr fallocate
 false **fgrep** file find flock fmt free **freeramdisk** **fsfreeze** **getconf**
@@ -174,7 +215,8 @@
 
 toolbox: getevent getprop newfs\_msdos
 
-toybox (0.7.6-ish): acpi base64 basename blockdev cal cat chcon chgrp chmod chown
+toybox ([0.7.6](http://landley.net/toybox/#24-02-2018)-ish):
+acpi base64 basename blockdev cal cat chcon chgrp chmod chown
 chroot chrt cksum clear cmp comm cp cpio cut date df diff dirname dmesg
 dos2unix du echo env expand expr fallocate false file find flock **fmt** free
 getenforce groups gunzip gzip head hostname hwclock id ifconfig inotifyd
@@ -198,7 +240,8 @@
 
 toolbox: getevent newfs\_msdos
 
-toybox (0.7.3-ish): acpi base64 basename blockdev cal cat chcon chgrp chmod chown
+toybox ([0.7.3](http://landley.net/toybox/#21-02-2017)-ish):
+acpi base64 basename blockdev cal cat chcon chgrp chmod chown
 chroot chrt cksum clear cmp comm cp cpio cut date df **diff** dirname dmesg
 dos2unix du echo env expand expr fallocate false **file** find flock free
 getenforce getprop groups **gunzip** **gzip** head hostname hwclock id ifconfig
@@ -221,7 +264,8 @@
 toolbox: getevent iftop ioctl log nandread newfs\_msdos ps prlimit
 sendevent start stop top
 
-toybox (0.7.0-ish): acpi **base64** basename blockdev bzcat cal cat chcon chgrp chmod
+toybox ([0.7.0](http://landley.net/toybox/#02-02-2016)-ish):
+acpi **base64** basename blockdev bzcat cal cat chcon chgrp chmod
 chown chroot cksum clear comm cmp cp cpio cut date **df** dirname dmesg
 dos2unix **du** echo env expand expr fallocate false find **flock** free
 getenforce getprop groups head hostname hwclock id ifconfig inotifyd
@@ -242,7 +286,8 @@
 toolbox: df getevent iftop ioctl ionice log ls lsof mount nandread
 newfs\_msdos ps prlimit renice sendevent start stop top uptime watchprops
 
-toybox (0.5.2-ish): acpi basename blockdev bzcat cal cat chcon chgrp chmod chown
+toybox ([0.5.2](http://landley.net/toybox/#25-02-2015)-ish):
+acpi basename blockdev bzcat cal cat chcon chgrp chmod chown
 chroot cksum clear comm cmp cp cpio cut date dirname dmesg dos2unix echo
 env expand expr fallocate false find free getenforce getprop groups
 head hostname hwclock id ifconfig inotifyd insmod kill load\_policy ln