Merge "Fix shutdown animation cannot be shown"
diff --git a/TEST_MAPPING b/TEST_MAPPING
deleted file mode 100644
index da7fca1..0000000
--- a/TEST_MAPPING
+++ /dev/null
@@ -1,66 +0,0 @@
-{
-  "presubmit": [
-    {
-      "name": "adbd_test"
-    },
-    {
-      "name": "adb_crypto_test"
-    },
-    {
-      "name": "adb_pairing_auth_test"
-    },
-    {
-      "name": "adb_pairing_connection_test"
-    },
-    {
-      "name": "adb_tls_connection_test"
-    },
-    {
-      "name": "CtsFsMgrTestCases"
-    },
-    {
-      "name": "CtsInitTestCases"
-    },
-    {
-      "name": "debuggerd_test"
-    },
-    {
-      "name": "fs_mgr_vendor_overlay_test"
-    },
-    {
-      "name": "init_kill_services_test"
-    },
-    {
-      "name": "libpackagelistparser_test"
-    },
-    {
-      "name": "libcutils_test"
-    },
-    {
-      "name": "libmodprobe_tests"
-    },
-    {
-      "name": "libprocinfo_test"
-    },
-    {
-      "name": "libutils_test"
-    },
-    {
-      "name": "memunreachable_test"
-    },
-    {
-      "name": "memunreachable_unit_test"
-    },
-    {
-      "name": "memunreachable_binder_test"
-    },
-    {
-      "name": "propertyinfoserializer_tests"
-    }
-  ],
-  "imports": [
-    {
-      "path": "frameworks/base/tests/StagedInstallTest"
-    }
-  ]
-}
diff --git a/debuggerd/TEST_MAPPING b/debuggerd/TEST_MAPPING
new file mode 100644
index 0000000..d5327db
--- /dev/null
+++ b/debuggerd/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "debuggerd_test"
+    }
+  ]
+}
diff --git a/fastboot/README.md b/fastboot/README.md
index c224448..d3b6c1a 100644
--- a/fastboot/README.md
+++ b/fastboot/README.md
@@ -27,16 +27,16 @@
 1. Host sends a command, which is an ascii string in a single
    packet no greater than 64 bytes.
 
-2. Client response with a single packet no greater than 64 bytes.
+2. Client response with a single packet no greater than 256 bytes.
    The first four bytes of the response are "OKAY", "FAIL", "DATA",
    or "INFO".  Additional bytes may contain an (ascii) informative
    message.
 
-   a. INFO -> the remaining 60 bytes are an informative message
+   a. INFO -> the remaining 252 bytes are an informative message
       (providing progress or diagnostic messages).  They should
       be displayed and then step #2 repeats
 
-   b. FAIL -> the requested command failed.  The remaining 60 bytes
+   b. FAIL -> the requested command failed.  The remaining 252 bytes
       of the response (if present) provide a textual failure message
       to present to the user.  Stop.
 
@@ -53,13 +53,13 @@
    until the client has sent or received the number of bytes indicated
    in the "DATA" response above.
 
-4. Client responds with a single packet no greater than 64 bytes.
+4. Client responds with a single packet no greater than 256 bytes.
    The first four bytes of the response are "OKAY", "FAIL", or "INFO".
    Similar to #2:
 
-   a. INFO -> display the remaining 60 bytes and return to #4
+   a. INFO -> display the remaining 252 bytes and return to #4
 
-   b. FAIL -> display the remaining 60 bytes (if present) as a failure
+   b. FAIL -> display the remaining 252 bytes (if present) as a failure
       reason and consider the command failed.  Stop.
 
    c. OKAY -> success.  Go to #5
diff --git a/fastboot/socket.cpp b/fastboot/socket.cpp
index 5a14b63..3096905 100644
--- a/fastboot/socket.cpp
+++ b/fastboot/socket.cpp
@@ -28,6 +28,10 @@
 
 #include "socket.h"
 
+#ifndef _WIN32
+#include <sys/select.h>
+#endif
+
 #include <android-base/errors.h>
 #include <android-base/stringprintf.h>
 
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index d4fc2b9..7ae526f 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -65,6 +65,7 @@
         "-D_FILE_OFFSET_BITS=64",
     ],
     srcs: [
+        "blockdev.cpp",
         "file_wait.cpp",
         "fs_mgr.cpp",
         "fs_mgr_format.cpp",
@@ -126,10 +127,19 @@
     export_header_lib_headers: [
         "libfiemap_headers",
     ],
-    required: [
-        "e2freefrag",
-        "e2fsdroid",
-    ],
+    target: {
+        platform: {
+            required: [
+                "e2freefrag",
+                "e2fsdroid",
+            ],
+        },
+        recovery: {
+            required: [
+                "e2fsdroid.recovery",
+            ],
+        },
+    },
 }
 
 // Two variants of libfs_mgr are provided: libfs_mgr and libfs_mgr_binder.
