/*
 * 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/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::SocketLocalClient(log_monitor_name.c_str(), false,
                                          SOCK_STREAM);
}

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"; }

void CrosvmManager::ConfigureBootDevices(vsoc::CuttlefishConfig* config) {
  // PCI domain 0, bus 0, device 5, 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:05.0");
}

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

cvd::Command CrosvmManager::StartCommand() {
  // TODO Add aarch64 support
  // TODO Add the tap interfaces (--tap-fd)
  // TODO Redirect logcat output

  // 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_->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_->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());
  }
  command.AddParameter("--socket=", GetControlSocketPath(config_));
  if (!config_->gsi_fstab_path().empty()) {
    command.AddParameter("--android-fstab=", config_->gsi_fstab_path());
  }
  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_socket_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

