Merge "Move libbinderwrapper to update_engine"
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 30eb7b5..6fc6f5f 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -173,7 +173,7 @@
         // clang-format on
 };
 
-static char* get_android_product_out() {
+char* get_android_product_out() {
     char* dir = getenv("ANDROID_PRODUCT_OUT");
     if (dir == nullptr || dir[0] == '\0') {
         return nullptr;
@@ -1747,7 +1747,7 @@
         }
         tasks.emplace_back(std::move(task));
     }
-    if (auto flash_super_task = FlashSuperLayoutTask::InitializeFromTasks(fp, tasks)) {
+    if (auto flash_super_task = OptimizedFlashSuperTask::InitializeFromTasks(fp, tasks)) {
         auto it = tasks.begin();
         for (size_t i = 0; i < tasks.size(); i++) {
             if (auto flash_task = tasks[i]->AsFlashTask()) {
@@ -1787,13 +1787,25 @@
 
     CancelSnapshotIfNeeded();
 
-    tasks_ = CollectTasksFromImageList();
+    tasks_ = CollectTasks();
     for (auto& task : tasks_) {
         task->Run();
     }
     return;
 }
 
+std::vector<std::unique_ptr<Task>> FlashAllTool::CollectTasks() {
+    std::vector<std::unique_ptr<Task>> tasks;
+    if (fp_->should_use_fastboot_info) {
+        tasks = CollectTasksFromFastbootInfo();
+
+    } else {
+        tasks = CollectTasksFromImageList();
+    }
+
+    return tasks;
+}
+
 void FlashAllTool::CheckRequirements() {
     std::vector<char> contents;
     if (!fp_->source->ReadFile("android-info.txt", &contents)) {
@@ -1848,8 +1860,7 @@
     // or in bootloader fastboot.
     std::vector<std::unique_ptr<Task>> tasks;
     AddFlashTasks(boot_images_, tasks);
-
-    if (auto flash_super_task = FlashSuperLayoutTask::Initialize(fp_, os_images_)) {
+    if (auto flash_super_task = OptimizedFlashSuperTask::Initialize(fp_, os_images_)) {
         tasks.emplace_back(std::move(flash_super_task));
     } else {
         // Sync the super partition. This will reboot to userspace fastboot if needed.
@@ -1871,10 +1882,23 @@
             tasks.emplace_back(std::make_unique<ResizeTask>(fp_, image->part_name, "0", slot));
         }
     }
+
     AddFlashTasks(os_images_, tasks);
     return tasks;
 }
 
+std::vector<std::unique_ptr<Task>> FlashAllTool::CollectTasksFromFastbootInfo() {
+    std::vector<std::unique_ptr<Task>> tasks;
+    std::vector<char> contents;
+    if (!fp_->source->ReadFile("fastboot-info.txt", &contents)) {
+        LOG(VERBOSE) << "Flashing from hardcoded images. fastboot-info.txt is empty or does not "
+                        "exist";
+        return CollectTasksFromImageList();
+    }
+    tasks = ParseFastbootInfo(fp_, Split({contents.data(), contents.size()}, "\n"));
+    return tasks;
+}
+
 void FlashAllTool::AddFlashTasks(const std::vector<std::pair<const Image*, std::string>>& images,
                                  std::vector<std::unique_ptr<Task>>& tasks) {
     for (const auto& [image, slot] : images) {
@@ -2205,8 +2229,9 @@
                                       {0, 0, 0, 0}};
 
     serial = getenv("FASTBOOT_DEVICE");
-    if (!serial)
+    if (!serial) {
         serial = getenv("ANDROID_SERIAL");
+    }
 
     int c;
     while ((c = getopt_long(argc, argv, "a::hls:S:vw", longopts, &longindex)) != -1) {
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index 196bd67..77430f0 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -97,6 +97,7 @@
     bool skip_secondary = false;
     bool force_flash = false;
     bool should_optimize_flash_super = true;
+    bool should_use_fastboot_info = false;
     uint64_t sparse_limit = 0;
 
     std::string slot_override;
@@ -111,6 +112,7 @@
     FlashAllTool(FlashingPlan* fp);
 
     void Flash();
+    std::vector<std::unique_ptr<Task>> CollectTasks();
 
   private:
     void CheckRequirements();
@@ -118,6 +120,8 @@
     void CollectImages();
     void AddFlashTasks(const std::vector<std::pair<const Image*, std::string>>& images,
                        std::vector<std::unique_ptr<Task>>& tasks);
+
+    std::vector<std::unique_ptr<Task>> CollectTasksFromFastbootInfo();
     std::vector<std::unique_ptr<Task>> CollectTasksFromImageList();
 
     std::vector<ImageEntry> boot_images_;
@@ -143,6 +147,7 @@
     unique_fd OpenFile(const std::string& name) const override;
 };
 
+char* get_android_product_out();
 bool should_flash_in_userspace(const std::string& partition_name);
 bool is_userspace_fastboot();
 void do_flash(const char* pname, const char* fname, const bool apply_vbmeta,
diff --git a/fastboot/task.cpp b/fastboot/task.cpp
index c1b9a31..bf64f0e 100644
--- a/fastboot/task.cpp
+++ b/fastboot/task.cpp
@@ -96,17 +96,17 @@
     return "reboot " + reboot_target_;
 }
 
-FlashSuperLayoutTask::FlashSuperLayoutTask(const std::string& super_name,
-                                           std::unique_ptr<SuperFlashHelper> helper,
-                                           SparsePtr sparse_layout, uint64_t super_size,
-                                           const FlashingPlan* fp)
+OptimizedFlashSuperTask::OptimizedFlashSuperTask(const std::string& super_name,
+                                                 std::unique_ptr<SuperFlashHelper> helper,
+                                                 SparsePtr sparse_layout, uint64_t super_size,
+                                                 const FlashingPlan* fp)
     : super_name_(super_name),
       helper_(std::move(helper)),
       sparse_layout_(std::move(sparse_layout)),
       super_size_(super_size),
       fp_(fp) {}
 
-void FlashSuperLayoutTask::Run() {
+void OptimizedFlashSuperTask::Run() {
     // Use the reported super partition size as the upper limit, rather than
     // sparse_file_len, which (1) can fail and (2) is kind of expensive, since
     // it will map in all of the embedded fds.
@@ -120,11 +120,11 @@
     // Send the data to the device.
     flash_partition_files(super_name_, files);
 }
-std::string FlashSuperLayoutTask::ToString() {
+std::string OptimizedFlashSuperTask::ToString() {
     return "optimized-flash-super";
 }
 
-std::unique_ptr<FlashSuperLayoutTask> FlashSuperLayoutTask::Initialize(
+std::unique_ptr<OptimizedFlashSuperTask> OptimizedFlashSuperTask::Initialize(
         const FlashingPlan* fp, std::vector<ImageEntry>& os_images) {
     if (!fp->should_optimize_flash_super) {
         LOG(INFO) << "super optimization is disabled";
@@ -188,11 +188,11 @@
     };
     os_images.erase(std::remove_if(os_images.begin(), os_images.end(), remove_if_callback),
                     os_images.end());
-    return std::make_unique<FlashSuperLayoutTask>(super_name, std::move(helper), std::move(s),
-                                                  partition_size, fp);
+    return std::make_unique<OptimizedFlashSuperTask>(super_name, std::move(helper), std::move(s),
+                                                     partition_size, fp);
 }
 
-std::unique_ptr<FlashSuperLayoutTask> FlashSuperLayoutTask::InitializeFromTasks(
+std::unique_ptr<OptimizedFlashSuperTask> OptimizedFlashSuperTask::InitializeFromTasks(
         const FlashingPlan* fp, std::vector<std::unique_ptr<Task>>& tasks) {
     if (!fp->should_optimize_flash_super) {
         LOG(INFO) << "super optimization is disabled";
@@ -261,8 +261,8 @@
     };
     tasks.erase(std::remove_if(tasks.begin(), tasks.end(), remove_if_callback), tasks.end());
 
-    return std::make_unique<FlashSuperLayoutTask>(super_name, std::move(helper), std::move(s),
-                                                  partition_size, fp);
+    return std::make_unique<OptimizedFlashSuperTask>(super_name, std::move(helper), std::move(s),
+                                                     partition_size, fp);
 }
 
 UpdateSuperTask::UpdateSuperTask(const FlashingPlan* fp) : fp_(fp) {}
diff --git a/fastboot/task.h b/fastboot/task.h
index 858f43a..f7c8801 100644
--- a/fastboot/task.h
+++ b/fastboot/task.h
@@ -79,13 +79,13 @@
     const FlashingPlan* fp_;
 };
 
-class FlashSuperLayoutTask : public Task {
+class OptimizedFlashSuperTask : public Task {
   public:
-    FlashSuperLayoutTask(const std::string& super_name, std::unique_ptr<SuperFlashHelper> helper,
-                         SparsePtr sparse_layout, uint64_t super_size, const FlashingPlan* fp);
-    static std::unique_ptr<FlashSuperLayoutTask> Initialize(const FlashingPlan* fp,
-                                                            std::vector<ImageEntry>& os_images);
-    static std::unique_ptr<FlashSuperLayoutTask> InitializeFromTasks(
+    OptimizedFlashSuperTask(const std::string& super_name, std::unique_ptr<SuperFlashHelper> helper,
+                            SparsePtr sparse_layout, uint64_t super_size, const FlashingPlan* fp);
+    static std::unique_ptr<OptimizedFlashSuperTask> Initialize(const FlashingPlan* fp,
+                                                               std::vector<ImageEntry>& os_images);
+    static std::unique_ptr<OptimizedFlashSuperTask> InitializeFromTasks(
             const FlashingPlan* fp, std::vector<std::unique_ptr<Task>>& tasks);
     using ImageEntry = std::pair<const Image*, std::string>;
     void Run() override;
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index c3c10ba..c85e831 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -51,6 +51,7 @@
 namespace {
 
 constexpr char kDefaultAndroidDtDir[] = "/proc/device-tree/firmware/android";
+constexpr char kProcMountsPath[] = "/proc/mounts";
 
 struct FlagList {
     const char *name;
@@ -699,9 +700,7 @@
     }
 }
 
-bool ReadFstabFromFile(const std::string& path, Fstab* fstab_out) {
-    const bool is_proc_mounts = (path == "/proc/mounts");
-
+static bool ReadFstabFromFileCommon(const std::string& path, Fstab* fstab_out) {
     std::string fstab_str;
     if (!android::base::ReadFileToString(path, &fstab_str, /* follow_symlinks = */ true)) {
         PERROR << __FUNCTION__ << "(): failed to read file: '" << path << "'";
@@ -709,11 +708,22 @@
     }
 
     Fstab fstab;
-    if (!ParseFstabFromString(fstab_str, is_proc_mounts, &fstab)) {
+    if (!ParseFstabFromString(fstab_str, path == kProcMountsPath, &fstab)) {
         LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << path << "'";
         return false;
     }
-    if (!is_proc_mounts) {
+
+    EnableMandatoryFlags(&fstab);
+
+    *fstab_out = std::move(fstab);
+    return true;
+}
+
+bool ReadFstabFromFile(const std::string& path, Fstab* fstab) {
+    if (!ReadFstabFromFileCommon(path, fstab)) {
+        return false;
+    }
+    if (path != kProcMountsPath) {
         if (!access(android::gsi::kGsiBootedIndicatorFile, F_OK)) {
             std::string dsu_slot;
             if (!android::gsi::GetActiveDsu(&dsu_slot)) {
@@ -725,20 +735,23 @@
                 PERROR << __FUNCTION__ << "(): failed to read DSU LP names";
                 return false;
             }
-            TransformFstabForDsu(&fstab, dsu_slot, Split(lp_names, ","));
+            TransformFstabForDsu(fstab, dsu_slot, Split(lp_names, ","));
         } else if (errno != ENOENT) {
             PERROR << __FUNCTION__ << "(): failed to access() DSU booted indicator";
             return false;
         }
+
+        SkipMountingPartitions(fstab, false /* verbose */);
     }
-
-    SkipMountingPartitions(&fstab, false /* verbose */);
-    EnableMandatoryFlags(&fstab);
-
-    *fstab_out = std::move(fstab);
     return true;
 }
 
+bool ReadFstabFromProcMounts(Fstab* fstab) {
+    // Don't call `ReadFstabFromFile` because the code for `path != kProcMountsPath` has an extra
+    // code size cost, even if it's never executed.
+    return ReadFstabFromFileCommon(kProcMountsPath, fstab);
+}
+
 // Returns fstab entries parsed from the device tree if they exist
 bool ReadFstabFromDt(Fstab* fstab, bool verbose) {
     std::string fstab_buf = ReadFstabFromDt();
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index a914b53..9cb1546 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -101,6 +101,7 @@
 bool SkipMountWithConfig(const std::string& skip_config, Fstab* fstab, bool verbose);
 
 bool ReadFstabFromFile(const std::string& path, Fstab* fstab);
+bool ReadFstabFromProcMounts(Fstab* fstab);
 bool ReadFstabFromDt(Fstab* fstab, bool verbose = true);
 bool ReadDefaultFstab(Fstab* fstab);
 bool SkipMountingPartitions(Fstab* fstab, bool verbose = false);
diff --git a/libcutils/include/cutils/trace.h b/libcutils/include/cutils/trace.h
index 3867f34..7f57637 100644
--- a/libcutils/include/cutils/trace.h
+++ b/libcutils/include/cutils/trace.h
@@ -89,6 +89,36 @@
 #error ATRACE_TAG must be defined to be one of the tags defined in cutils/trace.h
 #endif
 
+/** Internal implementation detail. Do not use. */
+void atrace_begin_body(const char*);
+
+/** Internal implementation detail. Do not use. */
+void atrace_end_body();
+
+/** Internal implementation detail. Do not use. */
+void atrace_async_begin_body(const char*, int32_t);
+
+/** Internal implementation detail. Do not use. */
+void atrace_async_end_body(const char*, int32_t);
+
+/** Internal implementation detail. Do not use. */
+void atrace_async_for_track_begin_body(const char*, const char*, int32_t);
+
+/** Internal implementation detail. Do not use. */
+void atrace_async_for_track_end_body(const char*, int32_t);
+
+/** Internal implementation detail. Do not use. */
+void atrace_instant_body(const char*);
+
+/** Internal implementation detail. Do not use. */
+void atrace_instant_for_track_body(const char*, const char*);
+
+/** Internal implementation detail. Do not use. */
+void atrace_int_body(const char*, int32_t);
+
+/** Internal implementation detail. Do not use. */
+void atrace_int64_body(const char*, int64_t);
+
 /**
  * Opens the trace file for writing and reads the property for initial tags.
  * The atrace.tags.enableflags property sets the tags to trace.
@@ -159,7 +189,6 @@
 static inline void atrace_begin(uint64_t tag, const char* name)
 {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_begin_body(const char*);
         atrace_begin_body(name);
     }
 }
@@ -172,7 +201,6 @@
 static inline void atrace_end(uint64_t tag)
 {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_end_body();
         atrace_end_body();
     }
 }
@@ -190,7 +218,6 @@
         int32_t cookie)
 {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_async_begin_body(const char*, int32_t);
         atrace_async_begin_body(name, cookie);
     }
 }
@@ -203,7 +230,6 @@
 static inline void atrace_async_end(uint64_t tag, const char* name, int32_t cookie)
 {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_async_end_body(const char*, int32_t);
         atrace_async_end_body(name, cookie);
     }
 }
@@ -221,7 +247,6 @@
 static inline void atrace_async_for_track_begin(uint64_t tag, const char* track_name,
                                                 const char* name, int32_t cookie) {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_async_for_track_begin_body(const char*, const char*, int32_t);
         atrace_async_for_track_begin_body(track_name, name, cookie);
     }
 }
@@ -235,7 +260,6 @@
 static inline void atrace_async_for_track_end(uint64_t tag, const char* track_name,
                                               int32_t cookie) {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_async_for_track_end_body(const char*, int32_t);
         atrace_async_for_track_end_body(track_name, cookie);
     }
 }
@@ -252,7 +276,6 @@
 #define ATRACE_INSTANT(name) atrace_instant(ATRACE_TAG, name)
 static inline void atrace_instant(uint64_t tag, const char* name) {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_instant_body(const char*);
         atrace_instant_body(name);
     }
 }
@@ -269,7 +292,6 @@
 static inline void atrace_instant_for_track(uint64_t tag, const char* track_name,
                                             const char* name) {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_instant_for_track_body(const char*, const char*);
         atrace_instant_for_track_body(track_name, name);
     }
 }
@@ -282,7 +304,6 @@
 static inline void atrace_int(uint64_t tag, const char* name, int32_t value)
 {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_int_body(const char*, int32_t);
         atrace_int_body(name, value);
     }
 }
@@ -295,7 +316,6 @@
 static inline void atrace_int64(uint64_t tag, const char* name, int64_t value)
 {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_int64_body(const char*, int64_t);
         atrace_int64_body(name, value);
     }
 }
diff --git a/libcutils/trace-host.cpp b/libcutils/trace-host.cpp
index e9f58c3..2bf57eb 100644
--- a/libcutils/trace-host.cpp
+++ b/libcutils/trace-host.cpp
@@ -20,7 +20,6 @@
 int                     atrace_marker_fd     = -1;
 uint64_t                atrace_enabled_tags  = 0;
 
-void atrace_set_debuggable(bool /*debuggable*/) {}
 void atrace_set_tracing_enabled(bool /*enabled*/) {}
 void atrace_update_tags() { }
 void atrace_setup() { }
diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp
index d20b6b1..5023c79 100644
--- a/libmodprobe/libmodprobe.cpp
+++ b/libmodprobe/libmodprobe.cpp
@@ -525,11 +525,8 @@
 
         std::lock_guard guard(module_loaded_lock_);
         // Remove loaded module form mod_with_deps and soft dependencies of other modules
-        for (const auto& module_loaded : module_loaded_) {
-            if (mod_with_deps.find(module_loaded) != mod_with_deps.end()) {
-                mod_with_deps.erase(module_loaded);
-            }
-        }
+        for (const auto& module_loaded : module_loaded_)
+            mod_with_deps.erase(module_loaded);
 
         // Remove loaded module form dependencies of other modules which are not loaded yet
         for (const auto& module_loaded_path : module_loaded_paths_) {
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index 5999e39..7cca105 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -362,14 +362,19 @@
     return err->error;
 }
 
+// Pass bitwise complement of prefix length to disable DAD, ie. use ~64 instead of 64.
 // Returns zero on success and negative errno on failure.
 int ifc_add_address(const char *name, const char *address, int prefixlen) {
-    return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen, /*nodad*/ false);
+    bool nodad = (prefixlen < 0);
+    if (nodad) prefixlen = ~prefixlen;
+    return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen, nodad);
 }
 
 // Returns zero on success and negative errno on failure.
 int ifc_del_address(const char *name, const char * address, int prefixlen) {
-    return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen, /*nodad*/ false);
+    bool nodad = (prefixlen < 0);
+    if (nodad) prefixlen = ~prefixlen;
+    return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen, nodad);
 }
 
 /*
diff --git a/libstats/pull_rust/Android.bp b/libstats/pull_rust/Android.bp
index 85a38f8..4609e6b 100644
--- a/libstats/pull_rust/Android.bp
+++ b/libstats/pull_rust/Android.bp
@@ -28,7 +28,6 @@
     ],
     source_stem: "bindings",
     bindgen_flags: [
-        "--size_t-is-usize",
         "--allowlist-function=AStatsEventList_addStatsEvent",
         "--allowlist-function=AStatsEvent_.*",
         "--allowlist-function=AStatsManager_.*",
diff --git a/libutils/Vector_fuzz.cpp b/libutils/Vector_fuzz.cpp
index f6df051..6fd2baf 100644
--- a/libutils/Vector_fuzz.cpp
+++ b/libutils/Vector_fuzz.cpp
@@ -13,71 +13,203 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "fuzzer/FuzzedDataProvider.h"
-#include "utils/Vector.h"
-static constexpr uint16_t MAX_VEC_SIZE = 5000;
+#include <fuzzer/FuzzedDataProvider.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
 
-void runVectorFuzz(const uint8_t* data, size_t size) {
-    FuzzedDataProvider dataProvider(data, size);
-    android::Vector<uint8_t> vec = android::Vector<uint8_t>();
-    // We want to test handling of sizeof as well.
-    android::Vector<uint32_t> vec32 = android::Vector<uint32_t>();
+#include <functional>
 
-    // We're going to generate two vectors of this size
-    size_t vectorSize = dataProvider.ConsumeIntegralInRange<size_t>(0, MAX_VEC_SIZE);
-    vec.setCapacity(vectorSize);
-    vec32.setCapacity(vectorSize);
-    for (size_t i = 0; i < vectorSize; i++) {
-        uint8_t count = dataProvider.ConsumeIntegralInRange<uint8_t>(1, 5);
-        vec.insertAt((uint8_t)i, i, count);
-        vec32.insertAt((uint32_t)i, i, count);
-        vec.push_front(i);
-        vec32.push(i);
+using android::Vector;
+
+static constexpr uint16_t MAX_VEC_SIZE = 100;
+static constexpr bool kLog = false;
+
+struct NonTrivialDestructor {
+    NonTrivialDestructor() : mInit(1) {}
+    ~NonTrivialDestructor() {
+        LOG_ALWAYS_FATAL_IF(mInit != 1, "mInit should be 1, but it's: %d", mInit);
+        mInit--;
+        LOG_ALWAYS_FATAL_IF(mInit != 0, "mInit should be 0, but it's: %d", mInit);
     }
 
-    // Now we'll perform some test operations with any remaining data
-    // Index to perform operations at
-    size_t index = dataProvider.ConsumeIntegralInRange<size_t>(0, vec.size());
-    std::vector<uint8_t> remainingVec = dataProvider.ConsumeRemainingBytes<uint8_t>();
-    // Insert an array and vector
-    vec.insertArrayAt(remainingVec.data(), index, remainingVec.size());
-    android::Vector<uint8_t> vecCopy = android::Vector<uint8_t>(vec);
-    vec.insertVectorAt(vecCopy, index);
-    // Same thing for 32 bit vector
-    android::Vector<uint32_t> vec32Copy = android::Vector<uint32_t>(vec32);
-    vec32.insertArrayAt(vec32Copy.array(), index, vec32.size());
-    vec32.insertVectorAt(vec32Copy, index);
-    // Replace single character
-    if (remainingVec.size() > 0) {
-        vec.replaceAt(remainingVec[0], index);
-        vec32.replaceAt(static_cast<uint32_t>(remainingVec[0]), index);
-    } else {
-        vec.replaceAt(0, index);
-        vec32.replaceAt(0, index);
+  private:
+    uint8_t mInit;
+};
+
+template <typename T>
+struct VectorFuzzerData {
+    Vector<T> vector;
+    const std::vector<std::function<void(FuzzedDataProvider&, Vector<T>&)>> funcs = {
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                // operator= Vector<TYPE>, still needs for SortedVector
+                if (kLog) ALOGI("operator=");
+                vector = testVector(provider);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("clear");
+                vector.clear();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("size");
+                vector.size();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("isEmpty");
+                vector.isEmpty();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("capacity");
+                vector.capacity();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                size_t vectorSize = provider.ConsumeIntegralInRange<size_t>(0, MAX_VEC_SIZE);
+                if (kLog) ALOGI("setCapacity");
+                vector.setCapacity(vectorSize);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                size_t vectorSize = provider.ConsumeIntegralInRange<size_t>(0, MAX_VEC_SIZE);
+                if (kLog) ALOGI("resize");
+                vector.resize(vectorSize);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("array");
+                vector.array();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("editArray");
+                vector.editArray();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                if (vector.size() == 0) return;
+                size_t idx = provider.ConsumeIntegralInRange<size_t>(0, vector.size() - 1);
+                if (kLog) ALOGI("operator[]");
+                vector[idx];  // returns a const value for Vector
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                if (vector.size() == 0) return;
+                size_t idx = provider.ConsumeIntegralInRange<size_t>(0, vector.size() - 1);
+                if (kLog) ALOGI("itemAt");
+                vector.itemAt(idx);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (vector.size() == 0) return;
+                if (kLog) ALOGI("top");
+                vector.top();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                if (vector.size() == 0) return;
+                size_t idx = provider.ConsumeIntegralInRange<size_t>(0, vector.size() - 1);
+                if (kLog) ALOGI("editItemAt");
+                vector.editItemAt(idx);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (vector.size() == 0) return;
+                if (kLog) ALOGI("editTop");
+                vector.editTop() = T{};
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size());
+                Vector vec2 = testVector(provider);
+                if (vec2.size() == 0) return;  // TODO: maybe we should support this?
+                if (kLog) ALOGI("insertVectorAt %d of size %zu", idx, vec2.size());
+                vector.insertVectorAt(vec2, idx);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                if (kLog) ALOGI("appendVector");
+                vector.appendVector(testVector(provider));
+            },
+            // TODO: insertArrayAt
+            // TODO: appendArray
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size());
+                uint8_t numItems = provider.ConsumeIntegralInRange<uint8_t>(1, 100);
+                if (kLog) ALOGI("insertAt");
+                vector.insertAt(idx, numItems);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size());
+                uint8_t numItems = provider.ConsumeIntegralInRange<uint8_t>(1, 100);
+                if (kLog) ALOGI("insertAt");
+                vector.insertAt(T{}, idx, numItems);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (vector.size() == 0) return;
+                if (kLog) ALOGI("pop");
+                vector.pop();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("push");
+                vector.push();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("add");
+                vector.add();
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("add");
+                vector.add(T{});
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size() - 1);
+                if (kLog) ALOGI("replaceAt");
+                vector.replaceAt(idx);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size() - 1);
+                if (kLog) ALOGI("replaceAt");
+                vector.replaceAt(T{}, idx);
+            },
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                if (vector.size() == 0) return;
+                uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, vector.size() - 1);
+                if (kLog) ALOGI("remoteItemsAt");
+                vector.removeItemsAt(idx);  // TODO: different count
+            },
+            // removeAt is alias for removeItemsAt
+            // TODO: sort
+            [&](FuzzedDataProvider& provider, Vector<T>& vector) {
+                (void)provider;
+                if (kLog) ALOGI("getItemSize");
+                vector.getItemSize();
+            },
+            // TODO: iterators
+    };
+
+    Vector<T> testVector(FuzzedDataProvider& provider) {
+        Vector<T> vec;
+        size_t vectorSize = provider.ConsumeIntegralInRange<size_t>(0, MAX_VEC_SIZE);
+        return vec;
     }
-    // Add any remaining bytes
-    for (uint8_t i : remainingVec) {
-        vec.add(i);
-        vec32.add(static_cast<uint32_t>(i));
+
+    void fuzz(FuzzedDataProvider&& provider) {
+        while (provider.remaining_bytes()) {
+            size_t funcIdx = provider.ConsumeIntegralInRange<size_t>(0, funcs.size() - 1);
+            funcs[funcIdx](provider, vector);
+        }
     }
-    // Shrink capactiy
-    vec.setCapacity(remainingVec.size());
-    vec32.setCapacity(remainingVec.size());
-    // Iterate through each pointer
-    size_t sum = 0;
-    for (auto& it : vec) {
-        sum += it;
-    }
-    for (auto& it : vec32) {
-        sum += it;
-    }
-    // Cleanup
-    vec.clear();
-    vecCopy.clear();
-    vec32.clear();
-    vec32Copy.clear();
-}
+};
+
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-    runVectorFuzz(data, size);
+    FuzzedDataProvider provider(data, size);
+
+    provider.PickValueInArray<std::function<void()>>({
+            [&]() { VectorFuzzerData<uint8_t>().fuzz(std::move(provider)); },
+            [&]() { VectorFuzzerData<int32_t>().fuzz(std::move(provider)); },
+            [&]() { VectorFuzzerData<NonTrivialDestructor>().fuzz(std::move(provider)); },
+    })();
+
     return 0;
 }
diff --git a/libutils/include/utils/Vector.h b/libutils/include/utils/Vector.h
index be35ea2..d5db3cb 100644
--- a/libutils/include/utils/Vector.h
+++ b/libutils/include/utils/Vector.h
@@ -67,13 +67,10 @@
     virtual                 ~Vector();
 
     /*! copy operator */
-            const Vector<TYPE>&     operator = (const Vector<TYPE>& rhs) const;
-            Vector<TYPE>&           operator = (const Vector<TYPE>& rhs);
+    Vector<TYPE>& operator=(const Vector<TYPE>& rhs);        // NOLINT(cert-oop54-cpp)
+    Vector<TYPE>& operator=(const SortedVector<TYPE>& rhs);  // NOLINT(cert-oop54-cpp)
 
-            const Vector<TYPE>&     operator = (const SortedVector<TYPE>& rhs) const;
-            Vector<TYPE>&           operator = (const SortedVector<TYPE>& rhs);
-
-            /*
+    /*
      * empty the vector
      */
 
@@ -248,27 +245,18 @@
     finish_vector();
 }
 
-template<class TYPE> inline
-Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) {
-    VectorImpl::operator = (rhs);
+template <class TYPE>
+inline Vector<TYPE>& Vector<TYPE>::operator=(const Vector<TYPE>& rhs)  // NOLINT(cert-oop54-cpp)
+{
+    VectorImpl::operator=(rhs);
     return *this;
 }
 
-template<class TYPE> inline
-const Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) const {
-    VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
-    return *this;
-}
-
-template<class TYPE> inline
-Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
-    VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
-    return *this;
-}
-
-template<class TYPE> inline
-const Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
-    VectorImpl::operator = (rhs);
+template <class TYPE>
+inline Vector<TYPE>& Vector<TYPE>::operator=(
+        const SortedVector<TYPE>& rhs)  // NOLINT(cert-oop54-cpp)
+{
+    VectorImpl::operator=(static_cast<const VectorImpl&>(rhs));
     return *this;
 }
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 5344368..a8b78d5 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -1129,7 +1129,7 @@
     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
+    write /dev/sys/fs/by-name/userdata/seq_file_ra_mul 128
 
     # limit discard size to 128MB in order to avoid long IO latency
     # for filesystem tuning first (dm or sda)