Pass active APEXes to VM
apex-info-list.xml lists active and inactive APEXes. We want only
"active" ones to be passed to VM.
Bug: 216583321
Test: atest virtualizationservice_device_test
Change-Id: I9dc6064fa87f2d1a8d0871aea336d75fa01a8e80
diff --git a/virtualizationservice/src/payload.rs b/virtualizationservice/src/payload.rs
index e4a763c..9e9bfc0 100644
--- a/virtualizationservice/src/payload.rs
+++ b/virtualizationservice/src/payload.rs
@@ -53,7 +53,7 @@
list: Vec<ApexInfo>,
}
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
struct ApexInfo {
#[serde(rename = "moduleName")]
name: String,
@@ -69,6 +69,9 @@
#[serde(rename = "isFactory")]
is_factory: bool,
+
+ #[serde(rename = "isActive")]
+ is_active: bool,
}
impl ApexInfoList {
@@ -94,21 +97,19 @@
Ok(apex_info_list)
})
}
+}
- /// Returns the list of apex names matching with the predicate
- fn get_matching(&self, predicate: fn(&ApexInfo) -> bool) -> Vec<String> {
- self.list.iter().filter(|info| predicate(info)).map(|info| info.name.clone()).collect()
- }
-
- fn get(&self, apex_name: &str) -> Result<&ApexInfo> {
- self.list
- .iter()
- .find(|apex| apex.name == apex_name)
- .ok_or_else(|| anyhow!("{} not found.", apex_name))
- }
-
- fn get_path_for(&self, apex_name: &str) -> Result<PathBuf> {
- Ok(self.get(apex_name)?.path.clone())
+impl ApexInfo {
+ fn matches(&self, apex_config: &ApexConfig) -> bool {
+ // Match with pseudo name "{CLASSPATH}" which represents APEXes contributing
+ // to any derive_classpath environment variable
+ if apex_config.name == "{CLASSPATH}" && self.has_classpath_jar {
+ return true;
+ }
+ if apex_config.name == self.name {
+ return true;
+ }
+ false
}
}
@@ -152,20 +153,18 @@
fn make_metadata_file(
config_path: &str,
- apex_names: &[String],
+ apex_infos: &[&ApexInfo],
temporary_directory: &Path,
- apex_list: &ApexInfoList,
) -> Result<ParcelFileDescriptor> {
let metadata_path = temporary_directory.join("metadata");
let metadata = Metadata {
version: 1,
- apexes: apex_names
+ apexes: apex_infos
.iter()
.enumerate()
- .map(|(i, apex_name)| {
- let apex_info = apex_list.get(apex_name)?;
+ .map(|(i, apex_info)| {
Ok(ApexPayload {
- name: apex_name.clone(),
+ name: apex_info.name.clone(),
partition_name: format!("microdroid-apex-{}", i),
last_update_seconds: apex_info.last_update_seconds,
is_factory: apex_info.is_factory,
@@ -227,12 +226,13 @@
let pm = PackageManager::new()?;
let apex_list = pm.get_apex_list(vm_payload_config.prefer_staged)?;
- // collect APEX names from config
- let apexes = collect_apex_names(&apex_list, &vm_payload_config.apexes, app_config.debugLevel);
- info!("Microdroid payload APEXes: {:?}", apexes);
+ // collect APEXes from config
+ let apex_infos =
+ 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, &apexes, temporary_directory, &apex_list)?;
+ make_metadata_file(&app_config.configPath, &apex_infos, temporary_directory)?;
// put metadata at the first partition
let mut partitions = vec![Partition {
label: "payload-metadata".to_owned(),
@@ -240,9 +240,8 @@
writable: false,
}];
- for (i, apex) in apexes.iter().enumerate() {
- let apex_path = apex_list.get_path_for(apex)?;
- let apex_file = open_parcel_file(&apex_path, false)?;
+ for (i, apex_info) in apex_infos.iter().enumerate() {
+ let apex_file = open_parcel_file(&apex_info.path, false)?;
partitions.push(Partition {
label: format!("microdroid-apex-{}", i),
image: Some(apex_file),
@@ -317,30 +316,25 @@
Ok(apexes)
}
-// Collect APEX names from config
-fn collect_apex_names(
- apex_list: &ApexInfoList,
- apexes: &[ApexConfig],
+// Collect ApexInfos from VM config
+fn collect_apex_infos<'a>(
+ apex_list: &'a ApexInfoList,
+ apex_configs: &[ApexConfig],
debug_level: DebugLevel,
-) -> Vec<String> {
- // Process pseudo names like "{CLASSPATH}".
- // For now we have following pseudo APEX names:
- // - {CLASSPATH}: represents APEXes contributing to any derive_classpath environment variable
- let mut apex_names: Vec<String> = apexes
- .iter()
- .flat_map(|apex| match apex.name.as_str() {
- "{CLASSPATH}" => apex_list.get_matching(|apex| apex.has_classpath_jar),
- _ => vec![apex.name.clone()],
- })
- .collect();
- // Add required APEXes
- apex_names.extend(MICRODROID_REQUIRED_APEXES.iter().map(|name| name.to_string()));
+) -> Vec<&'a ApexInfo> {
+ let mut additional_apexes: Vec<&str> = MICRODROID_REQUIRED_APEXES.to_vec();
if debug_level != DebugLevel::NONE {
- apex_names.extend(MICRODROID_REQUIRED_APEXES_DEBUG.iter().map(|name| name.to_string()));
+ additional_apexes.extend(MICRODROID_REQUIRED_APEXES_DEBUG.to_vec());
}
- apex_names.sort();
- apex_names.dedup();
- apex_names
+
+ apex_list
+ .list
+ .iter()
+ .filter(|ai| {
+ apex_configs.iter().any(|cfg| ai.matches(cfg) && ai.is_active)
+ || additional_apexes.iter().any(|name| name == &ai.name && ai.is_active)
+ })
+ .collect()
}
pub fn add_microdroid_images(
@@ -410,36 +404,94 @@
}
#[test]
- fn test_collect_apex_names() {
- let apex_list = ApexInfoList {
+ fn test_collect_apexes() {
+ let apex_info_list = ApexInfoList {
list: vec![
ApexInfo {
- name: "hasnt_classpath".to_string(),
- path: PathBuf::from("path0"),
+ // 0
+ name: "com.android.adbd".to_string(),
+ path: PathBuf::from("adbd"),
has_classpath_jar: false,
last_update_seconds: 12345678,
is_factory: true,
+ is_active: true,
},
ApexInfo {
+ // 1
+ name: "com.android.os.statsd".to_string(),
+ path: PathBuf::from("statsd"),
+ has_classpath_jar: false,
+ last_update_seconds: 12345678,
+ is_factory: true,
+ is_active: false,
+ },
+ ApexInfo {
+ // 2
+ name: "com.android.os.statsd".to_string(),
+ path: PathBuf::from("statsd/updated"),
+ has_classpath_jar: false,
+ last_update_seconds: 12345678 + 1,
+ is_factory: false,
+ is_active: true,
+ },
+ ApexInfo {
+ // 3
+ name: "no_classpath".to_string(),
+ path: PathBuf::from("no_classpath"),
+ has_classpath_jar: false,
+ last_update_seconds: 12345678,
+ is_factory: true,
+ is_active: true,
+ },
+ ApexInfo {
+ // 4
name: "has_classpath".to_string(),
- path: PathBuf::from("path1"),
+ path: PathBuf::from("has_classpath"),
has_classpath_jar: true,
last_update_seconds: 87654321,
+ is_factory: true,
+ is_active: false,
+ },
+ ApexInfo {
+ // 5
+ name: "has_classpath".to_string(),
+ path: PathBuf::from("has_classpath/updated"),
+ has_classpath_jar: true,
+ last_update_seconds: 87654321 + 1,
is_factory: false,
+ is_active: true,
+ },
+ ApexInfo {
+ // 6
+ name: "apex-foo".to_string(),
+ path: PathBuf::from("apex-foo"),
+ has_classpath_jar: false,
+ last_update_seconds: 87654321,
+ is_factory: true,
+ is_active: false,
+ },
+ ApexInfo {
+ // 7
+ name: "apex-foo".to_string(),
+ path: PathBuf::from("apex-foo/updated"),
+ has_classpath_jar: false,
+ last_update_seconds: 87654321 + 1,
+ is_factory: false,
+ is_active: true,
},
],
};
- let apexes = vec![
- ApexConfig { name: "config_name".to_string() },
+ let apex_configs = vec![
+ ApexConfig { name: "apex-foo".to_string() },
ApexConfig { name: "{CLASSPATH}".to_string() },
];
assert_eq!(
- collect_apex_names(&apex_list, &apexes, DebugLevel::FULL),
+ collect_apex_infos(&apex_info_list, &apex_configs, DebugLevel::FULL),
vec![
- "com.android.adbd".to_string(),
- "com.android.os.statsd".to_string(),
- "config_name".to_string(),
- "has_classpath".to_string(),
+ &apex_info_list.list[0],
+ &apex_info_list.list[2],
+ &apex_info_list.list[5],
+ &apex_info_list.list[7],
]
);
}