Specify virtual platform version and enforce it

VM config can now specify the requirement on the virtual platform
version. At runtime, the requirement is matched against the actual
virtual platform version that crosvm implements. If they don't match,
the VM can't be created. The version format follows SemVer, allowing us
to express backwards compatible and incompatible changes in the future.

Bug: 193504487
Test: atest VirtualizationTestCases
Change-Id: I23d370081e10399502178b9cfe8a46b05addf186
diff --git a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
index 1218b68..58935d8 100644
--- a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
+++ b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
@@ -122,6 +122,7 @@
         int memory_mib;
         @SerializedName("protected")
         boolean isProtected;
+        String platform_version;
     }
 
     static class Disk {
diff --git a/tests/vsock_test.cc b/tests/vsock_test.cc
index c478f64..0fc451d 100644
--- a/tests/vsock_test.cc
+++ b/tests/vsock_test.cc
@@ -48,6 +48,7 @@
 static constexpr const char kVmInitrdPath[] = "/data/local/tmp/virt-test/initramfs";
 static constexpr const char kVmParams[] = "rdinit=/bin/init bin/vsock_client 2 45678 HelloWorld";
 static constexpr const char kTestMessage[] = "HelloWorld";
+static constexpr const char kPlatformVersion[] = "~1.0";
 
 /** Returns true if the kernel supports unprotected VMs. */
 bool isUnprotectedVmSupported() {
@@ -82,6 +83,7 @@
     raw_config.initrd = ParcelFileDescriptor(unique_fd(open(kVmInitrdPath, O_RDONLY | O_CLOEXEC)));
     raw_config.params = kVmParams;
     raw_config.protectedVm = false;
+    raw_config.platformVersion = kPlatformVersion;
 
     VirtualMachineConfig config(std::move(raw_config));
     sp<IVirtualMachine> vm;
@@ -112,4 +114,17 @@
     ASSERT_EQ(msg, kTestMessage);
 }
 
+TEST_F(VirtualizationTest, RejectIncompatiblePlatformVersion) {
+    VirtualMachineRawConfig raw_config;
+    raw_config.kernel = ParcelFileDescriptor(unique_fd(open(kVmKernelPath, O_RDONLY | O_CLOEXEC)));
+    raw_config.initrd = ParcelFileDescriptor(unique_fd(open(kVmInitrdPath, O_RDONLY | O_CLOEXEC)));
+    raw_config.params = kVmParams;
+    raw_config.platformVersion = "~2.0"; // The current platform version is 1.0.0.
+
+    VirtualMachineConfig config(std::move(raw_config));
+    sp<IVirtualMachine> vm;
+    auto status = mVirtualizationService->createVm(config, std::nullopt, std::nullopt, &vm);
+    ASSERT_FALSE(status.isOk());
+}
+
 } // namespace virt