// Copyright 2022, 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. //! Functions for creating and collecting atoms. use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::DeathReason::DeathReason; use android_system_virtualizationservice_internal::aidl::android::system::virtualizationservice_internal::{ AtomVmBooted::AtomVmBooted, AtomVmCreationRequested::AtomVmCreationRequested, AtomVmExited::AtomVmExited, }; use anyhow::Result; use log::{trace, warn}; use rustutils::system_properties::PropertyWatcher; use statslog_virtualization_rust::{vm_booted, vm_creation_requested, vm_exited}; pub fn forward_vm_creation_atom(atom: &AtomVmCreationRequested) { let config_type = match atom.configType { x if x == vm_creation_requested::ConfigType::VirtualMachineAppConfig as i32 => { vm_creation_requested::ConfigType::VirtualMachineAppConfig } x if x == vm_creation_requested::ConfigType::VirtualMachineRawConfig as i32 => { vm_creation_requested::ConfigType::VirtualMachineRawConfig } _ => vm_creation_requested::ConfigType::UnknownConfig, }; let vm_creation_requested = vm_creation_requested::VmCreationRequested { uid: atom.uid, vm_identifier: &atom.vmIdentifier, hypervisor: vm_creation_requested::Hypervisor::Pkvm, is_protected: atom.isProtected, creation_succeeded: atom.creationSucceeded, binder_exception_code: atom.binderExceptionCode, config_type, num_cpus: atom.numCpus, cpu_affinity: "", // deprecated memory_mib: atom.memoryMib, apexes: &atom.apexes, // TODO(seungjaeyoo) Fill information about disk_image for raw config }; wait_for_statsd().unwrap_or_else(|e| warn!("failed to wait for statsd with error: {}", e)); match vm_creation_requested.stats_write() { Err(e) => warn!("statslog_rust failed with error: {}", e), Ok(_) => trace!("statslog_rust succeeded for virtualization service"), } } pub fn forward_vm_booted_atom(atom: &AtomVmBooted) { let vm_booted = vm_booted::VmBooted { uid: atom.uid, vm_identifier: &atom.vmIdentifier, elapsed_time_millis: atom.elapsedTimeMillis, }; wait_for_statsd().unwrap_or_else(|e| warn!("failed to wait for statsd with error: {}", e)); match vm_booted.stats_write() { Err(e) => warn!("statslog_rust failed with error: {}", e), Ok(_) => trace!("statslog_rust succeeded for virtualization service"), } } pub fn forward_vm_exited_atom(atom: &AtomVmExited) { let death_reason = match atom.deathReason { DeathReason::INFRASTRUCTURE_ERROR => vm_exited::DeathReason::InfrastructureError, DeathReason::KILLED => vm_exited::DeathReason::Killed, DeathReason::UNKNOWN => vm_exited::DeathReason::Unknown, DeathReason::SHUTDOWN => vm_exited::DeathReason::Shutdown, DeathReason::START_FAILED => vm_exited::DeathReason::Error, DeathReason::REBOOT => vm_exited::DeathReason::Reboot, DeathReason::CRASH => vm_exited::DeathReason::Crash, DeathReason::PVM_FIRMWARE_PUBLIC_KEY_MISMATCH => { vm_exited::DeathReason::PvmFirmwarePublicKeyMismatch } DeathReason::PVM_FIRMWARE_INSTANCE_IMAGE_CHANGED => { vm_exited::DeathReason::PvmFirmwareInstanceImageChanged } DeathReason::MICRODROID_FAILED_TO_CONNECT_TO_VIRTUALIZATION_SERVICE => { vm_exited::DeathReason::MicrodroidFailedToConnectToVirtualizationService } DeathReason::MICRODROID_PAYLOAD_HAS_CHANGED => { vm_exited::DeathReason::MicrodroidPayloadHasChanged } DeathReason::MICRODROID_PAYLOAD_VERIFICATION_FAILED => { vm_exited::DeathReason::MicrodroidPayloadVerificationFailed } DeathReason::MICRODROID_INVALID_PAYLOAD_CONFIG => { vm_exited::DeathReason::MicrodroidInvalidPayloadConfig } DeathReason::MICRODROID_UNKNOWN_RUNTIME_ERROR => { vm_exited::DeathReason::MicrodroidUnknownRuntimeError } DeathReason::HANGUP => vm_exited::DeathReason::Hangup, _ => vm_exited::DeathReason::Unknown, }; let vm_exited = vm_exited::VmExited { uid: atom.uid, vm_identifier: &atom.vmIdentifier, elapsed_time_millis: atom.elapsedTimeMillis, death_reason, guest_time_millis: atom.guestTimeMillis, rss_vm_kb: atom.rssVmKb, rss_crosvm_kb: atom.rssCrosvmKb, exit_signal: atom.exitSignal, }; wait_for_statsd().unwrap_or_else(|e| warn!("failed to wait for statsd with error: {}", e)); match vm_exited.stats_write() { Err(e) => warn!("statslog_rust failed with error: {}", e), Ok(_) => trace!("statslog_rust succeeded for virtualization service"), } } fn wait_for_statsd() -> Result<()> { PropertyWatcher::new("init.svc.statsd")?.wait_for_value("running", None)?; Ok(()) }