Merge "adbd: wait for FUNCTIONFS_BIND for up to a second, then retry."
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index d26f2d5..ba6b9eb 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1602,6 +1602,14 @@
     return true;
 }
 
+std::string fs_mgr_get_verity_device_name(const FstabEntry& entry) {
+    if (entry.mount_point == "/") {
+        // In AVB, the dm device name is vroot instead of system.
+        return entry.fs_mgr_flags.avb ? "vroot" : "system";
+    }
+    return Basename(entry.mount_point);
+}
+
 bool fs_mgr_is_verity_enabled(const FstabEntry& entry) {
     if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
         return false;
@@ -1609,14 +1617,7 @@
 
     DeviceMapper& dm = DeviceMapper::Instance();
 
-    std::string mount_point;
-    if (entry.mount_point == "/") {
-        // In AVB, the dm device name is vroot instead of system.
-        mount_point = entry.fs_mgr_flags.avb ? "vroot" : "system";
-    } else {
-        mount_point = Basename(entry.mount_point);
-    }
-
+    std::string mount_point = fs_mgr_get_verity_device_name(entry);
     if (dm.GetState(mount_point) == DmDeviceState::INVALID) {
         return false;
     }
@@ -1639,6 +1640,27 @@
     return false;
 }
 
+bool fs_mgr_verity_is_check_at_most_once(const android::fs_mgr::FstabEntry& entry) {
+    if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
+        return false;
+    }
+
+    DeviceMapper& dm = DeviceMapper::Instance();
+    std::string device = fs_mgr_get_verity_device_name(entry);
+
+    std::vector<DeviceMapper::TargetInfo> table;
+    if (dm.GetState(device) == DmDeviceState::INVALID || !dm.GetTableInfo(device, &table)) {
+        return false;
+    }
+    for (const auto& target : table) {
+        if (strcmp(target.spec.target_type, "verity") == 0 &&
+            target.data.find("check_at_most_once") != std::string::npos) {
+            return true;
+        }
+    }
+    return false;
+}
+
 std::string fs_mgr_get_super_partition_name(int slot) {
     // Devices upgrading to dynamic partitions are allowed to specify a super
     // partition name, assumed to be A/B (non-A/B retrofit is not supported).
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index a3bb852..8abe609 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -77,6 +77,10 @@
 bool fs_mgr_swapon_all(const android::fs_mgr::Fstab& fstab);
 bool fs_mgr_update_logical_partition(android::fs_mgr::FstabEntry* entry);
 
+// Returns true if the given fstab entry has verity enabled, *and* the verity
+// device is in "check_at_most_once" mode.
+bool fs_mgr_verity_is_check_at_most_once(const android::fs_mgr::FstabEntry& entry);
+
 int fs_mgr_do_format(const android::fs_mgr::FstabEntry& entry, bool reserve_footer);
 
 #define FS_MGR_SETUP_VERITY_SKIPPED  (-3)
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 63661f0..9309aad 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -316,7 +316,7 @@
 
     DeviceMapper& dm = DeviceMapper::Instance();
     std::vector<DeviceMapper::TargetInfo> table;
-    if (!dm.GetTableStatus(argv[0], &table)) {
+    if (!dm.GetTableInfo(argv[0], &table)) {
         std::cerr << "Could not query table status of device \"" << argv[0] << "\"." << std::endl;
         return -EINVAL;
     }
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 5fe58ac..bde5fbe 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -36,6 +36,7 @@
 #include <linux/netlink.h>
 #include <sys/socket.h>
 
+#include <cutils/android_get_control_file.h>
 #include <cutils/klog.h>
 #include <cutils/misc.h>
 #include <cutils/properties.h>
@@ -206,10 +207,9 @@
 #define MAX_KLOG_WRITE_BUF_SZ 256
 
 static void dump_last_kmsg(void) {
-    char* buf;
+    std::string buf;
     char* ptr;
-    unsigned sz = 0;
-    int len;
+    size_t len;
 
     LOGW("\n");
     LOGW("*************** LAST KMSG ***************\n");
@@ -221,21 +221,25 @@
         "/proc/last_kmsg",
         // clang-format on
     };
-    for (size_t i = 0; i < arraysize(kmsg); ++i) {
-        buf = (char*)load_file(kmsg[i], &sz);
-        if (buf && sz) break;
+    for (size_t i = 0; i < arraysize(kmsg) && buf.empty(); ++i) {
+        auto fd = android_get_control_file(kmsg[i]);
+        if (fd >= 0) {
+            android::base::ReadFdToString(fd, &buf);
+        } else {
+            android::base::ReadFileToString(kmsg[i], &buf);
+        }
     }
 
-    if (!buf || !sz) {
+    if (buf.empty()) {
         LOGW("last_kmsg not found. Cold reset?\n");
         goto out;
     }
 
-    len = min(sz, LAST_KMSG_MAX_SZ);
-    ptr = buf + (sz - len);
+    len = min(buf.size(), LAST_KMSG_MAX_SZ);
+    ptr = &buf[buf.size() - len];
 
     while (len > 0) {
-        int cnt = min(len, MAX_KLOG_WRITE_BUF_SZ);
+        size_t cnt = min(len, MAX_KLOG_WRITE_BUF_SZ);
         char yoink;
         char* nl;
 
@@ -251,8 +255,6 @@
         ptr += cnt;
     }
 
-    free(buf);
-
 out:
     LOGW("\n");
     LOGW("************* END LAST KMSG *************\n");
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 4b0f05d..d458924 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -78,6 +78,7 @@
     ListenerAction HandleBlockDevice(const std::string& name, const Uevent&);
     bool InitRequiredDevices();
     bool InitMappedDevice(const std::string& verity_device);
+    bool InitDeviceMapper();
     bool CreateLogicalPartitions();
     bool MountPartition(const Fstab::iterator& begin, bool erase_used_fstab_entry,
                         Fstab::iterator* end = nullptr);
@@ -97,6 +98,7 @@
     virtual bool SetUpDmVerity(FstabEntry* fstab_entry) = 0;
 
     bool need_dm_verity_;
+    bool gsi_not_on_userdata_ = false;
 
     Fstab fstab_;
     std::string lp_metadata_partition_;
@@ -267,8 +269,6 @@
     }
 
     required_devices_partition_names_.emplace(super_partition_name_);
-    // When booting from live GSI images, userdata is the super device.
-    required_devices_partition_names_.emplace("userdata");
     return true;
 }
 
@@ -281,25 +281,7 @@
     }
 
     if (IsDmLinearEnabled() || need_dm_verity_) {
-        const std::string dm_path = "/devices/virtual/misc/device-mapper";
-        bool found = false;
-        auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) {
-            if (uevent.path == dm_path) {
-                device_handler_->HandleUevent(uevent);
-                found = true;
-                return ListenerAction::kStop;
-            }
-            return ListenerAction::kContinue;
-        };
-        uevent_listener_.RegenerateUeventsForPath("/sys" + dm_path, dm_callback);
-        if (!found) {
-            LOG(INFO) << "device-mapper device not found in /sys, waiting for its uevent";
-            Timer t;
-            uevent_listener_.Poll(dm_callback, 10s);
-            LOG(INFO) << "Wait for device-mapper returned after " << t;
-        }
-        if (!found) {
-            LOG(ERROR) << "device-mapper device not found after polling timeout";
+        if (!InitDeviceMapper()) {
             return false;
         }
     }
@@ -327,11 +309,36 @@
     return true;
 }
 
