blob: feaa72ae58255501dd3d533a82fb89b28cec3485 [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 Yoo0a8c84c2022-07-11 08:19:15 +000028use zip::ZipArchive;
29
30fn get_vm_payload_config(config: &VirtualMachineAppConfig) -> Result<VmPayloadConfig> {
31 let apk = config.apk.as_ref().ok_or_else(|| anyhow!("APK is none"))?;
32 let apk_file = clone_file(apk)?;
33 let mut apk_zip = ZipArchive::new(&apk_file)?;
34 let config_file = apk_zip.by_name(&config.configPath)?;
35 let vm_payload_config: VmPayloadConfig = serde_json::from_reader(config_file)?;
36 Ok(vm_payload_config)
37}
38
39/// Write the stats of VMCreation to statsd
40pub fn write_vm_creation_stats(
41 config: &VirtualMachineConfig,
42 is_protected: bool,
43 ret: &binder::Result<Strong<dyn IVirtualMachine>>,
44) {
45 let creation_succeeded;
46 let binder_exception_code;
47 match ret {
48 Ok(_) => {
49 creation_succeeded = true;
50 binder_exception_code = Status::ok().exception_code() as i32;
51 }
52 Err(ref e) => {
53 creation_succeeded = false;
54 binder_exception_code = e.exception_code() as i32;
55 }
56 }
57
Seungjae Yoo62085c02022-08-12 04:44:52 +000058 let vm_identifier;
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000059 let config_type;
60 let num_cpus;
61 let cpu_affinity;
62 let memory_mib;
63 let apexes;
64 match config {
65 VirtualMachineConfig::AppConfig(config) => {
Seungjae Yoo62085c02022-08-12 04:44:52 +000066 vm_identifier = &config.name;
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000067 config_type = vm_creation_requested::ConfigType::VirtualMachineAppConfig;
68 num_cpus = config.numCpus;
69 cpu_affinity = config.cpuAffinity.clone().unwrap_or_default();
70 memory_mib = config.memoryMib;
71
72 let vm_payload_config = get_vm_payload_config(config);
73 if let Ok(vm_payload_config) = vm_payload_config {
74 apexes = vm_payload_config
75 .apexes
76 .iter()
77 .map(|x| x.name.clone())
78 .collect::<Vec<String>>()
79 .join(":");
80 } else {
81 apexes = "INFO: Can't get VmPayloadConfig".into();
82 }
83 }
84 VirtualMachineConfig::RawConfig(config) => {
Seungjae Yoo62085c02022-08-12 04:44:52 +000085 vm_identifier = &config.name;
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000086 config_type = vm_creation_requested::ConfigType::VirtualMachineRawConfig;
87 num_cpus = config.numCpus;
88 cpu_affinity = config.cpuAffinity.clone().unwrap_or_default();
89 memory_mib = config.memoryMib;
90 apexes = String::new();
91 }
92 }
93
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000094 let vm_creation_requested = vm_creation_requested::VmCreationRequested {
Seungjae Yoo62085c02022-08-12 04:44:52 +000095 uid: ThreadState::get_calling_uid() as i32,
96 vm_identifier,
Seungjae Yoo0a8c84c2022-07-11 08:19:15 +000097 hypervisor: vm_creation_requested::Hypervisor::Pkvm,
98 is_protected,
99 creation_succeeded,
100 binder_exception_code,
101 config_type,
102 num_cpus,
103 cpu_affinity: &cpu_affinity,
104 memory_mib,
105 apexes: &apexes,
106 // TODO(seungjaeyoo) Fill information about task_profile
107 // TODO(seungjaeyoo) Fill information about disk_image for raw config
108 };
109
110 match vm_creation_requested.stats_write() {
111 Err(e) => {
112 warn!("statslog_rust failed with error: {}", e);
113 }
114 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
115 }
116}
Seungjae Yooacf559a2022-08-12 04:44:51 +0000117
118/// Write the stats of VM boot to statsd
Seungjae Yoo62085c02022-08-12 04:44:52 +0000119pub fn write_vm_booted_stats(uid: i32, vm_identifier: &String) {
120 let vm_booted = vm_booted::VmBooted { uid, vm_identifier };
Seungjae Yooacf559a2022-08-12 04:44:51 +0000121 match vm_booted.stats_write() {
122 Err(e) => {
123 warn!("statslog_rust failed with error: {}", e);
124 }
125 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
126 }
127}
Seungjae Yoob4c07ba2022-08-12 04:44:52 +0000128
129/// Write the stats of VM exit to statsd
Seungjae Yoo62085c02022-08-12 04:44:52 +0000130pub fn write_vm_exited_stats(uid: i32, vm_identifier: &String, reason: DeathReason) {
Seungjae Yoob4c07ba2022-08-12 04:44:52 +0000131 let vm_exited = vm_exited::VmExited {
Seungjae Yoo62085c02022-08-12 04:44:52 +0000132 uid,
133 vm_identifier,
Seungjae Yoob4c07ba2022-08-12 04:44:52 +0000134 death_reason: match reason {
135 DeathReason::INFRASTRUCTURE_ERROR => vm_exited::DeathReason::InfrastructureError,
136 DeathReason::KILLED => vm_exited::DeathReason::Killed,
137 DeathReason::UNKNOWN => vm_exited::DeathReason::Unknown,
138 DeathReason::SHUTDOWN => vm_exited::DeathReason::Shutdown,
139 DeathReason::ERROR => vm_exited::DeathReason::Error,
140 DeathReason::REBOOT => vm_exited::DeathReason::Reboot,
141 DeathReason::CRASH => vm_exited::DeathReason::Crash,
142 DeathReason::PVM_FIRMWARE_PUBLIC_KEY_MISMATCH => {
143 vm_exited::DeathReason::PvmFirmwarePublicKeyMismatch
144 }
145 DeathReason::PVM_FIRMWARE_INSTANCE_IMAGE_CHANGED => {
146 vm_exited::DeathReason::PvmFirmwareInstanceImageChanged
147 }
148 DeathReason::BOOTLOADER_PUBLIC_KEY_MISMATCH => {
149 vm_exited::DeathReason::BootloaderPublicKeyMismatch
150 }
151 DeathReason::BOOTLOADER_INSTANCE_IMAGE_CHANGED => {
152 vm_exited::DeathReason::BootloaderInstanceImageChanged
153 }
154 DeathReason::MICRODROID_FAILED_TO_CONNECT_TO_VIRTUALIZATION_SERVICE => {
155 vm_exited::DeathReason::MicrodroidFailedToConnectToVirtualizationService
156 }
157 DeathReason::MICRODROID_PAYLOAD_HAS_CHANGED => {
158 vm_exited::DeathReason::MicrodroidPayloadHasChanged
159 }
160 DeathReason::MICRODROID_PAYLOAD_VERIFICATION_FAILED => {
161 vm_exited::DeathReason::MicrodroidPayloadVerificationFailed
162 }
163 DeathReason::MICRODROID_INVALID_PAYLOAD_CONFIG => {
164 vm_exited::DeathReason::MicrodroidInvalidPayloadConfig
165 }
166 DeathReason::MICRODROID_UNKNOWN_RUNTIME_ERROR => {
167 vm_exited::DeathReason::MicrodroidUnknownRuntimeError
168 }
169 DeathReason::HANGUP => vm_exited::DeathReason::Hangup,
170 _ => vm_exited::DeathReason::Unknown,
171 },
172 };
173 match vm_exited.stats_write() {
174 Err(e) => {
175 warn!("statslog_rust failed with error: {}", e);
176 }
177 Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
178 }
179}