Merge "Remove VM attestation flag check in VmAttestationTestApp" into main
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/PortsStateManager.java b/android/TerminalApp/java/com/android/virtualization/terminal/PortsStateManager.java
index 56ecd96..5321d89 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/PortsStateManager.java
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/PortsStateManager.java
@@ -116,6 +116,18 @@
         notifyPortsStateUpdated(activePorts, activePorts);
     }
 
+    void clearEnabledPorts() {
+        Set<Integer> activePorts;
+        synchronized (mLock) {
+            SharedPreferences.Editor editor = mSharedPref.edit();
+            editor.clear();
+            editor.apply();
+            mEnabledPorts.clear();
+            activePorts = mActivePorts;
+        }
+        notifyPortsStateUpdated(activePorts, activePorts);
+    }
+
     void registerListener(Listener listener) {
         synchronized (mLock) {
             mListeners.add(listener);
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsRecoveryActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsRecoveryActivity.kt
index 0d74eb0..a4d43b8 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsRecoveryActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsRecoveryActivity.kt
@@ -103,6 +103,7 @@
                 image.uninstallAndBackup()
                 backupDone = true
             } else {
+                PortsStateManager.getInstance(this).clearEnabledPorts()
                 image.uninstallFully()
             }
         } catch (e: IOException) {
diff --git a/tests/Terminal/src/com/android/virtualization/terminal/TerminalAppTest.java b/tests/Terminal/src/com/android/virtualization/terminal/TerminalAppTest.java
index 42c31e3..4a18ee8 100644
--- a/tests/Terminal/src/com/android/virtualization/terminal/TerminalAppTest.java
+++ b/tests/Terminal/src/com/android/virtualization/terminal/TerminalAppTest.java
@@ -90,6 +90,7 @@
 
     @After
     public void tearDown() throws IOException {
+        PortsStateManager.getInstance(mTargetContext).clearEnabledPorts();
         InstalledImage.getDefault(mTargetContext).uninstallFully();
     }
 }
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 2986bdc..e6f15ff 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
@@ -21,6 +21,7 @@
 import static android.content.pm.PackageManager.FEATURE_WATCH;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
 import static com.google.common.truth.TruthJUnit.assume;
 
 import static org.junit.Assume.assumeFalse;
@@ -257,6 +258,14 @@
         return SystemProperties.getInt("ro.board.api_level", 0);
     }
 
+    /**
+     * @return The first vendor API level when the vendor images for an SoC that is qualified for
+     *     vendor freeze are first released with this property, or 0 if the property is not set.
+     */
+    protected static int getFirstVendorApiLevel() {
+        return SystemProperties.getInt("ro.board.first_api_level", 0);
+    }
+
     protected void assumeSupportedDevice() {
         assume().withMessage("Skip on 5.4 kernel. b/218303240")
                 .that(KERNEL_VERSION)
@@ -277,6 +286,24 @@
                 .isFalse();
     }
 
+    protected void ensureVmAttestationSupported() throws Exception {
+        // The first vendor API level is checked because VM attestation requires the VM DICE chain
+        // to be ROM-rooted.
+        int firstVendorApiLevel = getFirstVendorApiLevel();
+        boolean isRemoteAttestationSupported =
+                getVirtualMachineManager().isRemoteAttestationSupported();
+        if (firstVendorApiLevel >= 202504) {
+            assertWithMessage(
+                            "First vendor API '"
+                                    + firstVendorApiLevel
+                                    + "' (>=202504) must support VM remote attestation")
+                    .that(isRemoteAttestationSupported)
+                    .isTrue();
+        } else {
+            assumeTrue("Skip on VM remote attestation not supported", isRemoteAttestationSupported);
+        }
+    }
+
     public abstract static class VmEventListener implements VirtualMachineCallback {
         private ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
         private OptionalLong mVcpuStartedNanoTime = OptionalLong.empty();
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 e69b8f6..dff408c 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -301,10 +301,7 @@
     public void vmAttestationWhenRemoteAttestationIsSupported() throws Exception {
         // pVM remote attestation is only supported on protected VMs.
         assumeProtectedVM();
-        assumeFeatureEnabled(VirtualMachineManager.FEATURE_REMOTE_ATTESTATION);
-        assume().withMessage("Test needs Remote Attestation support")
-                .that(getVirtualMachineManager().isRemoteAttestationSupported())
-                .isTrue();
+        ensureVmAttestationSupported();
         VirtualMachineConfig config =
                 newVmConfigBuilderWithPayloadBinary(VM_ATTESTATION_PAYLOAD_PATH)
                         .setProtectedVm(mProtectedVm)
diff --git a/tests/vm_attestation/src/java/com/android/virt/rkpd/vm_attestation/testapp/RkpdVmAttestationTest.java b/tests/vm_attestation/src/java/com/android/virt/rkpd/vm_attestation/testapp/RkpdVmAttestationTest.java
index 340de72..1762b6d 100644
--- a/tests/vm_attestation/src/java/com/android/virt/rkpd/vm_attestation/testapp/RkpdVmAttestationTest.java
+++ b/tests/vm_attestation/src/java/com/android/virt/rkpd/vm_attestation/testapp/RkpdVmAttestationTest.java
@@ -26,7 +26,6 @@
 import android.net.NetworkCapabilities;
 import android.system.virtualmachine.VirtualMachine;
 import android.system.virtualmachine.VirtualMachineConfig;
-import android.system.virtualmachine.VirtualMachineManager;
 
 import com.android.microdroid.test.device.MicrodroidDeviceTestBase;
 import com.android.virt.vm_attestation.testservice.IAttestationService.SigningResult;
@@ -86,7 +85,6 @@
         assume().withMessage("RKP Integration tests rely on network availability.")
                 .that(isNetworkConnected(getContext()))
                 .isTrue();
-        assumeFeatureEnabled(VirtualMachineManager.FEATURE_REMOTE_ATTESTATION);
         assume().withMessage("Test needs Remote Attestation support")
                 .that(getVirtualMachineManager().isRemoteAttestationSupported())
                 .isTrue();