blob: 3b29d19495832872e6c543fae5feb203a009cb71 [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::{
Seungjae Yoob4c07ba2022-08-12 04:44:52 +000019 DeathReason::DeathReason, IVirtualMachine::IVirtualMachine,
20 VirtualMachineAppConfig::VirtualMachineAppConfig, VirtualMachineConfig::VirtualMachineConfig,
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000021};
22use android_system_virtualizationservice::binder::{Status, Strong};
23use anyhow::{anyhow, Result};
Seungjae Yoo62085c02022-08-12 04:44:52 +000024use binder::ThreadState;
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000025use log::{trace, warn};
26use microdroid_payload_config::VmPayloadConfig;
Seungjae Yoob4c07ba2022-08-12 04:44:52 +000027use statslog_virtualization_rust::{vm_booted, vm_creation_requested, vm_exited};
Seungjae Yoo2e7beea2022-08-24 16:09:12 +090028use std::time::{Duration, SystemTime};
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000029use zip::ZipArchive;
30
31fn get_vm_payload_config(config: &VirtualMachineAppConfig) -> Result<VmPayloadConfig> {
32 let apk = config.apk.as_ref().ok_or_else(|| anyhow!("APK is none"))?;
33 let apk_file = clone_file(apk)?;
34 let mut apk_zip = ZipArchive::new(&apk_file)?;
35 let config_file = apk_zip.by_name(&config.configPath)?;
36 let vm_payload_config: VmPayloadConfig = serde_json::from_reader(config_file)?;
37 Ok(vm_payload_config)
38}
39
Seungjae Yoo2e7beea2022-08-24 16:09:12 +090040fn get_duration(vm_start_timestamp: Option<SystemTime>) -> Duration {
41 match vm_start_timestamp {
42 Some(vm_start_timestamp) => vm_start_timestamp.elapsed().unwrap_or_default(),
43 None => Duration::default(),
44 }
45}
46
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000047/// Write the stats of VMCreation to statsd
48pub fn write_vm_creation_stats(
49 config: &VirtualMachineConfig,
50 is_protected: bool,
51 ret: &binder::Result<Strong<dyn IVirtualMachine>>,
52) {
53 let creation_succeeded;
54 let binder_exception_code;
55 match ret {
56 Ok(_) => {
57 creation_succeeded = true;
58 binder_exception_code = Status::ok().exception_code() as i32;
59 }
60 Err(ref e) => {
61 creation_succeeded = false;
62 binder_exception_code = e.exception_code() as i32;
63 }
64 }
65
Seungjae Yoo62085c02022-08-12 04:44:52 +000066 let vm_identifier;
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000067 let config_type;
68 let num_cpus;
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000069 let memory_mib;
70 let apexes;
71 match config {
72 VirtualMachineConfig::AppConfig(config) => {
Seungjae Yoo62085c02022-08-12 04:44:52 +000073 vm_identifier = &config.name;
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000074 config_type = vm_creation_requested::ConfigType::VirtualMachineAppConfig;
75 num_cpus = config.numCpus;
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000076 memory_mib = config.memoryMib;
77
78 let vm_payload_config = get_vm_payload_config(config);
79 if let Ok(vm_payload_config) = vm_payload_config {
80 apexes = vm_payload_config
81 .apexes
82 .iter()
83 .map(|x| x.name.clone())
84 .collect::<Vec<String>>()
85 .join(":");
86 } else {
87 apexes = "INFO: Can't get VmPayloadConfig".into();
88 }
89 }
90 VirtualMachineConfig::RawConfig(config) => {
Seungjae Yoo62085c02022-08-12 04:44:52 +000091 vm_identifier = &config.name;
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000092 config_type = vm_creation_requested::ConfigType::VirtualMachineRawConfig;
93 num_cpus = config.numCpus;
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000094 memory_mib = config.memoryMib;
95 apexes = String::new();
96 }
97 }
98
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000099 let vm_creation_requested = vm_creation_requested::VmCreationRequested {
Seungjae Yoo62085c02022-08-12 04:44:52 +0000100 uid: ThreadState::get_calling_uid() as i32,
101 vm_identifier,
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +0000102 hypervisor: vm_creation_requested::Hypervisor::Pkvm,
103 is_protected,
104 creation_succeeded,
105 binder_exception_code,
106 config_type,
107 num_cpus,
Victor Hsiehf219cd82022-09-09 13:13:11 -0700108 cpu_affinity: "", // deprecated
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +0000109 memory_mib,
110 apexes: &apexes,
111 // TODO(seungjaeyoo) Fill information about task_profile
112 // TODO(seungjaeyoo) Fill information about disk_image for raw config
113 };
114
115 match vm_creation_requested.stats_write() {
116 Err(e) => {
117 warn!("statslog_rust failed with error: {}", e);
118 }
119 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
120 }
121}
Seungjae Yooacf559a2022-08-12 04:44:51 +0000122
123/// Write the stats of VM boot to statsd
Seungjae Yoo2e7beea2022-08-24 16:09:12 +0900124pub fn write_vm_booted_stats(
125 uid: i32,
126 vm_identifier: &String,
127 vm_start_timestamp: Option<SystemTime>,
128) {
129 let duration = get_duration(vm_start_timestamp);
130 let vm_booted = vm_booted::VmBooted {
131 uid,
132 vm_identifier,
133 elapsed_time_millis: duration.as_millis() as i64,
134 };
Seungjae Yooacf559a2022-08-12 04:44:51 +0000135 match vm_booted.stats_write() {
136 Err(e) => {
137 warn!("statslog_rust failed with error: {}", e);
138 }
139 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
140 }
141}
Seungjae Yoob4c07ba2022-08-12 04:44:52 +0000142
143/// Write the stats of VM exit to statsd
Seungjae Yoo2e7beea2022-08-24 16:09:12 +0900144pub fn write_vm_exited_stats(
145 uid: i32,
146 vm_identifier: &String,
147 reason: DeathReason,
148 vm_start_timestamp: Option<SystemTime>,
149) {
150 let duration = get_duration(vm_start_timestamp);
Seungjae Yoob4c07ba2022-08-12 04:44:52 +0000151 let vm_exited = vm_exited::VmExited {
Seungjae Yoo62085c02022-08-12 04:44:52 +0000152 uid,
153 vm_identifier,
Seungjae Yoo2e7beea2022-08-24 16:09:12 +0900154 elapsed_time_millis: duration.as_millis() as i64,
Seungjae Yoob4c07ba2022-08-12 04:44:52 +0000155 death_reason: match reason {
156 DeathReason::INFRASTRUCTURE_ERROR => vm_exited::DeathReason::InfrastructureError,
157 DeathReason::KILLED => vm_exited::DeathReason::Killed,
158 DeathReason::UNKNOWN => vm_exited::DeathReason::Unknown,
159 DeathReason::SHUTDOWN => vm_exited::DeathReason::Shutdown,
160 DeathReason::ERROR => vm_exited::DeathReason::Error,
161 DeathReason::REBOOT => vm_exited::DeathReason::Reboot,
162 DeathReason::CRASH => vm_exited::DeathReason::Crash,
163 DeathReason::PVM_FIRMWARE_PUBLIC_KEY_MISMATCH => {
164 vm_exited::DeathReason::PvmFirmwarePublicKeyMismatch
165 }
166 DeathReason::PVM_FIRMWARE_INSTANCE_IMAGE_CHANGED => {
167 vm_exited::DeathReason::PvmFirmwareInstanceImageChanged
168 }
169 DeathReason::BOOTLOADER_PUBLIC_KEY_MISMATCH => {
170 vm_exited::DeathReason::BootloaderPublicKeyMismatch
171 }
172 DeathReason::BOOTLOADER_INSTANCE_IMAGE_CHANGED => {
173 vm_exited::DeathReason::BootloaderInstanceImageChanged
174 }
175 DeathReason::MICRODROID_FAILED_TO_CONNECT_TO_VIRTUALIZATION_SERVICE => {
176 vm_exited::DeathReason::MicrodroidFailedToConnectToVirtualizationService
177 }
178 DeathReason::MICRODROID_PAYLOAD_HAS_CHANGED => {
179 vm_exited::DeathReason::MicrodroidPayloadHasChanged
180 }
181 DeathReason::MICRODROID_PAYLOAD_VERIFICATION_FAILED => {
182 vm_exited::DeathReason::MicrodroidPayloadVerificationFailed
183 }
184 DeathReason::MICRODROID_INVALID_PAYLOAD_CONFIG => {
185 vm_exited::DeathReason::MicrodroidInvalidPayloadConfig
186 }
187 DeathReason::MICRODROID_UNKNOWN_RUNTIME_ERROR => {
188 vm_exited::DeathReason::MicrodroidUnknownRuntimeError
189 }
190 DeathReason::HANGUP => vm_exited::DeathReason::Hangup,
191 _ => vm_exited::DeathReason::Unknown,
192 },
193 };
194 match vm_exited.stats_write() {
195 Err(e) => {
196 warn!("statslog_rust failed with error: {}", e);
197 }
198 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
199 }
200}