+bool FirstStageMount::InitDeviceMapper() {
+    const std::string dm_path = "/devices/virtual/misc/device-mapper";
+    bool found = false;
+    auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) {
+        if (uevent.path == dm_path) {
+            device_handler_->HandleUevent(uevent);
+            found = true;
+            return ListenerAction::kStop;
+        }
+        return ListenerAction::kContinue;
+    };
+    uevent_listener_.RegenerateUeventsForPath("/sys" + dm_path, dm_callback);
+    if (!found) {
+        LOG(INFO) << "device-mapper device not found in /sys, waiting for its uevent";
+        Timer t;
+        uevent_listener_.Poll(dm_callback, 10s);
+        LOG(INFO) << "Wait for device-mapper returned after " << t;
+    }
+    if (!found) {
+        LOG(ERROR) << "device-mapper device not found after polling timeout";
+        return false;
+    }
+    return true;
+}
+
 bool FirstStageMount::InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata) {
     auto partition_names = android::fs_mgr::GetBlockDevicePartitionNames(metadata);
     for (const auto& partition_name : partition_names) {
-        const auto super_device = android::fs_mgr::GetMetadataSuperBlockDevice(metadata);
-        if (partition_name == android::fs_mgr::GetBlockDevicePartitionName(*super_device)) {
+        // The super partition was found in the earlier pass.
+        if (partition_name == super_partition_name_) {
             continue;
         }
         required_devices_partition_names_.emplace(partition_name);
@@ -499,6 +506,10 @@
     if (system_partition == fstab_.end()) return true;
 
     if (MountPartition(system_partition, false)) {
+        if (gsi_not_on_userdata_ && fs_mgr_verity_is_check_at_most_once(*system_partition)) {
+            LOG(ERROR) << "check_most_at_once forbidden on external media";
+            return false;
+        }
         SwitchRoot("/system");
     } else {
         PLOG(ERROR) << "Failed to mount /system";
@@ -612,7 +623,29 @@
         return;
     }
 
-    if (!android::fs_mgr::CreateLogicalPartitions(*metadata.get(), "/dev/block/by-name/userdata")) {
+    if (!InitDmLinearBackingDevices(*metadata.get())) {
+        return;
+    }
+
+    // Device-mapper might not be ready if the device doesn't use DAP or verity
+    // (for example, hikey).
+    if (access("/dev/device-mapper", F_OK) && !InitDeviceMapper()) {
+        return;
+    }
+
+    // Find the name of the super partition for the GSI. It will either be
+    // "userdata", or a block device such as an sdcard. There are no by-name
+    // partitions other than userdata that we support installing GSIs to.
+    auto super = GetMetadataSuperBlockDevice(*metadata.get());
+    std::string super_name = android::fs_mgr::GetBlockDevicePartitionName(*super);
+    std::string super_path;
+    if (super_name == "userdata") {
+        super_path = "/dev/block/by-name/" + super_name;
+    } else {
+        super_path = "/dev/block/" + super_name;
+    }
+
+    if (!android::fs_mgr::CreateLogicalPartitions(*metadata.get(), super_path)) {
         LOG(ERROR) << "GSI partition layout could not be instantiated";
         return;
     }
@@ -630,6 +663,7 @@
         fstab_.erase(system_partition);
     }
     fstab_.emplace_back(BuildGsiSystemFstabEntry());
+    gsi_not_on_userdata_ = (super_name != "userdata");
 }
 
 bool FirstStageMountVBootV1::GetDmVerityDevices() {
diff --git a/init/init.cpp b/init/init.cpp
index a5f4549..cdec41c 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -357,7 +357,7 @@
 static Result<Success> SetupCgroupsAction(const BuiltinArguments&) {
     // Have to create <CGROUPS_RC_DIR> using make_dir function
     // for appropriate sepolicy to be set for it
-    make_dir(CGROUPS_RC_DIR, 0711);
+    make_dir(android::base::Dirname(CGROUPS_RC_PATH), 0711);
     if (!CgroupSetupCgroups()) {
         return ErrnoError() << "Failed to setup cgroups";
     }
diff --git a/init/mount_handler.cpp b/init/mount_handler.cpp
index 12dfc6d..c8f0e76 100644
--- a/init/mount_handler.cpp
+++ b/init/mount_handler.cpp
@@ -27,6 +27,7 @@
 #include <algorithm>
 #include <string>
 #include <utility>
+#include <vector>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
@@ -34,6 +35,7 @@
 #include <android-base/strings.h>
 #include <fs_mgr.h>
 #include <fstab/fstab.h>
+#include <libdm/dm.h>
 
 #include "epoll.h"
 #include "property_service.h"
@@ -47,8 +49,13 @@
     auto fields = android::base::Split(line, " ");
     while (fields.size() < 3) fields.emplace_back("");
     if (fields[0] == "/dev/root") {
-        if (android::fs_mgr::Fstab fstab; android::fs_mgr::ReadDefaultFstab(&fstab)) {
-            if (auto entry = GetEntryForMountPoint(&fstab, "/")) {
+        auto& dm = dm::DeviceMapper::Instance();
+        std::string path;
+        if (dm.GetDmDevicePathByName("system", &path) || dm.GetDmDevicePathByName("vroot", &path)) {
+            fields[0] = path;
+        } else if (android::fs_mgr::Fstab fstab; android::fs_mgr::ReadDefaultFstab(&fstab)) {
+            auto entry = GetEntryForMountPoint(&fstab, "/");
+            if (entry || (entry = GetEntryForMountPoint(&fstab, "/system"))) {
                 fields[0] = entry->blk_device;
             }
         }
@@ -77,14 +84,19 @@
         struct stat sb;
         if (stat(queue.c_str(), &sb) || !S_ISDIR(sb.st_mode)) value = "";
         if (stat(entry.mount_point.c_str(), &sb) || !S_ISDIR(sb.st_mode)) value = "";
-        // Skip the noise associated with APEX until there is a need
+        // Clear the noise associated with loopback and APEX.
         if (android::base::StartsWith(value, "loop")) value = "";
+        if (android::base::StartsWith(entry.mount_point, "/apex/")) value = "";
     }
-    std::string property =
-            "dev.mnt.blk" + ((entry.mount_point == "/") ? "/root" : entry.mount_point);
-    std::replace(property.begin(), property.end(), '/', '.');
-    if (value.empty() && android::base::GetProperty(property, "").empty()) return;
-    property_set(property, value);
+    auto mount_prop = entry.mount_point;
+    if (mount_prop == "/") mount_prop = "/root";
+    std::replace(mount_prop.begin(), mount_prop.end(), '/', '.');
+    mount_prop = "dev.mnt.blk" + mount_prop;
+    // Set property even if its value does not change to trigger 'on property:'
+    // handling, except for clearing non-existent or already clear property.
+    // Goal is reduction of empty properties and associated triggers.
+    if (value.empty() && android::base::GetProperty(mount_prop, "").empty()) return;
+    property_set(mount_prop, value);
 }
 
 }  // namespace
@@ -114,25 +126,27 @@
 
 void MountHandler::MountHandlerFunction() {
     rewind(fp_.get());
+    std::vector<MountHandlerEntry> touched;
+    auto untouched = mounts_;
     char* buf = nullptr;
     size_t len = 0;
-    auto untouched = mounts_;
     while (getline(&buf, &len, fp_.get()) != -1) {
-        auto entry = ParseMount(std::string(buf, len));
+        auto entry = ParseMount(std::string(buf));
         auto match = untouched.find(entry);
         if (match == untouched.end()) {
-            SetMountProperty(entry, true);
-            mounts_.emplace(std::move(entry));
+            touched.emplace_back(std::move(entry));
         } else {
             untouched.erase(match);
         }
     }
     free(buf);
     for (auto entry : untouched) {
-        auto match = mounts_.find(entry);
-        if (match == mounts_.end()) continue;
-        mounts_.erase(match);
         SetMountProperty(entry, false);
+        mounts_.erase(entry);
+    }
+    for (auto entry : touched) {
+        SetMountProperty(entry, true);
+        mounts_.emplace(std::move(entry));
     }
 }
 
diff --git a/libkeyutils/mini_keyctl.cpp b/libkeyutils/mini_keyctl.cpp
index e09c864..fe89e62 100644
--- a/libkeyutils/mini_keyctl.cpp
+++ b/libkeyutils/mini_keyctl.cpp
@@ -30,7 +30,6 @@
   fprintf(stderr, "usage: mini-keyctl <action> [args,]\n");
   fprintf(stderr, "       mini-keyctl add <type> <desc> <data> <keyring>\n");
   fprintf(stderr, "       mini-keyctl padd <type> <desc> <keyring>\n");
-  fprintf(stderr, "       mini-keyctl dadd <type> <desc_prefix> <cert_dir> <keyring>\n");
   fprintf(stderr, "       mini-keyctl unlink <key> <keyring>\n");
   fprintf(stderr, "       mini-keyctl restrict_keyring <keyring>\n");
   fprintf(stderr, "       mini-keyctl security <key>\n");
@@ -56,14 +55,6 @@
     std::string data = argv[4];
     std::string keyring = argv[5];
     return Add(type, desc, data, keyring);
-  } else if (action == "dadd") {
-    if (argc != 6) Usage(1);
-    std::string type = argv[2];
-    // The key description contains desc_prefix and an index.
-    std::string desc_prefix = argv[3];
-    std::string cert_dir = argv[4];
-    std::string keyring = argv[5];
-    return AddCertsFromDir(type, desc_prefix, cert_dir, keyring);
   } else if (action == "padd") {
     if (argc != 5) Usage(1);
     std::string type = argv[2];
diff --git a/libkeyutils/mini_keyctl_utils.cpp b/libkeyutils/mini_keyctl_utils.cpp
index 9fe2dfe..56afea4 100644
--- a/libkeyutils/mini_keyctl_utils.cpp
+++ b/libkeyutils/mini_keyctl_utils.cpp
@@ -86,53 +86,6 @@
   return false;
 }
 
-int AddCertsFromDir(const std::string& type, const std::string& desc_prefix,
-                    const std::string& cert_dir, const std::string& keyring) {
-  key_serial_t keyring_id;
-  if (!GetKeyringId(keyring, &keyring_id)) {
-    LOG(ERROR) << "Can not find keyring id";
-    return 1;
-  }
-
-  std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(cert_dir.c_str()), closedir);
-  if (!dir) {
-    PLOG(WARNING) << "Failed to open directory " << cert_dir;
-    return 1;
-  }
-  int keys_added = 0;
-  struct dirent* dp;
-  while ((dp = readdir(dir.get())) != NULL) {
-    if (dp->d_type != DT_REG) {
-      continue;
-    }
-    std::string cert_path = cert_dir + "/" + dp->d_name;
-    std::string cert_buf;
-    if (!android::base::ReadFileToString(cert_path, &cert_buf, false /* follow_symlinks */)) {
-      LOG(ERROR) << "Failed to read " << cert_path;
-      continue;
-    }
-
-    if (cert_buf.size() > kMaxCertSize) {
-      LOG(ERROR) << "Certficate size too large: " << cert_path;
-      continue;
-    }
-
-    // Add key to keyring.
-    int key_desc_index = keys_added;
-    std::string key_desc = desc_prefix + std::to_string(key_desc_index);
-    key_serial_t key =
-        add_key(type.c_str(), key_desc.c_str(), &cert_buf[0], cert_buf.size(), keyring_id);
-    if (key < 0) {
-      PLOG(ERROR) << "Failed to add key to keyring: " << cert_path;
-      continue;
-    }
-    LOG(INFO) << "Key " << cert_path << " added to " << keyring << " with key id 0x" << std::hex
-              << key;
-    keys_added++;
-  }
-  return 0;
-}
-
 int Unlink(key_serial_t key, const std::string& keyring) {
   key_serial_t keyring_id;
   if (!GetKeyringId(keyring, &keyring_id)) {
diff --git a/libkeyutils/mini_keyctl_utils.h b/libkeyutils/mini_keyctl_utils.h
index 804a357..3616831 100644
--- a/libkeyutils/mini_keyctl_utils.h
+++ b/libkeyutils/mini_keyctl_utils.h
@@ -18,11 +18,6 @@
 
 #include <string>
 
-// Add all files in a directory as certificates to a keyring. |keyring| could be the keyring
-// description or keyring id in hex.
-int AddCertsFromDir(const std::string& type, const std::string& desc_prefix,
-                    const std::string& cert_dir, const std::string& keyring);
-
 // Add key to a keyring. Returns non-zero if error happens.
 int Add(const std::string& type, const std::string& desc, const std::string& data,
         const std::string& keyring);
diff --git a/libprocessgroup/Android.bp b/libprocessgroup/Android.bp
index d97f09f..07cbce9 100644
--- a/libprocessgroup/Android.bp
+++ b/libprocessgroup/Android.bp
@@ -45,5 +45,6 @@
     cflags: [
         "-Wall",
         "-Werror",
+        "-Wexit-time-destructors",
     ],
 }
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index b3b497f..1e66fa4 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -227,13 +227,16 @@
 
 #endif
 
+// WARNING: This function should be called only from SetupCgroups and only once.
+// It intentionally leaks an FD, so additional invocation will result in additional leak.
 static bool WriteRcFile(const std::map<std::string, CgroupDescriptor>& descriptors) {
-    std::string cgroup_rc_path = StringPrintf("%s/%s", CGROUPS_RC_DIR, CgroupMap::CGROUPS_RC_FILE);
-    unique_fd fd(TEMP_FAILURE_RETRY(open(cgroup_rc_path.c_str(),
-                                         O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC,
-                                         S_IRUSR | S_IRGRP | S_IROTH)));
+    // WARNING: We are intentionally leaking the FD to keep the file open forever.
+    // Let init keep the FD open to prevent file mappings from becoming invalid in
+    // case the file gets deleted somehow.
+    int fd = TEMP_FAILURE_RETRY(open(CGROUPS_RC_PATH, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC,
+                                     S_IRUSR | S_IRGRP | S_IROTH));
     if (fd < 0) {
-        PLOG(ERROR) << "open() failed for " << cgroup_rc_path;
+        PLOG(ERROR) << "open() failed for " << CGROUPS_RC_PATH;
         return false;
     }
 
@@ -242,14 +245,14 @@
     fl.controller_count_ = descriptors.size();
     int ret = TEMP_FAILURE_RETRY(write(fd, &fl, sizeof(fl)));
     if (ret < 0) {
-        PLOG(ERROR) << "write() failed for " << cgroup_rc_path;
+        PLOG(ERROR) << "write() failed for " << CGROUPS_RC_PATH;
         return false;
     }
 
     for (const auto& [name, descriptor] : descriptors) {
         ret = TEMP_FAILURE_RETRY(write(fd, descriptor.controller(), sizeof(CgroupController)));
         if (ret < 0) {
-            PLOG(ERROR) << "write() failed for " << cgroup_rc_path;
+            PLOG(ERROR) << "write() failed for " << CGROUPS_RC_PATH;
             return false;
         }
     }
@@ -350,38 +353,37 @@
         return true;
     }
 
-    std::string cgroup_rc_path = StringPrintf("%s/%s", CGROUPS_RC_DIR, CGROUPS_RC_FILE);
-    unique_fd fd(TEMP_FAILURE_RETRY(open(cgroup_rc_path.c_str(), O_RDONLY | O_CLOEXEC)));
+    unique_fd fd(TEMP_FAILURE_RETRY(open(CGROUPS_RC_PATH, O_RDONLY | O_CLOEXEC)));
     if (fd < 0) {
-        PLOG(ERROR) << "open() failed for " << cgroup_rc_path;
+        PLOG(ERROR) << "open() failed for " << CGROUPS_RC_PATH;
         return false;
     }
 
     if (fstat(fd, &sb) < 0) {
-        PLOG(ERROR) << "fstat() failed for " << cgroup_rc_path;
+        PLOG(ERROR) << "fstat() failed for " << CGROUPS_RC_PATH;
         return false;
     }
 
     size_t file_size = sb.st_size;
     if (file_size < sizeof(CgroupFile)) {
-        LOG(ERROR) << "Invalid file format " << cgroup_rc_path;
+        LOG(ERROR) << "Invalid file format " << CGROUPS_RC_PATH;
         return false;
     }
 
     CgroupFile* file_data = (CgroupFile*)mmap(nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0);
     if (file_data == MAP_FAILED) {
-        PLOG(ERROR) << "Failed to mmap " << cgroup_rc_path;
+        PLOG(ERROR) << "Failed to mmap " << CGROUPS_RC_PATH;
         return false;
     }
 
     if (file_data->version_ != CgroupFile::FILE_CURR_VERSION) {
-        LOG(ERROR) << cgroup_rc_path << " file version mismatch";
+        LOG(ERROR) << CGROUPS_RC_PATH << " file version mismatch";
         munmap(file_data, file_size);
         return false;
     }
 
     if (file_size != sizeof(CgroupFile) + file_data->controller_count_ * sizeof(CgroupController)) {
-        LOG(ERROR) << cgroup_rc_path << " file has invalid size";
+        LOG(ERROR) << CGROUPS_RC_PATH << " file has invalid size";
         munmap(file_data, file_size);
         return false;
     }
@@ -412,6 +414,18 @@
 bool CgroupMap::SetupCgroups() {
     std::map<std::string, CgroupDescriptor> descriptors;
 
+    if (getpid() != 1) {
+        LOG(ERROR) << "Cgroup setup can be done only by init process";
+        return false;
+    }
+
+    // Make sure we do this only one time. No need for std::call_once because
+    // init is a single-threaded process
+    if (access(CGROUPS_RC_PATH, F_OK) == 0) {
+        LOG(WARNING) << "Attempt to call SetupCgroups more than once";
+        return true;
+    }
+
     // load cgroups.json file
     if (!ReadDescriptors(&descriptors)) {
         LOG(ERROR) << "Failed to load cgroup description file";
@@ -428,8 +442,8 @@
     }
 
     // mkdir <CGROUPS_RC_DIR> 0711 system system
-    if (!Mkdir(CGROUPS_RC_DIR, 0711, "system", "system")) {
-        LOG(ERROR) << "Failed to create directory for <CGROUPS_RC_FILE> file";
+    if (!Mkdir(android::base::Dirname(CGROUPS_RC_PATH), 0711, "system", "system")) {
+        LOG(ERROR) << "Failed to create directory for " << CGROUPS_RC_PATH << " file";
         return false;
     }
 
@@ -438,13 +452,12 @@
     // and limits infrormation shared with unprivileged processes
     // to the minimum subset of information from cgroups.json
     if (!WriteRcFile(descriptors)) {
-        LOG(ERROR) << "Failed to write " << CGROUPS_RC_FILE << " file";
+        LOG(ERROR) << "Failed to write " << CGROUPS_RC_PATH << " file";
         return false;
     }
 
-    std::string cgroup_rc_path = StringPrintf("%s/%s", CGROUPS_RC_DIR, CGROUPS_RC_FILE);
-    // chmod 0644 <cgroup_rc_path>
-    if (fchmodat(AT_FDCWD, cgroup_rc_path.c_str(), 0644, AT_SYMLINK_NOFOLLOW) < 0) {
+    // chmod 0644 <CGROUPS_RC_PATH>
+    if (fchmodat(AT_FDCWD, CGROUPS_RC_PATH, 0644, AT_SYMLINK_NOFOLLOW) < 0) {
         PLOG(ERROR) << "fchmodat() failed";
         return false;
     }
diff --git a/libprocessgroup/cgroup_map.h b/libprocessgroup/cgroup_map.h
index 1c355cd..304ae15 100644
--- a/libprocessgroup/cgroup_map.h
+++ b/libprocessgroup/cgroup_map.h
@@ -75,8 +75,6 @@
 
 class CgroupMap {
   public:
-    static constexpr const char* CGROUPS_RC_FILE = "cgroup.rc";
-
     // Selinux policy ensures only init process can successfully use this function
     static bool SetupCgroups();
 
diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h
index 6f973b8..46b8676 100644
--- a/libprocessgroup/include/processgroup/processgroup.h
+++ b/libprocessgroup/include/processgroup/processgroup.h
@@ -24,7 +24,7 @@
 __BEGIN_DECLS
 
 static constexpr const char* CGROUPV2_CONTROLLER_NAME = "cgroup2";
-static constexpr const char* CGROUPS_RC_DIR = "/dev/cgroup_info";
+static constexpr const char* CGROUPS_RC_PATH = "/dev/cgroup_info/cgroup.rc";
 
 bool CgroupSetupCgroups();
 bool CgroupGetControllerPath(const std::string& cgroup_name, std::string* path);
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index 9538bba..bc1543b 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -38,6 +38,19 @@
             ],
         },
     },
+    sanitize: {
+        misc_undefined: [
+            "signed-integer-overflow",
+            "unsigned-integer-overflow",
+            "shift",
+            "integer-divide-by-zero",
+            "implicit-signed-integer-truncation",
+            // TODO: Fix crash when we enable this option
+            // "implicit-unsigned-integer-truncation",
+            // TODO: not tested yet.
+            // "implicit-integer-sign-change",
+        ],
+    },
 }
 
 cc_defaults {
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 2d3fbfc..2de7378 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -110,7 +110,7 @@
  */
 #define PSI_WINDOW_SIZE_MS 1000
 /* Polling period after initial PSI signal */
-#define PSI_POLL_PERIOD_MS 40
+#define PSI_POLL_PERIOD_MS 10
 /* Poll for the duration of one window after initial PSI signal */
 #define PSI_POLL_COUNT (PSI_WINDOW_SIZE_MS / PSI_POLL_PERIOD_MS)
 
diff --git a/logcat/event.logtags b/logcat/event.logtags
index da8d2d4..3a1d36f 100644
--- a/logcat/event.logtags
+++ b/logcat/event.logtags
@@ -116,8 +116,8 @@
 # audio
 # 61000 - 61199 reserved for audioserver
 
-# 0 for screen off, 1 for screen on, 2 for key-guard done
-70000 screen_toggled (screen_state|1|5)
+# com.android.server.policy
+# 70000 - 70199 reserved for PhoneWindowManager and other policies
 
 # aggregation service
 70200 aggregation (aggregation time|2|3)
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 54b019e..f78a926 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -8,6 +8,7 @@
 LOCAL_SRC_FILES := $(LOCAL_MODULE)
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
+LOCAL_REQUIRED_MODULES := fsverity_init
 
 # The init symlink must be a post install command of a file that is to TARGET_ROOT_OUT.
 # Since init.rc is required for init and satisfies that requirement, we hijack it to create the symlink.
@@ -57,6 +58,15 @@
 endif
 
 #######################################
+# fsverity_init
+
+include $(CLEAR_VARS)
+LOCAL_MODULE:= fsverity_init
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_SRC_FILES := fsverity_init.sh
+include $(BUILD_PREBUILT)
+
+#######################################
 # init.environ.rc
 
 include $(CLEAR_VARS)
diff --git a/rootdir/etc/ld.config.legacy.txt b/rootdir/etc/ld.config.legacy.txt
index 9cf93ca..0fccd31 100644
--- a/rootdir/etc/ld.config.legacy.txt
+++ b/rootdir/etc/ld.config.legacy.txt
@@ -11,14 +11,13 @@
 dir.legacy = /odm
 dir.legacy = /sbin
 
-dir.legacy = /data/nativetest
-dir.legacy = /data/nativetest64
-dir.legacy = /data/benchmarktest
-dir.legacy = /data/benchmarktest64
-
 # Except for /postinstall, where only /system and /product are searched
 dir.postinstall = /postinstall
 
+# Fallback entry to provide APEX namespace lookups for binaries anywhere else.
+# This must be last.
+dir.legacy = /data
+
 [legacy]
 namespace.default.isolated = false
 
@@ -54,8 +53,7 @@
 # Visible because some libraries are dlopen'ed, e.g. libopenjdk is dlopen'ed by
 # libart.
 namespace.default.visible = true
-namespace.default.link.runtime.shared_libs  = libart.so:libartd.so
-namespace.default.link.runtime.shared_libs += libdexfile_external.so
+namespace.default.link.runtime.shared_libs  = libdexfile_external.so
 namespace.default.link.runtime.shared_libs += libnativebridge.so
 namespace.default.link.runtime.shared_libs += libnativehelper.so
 namespace.default.link.runtime.shared_libs += libnativeloader.so
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 85deacf..2b0ef4c 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -27,13 +27,12 @@
 # necessary) the unrestricted subdirs above. Then clean this up.
 dir.unrestricted = /data/local/tmp
 
-dir.system = /data/nativetest
-dir.system = /data/nativetest64
-dir.system = /data/benchmarktest
-dir.system = /data/benchmarktest64
-
 dir.postinstall = /postinstall
 
+# Fallback entry to provide APEX namespace lookups for binaries anywhere else.
+# This must be last.
+dir.system = /data
+
 [system]
 additional.namespaces = runtime,conscrypt,media,resolv,sphal,vndk,rs
 
@@ -133,8 +132,7 @@
 # Visible because some libraries are dlopen'ed, e.g. libopenjdk is dlopen'ed by
 # libart.
 namespace.default.visible = true
-namespace.default.link.runtime.shared_libs  = libart.so:libartd.so
-namespace.default.link.runtime.shared_libs += libdexfile_external.so
+namespace.default.link.runtime.shared_libs  = libdexfile_external.so
 namespace.default.link.runtime.shared_libs += libnativebridge.so
 namespace.default.link.runtime.shared_libs += libnativehelper.so
 namespace.default.link.runtime.shared_libs += libnativeloader.so
@@ -577,8 +575,7 @@
 namespace.default.links = runtime,resolv
 namespace.default.visible = true
 
-namespace.default.link.runtime.shared_libs  = libart.so:libartd.so
-namespace.default.link.runtime.shared_libs += libdexfile_external.so
+namespace.default.link.runtime.shared_libs  = libdexfile_external.so
 namespace.default.link.runtime.shared_libs += libnativebridge.so
 namespace.default.link.runtime.shared_libs += libnativehelper.so
 namespace.default.link.runtime.shared_libs += libnativeloader.so
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index 26e1dd9..c8312df 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -27,13 +27,12 @@
 # necessary) the unrestricted subdirs above. Then clean this up.
 dir.unrestricted = /data/local/tmp
 
-dir.system = /data/nativetest
-dir.system = /data/nativetest64
-dir.system = /data/benchmarktest
-dir.system = /data/benchmarktest64
-
 dir.postinstall = /postinstall
 
+# Fallback entry to provide APEX namespace lookups for binaries anywhere else.
+# This must be last.
+dir.system = /data
+
 [system]
 additional.namespaces = runtime,conscrypt,media,resolv,sphal,vndk,rs
 
@@ -74,8 +73,7 @@
 # Visible because some libraries are dlopen'ed, e.g. libopenjdk is dlopen'ed by
 # libart.
 namespace.default.visible = true
-namespace.default.link.runtime.shared_libs  = libart.so:libartd.so
-namespace.default.link.runtime.shared_libs += libdexfile_external.so
+namespace.default.link.runtime.shared_libs  = libdexfile_external.so
 namespace.default.link.runtime.shared_libs += libnativebridge.so
 namespace.default.link.runtime.shared_libs += libnativehelper.so
 namespace.default.link.runtime.shared_libs += libnativeloader.so
@@ -400,8 +398,7 @@
 namespace.default.links = runtime,resolv
 namespace.default.visible = true
 
-namespace.default.link.runtime.shared_libs  = libart.so:libartd.so
-namespace.default.link.runtime.shared_libs += libdexfile_external.so
+namespace.default.link.runtime.shared_libs  = libdexfile_external.so
 namespace.default.link.runtime.shared_libs += libnativebridge.so
 namespace.default.link.runtime.shared_libs += libnativehelper.so
 namespace.default.link.runtime.shared_libs += libnativeloader.so
diff --git a/rootdir/fsverity_init.sh b/rootdir/fsverity_init.sh
new file mode 100644
index 0000000..29e4519
--- /dev/null
+++ b/rootdir/fsverity_init.sh
@@ -0,0 +1,29 @@
+#!/system/bin/sh
+#
+# Copyright (C) 2019 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.
+#
+
+# Enforce fsverity signature checking
+echo 1 > /proc/sys/fs/verity/require_signatures
+
+# Load all keys
+for cert in /product/etc/security/fsverity/*.der; do
+  /system/bin/mini-keyctl padd asymmetric fsv_product .fs-verity < "$cert" ||
+    log -p e -t fsverity_init "Failed to load $cert"
+done
+
+# Prevent future key links to .fs-verity keyring
+/system/bin/mini-keyctl restrict_keyring .fs-verity ||
+  log -p e -t fsverity_init "Failed to restrict .fs-verity keyring"
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 8e63a81..fec1e68 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -420,12 +420,7 @@
 
     # Load fsverity keys. This needs to happen before apexd, as post-install of
     # APEXes may rely on keys.
-    exec -- /system/bin/mini-keyctl dadd asymmetric product_cert /product/etc/security/cacerts_fsverity .fs-verity
-    exec -- /system/bin/mini-keyctl dadd asymmetric vendor_cert /vendor/etc/security/cacerts_fsverity .fs-verity
-    # Prevent future key links to fsverity keyring
-    exec -- /system/bin/mini-keyctl restrict_keyring .fs-verity
-    # Enforce fsverity signature checking
-    write /proc/sys/fs/verity/require_signatures 1
+    exec -- /system/bin/fsverity_init
 
     # Make sure that apexd is started in the default namespace
     enter_default_mount_ns