Merge "Replace "apex_inherit" min_sdk_version"
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 0f2a75a..6349c20 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -116,8 +116,7 @@
 
     // For non-A/B devices prefer cache backing storage if
     // kPreferCacheBackingStorageProp property set.
-    if (!IsABDevice() &&
-        android::base::GetBoolProperty(kPreferCacheBackingStorageProp, false) &&
+    if (!IsABDevice() && android::base::GetBoolProperty(kPreferCacheBackingStorageProp, false) &&
         android::base::GetIntProperty("ro.vendor.api_level", -1) < __ANDROID_API_T__) {
         return {kCacheMountPoint, kScratchMountPoint};
     }
@@ -332,8 +331,14 @@
     return major > 5 || (major == 5 && minor >= 15);
 }
 
+const std::string fs_mgr_mount_point(const std::string& mount_point) {
+    if ("/"s != mount_point) return mount_point;
+    return "/system";
+}
+
 // default options for mount_point, returns empty string for none available.
-std::string fs_mgr_get_overlayfs_options(const std::string& mount_point) {
+std::string fs_mgr_get_overlayfs_options(const FstabEntry& entry) {
+    const auto mount_point = fs_mgr_mount_point(entry.mount_point);
     auto candidate = fs_mgr_get_overlayfs_candidate(mount_point);
     if (candidate.empty()) return "";
     auto ret = kLowerdirOption + mount_point + "," + kUpperdirOption + candidate + kUpperName +
@@ -344,14 +349,14 @@
     if (KernelSupportsUserXattrs()) {
         ret += ",userxattr";
     }
+    for (const auto& flag : android::base::Split(entry.fs_options, ",")) {
+        if (android::base::StartsWith(flag, "context=")) {
+            ret += "," + flag;
+        }
+    }
     return ret;
 }
 
-const std::string fs_mgr_mount_point(const std::string& mount_point) {
-    if ("/"s != mount_point) return mount_point;
-    return "/system";
-}
-
 constexpr char kOverlayfsFileContext[] = "u:object_r:overlayfs_file:s0";
 
 class AutoSetFsCreateCon final {
@@ -710,8 +715,9 @@
     return info;
 }
 
-bool fs_mgr_overlayfs_mount(const std::string& mount_point) {
-    auto options = fs_mgr_get_overlayfs_options(mount_point);
+bool fs_mgr_overlayfs_mount(const FstabEntry& entry) {
+    const auto mount_point = fs_mgr_mount_point(entry.mount_point);
+    const auto options = fs_mgr_get_overlayfs_options(entry);
     if (options.empty()) return false;
 
     auto retval = true;
@@ -1346,7 +1352,7 @@
             scratch_can_be_mounted = false;
             TryMountScratch();
         }
-        ret &= fs_mgr_overlayfs_mount(mount_point);
+        ret &= fs_mgr_overlayfs_mount(entry);
     }
     return ret;
 }
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index 0624fe0..deffae1 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -20,6 +20,7 @@
 #include <sys/ioctl.h>
 #include <sys/sysmacros.h>
 #include <sys/types.h>
+#include <sys/utsname.h>
 
 #include <chrono>
 #include <functional>
@@ -711,5 +712,28 @@
     return dm_block_devices;
 }
 
+bool DeviceMapper::CreatePlaceholderDevice(const std::string& name) {
+    if (!CreateEmptyDevice(name)) {
+        return false;
+    }
+
+    struct utsname uts;
+    unsigned int major, minor;
+    if (uname(&uts) != 0 || sscanf(uts.release, "%u.%u", &major, &minor) != 2) {
+        LOG(ERROR) << "Could not parse the kernel version from uname";
+        return true;
+    }
+
+    // On Linux 5.15+, there is no uevent until DM_TABLE_LOAD.
+    if (major > 5 || (major == 5 && minor >= 15)) {
+        DmTable table;
+        table.Emplace<DmTargetError>(0, 1);
+        if (!LoadTable(name, table)) {
+            return false;
+        }
+    }
+    return true;
+}
+
 }  // namespace dm
 }  // namespace android
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index f17ae13..dbef8f9 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -292,6 +292,12 @@
     // Returns mapping <partition-name, /dev/block/dm-x>
     std::map<std::string, std::string> FindDmPartitions();
 
