Merge changes Ia10f2b6e,If05b871b

* changes:
  Serialise number of CPUs.
  Don't fall back to unprotected mode if protected is not supported.
diff --git a/compos/common/compos_client.rs b/compos/common/compos_client.rs
index f4b3440..6a35fb0 100644
--- a/compos/common/compos_client.rs
+++ b/compos/common/compos_client.rs
@@ -122,6 +122,7 @@
             configPath: config_path.to_owned(),
             debugLevel: debug_level,
             extraIdsigs: vec![idsig_manifest_apk_fd],
+            protectedVm: false,
             memoryMib: VM_MEMORY_MIB,
             numCpus: parameters.cpus.map_or(1, NonZeroU32::get) as i32,
             cpuAffinity: parameters.cpu_set.clone(),
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java b/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
index 7d1f9b0..04a90e0 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
@@ -51,6 +51,7 @@
     private static final String KEY_APKPATH = "apkPath";
     private static final String KEY_PAYLOADCONFIGPATH = "payloadConfigPath";
     private static final String KEY_DEBUGLEVEL = "debugLevel";
+    private static final String KEY_PROTECTED_VM = "protectedVm";
     private static final String KEY_MEMORY_MIB = "memoryMib";
     private static final String KEY_NUM_CPUS = "numCpus";
     private static final String KEY_CPU_AFFINITY = "cpuAffinity";
@@ -83,6 +84,11 @@
     private final DebugLevel mDebugLevel;
 
     /**
+     * Whether to run the VM in protected mode, so the host can't access its memory.
+     */
+    private final boolean mProtectedVm;
+
+    /**
      * The amount of RAM to give the VM, in MiB. If this is 0 or negative the default will be used.
      */
     private final int mMemoryMib;
@@ -111,6 +117,7 @@
             @NonNull Signature[] certs,
             @NonNull String payloadConfigPath,
             DebugLevel debugLevel,
+            boolean protectedVm,
             int memoryMib,
             int numCpus,
             String cpuAffinity) {
@@ -118,6 +125,7 @@
         mCerts = certs;
         mPayloadConfigPath = payloadConfigPath;
         mDebugLevel = debugLevel;
+        mProtectedVm = protectedVm;
         mMemoryMib = memoryMib;
         mNumCpus = numCpus;
         mCpuAffinity = cpuAffinity;
@@ -149,11 +157,12 @@
             throw new VirtualMachineException("No payloadConfigPath");
         }
         final DebugLevel debugLevel = DebugLevel.values()[b.getInt(KEY_DEBUGLEVEL)];
+        final boolean protectedVm = b.getBoolean(KEY_PROTECTED_VM);
         final int memoryMib = b.getInt(KEY_MEMORY_MIB);
         final int numCpus = b.getInt(KEY_NUM_CPUS);
         final String cpuAffinity = b.getString(KEY_CPU_AFFINITY);
-        return new VirtualMachineConfig(apkPath, certs, payloadConfigPath, debugLevel, memoryMib,
-                numCpus, cpuAffinity);
+        return new VirtualMachineConfig(apkPath, certs, payloadConfigPath, debugLevel, protectedVm,
+                memoryMib, numCpus, cpuAffinity);
     }
 
     /** Persists this config to a stream, for example a file. */
@@ -169,6 +178,8 @@
         b.putStringArray(KEY_CERTS, certs);
         b.putString(KEY_PAYLOADCONFIGPATH, mPayloadConfigPath);
         b.putInt(KEY_DEBUGLEVEL, mDebugLevel.ordinal());
+        b.putBoolean(KEY_PROTECTED_VM, mProtectedVm);
+        b.putInt(KEY_NUM_CPUS, mNumCpus);
         if (mMemoryMib > 0) {
             b.putInt(KEY_MEMORY_MIB, mMemoryMib);
         }
