Merge changes I1b7d795a,I91d28982,Ia004b216,I93eca3eb,I6b91d837

* changes:
  Pass x0-x3 boot values to Rust main function.
  Load pvmfw as pVM firmware rather than bootloader.
  Add a heap allocator.
  Test BSS and data sections.
  Print addresses.
diff --git a/compos/aidl/com/android/compos/ICompOsService.aidl b/compos/aidl/com/android/compos/ICompOsService.aidl
index 48a46b1..9cf99be 100644
--- a/compos/aidl/com/android/compos/ICompOsService.aidl
+++ b/compos/aidl/com/android/compos/ICompOsService.aidl
@@ -19,6 +19,18 @@
 /** {@hide} */
 interface ICompOsService {
     /**
+     * Initializes system properties. ART expects interesting properties that have to be passed from
+     * Android. The API client should call this method once with all desired properties, since once
+     * the call completes, the service is considered initialized and cannot be re-initialized again.
+     *
+     * <p>If the initialization failed, Microdroid may already have some properties set. It is up to
+     * the service to reject further calls by the client.
+     *
+     * <p>The service may reject unrecognized names, but it does not interpret values.
+     */
+    void initializeSystemProperties(in String[] names, in String[] values);
+
+    /**
      * What type of compilation to perform.
      */
     @Backing(type="int")
diff --git a/compos/common/binder.rs b/compos/common/binder.rs
index ae857e0..4935b80 100644
--- a/compos/common/binder.rs
+++ b/compos/common/binder.rs
@@ -16,7 +16,6 @@
 
 //! Helper for converting Error types to what Binder expects
 
-use anyhow::Result;
 use binder::{ExceptionCode, Result as BinderResult};
 use binder_common::new_binder_exception;
 use log::warn;
diff --git a/compos/common/odrefresh.rs b/compos/common/odrefresh.rs
index 390e50c..2d7635b 100644
--- a/compos/common/odrefresh.rs
+++ b/compos/common/odrefresh.rs
@@ -35,6 +35,10 @@
 /// The directory under ODREFRESH_OUTPUT_ROOT_DIR where the current (active) artifacts are stored
 pub const CURRENT_ARTIFACTS_SUBDIR: &str = "dalvik-cache";
 
+/// Prefixes of system properties that are interested to odrefresh and dex2oat.
+const ALLOWLIST_SYSTEM_PROPERTY_PREFIXES: &[&str] =
+    &["dalvik.vm.", "ro.dalvik.vm.", "persist.device_config.runtime_native_boot."];
+
 // The highest "standard" exit code defined in sysexits.h (as EX__MAX); odrefresh error codes
 // start above here to avoid clashing.
 // TODO: What if this changes?
@@ -63,3 +67,13 @@
             .ok_or_else(|| anyhow!("Unexpected odrefresh exit code: {}", exit_code))
     }
 }
+
+/// Returns whether the system property name is interesting to odrefresh and dex2oat.
+pub fn is_system_property_interesting(name: &str) -> bool {
+    for prefix in ALLOWLIST_SYSTEM_PROPERTY_PREFIXES {
+        if name.starts_with(prefix) {
+            return true;
+        }
+    }
+    false
+}
diff --git a/compos/composd/src/odrefresh_task.rs b/compos/composd/src/odrefresh_task.rs
index e06e5fe..51e866f 100644
--- a/compos/composd/src/odrefresh_task.rs
+++ b/compos/composd/src/odrefresh_task.rs
@@ -27,7 +27,9 @@
 use compos_aidl_interface::aidl::com::android::compos::ICompOsService::{
     CompilationMode::CompilationMode, ICompOsService,
 };
-use compos_common::odrefresh::{ExitCode, ODREFRESH_OUTPUT_ROOT_DIR};
+use compos_common::odrefresh::{
+    is_system_property_interesting, ExitCode, ODREFRESH_OUTPUT_ROOT_DIR,
+};
 use log::{error, info, warn};
 use rustutils::system_properties;
 use std::fs::{remove_dir_all, File, OpenOptions};
