blob: 47a1603b73eb774bf69c9d464fbc2fa9d90a5fc5 [file] [log] [blame]
David Brazdilafc9a9e2023-01-12 16:08:10 +00001// 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
17use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::DeathReason::DeathReason;
18use android_system_virtualizationservice_internal::aidl::android::system::virtualizationservice_internal::{
19 AtomVmBooted::AtomVmBooted,
20 AtomVmCreationRequested::AtomVmCreationRequested,
21 AtomVmExited::AtomVmExited,
22};
23use anyhow::Result;
24use log::{trace, warn};
25use rustutils::system_properties;
26use statslog_virtualization_rust::{vm_booted, vm_creation_requested, vm_exited};
27
28pub 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 task_profile
51 // TODO(seungjaeyoo) Fill information about disk_image for raw config
52 };
53
54 wait_for_statsd().unwrap_or_else(|e| warn!("failed to wait for statsd with error: {}", e));
55 match vm_creation_requested.stats_write() {
56 Err(e) => warn!("statslog_rust failed with error: {}", e),
57 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
58 }
59}
60
61pub fn forward_vm_booted_atom(atom: &AtomVmBooted) {
62 let vm_booted = vm_booted::VmBooted {
63 uid: atom.uid,
64 vm_identifier: &atom.vmIdentifier,
65 elapsed_time_millis: atom.elapsedTimeMillis,
66 };
67
68 wait_for_statsd().unwrap_or_else(|e| warn!("failed to wait for statsd with error: {}", e));
69 match vm_booted.stats_write() {
70 Err(e) => warn!("statslog_rust failed with error: {}", e),
71 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
72 }
73}
74
75pub fn forward_vm_exited_atom(atom: &AtomVmExited) {
76 let death_reason = match atom.deathReason {
77 DeathReason::INFRASTRUCTURE_ERROR => vm_exited::DeathReason::InfrastructureError,
78 DeathReason::KILLED => vm_exited::DeathReason::Killed,
79 DeathReason::UNKNOWN => vm_exited::DeathReason::Unknown,
80 DeathReason::SHUTDOWN => vm_exited::DeathReason::Shutdown,
81 DeathReason::START_FAILED => vm_exited::DeathReason::Error,
82 DeathReason::REBOOT => vm_exited::DeathReason::Reboot,
83 DeathReason::CRASH => vm_exited::DeathReason::Crash,
84 DeathReason::PVM_FIRMWARE_PUBLIC_KEY_MISMATCH => {
85 vm_exited::DeathReason::PvmFirmwarePublicKeyMismatch
86 }
87 DeathReason::PVM_FIRMWARE_INSTANCE_IMAGE_CHANGED => {
88 vm_exited::DeathReason::PvmFirmwareInstanceImageChanged
89 }
90 DeathReason::BOOTLOADER_PUBLIC_KEY_MISMATCH => {
91 vm_exited::DeathReason::BootloaderPublicKeyMismatch
92 }
93 DeathReason::BOOTLOADER_INSTANCE_IMAGE_CHANGED => {
94 vm_exited::DeathReason::BootloaderInstanceImageChanged
95 }
96 DeathReason::MICRODROID_FAILED_TO_CONNECT_TO_VIRTUALIZATION_SERVICE => {
97 vm_exited::DeathReason::MicrodroidFailedToConnectToVirtualizationService
98 }
99 DeathReason::MICRODROID_PAYLOAD_HAS_CHANGED => {
100 vm_exited::DeathReason::MicrodroidPayloadHasChanged
101 }
102 DeathReason::MICRODROID_PAYLOAD_VERIFICATION_FAILED => {
103 vm_exited::DeathReason::MicrodroidPayloadVerificationFailed
104 }
105 DeathReason::MICRODROID_INVALID_PAYLOAD_CONFIG => {
106 vm_exited::DeathReason::MicrodroidInvalidPayloadConfig
107 }
108 DeathReason::MICRODROID_UNKNOWN_RUNTIME_ERROR => {
109 vm_exited::DeathReason::MicrodroidUnknownRuntimeError
110 }
111 DeathReason::HANGUP => vm_exited::DeathReason::Hangup,
112 _ => vm_exited::DeathReason::Unknown,
113 };
114
115 let vm_exited = vm_exited::VmExited {
116 uid: atom.uid,
117 vm_identifier: &atom.vmIdentifier,
118 elapsed_time_millis: atom.elapsedTimeMillis,
119 death_reason,
120 guest_time_millis: atom.guestTimeMillis,
121 rss_vm_kb: atom.rssVmKb,
122 rss_crosvm_kb: atom.rssCrosvmKb,
123 exit_signal: atom.exitSignal,
124 };
125
126 wait_for_statsd().unwrap_or_else(|e| warn!("failed to wait for statsd with error: {}", e));
127 match vm_exited.stats_write() {
128 Err(e) => warn!("statslog_rust failed with error: {}", e),
129 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
130 }
131}
132
133fn wait_for_statsd() -> Result<()> {
134 let mut prop = system_properties::PropertyWatcher::new("init.svc.statsd")?;
135 loop {
136 prop.wait()?;
137 match system_properties::read("init.svc.statsd")? {
138 Some(s) => {
139 if s == "running" {
140 break;
141 }
142 }
143 None => {
144 // This case never really happens because
145 // prop.wait() waits for property to be non-null.
146 break;
147 }
148 }
149 }
150 Ok(())
151}