+    // Create a placeholder device. This is useful for ensuring that a uevent is in the pipeline,
+    // to reduce the amount of time a future WaitForDevice will block. On kernels < 5.15, this
+    // simply calls CreateEmptyDevice. On 5.15 and higher, it also loads (but does not activate)
+    // a placeholder table containing dm-error.
+    bool CreatePlaceholderDevice(const std::string& name);
+
   private:
     // Maximum possible device mapper targets registered in the kernel.
     // This is only used to read the list of targets from kernel so we allocate
diff --git a/fs_mgr/tests/vts_fs_test.cpp b/fs_mgr/tests/vts_fs_test.cpp
index b8b34e2..bb2ceb9 100644
--- a/fs_mgr/tests/vts_fs_test.cpp
+++ b/fs_mgr/tests/vts_fs_test.cpp
@@ -66,6 +66,14 @@
 
     int vsr_level = GetVsrLevel();
 
+    std::vector<std::string> must_be_f2fs;
+    if (vsr_level >= __ANDROID_API_T__) {
+        must_be_f2fs.emplace_back("/data");
+    }
+    if (vsr_level >= __ANDROID_API_U__) {
+        must_be_f2fs.emplace_back("/metadata");
+    }
+
     for (const auto& entry : fstab) {
         std::string parent_bdev = entry.blk_device;
         while (true) {
@@ -99,15 +107,15 @@
         }
 
         if (entry.flags & MS_RDONLY) {
-            std::vector<std::string> allowed = {"erofs", "ext4"};
-            if (vsr_level == __ANDROID_API_T__) {
-                allowed.emplace_back("f2fs");
-            }
+            std::vector<std::string> allowed = {"erofs", "ext4", "f2fs"};
 
             EXPECT_NE(std::find(allowed.begin(), allowed.end(), entry.fs_type), allowed.end())
                     << entry.mount_point;
         } else {
-            EXPECT_NE(entry.fs_type, "ext4") << entry.mount_point;
+            if (std::find(must_be_f2fs.begin(), must_be_f2fs.end(), entry.mount_point) !=
+                must_be_f2fs.end()) {
+                EXPECT_EQ(entry.fs_type, "f2fs") << entry.mount_point;
+            }
         }
     }
 }
diff --git a/init/README.md b/init/README.md
index 6596528..957eb9e 100644
--- a/init/README.md
+++ b/init/README.md
@@ -162,6 +162,17 @@
     setprop e 1
     setprop f 2
 
+If the property `true` wasn't `true` when the `boot` was triggered, then the
+order of the commands executed will be:
+
+    setprop a 1
+    setprop b 2
+    setprop e 1
+    setprop f 2
+
+If the property `true` becomes `true` *AFTER* `boot` was triggered, nothing will
+be executed. The condition `boot && property:true=true` will be evaluated to
+false because the `boot` trigger is a past event.
 
 Services
 --------
@@ -184,8 +195,10 @@
   capability without the "CAP\_" prefix, like "NET\_ADMIN" or "SETPCAP". See
   http://man7.org/linux/man-pages/man7/capabilities.7.html for a list of Linux
   capabilities.
-  If no capabilities are provided, then all capabilities are removed from this service, even if it
-  runs as root.
+  If no capabilities are provided, then behaviour depends on the user the service runs under:
+    * if it's root, then the service will run with all the capabitilies (note: whether the
+        service can actually use them is controlled by selinux);
+    * otherwise all capabilities will be dropped.
 
 `class <name> [ <name>\* ]`
 > Specify class names for the service.  All services in a
