Merge "Test CompOS more directly."
diff --git a/compos/tests/AndroidTest.xml b/compos/tests/AndroidTest.xml
index 61b6d47..940531b 100644
--- a/compos/tests/AndroidTest.xml
+++ b/compos/tests/AndroidTest.xml
@@ -18,10 +18,6 @@
         <option name="force-root" value="true" />
     </target_preparer>
 
-    <!-- virtualizationservice doesn't have access to shell_data_file. Instead of giving it
-      a test-only permission, run it without selinux -->
-    <target_preparer class="com.android.tradefed.targetprep.DisableSELinuxTargetPreparer"/>
-
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
         <option name="jar" value="ComposHostTestCases.jar" />
     </test>
diff --git a/compos/tests/java/android/compos/test/ComposTestCase.java b/compos/tests/java/android/compos/test/ComposTestCase.java
index 40f95c3..01d8ff1 100644
--- a/compos/tests/java/android/compos/test/ComposTestCase.java
+++ b/compos/tests/java/android/compos/test/ComposTestCase.java
@@ -22,8 +22,6 @@
 import android.virt.test.CommandRunner;
 import android.virt.test.VirtualizationTestCaseBase;
 
-import com.android.compatibility.common.util.PollingCheck;
-import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import com.android.tradefed.util.CommandResult;
@@ -37,11 +35,10 @@
 @RunWith(DeviceJUnit4ClassRunner.class)
 public final class ComposTestCase extends VirtualizationTestCaseBase {
 
-    /** Path to odrefresh on Microdroid */
+    // Binaries used in test. (These paths are valid both in host and Microdroid.)
     private static final String ODREFRESH_BIN = "/apex/com.android.art/bin/odrefresh";
-
-    /** Path to compos_key_cmd on Microdroid */
     private static final String COMPOS_KEY_CMD_BIN = "/apex/com.android.compos/bin/compos_key_cmd";
+    private static final String COMPOSD_CMD_BIN = "/apex/com.android.compos/bin/composd_cmd";
 
     /** Output directory of odrefresh */
     private static final String ODREFRESH_OUTPUT_DIR =
@@ -50,38 +47,29 @@
     /** Timeout of odrefresh to finish */
     private static final int ODREFRESH_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes
 
-    /** Wait time for compsvc to be ready on boot */
-    private static final int COMPSVC_READY_LATENCY_MS = 10 * 1000; // 10 seconds
-
     // ExitCode expanded from art/odrefresh/include/odrefresh/odrefresh.h.
     private static final int OKAY = 0;
     private static final int COMPILATION_SUCCESS = 80;
 
-    private String mCid;
+    // Files that define the "current" instance of CompOS
+    private static final String COMPOS_CURRENT_ROOT =
+            "/data/misc/apexdata/com.android.compos/current/";
+    private static final String INSTANCE_IMAGE = COMPOS_CURRENT_ROOT + "instance.img";
+    private static final String PUBLIC_KEY = COMPOS_CURRENT_ROOT + "key.pubkey";
+    private static final String PRIVATE_KEY_BLOB = COMPOS_CURRENT_ROOT + "key.blob";
 
     @Before
     public void setUp() throws Exception {
         testIfDeviceIsCapable(getDevice());
-
-        prepareVirtualizationTestSetup(getDevice());
-
-        startComposVm();
     }
 
     @After
     public void tearDown() throws Exception {
-        if (mCid != null) {
-            shutdownMicrodroid(getDevice(), mCid);
-            mCid = null;
-        }
-
-        cleanUpVirtualizationTestSetup(getDevice());
+        killVmAndReconnectAdb();
     }
 
     @Test
     public void testOdrefresh() throws Exception {
-        waitForServiceRunning();
-
         CommandRunner android = new CommandRunner(getDevice());
 
         // Prepare the groundtruth. The compilation on Android should finish successfully.
@@ -103,28 +91,18 @@
                 android.runForResultWithTimeout(ODREFRESH_TIMEOUT_MS, ODREFRESH_BIN, "--check");
         assertThat(result.getExitCode()).isEqualTo(OKAY);
 
-        // Initialize the service with the generated key. Should succeed.
-        android.run(
-                COMPOS_KEY_CMD_BIN,
-                "--cid " + mCid,
-                "generate",
-                TEST_ROOT + "test_key.blob",
-                TEST_ROOT + "test_key.pubkey");
-        android.run(COMPOS_KEY_CMD_BIN, "--cid " + mCid, "init-key", TEST_ROOT + "test_key.blob");
+        // Make sure we generate a fresh instance
+        android.tryRun("rm", "-rf", COMPOS_CURRENT_ROOT);
 
         // Expect the compilation in Compilation OS to finish successfully.
         {
             long start = System.currentTimeMillis();
-            result =
-                    android.runForResultWithTimeout(
-                            ODREFRESH_TIMEOUT_MS,
-                            ODREFRESH_BIN,
-                            "--use-compilation-os=" + mCid,
-                            "--force-compile");
+            result = android.runForResultWithTimeout(ODREFRESH_TIMEOUT_MS, COMPOSD_CMD_BIN);
             long elapsed = System.currentTimeMillis() - start;
-            assertThat(result.getExitCode()).isEqualTo(COMPILATION_SUCCESS);
+            assertThat(result.getExitCode()).isEqualTo(0);
             CLog.i("Comp OS compilation took " + elapsed + "ms");
         }
+        killVmAndReconnectAdb();
 
         // Save the actual checksum for the output directory.
         String actualChecksumSnapshot = checksumDirectoryContent(android, ODREFRESH_OUTPUT_DIR);
@@ -140,35 +118,27 @@
         assertThat(actualChecksumSnapshot).isEqualTo(expectedChecksumSnapshot);
     }
 
-    private void startComposVm() throws DeviceNotAvailableException {
-        final String apkName = "CompOSPayloadApp.apk";
-        final String packageName = "com.android.compos.payload";
-        mCid =
-                startMicrodroid(
-                        getDevice(),
-                        getBuild(),
-                        apkName,
-                        packageName,
-                        "assets/vm_test_config.json",
-                        /* debug */ false,
-                        /* Use default memory */ 0);
-        adbConnectToMicrodroid(getDevice(), mCid);
+    private void killVmAndReconnectAdb() throws Exception {
+        CommandRunner android = new CommandRunner(getDevice());
+
+        // When a VM exits, we tend to see adb disconnecting. So we attempt to reconnect
+        // when we kill it to avoid problems. Of course VirtualizationService may exit anyway
+        // (it's an on-demand service and all its clients have gone), taking the VM with it,
+        // which makes this a bit unpredictable.
+        reconnectHostAdb(getDevice());
+        android.tryRun("killall", "crosvm");
+        reconnectHostAdb(getDevice());
+        android.tryRun("stop", "virtualizationservice");
+        reconnectHostAdb(getDevice());
+
+        // Delete stale data
+        android.tryRun("rm", "-rf", "/data/misc/virtualizationservice/*");
     }
 
-    private void waitForServiceRunning() {
-        try {
-            PollingCheck.waitFor(COMPSVC_READY_LATENCY_MS, this::isServiceRunning);
-        } catch (Exception e) {
-            throw new RuntimeException("Service unavailable", e);
-        }
-    }
-
-    private boolean isServiceRunning() {
-        return tryRunOnMicrodroid("pidof compsvc") != null;
-    }
-
-    private String checksumDirectoryContent(CommandRunner runner, String path)
-            throws DeviceNotAvailableException {
-        return runner.run("find " + path + " -type f -exec sha256sum {} \\; | sort");
+    private String checksumDirectoryContent(CommandRunner runner, String path) throws Exception {
+        // Sort by filename (second column) to make comparison easier.
+        // TODO(b/192690283): Figure out how to make this work for files odex/oat/art files.
+        return runner.run(
+                "find " + path + " -type f -exec sha256sum {} \\; | grep vdex | sort -k2");
     }
 }
diff --git a/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java b/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java
index 24a955b..d62892c 100644
--- a/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java
+++ b/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java
@@ -73,18 +73,26 @@
         // disconnect from microdroid
         tryRunOnHost("adb", "disconnect", MICRODROID_SERIAL);
 
-        // Make sure we're connected to the host adb again (b/194219111)
+        reconnectHostAdb(androidDevice);
+
+        // kill stale VMs and directories
+        android.tryRun("killall", "crosvm");
+        android.tryRun("stop", "virtualizationservice");
+        android.tryRun("rm", "-rf", "/data/misc/virtualizationservice/*");
+    }
+
+    public static void reconnectHostAdb(ITestDevice androidDevice)
+            throws DeviceNotAvailableException {
+        CommandRunner android = new CommandRunner(androidDevice);
+
+        // Make sure we're connected to the host adb; this connection seems to get dropped when a VM
+        // exits.
         for (int retry = 0; retry < 3; ++retry) {
             if (android.tryRun("true") != null) {
                 break;
             }
             androidDevice.waitForDeviceOnline(1000);
         }
-
-        // kill stale VMs and directories
-        android.tryRun("killall", "crosvm");
-        android.tryRun("rm", "-rf", "/data/misc/virtualizationservice/*");
-        android.tryRun("stop", "virtualizationservice");
     }
 
     public static void testIfDeviceIsCapable(ITestDevice androidDevice)