Merge "Make sure a deleted VM stays deleted"
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachine.java b/javalib/src/android/system/virtualmachine/VirtualMachine.java
index db5b4d1..b040cc0 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachine.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachine.java
@@ -311,6 +311,9 @@
     @Nullable
     private ParcelFileDescriptor mLogWriter;
 
+    @GuardedBy("mLock")
+    private boolean mWasDeleted = false;
+
     /** The registered callback */
     @GuardedBy("mCallbackLock")
     @Nullable
@@ -506,6 +509,9 @@
     void delete(Context context, String name) throws VirtualMachineException {
         synchronized (mLock) {
             checkStopped();
+            // Once we explicitly delete a VM it must remain permanently in the deleted state;
+            // if a new VM is created with the same name (and files) that's unrelated.
+            mWasDeleted = true;
             deleteVmDirectory(context, name);
         }
     }
@@ -587,6 +593,9 @@
     public int getStatus() {
         IVirtualMachine virtualMachine;
         synchronized (mLock) {
+            if (mWasDeleted) {
+                return STATUS_DELETED;
+            }
             virtualMachine = mVirtualMachine;
         }
         if (virtualMachine == null) {
@@ -617,7 +626,7 @@
     // Throw an appropriate exception if we have a running VM, or the VM has been deleted.
     @GuardedBy("mLock")
     private void checkStopped() throws VirtualMachineException {
-        if (!mVmRootPath.exists()) {
+        if (mWasDeleted || !mVmRootPath.exists()) {
             throw new VirtualMachineException("VM has been deleted");
         }
         if (mVirtualMachine == null) {
@@ -653,7 +662,7 @@
                     && stateToStatus(mVirtualMachine.getState()) == STATUS_RUNNING) {
                 return mVirtualMachine;
             } else {
-                if (!mVmRootPath.exists()) {
+                if (mWasDeleted || !mVmRootPath.exists()) {
                     throw new VirtualMachineException("VM has been deleted");
                 } else {
                     throw new VirtualMachineException("VM is not in running state");
diff --git a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
index f3bbbf1..160b679 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -429,31 +429,37 @@
         VirtualMachineManager vmm = getVirtualMachineManager();
         String vmName = "vmName";
 
-        // VM does not yet exist
-        assertThat(vmm.get(vmName)).isNull();
+        try {
+            // VM does not yet exist
+            assertThat(vmm.get(vmName)).isNull();
 
-        VirtualMachine vm1 = vmm.create(vmName, config);
+            VirtualMachine vm1 = vmm.create(vmName, config);
 
-        // Now it does, and we should get the same instance back
-        assertThat(vmm.get(vmName)).isSameInstanceAs(vm1);
-        assertThat(vmm.getOrCreate(vmName, config)).isSameInstanceAs(vm1);
+            // Now it does, and we should get the same instance back
+            assertThat(vmm.get(vmName)).isSameInstanceAs(vm1);
+            assertThat(vmm.getOrCreate(vmName, config)).isSameInstanceAs(vm1);
 
-        // Can't recreate it though
-        assertThrowsVmException(() -> vmm.create(vmName, config));
+            // Can't recreate it though
+            assertThrowsVmException(() -> vmm.create(vmName, config));
 
-        vmm.delete(vmName);
-        assertThat(vmm.get(vmName)).isNull();
+            vmm.delete(vmName);
+            assertThat(vmm.get(vmName)).isNull();
 
-        // Now that we deleted the old one, this should create rather than get, and it should be a
-        // new instance.
-        VirtualMachine vm2 = vmm.getOrCreate(vmName, config);
-        assertThat(vm2).isNotSameInstanceAs(vm1);
+            // Now that we deleted the old one, this should create rather than get, and it should be
+            // a new instance.
+            VirtualMachine vm2 = vmm.getOrCreate(vmName, config);
+            assertThat(vm2).isNotSameInstanceAs(vm1);
 
-        // Subsequent gets should return this new one.
-        assertThat(vmm.get(vmName)).isSameInstanceAs(vm2);
-        assertThat(vmm.getOrCreate(vmName, config)).isSameInstanceAs(vm2);
+            // The old one must remain deleted, or we'd have two VirtualMachine instances referring
+            // to the same VM.
+            assertThat(vm1.getStatus()).isEqualTo(STATUS_DELETED);
 
-        vmm.delete(vmName);
+            // Subsequent gets should return this new one.
+            assertThat(vmm.get(vmName)).isSameInstanceAs(vm2);
+            assertThat(vmm.getOrCreate(vmName, config)).isSameInstanceAs(vm2);
+        } finally {
+            vmm.delete(vmName);
+        }
     }
 
     @Test