@@ -399,7 +412,7 @@
   using this new mechanism, processes can use the user option to
   select their desired uid without ever running as root.
   As of Android O, processes can also request capabilities directly in their .rc
-  files. See the "capabilities" option below.
+  files. See the "capabilities" option above.
 
 `writepid <file> [ <file>\* ]`
 > Write the child's pid to the given files when it forks. Meant for
@@ -433,7 +446,9 @@
 
 For example:
 `on boot && property:a=b` defines an action that is only executed when
-the 'boot' event trigger happens and the property a equals b.
+the 'boot' event trigger happens and the property a equals b at the moment. This
+will NOT be executed when the property a transitions to value b after the `boot`
+event was triggered.
 
 `on property:a=b && property:c=d` defines an action that is executed
 at three times:
diff --git a/init/init_test.cpp b/init/init_test.cpp
index aea1cb3..18a08c7 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -194,13 +194,14 @@
 }
 
 TEST(init, StartConsole) {
-    if (access("/dev/console", F_OK) < 0) {
-        GTEST_SKIP() << "/dev/console not found";
+    if (GetProperty("ro.build.type", "") == "user") {
+        GTEST_SKIP() << "Must run on userdebug/eng builds. b/262090304";
+        return;
     }
     std::string init_script = R"init(
 service console /system/bin/sh
     class core
-    console console
+    console null
     disabled
     user root
     group root shell log readproc
diff --git a/init/service.cpp b/init/service.cpp
index 78bf42f..d495b91 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -866,6 +866,8 @@
 
     if ((how != SVC_DISABLED) && (how != SVC_RESET) && (how != SVC_RESTART)) {
         // An illegal flag: default to SVC_DISABLED.
+        LOG(ERROR) << "service '" << name_ << "' requested unknown flag " << how
+                   << ", defaulting to disabling it.";
         how = SVC_DISABLED;
     }
 
diff --git a/libcutils/ashmem_test.cpp b/libcutils/ashmem_test.cpp
index fb657f6..d158427 100644
--- a/libcutils/ashmem_test.cpp
+++ b/libcutils/ashmem_test.cpp
@@ -75,7 +75,7 @@
     unique_fd fd;
     ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
 
-    void *region1;
+    void* region1 = nullptr;
     ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ | PROT_WRITE, &region1));
 
     memcpy(region1, &data, size);
@@ -97,7 +97,7 @@
     unique_fd fd;
     ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
 
-    void *region1;
+    void* region1 = nullptr;
     ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ | PROT_WRITE, &region1));
 
     memcpy(region1, &data, size);
@@ -131,7 +131,7 @@
 
 TEST(AshmemTest, FileOperationsTest) {
     unique_fd fd;
-    void* region;
+    void* region = nullptr;
 
     // Allocate a 4-page buffer, but leave page-sized holes on either side
     constexpr size_t size = PAGE_SIZE * 4;
@@ -246,7 +246,7 @@
     unique_fd fd[nRegions];
     for (int i = 0; i < nRegions; i++) {
         ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd[i], PROT_READ | PROT_WRITE));
-        void *region;
+        void* region = nullptr;
         ASSERT_NO_FATAL_FAILURE(TestMmap(fd[i], size, PROT_READ | PROT_WRITE, &region));
         memcpy(region, &data, size);
         ASSERT_EQ(0, memcmp(region, &data, size));
diff --git a/libprocessgroup/OWNERS b/libprocessgroup/OWNERS
index 8ebb8cc..d5aa721 100644
--- a/libprocessgroup/OWNERS
+++ b/libprocessgroup/OWNERS
@@ -1,2 +1,4 @@
-ccross@google.com
+# Bug component: 1293033
 surenb@google.com
