Merge "Move getProcMemInfo() from MicrodroidTestCase to ProcessUtil."
diff --git a/compos/common/compos_client.rs b/compos/common/compos_client.rs
index 49396d7..7327df7 100644
--- a/compos/common/compos_client.rs
+++ b/compos/common/compos_client.rs
@@ -23,7 +23,7 @@
};
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
IVirtualizationService::IVirtualizationService,
- VirtualMachineAppConfig::{DebugLevel::DebugLevel, VirtualMachineAppConfig},
+ VirtualMachineAppConfig::{DebugLevel::DebugLevel, Payload::Payload, VirtualMachineAppConfig},
VirtualMachineConfig::VirtualMachineConfig,
};
use anyhow::{bail, Context, Result};
@@ -122,7 +122,7 @@
apk: Some(apk_fd),
idsig: Some(idsig_fd),
instanceImage: Some(instance_fd),
- configPath: config_path,
+ payload: Payload::ConfigPath(config_path),
debugLevel: debug_level,
extraIdsigs: extra_idsigs,
protectedVm: protected_vm,
diff --git a/docs/getting_started/index.md b/docs/getting_started/index.md
index 7fddc5a..34a990d 100644
--- a/docs/getting_started/index.md
+++ b/docs/getting_started/index.md
@@ -118,7 +118,7 @@
on pVM. You can manually run the demo app on top of Microdroid as follows:
```shell
-TARGET_BUILD_APPS=MicrodroidDemoApp m apps_only dist
+UNBUNDLED_BUILD_SDKS_FROM_SOURCE=true TARGET_BUILD_APPS=MicrodroidDemoApp m apps_only dist
adb shell mkdir -p /data/local/tmp/virt
adb push out/dist/MicrodroidDemoApp.apk /data/local/tmp/virt/
adb shell /apex/com.android.virt/bin/vm run-app \
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java b/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
index 4ecd942..63a3f43 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
@@ -222,7 +222,7 @@
/* package */ VirtualMachineAppConfig toParcel() throws FileNotFoundException {
VirtualMachineAppConfig parcel = new VirtualMachineAppConfig();
parcel.apk = ParcelFileDescriptor.open(new File(mApkPath), MODE_READ_ONLY);
- parcel.configPath = mPayloadConfigPath;
+ parcel.payload = VirtualMachineAppConfig.Payload.configPath(mPayloadConfigPath);
switch (mDebugLevel) {
case NONE:
parcel.debugLevel = VirtualMachineAppConfig.DebugLevel.NONE;
diff --git a/libs/apkverify/src/algorithms.rs b/libs/apkverify/src/algorithms.rs
index ed2c1fc..6315606 100644
--- a/libs/apkverify/src/algorithms.rs
+++ b/libs/apkverify/src/algorithms.rs
@@ -16,7 +16,8 @@
//! Algorithms used for APK Signature Scheme.
-use anyhow::{ensure, Result};
+use anyhow::{ensure, Context, Result};
+use byteorder::{LittleEndian, ReadBytesExt};
use bytes::{Buf, Bytes};
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive};
@@ -25,6 +26,7 @@
use openssl::rsa::Padding;
use openssl::sign::Verifier;
use serde::{Deserialize, Serialize};
+use std::io::Read;
use crate::bytes_ext::ReadFromBytes;
@@ -203,3 +205,24 @@
VerityChunkedSha256,
ChunkedSha512,
}
+
+/// Hash algorithms.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, FromPrimitive, ToPrimitive)]
+#[repr(u32)]
+pub enum HashAlgorithm {
+ /// SHA-256
+ SHA256 = 1,
+}
+
+impl HashAlgorithm {
+ pub(crate) fn from_read<R: Read>(read: &mut R) -> Result<Self> {
+ let val = read.read_u32::<LittleEndian>()?;
+ Self::from_u32(val).context(format!("Unsupported hash algorithm: {}", val))
+ }
+}
+
+impl Default for HashAlgorithm {
+ fn default() -> Self {
+ HashAlgorithm::SHA256
+ }
+}
diff --git a/libs/apkverify/src/lib.rs b/libs/apkverify/src/lib.rs
index 359d963..f7cbb7e 100644
--- a/libs/apkverify/src/lib.rs
+++ b/libs/apkverify/src/lib.rs
@@ -26,6 +26,6 @@
mod v4;
mod ziputil;
-pub use algorithms::SignatureAlgorithmID;
+pub use algorithms::{HashAlgorithm, SignatureAlgorithmID};
pub use v3::{get_public_key_der, verify};
-pub use v4::{get_apk_digest, HashAlgorithm, V4Signature};
+pub use v4::{get_apk_digest, V4Signature};
diff --git a/libs/apkverify/src/v4.rs b/libs/apkverify/src/v4.rs
index 33e666f..715f742 100644
--- a/libs/apkverify/src/v4.rs
+++ b/libs/apkverify/src/v4.rs
@@ -26,7 +26,7 @@
use std::io::{copy, Cursor, Read, Seek, SeekFrom, Write};
use std::path::Path;
-use crate::algorithms::SignatureAlgorithmID;
+use crate::algorithms::{HashAlgorithm, SignatureAlgorithmID};
use crate::hashtree::*;
use crate::v3::extract_signer_and_apk_sections;
@@ -123,26 +123,6 @@
}
}
-/// Hash algorithm that can be used for idsig file.
-#[derive(Debug, PartialEq, Eq, FromPrimitive, ToPrimitive)]
-#[repr(u32)]
-pub enum HashAlgorithm {
- /// SHA2-256
- SHA256 = 1,
-}
-
-impl HashAlgorithm {
- fn from(val: u32) -> Result<HashAlgorithm> {
- Self::from_u32(val).ok_or_else(|| anyhow!("{} is an unsupported hash algorithm", val))
- }
-}
-
-impl Default for HashAlgorithm {
- fn default() -> Self {
- HashAlgorithm::SHA256
- }
-}
-
impl V4Signature<fs::File> {
/// Creates a `V4Signature` struct from the given idsig path.
pub fn from_idsig_path<P: AsRef<Path>>(idsig_path: P) -> Result<Self> {
@@ -239,7 +219,7 @@
// fields in the struct are also length encoded.
r.read_u32::<LittleEndian>()?;
Ok(HashingInfo {
- hash_algorithm: HashAlgorithm::from(r.read_u32::<LittleEndian>()?)?,
+ hash_algorithm: HashAlgorithm::from_read(&mut r)?,
log2_blocksize: r.read_u8()?,
salt: read_sized_array(&mut r)?,
raw_root_hash: read_sized_array(&mut r)?,
diff --git a/microdroid/payload/metadata.cc b/microdroid/payload/metadata.cc
index 07083e9..fd07bdd 100644
--- a/microdroid/payload/metadata.cc
+++ b/microdroid/payload/metadata.cc
@@ -40,7 +40,7 @@
}
size = be32toh(*reinterpret_cast<uint32_t*>(content.data()));
if (content.size() < length_prefix_bytes + size) {
- return Error() << "Invalid metadata: size(" << size << ") mimatches to the content size("
+ return Error() << "Invalid metadata: size(" << size << ") doesn't match content size("
<< content.size() - length_prefix_bytes << ")";
}
content = content.substr(length_prefix_bytes, size);
diff --git a/microdroid/payload/metadata.proto b/microdroid/payload/metadata.proto
index 2e92f55..06cbbf4 100644
--- a/microdroid/payload/metadata.proto
+++ b/microdroid/payload/metadata.proto
@@ -26,7 +26,11 @@
ApkPayload apk = 3;
- string payload_config_path = 4;
+ oneof payload {
+ // Path to JSON config file inside the APK.
+ string config_path = 4;
+ PayloadConfig config = 5;
+ }
}
message ApexPayload {
@@ -58,3 +62,14 @@
string idsig_partition_name = 3;
}
+
+message PayloadConfig {
+ // Required.
+ // Path to the payload binary file inside the APK.
+ string payload_binary_path = 1;
+
+ // Optional.
+ // Arguments to be passed to the payload.
+ // TODO(b/249064104): Remove this
+ repeated string args = 2;
+}
diff --git a/microdroid/payload/metadata/src/lib.rs b/microdroid/payload/metadata/src/lib.rs
index eb9d90d..bfbec60 100644
--- a/microdroid/payload/metadata/src/lib.rs
+++ b/microdroid/payload/metadata/src/lib.rs
@@ -23,7 +23,9 @@
use std::io::Read;
use std::io::Write;
-pub use microdroid_metadata::metadata::{ApexPayload, ApkPayload, Metadata};
+pub use microdroid_metadata::metadata::{
+ ApexPayload, ApkPayload, Metadata, Metadata_oneof_payload as PayloadMetadata, PayloadConfig,
+};
/// Reads a metadata from a reader
pub fn read_metadata<T: Read>(mut r: T) -> Result<Metadata> {
diff --git a/microdroid/payload/mk_payload.cc b/microdroid/payload/mk_payload.cc
index 4dbcabf..d31333f 100644
--- a/microdroid/payload/mk_payload.cc
+++ b/microdroid/payload/mk_payload.cc
@@ -181,7 +181,7 @@
}
if (config.payload_config_path.has_value()) {
- *metadata.mutable_payload_config_path() = config.payload_config_path.value();
+ *metadata.mutable_config_path() = config.payload_config_path.value();
}
std::ofstream out(filename);
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 30521f6..b4b2c8b 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -30,12 +30,12 @@
use anyhow::{anyhow, bail, ensure, Context, Error, Result};
use apkverify::{get_public_key_der, verify, V4Signature};
use binder::{wait_for_interface, Strong};
-use diced_utils::cbor::encode_header;
+use diced_utils::cbor::{encode_header, encode_number};
use glob::glob;
use itertools::sorted;
use log::{error, info};
-use microdroid_metadata::{write_metadata, Metadata};
-use microdroid_payload_config::{Task, TaskType, VmPayloadConfig};
+use microdroid_metadata::{write_metadata, Metadata, PayloadMetadata};
+use microdroid_payload_config::{Task, TaskType, VmPayloadConfig, OsConfig};
use openssl::sha::Sha512;
use payload::{get_apex_data_from_payload, load_metadata, to_metadata};
use rand::Fill;
@@ -191,7 +191,10 @@
}
}
-fn dice_derivation(verified_data: &MicrodroidData, payload_config_path: &str) -> Result<()> {
+fn dice_derivation(
+ verified_data: &MicrodroidData,
+ payload_metadata: &PayloadMetadata,
+) -> Result<()> {
// Calculate compound digests of code and authorities
let mut code_hash_ctx = Sha512::new();
let mut authority_hash_ctx = Sha512::new();
@@ -210,15 +213,33 @@
// {
// -70002: "Microdroid payload",
- // -71000: payload_config_path
+ // ? -71000: tstr // payload_config_path
+ // ? -71001: PayloadConfig
// }
+ // PayloadConfig = {
+ // 1: tstr // payload_binary_path
+ // // TODO(b/249064104 Either include args, or deprecate them
+ // }
+
let mut config_desc = vec![
- 0xa2, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x72, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x3a, 0x00, 0x01, 0x15, 0x57,
+ 0xa2, // map(2)
+ 0x3a, 0x00, 0x01, 0x11, 0x71, // -70002
+ 0x72, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x20, 0x70, 0x61, 0x79,
+ 0x6c, 0x6f, 0x61, 0x64, // "Microdroid payload"
];
- let config_path_bytes = payload_config_path.as_bytes();
- encode_header(3, config_path_bytes.len().try_into().unwrap(), &mut config_desc)?;
- config_desc.extend_from_slice(config_path_bytes);
+
+ match payload_metadata {
+ PayloadMetadata::config_path(payload_config_path) => {
+ encode_negative_number(-71000, &mut config_desc)?;
+ encode_tstr(payload_config_path, &mut config_desc)?;
+ }
+ PayloadMetadata::config(payload_config) => {
+ encode_negative_number(-71001, &mut config_desc)?;
+ encode_header(5, 1, &mut config_desc)?; // map(1)
+ encode_number(1, &mut config_desc)?;
+ encode_tstr(&payload_config.payload_binary_path, &mut config_desc)?;
+ }
+ }
// Check app debuggability, conervatively assuming it is debuggable
let app_debuggable = system_properties::read_bool(APP_DEBUGGABLE_PROP, true)?;
@@ -240,6 +261,19 @@
Ok(())
}
+fn encode_tstr(tstr: &str, buffer: &mut Vec<u8>) -> Result<()> {
+ let bytes = tstr.as_bytes();
+ encode_header(3, bytes.len().try_into().unwrap(), buffer)?;
+ buffer.extend_from_slice(bytes);
+ Ok(())
+}
+
+fn encode_negative_number(n: i64, buffer: &mut dyn Write) -> Result<()> {
+ ensure!(n < 0);
+ let n = -1 - n;
+ encode_header(1, n.try_into().unwrap(), buffer)
+}
+
fn is_strict_boot() -> bool {
Path::new(AVF_STRICT_BOOT).exists()
}
@@ -301,9 +335,13 @@
verified_data
};
+ let payload_metadata = metadata.payload.ok_or_else(|| {
+ MicrodroidError::InvalidConfig("No payload config in metadata".to_string())
+ })?;
+
// To minimize the exposure to untrusted data, derive dice profile as soon as possible.
info!("DICE derivation for payload");
- dice_derivation(&verified_data, &metadata.payload_config_path)?;
+ dice_derivation(&verified_data, &payload_metadata)?;
// Before reading a file from the APK, start zipfuse
let noexec = false;
@@ -315,12 +353,7 @@
)
.context("Failed to run zipfuse")?;
- ensure!(
- !metadata.payload_config_path.is_empty(),
- MicrodroidError::InvalidConfig("No payload_config_path in metadata".to_string())
- );
-
- let config = load_config(Path::new(&metadata.payload_config_path))?;
+ let config = load_config(payload_metadata)?;
let task = config
.task
@@ -329,7 +362,7 @@
if config.extra_apks.len() != verified_data.extra_apks_data.len() {
return Err(anyhow!(
- "config expects {} extra apks, but found only {}",
+ "config expects {} extra apks, but found {}",
config.extra_apks.len(),
verified_data.extra_apks_data.len()
));
@@ -615,10 +648,31 @@
}
}
-fn load_config(path: &Path) -> Result<VmPayloadConfig> {
- info!("loading config from {:?}...", path);
- let file = ioutil::wait_for_file(path, WAIT_TIMEOUT)?;
- Ok(serde_json::from_reader(file)?)
+fn load_config(payload_metadata: PayloadMetadata) -> Result<VmPayloadConfig> {
+ match payload_metadata {
+ PayloadMetadata::config_path(path) => {
+ let path = Path::new(&path);
+ info!("loading config from {:?}...", path);
+ let file = ioutil::wait_for_file(path, WAIT_TIMEOUT)?;
+ Ok(serde_json::from_reader(file)?)
+ }
+ PayloadMetadata::config(payload_config) => {
+ let task = Task {
+ type_: TaskType::MicrodroidLauncher,
+ command: payload_config.payload_binary_path,
+ args: payload_config.args.into_vec(),
+ };
+ Ok(VmPayloadConfig {
+ os: OsConfig { name: "microdroid".to_owned() },
+ task: Some(task),
+ apexes: vec![],
+ extra_apks: vec![],
+ prefer_staged: false,
+ export_tombstones: false,
+ enable_authfs: false,
+ })
+ }
+ }
}
/// Loads the crashkernel into memory using kexec if the VM is loaded with `crashkernel=' parameter
diff --git a/pvmfw/Android.bp b/pvmfw/Android.bp
index 5bcafd5..57a3df0 100644
--- a/pvmfw/Android.bp
+++ b/pvmfw/Android.bp
@@ -42,3 +42,17 @@
},
},
}
+
+bootimg {
+ name: "pvmfw_img",
+ stem: "pvmfw.img",
+ kernel_prebuilt: ":pvmfw_bin",
+ header_version: "3",
+ partition_name: "pvmfw",
+ enabled: false,
+ target: {
+ android_arm64: {
+ enabled: true,
+ },
+ },
+}
diff --git a/tests/benchmark/AndroidTest.xml b/tests/benchmark/AndroidTest.xml
index e908077..4949d22 100644
--- a/tests/benchmark/AndroidTest.xml
+++ b/tests/benchmark/AndroidTest.xml
@@ -21,6 +21,10 @@
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="test-file-name" value="MicrodroidBenchmarkApp.apk" />
</target_preparer>
+ <!-- Need root to access /proc/$pid/smaps when measuring memory usage. -->
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+ <option name="force-root" value="true" />
+ </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<option
name="run-command"
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
index cf5398d..9b0a658 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
@@ -15,6 +15,8 @@
*/
package android.system.virtualizationservice;
+import android.system.virtualizationservice.VirtualMachinePayloadConfig;
+
/** Configuration for running an App in a VM */
parcelable VirtualMachineAppConfig {
/** Name of VM */
@@ -32,8 +34,20 @@
/** instance.img that has per-instance data */
ParcelFileDescriptor instanceImage;
- /** Path to a configuration in an APK. This is the actual configuration for a VM. */
- @utf8InCpp String configPath;
+ union Payload {
+ /**
+ * Path to a JSON file in an APK containing the configuration.
+ */
+ @utf8InCpp String configPath;
+
+ /**
+ * Configuration provided explicitly.
+ */
+ VirtualMachinePayloadConfig payloadConfig;
+ }
+
+ /** Detailed configuration for the VM, specifying how the payload will be run. */
+ Payload payload;
enum DebugLevel {
/** Not debuggable at all */
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachinePayloadConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachinePayloadConfig.aidl
new file mode 100644
index 0000000..4d37848
--- /dev/null
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachinePayloadConfig.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.system.virtualizationservice;
+
+parcelable VirtualMachinePayloadConfig {
+ /**
+ * Path to the payload executable code in an APK. The code is in the form of a .so with a
+ * defined entry point; inside the VM this file is loaded and the entry function invoked.
+ */
+ @utf8InCpp String payloadPath;
+
+ /**
+ * Command-line style arguments to be passed to the payload when it is executed.
+ * TODO(b/249064104): Remove this
+ */
+ @utf8InCpp String[] args;
+}
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index b35f8da..563fab0 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -29,9 +29,10 @@
IVirtualizationService::IVirtualizationService,
Partition::Partition,
PartitionType::PartitionType,
- VirtualMachineAppConfig::VirtualMachineAppConfig,
+ VirtualMachineAppConfig::{VirtualMachineAppConfig, Payload::Payload},
VirtualMachineConfig::VirtualMachineConfig,
VirtualMachineDebugInfo::VirtualMachineDebugInfo,
+ VirtualMachinePayloadConfig::VirtualMachinePayloadConfig,
VirtualMachineRawConfig::VirtualMachineRawConfig,
VirtualMachineState::VirtualMachineState,
};
@@ -49,7 +50,7 @@
use disk::QcowFile;
use apkverify::{HashAlgorithm, V4Signature};
use log::{debug, error, info, warn};
-use microdroid_payload_config::VmPayloadConfig;
+use microdroid_payload_config::{VmPayloadConfig, OsConfig, Task, TaskType};
use rustutils::system_properties;
use semver::VersionReq;
use std::convert::TryInto;
@@ -85,6 +86,8 @@
const CHUNK_RECV_MAX_LEN: usize = 1024;
+const MICRODROID_OS_NAME: &str = "microdroid";
+
/// Implementation of `IVirtualizationService`, the entry point of the AIDL service.
#[derive(Debug, Default)]
pub struct VirtualizationService {
@@ -376,15 +379,10 @@
let config = match config {
VirtualMachineConfig::AppConfig(config) => BorrowedOrOwned::Owned(
load_app_config(config, &temporary_directory).map_err(|e| {
- error!("Failed to load app config from {}: {:?}", &config.configPath, e);
*is_protected = config.protectedVm;
- Status::new_service_specific_error_str(
- -1,
- Some(format!(
- "Failed to load app config from {}: {:?}",
- &config.configPath, e
- )),
- )
+ let message = format!("Failed to load app config: {:?}", e);
+ error!("{}", message);
+ Status::new_service_specific_error_str(-1, Some(message))
})?,
),
VirtualMachineConfig::RawConfig(config) => BorrowedOrOwned::Borrowed(config),
@@ -604,16 +602,18 @@
let apk_file = clone_file(config.apk.as_ref().unwrap())?;
let idsig_file = clone_file(config.idsig.as_ref().unwrap())?;
let instance_file = clone_file(config.instanceImage.as_ref().unwrap())?;
- let config_path = &config.configPath;
- let mut apk_zip = ZipArchive::new(&apk_file)?;
- let config_file = apk_zip.by_name(config_path)?;
- let vm_payload_config: VmPayloadConfig = serde_json::from_reader(config_file)?;
+ let vm_payload_config = match &config.payload {
+ Payload::ConfigPath(config_path) => {
+ load_vm_payload_config_from_file(&apk_file, config_path.as_str())
+ .with_context(|| format!("Couldn't read config from {}", config_path))?
+ }
+ Payload::PayloadConfig(payload_config) => create_vm_payload_config(payload_config),
+ };
- let os_name = &vm_payload_config.os.name;
-
- // For now, the only supported "os" value is "microdroid"
- if os_name != "microdroid" {
+ // For now, the only supported OS is Microdroid
+ let os_name = vm_payload_config.os.name.as_str();
+ if os_name != MICRODROID_OS_NAME {
bail!("Unknown OS \"{}\"", os_name);
}
@@ -633,21 +633,45 @@
vm_config.taskProfiles = config.taskProfiles.clone();
// Microdroid requires an additional init ramdisk & payload disk image
- if os_name == "microdroid" {
- add_microdroid_images(
- config,
- temporary_directory,
- apk_file,
- idsig_file,
- instance_file,
- &vm_payload_config,
- &mut vm_config,
- )?;
- }
+ add_microdroid_images(
+ config,
+ temporary_directory,
+ apk_file,
+ idsig_file,
+ instance_file,
+ &vm_payload_config,
+ &mut vm_config,
+ )?;
Ok(vm_config)
}
+fn load_vm_payload_config_from_file(apk_file: &File, config_path: &str) -> Result<VmPayloadConfig> {
+ let mut apk_zip = ZipArchive::new(apk_file)?;
+ let config_file = apk_zip.by_name(config_path)?;
+ Ok(serde_json::from_reader(config_file)?)
+}
+
+fn create_vm_payload_config(payload_config: &VirtualMachinePayloadConfig) -> VmPayloadConfig {
+ // There isn't an actual config file. Construct a synthetic VmPayloadConfig from the explicit
+ // parameters we've been given. Microdroid will do something equivalent inside the VM using the
+ // payload config that we send it via the metadata file.
+ let task = Task {
+ type_: TaskType::MicrodroidLauncher,
+ command: payload_config.payloadPath.clone(),
+ args: payload_config.args.clone(),
+ };
+ VmPayloadConfig {
+ os: OsConfig { name: MICRODROID_OS_NAME.to_owned() },
+ task: Some(task),
+ apexes: vec![],
+ extra_apks: vec![],
+ prefer_staged: false,
+ export_tombstones: false,
+ enable_authfs: false,
+ }
+}
+
/// Generates a unique filename to use for a composite disk image.
fn make_composite_image_filenames(
temporary_directory: &Path,
diff --git a/virtualizationservice/src/atom.rs b/virtualizationservice/src/atom.rs
index 3b29d19..eabb4cc 100644
--- a/virtualizationservice/src/atom.rs
+++ b/virtualizationservice/src/atom.rs
@@ -16,23 +16,47 @@
use crate::aidl::clone_file;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
- DeathReason::DeathReason, IVirtualMachine::IVirtualMachine,
- VirtualMachineAppConfig::VirtualMachineAppConfig, VirtualMachineConfig::VirtualMachineConfig,
+ DeathReason::DeathReason,
+ IVirtualMachine::IVirtualMachine,
+ VirtualMachineAppConfig::{Payload::Payload, VirtualMachineAppConfig},
+ VirtualMachineConfig::VirtualMachineConfig,
};
use android_system_virtualizationservice::binder::{Status, Strong};
use anyhow::{anyhow, Result};
-use binder::ThreadState;
+use binder::{ParcelFileDescriptor, ThreadState};
use log::{trace, warn};
use microdroid_payload_config::VmPayloadConfig;
use statslog_virtualization_rust::{vm_booted, vm_creation_requested, vm_exited};
use std::time::{Duration, SystemTime};
use zip::ZipArchive;
-fn get_vm_payload_config(config: &VirtualMachineAppConfig) -> Result<VmPayloadConfig> {
- let apk = config.apk.as_ref().ok_or_else(|| anyhow!("APK is none"))?;
+fn get_apex_list(config: &VirtualMachineAppConfig) -> String {
+ match &config.payload {
+ Payload::PayloadConfig(_) => String::new(),
+ Payload::ConfigPath(config_path) => {
+ let vm_payload_config = get_vm_payload_config(&config.apk, config_path);
+ if let Ok(vm_payload_config) = vm_payload_config {
+ vm_payload_config
+ .apexes
+ .iter()
+ .map(|x| x.name.clone())
+ .collect::<Vec<String>>()
+ .join(":")
+ } else {
+ "INFO: Can't get VmPayloadConfig".to_owned()
+ }
+ }
+ }
+}
+
+fn get_vm_payload_config(
+ apk_fd: &Option<ParcelFileDescriptor>,
+ config_path: &str,
+) -> Result<VmPayloadConfig> {
+ let apk = apk_fd.as_ref().ok_or_else(|| anyhow!("APK is none"))?;
let apk_file = clone_file(apk)?;
let mut apk_zip = ZipArchive::new(&apk_file)?;
- let config_file = apk_zip.by_name(&config.configPath)?;
+ let config_file = apk_zip.by_name(config_path)?;
let vm_payload_config: VmPayloadConfig = serde_json::from_reader(config_file)?;
Ok(vm_payload_config)
}
@@ -63,38 +87,22 @@
}
}
- let vm_identifier;
- let config_type;
- let num_cpus;
- let memory_mib;
- let apexes;
- match config {
- VirtualMachineConfig::AppConfig(config) => {
- vm_identifier = &config.name;
- config_type = vm_creation_requested::ConfigType::VirtualMachineAppConfig;
- num_cpus = config.numCpus;
- memory_mib = config.memoryMib;
-
- let vm_payload_config = get_vm_payload_config(config);
- if let Ok(vm_payload_config) = vm_payload_config {
- apexes = vm_payload_config
- .apexes
- .iter()
- .map(|x| x.name.clone())
- .collect::<Vec<String>>()
- .join(":");
- } else {
- apexes = "INFO: Can't get VmPayloadConfig".into();
- }
- }
- VirtualMachineConfig::RawConfig(config) => {
- vm_identifier = &config.name;
- config_type = vm_creation_requested::ConfigType::VirtualMachineRawConfig;
- num_cpus = config.numCpus;
- memory_mib = config.memoryMib;
- apexes = String::new();
- }
- }
+ let (vm_identifier, config_type, num_cpus, memory_mib, apexes) = match config {
+ VirtualMachineConfig::AppConfig(config) => (
+ &config.name,
+ vm_creation_requested::ConfigType::VirtualMachineAppConfig,
+ config.numCpus,
+ config.memoryMib,
+ get_apex_list(config),
+ ),
+ VirtualMachineConfig::RawConfig(config) => (
+ &config.name,
+ vm_creation_requested::ConfigType::VirtualMachineRawConfig,
+ config.numCpus,
+ config.memoryMib,
+ String::new(),
+ ),
+ };
let vm_creation_requested = vm_creation_requested::VmCreationRequested {
uid: ThreadState::get_calling_uid() as i32,
diff --git a/virtualizationservice/src/crosvm.rs b/virtualizationservice/src/crosvm.rs
index 82a9e78..4a9df46 100644
--- a/virtualizationservice/src/crosvm.rs
+++ b/virtualizationservice/src/crosvm.rs
@@ -434,6 +434,7 @@
.arg("--extended-status")
.arg("run")
.arg("--disable-sandbox")
+ .arg("--no-balloon")
.arg("--cid")
.arg(config.cid.to_string());
diff --git a/virtualizationservice/src/payload.rs b/virtualizationservice/src/payload.rs
index 06b9716..82aa760 100644
--- a/virtualizationservice/src/payload.rs
+++ b/virtualizationservice/src/payload.rs
@@ -15,14 +15,16 @@
//! Payload disk image
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
- DiskImage::DiskImage, Partition::Partition, VirtualMachineAppConfig::DebugLevel::DebugLevel,
- VirtualMachineAppConfig::VirtualMachineAppConfig,
+ DiskImage::DiskImage,
+ Partition::Partition,
+ VirtualMachineAppConfig::DebugLevel::DebugLevel,
+ VirtualMachineAppConfig::{Payload::Payload, VirtualMachineAppConfig},
VirtualMachineRawConfig::VirtualMachineRawConfig,
};
use anyhow::{anyhow, bail, Context, Result};
use binder::{wait_for_interface, ParcelFileDescriptor};
use log::{info, warn};
-use microdroid_metadata::{ApexPayload, ApkPayload, Metadata};
+use microdroid_metadata::{ApexPayload, ApkPayload, Metadata, PayloadConfig, PayloadMetadata};
use microdroid_payload_config::{ApexConfig, VmPayloadConfig};
use once_cell::sync::OnceCell;
use packagemanager_aidl::aidl::android::content::pm::IPackageManagerNative::IPackageManagerNative;
@@ -156,11 +158,21 @@
}
fn make_metadata_file(
- config_path: &str,
+ app_config: &VirtualMachineAppConfig,
apex_infos: &[&ApexInfo],
temporary_directory: &Path,
) -> Result<ParcelFileDescriptor> {
- let metadata_path = temporary_directory.join("metadata");
+ let payload_metadata = match &app_config.payload {
+ Payload::PayloadConfig(payload_config) => PayloadMetadata::config(PayloadConfig {
+ payload_binary_path: payload_config.payloadPath.clone(),
+ args: payload_config.args.clone().into(),
+ ..Default::default()
+ }),
+ Payload::ConfigPath(config_path) => {
+ PayloadMetadata::config_path(format!("/mnt/apk/{}", config_path))
+ }
+ };
+
let metadata = Metadata {
version: 1,
apexes: apex_infos
@@ -183,11 +195,12 @@
..Default::default()
})
.into(),
- payload_config_path: format!("/mnt/apk/{}", config_path),
+ payload: Some(payload_metadata),
..Default::default()
};
// Write metadata to file.
+ let metadata_path = temporary_directory.join("metadata");
let mut metadata_file = OpenOptions::new()
.create_new(true)
.read(true)
@@ -235,8 +248,7 @@
collect_apex_infos(&apex_list, &vm_payload_config.apexes, app_config.debugLevel);
info!("Microdroid payload APEXes: {:?}", apex_infos.iter().map(|ai| &ai.name));
- let metadata_file =
- make_metadata_file(&app_config.configPath, &apex_infos, temporary_directory)?;
+ let metadata_file = make_metadata_file(app_config, &apex_infos, temporary_directory)?;
// put metadata at the first partition
let mut partitions = vec![Partition {
label: "payload-metadata".to_owned(),
diff --git a/vm/src/main.rs b/vm/src/main.rs
index 0845897..21cc74b 100644
--- a/vm/src/main.rs
+++ b/vm/src/main.rs
@@ -48,7 +48,7 @@
instance: PathBuf,
/// Path to VM config JSON within APK (e.g. assets/vm_config.json)
- config_path: String,
+ config_path: Option<String>,
/// Name of VM
#[clap(long)]
@@ -205,7 +205,7 @@
&apk,
&idsig,
&instance,
- &config_path,
+ config_path.as_deref().unwrap_or(""),
daemonize,
console.as_deref(),
log.as_deref(),
diff --git a/vm/src/run.rs b/vm/src/run.rs
index 44e15f9..c524c59 100644
--- a/vm/src/run.rs
+++ b/vm/src/run.rs
@@ -16,9 +16,10 @@
use crate::create_partition::command_create_partition;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
- IVirtualizationService::IVirtualizationService, PartitionType::PartitionType,
- VirtualMachineAppConfig::DebugLevel::DebugLevel,
- VirtualMachineAppConfig::VirtualMachineAppConfig, VirtualMachineConfig::VirtualMachineConfig,
+ IVirtualizationService::IVirtualizationService,
+ PartitionType::PartitionType,
+ VirtualMachineAppConfig::{DebugLevel::DebugLevel, Payload::Payload, VirtualMachineAppConfig},
+ VirtualMachineConfig::VirtualMachineConfig,
VirtualMachineState::VirtualMachineState,
};
use anyhow::{bail, Context, Error};
@@ -96,7 +97,7 @@
idsig: idsig_fd.into(),
extraIdsigs: extra_idsig_fds,
instanceImage: open_parcel_file(instance, true /* writable */)?.into(),
- configPath: config_path.to_owned(),
+ payload: Payload::ConfigPath(config_path.to_owned()),
debugLevel: debug_level,
protectedVm: protected,
memoryMib: mem.unwrap_or(0) as i32, // 0 means use the VM default