Merge "Moved contents of clang_cflags into cflags"
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 5a9d4f2..f4ba347 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -113,8 +113,14 @@
 // Enable GWP-ASan at the start of this process. GWP-ASan is enabled using
 // process sampling, so we need to ensure we force GWP-ASan on.
 __attribute__((constructor)) static void enable_gwp_asan() {
-  bool force = true;
-  android_mallopt(M_INITIALIZE_GWP_ASAN, &force, sizeof(force));
+  android_mallopt_gwp_asan_options_t opts;
+  // No, we're not an app, but let's turn ourselves on without sampling.
+  // Technically, if someone's using the *.default_app sysprops, they'll adjust
+  // our settings, but I don't think this will be common on a device that's
+  // running debuggerd_tests.
+  opts.desire = android_mallopt_gwp_asan_options_t::Action::TURN_ON_FOR_APP;
+  opts.program_name = "";
+  android_mallopt(M_INITIALIZE_GWP_ASAN, &opts, sizeof(android_mallopt_gwp_asan_options_t));
 }
 
 static void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, unique_fd* output_fd,
diff --git a/debuggerd/libdebuggerd/gwp_asan.cpp b/debuggerd/libdebuggerd/gwp_asan.cpp
index b2077ba..3d96627 100644
--- a/debuggerd/libdebuggerd/gwp_asan.cpp
+++ b/debuggerd/libdebuggerd/gwp_asan.cpp
@@ -43,10 +43,13 @@
 static const gwp_asan::AllocationMetadata* retrieve_gwp_asan_metadata(
     unwindstack::Memory* process_memory, const gwp_asan::AllocatorState& state,
     uintptr_t metadata_addr) {
-  if (state.MaxSimultaneousAllocations > 1024) {
+  // 1 million GWP-ASan slots would take 4.1GiB of space. Thankfully, copying
+  // the metadata for that amount of slots is only 532MiB, and this really will
+  // only be used with some ridiculous torture-tests.
+  if (state.MaxSimultaneousAllocations > 1000000) {
     ALOGE(
         "Error when retrieving GWP-ASan metadata, MSA from state (%zu) "
-        "exceeds maximum allowed (1024).",
+        "exceeds maximum allowed (1,000,000).",
         state.MaxSimultaneousAllocations);
     return nullptr;
   }
diff --git a/fastboot/fastboot.bash b/fastboot/fastboot.bash
index e9bf9e9..911071a 100644
--- a/fastboot/fastboot.bash
+++ b/fastboot/fastboot.bash
@@ -109,7 +109,7 @@
 
     cur="${COMP_WORDS[COMP_CWORD]}"
     if [[ $i -eq $COMP_CWORD ]]; then
-        partitions="boot bootloader dtbo init_boot modem odm odm_dlkm oem product pvmfw radio recovery system system_dlkm vbmeta vendor vendor_dlkm"
+        partitions="boot bootloader dtbo init_boot modem odm odm_dlkm oem product pvmfw radio recovery system system_dlkm vbmeta vendor vendor_dlkm vendor_kernel_boot"
         COMPREPLY=( $(compgen -W "$partitions" -- $cur) )
     else
         _fastboot_util_complete_local_file "${cur}" '!*.img'
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 39d86f9..79c3ac7 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -186,6 +186,11 @@
                   "vendor_dlkm.img",  "vendor_dlkm.sig",
                                                       "vendor_dlkm",
                                                                   true,  ImageType::Normal },
+    { "vendor_kernel_boot",
+                  "vendor_kernel_boot.img",
+                                      "vendor_kernel_boot.sig",
+                                                      "vendor_kernel_boot",
+                                                                  true,  ImageType::BootCritical },
     { nullptr,    "vendor_other.img", "vendor.sig",   "vendor",   true,  ImageType::Normal },
         // clang-format on
 };
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index b7db9b6..f46fb09 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -140,6 +140,20 @@
 static void bootchart_thread_main() {
   LOG(INFO) << "Bootcharting started";
 
+  // Unshare the mount namespace of this thread so that the init process itself can switch
+  // the mount namespace later while this thread is still running.
+  // Otherwise, setns() call invoked as part of `enter_default_mount_ns` fails with EINVAL.
+  //
+  // Note that after unshare()'ing the mount namespace from the main thread, this thread won't
+  // receive mount/unmount events from the other mount namespace unless the events are happening
+  // from under a sharable mount.
+  //
+  // The bootchart thread is safe to unshare the mount namespace because it only reads from /proc
+  // and write to /data which are not private mounts.
+  if (unshare(CLONE_NEWNS) == -1) {
+      PLOG(ERROR) << "Cannot create mount namespace";
+      return;
+  }
   // Open log files.
   auto stat_log = fopen_unique("/data/bootchart/proc_stat.log", "we");
   if (!stat_log) return;
diff --git a/init/compare-bootcharts.py b/init/compare-bootcharts.py
index 2057b55..009b639 100755
--- a/init/compare-bootcharts.py
+++ b/init/compare-bootcharts.py
@@ -56,24 +56,24 @@
     ]
 
     jw = jiffy_record['jiffy_to_wallclock']