@@ -219,6 +230,7 @@
                 parcel.debugLevel = VirtualMachineAppConfig.DebugLevel.FULL;
                 break;
         }
+        parcel.protectedVm = mProtectedVm;
         parcel.memoryMib = mMemoryMib;
         parcel.numCpus = mNumCpus;
         parcel.cpuAffinity = mCpuAffinity;
@@ -230,16 +242,17 @@
         private Context mContext;
         private String mPayloadConfigPath;
         private DebugLevel mDebugLevel;
+        private boolean mProtectedVm;
         private int mMemoryMib;
         private int mNumCpus;
         private String mCpuAffinity;
-        // TODO(jiyong): add more items like # of cpu, size of ram, debuggability, etc.
 
         /** Creates a builder for the given context (APK), and the payload config file in APK. */
         public Builder(@NonNull Context context, @NonNull String payloadConfigPath) {
             mContext = context;
             mPayloadConfigPath = payloadConfigPath;
             mDebugLevel = DebugLevel.NONE;
+            mProtectedVm = false;
             mNumCpus = 1;
             mCpuAffinity = null;
         }
@@ -250,6 +263,12 @@
             return this;
         }
 
+        /** Sets whether to protect the VM memory from the host. Defaults to false. */
+        public Builder protectedVm(boolean protectedVm) {
+            mProtectedVm = protectedVm;
+            return this;
+        }
+
         /**
          * Sets the amount of RAM to give the VM. If this is zero or negative then the default will
          * be used.
@@ -309,8 +328,8 @@
             }
 
             return new VirtualMachineConfig(
-                    apkPath, certs, mPayloadConfigPath, mDebugLevel, mMemoryMib, mNumCpus,
-                    mCpuAffinity);
+                    apkPath, certs, mPayloadConfigPath, mDebugLevel, mProtectedVm, mMemoryMib,
+                    mNumCpus, mCpuAffinity);
         }
     }
 }
diff --git a/microdroid/microdroid.json b/microdroid/microdroid.json
index 0c294e9..cb27a24 100644
--- a/microdroid/microdroid.json
+++ b/microdroid/microdroid.json
@@ -37,6 +37,5 @@
       "writable": true
     }
   ],
-  "memory_mib": 256,
-  "protected": false
+  "memory_mib": 256
 }
diff --git a/virtualizationservice/Android.bp b/virtualizationservice/Android.bp
index 653524e..b82064b 100644
--- a/virtualizationservice/Android.bp
+++ b/virtualizationservice/Android.bp
@@ -31,7 +31,6 @@
         "libcommand_fds",
         "libdisk",
         "libidsig",
-        "libkvm",
         "liblog_rust",
         "libmicrodroid_metadata",
         "libmicrodroid_payload_config",
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
index 8265f96..c36e561 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
@@ -47,6 +47,9 @@
     /** Debug level of the VM */
     DebugLevel debugLevel;
 
