Pass sorted list of apexes to VM
The order of apex list does matter within microdroid. To keep the
stability, sort the list of apexes before passing to a VM.
Sorting key is a composite of (apex name, apex version, apex mod
timestamp). Paths are not suitable for sorting key because
"prefer_staged" will result in different paths before/after reboot.
We could use "unordered list", especially when checking the VM identity
within a VM. But "ordered list" is assumed in many places and is more
efficient.
Bug: 257377686
Test: virtualizationservice_device_test
Merged-In: I1c269afc059da0df4c6f318d5a591f7a03d4600f
Change-Id: I1c269afc059da0df4c6f318d5a591f7a03d4600f
(cherry picked from commit a44227570f032d166b7636daf47a369670925d89)
diff --git a/virtualizationservice/src/payload.rs b/virtualizationservice/src/payload.rs
index f85a839..cd80efd 100644
--- a/virtualizationservice/src/payload.rs
+++ b/virtualizationservice/src/payload.rs
@@ -59,6 +59,8 @@
struct ApexInfo {
#[serde(rename = "moduleName")]
name: String,
+ #[serde(rename = "versionCode")]
+ version: u64,
#[serde(rename = "modulePath")]
path: PathBuf,
@@ -119,6 +121,7 @@
}
// Active one is overridden with the staged one.
if apex_info.is_active {
+ apex_info.version = staged_apex_info.versionCode as u64;
apex_info.path = PathBuf::from(&staged_apex_info.diskImagePath);
apex_info.has_classpath_jar = staged_apex_info.hasClassPathJars;
apex_info.last_update_seconds = last_updated(&apex_info.path)?;
@@ -259,8 +262,13 @@
let apex_list = pm.get_apex_list(vm_payload_config.prefer_staged)?;
// collect APEXes from config
- let apex_infos =
+ let mut apex_infos =
collect_apex_infos(&apex_list, &vm_payload_config.apexes, app_config.debugLevel);
+
+ // Pass sorted list of apexes. Sorting key shouldn't use `path` because it will change after
+ // reboot with prefer_staged. `last_update_seconds` is added to distinguish "samegrade"
+ // update.
+ apex_infos.sort_by_key(|info| (&info.name, &info.version, &info.last_update_seconds));
info!("Microdroid payload APEXes: {:?}", apex_infos.iter().map(|ai| &ai.name));
let metadata_file =
@@ -565,6 +573,7 @@
fn test_prefer_staged_apex_with_factory_active_apex() {
let single_apex = ApexInfo {
name: "foo".to_string(),
+ version: 1,
path: PathBuf::from("foo.apex"),
is_factory: true,
is_active: true,
@@ -576,6 +585,7 @@
apex_info_list
.override_staged_apex(&StagedApexInfo {
moduleName: "foo".to_string(),
+ versionCode: 2,
diskImagePath: staged.path().to_string_lossy().to_string(),
..Default::default()
})
@@ -586,6 +596,7 @@
ApexInfoList {
list: vec![
ApexInfo {
+ version: 2,
is_factory: false,
path: staged.path().to_owned(),
last_update_seconds: last_updated(staged.path()).unwrap(),
@@ -601,12 +612,14 @@
fn test_prefer_staged_apex_with_factory_and_inactive_apex() {
let factory_apex = ApexInfo {
name: "foo".to_string(),
+ version: 1,
path: PathBuf::from("foo.apex"),
is_factory: true,
..Default::default()
};
let active_apex = ApexInfo {
name: "foo".to_string(),
+ version: 2,
path: PathBuf::from("foo.downloaded.apex"),
is_active: true,
..Default::default()
@@ -618,6 +631,7 @@
apex_info_list
.override_staged_apex(&StagedApexInfo {
moduleName: "foo".to_string(),
+ versionCode: 3,
diskImagePath: staged.path().to_string_lossy().to_string(),
..Default::default()
})
@@ -631,6 +645,7 @@
factory_apex,
// update active one
ApexInfo {
+ version: 3,
path: staged.path().to_owned(),
last_update_seconds: last_updated(staged.path()).unwrap(),
..active_apex