/*
 * Copyright (C) 2019 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.
 */

#include "host/libs/vm_manager/crosvm_manager.h"

#include <string>
#include <vector>

#include <glog/logging.h>

#include "common/libs/utils/network.h"
#include "common/libs/utils/subprocess.h"
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/vm_manager/disk_config.h"
#include "host/libs/vm_manager/qemu_manager.h"

namespace vm_manager {

namespace {

std::string GetControlSocketPath(const vsoc::CuttlefishConfig* config) {
  return config->PerInstancePath("crosvm_control.sock");
}

cvd::SharedFD ConnectToLogMonitor(const std::string& log_monitor_name) {
  return cvd::SharedFD::Open(log_monitor_name.c_str(), O_WRONLY);
}

void AddTapFdParameter(cvd::Command* crosvm_cmd, const std::string& tap_name) {
  auto tap_fd = cvd::OpenTapInterface(tap_name);
  if (tap_fd->IsOpen()) {
    crosvm_cmd->AddParameter("--tap-fd=", tap_fd);
  } else {
    LOG(ERROR) << "Unable to connect to " << tap_name << ": "
               << tap_fd->StrError();
  }
}

}  // namespace

const std::string CrosvmManager::name() { return "crosvm"; }

bool CrosvmManager::ConfigureGpu(vsoc::CuttlefishConfig* config) {
  // Override the default HAL search paths in all cases. We do this because
  // the HAL search path allows for fallbacks, and fallbacks in conjunction
  // with properities lead to non-deterministic behavior while loading the
  // HALs.
  if (config->gpu_mode() == vsoc::kGpuModeDrmVirgl) {
    config->add_kernel_cmdline("androidboot.hardware.gralloc=minigbm");
    config->add_kernel_cmdline("androidboot.hardware.hwcomposer=drm_minigbm");
    config->add_kernel_cmdline("androidboot.hardware.egl=mesa");
    return true;
  }
  if (config->gpu_mode() == vsoc::kGpuModeGuestSwiftshader) {
    config->add_kernel_cmdline(
        "androidboot.hardware.gralloc=cutf_ashmem");
    config->add_kernel_cmdline(
        "androidboot.hardware.hwcomposer=cutf_cvm_ashmem");
    config->add_kernel_cmdline("androidboot.hardware.egl=swiftshader");
    return true;
  }
  return false;
}

void CrosvmManager::ConfigureBootDevices(vsoc::CuttlefishConfig* config) {
  // PCI domain 0, bus 0, device 1, function 0
  // TODO There is no way to control this assignment with crosvm (yet)
  config->add_kernel_cmdline(
    "androidboot.boot_devices=pci0000:00/0000:00:01.0");
}

CrosvmManager::CrosvmManager(const vsoc::CuttlefishConfig* config)
    : VmManager(config) {}

cvd::Command CrosvmManager::StartCommand(bool with_frontend) {
  // Run crosvm directly instead of through a cf_crosvm.sh script. The kernel
  // logs are on crosvm's standard output, so we need to redirect it to the log
  // monitor socket, a helper script will print more than just the logs to
  // standard output.
  cvd::Command command(config_->crosvm_binary());
  command.AddParameter("run");

  if (config_->gpu_mode() != vsoc::kGpuModeGuestSwiftshader) {
    command.AddParameter("--gpu");
    command.AddParameter("--wayland-sock=", config_->wayland_socket());
  }
  if (!config_->ramdisk_image_path().empty()) {
    command.AddParameter("--initrd=", config_->ramdisk_image_path());
  }
  command.AddParameter("--null-audio");
  command.AddParameter("--mem=", config_->memory_mb());
  command.AddParameter("--cpus=", config_->cpus());
  command.AddParameter("--params=", config_->kernel_cmdline_as_string());
  if (config_->composite_disk_path().empty()) {
    if (config_->super_image_path().empty()) {
      command.AddParameter("--rwdisk=", config_->system_image_path());
    } else {
      command.AddParameter("--rwdisk=", config_->super_image_path());
    }
    command.AddParameter("--rwdisk=", config_->data_image_path());
    command.AddParameter("--rwdisk=", config_->cache_image_path());
    command.AddParameter("--rwdisk=", config_->metadata_image_path());
    if (config_->super_image_path().empty()) {
      command.AddParameter("--rwdisk=", config_->vendor_image_path());
      command.AddParameter("--rwdisk=", config_->product_image_path());
    }
  } else {
    if (should_create_composite_disk(*config_)) {
      create_composite_disk(*config_);
    }
    command.AddParameter("--rwdisk=", config_->composite_disk_path());
  }
  command.AddParameter("--socket=", GetControlSocketPath(config_));
  if (!config_->gsi_fstab_path().empty()) {
    command.AddParameter("--android-fstab=", config_->gsi_fstab_path());
  }

  if (with_frontend) {
    command.AddParameter("--single-touch=", config_->touch_socket_path(), ":",
                         config_->x_res(), ":", config_->y_res());
    command.AddParameter("--keyboard=", config_->keyboard_socket_path());
  }

  AddTapFdParameter(&command, config_->wifi_tap_name());
  AddTapFdParameter(&command, config_->mobile_tap_name());

  // TODO remove this (use crosvm's seccomp files)
  command.AddParameter("--disable-sandbox");

  if (config_->vsock_guest_cid() >= 2) {
    command.AddParameter("--cid=", config_->vsock_guest_cid());
  }

  auto kernel_log_connection =
      ConnectToLogMonitor(config_->kernel_log_pipe_name());
  if (!kernel_log_connection->IsOpen()) {
    LOG(WARNING) << "Unable to connect to log monitor: "
                 << kernel_log_connection->StrError();
  } else {
    command.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut,
                          kernel_log_connection);
  }

  auto dev_null = cvd::SharedFD::Open("/dev/null", O_RDONLY);
  if (dev_null->IsOpen()) {
    command.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdIn, dev_null);
  } else {
    LOG(ERROR) << "Unable to open /dev/null for stdin redirection";
  }

  // This needs to be the last parameter
  command.AddParameter(config_->GetKernelImageToUse());

  return command;
}

bool CrosvmManager::Stop() {
  cvd::Command command(config_->crosvm_binary());
  command.AddParameter("stop");
  command.AddParameter(GetControlSocketPath(config_));

  auto process = command.Start();

  return process.Wait() == 0;
}

}  // namespace vm_manager
