Don't update idsig when it's already up-to-date
Bug: 193504400
Test: run atest virtualizationmanager_device_test
Test: run MicrodroidDemoApp. Start a VM, stop it, run it again. Observe
the timestamp of
/data/data/com.android.microdroid.demo/vm/test_vm/idsig. It's not
changed.
Change-Id: I2a0d600b70dd5cd83cc5244c4a51a7bccbc5962d
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index 86c8596..9cd70e6 100644
--- a/virtualizationmanager/src/aidl.rs
+++ b/virtualizationmanager/src/aidl.rs
@@ -116,6 +116,20 @@
.context("failed to create idsig")?;
let mut output = clone_file(idsig_fd)?;
+
+ // Optimization. We don't have to update idsig file whenever a VM is started. Don't update it,
+ // if the idsig file already has the same APK digest.
+ if output.metadata()?.len() > 0 {
+ if let Ok(out_sig) = V4Signature::from_idsig(&mut output) {
+ if out_sig.signing_info.apk_digest == sig.signing_info.apk_digest {
+ debug!("idsig {:?} is up-to-date with apk {:?}.", output, input);
+ return Ok(());
+ }
+ }
+ // if we fail to read v4signature from output, that's fine. User can pass a random file.
+ // We will anyway overwrite the file to the v4signature generated from input_fd.
+ }
+
output.set_len(0).context("failed to set_len on the idsig output")?;
sig.write_into(&mut output).context("failed to write idsig")?;
Ok(())
@@ -236,9 +250,6 @@
input_fd: &ParcelFileDescriptor,
idsig_fd: &ParcelFileDescriptor,
) -> binder::Result<()> {
- // TODO(b/193504400): do this only when (1) idsig_fd is empty or (2) the APK digest in
- // idsig_fd is different from APK digest in input_fd
-
check_manage_access()?;
create_or_update_idsig_file(input_fd, idsig_fd)
@@ -1300,4 +1311,30 @@
assert!(ret.is_err(), "should fail");
Ok(())
}
+
+ #[test]
+ fn test_create_or_update_idsig_does_not_update_if_already_valid() -> Result<()> {
+ use std::io::Seek;
+
+ // Pick any APK
+ let mut apk = File::open("/system/priv-app/Shell/Shell.apk").unwrap();
+ let mut idsig = tempfile::tempfile().unwrap();
+
+ create_or_update_idsig_file(
+ &ParcelFileDescriptor::new(apk.try_clone()?),
+ &ParcelFileDescriptor::new(idsig.try_clone()?),
+ )?;
+ let modified_orig = idsig.metadata()?.modified()?;
+ apk.rewind()?;
+ idsig.rewind()?;
+
+ // Call the function again
+ create_or_update_idsig_file(
+ &ParcelFileDescriptor::new(apk.try_clone()?),
+ &ParcelFileDescriptor::new(idsig.try_clone()?),
+ )?;
+ let modified_new = idsig.metadata()?.modified()?;
+ assert!(modified_orig == modified_new, "idsig file was updated unnecessarily");
+ Ok(())
+ }
}