Merge changes I51628abe,I412d62b7

* changes:
  Wrap flock with TEMP_FAILURE_RETRY.
  Try locking after mounting metadata
diff --git a/adb/client/transport_mdns.cpp b/adb/client/transport_mdns.cpp
index 9611212..a0fc9ca 100644
--- a/adb/client/transport_mdns.cpp
+++ b/adb/client/transport_mdns.cpp
@@ -249,6 +249,9 @@
             return false;
         }
 
+        // Remove any services with the same instance name, as it may be a stale registration.
+        removeDNSService(regType_.c_str(), serviceName_.c_str());
+
         // Add to the service registry before trying to auto-connect, since socket_spec_connect will
         // check these registries for the ip address when connecting via mdns instance name.
         int adbSecureServiceType = serviceIndex();
@@ -268,13 +271,6 @@
                 return false;
         }
 
-        if (!services->empty()) {
-            // Remove the previous resolved service, if any.
-            services->erase(std::remove_if(services->begin(), services->end(),
-                                           [&](std::unique_ptr<ResolvedService>& service) {
-                                               return (serviceName_ == service->serviceName());
-                                           }));
-        }
         services->push_back(std::unique_ptr<ResolvedService>(this));
 
         if (adb_DNSServiceShouldAutoConnect(regType_.c_str(), serviceName_.c_str())) {
@@ -327,6 +323,8 @@
     static bool connectByServiceName(const ServiceRegistry& services,
                                      const std::string& service_name);
 
+    static void removeDNSService(const char* regType, const char* serviceName);
+
   private:
     int clientVersion_ = ADB_SECURE_CLIENT_VERSION;
     std::string addr_format_;
@@ -396,6 +394,37 @@
     return false;
 }
 
+// static
+void ResolvedService::removeDNSService(const char* regType, const char* serviceName) {
+    D("%s: regType=[%s] serviceName=[%s]", __func__, regType, serviceName);
+    int index = adb_DNSServiceIndexByName(regType);
+    ServiceRegistry* services;
+    switch (index) {
+        case kADBTransportServiceRefIndex:
+            services = sAdbTransportServices;
+            break;
+        case kADBSecurePairingServiceRefIndex:
+            services = sAdbSecurePairingServices;
+            break;
+        case kADBSecureConnectServiceRefIndex:
+            services = sAdbSecureConnectServices;
+            break;
+        default:
+            return;
+    }
+
+    if (services->empty()) {
+        return;
+    }
+
+    std::string sName(serviceName);
+    services->erase(std::remove_if(services->begin(), services->end(),
+                                   [&sName](std::unique_ptr<ResolvedService>& service) {
+                                       return (sName == service->serviceName());
+                                   }),
+                    services->end());
+}
+
 void adb_secure_foreach_pairing_service(const char* service_name,
                                         adb_secure_foreach_service_callback cb) {
     ResolvedService::forEachService(*ResolvedService::sAdbSecurePairingServices, service_name, cb);
@@ -481,35 +510,6 @@
     std::string regType_;
 };
 
-static void adb_RemoveDNSService(const char* regType, const char* serviceName) {
-    D("%s: regType=[%s] serviceName=[%s]", __func__, regType, serviceName);
-    int index = adb_DNSServiceIndexByName(regType);
-    ResolvedService::ServiceRegistry* services;
-    switch (index) {
-        case kADBTransportServiceRefIndex:
-            services = ResolvedService::sAdbTransportServices;
-            break;
-        case kADBSecurePairingServiceRefIndex:
-            services = ResolvedService::sAdbSecurePairingServices;
-            break;
-        case kADBSecureConnectServiceRefIndex:
-            services = ResolvedService::sAdbSecureConnectServices;
-            break;
-        default:
-            return;
-    }
-
-    if (services->empty()) {
-        return;
-    }
-
-    std::string sName(serviceName);
-    services->erase(std::remove_if(services->begin(), services->end(),
-                                   [&sName](std::unique_ptr<ResolvedService>& service) {
-                                       return (sName == service->serviceName());
-                                   }));
-}
-
 // Returns the version the device wanted to advertise,
 // or -1 if parsing fails.
 static int parse_version_from_txt_record(uint16_t txtLen, const unsigned char* txtRecord) {
@@ -612,7 +612,7 @@
     } else {
         D("%s: Discover lost serviceName=[%s] regtype=[%s] domain=[%s]", __func__, serviceName,
           regtype, domain);
-        adb_RemoveDNSService(regtype, serviceName);
+        ResolvedService::removeDNSService(regtype, serviceName);
     }
 }
 
diff --git a/adb/test_adb.py b/adb/test_adb.py
index b9f0d54..a32d875 100755
--- a/adb/test_adb.py
+++ b/adb/test_adb.py
@@ -618,21 +618,37 @@
     finally:
         zeroconf_ctx.unregister_service(info)
 
+@contextlib.contextmanager
+def zeroconf_register_services(zeroconf_ctx, infos):
+    """Context manager for multiple zeroconf services
+
+    Registers all services given and unregisters all on cleanup. Returns the ServiceInfo
+    list supplied.
+    """
+
+    try:
+        for info in infos:
+            zeroconf_ctx.register_service(info)
+        yield infos
+    finally:
+        for info in infos:
+            zeroconf_ctx.unregister_service(info)
+
 """Should match the service names listed in adb_mdns.h"""
 class MdnsTest:
     """Tests for adb mdns."""
+    @staticmethod
+    def _mdns_services(port):
+        output = subprocess.check_output(["adb", "-P", str(port), "mdns", "services"])
+        return [x.split("\t") for x in output.decode("utf8").strip().splitlines()[1:]]
+
+    @staticmethod
+    def _devices(port):
+        output = subprocess.check_output(["adb", "-P", str(port), "devices"])
+        return [x.split("\t") for x in output.decode("utf8").strip().splitlines()[1:]]
+
 
     class Base(unittest.TestCase):
