Merge "[API] Add vm_payload API to get APK contents path"
diff --git a/microdroid/vm_payload/Android.bp b/microdroid/vm_payload/Android.bp
index dc314ce..eeca1c1 100644
--- a/microdroid/vm_payload/Android.bp
+++ b/microdroid/vm_payload/Android.bp
@@ -13,6 +13,7 @@
"libandroid_logger",
"libanyhow",
"libbinder_rs",
+ "liblazy_static",
"liblog_rust",
"librpcbinder_rs",
],
diff --git a/microdroid/vm_payload/include/vm_payload.h b/microdroid/vm_payload/include/vm_payload.h
index dc01662..2aeb44e 100644
--- a/microdroid/vm_payload/include/vm_payload.h
+++ b/microdroid/vm_payload/include/vm_payload.h
@@ -96,6 +96,17 @@
*/
bool AVmPayload_getDiceAttestationCdi(void *data, size_t size, size_t *total);
+/**
+ * Gets the path to the APK contents. It is a directory, under which are
+ * the unzipped contents of the APK containing the payload, all read-only
+ * but accessible to the payload.
+ *
+ * \return the path to the APK contents. The returned string should not be
+ * deleted or freed by the application. The string remains valid for the
+ * lifetime of the VM.
+ */
+const char *AVmPayload_getApkContentsPath(void);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/microdroid/vm_payload/src/vm_payload_service.rs b/microdroid/vm_payload/src/vm_payload_service.rs
index bec4fde..b0dd891 100644
--- a/microdroid/vm_payload/src/vm_payload_service.rs
+++ b/microdroid/vm_payload/src/vm_payload_service.rs
@@ -15,12 +15,19 @@
//! This module handles the interaction with virtual machine payload service.
use android_system_virtualization_payload::aidl::android::system::virtualization::payload::IVmPayloadService::{
- IVmPayloadService, VM_PAYLOAD_SERVICE_NAME};
+ IVmPayloadService, VM_PAYLOAD_SERVICE_NAME, VM_APK_CONTENTS_PATH};
use anyhow::{Context, Result};
use binder::{wait_for_interface, Strong, unstable_api::{AIBinder, new_spibinder}};
+use lazy_static::lazy_static;
use log::{error, info, Level};
use rpcbinder::run_vsock_rpc_server;
-use std::os::raw::c_void;
+use std::ffi::CString;
+use std::os::raw::{c_char, c_void};
+
+lazy_static! {
+ static ref VM_APK_CONTENTS_PATH_C: CString =
+ CString::new(VM_APK_CONTENTS_PATH).expect("CString::new failed");
+}
/// Notifies the host that the payload is ready.
/// Returns true if the notification succeeds else false.
@@ -185,6 +192,12 @@
}
}
+/// 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()
+}
+
fn try_get_dice_attestation_cdi() -> Result<Vec<u8>> {
get_vm_payload_service()?.getDiceAttestationCdi().context("Cannot get attestation CDI")
}
diff --git a/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl b/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl
index 4dd3db6..4823bb8 100644
--- a/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl
+++ b/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl
@@ -24,6 +24,9 @@
/** Name of the service IVmPayloadService. */
const String VM_PAYLOAD_SERVICE_NAME = "virtual_machine_payload_service";
+ /** Path to the APK contents path. */
+ const String VM_APK_CONTENTS_PATH = "/mnt/apk";
+
/** 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 e42f159..b8e85e7 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -33,6 +33,7 @@
VirtualMachineCpuStatus::VirtualMachineCpuStatus,
VirtualMachineMemStatus::VirtualMachineMemStatus,
};
+use android_system_virtualization_payload::aidl::android::system::virtualization::payload::IVmPayloadService::VM_APK_CONTENTS_PATH;
use anyhow::{anyhow, bail, ensure, Context, Error, Result};
use apkverify::{get_public_key_der, verify, V4Signature};
use binder::{ProcessState, Strong};
@@ -398,7 +399,7 @@
MountForExec::Allowed,
"fscontext=u:object_r:zipfusefs:s0,context=u:object_r:system_file:s0",
Path::new("/dev/block/mapper/microdroid-apk"),
- Path::new("/mnt/apk"),
+ Path::new(VM_APK_CONTENTS_PATH),
Some(APK_MOUNT_DONE_PROP),
)
.context("Failed to run zipfuse")?;
@@ -824,7 +825,7 @@
let mut watcher = PropertyWatcher::new("ro.product.cpu.abilist")?;
let value = watcher.read(|_name, value| Ok(value.trim().to_string()))?;
let abi = value.split(',').next().ok_or_else(|| anyhow!("no abilist"))?;
- let path = format!("/mnt/apk/lib/{}/{}", abi, name);
+ let path = format!("{}/lib/{}/{}", VM_APK_CONTENTS_PATH, abi, name);
let metadata = fs::metadata(&path).with_context(|| format!("Unable to access {}", path))?;
if !metadata.is_file() {
diff --git a/tests/aidl/com/android/microdroid/testservice/ITestService.aidl b/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
index ebb2bcf..e8c435f 100644
--- a/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
+++ b/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
@@ -33,4 +33,7 @@
/* get the VM's boot certificate chain (BCC). */
byte[] getBcc();
+
+ /* get the APK contents path. */
+ String getApkContentsPath();
}
diff --git a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
index 5c9cf42..c4296df 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -111,6 +111,7 @@
assertThat(testResults.mAddInteger).isEqualTo(123 + 456);
assertThat(testResults.mAppRunProp).isEqualTo("true");
assertThat(testResults.mSublibRunProp).isEqualTo("true");
+ assertThat(testResults.mApkContentsPath).isEqualTo("/mnt/apk");
}
@Test
@@ -538,6 +539,7 @@
String mAppRunProp;
String mSublibRunProp;
String mExtraApkTestProp;
+ String mApkContentsPath;
}
private TestResults runVmTestService(VirtualMachine vm) throws Exception {
@@ -557,6 +559,7 @@
testService.readProperty("debug.microdroid.app.sublib.run");
testResults.mExtraApkTestProp =
testService.readProperty("debug.microdroid.test.extra_apk");
+ testResults.mApkContentsPath = testService.getApkContentsPath();
} catch (Exception e) {
testResults.mException = e;
}
diff --git a/tests/testapk/src/native/testbinary.cpp b/tests/testapk/src/native/testbinary.cpp
index d57d224..1a3e940 100644
--- a/tests/testapk/src/native/testbinary.cpp
+++ b/tests/testapk/src/native/testbinary.cpp
@@ -112,6 +112,17 @@
}
return ndk::ScopedAStatus::ok();
}
+
+ ndk::ScopedAStatus getApkContentsPath(std::string* out) override {
+ const char* path_c = AVmPayload_getApkContentsPath();
+ if (path_c == nullptr) {
+ return ndk::ScopedAStatus::
+ fromServiceSpecificErrorWithMessage(0, "Failed to get APK contents path");
+ }
+ std::string path(path_c);
+ *out = path;
+ return ndk::ScopedAStatus::ok();
+ }
};
auto testService = ndk::SharedRefBase::make<TestService>();