@@ -124,6 +126,16 @@
     compilation_mode: CompilationMode,
     target_dir_name: &str,
 ) -> Result<ExitCode> {
+    let mut names = Vec::new();
+    let mut values = Vec::new();
+    system_properties::foreach(|name, value| {
+        if is_system_property_interesting(name) {
+            names.push(name.to_owned());
+            values.push(value.to_owned());
+        }
+    })?;
+    service.initializeSystemProperties(&names, &values).context("initialize system properties")?;
+
     let output_root = Path::new(ODREFRESH_OUTPUT_ROOT_DIR);
 
     // We need to remove the target directory because odrefresh running in compos will create it
diff --git a/compos/src/compsvc.rs b/compos/src/compsvc.rs
index e21aa7d..91415bb 100644
--- a/compos/src/compsvc.rs
+++ b/compos/src/compsvc.rs
@@ -19,9 +19,14 @@
 //! actual compiler.
 
 use anyhow::{bail, Context, Result};
+use binder_common::new_binder_exception;
+use log::error;
+use rustutils::system_properties;
 use std::default::Default;
 use std::fs::read_dir;
+use std::iter::zip;
 use std::path::{Path, PathBuf};
+use std::sync::RwLock;
 
 use crate::artifact_signer::ArtifactSigner;
 use crate::compilation::{odrefresh, OdrefreshContext};
@@ -29,25 +34,73 @@
 use compos_aidl_interface::aidl::com::android::compos::ICompOsService::{
     BnCompOsService, CompilationMode::CompilationMode, ICompOsService,
 };
-use compos_aidl_interface::binder::{BinderFeatures, Interface, Result as BinderResult, Strong};
+use compos_aidl_interface::binder::{
+    BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Strong,
+};
 use compos_common::binder::to_binder_result;
-use compos_common::odrefresh::ODREFRESH_PATH;
+use compos_common::odrefresh::{is_system_property_interesting, ODREFRESH_PATH};
 
 const AUTHFS_SERVICE_NAME: &str = "authfs_service";
 
 /// Constructs a binder object that implements ICompOsService.
 pub fn new_binder() -> Result<Strong<dyn ICompOsService>> {
-    let service = CompOsService { odrefresh_path: PathBuf::from(ODREFRESH_PATH) };
+    let service = CompOsService {
+        odrefresh_path: PathBuf::from(ODREFRESH_PATH),
+        initialized: RwLock::new(None),
+    };
     Ok(BnCompOsService::new_binder(service, BinderFeatures::default()))
 }
 
 struct CompOsService {
     odrefresh_path: PathBuf,
+
+    /// A locked protected tri-state.
+    ///  * None: uninitialized
+    ///  * Some(true): initialized successfully
+    ///  * Some(false): failed to initialize
+    initialized: RwLock<Option<bool>>,
 }
 
 impl Interface for CompOsService {}
 
 impl ICompOsService for CompOsService {
+    fn initializeSystemProperties(&self, names: &[String], values: &[String]) -> BinderResult<()> {
+        let mut initialized = self.initialized.write().unwrap();
+        if initialized.is_some() {
+            return Err(new_binder_exception(
+                ExceptionCode::ILLEGAL_STATE,
+                format!("Already initialized: {:?}", initialized),
+            ));
+        }
+        *initialized = Some(false);
+
+        if names.len() != values.len() {
+            return Err(new_binder_exception(
+                ExceptionCode::ILLEGAL_ARGUMENT,
+                format!(
+                    "Received inconsistent number of keys ({}) and values ({})",
+                    names.len(),
+                    values.len()
+                ),
+            ));
+        }
+        for (name, value) in zip(names, values) {
+            if !is_system_property_interesting(name) {
+                return Err(new_binder_exception(
+                    ExceptionCode::ILLEGAL_ARGUMENT,
+                    format!("Received invalid system property {}", &name),
+                ));
+            }
+            let result = system_properties::write(name, value);
+            if result.is_err() {
+                error!("Failed to setprop {}", &name);
+                return to_binder_result(result);
+            }
+        }
+        *initialized = Some(true);
+        Ok(())
+    }
+
     fn odrefresh(
         &self,
         compilation_mode: CompilationMode,
@@ -58,6 +111,14 @@
         zygote_arch: &str,
         system_server_compiler_filter: &str,
     ) -> BinderResult<i8> {
+        let initialized = *self.initialized.read().unwrap();
+        if !initialized.unwrap_or(false) {
+            return Err(new_binder_exception(
+                ExceptionCode::ILLEGAL_STATE,
+                "Service has not been initialized",
+            ));
+        }
+
         let context = to_binder_result(OdrefreshContext::new(
             compilation_mode,
             system_dir_fd,
diff --git a/microdroid/README.md b/microdroid/README.md
index a652139..681c23a 100644
--- a/microdroid/README.md
+++ b/microdroid/README.md
@@ -7,7 +7,7 @@
 
 ## Prerequisites
 
-Any 64-bit target (either x86_64 or arm64) is supported. 32-bit target is not
+Any 64-bit target (either x86\_64 or arm64) is supported. 32-bit target is not
 supported. Note that we currently don't support user builds; only userdebug
 builds are supported.
 
@@ -36,7 +36,7 @@
 adb reboot
 ```
 
-If your target is x86_64 (e.g. `aosp_cf_x86_64_phone`), replace `aosp_arm64`
+If your target is x86\_64 (e.g. `aosp_cf_x86_64_phone`), replace `aosp_arm64`
 with `aosp_x86_64`.
 
 ## Building an app
diff --git a/tests/hostside/AndroidTest.xml b/tests/hostside/AndroidTest.xml
index 79428ce..5c3e5d1 100644
--- a/tests/hostside/AndroidTest.xml
+++ b/tests/hostside/AndroidTest.xml
@@ -19,6 +19,12 @@
     <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+        <!-- Permission checks are bypassed if shell is root -->
+        <option name="force-root" value="false"/>
+    </target_preparer>
+
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
         <option name="jar" value="MicrodroidHostTestCases.jar" />
     </test>
diff --git a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
index 9ee95c0..e2d4be1 100644
--- a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
+++ b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
@@ -478,6 +478,7 @@
     @Test
     public void testCustomVirtualMachinePermission()
             throws DeviceNotAvailableException, IOException, JSONException {
+        assumeTrue(isProtectedVmSupported());
         CommandRunner android = new CommandRunner(getDevice());
 
         // Pull etc/microdroid.json