blob: 8c46ac5b7eb8a31e4188f0cd608b32789ef59538 [file] [log] [blame]
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +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 crate::aidl::clone_file;
18use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
Alan Stokes0d1ef782022-09-27 13:46:35 +010019 DeathReason::DeathReason,
20 IVirtualMachine::IVirtualMachine,
21 VirtualMachineAppConfig::{Payload::Payload, VirtualMachineAppConfig},
22 VirtualMachineConfig::VirtualMachineConfig,
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000023};
24use android_system_virtualizationservice::binder::{Status, Strong};
Seungjae Yoofd9a0622022-10-14 10:01:29 +090025use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice::{
26 VirtualMachineCpuStatus::VirtualMachineCpuStatus,
27 VirtualMachineMemStatus::VirtualMachineMemStatus,
28};
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000029use anyhow::{anyhow, Result};
Alan Stokes0d1ef782022-09-27 13:46:35 +010030use binder::{ParcelFileDescriptor, ThreadState};
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000031use log::{trace, warn};
32use microdroid_payload_config::VmPayloadConfig;
Seungjae Yoofd9a0622022-10-14 10:01:29 +090033use statslog_virtualization_rust::{
34 vm_booted, vm_cpu_status_reported, vm_creation_requested, vm_exited, vm_mem_status_reported,
35};
Seungjae Yoo2e7beea2022-08-24 16:09:12 +090036use std::time::{Duration, SystemTime};
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000037use zip::ZipArchive;
38
Alan Stokes0d1ef782022-09-27 13:46:35 +010039fn get_apex_list(config: &VirtualMachineAppConfig) -> String {
40 match &config.payload {
41 Payload::PayloadConfig(_) => String::new(),
42 Payload::ConfigPath(config_path) => {
43 let vm_payload_config = get_vm_payload_config(&config.apk, config_path);
44 if let Ok(vm_payload_config) = vm_payload_config {
45 vm_payload_config
46 .apexes
47 .iter()
48 .map(|x| x.name.clone())
49 .collect::<Vec<String>>()
50 .join(":")
51 } else {
52 "INFO: Can't get VmPayloadConfig".to_owned()
53 }
54 }
55 }
56}
57
58fn get_vm_payload_config(
59 apk_fd: &Option<ParcelFileDescriptor>,
60 config_path: &str,
61) -> Result<VmPayloadConfig> {
62 let apk = apk_fd.as_ref().ok_or_else(|| anyhow!("APK is none"))?;
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000063 let apk_file = clone_file(apk)?;
64 let mut apk_zip = ZipArchive::new(&apk_file)?;
Alan Stokes0d1ef782022-09-27 13:46:35 +010065 let config_file = apk_zip.by_name(config_path)?;
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000066 let vm_payload_config: VmPayloadConfig = serde_json::from_reader(config_file)?;
67 Ok(vm_payload_config)
68}
69
Seungjae Yoo2e7beea2022-08-24 16:09:12 +090070fn get_duration(vm_start_timestamp: Option<SystemTime>) -> Duration {
71 match vm_start_timestamp {
72 Some(vm_start_timestamp) => vm_start_timestamp.elapsed().unwrap_or_default(),
73 None => Duration::default(),
74 }
75}
76
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000077/// Write the stats of VMCreation to statsd
78pub fn write_vm_creation_stats(
79 config: &VirtualMachineConfig,
80 is_protected: bool,
81 ret: &binder::Result<Strong<dyn IVirtualMachine>>,
82) {
83 let creation_succeeded;
84 let binder_exception_code;
85 match ret {
86 Ok(_) => {
87 creation_succeeded = true;
88 binder_exception_code = Status::ok().exception_code() as i32;
89 }
90 Err(ref e) => {
91 creation_succeeded = false;
92 binder_exception_code = e.exception_code() as i32;
93 }
94 }
95
Alan Stokes0d1ef782022-09-27 13:46:35 +010096 let (vm_identifier, config_type, num_cpus, memory_mib, apexes) = match config {
97 VirtualMachineConfig::AppConfig(config) => (
98 &config.name,
99 vm_creation_requested::ConfigType::VirtualMachineAppConfig,
100 config.numCpus,
101 config.memoryMib,
102 get_apex_list(config),
103 ),
104 VirtualMachineConfig::RawConfig(config) => (
105 &config.name,
106 vm_creation_requested::ConfigType::VirtualMachineRawConfig,
107 config.numCpus,
108 config.memoryMib,
109 String::new(),
110 ),
111 };
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +0000112
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +0000113 let vm_creation_requested = vm_creation_requested::VmCreationRequested {
Seungjae Yoo62085c02022-08-12 04:44:52 +0000114 uid: ThreadState::get_calling_uid() as i32,
115 vm_identifier,
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +0000116 hypervisor: vm_creation_requested::Hypervisor::Pkvm,
117 is_protected,
118 creation_succeeded,
119 binder_exception_code,
120 config_type,
121 num_cpus,
Victor Hsiehf219cd82022-09-09 13:13:11 -0700122 cpu_affinity: "", // deprecated
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +0000123 memory_mib,
124 apexes: &apexes,
125 // TODO(seungjaeyoo) Fill information about task_profile
126 // TODO(seungjaeyoo) Fill information about disk_image for raw config
127 };
128
129 match vm_creation_requested.stats_write() {
130 Err(e) => {
131 warn!("statslog_rust failed with error: {}", e);
132 }
133 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
134 }
135}
Seungjae Yooacf559a2022-08-12 04:44:51 +0000136
137/// Write the stats of VM boot to statsd
Seungjae Yoo2e7beea2022-08-24 16:09:12 +0900138pub fn write_vm_booted_stats(
139 uid: i32,
140 vm_identifier: &String,
141 vm_start_timestamp: Option<SystemTime>,
142) {
143 let duration = get_duration(vm_start_timestamp);
144 let vm_booted = vm_booted::VmBooted {
145 uid,
146 vm_identifier,
147 elapsed_time_millis: duration.as_millis() as i64,
148 };
Seungjae Yooacf559a2022-08-12 04:44:51 +0000149 match vm_booted.stats_write() {
150 Err(e) => {
151 warn!("statslog_rust failed with error: {}", e);
152 }
153 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
154 }
155}
Seungjae Yoob4c07ba2022-08-12 04:44:52 +0000156
157/// Write the stats of VM exit to statsd
Seungjae Yoo2e7beea2022-08-24 16:09:12 +0900158pub fn write_vm_exited_stats(
159 uid: i32,
160 vm_identifier: &String,
161 reason: DeathReason,
162 vm_start_timestamp: Option<SystemTime>,
163) {
164 let duration = get_duration(vm_start_timestamp);
Seungjae Yoob4c07ba2022-08-12 04:44:52 +0000165 let vm_exited = vm_exited::VmExited {
Seungjae Yoo62085c02022-08-12 04:44:52 +0000166 uid,
167 vm_identifier,
Seungjae Yoo2e7beea2022-08-24 16:09:12 +0900168 elapsed_time_millis: duration.as_millis() as i64,
Seungjae Yoob4c07ba2022-08-12 04:44:52 +0000169 death_reason: match reason {
170 DeathReason::INFRASTRUCTURE_ERROR => vm_exited::DeathReason::InfrastructureError,
171 DeathReason::KILLED => vm_exited::DeathReason::Killed,
172 DeathReason::UNKNOWN => vm_exited::DeathReason::Unknown,
173 DeathReason::SHUTDOWN => vm_exited::DeathReason::Shutdown,
174 DeathReason::ERROR => vm_exited::DeathReason::Error,
175 DeathReason::REBOOT => vm_exited::DeathReason::Reboot,
176 DeathReason::CRASH => vm_exited::DeathReason::Crash,
177 DeathReason::PVM_FIRMWARE_PUBLIC_KEY_MISMATCH => {
178 vm_exited::DeathReason::PvmFirmwarePublicKeyMismatch
179 }
180 DeathReason::PVM_FIRMWARE_INSTANCE_IMAGE_CHANGED => {
181 vm_exited::DeathReason::PvmFirmwareInstanceImageChanged
182 }
183 DeathReason::BOOTLOADER_PUBLIC_KEY_MISMATCH => {
184 vm_exited::DeathReason::BootloaderPublicKeyMismatch
185 }
186 DeathReason::BOOTLOADER_INSTANCE_IMAGE_CHANGED => {
187 vm_exited::DeathReason::BootloaderInstanceImageChanged
188 }
189 DeathReason::MICRODROID_FAILED_TO_CONNECT_TO_VIRTUALIZATION_SERVICE => {
190 vm_exited::DeathReason::MicrodroidFailedToConnectToVirtualizationService
191 }
192 DeathReason::MICRODROID_PAYLOAD_HAS_CHANGED => {
193 vm_exited::DeathReason::MicrodroidPayloadHasChanged
194 }
195 DeathReason::MICRODROID_PAYLOAD_VERIFICATION_FAILED => {
196 vm_exited::DeathReason::MicrodroidPayloadVerificationFailed
197 }
198 DeathReason::MICRODROID_INVALID_PAYLOAD_CONFIG => {
199 vm_exited::DeathReason::MicrodroidInvalidPayloadConfig
200 }
201 DeathReason::MICRODROID_UNKNOWN_RUNTIME_ERROR => {
202 vm_exited::DeathReason::MicrodroidUnknownRuntimeError
203 }
204 DeathReason::HANGUP => vm_exited::DeathReason::Hangup,
205 _ => vm_exited::DeathReason::Unknown,
206 },
207 };
208 match vm_exited.stats_write() {
209 Err(e) => {
210 warn!("statslog_rust failed with error: {}", e);
211 }
212 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
213 }
214}
Seungjae Yoofd9a0622022-10-14 10:01:29 +0900215
216/// Write the stats of VM cpu status to statsd
217pub fn write_vm_cpu_status_stats(
218 uid: i32,
219 vm_identifier: &String,
220 cpu_status: &VirtualMachineCpuStatus,
221) {
222 let vm_cpu_status_reported = vm_cpu_status_reported::VmCpuStatusReported {
223 uid,
224 vm_identifier,
225 cpu_time_user_millis: cpu_status.cpu_time_user,
226 cpu_time_nice_millis: cpu_status.cpu_time_nice,
227 cpu_time_sys_millis: cpu_status.cpu_time_sys,
228 cpu_time_idle_millis: cpu_status.cpu_time_idle,
229 };
230 match vm_cpu_status_reported.stats_write() {
231 Err(e) => {
232 warn!("statslog_rust failed with error: {}", e);
233 }
234 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
235 }
236}
237
238/// Write the stats of VM memory status to statsd
239pub fn write_vm_mem_status_stats(
240 uid: i32,
241 vm_identifier: &String,
242 mem_status: &VirtualMachineMemStatus,
243) {
244 let vm_mem_status_reported = vm_mem_status_reported::VmMemStatusReported {
245 uid,
246 vm_identifier,
247 mem_total_kb: mem_status.mem_total,
248 mem_free_kb: mem_status.mem_free,
249 mem_available_kb: mem_status.mem_available,
250 mem_buffer_kb: mem_status.mem_buffer,
251 mem_cached_kb: mem_status.mem_cached,
252 };
253 match vm_mem_status_reported.stats_write() {
254 Err(e) => {
255 warn!("statslog_rust failed with error: {}", e);
256 }
257 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
258 }
259}