// Copyright 2022, The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Functions for creating and collecting atoms.

use crate::aidl::{clone_file, GLOBAL_SERVICE};
use crate::crosvm::VmMetric;
use crate::get_calling_uid;
use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::DeathReason::DeathReason;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
    CpuTopology::CpuTopology,
    IVirtualMachine::IVirtualMachine,
    VirtualMachineAppConfig::{Payload::Payload, VirtualMachineAppConfig},
    VirtualMachineConfig::VirtualMachineConfig,
};
use android_system_virtualizationservice::binder::{Status, Strong};
use android_system_virtualizationservice_internal::aidl::android::system::virtualizationservice_internal::{
    AtomVmBooted::AtomVmBooted,
    AtomVmCreationRequested::AtomVmCreationRequested,
    AtomVmExited::AtomVmExited,
};
use anyhow::{anyhow, Result};
use binder::ParcelFileDescriptor;
use log::{info, warn};
use microdroid_payload_config::VmPayloadConfig;
use statslog_virtualization_rust::vm_creation_requested;
use std::thread;
use std::time::{Duration, SystemTime};
use zip::ZipArchive;

const INVALID_NUM_CPUS: i32 = -1;

fn get_apex_list(config: &VirtualMachineAppConfig) -> String {
    match &config.payload {
        Payload::PayloadConfig(_) => String::new(),
        Payload::ConfigPath(config_path) => {
            let vm_payload_config = get_vm_payload_config(&config.apk, config_path);
            if let Ok(vm_payload_config) = vm_payload_config {
                vm_payload_config
                    .apexes
                    .iter()
                    .map(|x| x.name.clone())
                    .collect::<Vec<String>>()
                    .join(":")
            } else {
                "INFO: Can't get VmPayloadConfig".to_owned()
            }
        }
    }
}

fn get_vm_payload_config(
    apk_fd: &Option<ParcelFileDescriptor>,
    config_path: &str,
) -> Result<VmPayloadConfig> {
    let apk = apk_fd.as_ref().ok_or_else(|| anyhow!("APK is none"))?;
    let apk_file = clone_file(apk)?;
    let mut apk_zip = ZipArchive::new(&apk_file)?;
    let config_file = apk_zip.by_name(config_path)?;
    let vm_payload_config: VmPayloadConfig = serde_json::from_reader(config_file)?;
    Ok(vm_payload_config)
}

fn get_duration(vm_start_timestamp: Option<SystemTime>) -> Duration {
    match vm_start_timestamp {
        Some(vm_start_timestamp) => vm_start_timestamp.elapsed().unwrap_or_default(),
        None => Duration::default(),
    }
}

// Returns the number of CPUs configured in the host system.
// This matches how crosvm determines the number of logical cores.
// For telemetry purposes only.
pub(crate) fn get_num_cpus() -> Option<usize> {
    // SAFETY - Only integer constants passed back and forth.
    let ret = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_CONF) };
    if ret > 0 {
        ret.try_into().ok()
    } else {
        None
    }
}

/// Write the stats of VMCreation to statsd
/// The function creates a separate thread which waits for statsd to start to push atom
pub fn write_vm_creation_stats(
    config: &VirtualMachineConfig,
    is_protected: bool,
    ret: &binder::Result<Strong<dyn IVirtualMachine>>,
) {
    let creation_succeeded;
    let binder_exception_code;
    match ret {
        Ok(_) => {
            creation_succeeded = true;
            binder_exception_code = Status::ok().exception_code() as i32;
        }
        Err(ref e) => {
            creation_succeeded = false;
            binder_exception_code = e.exception_code() as i32;
        }
    }
    let (vm_identifier, config_type, cpu_topology, memory_mib, apexes) = match config {
        VirtualMachineConfig::AppConfig(config) => (
            config.name.clone(),
            vm_creation_requested::ConfigType::VirtualMachineAppConfig,
            config.cpuTopology,
            config.memoryMib,
            get_apex_list(config),
        ),
        VirtualMachineConfig::RawConfig(config) => (
            config.name.clone(),
            vm_creation_requested::ConfigType::VirtualMachineRawConfig,
            config.cpuTopology,
            config.memoryMib,
            String::new(),
        ),
    };

    let num_cpus: i32 = match cpu_topology {
        CpuTopology::MATCH_HOST => {
            get_num_cpus().and_then(|v| v.try_into().ok()).unwrap_or_else(|| {
                warn!("Failed to determine the number of CPUs in the host");
                INVALID_NUM_CPUS
            })
        }
        _ => 1,
    };

    let atom = AtomVmCreationRequested {
        uid: get_calling_uid() as i32,
        vmIdentifier: vm_identifier,
        isProtected: is_protected,
        creationSucceeded: creation_succeeded,
        binderExceptionCode: binder_exception_code,
        configType: config_type as i32,
        numCpus: num_cpus,
        memoryMib: memory_mib,
        apexes,
    };

    info!("Writing VmCreationRequested atom into statsd.");
    thread::spawn(move || {
        GLOBAL_SERVICE.atomVmCreationRequested(&atom).unwrap_or_else(|e| {
            warn!("Failed to write VmCreationRequested atom: {e}");
        });
    });
}

/// Write the stats of VM boot to statsd
/// The function creates a separate thread which waits for statsd to start to push atom
pub fn write_vm_booted_stats(
    uid: i32,
    vm_identifier: &str,
    vm_start_timestamp: Option<SystemTime>,
) {
    let vm_identifier = vm_identifier.to_owned();
    let duration = get_duration(vm_start_timestamp);

    let atom = AtomVmBooted {
        uid,
        vmIdentifier: vm_identifier,
        elapsedTimeMillis: duration.as_millis() as i64,
    };

    info!("Writing VmBooted atom into statsd.");
    thread::spawn(move || {
        GLOBAL_SERVICE.atomVmBooted(&atom).unwrap_or_else(|e| {
            warn!("Failed to write VmBooted atom: {e}");
        });
    });
}

/// Write the stats of VM exit to statsd
pub fn write_vm_exited_stats_sync(
    uid: i32,
    vm_identifier: &str,
    reason: DeathReason,
    exit_signal: Option<i32>,
    vm_metric: &VmMetric,
) {
    let vm_identifier = vm_identifier.to_owned();
    let elapsed_time_millis = get_duration(vm_metric.start_timestamp).as_millis() as i64;
    let guest_time_millis = vm_metric.cpu_guest_time.unwrap_or_default();
    let rss = vm_metric.rss.unwrap_or_default();

    let atom = AtomVmExited {
        uid,
        vmIdentifier: vm_identifier,
        elapsedTimeMillis: elapsed_time_millis,
        deathReason: reason,
        guestTimeMillis: guest_time_millis,
        rssVmKb: rss.vm,
        rssCrosvmKb: rss.crosvm,
        exitSignal: exit_signal.unwrap_or_default(),
    };

    info!("Writing VmExited atom into statsd.");
    GLOBAL_SERVICE.atomVmExited(&atom).unwrap_or_else(|e| {
        warn!("Failed to write VmExited atom: {e}");
    });
}
