Merge changes from topic "lmkd-vm-integration"

* changes:
  Implement a memory reclaim microdroid benchmark test
  Plumb onTrimMemory app callback to virtualizationservice
diff --git a/microdroid/init.rc b/microdroid/init.rc
index 7d04557..310cf2b 100644
--- a/microdroid/init.rc
+++ b/microdroid/init.rc
@@ -45,7 +45,7 @@
 
     setprop ro.debuggable ${ro.boot.microdroid.debuggable:-0}
 
-on property:dev.bootcomplete=1
+on property:microdroid_manager.init_done=1
     # Stop ueventd to save memory
     stop ueventd
 
diff --git a/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl b/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl
index f8e7d34..3859785 100644
--- a/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl
+++ b/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl
@@ -27,6 +27,12 @@
     /** Path to the APK contents path. */
     const String VM_APK_CONTENTS_PATH = "/mnt/apk";
 
+    /**
+     * Path to the encrypted storage. Note the path will not exist if encrypted storage
+     * is not enabled.
+     */
+    const String ENCRYPTEDSTORE_MOUNTPOINT = "/mnt/encryptedstore";
+
     /** Notifies that the payload is ready to serve. */
     void notifyPayloadReady();
 
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 4f94bb4..0e45461 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -29,6 +29,7 @@
 use android_system_virtualization_payload::aidl::android::system::virtualization::payload::IVmPayloadService::{
     VM_APK_CONTENTS_PATH,
     VM_PAYLOAD_SERVICE_SOCKET_NAME,
+    ENCRYPTEDSTORE_MOUNTPOINT,
 };
 use anyhow::{anyhow, bail, ensure, Context, Error, Result};
 use apkverify::{get_public_key_der, verify, V4Signature};
@@ -86,7 +87,6 @@
 const ENCRYPTEDSTORE_BIN: &str = "/system/bin/encryptedstore";
 const ENCRYPTEDSTORE_KEY_IDENTIFIER: &str = "encryptedstore_key";
 const ENCRYPTEDSTORE_KEYSIZE: u32 = 32;
-const ENCRYPTEDSTORE_MOUNTPOINT: &str = "/mnt/encryptedstore";
 
 #[derive(thiserror::Error, Debug)]
 enum MicrodroidError {
@@ -433,12 +433,17 @@
 
     register_vm_payload_service(allow_restricted_apis, service.clone(), dice_context)?;
 
+    // Wait for encryptedstore to finish mounting the storage (if enabled) before setting
+    // microdroid_manager.init_done. Reason is init stops uneventd after that.
+    // Encryptedstore, however requires ueventd
     if let Some(mut child) = encryptedstore_child {
         let exitcode = child.wait().context("Wait for encryptedstore child")?;
         ensure!(exitcode.success(), "Unable to prepare encrypted storage. Exitcode={}", exitcode);
     }
 
     wait_for_property_true("dev.bootcomplete").context("failed waiting for dev.bootcomplete")?;
+    system_properties::write("microdroid_manager.init_done", "1")
+        .context("set microdroid_manager.init_done")?;
     info!("boot completed, time to run payload");
     exec_task(task, service).context("Failed to run payload")
 }
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
index 11b3e84..231fc7b 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
@@ -407,20 +407,26 @@
     }
 
     @Test
-    @Ignore("b/245081929")
     @CddTest(requirements = {"9.17/C-2-1", "9.17/C-2-2", "9.17/C-2-6"})
-    public void testBootFailsWhenProtectedVmStartsWithImagesSignedWithDifferentKey()
-            throws Exception {
+    public void protectedVmWithImageSignedWithDifferentKeyRunsPvmfw() throws Exception {
+        // Arrange
         boolean protectedVm = true;
         assumeTrue(
                 "Skip if protected VMs are not supported",
                 getAndroidDevice().supportsMicrodroid(protectedVm));
-
         File key = findTestFile("test.com.android.virt.pem");
-        Map<String, File> keyOverrides = Map.of();
-        VmInfo vmInfo = runMicrodroidWithResignedImages(key, keyOverrides, protectedVm);
+
+        // Act
+        VmInfo vmInfo =
+                runMicrodroidWithResignedImages(key, /*keyOverrides=*/ Map.of(), protectedVm);
+
+        // Asserts
         vmInfo.mProcess.waitFor(5L, TimeUnit.SECONDS);
-        assertThat(getDevice().pullFileContents(CONSOLE_PATH), containsString("pvmfw boot failed"));
+        String consoleLog = getDevice().pullFileContents(CONSOLE_PATH);
+        assertWithMessage("pvmfw should start").that(consoleLog).contains("pVM firmware");
+        // TODO(b/256148034): Asserts that pvmfw run fails when this verification is implemented.
+        // Also rename the test.
+        vmInfo.mProcess.destroy();
     }
 
     // TODO(b/245277660): Resigning the system/vendor image changes the vbmeta hash.
diff --git a/virtualizationservice/src/crosvm.rs b/virtualizationservice/src/crosvm.rs
index e535258..0fdc293 100644
--- a/virtualizationservice/src/crosvm.rs
+++ b/virtualizationservice/src/crosvm.rs
@@ -22,12 +22,13 @@
 use libc::{sysconf, _SC_CLK_TCK};
 use log::{debug, error, info};
 use semver::{Version, VersionReq};
-use nix::{fcntl::OFlag, unistd::pipe2};
+use nix::{fcntl::OFlag, unistd::pipe2, unistd::Uid, unistd::User};
 use regex::{Captures, Regex};
 use rustutils::system_properties;
 use shared_child::SharedChild;
 use std::borrow::Cow;
 use std::cmp::max;
+use std::fmt;
 use std::fs::{read_to_string, remove_dir_all, File};
 use std::io::{self, Read};
 use std::mem;
@@ -255,6 +256,19 @@
     payload_state: Mutex<PayloadState>,
     /// Represents the condition that payload_state was updated
     payload_state_updated: Condvar,
+    /// The human readable name of requester_uid
+    requester_uid_name: String,
+}
+
+impl fmt::Display for VmInstance {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let adj = if self.protected { "Protected" } else { "Non-protected" };
+        write!(
+            f,
+            "{} virtual machine \"{}\" (owner: {}, cid: {})",
+            adj, self.name, self.requester_uid_name, self.cid
+        )
+    }
 }
 
 impl VmInstance {
@@ -270,7 +284,11 @@
         let cid = config.cid;
         let name = config.name.clone();
         let protected = config.protected;
-        Ok(VmInstance {
+        let requester_uid_name = User::from_uid(Uid::from_raw(requester_uid))
+            .ok()
+            .flatten()
+            .map_or_else(|| format!("{}", requester_uid), |u| u.name);
+        let instance = VmInstance {
             vm_state: Mutex::new(VmState::NotStarted { config }),
             vm_context,
             cid,
@@ -285,7 +303,10 @@
             vm_metric: Mutex::new(Default::default()),
             payload_state: Mutex::new(PayloadState::Starting),
             payload_state_updated: Condvar::new(),
-        })
+            requester_uid_name,
+        };
+        info!("{} created", &instance);
+        Ok(instance)
     }
 
     /// Starts an instance of `crosvm` to manage the VM. The `crosvm` instance will be killed when
