Merge "Update OWNERS files"
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index fb07840..379cf92 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -20,15 +20,19 @@
 #include <sys/stat.h>
 #include <sys/wait.h>
 
+#include <fstream>
 #include <sstream>
 
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
 #include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
 #include <libdm/dm.h>
 #include <selinux/android.h>
 
 #include <apex_file_repository.h>
+#include <apex_constants.h>
 #include <apexd.h>
 
 #include "installd_constants.h"
@@ -77,6 +81,22 @@
     return apex::GetActivePackages();
 }
 
+static void CreateApexInfoList(const std::vector<apex::ApexFile>& apex_files) {
+    // Setup the apex-info-list.xml file
+    const std::string apex_info_file = std::string(apex::kApexRoot) + "/" + apex::kApexInfoList;
+    std::fstream xml(apex_info_file.c_str(), std::ios::out | std::ios::trunc);
+    if (!xml.is_open()) {
+        PLOG(ERROR) << "Failed to open " << apex_info_file;
+        exit(216);
+    }
+
+    // we do not care about inactive apexs
+    std::vector<apex::ApexFile> inactive;
+    apex::CollectApexInfoList(xml, apex_files, inactive);
+    xml.flush();
+    xml.close();
+}
+
 static void DeactivateApexPackages(const std::vector<apex::ApexFile>& active_packages) {
     for (const apex::ApexFile& apex_file : active_packages) {
         const std::string& package_path = apex_file.GetPath();
@@ -185,6 +205,13 @@
     // want it for product APKs. Same notes as vendor above.
     TryExtraMount("product", arg[2], "/postinstall/product");
 
+    constexpr const char* kPostInstallLinkerconfig = "/postinstall/linkerconfig";
+    // Try to mount /postinstall/linkerconfig. we will set it up after performing the chroot
+    if (mount("tmpfs", kPostInstallLinkerconfig, "tmpfs", 0, nullptr) != 0) {
+        PLOG(ERROR) << "Failed to mount a tmpfs for " << kPostInstallLinkerconfig;
+        exit(215);
+    }
+
     // Setup APEX mount point and its security context.
     static constexpr const char* kPostinstallApexDir = "/postinstall/apex";
     // The following logic is similar to the one in system/core/rootdir/init.rc:
@@ -243,17 +270,37 @@
     // Try to mount APEX packages in "/apex" in the chroot dir. We need at least
     // the ART APEX, as it is required by otapreopt to run dex2oat.
     std::vector<apex::ApexFile> active_packages = ActivateApexPackages();
+    CreateApexInfoList(active_packages);
 
     // Check that an ART APEX has been activated; clean up and exit
     // early otherwise.
-    if (std::none_of(active_packages.begin(),
-                     active_packages.end(),
-                     [](const apex::ApexFile& package){
-                         return package.GetManifest().name() == "com.android.art";
-                     })) {
-        LOG(FATAL_WITHOUT_ABORT) << "No activated com.android.art APEX package.";
-        DeactivateApexPackages(active_packages);
-        exit(217);
+    static constexpr const std::string_view kRequiredApexs[] = {
+      "com.android.art",
+      "com.android.runtime",
+    };
+    for (std::string_view apex : kRequiredApexs) {
+        if (std::none_of(active_packages.begin(), active_packages.end(),
+                         [&](const apex::ApexFile& package) {
+                             return package.GetManifest().name() == apex;
+                         })) {
+            LOG(FATAL_WITHOUT_ABORT) << "No activated " << apex << " APEX package.";
+            DeactivateApexPackages(active_packages);
+            exit(217);
+        }
+    }
+
+    // Setup /linkerconfig. Doing it after the chroot means it doesn't need its own category
+    if (selinux_android_restorecon("/linkerconfig", 0) < 0) {
+        PLOG(ERROR) << "Failed to restorecon /linkerconfig";
+        exit(219);
+    }
+    std::vector<std::string> linkerconfig_cmd{"/apex/com.android.runtime/bin/linkerconfig",
+                                              "--target", "/linkerconfig"};
+    std::string linkerconfig_error_msg;
+    bool linkerconfig_exec_result = Exec(linkerconfig_cmd, &linkerconfig_error_msg);
+    if (!linkerconfig_exec_result) {
+        LOG(ERROR) << "Running linkerconfig failed: " << linkerconfig_error_msg;
+        exit(218);
     }
 
     // Now go on and run otapreopt.
diff --git a/libs/binder/rust/src/error.rs b/libs/binder/rust/src/error.rs
index 4492cf7..2598ebc 100644
--- a/libs/binder/rust/src/error.rs
+++ b/libs/binder/rust/src/error.rs
@@ -77,9 +77,7 @@
         e if e == ExceptionCode::ILLEGAL_ARGUMENT as i32 => ExceptionCode::ILLEGAL_ARGUMENT,
         e if e == ExceptionCode::NULL_POINTER as i32 => ExceptionCode::NULL_POINTER,
         e if e == ExceptionCode::ILLEGAL_STATE as i32 => ExceptionCode::ILLEGAL_STATE,
-        e if e == ExceptionCode::NETWORK_MAIN_THREAD as i32 => {
-            ExceptionCode::NETWORK_MAIN_THREAD
-        }
+        e if e == ExceptionCode::NETWORK_MAIN_THREAD as i32 => ExceptionCode::NETWORK_MAIN_THREAD,
         e if e == ExceptionCode::UNSUPPORTED_OPERATION as i32 => {
             ExceptionCode::UNSUPPORTED_OPERATION
         }
@@ -96,6 +94,16 @@
 /// Used in AIDL transactions to represent failed transactions.
 pub struct Status(*mut sys::AStatus);
 
+// Safety: The `AStatus` that the `Status` points to must have an entirely thread-safe API for the
+// duration of the `Status` object's lifetime. We ensure this by not allowing mutation of a `Status`
+// in Rust, and the NDK API says we're the owner of our `AStatus` objects so outside code should not
+// be mutating them underneath us.
+unsafe impl Sync for Status {}
+
+// Safety: `Status` always contains an owning pointer to a global, immutable, interned `AStatus`.
+// A thread-local `AStatus` would not be valid.
+unsafe impl Send for Status {}
+
 impl Status {
     /// Create a status object representing a successful transaction.
     pub fn ok() -> Self {