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/libs/vmconfig/Android.bp b/libs/vmconfig/Android.bp
index 321eba0..1aee1ce 100644
--- a/libs/vmconfig/Android.bp
+++ b/libs/vmconfig/Android.bp
@@ -10,8 +10,9 @@
     rustlibs: [
         "android.system.virtualizationservice-rust",
         "libanyhow",
-        "libserde_json",
+        "libsemver",
         "libserde",
+        "libserde_json",
     ],
     apex_available: [
         "com.android.virt",
diff --git a/libs/vmconfig/src/lib.rs b/libs/vmconfig/src/lib.rs
index 9c3e671..607b347 100644
--- a/libs/vmconfig/src/lib.rs
+++ b/libs/vmconfig/src/lib.rs
@@ -22,6 +22,7 @@
 };
 
 use anyhow::{bail, Context, Error, Result};
+use semver::VersionReq;
 use serde::{Deserialize, Serialize};
 use std::convert::TryInto;
 use std::fs::{File, OpenOptions};
@@ -51,6 +52,9 @@
     /// The amount of RAM to give the VM, in MiB.
     #[serde(default)]
     pub memory_mib: Option<NonZeroU32>,
+    /// Version or range of versions of the virtual platform that this config is compatible with.
+    /// The format follows SemVer (https://semver.org).
+    pub platform_version: VersionReq,
 }
 
 impl VmConfig {
@@ -95,6 +99,7 @@
             disks: self.disks.iter().map(DiskImage::to_parcelable).collect::<Result<_, Error>>()?,
             protectedVm: self.protected,
             memoryMib: memory_mib,
+            platformVersion: self.platform_version.to_string(),
             ..Default::default()
         })
     }