Run microdroid in protected mode

... but run in non-protected mode when

(1) on non-aarch64 architectures, or
(2) debug level is set to FULL

Bug: 210803811
Test: watch TH for all our tests
Change-Id: I4d33be8d560b14c2c2e3ce50605298ad58fbf42d
diff --git a/microdroid/microdroid.json b/microdroid/microdroid.json
index 211bae4..8496052 100644
--- a/microdroid/microdroid.json
+++ b/microdroid/microdroid.json
@@ -33,5 +33,6 @@
       "writable": true
     }
   ],
-  "memory_mib": 2048
+  "memory_mib": 2048,
+  "protected": true
 }
diff --git a/virtualizationservice/Android.bp b/virtualizationservice/Android.bp
index 37350ff..277432b 100644
--- a/virtualizationservice/Android.bp
+++ b/virtualizationservice/Android.bp
@@ -31,6 +31,7 @@
         "libcommand_fds",
         "libdisk",
         "libidsig",
+        "libkvm",
         "liblog_rust",
         "libmicrodroid_metadata",
         "libmicrodroid_payload_config",
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index e6210e2..1bd7ee0 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -49,6 +49,7 @@
 use binder_common::{lazy_service::LazyServiceGuard, new_binder_exception};
 use disk::QcowFile;
 use idsig::{HashAlgorithm, V4Signature};
+use kvm::{Kvm, Cap};
 use log::{debug, error, info, warn};
 use microdroid_payload_config::VmPayloadConfig;
 use rustutils::system_properties;
@@ -172,6 +173,13 @@
         }
 
         let is_app_config = matches!(config, VirtualMachineConfig::AppConfig(_));
+        let is_debug_level_full = matches!(
+            config,
+            VirtualMachineConfig::AppConfig(VirtualMachineAppConfig {
+                debugLevel: DebugLevel::FULL,
+                ..
+            })
+        );
 
         let config = match config {
             VirtualMachineConfig::AppConfig(config) => BorrowedOrOwned::Owned(
@@ -230,6 +238,24 @@
             })
             .collect::<Result<Vec<DiskFile>, _>>()?;
 
+        let protected_vm_supported = Kvm::new()
+            .map_err(|e| new_binder_exception(ExceptionCode::SERVICE_SPECIFIC, e.to_string()))?
+            .check_extension(Cap::ArmProtectedVm);
+        let protected = config.protectedVm && protected_vm_supported;
+        if config.protectedVm && !protected_vm_supported {
+            warn!("Protected VM was requested, but it isn't supported on this machine. Ignored.");
+        }
+
+        // And force run in non-protected mode when debug level is FULL
+        let protected = if is_debug_level_full {
+            if protected {
+                warn!("VM will run in FULL debug level. Running in non-protected mode");
+            }
+            false
+        } else {
+            protected
+        };
+
         // Actually start the VM.
         let crosvm_config = CrosvmConfig {
             cid,
@@ -238,7 +264,7 @@
             initrd: maybe_clone_file(&config.initrd)?,
             disks,
             params: config.params.to_owned(),
-            protected: config.protectedVm,
+            protected,
             memory_mib: config.memoryMib.try_into().ok().and_then(NonZeroU32::new),
             console_fd,
             log_fd,