diff --git a/fs_mgr/TEST_MAPPING b/fs_mgr/TEST_MAPPING
index 84709b6..432aa4f 100644
--- a/fs_mgr/TEST_MAPPING
+++ b/fs_mgr/TEST_MAPPING
@@ -1,6 +1,9 @@
 {
   "presubmit": [
     {
+      "name": "CtsFsMgrTestCases"
+    },
+    {
       "name": "libdm_test"
     },
     {
@@ -13,6 +16,9 @@
       "name": "fiemap_writer_test"
     },
     {
+      "name": "fs_mgr_vendor_overlay_test"
+    },
+    {
       "name": "vts_libsnapshot_test"
     },
     {
diff --git a/fs_mgr/blockdev.cpp b/fs_mgr/blockdev.cpp
new file mode 100644
index 0000000..14b217c
--- /dev/null
+++ b/fs_mgr/blockdev.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+
+#include <dirent.h>
+#include <libdm/dm.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+#include "blockdev.h"
+
+using android::base::Basename;
+using android::base::ErrnoError;
+using android::base::Error;
+using android::base::Result;
+using android::base::ResultError;
+using android::base::StartsWith;
+using android::base::StringPrintf;
+using android::base::unique_fd;
+using android::dm::DeviceMapper;
+
+// Return the parent device of a partition. Converts e.g. "sda26" into "sda".
+static std::string PartitionParent(const std::string& blockdev) {
+    if (blockdev.find('/') != std::string::npos) {
+        LOG(ERROR) << __func__ << ": invalid argument " << blockdev;
+        return blockdev;
+    }
+    auto dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/sys/class/block"), closedir};
+    if (!dir) {
+        return blockdev;
+    }
+    for (struct dirent* ent = readdir(dir.get()); ent; ent = readdir(dir.get())) {
+        if (ent->d_name[0] == '.') {
+            continue;
+        }
+        std::string path = StringPrintf("/sys/class/block/%s/%s", ent->d_name, blockdev.c_str());
+        struct stat statbuf;
+        if (stat(path.c_str(), &statbuf) >= 0) {
+            return ent->d_name;
+        }
+    }
+    return blockdev;
+}
+
+// Convert a major:minor pair into a block device name.
+static std::string BlockdevName(dev_t dev) {
+    auto dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/dev/block"), closedir};
+    if (!dir) {
+        return {};
+    }
+    for (struct dirent* ent = readdir(dir.get()); ent; ent = readdir(dir.get())) {
+        if (ent->d_name[0] == '.') {
+            continue;
+        }
+        const std::string path = std::string("/dev/block/") + ent->d_name;
+        struct stat statbuf;
+        if (stat(path.c_str(), &statbuf) >= 0 && dev == statbuf.st_rdev) {
+            return ent->d_name;
+        }
+    }
+    return {};
+}
+
+// Trim whitespace from the end of a string.
+static void rtrim(std::string& s) {
+    s.erase(s.find_last_not_of('\n') + 1, s.length());
+}
+
+// For file `file_path`, retrieve the block device backing the filesystem on
+// which the file exists and return the queue depth of the block device.
+static Result<uint32_t> BlockDeviceQueueDepth(const std::string& file_path) {
+    struct stat statbuf;
+    int res = stat(file_path.c_str(), &statbuf);
+    if (res < 0) {
+        return ErrnoError() << "stat(" << file_path << ")";
+    }
+    std::string blockdev = "/dev/block/" + BlockdevName(statbuf.st_dev);
+    LOG(DEBUG) << __func__ << ": " << file_path << " -> " << blockdev;
+    if (blockdev.empty()) {
+        const std::string err_msg =
+                StringPrintf("Failed to convert %u:%u (path %s)", major(statbuf.st_dev),
+                             minor(statbuf.st_dev), file_path.c_str());
+        return ResultError(err_msg, 0);
+    }
+    auto& dm = DeviceMapper::Instance();
+    for (;;) {
+        std::optional<std::string> child = dm.GetParentBlockDeviceByPath(blockdev);
+        if (!child) {
+            break;
+        }
+        LOG(DEBUG) << __func__ << ": " << blockdev << " -> " << *child;
+        blockdev = *child;
+    }
+    std::optional<std::string> maybe_blockdev = android::dm::ExtractBlockDeviceName(blockdev);
+    if (!maybe_blockdev) {
+        return ResultError("Failed to remove /dev/block/ prefix from " + blockdev, 0);
+    }
+    blockdev = PartitionParent(*maybe_blockdev);
+    LOG(DEBUG) << __func__ << ": "
+               << "Partition parent: " << blockdev;
+    const std::string nr_tags_path =
+            StringPrintf("/sys/class/block/%s/mq/0/nr_tags", blockdev.c_str());
+    std::string nr_tags;
+    if (!android::base::ReadFileToString(nr_tags_path, &nr_tags)) {
+        return ResultError("Failed to read " + nr_tags_path, 0);
+    }
+    rtrim(nr_tags);
+    LOG(DEBUG) << __func__ << ": " << file_path << " is backed by /dev/" << blockdev
+               << " and that block device supports queue depth " << nr_tags;
+    return strtol(nr_tags.c_str(), NULL, 0);
+}
+
+// Set 'nr_requests' of `loop_device_path` to the queue depth of the block
+// device backing `file_path`.
+Result<void> ConfigureQueueDepth(const std::string& loop_device_path,
+                                 const std::string& file_path) {
+    if (!StartsWith(loop_device_path, "/dev/")) {
+        return Error() << "Invalid argument " << loop_device_path;
+    }
+
+    const std::string loop_device_name = Basename(loop_device_path);
+
+    const Result<uint32_t> qd = BlockDeviceQueueDepth(file_path);
+    if (!qd.ok()) {
+        LOG(DEBUG) << __func__ << ": "
+                   << "BlockDeviceQueueDepth() returned " << qd.error();
+        return ResultError(qd.error());
+    }
+    const std::string nr_requests = StringPrintf("%u", *qd);
+    const std::string sysfs_path =
+            StringPrintf("/sys/class/block/%s/queue/nr_requests", loop_device_name.c_str());
+    unique_fd sysfs_fd(open(sysfs_path.c_str(), O_RDWR | O_CLOEXEC));
+    if (sysfs_fd == -1) {
+        return ErrnoError() << "Failed to open " << sysfs_path;
+    }
+
+    const int res = write(sysfs_fd.get(), nr_requests.data(), nr_requests.length());
+    if (res < 0) {
+        return ErrnoError() << "Failed to write to " << sysfs_path;
+    }
+    return {};
+}
diff --git a/fs_mgr/blockdev.h b/fs_mgr/blockdev.h
new file mode 100644
index 0000000..2c0d68a
--- /dev/null
+++ b/fs_mgr/blockdev.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/result.h>
+#include <string>
+
+android::base::Result<void> ConfigureQueueDepth(const std::string& loop_device_path,
+                                                const std::string& file_path);
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index ec66144..5f15aad 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -72,6 +72,7 @@
 #include <log/log_properties.h>
 #include <logwrap/logwrap.h>
 
+#include "blockdev.h"
 #include "fs_mgr_priv.h"
 
 #define KEY_LOC_PROP   "ro.crypto.keyfile.userdata"
@@ -2110,6 +2111,8 @@
 
     ConfigureIoScheduler(loop_device);
 
+    ConfigureQueueDepth(loop_device, "/");
+
     // set block size & direct IO
     unique_fd loop_fd(TEMP_FAILURE_RETRY(open(loop_device.c_str(), O_RDWR | O_CLOEXEC)));
     if (loop_fd.get() == -1) {
diff --git a/fs_mgr/fs_mgr_roots.cpp b/fs_mgr/fs_mgr_roots.cpp
index fdaffbe..d275320 100644
--- a/fs_mgr/fs_mgr_roots.cpp
+++ b/fs_mgr/fs_mgr_roots.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "android-base/file.h"
 #include "fs_mgr/roots.h"
 
 #include <sys/mount.h>
@@ -39,18 +40,26 @@
     while (true) {
         auto entry = GetEntryForMountPoint(fstab, str);
         if (entry != nullptr) return entry;
-        if (str == "/") break;
-        auto slash = str.find_last_of('/');
-        if (slash == std::string::npos) break;
-        if (slash == 0) {
-            str = "/";
-        } else {
-            str = str.substr(0, slash);
-        }
+        str = android::base::Dirname(str);
+        if (!str.compare(".") || !str.compare("/")) break;
     }
     return nullptr;
 }
 
+std::vector<FstabEntry*> GetEntriesForPath(Fstab* fstab, const std::string& path) {
+    std::vector<FstabEntry*> entries;
+    if (path.empty()) return entries;
+
+    std::string str(path);
+    while (true) {
+        entries = GetEntriesForMountPoint(fstab, str);
+        if (!entries.empty()) return entries;
+        str = android::base::Dirname(str);
+        if (!str.compare(".") || !str.compare("/")) break;
+    }
+    return entries;
+}
+
 enum class MountState {
     ERROR = -1,
     NOT_MOUNTED = 0,
@@ -71,12 +80,7 @@
     return MountState::NOT_MOUNTED;
 }
 
-bool EnsurePathMounted(Fstab* fstab, const std::string& path, const std::string& mount_pt) {
-    auto rec = GetEntryForPath(fstab, path);
-    if (rec == nullptr) {
-        LERROR << "unknown volume for path [" << path << "]";
-        return false;
-    }
+bool TryPathMount(FstabEntry* rec, const std::string& mount_pt) {
     if (rec->fs_type == "ramdisk") {
         // The ramdisk is always mounted.
         return true;
@@ -136,6 +140,21 @@
     return true;
 }
 
+bool EnsurePathMounted(Fstab* fstab, const std::string& path, const std::string& mount_point) {
+    auto entries = GetEntriesForPath(fstab, path);
+    if (entries.empty()) {
+        LERROR << "unknown volume for path [" << path << "]";
+        return false;
+    }
+
+    for (auto entry : entries) {
+        if (TryPathMount(entry, mount_point)) return true;
+    }
+
+    LERROR << "Failed to mount for path [" << path << "]";
+    return false;
+}
+
 bool EnsurePathUnmounted(Fstab* fstab, const std::string& path) {
     auto rec = GetEntryForPath(fstab, path);
     if (rec == nullptr) {
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index 8e3d5a5..4034e30 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -578,34 +578,30 @@
     return std::string{spec.target_type, sizeof(spec.target_type)};
 }
 
-static bool ExtractBlockDeviceName(const std::string& path, std::string* name) {
+std::optional<std::string> ExtractBlockDeviceName(const std::string& path) {
     static constexpr std::string_view kDevBlockPrefix("/dev/block/");
     if (android::base::StartsWith(path, kDevBlockPrefix)) {
-        *name = path.substr(kDevBlockPrefix.length());
-        return true;
+        return path.substr(kDevBlockPrefix.length());
     }
-    return false;
+    return {};
 }
 
 bool DeviceMapper::IsDmBlockDevice(const std::string& path) {
-    std::string name;
-    if (!ExtractBlockDeviceName(path, &name)) {
-        return false;
-    }
-    return android::base::StartsWith(name, "dm-");
+    std::optional<std::string> name = ExtractBlockDeviceName(path);
+    return name && android::base::StartsWith(*name, "dm-");
 }
 
 std::optional<std::string> DeviceMapper::GetDmDeviceNameByPath(const std::string& path) {
-    std::string name;
-    if (!ExtractBlockDeviceName(path, &name)) {
+    std::optional<std::string> name = ExtractBlockDeviceName(path);
+    if (!name) {
         LOG(WARNING) << path << " is not a block device";
         return std::nullopt;
     }
-    if (!android::base::StartsWith(name, "dm-")) {
+    if (!android::base::StartsWith(*name, "dm-")) {
         LOG(WARNING) << path << " is not a dm device";
         return std::nullopt;
     }
-    std::string dm_name_file = "/sys/block/" + name + "/dm/name";
+    std::string dm_name_file = "/sys/block/" + *name + "/dm/name";
     std::string dm_name;
     if (!android::base::ReadFileToString(dm_name_file, &dm_name)) {
         PLOG(ERROR) << "Failed to read file " << dm_name_file;
@@ -616,16 +612,16 @@
 }
 
 std::optional<std::string> DeviceMapper::GetParentBlockDeviceByPath(const std::string& path) {
-    std::string name;
-    if (!ExtractBlockDeviceName(path, &name)) {
+    std::optional<std::string> name = ExtractBlockDeviceName(path);
+    if (!name) {
         LOG(WARNING) << path << " is not a block device";
         return std::nullopt;
     }
-    if (!android::base::StartsWith(name, "dm-")) {
+    if (!android::base::StartsWith(*name, "dm-")) {
         // Reached bottom of the device mapper stack.
         return std::nullopt;
     }
-    auto slaves_dir = "/sys/block/" + name + "/slaves";
+    auto slaves_dir = "/sys/block/" + *name + "/slaves";
     auto dir = std::unique_ptr<DIR, decltype(&closedir)>(opendir(slaves_dir.c_str()), closedir);
     if (dir == nullptr) {
         PLOG(ERROR) << "Failed to open: " << slaves_dir;
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index 31c3003..7e01b85 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -51,6 +51,10 @@
 
 static constexpr uint64_t kSectorSize = 512;
 
+// Returns `path` without /dev/block prefix if and only if `path` starts with
+// that prefix.
+std::optional<std::string> ExtractBlockDeviceName(const std::string& path);
+
 class DeviceMapper final {
   public:
     class DmBlockDevice final {
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h
index 0457986..3655c01 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h
@@ -36,6 +36,8 @@
 
     MOCK_METHOD(bool, EmitCopy, (uint64_t, uint64_t), (override));
     MOCK_METHOD(bool, EmitRawBlocks, (uint64_t, const void*, size_t), (override));
+    MOCK_METHOD(bool, EmitXorBlocks, (uint32_t, const void*, size_t, uint32_t, uint16_t),
+                (override));
     MOCK_METHOD(bool, EmitZeroBlocks, (uint64_t, uint64_t), (override));
     MOCK_METHOD(bool, EmitLabel, (uint64_t), (override));
     MOCK_METHOD(bool, EmitSequenceData, (size_t, const uint32_t*), (override));
diff --git a/init/Android.bp b/init/Android.bp
index a04d2db..5d09687 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -236,6 +236,7 @@
                 "init.rc",
                 "ueventd.rc",
                 "e2fsdroid",
+                "extra_free_kbytes.sh",
                 "make_f2fs",
                 "mke2fs",
                 "sload_f2fs",
@@ -552,3 +553,8 @@
         },
     },
 }
+
+sh_binary {
+    name: "extra_free_kbytes.sh",
+    src: "extra_free_kbytes.sh",
+}
diff --git a/init/TEST_MAPPING b/init/TEST_MAPPING
new file mode 100644
index 0000000..905d41e
--- /dev/null
+++ b/init/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsInitTestCases"
+    },
+    {
+      "name": "init_kill_services_test"
+    }
+  ]
+}
diff --git a/init/extra_free_kbytes.sh b/init/extra_free_kbytes.sh
new file mode 100755
index 0000000..aeaa912
--- /dev/null
+++ b/init/extra_free_kbytes.sh
@@ -0,0 +1,136 @@
+#!/bin/sh
+
+# Script implements watermark_scale calculation which results in the same low
+# watermark as if extra_free_kbytes tunable were to be used.
+#
+# Usage: extra_free_kbytes.sh <extra_free_kbytes value>
+#
+# extra_free_kbytes is distributed between zones based on
+# zone.managed_pages/vm_total_pages ratio, where vm_total_pages is the sum of
+# zone.managed_pages for all zones (zone.high used in this calculation is 0
+# when this is calculated). Therefore for each zone its share is calculated as:
+#
+# extra_free_pages = extra_free_kbytes / page_size
+# extra_share = extra_free_pages * managed_pages / vm_total_pages
+#
+# This extra_share is added to the low and high watermarks:
+#
+# low = min + max(min / 4, managed_pages * (watermark_scale / 10000)) + extra_share
+# high = min + 2 * max(min / 4, managed_pages * (watermark_scale / 10000)) + extra_share
+#
+# Because Android uses extra_free_kbytes to adjust the low watermark, we ignore
+# the difference in how watermark_scale and extra_free_kbytes affect the high
+# watermark and will match the low watermark only.
+#
+# To eliminate extra_share and compansate the difference with watermark_scale,
+# a new watermark_scale_new is calculated as:
+#
+# (1) max(min / 4, managed_pages * (watermark_scale / 10000)) + extra_share =
+#   max(min / 4, managed_pages * (watermark_scale_new / 10000))
+#
+# Two cases to consider:
+# A. managed_pages * (watermark_scale / 10000) > min / 4
+# The formula (1) becomes:
+#
+# managed_pages * (watermark_scale / 10000) + extra_share =
+#   managed_pages * (watermark_scale_new / 10000)
+#
+# after simplifying and substituting extra_share formula becomes:
+#
+# (2) watermark_scale_new = watermark_scale + extra_free_pages / vm_total_pages * 10000
+#
+# B. managed_pages * (watermark_scale / 10000) < min / 4
+# The formula (1) becomes:
+#
+# min / 4 + extra_share = max(min / 4, managed_pages * (watermark_scale_new / 10000))
+#
+# after calculating watermark_scale_new, if (managed_pages * (watermark_scale_new / 10000))
+# is still smaller than min / 4 then we can't compensate extra_share with
+# watermark_scale anyway. Therefore calculation becomes:
+#
+# watermark_scale_new = (min / 4 + extra_share) / managed_pages * 10000
+#
+# after simplifying and substituting extra_share formula becomes:
+#
+# (3) watermark_scale_new = (min / 4) * 10000 / managed_pages + extra_free_pages / vm_total_pages * 10000
+#
+# After defining watermark_delta = extra_free_pages / vm_total_pages * 10000:
+#
+# if (managed_pages * (watermark_scale / 10000) > min / 4)
+#     watermark_scale_new = watermark_scale + watermark_delta
+# else
+#     watermark_scale_new = (min / 4) * 10000 / managed_pages + watermark_delta
+#
+
+if [ "$#" -ne 1 ]
+then
+    echo "Usage: $0 <extra_free_kbytes value>"
+    exit
+fi
+
+extra_free_kbytes=$1
+
+# if extra_free_kbytes knob exists, use it and exit
+if [ -e /proc/sys/vm/extra_free_kbytes ]
+then
+    echo $extra_free_kbytes > /proc/sys/vm/extra_free_kbytes
+    exit
+fi
+
+watermark_scale=`cat /proc/sys/vm/watermark_scale_factor`
+
+# convert extra_free_kbytes to pages
+page_size=$(getconf PAGESIZE)
+page_size_kb=$((page_size/1024))
+extra_free_pg=$((extra_free_kbytes/page_size_kb))
+
+managed=($(grep managed /proc/zoneinfo | awk '{print $2}'))
+length=${#managed[@]}
+min=($(grep "min" /proc/zoneinfo | awk '{print $2}'))
+
+# calculate vm_total_pages.
+# WARNING: if the final low watermark differs from the original, the source of
+# the error is likely vm_total_pages which is impossible to get exact from the
+# userspace. Grep for "Total pages" in the kernel logs to see the actual
+# vm_total_pages and plug it in the calculation to confirm the source of the
+# error. Error caused by this inaccuracy is normally within 1% range.
+vm_total_pages=0
+i=0
+while [ $i -lt $length ]
+do
+    vm_total_pages=$((vm_total_pages + managed[i]))
+    i=$((i+1))
+done
+
+# calculate watermark_scale_new for each zone and choose the max
+max_watermark_scale=0
+i=0
+while [ $i -lt $length ]
+do
+    # skip unmanaged zones
+    if [ ${managed[i]} -eq 0 ]
+    then
+        i=$((i+1))
+        continue
+    fi
+
+    base_margin=$((min[i] / 4))
+    calc_margin=$(echo "${managed[i]} * $watermark_scale / 10000" | bc)
+    # round the value by adding 0.5 and truncating the decimal part
+    watermark_delta=$(echo "x=($extra_free_pg / ($vm_total_pages / 10000) + 0.5); scale = 0; x/1" | bc -l)
+    if [ $calc_margin -gt $base_margin ]
+    then
+        watermark_scale_new=$(echo "$watermark_scale + $watermark_delta" | bc)
+    else
+        watermark_scale_new=$(echo "$base_margin / (${managed[i]} / 10000) + $watermark_delta" | bc)
+    fi
+
+    if [ $max_watermark_scale -lt $watermark_scale_new ]
+    then
+        max_watermark_scale=$watermark_scale_new
+    fi
+
+    i=$((i+1))
+done
+
+echo $max_watermark_scale > /proc/sys/vm/watermark_scale_factor
diff --git a/init/host_builtin_map.py b/init/host_builtin_map.py
index 6afcb17..41c86ac 100755
--- a/init/host_builtin_map.py
+++ b/init/host_builtin_map.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """Generates the builtins map to be used by host_init_verifier.
 
 It copies the builtin function map from builtins.cpp, then replaces do_xxx() functions with the
@@ -39,8 +39,7 @@
   match = DO_REGEX.match(line)
   if match:
     if match.group(1) in check_functions:
-      print line.replace('do_', 'check_'),
+      line = line.replace('do_', 'check_')
     else:
-      print FUNCTION_REGEX.sub('check_stub', line),
-  else:
-    print line,
+      line = FUNCTION_REGEX.sub('check_stub', line)
+  print(line, end=' ')
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 593913b..1681627 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -1037,6 +1037,20 @@
                         return;
                     }
                 }
+            } else if (reboot_target == "quiescent") {
+                bootloader_message boot = {};
+                if (std::string err; !read_bootloader_message(&boot, &err)) {
+                    LOG(ERROR) << "Failed to read bootloader message: " << err;
+                }
+                // Update the boot command field if it's empty, and preserve
+                // the other arguments in the bootloader message.
+                if (!CommandIsPresent(&boot)) {
+                    strlcpy(boot.command, "boot-quiescent", sizeof(boot.command));
+                    if (std::string err; !write_bootloader_message(boot, &err)) {
+                        LOG(ERROR) << "Failed to set bootloader message: " << err;
+                        return;
+                    }
+                }
             } else if (reboot_target == "sideload" || reboot_target == "sideload-auto-reboot" ||
                        reboot_target == "fastboot") {
                 std::string arg = reboot_target == "sideload-auto-reboot" ? "sideload_auto_reboot"
diff --git a/libcutils/TEST_MAPPING b/libcutils/TEST_MAPPING
new file mode 100644
index 0000000..e512ab7
--- /dev/null
+++ b/libcutils/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "libcutils_test"
+    }
+  ]
+}
diff --git a/libmodprobe/TEST_MAPPING b/libmodprobe/TEST_MAPPING
new file mode 100644
index 0000000..526b1e4
--- /dev/null
+++ b/libmodprobe/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "libmodprobe_tests"
+    }
+  ]
+}
diff --git a/libpackagelistparser/TEST_MAPPING b/libpackagelistparser/TEST_MAPPING
new file mode 100644
index 0000000..51773f9
--- /dev/null
+++ b/libpackagelistparser/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "libpackagelistparser_test"
+    }
+  ]
+}
diff --git a/libsparse/Android.bp b/libsparse/Android.bp
index 0b4b640..3f9aeb2 100644
--- a/libsparse/Android.bp
+++ b/libsparse/Android.bp
@@ -85,11 +85,11 @@
     srcs: ["simg_dump.py"],
     version: {
         py2: {
-            embedded_launcher: true,
-            enabled: true,
+            enabled: false,
         },
         py3: {
-            enabled: false,
+            embedded_launcher: true,
+            enabled: true,
         },
     },
 }
diff --git a/libsparse/simg_dump.py b/libsparse/simg_dump.py
index 82a03ad..b0b3b22 100755
--- a/libsparse/simg_dump.py
+++ b/libsparse/simg_dump.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python3
 
 # Copyright (C) 2012 The Android Open Source Project
 #
@@ -14,7 +14,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import print_function
 import csv
 import getopt
 import hashlib
@@ -47,7 +46,7 @@
     opts, args = getopt.getopt(sys.argv[1:],
                                "vsc:",
                                ["verbose", "showhash", "csvfile"])
-  except getopt.GetoptError, e:
+  except getopt.GetoptError as e:
     print(e)
     usage(me)
   for o, a in opts:
diff --git a/libutils/TEST_MAPPING b/libutils/TEST_MAPPING
new file mode 100644
index 0000000..c8ef45c
--- /dev/null
+++ b/libutils/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "libutils_test"
+    }
+  ]
+}
diff --git a/property_service/TEST_MAPPING b/property_service/TEST_MAPPING
new file mode 100644
index 0000000..fcdc86a
--- /dev/null
+++ b/property_service/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "propertyinfoserializer_tests"
+    }
+  ]
+}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index ab0aff5..9371617 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -1138,7 +1138,7 @@
 # and chown/chmod does not work for /proc/sys/ entries.
 # So proxy writes through init.
 on property:sys.sysctl.extra_free_kbytes=*
-    write /proc/sys/vm/extra_free_kbytes ${sys.sysctl.extra_free_kbytes}
+    exec -- /system/bin/extra_free_kbytes.sh ${sys.sysctl.extra_free_kbytes}
 
 # Allow users to drop caches
 on property:perf.drop_caches=3
diff --git a/toolbox/generate-input.h-labels.py b/toolbox/generate-input.h-labels.py
index c0e9fce..20db638 100755
--- a/toolbox/generate-input.h-labels.py
+++ b/toolbox/generate-input.h-labels.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright (C) 2015 The Android Open Source Project
 #
@@ -16,7 +16,7 @@
 #
 # pylint: disable=bad-indentation,bad-continuation
 
-from __future__ import print_function
+
 import os
 import re
 import sys
diff --git a/trusty/keymaster/ipc/trusty_keymaster_ipc.cpp b/trusty/keymaster/ipc/trusty_keymaster_ipc.cpp
index 0956fe6..2d44009 100644
--- a/trusty/keymaster/ipc/trusty_keymaster_ipc.cpp
+++ b/trusty/keymaster/ipc/trusty_keymaster_ipc.cpp
@@ -25,6 +25,8 @@
 #include <unistd.h>
 
 #include <algorithm>
+#include <variant>
+#include <vector>
 
 #include <log/log.h>
 #include <trusty/tipc.h>
@@ -46,8 +48,27 @@
     return 0;
 }
 
-int trusty_keymaster_call(uint32_t cmd, void* in, uint32_t in_size, uint8_t* out,
-                          uint32_t* out_size) {
+class VectorEraser {
+  public:
+    VectorEraser(std::vector<uint8_t>* v) : _v(v) {}
+    ~VectorEraser() {
+        if (_v) {
+            std::fill(const_cast<volatile uint8_t*>(_v->data()),
+                      const_cast<volatile uint8_t*>(_v->data() + _v->size()), 0);
+        }
+    }
+    void disarm() { _v = nullptr; }
+    VectorEraser(const VectorEraser&) = delete;
+    VectorEraser& operator=(const VectorEraser&) = delete;
+    VectorEraser(VectorEraser&& other) = delete;
+    VectorEraser& operator=(VectorEraser&&) = delete;
+
+  private:
+    std::vector<uint8_t>* _v;
+};
+
+std::variant<int, std::vector<uint8_t>> trusty_keymaster_call_2(uint32_t cmd, void* in,
+                                                                uint32_t in_size) {
     if (handle_ < 0) {
         ALOGE("not connected\n");
         return -EINVAL;
@@ -70,15 +91,38 @@
         ALOGE("failed to send cmd (%d) to %s: %s\n", cmd, KEYMASTER_PORT, strerror(errno));
         return -errno;
     }
-    size_t out_max_size = *out_size;
-    *out_size = 0;
+
+    std::vector<uint8_t> out(TRUSTY_KEYMASTER_RECV_BUF_SIZE);
+    VectorEraser out_eraser(&out);
+    uint8_t* write_pos = out.data();
+    uint8_t* out_end = out.data() + out.size();
+
     struct iovec iov[2];
     struct keymaster_message header;
     iov[0] = {.iov_base = &header, .iov_len = sizeof(struct keymaster_message)};
     while (true) {
-        iov[1] = {.iov_base = out + *out_size,
-                  .iov_len = std::min<uint32_t>(KEYMASTER_MAX_BUFFER_LENGTH,
-                                                out_max_size - *out_size)};
+        if (out_end - write_pos < KEYMASTER_MAX_BUFFER_LENGTH) {
+            // In stead of using std::vector.resize(), allocate a new one to have chance
+            // at zeroing the old buffer.
+            std::vector<uint8_t> new_out(out.size() + KEYMASTER_MAX_BUFFER_LENGTH);
+            // After the swap below this erases the old out buffer.
+            VectorEraser new_out_eraser(&new_out);
+            std::copy(out.data(), write_pos, new_out.begin());
+
+            auto write_offset = write_pos - out.data();
+
+            std::swap(new_out, out);
+
+            write_pos = out.data() + write_offset;
+            out_end = out.data() + out.size();
+        }
+        size_t buffer_size = 0;
+        if (__builtin_sub_overflow(reinterpret_cast<uintptr_t>(out_end),
+                                   reinterpret_cast<uintptr_t>(write_pos), &buffer_size)) {
+            return -EOVERFLOW;
+        }
+        iov[1] = {.iov_base = write_pos, .iov_len = buffer_size};
+
         rc = readv(handle_, iov, 2);
         if (rc < 0) {
             ALOGE("failed to retrieve response for cmd (%d) to %s: %s\n", cmd, KEYMASTER_PORT,
@@ -95,13 +139,36 @@
             ALOGE("invalid command (%d)", header.cmd);
             return -EINVAL;
         }
-        *out_size += ((size_t)rc - sizeof(struct keymaster_message));
+        write_pos += ((size_t)rc - sizeof(struct keymaster_message));
         if (header.cmd & KEYMASTER_STOP_BIT) {
             break;
         }
     }
 
-    return rc;
+    out.resize(write_pos - out.data());
+    out_eraser.disarm();
+    return out;
+}
+
+int trusty_keymaster_call(uint32_t cmd, void* in, uint32_t in_size, uint8_t* out,
+                          uint32_t* out_size) {
+    auto result = trusty_keymaster_call_2(cmd, in, in_size);
+    if (auto out_buffer = std::get_if<std::vector<uint8_t>>(&result)) {
+        if (out_buffer->size() <= *out_size) {
+            std::copy(out_buffer->begin(), out_buffer->end(), out);
+            std::fill(const_cast<volatile uint8_t*>(&*out_buffer->begin()),
+                      const_cast<volatile uint8_t*>(&*out_buffer->end()), 0);
+
+            *out_size = out_buffer->size();
+            return 0;
+        } else {
+            ALOGE("Message was to large (%zu) for the provided buffer (%u)", out_buffer->size(),
+                  *out_size);
+            return -EMSGSIZE;
+        }
+    } else {
+        return std::get<int>(result);
+    }
 }
 
 void trusty_keymaster_disconnect() {
@@ -155,28 +222,27 @@
     req.Serialize(send_buf, send_buf + req_size);
 
     // Send it
-    uint8_t recv_buf[TRUSTY_KEYMASTER_RECV_BUF_SIZE];
-    keymaster::Eraser recv_buf_eraser(recv_buf, TRUSTY_KEYMASTER_RECV_BUF_SIZE);
-    uint32_t rsp_size = TRUSTY_KEYMASTER_RECV_BUF_SIZE;
-    int rc = trusty_keymaster_call(command, send_buf, req_size, recv_buf, &rsp_size);
-    if (rc < 0) {
+    auto response = trusty_keymaster_call_2(command, send_buf, req_size);
+    if (auto response_buffer = std::get_if<std::vector<uint8_t>>(&response)) {
+        keymaster::Eraser response_buffer_erasor(response_buffer->data(), response_buffer->size());
+        ALOGV("Received %zu byte response\n", response_buffer->size());
+
+        const uint8_t* p = response_buffer->data();
+        if (!rsp->Deserialize(&p, p + response_buffer->size())) {
+            ALOGE("Error deserializing response of size %zu\n", response_buffer->size());
+            return KM_ERROR_UNKNOWN_ERROR;
+        } else if (rsp->error != KM_ERROR_OK) {
+            ALOGE("Response of size %zu contained error code %d\n", response_buffer->size(),
+                  (int)rsp->error);
+        }
+        return rsp->error;
+    } else {
+        auto rc = std::get<int>(response);
         // Reset the connection on tipc error
         trusty_keymaster_disconnect();
         trusty_keymaster_connect();
         ALOGE("tipc error: %d\n", rc);
         // TODO(swillden): Distinguish permanent from transient errors and set error_ appropriately.
         return translate_error(rc);
-    } else {
-        ALOGV("Received %d byte response\n", rsp_size);
     }
-
-    const uint8_t* p = recv_buf;
-    if (!rsp->Deserialize(&p, p + rsp_size)) {
-        ALOGE("Error deserializing response of size %d\n", (int)rsp_size);
-        return KM_ERROR_UNKNOWN_ERROR;
-    } else if (rsp->error != KM_ERROR_OK) {
-        ALOGE("Response of size %d contained error code %d\n", (int)rsp_size, (int)rsp->error);
-        return rsp->error;
-    }
-    return rsp->error;
 }