Add isNewInstanceStatus to vm_payload api

This can be used by payload to determine if this the first boot of the
VM. This becomes useful since `AVmPayload_getVmInstanceSecret` is
essentially equivalent to get_or_create secrets. Payload should be able
to check if the secrets were newly created or are the old ones & this
could be used to meaningfully use the secret.

For ex, encryptedstore or other data encrypted using the VM secrets
restored via backup and restore cannot be meaningfully decrypted using
newly created secrets on the new device.

Test: MicrodroidTests#isNewInstanceTest
Bug: 327576724
Bug: 378911776
Change-Id: I05983c7b1239d29f86f2b3fb9be7e3a1f2f91039
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 797214c..a50ce98 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -1941,6 +1941,44 @@
 
     @Test
     @CddTest
+    public void isNewInstanceTest() throws Exception {
+        assumeSupportedDevice();
+
+        VirtualMachineConfig config =
+                newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
+                        .setMemoryBytes(minMemoryRequired())
+                        .setDebugLevel(DEBUG_LEVEL_FULL)
+                        .build();
+        // TODO(b/325094712): Cuttlefish doesn't support device tree overlays which is required to
+        // find if the VM run is a new instance.
+        assumeFalse(
+                "Cuttlefish/Goldfish doesn't support device tree under /proc/device-tree",
+                isCuttlefish() || isGoldfish());
+        VirtualMachine vm = forceCreateNewVirtualMachine("test_vm_a", config);
+        TestResults testResults =
+                runVmTestService(
+                        TAG,
+                        vm,
+                        (ts, tr) -> {
+                            tr.mIsNewInstance = ts.isNewInstance();
+                        });
+        testResults.assertNoException();
+        assertThat(testResults.mIsNewInstance).isTrue();
+
+        // Re-run the same VM & ensure isNewInstance is false.
+        testResults =
+                runVmTestService(
+                        TAG,
+                        vm,
+                        (ts, tr) -> {
+                            tr.mIsNewInstance = ts.isNewInstance();
+                        });
+        testResults.assertNoException();
+        assertThat(testResults.mIsNewInstance).isFalse();
+    }
+
+    @Test
+    @CddTest(requirements = {"9.17/C-1-1", "9.17/C-2-1"})
     public void canReadFileFromAssets_debugFull() throws Exception {
         assumeSupportedDevice();
 
diff --git a/tests/testapk/src/native/testbinary.cpp b/tests/testapk/src/native/testbinary.cpp
index 83b6d23..06c7e9d 100644
--- a/tests/testapk/src/native/testbinary.cpp
+++ b/tests/testapk/src/native/testbinary.cpp
@@ -364,6 +364,11 @@
             return ScopedAStatus::ok();
         }
 
+        ScopedAStatus isNewInstance(bool* is_new_instance_out) override {
+            *is_new_instance_out = AVmPayload_isNewInstance();
+            return ScopedAStatus::ok();
+        }
+
         ScopedAStatus quit() override { exit(0); }
     };
     auto testService = ndk::SharedRefBase::make<TestService>();
diff --git a/tests/testapk/src/native/testbinary.rs b/tests/testapk/src/native/testbinary.rs
index dee3b8e..c9d46b8 100644
--- a/tests/testapk/src/native/testbinary.rs
+++ b/tests/testapk/src/native/testbinary.rs
@@ -132,6 +132,9 @@
     fn insecurelyWritePayloadRpData(&self, _: &[u8; 32]) -> BinderResult<()> {
         unimplemented()
     }
+    fn isNewInstance(&self) -> BinderResult<bool> {
+        unimplemented()
+    }
 }
 
 fn unimplemented<T>() -> BinderResult<T> {