-    print "process: baseline experiment (delta)"
-    print " - Unit is ms (a jiffy is %d ms on the system)" % jw
-    print "------------------------------------"
+    print("process: baseline experiment (delta)")
+    print(" - Unit is ms (a jiffy is %d ms on the system)" % jw)
+    print("------------------------------------")
     for p in processes_of_interest:
         # e.g., 32-bit system doesn't have zygote64
         if p in process_map1 and p in process_map2:
-            print "%s: %d %d (%+d)" % (
+            print("%s: %d %d (%+d)" % (
                 p, process_map1[p]['start_time'] * jw,
                 process_map2[p]['start_time'] * jw,
                 (process_map2[p]['start_time'] -
-                 process_map1[p]['start_time']) * jw)
+                 process_map1[p]['start_time']) * jw))
 
     # Print the last tick for the bootanimation process
-    print "bootanimation ends at: %d %d (%+d)" % (
+    print("bootanimation ends at: %d %d (%+d)" % (
         process_map1['/system/bin/bootanimation']['last_tick'] * jw,
         process_map2['/system/bin/bootanimation']['last_tick'] * jw,
         (process_map2['/system/bin/bootanimation']['last_tick'] -
-            process_map1['/system/bin/bootanimation']['last_tick']) * jw)
+            process_map1['/system/bin/bootanimation']['last_tick']) * jw))
 
 def parse_proc_file(pathname, process_map, jiffy_record=None):
     # Uncompress bootchart.tgz
@@ -83,7 +83,7 @@
             f = tf.extractfile('proc_ps.log')
 
             # Break proc_ps into chunks based on timestamps
-            blocks = f.read().split('\n\n')
+            blocks = f.read().decode('utf-8').split('\n\n')
             for b in blocks:
                 lines = b.split('\n')
                 if not lines[0]:
@@ -133,7 +133,7 @@
 
 def main():
     if len(sys.argv) != 3:
-        print "Usage: %s base_bootchart_dir exp_bootchart_dir" % sys.argv[0]
+        print("Usage: %s base_bootchart_dir exp_bootchart_dir" % sys.argv[0])
         sys.exit(1)
 
     process_map1 = {}
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 6aa9912..41cf748 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -18,6 +18,7 @@
 
 #include <dirent.h>
 #include <fcntl.h>
+#include <linux/f2fs.h>
 #include <linux/fs.h>
 #include <linux/loop.h>
 #include <mntent.h>
@@ -218,7 +219,7 @@
                  << stat;
 }
 