+    /** Whether the VM should be a protected VM. */
+    boolean protectedVm;
+
     /**
      * The amount of RAM to give the VM, in MiB. If this is 0 or negative then it will default to
      * the value in microdroid.json, if any, or the crosvm default.
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index 42eb1e6..5b0c9b7 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -50,7 +50,6 @@
 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;
@@ -190,9 +189,7 @@
             VirtualMachineConfig::AppConfig(config) => BorrowedOrOwned::Owned(
                 load_app_config(config, &temporary_directory).map_err(|e| {
                     error!("Failed to load app config from {}: {}", &config.configPath, e);
-                    // At this point, we do not know the protected status of Vm
-                    // setting it to false, though this may not be correct.
-                    write_vm_creation_stats(false, false);
+                    write_vm_creation_stats(config.protectedVm, false);
                     new_binder_exception(
                         ExceptionCode::SERVICE_SPECIFIC,
                         format!("Failed to load app config from {}: {}", &config.configPath, e),
@@ -202,7 +199,15 @@
             VirtualMachineConfig::RawConfig(config) => BorrowedOrOwned::Borrowed(config),
         };
         let config = config.as_ref();
-        let protected_vm = config.protectedVm;
+        let protected = config.protectedVm;
+
+        // Debug level FULL is only supported for non-protected VMs.
+        if is_debug_level_full && protected {
+            return Err(new_binder_exception(
+                ExceptionCode::SERVICE_SPECIFIC,
+                "FULL debug level not supported for protected VMs.",
+            ));
+        };
 
         // Check if partition images are labeled incorrectly. This is to prevent random images
         // which are not protected by the Android Verified Boot (e.g. bits downloaded by apps) from
@@ -226,7 +231,7 @@
         let zero_filler_path = temporary_directory.join("zero.img");
         write_zero_filler(&zero_filler_path).map_err(|e| {
             error!("Failed to make composite image: {}", e);
-            write_vm_creation_stats(protected_vm, false);
+            write_vm_creation_stats(protected, false);
             new_binder_exception(
                 ExceptionCode::SERVICE_SPECIFIC,
                 format!("Failed to make composite image: {}", e),
@@ -248,24 +253,6 @@
             })
             .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,
@@ -292,7 +279,7 @@
             )
             .map_err(|e| {
                 error!("Failed to create VM with config {:?}: {}", config, e);
-                write_vm_creation_stats(protected_vm, false);
+                write_vm_creation_stats(protected, false);
                 new_binder_exception(
                     ExceptionCode::SERVICE_SPECIFIC,
                     format!("Failed to create VM: {}", e),
@@ -300,7 +287,7 @@
             })?,
         );
         state.add_vm(Arc::downgrade(&instance));
-        write_vm_creation_stats(protected_vm, true);
+        write_vm_creation_stats(protected, true);
         Ok(VirtualMachine::create(instance))
     }
 
@@ -587,6 +574,7 @@
         vm_config.memoryMib = config.memoryMib;
     }
 
+    vm_config.protectedVm = config.protectedVm;
     vm_config.numCpus = config.numCpus;
     vm_config.cpuAffinity = config.cpuAffinity.clone();
 
diff --git a/vm/src/main.rs b/vm/src/main.rs
index ad8c201..25f9bfb 100644
--- a/vm/src/main.rs
+++ b/vm/src/main.rs
@@ -72,6 +72,10 @@
         #[structopt(long, default_value = "none", parse(try_from_str=parse_debug_level))]
         debug: DebugLevel,
 
+        /// Run VM in protected mode.
+        #[structopt(short, long)]
+        protected: bool,
+
         /// Memory size (in MiB) of the VM. If unspecified, defaults to the value of `memory_mib`
         /// in the VM config file.
         #[structopt(short, long)]
@@ -174,6 +178,7 @@
             console,
             log,
             debug,
+            protected,
             mem,
             cpus,
             cpu_affinity,
@@ -188,6 +193,7 @@
             console.as_deref(),
             log.as_deref(),
             debug,
+            protected,
             mem,
             cpus,
             cpu_affinity,
diff --git a/vm/src/run.rs b/vm/src/run.rs
index 8583fe2..d558add 100644
--- a/vm/src/run.rs
+++ b/vm/src/run.rs
@@ -50,6 +50,7 @@
     console_path: Option<&Path>,
     log_path: Option<&Path>,
     debug_level: DebugLevel,
+    protected: bool,
     mem: Option<u32>,
     cpus: Option<u32>,
     cpu_affinity: Option<String>,
@@ -100,6 +101,7 @@
         instanceImage: open_parcel_file(instance, true /* writable */)?.into(),
         configPath: config_path.to_owned(),
         debugLevel: debug_level,
+        protectedVm: protected,
         memoryMib: mem.unwrap_or(0) as i32, // 0 means use the VM default
         numCpus: cpus.unwrap_or(1) as i32,
         cpuAffinity: cpu_affinity,