1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 //! Functions for creating and collecting atoms.
16
17 use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::DeathReason::DeathReason;
18 use android_system_virtualizationservice_internal::aidl::android::system::virtualizationservice_internal::{
19 AtomVmBooted::AtomVmBooted,
20 AtomVmCreationRequested::AtomVmCreationRequested,
21 AtomVmExited::AtomVmExited,
22 };
23 use anyhow::Result;
24 use log::{trace, warn};
25 use rustutils::system_properties::PropertyWatcher;
26 use statslog_virtualization_rust::{vm_booted, vm_creation_requested, vm_exited};
27
forward_vm_creation_atom(atom: &AtomVmCreationRequested)28 pub fn forward_vm_creation_atom(atom: &AtomVmCreationRequested) {
29 let config_type = match atom.configType {
30 x if x == vm_creation_requested::ConfigType::VirtualMachineAppConfig as i32 => {
31 vm_creation_requested::ConfigType::VirtualMachineAppConfig
32 }
33 x if x == vm_creation_requested::ConfigType::VirtualMachineRawConfig as i32 => {
34 vm_creation_requested::ConfigType::VirtualMachineRawConfig
35 }
36 _ => vm_creation_requested::ConfigType::UnknownConfig,
37 };
38 let vm_creation_requested = vm_creation_requested::VmCreationRequested {
39 uid: atom.uid,
40 vm_identifier: &atom.vmIdentifier,
41 hypervisor: vm_creation_requested::Hypervisor::Pkvm,
42 is_protected: atom.isProtected,
43 creation_succeeded: atom.creationSucceeded,
44 binder_exception_code: atom.binderExceptionCode,
45 config_type,
46 num_cpus: atom.numCpus,
47 cpu_affinity: "", // deprecated
48 memory_mib: atom.memoryMib,
49 apexes: &atom.apexes,
50 // TODO(seungjaeyoo) Fill information about disk_image for raw config
51 };
52
53 wait_for_statsd().unwrap_or_else(|e| warn!("failed to wait for statsd with error: {}", e));
54 match vm_creation_requested.stats_write() {
55 Err(e) => warn!("statslog_rust failed with error: {}", e),
56 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
57 }
58 }
59
forward_vm_booted_atom(atom: &AtomVmBooted)60 pub fn forward_vm_booted_atom(atom: &AtomVmBooted) {
61 let vm_booted = vm_booted::VmBooted {
62 uid: atom.uid,
63 vm_identifier: &atom.vmIdentifier,
64 elapsed_time_millis: atom.elapsedTimeMillis,
65 };
66
67 wait_for_statsd().unwrap_or_else(|e| warn!("failed to wait for statsd with error: {}", e));
68 match vm_booted.stats_write() {
69 Err(e) => warn!("statslog_rust failed with error: {}", e),
70 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
71 }
72 }
73
forward_vm_exited_atom(atom: &AtomVmExited)74 pub fn forward_vm_exited_atom(atom: &AtomVmExited) {
75 let death_reason = match atom.deathReason {
76 DeathReason::INFRASTRUCTURE_ERROR => vm_exited::DeathReason::InfrastructureError,
77 DeathReason::KILLED => vm_exited::DeathReason::Killed,
78 DeathReason::UNKNOWN => vm_exited::DeathReason::Unknown,
79 DeathReason::SHUTDOWN => vm_exited::DeathReason::Shutdown,
80 DeathReason::START_FAILED => vm_exited::DeathReason::Error,
81 DeathReason::REBOOT => vm_exited::DeathReason::Reboot,
82 DeathReason::CRASH => vm_exited::DeathReason::Crash,
83 DeathReason::PVM_FIRMWARE_PUBLIC_KEY_MISMATCH => {
84 vm_exited::DeathReason::PvmFirmwarePublicKeyMismatch
85 }
86 DeathReason::PVM_FIRMWARE_INSTANCE_IMAGE_CHANGED => {
87 vm_exited::DeathReason::PvmFirmwareInstanceImageChanged
88 }
89 DeathReason::MICRODROID_FAILED_TO_CONNECT_TO_VIRTUALIZATION_SERVICE => {
90 vm_exited::DeathReason::MicrodroidFailedToConnectToVirtualizationService
91 }
92 DeathReason::MICRODROID_PAYLOAD_HAS_CHANGED => {
93 vm_exited::DeathReason::MicrodroidPayloadHasChanged
94 }
95 DeathReason::MICRODROID_PAYLOAD_VERIFICATION_FAILED => {
96 vm_exited::DeathReason::MicrodroidPayloadVerificationFailed
97 }
98 DeathReason::MICRODROID_INVALID_PAYLOAD_CONFIG => {
99 vm_exited::DeathReason::MicrodroidInvalidPayloadConfig
100 }
101 DeathReason::MICRODROID_UNKNOWN_RUNTIME_ERROR => {
102 vm_exited::DeathReason::MicrodroidUnknownRuntimeError
103 }
104 DeathReason::HANGUP => vm_exited::DeathReason::Hangup,
105 _ => vm_exited::DeathReason::Unknown,
106 };
107
108 let vm_exited = vm_exited::VmExited {
109 uid: atom.uid,
110 vm_identifier: &atom.vmIdentifier,
111 elapsed_time_millis: atom.elapsedTimeMillis,
112 death_reason,
113 guest_time_millis: atom.guestTimeMillis,
114 rss_vm_kb: atom.rssVmKb,
115 rss_crosvm_kb: atom.rssCrosvmKb,
116 exit_signal: atom.exitSignal,
117 };
118
119 wait_for_statsd().unwrap_or_else(|e| warn!("failed to wait for statsd with error: {}", e));
120 match vm_exited.stats_write() {
121 Err(e) => warn!("statslog_rust failed with error: {}", e),
122 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
123 }
124 }
125
wait_for_statsd() -> Result<()>126 fn wait_for_statsd() -> Result<()> {
127 PropertyWatcher::new("init.svc.statsd")?.wait_for_value("running", None)?;
128 Ok(())
129 }
130