Add logging from VMCreate method

this pushes the Westworld atom to statsD Atom from virtualization service. See go/westworld-create-atom#step-2-add-your-atom-logging-code

Change-Id: I69abf3de349609c8596d55c6379e64c415b36d43
Test: statsd_testdrive ATOM_ID
Bug: b/209008347
diff --git a/statslog_virtualization/Android.bp b/statslog_virtualization/Android.bp
new file mode 100644
index 0000000..846d12b
--- /dev/null
+++ b/statslog_virtualization/Android.bp
@@ -0,0 +1,67 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Autogenerate the class (and respective headers) with logging methods and constants
+genrule {
+    name: "statslog_virtualization_header.rs",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --module virtualizationservice --minApiLevel 34 --rustHeader $(genDir)/statslog_virtualization_header.rs --rustHeaderCrate statslog_virtualization_rust_header",
+    out: [
+        "statslog_virtualization_header.rs",
+    ],
+}
+
+rust_library {
+    name: "libstatslog_virtualization_rust_header",
+    crate_name: "statslog_virtualization_rust_header",
+    srcs: [
+        "statslog_header_wrapper.rs",
+        ":statslog_virtualization_header.rs",
+    ],
+    rustlibs: [
+        "libstatspull_bindgen",
+        "libthiserror",
+    ],
+    apex_available: [
+        "com.android.virt",
+    ],
+
+}
+
+genrule {
+    name: "statslog_virtualization.rs",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --module virtualizationservice --minApiLevel 34 --rustHeaderCrate statslog_virtualization_rust_header --rust $(genDir)/statslog_virtualization.rs",
+    out: [
+        "statslog_virtualization.rs",
+    ],
+}
+
+rust_library {
+    name: "libstatslog_virtualization_rust",
+    crate_name: "statslog_virtualization_rust",
+    srcs: [
+        "statslog_wrapper.rs",
+        ":statslog_virtualization.rs",
+    ],
+    rustlibs: [
+        "libstatslog_virtualization_rust_header",
+        "libstatspull_bindgen",
+    ],
+    apex_available: [
+        "com.android.virt",
+    ],
+
+}
diff --git a/statslog_virtualization/statslog_header_wrapper.rs b/statslog_virtualization/statslog_header_wrapper.rs
new file mode 100644
index 0000000..39ff51f
--- /dev/null
+++ b/statslog_virtualization/statslog_header_wrapper.rs
@@ -0,0 +1,4 @@
+#![allow(clippy::too_many_arguments)]
+#![allow(missing_docs)]
+
+include!(concat!(env!("OUT_DIR"), "/statslog_virtualization_header.rs"));
diff --git a/statslog_virtualization/statslog_wrapper.rs b/statslog_virtualization/statslog_wrapper.rs
new file mode 100644
index 0000000..4d1a0fa
--- /dev/null
+++ b/statslog_virtualization/statslog_wrapper.rs
@@ -0,0 +1,5 @@
+#![allow(clippy::too_many_arguments)]
+#![allow(missing_docs)]
+#![allow(unused)]
+
+include!(concat!(env!("OUT_DIR"), "/statslog_virtualization.rs"));
diff --git a/virtualizationservice/Android.bp b/virtualizationservice/Android.bp
index c3ab39a..653524e 100644
--- a/virtualizationservice/Android.bp
+++ b/virtualizationservice/Android.bp
@@ -43,6 +43,7 @@
         "libserde_json",
         "libserde_xml_rs",
         "libshared_child",
+        "libstatslog_virtualization_rust",
         "libvmconfig",
         "libzip",
         "libvsock",
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index c264270..6098821 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -53,6 +53,7 @@
 use log::{debug, error, info, warn};
 use microdroid_payload_config::VmPayloadConfig;
 use rustutils::system_properties;
+use statslog_virtualization_rust::vm_creation_requested::{stats_write, Hypervisor};
 use std::convert::TryInto;
 use std::ffi::CStr;
 use std::fs::{create_dir, File, OpenOptions};
@@ -146,6 +147,9 @@
         // Make directory for temporary files.
         let temporary_directory: PathBuf = format!("{}/{}", TEMPORARY_DIRECTORY, cid).into();
         create_dir(&temporary_directory).map_err(|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);
             error!(
                 "Failed to create temporary directory {:?} for VM files: {}",
                 temporary_directory, e
@@ -185,6 +189,9 @@
             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);
                     new_binder_exception(
                         ExceptionCode::SERVICE_SPECIFIC,
                         format!("Failed to load app config from {}: {}", &config.configPath, e),
@@ -194,6 +201,7 @@
             VirtualMachineConfig::RawConfig(config) => BorrowedOrOwned::Borrowed(config),
         };
         let config = config.as_ref();
+        let protected_vm = config.protectedVm;
 
         // 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
@@ -217,6 +225,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);
             new_binder_exception(
                 ExceptionCode::SERVICE_SPECIFIC,
                 format!("Failed to make composite image: {}", e),
@@ -282,6 +291,7 @@
             )
             .map_err(|e| {
                 error!("Failed to create VM with config {:?}: {}", config, e);
+                write_vm_creation_stats(protected_vm, false);
                 new_binder_exception(
                     ExceptionCode::SERVICE_SPECIFIC,
                     format!("Failed to create VM: {}", e),
@@ -289,6 +299,7 @@
             })?,
         );
         state.add_vm(Arc::downgrade(&instance));
+        write_vm_creation_stats(protected_vm, true);
         Ok(VirtualMachine::create(instance))
     }
 
@@ -437,6 +448,16 @@
     }
 }
 
+/// Write the stats of VMCreation to statsd
+fn write_vm_creation_stats(protected: bool, success: bool) {
+    match stats_write(Hypervisor::Pkvm, protected, success) {
+        Err(e) => {
+            info!("stastlog_rust fails with error: {}", e);
+        }
+        Ok(_) => info!("stastlog_rust succeeded for virtualization service"),
+    }
+}
+
 /// Waits for incoming connections from VM. If a new connection is made, stores the stream in the
 /// corresponding `VmInstance`.
 fn handle_stream_connection_from_vm(state: Arc<Mutex<State>>) -> Result<()> {