Merge changes from topic "vm-sharedlibs-apexes"

* changes:
  Pass sharedlibs APEXes to VM
  Pass active APEXes to VM
This commit is contained in:
Jooyung Han 2022-02-02 00:12:25 +00:00 committed by Gerrit Code Review
commit a30477c89d
1 changed files with 148 additions and 61 deletions

View File

@ -53,7 +53,7 @@ struct ApexInfoList {
list: Vec<ApexInfo>,
}
#[derive(Clone, Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq)]
struct ApexInfo {
#[serde(rename = "moduleName")]
name: String,
@ -69,6 +69,12 @@ struct ApexInfo {
#[serde(rename = "isFactory")]
is_factory: bool,
#[serde(rename = "isActive")]
is_active: bool,
#[serde(rename = "provideSharedApexLibs")]
provide_shared_apex_libs: bool,
}
impl ApexInfoList {
@ -94,21 +100,19 @@ impl ApexInfoList {
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
}
}
@ -151,20 +155,18 @@ impl PackageManager {
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,
@ -226,12 +228,13 @@ fn make_payload_disk(
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(),
@ -239,9 +242,8 @@ fn make_payload_disk(
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),
@ -316,30 +318,26 @@ fn find_apex_names_in_classpath(classpath_vars: &str) -> Result<HashSet<String>>
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)
|| ai.provide_shared_apex_libs
})
.collect()
}
pub fn add_microdroid_images(
@ -409,36 +407,125 @@ export OTHER /foo/bar:/baz:/apex/second.valid.apex/:gibberish:"#;
}
#[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,
..Default::default()
},
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,
..Default::default()
},
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,
..Default::default()
},
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,
..Default::default()
},
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,
..Default::default()
},
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,
..Default::default()
},
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,
..Default::default()
},
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,
..Default::default()
},
ApexInfo {
// 8
name: "sharedlibs".to_string(),
path: PathBuf::from("apex-foo"),
last_update_seconds: 87654321,
is_factory: true,
provide_shared_apex_libs: true,
..Default::default()
},
ApexInfo {
// 9
name: "sharedlibs".to_string(),
path: PathBuf::from("apex-foo/updated"),
last_update_seconds: 87654321 + 1,
is_active: true,
provide_shared_apex_libs: true,
..Default::default()
},
],
};
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(),
// Pass active/required APEXes
&apex_info_list.list[0],
&apex_info_list.list[2],
// Pass active APEXes specified in the config
&apex_info_list.list[5],
&apex_info_list.list[7],
// Pass both preinstalled(inactive) and updated(active) for "sharedlibs" APEXes
&apex_info_list.list[8],
&apex_info_list.list[9],
]
);
}