@@ -293,7 +314,11 @@
     pub fn start(self: &Arc<Self>) -> Result<(), Error> {
         let mut vm_metric = self.vm_metric.lock().unwrap();
         vm_metric.start_timestamp = Some(SystemTime::now());
-        self.vm_state.lock().unwrap().start(self.clone())
+        let ret = self.vm_state.lock().unwrap().start(self.clone());
+        if ret.is_ok() {
+            info!("{} started", &self);
+        }
+        ret.with_context(|| format!("{} failed to start", &self))
     }
 
     /// Monitors the exit of the VM (i.e. termination of the `child` process). When that happens,
@@ -317,6 +342,7 @@
         *vm_state = VmState::Dead;
         // Ensure that the mutex is released before calling the callbacks.
         drop(vm_state);
+        info!("{} exited", &self);
 
         // Read the pipe to see if any failure reason is written
         let mut failure_reason = String::new();
diff --git a/vm_payload/src/api.rs b/vm_payload/src/api.rs
index a79c0bb..28b440e 100644
--- a/vm_payload/src/api.rs
+++ b/vm_payload/src/api.rs
@@ -18,7 +18,7 @@
 #![warn(unsafe_op_in_unsafe_fn)]
 
 use android_system_virtualization_payload::aidl::android::system::virtualization::payload::IVmPayloadService::{
-    IVmPayloadService, VM_PAYLOAD_SERVICE_SOCKET_NAME, VM_APK_CONTENTS_PATH};
+    ENCRYPTEDSTORE_MOUNTPOINT, IVmPayloadService, VM_PAYLOAD_SERVICE_SOCKET_NAME, VM_APK_CONTENTS_PATH};
 use anyhow::{ensure, bail, Context, Result};
 use binder::{Strong, unstable_api::{AIBinder, new_spibinder}};
 use lazy_static::lazy_static;
@@ -28,6 +28,7 @@
 use std::ffi::CString;
 use std::fmt::Debug;
 use std::os::raw::{c_char, c_void};
+use std::path::Path;
 use std::ptr;
 use std::sync::{Mutex, atomic::{AtomicBool, Ordering}};
 
@@ -35,6 +36,8 @@
     static ref VM_APK_CONTENTS_PATH_C: CString =
         CString::new(VM_APK_CONTENTS_PATH).expect("CString::new failed");
     static ref PAYLOAD_CONNECTION: Mutex<Option<Strong<dyn IVmPayloadService>>> = Mutex::default();
+    static ref VM_ENCRYPTED_STORAGE_PATH_C: CString =
+        CString::new(ENCRYPTEDSTORE_MOUNTPOINT).expect("CString::new failed");
 }
 
 static ALREADY_NOTIFIED: AtomicBool = AtomicBool::new(false);
@@ -249,12 +252,15 @@
 /// Gets the path to the APK contents.
 #[no_mangle]
 pub extern "C" fn AVmPayload_getApkContentsPath() -> *const c_char {
-    (*VM_APK_CONTENTS_PATH_C).as_ptr()
+    VM_APK_CONTENTS_PATH_C.as_ptr()
 }
 
 /// Gets the path to the VM's encrypted storage.
 #[no_mangle]
 pub extern "C" fn AVmPayload_getEncryptedStoragePath() -> *const c_char {
-    // TODO(b/254454578): Return a real path if storage is present
-    ptr::null()
+    if Path::new(ENCRYPTEDSTORE_MOUNTPOINT).exists() {
+        VM_ENCRYPTED_STORAGE_PATH_C.as_ptr()
+    } else {
+        ptr::null()
+    }
 }