+tjmercier@google.com
+carlosgalo@google.com
diff --git a/rootdir/init.rc b/rootdir/init.rc
index d8e6b55..55be31a 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -55,10 +55,11 @@
     # Read more in b/136247322
     write /sys/module/dm_verity/parameters/prefetch_cluster 0
 
-    # Generate ld.config.txt for early executed processes
-    exec -- /system/bin/bootstrap/linkerconfig --target /linkerconfig/bootstrap
+    # Generate empty ld.config.txt for early executed processes which rely on
+    # /system/lib libraries.
+    write /linkerconfig/bootstrap/ld.config.txt \#
+    write /linkerconfig/default/ld.config.txt \#
     chmod 644 /linkerconfig/bootstrap/ld.config.txt
-    copy /linkerconfig/bootstrap/ld.config.txt /linkerconfig/default/ld.config.txt
     chmod 644 /linkerconfig/default/ld.config.txt
 
     # Mount bootstrap linker configuration as current
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index 4ec59af..0b7ffb8 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -69,8 +69,8 @@
 # CDMA radio interface MUX
 /dev/ppp                  0660   radio      vpn
 
-/dev/kvm                  0600   system     system
-/dev/vhost-vsock          0600   system	    system
+/dev/kvm                  0666   root       root
+/dev/vhost-vsock          0666   root       root
 
 # sysfs properties
 /sys/devices/platform/trusty.*      trusty_version        0440  root   log
diff --git a/trusty/keymint/src/keymint_hal_main.rs b/trusty/keymint/src/keymint_hal_main.rs
index d2d5f27..cfa859f 100644
--- a/trusty/keymint/src/keymint_hal_main.rs
+++ b/trusty/keymint/src/keymint_hal_main.rs
@@ -14,7 +14,9 @@
 // limitations under the License.
 
 //! This module implements the HAL service for Keymint (Rust) in Trusty.
-use kmr_hal::{keymint, rpc, secureclock, send_hal_info, sharedsecret, SerializedChannel};
+use kmr_hal::{
+    extract_rsp, keymint, rpc, secureclock, send_hal_info, sharedsecret, SerializedChannel,
+};
 use log::{error, info};
 use std::{
     ffi::CString,
@@ -41,6 +43,7 @@
 struct TipcChannel(trusty::TipcChannel);
 
 impl SerializedChannel for TipcChannel {
+    const MAX_SIZE: usize = 4000;
     fn execute(&mut self, serialized_req: &[u8]) -> binder::Result<Vec<u8>> {
         self.0.send(serialized_req).map_err(|e| {
             binder::Status::new_exception(
@@ -54,21 +57,27 @@
                 ),
             )
         })?;
-        let mut recv_buf = Vec::new();
-        // TODO(b/253501976): cope with fragmentation of responses
-        self.0.recv(&mut recv_buf).map_err(|e| {
-            binder::Status::new_exception(
-                binder::ExceptionCode::TRANSACTION_FAILED,
-                Some(
-                    &CString::new(format!(
-                        "Failed to receive the response via tipc channel because of {:?}",
-                        e
-                    ))
-                    .unwrap(),
-                ),
-            )
-        })?;
-        Ok(recv_buf)
+        let mut expect_more_msgs = true;
+        let mut full_rsp = Vec::new();
+        while expect_more_msgs {
+            let mut recv_buf = Vec::new();
+            self.0.recv(&mut recv_buf).map_err(|e| {
+                binder::Status::new_exception(
+                    binder::ExceptionCode::TRANSACTION_FAILED,
+                    Some(
+                        &CString::new(format!(
+                            "Failed to receive the response via tipc channel because of {:?}",
+                            e
+                        ))
+                        .unwrap(),
+                    ),
+                )
+            })?;
+            let current_rsp_content;
+            (expect_more_msgs, current_rsp_content) = extract_rsp(&recv_buf)?;
+            full_rsp.extend_from_slice(current_rsp_content);
+        }
+        Ok(full_rsp)
     }
 }