Merge "Correcting Reboot Task Functionality"
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index b302918..c9e097e 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -216,7 +216,7 @@
       log_error(output_fd, 0,
                 "received packet of unexpected length from tombstoned while reading %s response: "
                 "expected %zd, received %zd",
-                kind, sizeof(response), rc);
+                kind, sizeof(*response), rc);
       return false;
     }
     return true;
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index cf4c5d5..3563436 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -142,7 +142,8 @@
   return false;
 }
 
-static bool activity_manager_notify(pid_t pid, int signal, const std::string& amfd_data) {
+static bool activity_manager_notify(pid_t pid, int signal, const std::string& amfd_data,
+                                    bool recoverable_gwp_asan_crash) {
   ATRACE_CALL();
   android::base::unique_fd amfd(socket_local_client(
       "/data/system/ndebugsocket", ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM));
@@ -165,19 +166,32 @@
     return false;
   }
 
-  // Activity Manager protocol: binary 32-bit network-byte-order ints for the
-  // pid and signal number, followed by the raw text of the dump, culminating
-  // in a zero byte that marks end-of-data.
+  // Activity Manager protocol:
+  //  - 32-bit network-byte-order: pid
+  //  - 32-bit network-byte-order: signal number
+  //  - byte: recoverable_gwp_asan_crash
+  //  - bytes: raw text of the dump
+  //  - null terminator
+
   uint32_t datum = htonl(pid);
-  if (!android::base::WriteFully(amfd, &datum, 4)) {
+  if (!android::base::WriteFully(amfd, &datum, sizeof(datum))) {
     PLOG(ERROR) << "AM pid write failed";
     return false;
   }
+
   datum = htonl(signal);
-  if (!android::base::WriteFully(amfd, &datum, 4)) {
-    PLOG(ERROR) << "AM signal write failed";
+  if (!android::base::WriteFully(amfd, &datum, sizeof(datum))) {
+    PLOG(ERROR) << "AM signo write failed";
     return false;
   }
+
+  uint8_t recoverable_gwp_asan_crash_byte = recoverable_gwp_asan_crash ? 1 : 0;
+  if (!android::base::WriteFully(amfd, &recoverable_gwp_asan_crash_byte,
+                                 sizeof(recoverable_gwp_asan_crash_byte))) {
+    PLOG(ERROR) << "AM recoverable_gwp_asan_crash_byte write failed";
+    return false;
+  }
+
   if (!android::base::WriteFully(amfd, amfd_data.c_str(), amfd_data.size() + 1)) {
     PLOG(ERROR) << "AM data write failed";
     return false;
@@ -651,10 +665,10 @@
     }
   }
 
-  if (fatal_signal && !recoverable_gwp_asan_crash) {
+  if (fatal_signal) {
     // Don't try to notify ActivityManager if it just crashed, or we might hang until timeout.
     if (thread_info[target_process].thread_name != "system_server") {
-      activity_manager_notify(target_process, signo, amfd_data);
+      activity_manager_notify(target_process, signo, amfd_data, recoverable_gwp_asan_crash);
     }
   }
 
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp
index 4043a6e..6a19878 100644
--- a/debuggerd/crasher/crasher.cpp
+++ b/debuggerd/crasher/crasher.cpp
@@ -164,7 +164,8 @@
 }
 
 noinline void readdir_null() {
-    readdir(nullptr);
+    DIR* sneaky_null = nullptr;
+    readdir(sneaky_null);
 }
 
 noinline int strlen_null() {
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 4e4f431..01bafbd 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -1560,10 +1560,10 @@
     }
 }
 
-std::string GetPartitionName(const ImageEntry& entry) {
+std::string GetPartitionName(const ImageEntry& entry, std::string& current_slot) {
     auto slot = entry.second;
     if (slot.empty()) {
-        slot = get_current_slot();
+        slot = current_slot;
     }
     if (slot.empty()) {
         return entry.first->part_name;
@@ -1582,7 +1582,7 @@
 
   private:
     void CheckRequirements();
-    void DetermineSecondarySlot();
+    void DetermineSlot();
     void CollectImages();
     void FlashImages(const std::vector<std::pair<const Image*, std::string>>& images);
     void FlashImage(const Image& image, const std::string& slot, fastboot_buffer* buf);
@@ -1600,13 +1600,15 @@
 
     // Change the slot first, so we boot into the correct recovery image when
     // using fastbootd.
-    if (fp_->slot_override == "all") {
+    if (fp_->slot == "all") {
         set_active("a");
     } else {
-        set_active(fp_->slot_override);
+        set_active(fp_->slot);
     }
 
-    DetermineSecondarySlot();
+    DetermineSlot();
+    CollectImages();
+
     CancelSnapshotIfNeeded();
 
     // First flash boot partitions. We allow this to happen either in userspace
@@ -1651,12 +1653,18 @@
     ::CheckRequirements({contents.data(), contents.size()}, fp_->force_flash);
 }
 
-void FlashAllTool::DetermineSecondarySlot() {
+void FlashAllTool::DetermineSlot() {
+    if (fp_->slot.empty()) {
+        fp_->current_slot = get_current_slot();
+    } else {
+        fp_->current_slot = fp_->slot;
+    }
+
     if (fp_->skip_secondary) {
         return;
     }
-    if (fp_->slot_override != "" && fp_->slot_override != "all") {
-        fp_->secondary_slot = get_other_slot(fp_->slot_override);
+    if (fp_->slot != "" && fp_->slot != "all") {
+        fp_->secondary_slot = get_other_slot(fp_->slot);
     } else {
         fp_->secondary_slot = get_other_slot();
     }
@@ -1670,7 +1678,7 @@
 
 void FlashAllTool::CollectImages() {
     for (size_t i = 0; i < images.size(); ++i) {
-        std::string slot = fp_->slot_override;
+        std::string slot = fp_->slot;
         if (images[i].IsSecondary()) {
             if (fp_->skip_secondary) {
                 continue;
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index 029b583..c954487 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -80,7 +80,8 @@
     bool skip_secondary = false;
     bool force_flash = false;
 
-    std::string slot_override;
+    std::string slot;
+    std::string current_slot;
     std::string secondary_slot;
     fastboot::FastBootDriver* fb;
 };
@@ -102,7 +103,7 @@
 
 Result<NetworkSerial, FastbootError> ParseNetworkSerial(const std::string& serial);
 bool supports_AB();
-std::string GetPartitionName(const ImageEntry& entry);
+std::string GetPartitionName(const ImageEntry& entry, std::string& current_slot_);
 void flash_partition_files(const std::string& partition, const std::vector<SparsePtr>& files);
 int64_t get_sparse_limit(int64_t size);
 std::vector<SparsePtr> resparse_file(sparse_file* s, int64_t max_size);
diff --git a/fastboot/fuzzer/Android.bp b/fastboot/fuzzer/Android.bp
index 1b59e4a..a898070 100644
--- a/fastboot/fuzzer/Android.bp
+++ b/fastboot/fuzzer/Android.bp
@@ -58,5 +58,13 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 533764,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of libfastboot library",
+        vector: "local_no_privileges_required",
+        service_privilege: "host_only",
+        users: "single_user",
+        fuzzed_code_usage: "shipped",
     },
 }
diff --git a/fastboot/task.cpp b/fastboot/task.cpp
index 3d2c975..9d4cb75 100644
--- a/fastboot/task.cpp
+++ b/fastboot/task.cpp
@@ -95,7 +95,7 @@
         LOG(VERBOSE) << "Cannot optimize flashing super on non-AB device";
         return nullptr;
     }
-    if (fp->slot_override == "all") {
+    if (fp->slot == "all") {
         LOG(VERBOSE) << "Cannot optimize flashing super for all slots";
         return nullptr;
     }
@@ -132,7 +132,7 @@
     }
 
     for (const auto& entry : os_images) {
-        auto partition = GetPartitionName(entry);
+        auto partition = GetPartitionName(entry, fp->current_slot);
         auto image = entry.first;
 
         if (!helper->AddPartition(partition, image->img_name, image->optional_if_no_image)) {
@@ -145,7 +145,7 @@
 
     // Remove images that we already flashed, just in case we have non-dynamic OS images.
     auto remove_if_callback = [&](const ImageEntry& entry) -> bool {
-        return helper->WillFlash(GetPartitionName(entry));
+        return helper->WillFlash(GetPartitionName(entry, fp->current_slot));
     };
     os_images.erase(std::remove_if(os_images.begin(), os_images.end(), remove_if_callback),
                     os_images.end());
diff --git a/init/README.md b/init/README.md
index b006365..6bdff4a 100644
--- a/init/README.md
+++ b/init/README.md
@@ -642,17 +642,17 @@
   the current SELinux policy or its parent if not specified in the policy. If
   the directory exists, its security context will not be changed (even if
   different from the policy).
-
-  > _action_ can be one of:
-  * `None`: take no encryption action; directory will be encrypted if parent is.
-  * `Require`: encrypt directory, abort boot process if encryption fails
-  * `Attempt`: try to set an encryption policy, but continue if it fails
-  * `DeleteIfNecessary`: recursively delete directory if necessary to set
-  encryption policy.
-
-  > _key_ can be one of:
-  * `ref`: use the systemwide DE key
-  * `per_boot_ref`: use the key freshly generated on each boot.
+>
+> _action_ can be one of:
+>  * `None`: take no encryption action; directory will be encrypted if parent is.
+>  * `Require`: encrypt directory, abort boot process if encryption fails
+>  * `Attempt`: try to set an encryption policy, but continue if it fails
+>  * `DeleteIfNecessary`: recursively delete directory if necessary to set
+>  encryption policy.
+>
+> _key_ can be one of:
+>  * `ref`: use the systemwide DE key
+>  * `per_boot_ref`: use the key freshly generated on each boot.
 
 `mount_all [ <fstab> ] [--<option>]`
 > Calls fs\_mgr\_mount\_all on the given fs\_mgr-format fstab with optional
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 062ed39..907eb80 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -761,15 +761,7 @@
 
 constexpr size_t kKlogMessageSize = 1024;
 
-void SelinuxAvcLog(char* buf, size_t buf_len) {
-    CHECK_GT(buf_len, 0u);
-
-    size_t str_len = strnlen(buf, buf_len);
-    // trim newline at end of string
-    if (buf[str_len - 1] == '\n') {
-        buf[str_len - 1] = '\0';
-    }
-
+void SelinuxAvcLog(char* buf) {
     struct NetlinkMessage {
         nlmsghdr hdr;
         char buf[kKlogMessageSize];
@@ -835,8 +827,17 @@
     if (length_written <= 0) {
         return 0;
     }
+
+    // libselinux log messages usually contain a new line character, while
+    // Android LOG() does not expect it. Remove it to avoid empty lines in
+    // the log buffers.
+    size_t str_len = strlen(buf);
+    if (buf[str_len - 1] == '\n') {
+        buf[str_len - 1] = '\0';
+    }
+
     if (type == SELINUX_AVC) {
-        SelinuxAvcLog(buf, sizeof(buf));
+        SelinuxAvcLog(buf);
     } else {
         android::base::KernelLogger(android::base::MAIN, severity, "selinux", nullptr, 0, buf);
     }
diff --git a/libmodprobe/Android.bp b/libmodprobe/Android.bp
index 525a880..1d94a96 100644
--- a/libmodprobe/Android.bp
+++ b/libmodprobe/Android.bp
@@ -10,6 +10,7 @@
     vendor_available: true,
     ramdisk_available: true,
     recovery_available: true,
+    host_supported: true,
     srcs: [
         "libmodprobe.cpp",
         "libmodprobe_ext.cpp",
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index f7af08b..38eb92f 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -446,14 +446,9 @@
 
 static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries,
                             int* max_processes) {
-    if (uid < 0) {
-        LOG(ERROR) << __func__ << ": invalid UID " << uid;
-        return -1;
-    }
-    if (initialPid <= 0) {
-        LOG(ERROR) << __func__ << ": invalid PID " << initialPid;
-        return -1;
-    }
+    CHECK_GE(uid, 0);
+    CHECK_GT(initialPid, 0);
+
     std::string hierarchy_root_path;
     if (CgroupsAvailable()) {
         CgroupGetControllerPath(CGROUPV2_CONTROLLER_NAME, &hierarchy_root_path);
@@ -590,7 +585,8 @@
 }
 
 int createProcessGroup(uid_t uid, int initialPid, bool memControl) {
-    std::string cgroup;
+    CHECK_GE(uid, 0);
+    CHECK_GT(initialPid, 0);
 
     if (memControl && !UsePerAppMemcg()) {
         PLOG(ERROR) << "service memory controls are used without per-process memory cgroup support";
@@ -608,6 +604,7 @@
         }
     }
 
+    std::string cgroup;
     CgroupGetControllerPath(CGROUPV2_CONTROLLER_NAME, &cgroup);
     return createProcessGroupInternal(uid, initialPid, cgroup, true);
 }
diff --git a/libstats/expresslog/Histogram.cpp b/libstats/expresslog/Histogram.cpp
index cb29a00..50bb343 100644
--- a/libstats/expresslog/Histogram.cpp
+++ b/libstats/expresslog/Histogram.cpp
@@ -71,5 +71,10 @@
     stats_write(EXPRESS_HISTOGRAM_SAMPLE_REPORTED, mMetricIdHash, /*count*/ 1, binIndex);
 }
 
+void Histogram::logSampleWithUid(int32_t uid, float sample) const {
+    const int binIndex = mBinOptions->getBinForSample(sample);
+    stats_write(EXPRESS_UID_HISTOGRAM_SAMPLE_REPORTED, mMetricIdHash, /*count*/ 1, binIndex, uid);
+}
+
 }  // namespace expresslog
 }  // namespace android
diff --git a/libstats/expresslog/include/Histogram.h b/libstats/expresslog/include/Histogram.h
index 8fdc1b6..49aee3d 100644
--- a/libstats/expresslog/include/Histogram.h
+++ b/libstats/expresslog/include/Histogram.h
@@ -72,6 +72,11 @@
      */
     void logSample(float sample) const;
 
+    /**
+     * Logs increment sample count for automatically calculated bin with uid
+     */
+    void logSampleWithUid(int32_t uid, float sample) const;
+
 private:
     const int64_t mMetricIdHash;
     const std::shared_ptr<BinOptions> mBinOptions;