Merge "Don't update idsig when it's already up-to-date"
diff --git a/microdroid/Android.bp b/microdroid/Android.bp
index 37f68a2..5440695 100644
--- a/microdroid/Android.bp
+++ b/microdroid/Android.bp
@@ -55,10 +55,8 @@
         "microdroid_ueventd_rc",
         "microdroid_launcher",
 
-        "libbinder",
         "libbinder_ndk",
         "libstdc++",
-        "secilc",
 
         // "com.android.adbd" requires these,
         "libadbd_auth",
diff --git a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
index f58ce81..7e6080f 100644
--- a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
+++ b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
@@ -160,7 +160,7 @@
         private StringBuilder mLogOutput = new StringBuilder();
         private boolean mProcessedBootTimeMetrics = false;
 
-        private void processBootTimeMetrics(String log) {
+        private synchronized void processBootTimeMetrics(String log) {
             if (!mVcpuStartedNanoTime.isPresent()) {
                 mVcpuStartedNanoTime = OptionalLong.of(System.nanoTime());
             }
@@ -177,12 +177,8 @@
         }
 
         private void logVmOutputAndMonitorBootTimeMetrics(
-                String tag,
-                InputStream vmOutputStream,
-                String name,
-                StringBuilder result,
-                boolean monitorEvents) {
-            mProcessedBootTimeMetrics |= monitorEvents;
+                String tag, InputStream vmOutputStream, String name, StringBuilder result) {
+            mProcessedBootTimeMetrics = true;
             new Thread(
                             () -> {
                                 try {
@@ -192,7 +188,7 @@
                                     String line;
                                     while ((line = reader.readLine()) != null
                                             && !Thread.interrupted()) {
-                                        if (monitorEvents) processBootTimeMetrics(line);
+                                        processBootTimeMetrics(line);
                                         Log.i(tag, name + ": " + line);
                                         result.append(line + "\n");
                                     }
@@ -203,17 +199,6 @@
                     .start();
         }
 
-        private void logVmOutputAndMonitorBootTimeMetrics(
-                String tag, InputStream vmOutputStream, String name, StringBuilder result) {
-            logVmOutputAndMonitorBootTimeMetrics(tag, vmOutputStream, name, result, true);
-        }
-
-        /** Copy output from the VM to logcat. This is helpful when things go wrong. */
-        protected void logVmOutput(
-                String tag, InputStream vmOutputStream, String name, StringBuilder result) {
-            logVmOutputAndMonitorBootTimeMetrics(tag, vmOutputStream, name, result, false);
-        }
-
         public void runToFinish(String logTag, VirtualMachine vm)
                 throws VirtualMachineException, InterruptedException {
             vm.setCallback(mExecutorService, this);
@@ -221,7 +206,7 @@
             if (vm.getConfig().isVmOutputCaptured()) {
                 logVmOutputAndMonitorBootTimeMetrics(
                         logTag, vm.getConsoleOutput(), "Console", mConsoleOutput);
-                logVmOutput(logTag, vm.getLogOutput(), "Log", mLogOutput);
+                logVmOutputAndMonitorBootTimeMetrics(logTag, vm.getLogOutput(), "Log", mLogOutput);
             }
             mExecutorService.awaitTermination(300, TimeUnit.SECONDS);
         }
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
index 78d15dc..4f023ca 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
@@ -55,6 +55,7 @@
 import org.json.JSONObject;
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TestName;
@@ -844,6 +845,7 @@
         }
     }
 
+    @Ignore("b/288467613#comment9")
     @Test
     public void testCustomVirtualMachinePermission() throws Exception {
         assumeTrue(
diff --git a/vmbase/example/src/pci.rs b/vmbase/example/src/pci.rs
index 384a9c1..6abe66e 100644
--- a/vmbase/example/src/pci.rs
+++ b/vmbase/example/src/pci.rs
@@ -25,7 +25,7 @@
         pci::{bus::PciRoot, virtio_device_type, PciTransport},
         DeviceType, Transport,
     },
-    BufferDirection, Hal, PhysAddr, PAGE_SIZE,
+    BufferDirection, Error, Hal, PhysAddr, PAGE_SIZE,
 };
 
 /// The standard sector size of a VirtIO block device, in bytes.
@@ -36,6 +36,7 @@
 
 pub fn check_pci(pci_root: &mut PciRoot) {
     let mut checked_virtio_device_count = 0;
+    let mut block_device_count = 0;
     for (device_function, info) in pci_root.enumerate_bus(0) {
         let (status, command) = pci_root.get_status_command(device_function);
         info!("Found {} at {}, status {:?} command {:?}", info, device_function, status, command);
@@ -47,24 +48,31 @@
                 transport.device_type(),
                 transport.read_device_features(),
             );
-            if check_virtio_device(transport, virtio_type) {
-                checked_virtio_device_count += 1;
+            match virtio_type {
+                DeviceType::Block => {
+                    check_virtio_block_device(transport, block_device_count);
+                    block_device_count += 1;
+                    checked_virtio_device_count += 1;
+                }
+                DeviceType::Console => {
+                    check_virtio_console_device(transport);
+                    checked_virtio_device_count += 1;
+                }
+                _ => {}
             }
         }
     }
 
-    assert_eq!(checked_virtio_device_count, 4);
+    assert_eq!(checked_virtio_device_count, 5);
+    assert_eq!(block_device_count, 2);
 }
 
-/// Checks the given VirtIO device, if we know how to.
-///
-/// Returns true if the device was checked, or false if it was ignored.
-fn check_virtio_device(transport: impl Transport, device_type: DeviceType) -> bool {
-    match device_type {
-        DeviceType::Block => {
-            let mut blk =
-                VirtIOBlk::<HalImpl, _>::new(transport).expect("failed to create blk driver");
-            info!("Found {} KiB block device.", blk.capacity() * SECTOR_SIZE_BYTES as u64 / 1024);
+/// Checks the given VirtIO block device.
+fn check_virtio_block_device(transport: impl Transport, index: usize) {
+    let mut blk = VirtIOBlk::<HalImpl, _>::new(transport).expect("failed to create blk driver");
+    info!("Found {} KiB block device.", blk.capacity() * SECTOR_SIZE_BYTES as u64 / 1024);
+    match index {
+        0 => {
             assert_eq!(blk.capacity(), EXPECTED_SECTOR_COUNT as u64);
             let mut data = [0; SECTOR_SIZE_BYTES * EXPECTED_SECTOR_COUNT];
             for i in 0..EXPECTED_SECTOR_COUNT {
@@ -75,22 +83,27 @@
                 assert_eq!(chunk, &(i as u32).to_le_bytes());
             }
             info!("Read expected data from block device.");
-            true
         }
-        DeviceType::Console => {
-            let mut console = VirtIOConsole::<HalImpl, _>::new(transport)
-                .expect("Failed to create VirtIO console driver");
-            info!("Found console device: {:?}", console.info());
-            for &c in b"Hello VirtIO console\n" {
-                console.send(c).expect("Failed to send character to VirtIO console device");
-            }
-            info!("Wrote to VirtIO console.");
-            true
+        1 => {
+            assert_eq!(blk.capacity(), 0);
+            let mut data = [0; SECTOR_SIZE_BYTES];
+            assert_eq!(blk.read_block(0, &mut data), Err(Error::IoError));
         }
-        _ => false,
+        _ => panic!("Unexpected VirtIO block device index {}.", index),
     }
 }
 
+/// Checks the given VirtIO console device.
+fn check_virtio_console_device(transport: impl Transport) {
+    let mut console = VirtIOConsole::<HalImpl, _>::new(transport)
+        .expect("Failed to create VirtIO console driver");
+    info!("Found console device: {:?}", console.info());
+    for &c in b"Hello VirtIO console\n" {
+        console.send(c).expect("Failed to send character to VirtIO console device");
+    }
+    info!("Wrote to VirtIO console.");
+}
+
 /// Gets the memory region in which BARs are allocated.
 pub fn get_bar_region(pci_info: &PciInfo) -> MemoryRegion {
     MemoryRegion::new(pci_info.bar_range.start as usize, pci_info.bar_range.end as usize)
diff --git a/vmbase/example/tests/test.rs b/vmbase/example/tests/test.rs
index 9088f1a..085a620 100644
--- a/vmbase/example/tests/test.rs
+++ b/vmbase/example/tests/test.rs
@@ -35,6 +35,8 @@
 const VMBASE_EXAMPLE_PATH: &str =
     "/data/local/tmp/vmbase_example.integration_test/arm64/vmbase_example.bin";
 const TEST_DISK_IMAGE_PATH: &str = "/data/local/tmp/vmbase_example.integration_test/test_disk.img";
+const EMPTY_DISK_IMAGE_PATH: &str =
+    "/data/local/tmp/vmbase_example.integration_test/empty_disk.img";
 
 /// Runs the vmbase_example VM as an unprotected VM via VirtualizationService.
 #[test]
@@ -76,13 +78,25 @@
     let test_image = ParcelFileDescriptor::new(test_image);
     let disk_image = DiskImage { image: Some(test_image), writable: false, partitions: vec![] };
 
+    // Make file for empty test disk image.
+    let empty_image = File::options()
+        .create(true)
+        .read(true)
+        .write(true)
+        .truncate(true)
+        .open(EMPTY_DISK_IMAGE_PATH)
+        .with_context(|| format!("Failed to open empty disk image {}", EMPTY_DISK_IMAGE_PATH))?;
+    let empty_image = ParcelFileDescriptor::new(empty_image);
+    let empty_disk_image =
+        DiskImage { image: Some(empty_image), writable: false, partitions: vec![] };
+
     let config = VirtualMachineConfig::RawConfig(VirtualMachineRawConfig {
         name: String::from("VmBaseTest"),
         kernel: None,
         initrd: None,
         params: None,
         bootloader: Some(bootloader),
-        disks: vec![disk_image],
+        disks: vec![disk_image, empty_disk_image],
         protectedVm: false,
         memoryMib: 300,
         cpuTopology: CpuTopology::ONE_CPU,