-static bool IsDataMounted() {
+static bool IsDataMounted(const std::string& fstype) {
     std::unique_ptr<std::FILE, int (*)(std::FILE*)> fp(setmntent("/proc/mounts", "re"), endmntent);
     if (fp == nullptr) {
         PLOG(ERROR) << "Failed to open /proc/mounts";
@@ -227,7 +228,7 @@
     mntent* mentry;
     while ((mentry = getmntent(fp.get())) != nullptr) {
         if (mentry->mnt_dir == "/data"s) {
-            return true;
+            return fstype == "*" || mentry->mnt_type == fstype;
         }
     }
     return false;
@@ -633,7 +634,7 @@
 
     // If /data isn't mounted then we can skip the extra reboot steps below, since we don't need to
     // worry about unmounting it.
-    if (!IsDataMounted()) {
+    if (!IsDataMounted("*")) {
         sync();
         RebootSystem(cmd, reboot_target);
         abort();
@@ -758,6 +759,16 @@
     sem_post(&reboot_semaphore);
 
     // Reboot regardless of umount status. If umount fails, fsck after reboot will fix it.
+    if (IsDataMounted("f2fs")) {
+        uint32_t flag = F2FS_GOING_DOWN_FULLSYNC;
+        unique_fd fd(TEMP_FAILURE_RETRY(open("/data", O_RDONLY)));
+        int ret = ioctl(fd, F2FS_IOC_SHUTDOWN, &flag);
+        if (ret) {
+            PLOG(ERROR) << "Shutdown /data: ";
+        } else {
+            LOG(INFO) << "Shutdown /data";
+        }
+    }
     RebootSystem(cmd, reboot_target);
     abort();
 }
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index c6bf708..586e2cf 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -298,21 +298,31 @@
 
 static UeventdConfiguration GetConfiguration() {
     auto hardware = android::base::GetProperty("ro.hardware", "");
-    std::vector<std::string> legacy_paths{"/vendor/ueventd.rc", "/odm/ueventd.rc",
-                                          "/ueventd." + hardware + ".rc"};
+
+    struct LegacyPathInfo {
+        std::string legacy_path;
+        std::string preferred;
+    };
+    std::vector<LegacyPathInfo> legacy_paths{
+            {"/vendor/ueventd.rc", "/vendor/etc/ueventd.rc"},
+            {"/odm/ueventd.rc", "/odm/etc/ueventd.rc"},
+            {"/ueventd." + hardware + ".rc", "another ueventd.rc file"}};
 
     std::vector<std::string> canonical{"/system/etc/ueventd.rc"};
 
     if (android::base::GetIntProperty("ro.product.first_api_level", 10000) < __ANDROID_API_T__) {
         // TODO: Remove these legacy paths once Android S is no longer supported.
-        canonical.insert(canonical.end(), legacy_paths.begin(), legacy_paths.end());
+        for (const auto& info : legacy_paths) {
+            canonical.push_back(info.legacy_path);
+        }
     } else {
         // Warn if newer device is using legacy paths.
-        for (const auto& path : legacy_paths) {
-            if (access(path.c_str(), F_OK) == 0) {
+        for (const auto& info : legacy_paths) {
+            if (access(info.legacy_path.c_str(), F_OK) == 0) {
                 LOG(FATAL_WITHOUT_ABORT)
                         << "Legacy ueventd configuration file detected and will not be parsed: "
-                        << path;
+                        << info.legacy_path << ". Please move your configuration to "
+                        << info.preferred << " instead.";
             }
         }
     }
diff --git a/libsparse/sparse_fuzzer.cpp b/libsparse/sparse_fuzzer.cpp
index 235d15d..663c812 100644
--- a/libsparse/sparse_fuzzer.cpp
+++ b/libsparse/sparse_fuzzer.cpp
@@ -23,5 +23,7 @@
   if (!file) {
       return 0;
   }
-  return sparse_file_callback(file, false, false, WriteCallback, nullptr);
+  int32_t result = sparse_file_callback(file, false, false, WriteCallback, nullptr);
+  sparse_file_destroy(file);
+  return result;
 }
diff --git a/libstats/pull_rust/stats_pull.rs b/libstats/pull_rust/stats_pull.rs
index 174125e..09b2623 100644
--- a/libstats/pull_rust/stats_pull.rs
+++ b/libstats/pull_rust/stats_pull.rs
@@ -68,7 +68,7 @@
     }
 
     /// Calls AStatsManager_PullAtomMetadata_setAdditiveFields.
-    pub fn set_additive_fields(&mut self, additive_fields: &mut Vec<i32>) {
+    pub fn set_additive_fields(&mut self, additive_fields: &mut [i32]) {
         // Safety: Metadata::new ensures that self.metadata is a valid object.
         unsafe {
             AStatsManager_PullAtomMetadata_setAdditiveFields(
diff --git a/libutils/VectorImpl.cpp b/libutils/VectorImpl.cpp
index c97a19b..d951b8b 100644
--- a/libutils/VectorImpl.cpp
+++ b/libutils/VectorImpl.cpp
@@ -279,14 +279,12 @@
 
 ssize_t VectorImpl::removeItemsAt(size_t index, size_t count)
 {
-    ALOG_ASSERT((index+count)<=size(),
-        "[%p] remove: index=%d, count=%d, size=%d",
-               this, (int)index, (int)count, (int)size());
-
-    if ((index+count) > size())
-        return BAD_VALUE;
-   _shrink(index, count);
-   return index;
+    size_t end;
+    LOG_ALWAYS_FATAL_IF(__builtin_add_overflow(index, count, &end), "overflow: index=%zu count=%zu",
+                        index, count);
+    if (end > size()) return BAD_VALUE;
+    _shrink(index, count);
+    return index;
 }
 
 void VectorImpl::finish_vector()
diff --git a/libutils/Vector_test.cpp b/libutils/Vector_test.cpp
index 5336c40..6d90eaa 100644
--- a/libutils/Vector_test.cpp
+++ b/libutils/Vector_test.cpp
@@ -136,4 +136,13 @@
   }
 }
 
+TEST_F(VectorTest, removeItemsAt_overflow) {
+    android::Vector<int> v;
+    for (int i = 0; i < 666; i++) v.add(i);
+
+    ASSERT_DEATH(v.removeItemsAt(SIZE_MAX, 666), "overflow");
+    ASSERT_DEATH(v.removeItemsAt(666, SIZE_MAX), "overflow");
+    ASSERT_DEATH(v.removeItemsAt(SIZE_MAX, SIZE_MAX), "overflow");
+}
+
 } // namespace android
diff --git a/rootdir/init.rc b/rootdir/init.rc
index d39a21c..0bd0e1d 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -829,7 +829,10 @@
     mkdir /data/misc/odsign/metrics 0770 root system
 
     # Directory for VirtualizationService temporary image files.
-    mkdir /data/misc/virtualizationservice 0700 system system
+    # 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/preloads 0775 system system encryption=None
 
@@ -1096,6 +1099,9 @@
     write /dev/sys/fs/by-name/userdata/gc_urgent_sleep_time 50
     write /dev/sys/fs/by-name/userdata/iostat_enable 1
 
+    # set readahead multiplier for POSIX_FADV_SEQUENTIAL files
+    write /dev/sys/fs/by-name/userdata/seq_file_ra_mul 16
+
     # limit discard size to 128MB in order to avoid long IO latency
     # for filesystem tuning first (dm or sda)
     # this requires enabling selinux entry for sda/mmcblk0 in vendor side