-        @staticmethod
-        def _mdns_services(port):
-            output = subprocess.check_output(["adb", "-P", str(port), "mdns", "services"])
-            return [x.split("\t") for x in output.decode("utf8").strip().splitlines()[1:]]
-
-        @staticmethod
-        def _devices(port):
-            output = subprocess.check_output(["adb", "-P", str(port), "devices"])
-            return [x.split("\t") for x in output.decode("utf8").strip().splitlines()[1:]]
-
         @contextlib.contextmanager
         def _adb_mdns_connect(self, server_port, mdns_instance, serial, should_connect):
             """Context manager for an ADB connection.
@@ -691,6 +707,50 @@
                         for line in MdnsTest._mdns_services(server_port)))
 
         @unittest.skipIf(not is_zeroconf_installed(), "zeroconf library not installed")
+        def test_mdns_services_register_unregister_multiple(self):
+            """Ensure that `adb mdns services` correctly adds and removes multiple services
+            """
+            from zeroconf import IPVersion, ServiceInfo
+
+            with adb_server() as server_port:
+                output = subprocess.check_output(["adb", "-P", str(server_port),
+                                                  "mdns", "services"]).strip()
+                self.assertTrue(output.startswith(b"List of discovered mdns services"))
+
+                """TODO(joshuaduong): Add ipv6 tests once we have it working in adb"""
+                """Register/Unregister a service"""
+                with zeroconf_context(IPVersion.V4Only) as zc:
+                    srvs = {
+                        'mdns_name': ["testservice0", "testservice1", "testservice2"],
+                        'mdns_type': "_" + self.service_name + "._tcp.",
+                        'ipaddr': [
+                            socket.inet_aton("192.168.0.1"),
+                            socket.inet_aton("10.0.0.255"),
+                            socket.inet_aton("172.16.1.100")],
+                        'port': [10000, 20000, 65535]}
+                    srv_infos = []
+                    for i in range(len(srvs['mdns_name'])):
+                        srv_infos.append(ServiceInfo(
+                                srvs['mdns_type'] + "local.",
+                                name=srvs['mdns_name'][i] + "." + srvs['mdns_type'] + "local.",
+                                addresses=[srvs['ipaddr'][i]],
+                                port=srvs['port'][i]))
+
+                    """ Register all devices, then unregister"""
+                    with zeroconf_register_services(zc, srv_infos) as infos:
+                        """Give adb some time to register the service"""
+                        time.sleep(1)
+                        for i in range(len(srvs['mdns_name'])):
+                            self.assertTrue(any((srvs['mdns_name'][i] in line and srvs['mdns_type'] in line)
+                                for line in MdnsTest._mdns_services(server_port)))
+
+                    """Give adb some time to unregister the service"""
+                    time.sleep(1)
+                    for i in range(len(srvs['mdns_name'])):
+                        self.assertFalse(any((srvs['mdns_name'][i] in line and srvs['mdns_type'] in line)
+                            for line in MdnsTest._mdns_services(server_port)))
+
+        @unittest.skipIf(not is_zeroconf_installed(), "zeroconf library not installed")
         def test_mdns_connect(self):
             """Ensure that `adb connect` by mdns instance name works (for non-pairing services)
             """
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 5d6cee4..8979e9a 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -436,6 +436,8 @@
     {"reboot,userspace_failed,watchdog_fork", 188},
     {"reboot,userspace_failed,*", 189},
     {"reboot,mount_userdata_failed", 190},
+    {"reboot,forcedsilent", 191},
+    {"reboot,forcednonsilent", 192},
 };
 
 // Converts a string value representing the reason the system booted to an
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index cd64599..ac784b2 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -149,6 +149,14 @@
         darwin: {
             enabled: false,
         },
+        vendor: {
+            cflags: [
+                // Skipping entries in fstab should only be done in a system
+                // process as the config file is in /system_ext.
+                // Remove the op from the vendor variant.
+                "-DNO_SKIP_MOUNT",
+            ],
+        },
     },
     export_include_dirs: ["include_fstab"],
     header_libs: [
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index f333a85..54102ec 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -696,7 +696,9 @@
         TransformFstabForDsu(fstab, Split(lp_names, ","));
     }
 
+#ifndef NO_SKIP_MOUNT
     SkipMountingPartitions(fstab);
+#endif
     EnableMandatoryFlags(fstab);
 
     return true;
@@ -726,11 +728,14 @@
         return false;
     }
 
+#ifndef NO_SKIP_MOUNT
     SkipMountingPartitions(fstab);
+#endif
 
     return true;
 }
 
+#ifndef NO_SKIP_MOUNT
 // For GSI to skip mounting /product and /system_ext, until there are well-defined interfaces
 // between them and /system. Otherwise, the GSI flashed on /system might not be able to work with
 // device-specific /product and /system_ext. skip_mount.cfg belongs to system_ext partition because
@@ -762,6 +767,7 @@
 
     return true;
 }
+#endif
 
 // Loads the fstab file and combines with fstab entries passed in from device tree.
 bool ReadDefaultFstab(Fstab* fstab) {
diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp
index 250cb82..8788b5a 100644
--- a/fs_mgr/libdm/dm_target.cpp
+++ b/fs_mgr/libdm/dm_target.cpp
@@ -280,5 +280,12 @@
     return android::base::Join(argv, " ");
 }
 
+std::string DmTargetUser::GetParameterString() const {
+    std::vector<std::string> argv;
+    argv.push_back(std::to_string(start()));
+    argv.push_back(std::to_string(size()));
+    return android::base::Join(argv, " ");
+}
+
 }  // namespace dm
 }  // namespace android
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index f986cfe..57e3884 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -309,6 +309,14 @@
     bool is_hw_wrapped_ = false;
 };
 
+class DmTargetUser final : public DmTarget {
+  public:
+    DmTargetUser(uint64_t start, uint64_t length) : DmTarget(start, length) {}
+
+    std::string name() const override { return "user"; }
+    std::string GetParameterString() const override;
+};
+
 }  // namespace dm
 }  // namespace android
 
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index c37d70e..ace6210 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -205,11 +205,18 @@
         }
     }
 
-    if (IPropertyFetcher::GetInstance()->GetBoolProperty("ro.virtual_ab.enabled", false) &&
-        !always_keep_source_slot) {
-        if (!UpdateMetadataForInPlaceSnapshot(metadata.get(), source_slot_number,
-                                              target_slot_number)) {
-            return nullptr;
+    if (IPropertyFetcher::GetInstance()->GetBoolProperty("ro.virtual_ab.enabled", false)) {
+        if (always_keep_source_slot) {
+            // always_keep_source_slot implies the target build does not support snapshots.
+            // Clear unsupported attributes.
+            SetMetadataHeaderV0(metadata.get());
+        } else {
+            // !always_keep_source_slot implies the target build supports snapshots. Do snapshot
+            // updates.
+            if (!UpdateMetadataForInPlaceSnapshot(metadata.get(), source_slot_number,
+                                                  target_slot_number)) {
+                return nullptr;
+            }
         }
     }
 
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index 89a47b1..f2e7370 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -208,8 +208,10 @@
     // metadata may not have the target slot's devices listed yet, in which
     // case, it is automatically upgraded to include all available block
     // devices.
-    // If |always_keep_source_slot| is set, on a Virtual A/B device, source slot
-    // partitions are kept. This is useful when applying a downgrade package.
+    // If |always_keep_source_slot| is set, on a Virtual A/B device
+    // - source slot partitions are kept.
+    // - UPDATED flag is cleared.
+    // This is useful when applying a downgrade package.
     static std::unique_ptr<MetadataBuilder> NewForUpdate(const IPartitionOpener& opener,
                                                          const std::string& source_partition,
                                                          uint32_t source_slot_number,
diff --git a/fs_mgr/liblp/utility.cpp b/fs_mgr/liblp/utility.cpp
index 48c5c83..d8e171b 100644
--- a/fs_mgr/liblp/utility.cpp
+++ b/fs_mgr/liblp/utility.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <fcntl.h>
+#include <inttypes.h>
 #include <stdint.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -29,6 +30,7 @@
 #include <vector>
 
 #include <android-base/file.h>
+#include <android-base/stringprintf.h>
 #include <ext4_utils/ext4_utils.h>
 #include <openssl/sha.h>
 
@@ -285,5 +287,42 @@
     return true;
 }
 
+inline std::string ToHexString(uint64_t value) {
+    return android::base::StringPrintf("0x%" PRIx64, value);
+}
+
+void SetMetadataHeaderV0(LpMetadata* metadata) {
+    if (metadata->header.minor_version <= LP_METADATA_MINOR_VERSION_MIN) {
+        return;
+    }
+    LINFO << "Forcefully setting metadata header version " << LP_METADATA_MAJOR_VERSION << "."
+          << metadata->header.minor_version << " to " << LP_METADATA_MAJOR_VERSION << "."
+          << LP_METADATA_MINOR_VERSION_MIN;
+    metadata->header.minor_version = LP_METADATA_MINOR_VERSION_MIN;
+    metadata->header.header_size = sizeof(LpMetadataHeaderV1_0);
+
+    // Retrofit Virtual A/B devices should have version 10.1, so flags shouldn't be set.
+    // Warn if this is the case, but zero it out anyways.
+    if (metadata->header.flags) {
+        LWARN << "Zeroing unexpected flags: " << ToHexString(metadata->header.flags);
+    }
+
+    // Zero out all fields beyond LpMetadataHeaderV0.
+    static_assert(sizeof(metadata->header) > sizeof(LpMetadataHeaderV1_0));
+    memset(reinterpret_cast<uint8_t*>(&metadata->header) + sizeof(LpMetadataHeaderV1_0), 0,
+           sizeof(metadata->header) - sizeof(LpMetadataHeaderV1_0));
+
+    // Clear partition attributes unknown to V0.
+    // On retrofit Virtual A/B devices, UPDATED flag may be set, so only log info here.
+    for (auto& partition : metadata->partitions) {
+        if (partition.attributes & ~LP_PARTITION_ATTRIBUTE_MASK_V0) {
+            LINFO << "Clearing " << GetPartitionName(partition)
+                  << " partition attribute: " << ToHexString(partition.attributes);
+        }
+
+        partition.attributes &= LP_PARTITION_ATTRIBUTE_MASK_V0;
+    }
+}
+
 }  // namespace fs_mgr
 }  // namespace android
diff --git a/fs_mgr/liblp/utility.h b/fs_mgr/liblp/utility.h
index c4fe3ed..aa3a6a0 100644
--- a/fs_mgr/liblp/utility.h
+++ b/fs_mgr/liblp/utility.h
@@ -103,6 +103,10 @@
 bool UpdateMetadataForInPlaceSnapshot(LpMetadata* metadata, uint32_t source_slot_number,
                                       uint32_t target_slot_number);
 
+// Forcefully set metadata header version to 1.0, clearing any incompatible flags and attributes
+// so that when downgrading to a build with liblp V0, the device still boots.
+void SetMetadataHeaderV0(LpMetadata* metadata);
+
 }  // namespace fs_mgr
 }  // namespace android
 
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 2738457..7a3d9a9 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -174,6 +174,8 @@
             }
             return std::make_unique<DmTargetSnapshot>(start_sector, num_sectors, base_device,
                                                       cow_device, mode, chunk_size);
+        } else if (target_type == "user") {
+            return std::make_unique<DmTargetUser>(start_sector, num_sectors);
         } else {
             std::cerr << "Unrecognized target type: " << target_type << std::endl;
             return nullptr;
diff --git a/init/Android.bp b/init/Android.bp
index edf9099..3f2cd07 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -130,6 +130,7 @@
         "libpropertyinfoserializer",
         "libpropertyinfoparser",
         "libsnapshot_init",
+        "libxml2",
         "lib_apex_manifest_proto_lite",
         "update_metadata-protos",
     ],
@@ -164,6 +165,9 @@
         "selinux_policy_version",
     ],
     srcs: init_common_sources + init_device_sources,
+    generated_sources: [
+        "apex-info-list",
+    ],
     whole_static_libs: [
         "libcap",
         "com.android.sysprop.apex",
@@ -178,6 +182,12 @@
     target: {
         recovery: {
             cflags: ["-DRECOVERY"],
+            exclude_static_libs: [
+                "libxml2",
+            ],
+            exclude_generated_sources: [
+                "apex-info-list",
+            ],
             exclude_shared_libs: [
                 "libbinder",
                 "libutils",
@@ -212,6 +222,9 @@
     target: {
         recovery: {
             cflags: ["-DRECOVERY"],
+            exclude_static_libs: [
+                "libxml2",
+            ],
             exclude_shared_libs: [
                 "libbinder",
                 "libutils",
diff --git a/init/devices.cpp b/init/devices.cpp
index 9fbec64..53ca875 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -193,7 +193,8 @@
     while (directory != "/" && directory != ".") {
         std::string subsystem_link_path;
         if (Realpath(directory + "/subsystem", &subsystem_link_path) &&
-            subsystem_link_path == sysfs_mount_point_ + "/bus/platform") {
+            (subsystem_link_path == sysfs_mount_point_ + "/bus/platform" ||
+             subsystem_link_path == sysfs_mount_point_ + "/bus/amba")) {
             // We need to remove the mount point that we added above before returning.
             directory.erase(0, sysfs_mount_point_.size());
             *platform_device_path = directory;
diff --git a/init/init.cpp b/init/init.cpp
index 631db8e..ba880ea 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -868,6 +868,8 @@
     // Run all property triggers based on current state of the properties.
     am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
 
+    // Restore prio before main loop
+    setpriority(PRIO_PROCESS, 0, 0);
     while (true) {
         // By default, sleep until something happens.
         auto epoll_timeout = std::optional<std::chrono::milliseconds>{};
diff --git a/init/main.cpp b/init/main.cpp
index 38bc74b..23f5530 100644
--- a/init/main.cpp
+++ b/init/main.cpp
@@ -52,7 +52,8 @@
 #if __has_feature(address_sanitizer)
     __asan_set_error_report_callback(AsanReportCallback);
 #endif
-
+    // Boost prio which will be restored later
+    setpriority(PRIO_PROCESS, 0, -20);
     if (!strcmp(basename(argv[0]), "ueventd")) {
         return ueventd_main(argc, argv);
     }
diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp
index b9d5d67..f8359bc 100644
--- a/init/mount_namespace.cpp
+++ b/init/mount_namespace.cpp
@@ -27,10 +27,19 @@
 #include <android-base/properties.h>
 #include <android-base/result.h>
 #include <android-base/unique_fd.h>
-#include <apex_manifest.pb.h>
 
 #include "util.h"
 
+#ifndef RECOVERY
+#define ACTIVATE_FLATTENED_APEX 1
+#endif
+
+#ifdef ACTIVATE_FLATTENED_APEX
+#include <apex_manifest.pb.h>
+#include <com_android_apex.h>
+#include <selinux/android.h>
+#endif  // ACTIVATE_FLATTENED_APEX
+
 namespace android {
 namespace init {
 namespace {
@@ -106,6 +115,8 @@
     return updatable;
 }
 
+#ifdef ACTIVATE_FLATTENED_APEX
+
 static Result<void> MountDir(const std::string& path, const std::string& mount_path) {
     if (int ret = mkdir(mount_path.c_str(), 0755); ret != 0 && errno != EEXIST) {
         return ErrnoError() << "Could not create mount point " << mount_path;
@@ -116,7 +127,7 @@
     return {};
 }
 
-static Result<std::string> GetApexName(const std::string& apex_dir) {
+static Result<apex::proto::ApexManifest> GetApexManifest(const std::string& apex_dir) {
     const std::string manifest_path = apex_dir + "/apex_manifest.pb";
     std::string content;
     if (!android::base::ReadFileToString(manifest_path, &content)) {
@@ -126,11 +137,12 @@
     if (!manifest.ParseFromString(content)) {
         return Error() << "Can't parse manifest file: " << manifest_path;
     }
-    return manifest.name();
+    return manifest;
 }
 
+template <typename Fn>
 static Result<void> ActivateFlattenedApexesFrom(const std::string& from_dir,
-                                                const std::string& to_dir) {
+                                                const std::string& to_dir, Fn on_activate) {
     std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(from_dir.c_str()), closedir);
     if (!dir) {
         return {};
@@ -140,15 +152,16 @@
         if (entry->d_name[0] == '.') continue;
         if (entry->d_type == DT_DIR) {
             const std::string apex_path = from_dir + "/" + entry->d_name;
-            const auto apex_name = GetApexName(apex_path);
-            if (!apex_name.ok()) {
-                LOG(ERROR) << apex_path << " is not an APEX directory: " << apex_name.error();
+            const auto apex_manifest = GetApexManifest(apex_path);
+            if (!apex_manifest.ok()) {
+                LOG(ERROR) << apex_path << " is not an APEX directory: " << apex_manifest.error();
                 continue;
             }
-            const std::string mount_path = to_dir + "/" + (*apex_name);
+            const std::string mount_path = to_dir + "/" + apex_manifest->name();
             if (auto result = MountDir(apex_path, mount_path); !result.ok()) {
                 return result;
             }
+            on_activate(apex_path, *apex_manifest);
         }
     }
     return {};
@@ -167,15 +180,37 @@
             "/vendor/apex",
     };
 
+    std::vector<com::android::apex::ApexInfo> apex_infos;
+    auto on_activate = [&](const std::string& apex_path,
+                           const apex::proto::ApexManifest& apex_manifest) {
+        apex_infos.emplace_back(apex_manifest.name(), apex_path, apex_path, apex_manifest.version(),
+                                apex_manifest.versionname(), /*isFactory=*/true, /*isActive=*/true);
+    };
+
     for (const auto& dir : kBuiltinDirsForApexes) {
-        if (auto result = ActivateFlattenedApexesFrom(dir, kApexTop); !result.ok()) {
+        if (auto result = ActivateFlattenedApexesFrom(dir, kApexTop, on_activate); !result.ok()) {
             LOG(ERROR) << result.error();
             return false;
         }
     }
+
+    std::ostringstream oss;
+    com::android::apex::ApexInfoList apex_info_list(apex_infos);
+    com::android::apex::write(oss, apex_info_list);
+    const std::string kApexInfoList = kApexTop + "/apex-info-list.xml";
+    if (!android::base::WriteStringToFile(oss.str(), kApexInfoList)) {
+        PLOG(ERROR) << "Failed to write " << kApexInfoList;
+        return false;
+    }
+    if (selinux_android_restorecon(kApexInfoList.c_str(), 0) != 0) {
+        PLOG(ERROR) << "selinux_android_restorecon(" << kApexInfoList << ") failed";
+    }
+
     return true;
 }
 
+#endif  // ACTIVATE_FLATTENED_APEX
+
 static android::base::unique_fd bootstrap_ns_fd;
 static android::base::unique_fd default_ns_fd;
 
@@ -269,9 +304,9 @@
         default_ns_fd.reset(OpenMountNamespace());
         default_ns_id = GetMountNamespaceId();
     }
-
+#ifdef ACTIVATE_FLATTENED_APEX
     success &= ActivateFlattenedApexesIfPossible();
-
+#endif
     LOG(INFO) << "SetupMountNamespaces done";
     return success;
 }
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 612854d..b593b62 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -51,6 +51,7 @@
 #include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/parseint.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
@@ -74,6 +75,7 @@
 using namespace std::literals;
 
 using android::base::GetProperty;
+using android::base::ParseInt;
 using android::base::ReadFileToString;
 using android::base::Split;
 using android::base::StartsWith;
@@ -886,24 +888,60 @@
         load_properties_from_file("/prop.default", nullptr, &properties);
     }
 
+    // /<part>/etc/build.prop is the canonical location of the build-time properties since S.
+    // Falling back to /<part>/defalt.prop and /<part>/build.prop only when legacy path has to
+    // be supported, which is controlled by the support_legacy_path_until argument.
+    const auto load_properties_from_partition = [&properties](const std::string& partition,
+                                                              int support_legacy_path_until) {
+        auto path = "/" + partition + "/etc/build.prop";
+        if (load_properties_from_file(path.c_str(), nullptr, &properties)) {
+            return;
+        }
+        // To read ro.<partition>.build.version.sdk, temporarily load the legacy paths into a
+        // separate map. Then by comparing its value with legacy_version, we know that if the
+        // partition is old enough so that we need to respect the legacy paths.
+        std::map<std::string, std::string> temp;
+        auto legacy_path1 = "/" + partition + "/default.prop";
+        auto legacy_path2 = "/" + partition + "/build.prop";
+        load_properties_from_file(legacy_path1.c_str(), nullptr, &temp);
+        load_properties_from_file(legacy_path2.c_str(), nullptr, &temp);
+        bool support_legacy_path = false;
+        auto version_prop_name = "ro." + partition + ".build.version.sdk";
+        auto it = temp.find(version_prop_name);
+        if (it == temp.end()) {
+            // This is embarassing. Without the prop, we can't determine how old the partition is.
+            // Let's be conservative by assuming it is very very old.
+            support_legacy_path = true;
+        } else if (int value;
+                   ParseInt(it->second.c_str(), &value) && value <= support_legacy_path_until) {
+            support_legacy_path = true;
+        }
+        if (support_legacy_path) {
+            // We don't update temp into properties directly as it might skip any (future) logic
+            // for resolving duplicates implemented in load_properties_from_file.  Instead, read
+            // the files again into the properties map.
+            load_properties_from_file(legacy_path1.c_str(), nullptr, &properties);
+            load_properties_from_file(legacy_path2.c_str(), nullptr, &properties);
+        } else {
+            LOG(FATAL) << legacy_path1 << " and " << legacy_path2 << " were not loaded "
+                       << "because " << version_prop_name << "(" << it->second << ") is newer "
+                       << "than " << support_legacy_path_until;
+        }
+    };
+
+    // Order matters here. The more the partition is specific to a product, the higher its
+    // precedence is.
     load_properties_from_file("/system/build.prop", nullptr, &properties);
-    load_properties_from_file("/system_ext/build.prop", nullptr, &properties);
-
-    // TODO(b/117892318): uncomment the following condition when vendor.imgs for
-    // aosp_* targets are all updated.
-//    if (SelinuxGetVendorAndroidVersion() <= __ANDROID_API_R__) {
-        load_properties_from_file("/vendor/default.prop", nullptr, &properties);
-//    }
+    load_properties_from_partition("system_ext", /* support_legacy_path_until */ 30);
+    // TODO(b/117892318): uncomment the following condition when vendor.imgs for aosp_* targets are
+    // all updated.
+    // if (SelinuxGetVendorAndroidVersion() <= __ANDROID_API_R__) {
+    load_properties_from_file("/vendor/default.prop", nullptr, &properties);
+    // }
     load_properties_from_file("/vendor/build.prop", nullptr, &properties);
+    load_properties_from_partition("odm", /* support_legacy_path_until */ 28);
+    load_properties_from_partition("product", /* support_legacy_path_until */ 30);
 
-    if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_Q__) {
-        load_properties_from_file("/odm/etc/build.prop", nullptr, &properties);
-    } else {
-        load_properties_from_file("/odm/default.prop", nullptr, &properties);
-        load_properties_from_file("/odm/build.prop", nullptr, &properties);
-    }
-
-    load_properties_from_file("/product/build.prop", nullptr, &properties);
     load_properties_from_file("/factory/factory.prop", "ro.*", &properties);
 
     if (access(kDebugRamdiskProp, R_OK) == 0) {
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index f3dd538..9d4ea8c 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -18,6 +18,8 @@
 
 #include <fcntl.h>
 #include <poll.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 #include <unistd.h>
 
 #include <android-base/file.h>
@@ -181,6 +183,8 @@
     trigger_shutdown = [](const std::string& command) { shutdown_command = command; };
 
     auto subcontext_process = SubcontextProcess(function_map, context, init_fd);
+    // Restore prio before main loop
+    setpriority(PRIO_PROCESS, 0, 0);
     subcontext_process.MainLoop();
     return 0;
 }
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index 7514b61..54659c5 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -321,6 +321,8 @@
     while (waitpid(-1, nullptr, WNOHANG) > 0) {
     }
 
+    // Restore prio before main loop
+    setpriority(PRIO_PROCESS, 0, 0);
     uevent_listener.Poll([&uevent_handlers](const Uevent& uevent) {
         for (auto& uevent_handler : uevent_handlers) {
             uevent_handler->HandleUevent(uevent);
diff --git a/libmodprobe/include/modprobe/modprobe.h b/libmodprobe/include/modprobe/modprobe.h
index 4806b08..baee4f9 100644
--- a/libmodprobe/include/modprobe/modprobe.h
+++ b/libmodprobe/include/modprobe/modprobe.h
@@ -37,7 +37,6 @@
     void ResetModuleCount() { module_count_ = 0; }
     int GetModuleCount() { return module_count_; }
     void EnableBlocklist(bool enable);
-    void EnableVerbose(bool enable);
 
   private:
     std::string MakeCanonical(const std::string& module_path);
diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp
index 5a6ae8b..bbdd317 100644
--- a/libmodprobe/libmodprobe.cpp
+++ b/libmodprobe/libmodprobe.cpp
@@ -343,14 +343,6 @@
     blocklist_enabled = enable;
 }
 
-void Modprobe::EnableVerbose(bool enable) {
-    if (enable) {
-        android::base::SetMinimumLogSeverity(android::base::VERBOSE);
-    } else {
-        android::base::SetMinimumLogSeverity(android::base::INFO);
-    }
-}
-
 std::vector<std::string> Modprobe::GetDependencies(const std::string& module) {
     auto it = module_deps_.find(module);
     if (it == module_deps_.end()) {
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index 4af4589..a638fca 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -44,6 +44,11 @@
 #define TASK_PROFILE_DB_FILE "/etc/task_profiles.json"
 #define TASK_PROFILE_DB_VENDOR_FILE "/vendor/etc/task_profiles.json"
 
+void ProfileAttribute::Reset(const CgroupController& controller, const std::string& file_name) {
+    controller_ = controller;
+    file_name_ = file_name;
+}
+
 bool ProfileAttribute::GetPathForTask(int tid, std::string* path) const {
     std::string subgroup;
     if (!controller()->GetTaskGroup(tid, &subgroup)) {
@@ -380,15 +385,16 @@
         std::string controller_name = attr[i]["Controller"].asString();
         std::string file_attr = attr[i]["File"].asString();
 
-        if (attributes_.find(name) == attributes_.end()) {
-            auto controller = cg_map.FindController(controller_name);
-            if (controller.HasValue()) {
+        auto controller = cg_map.FindController(controller_name);
+        if (controller.HasValue()) {
+            auto iter = attributes_.find(name);
+            if (iter == attributes_.end()) {
                 attributes_[name] = std::make_unique<ProfileAttribute>(controller, file_attr);
             } else {
-                LOG(WARNING) << "Controller " << controller_name << " is not found";
+                iter->second->Reset(controller, file_attr);
             }
         } else {
-            LOG(WARNING) << "Attribute " << name << " is already defined";
+            LOG(WARNING) << "Controller " << controller_name << " is not found";
         }
     }
 
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index 28bc00c..2983a09 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -33,6 +33,7 @@
 
     const CgroupController* controller() const { return &controller_; }
     const std::string& file_name() const { return file_name_; }
+    void Reset(const CgroupController& controller, const std::string& file_name);
 
     bool GetPathForTask(int tid, std::string* path) const;
 
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 7392806..9bd15c6 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -78,6 +78,9 @@
         "libcutils",
         "liblog",
     ],
+    sanitize: {
+        misc_undefined: ["integer"],
+    },
 
     target: {
         android: {
diff --git a/toolbox/modprobe.cpp b/toolbox/modprobe.cpp
index 0033b65..7df7b71 100644
--- a/toolbox/modprobe.cpp
+++ b/toolbox/modprobe.cpp
@@ -18,9 +18,10 @@
 #include <getopt.h>
 #include <stdlib.h>
 
-#include <iostream>
+#include <string>
 
 #include <android-base/file.h>
+#include <android-base/logging.h>
 #include <android-base/strings.h>
 #include <modprobe/modprobe.h>
 
@@ -34,42 +35,66 @@
 };
 
 void print_usage(void) {
-    std::cerr << "Usage:" << std::endl;
-    std::cerr << std::endl;
+    LOG(INFO) << "Usage:";
+    LOG(INFO);
     // -d option is required on Android
-    std::cerr << "  modprobe [options] -d DIR MODULE..." << std::endl;
-    std::cerr << "  modprobe [options] -d DIR MODULE [symbol=value]..." << std::endl;
-    std::cerr << std::endl;
-    std::cerr << "Options:" << std::endl;
-    std::cerr << "  -b, --use-blocklist: Apply blocklist to module names too" << std::endl;
-    std::cerr << "  -d, --dirname=DIR: Load modules from DIR, option may be used multiple times"
-              << std::endl;
-    std::cerr << "  -D, --show-depends: Print dependencies for modules only, do not load"
-              << std::endl;
-    std::cerr << "  -h, --help: Print this help" << std::endl;
-    std::cerr << "  -l, --list: List modules matching pattern" << std::endl;
-    std::cerr << "  -r, --remove: Remove MODULE (multiple modules may be specified)" << std::endl;
-    std::cerr << "  -q, --quiet: disable messages" << std::endl;
-    std::cerr << "  -v, --verbose: enable more messages" << std::endl;
-    std::cerr << std::endl;
+    LOG(INFO) << "  modprobe [options] -d DIR [--all=FILE|MODULE]...";
+    LOG(INFO) << "  modprobe [options] -d DIR MODULE [symbol=value]...";
+    LOG(INFO);
+    LOG(INFO) << "Options:";
+    LOG(INFO) << "  --all=FILE: FILE to acquire module names from";
+    LOG(INFO) << "  -b, --use-blocklist: Apply blocklist to module names too";
+    LOG(INFO) << "  -d, --dirname=DIR: Load modules from DIR, option may be used multiple times";
+    LOG(INFO) << "  -D, --show-depends: Print dependencies for modules only, do not load";
+    LOG(INFO) << "  -h, --help: Print this help";
+    LOG(INFO) << "  -l, --list: List modules matching pattern";
+    LOG(INFO) << "  -r, --remove: Remove MODULE (multiple modules may be specified)";
+    LOG(INFO) << "  -s, --syslog: print to syslog also";
+    LOG(INFO) << "  -q, --quiet: disable messages";
+    LOG(INFO) << "  -v, --verbose: enable more messages, even more with a second -v";
+    LOG(INFO);
 }
 
-#define check_mode()                                                      \
-    if (mode != AddModulesMode) {                                         \
-        std::cerr << "Error, multiple mode flags specified" << std::endl; \
-        print_usage();                                                    \
-        return EXIT_FAILURE;                                              \
+#define check_mode()                                   \
+    if (mode != AddModulesMode) {                      \
+        LOG(ERROR) << "multiple mode flags specified"; \
+        print_usage();                                 \
+        return EXIT_FAILURE;                           \
     }
 
+std::string stripComments(const std::string& str) {
+    for (std::string rv = str;;) {
+        auto comment = rv.find('#');
+        if (comment == std::string::npos) return rv;
+        auto end = rv.find('\n', comment);
+        if (end != std::string::npos) end = end - comment;
+        rv.erase(comment, end);
+    }
+    /* NOTREACHED */
+}
+
+auto syslog = false;
+
+void MyLogger(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
+              const char* file, unsigned int line, const char* message) {
+    android::base::StdioLogger(id, severity, tag, file, line, message);
+    if (syslog && message[0]) {
+        android::base::KernelLogger(id, severity, tag, file, line, message);
+    }
+}
+
 }  // anonymous namespace
 
 extern "C" int modprobe_main(int argc, char** argv) {
+    android::base::InitLogging(argv, MyLogger);
+    android::base::SetMinimumLogSeverity(android::base::INFO);
+
     std::vector<std::string> modules;
     std::string module_parameters;
+    std::string mods;
     std::vector<std::string> mod_dirs;
     modprobe_mode mode = AddModulesMode;
     bool blocklist = false;
-    bool verbose = false;
     int rv = EXIT_SUCCESS;
 
     int opt;
@@ -78,7 +103,7 @@
     // OEMs to transition from toybox.
     // clang-format off
     static struct option long_options[] = {
-        { "all",                 no_argument,       0, 'a' },
+        { "all",                 optional_argument, 0, 'a' },
         { "use-blocklist",       no_argument,       0, 'b' },
         { "dirname",             required_argument, 0, 'd' },
         { "show-depends",        no_argument,       0, 'D' },
@@ -86,15 +111,27 @@
         { "list",                no_argument,       0, 'l' },
         { "quiet",               no_argument,       0, 'q' },
         { "remove",              no_argument,       0, 'r' },
+        { "syslog",              no_argument,       0, 's' },
         { "verbose",             no_argument,       0, 'v' },
     };
     // clang-format on
-    while ((opt = getopt_long(argc, argv, "abd:Dhlqrv", long_options, &option_index)) != -1) {
+    while ((opt = getopt_long(argc, argv, "a::bd:Dhlqrsv", long_options, &option_index)) != -1) {
         switch (opt) {
             case 'a':
                 // toybox modprobe supported -a to load multiple modules, this
-                // is supported here by default, ignore flag
+                // is supported here by default, ignore flag if no argument.
                 check_mode();
+                if (optarg == NULL) break;
+                if (!android::base::ReadFileToString(optarg, &mods)) {
+                    PLOG(ERROR) << "Failed to open " << optarg;
+                    rv = EXIT_FAILURE;
+                }
+                for (auto mod : android::base::Split(stripComments(mods), "\n")) {
+                    mod = android::base::Trim(mod);
+                    if (mod == "") continue;
+                    if (std::find(modules.begin(), modules.end(), mod) != modules.end()) continue;
+                    modules.emplace_back(mod);
+                }
                 break;
             case 'b':
                 blocklist = true;
@@ -107,24 +144,33 @@
                 mode = ShowDependenciesMode;
                 break;
             case 'h':
+                android::base::SetMinimumLogSeverity(android::base::INFO);
                 print_usage();
-                return EXIT_SUCCESS;
+                return rv;
             case 'l':
                 check_mode();
                 mode = ListModulesMode;
                 break;
             case 'q':
-                verbose = false;
+                android::base::SetMinimumLogSeverity(android::base::WARNING);
                 break;
             case 'r':
                 check_mode();
                 mode = RemoveModulesMode;
                 break;
+            case 's':
+                syslog = true;
+                break;
             case 'v':
-                verbose = true;
+                if (android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
+                    android::base::SetMinimumLogSeverity(android::base::VERBOSE);
+                } else {
+                    android::base::SetMinimumLogSeverity(android::base::DEBUG);
+                }
                 break;
             default:
-                std::cerr << "Unrecognized option: " << opt << std::endl;
+                LOG(ERROR) << "Unrecognized option: " << opt;
+                print_usage();
                 return EXIT_FAILURE;
         }
     }
@@ -143,39 +189,33 @@
         }
     }
 
-    if (verbose) {
-        std::cout << "mode is " << mode << std::endl;
-        std::cout << "verbose is " << verbose << std::endl;
-        std::cout << "mod_dirs is: " << android::base::Join(mod_dirs, " ") << std::endl;
-        std::cout << "modules is: " << android::base::Join(modules, " ") << std::endl;
-        std::cout << "module parameters is: " << android::base::Join(module_parameters, " ")
-                  << std::endl;
-    }
+    LOG(DEBUG) << "mode is " << mode;
+    LOG(DEBUG) << "mod_dirs is: " << android::base::Join(mod_dirs, " ");
+    LOG(DEBUG) << "modules is: " << android::base::Join(modules, " ");
+    LOG(DEBUG) << "module parameters is: " << android::base::Join(module_parameters, " ");
 
     if (modules.empty()) {
         if (mode == ListModulesMode) {
             // emulate toybox modprobe list with no pattern (list all)
             modules.emplace_back("*");
         } else {
-            std::cerr << "No modules given." << std::endl;
+            LOG(ERROR) << "No modules given.";
             print_usage();
             return EXIT_FAILURE;
         }
     }
     if (mod_dirs.empty()) {
-        std::cerr << "No module configuration directories given." << std::endl;
+        LOG(ERROR) << "No module configuration directories given.";
         print_usage();
         return EXIT_FAILURE;
     }
     if (parameter_count && modules.size() > 1) {
-        std::cerr << "Only one module may be loaded when specifying module parameters."
-                  << std::endl;
+        LOG(ERROR) << "Only one module may be loaded when specifying module parameters.";
         print_usage();
         return EXIT_FAILURE;
     }
 
     Modprobe m(mod_dirs);
-    m.EnableVerbose(verbose);
     if (blocklist) {
         m.EnableBlocklist(true);
     }
@@ -184,19 +224,19 @@
         switch (mode) {
             case AddModulesMode:
                 if (!m.LoadWithAliases(module, true, module_parameters)) {
-                    std::cerr << "Failed to load module " << module << std::endl;
+                    PLOG(ERROR) << "Failed to load module " << module;
                     rv = EXIT_FAILURE;
                 }
                 break;
             case RemoveModulesMode:
                 if (!m.Remove(module)) {
-                    std::cerr << "Failed to remove module " << module << std::endl;
+                    PLOG(ERROR) << "Failed to remove module " << module;
                     rv = EXIT_FAILURE;
                 }
                 break;
             case ListModulesMode: {
                 std::vector<std::string> list = m.ListModules(module);
-                std::cout << android::base::Join(list, "\n") << std::endl;
+                LOG(INFO) << android::base::Join(list, "\n");
                 break;
             }
             case ShowDependenciesMode: {
@@ -207,17 +247,17 @@
                     rv = EXIT_FAILURE;
                     break;
                 }
-                std::cout << "Dependencies for " << module << ":" << std::endl;
-                std::cout << "Soft pre-dependencies:" << std::endl;
-                std::cout << android::base::Join(pre_deps, "\n") << std::endl;
-                std::cout << "Hard dependencies:" << std::endl;
-                std::cout << android::base::Join(deps, "\n") << std::endl;
-                std::cout << "Soft post-dependencies:" << std::endl;
-                std::cout << android::base::Join(post_deps, "\n") << std::endl;
+                LOG(INFO) << "Dependencies for " << module << ":";
+                LOG(INFO) << "Soft pre-dependencies:";
+                LOG(INFO) << android::base::Join(pre_deps, "\n");
+                LOG(INFO) << "Hard dependencies:";
+                LOG(INFO) << android::base::Join(deps, "\n");
+                LOG(INFO) << "Soft post-dependencies:";
+                LOG(INFO) << android::base::Join(post_deps, "\n");
                 break;
             }
             default:
-                std::cerr << "Bad mode" << std::endl;
+                LOG(ERROR) << "Bad mode";
                 rv = EXIT_FAILURE;
         }
     }