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

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());
  command.AddParameter("--rwdisk=", config_->system_image_path());
  command.AddParameter("--rwdisk=", config_->data_image_path());
  command.AddParameter("--rwdisk=", config_->cache_image_path());
  command.AddParameter("--rwdisk=", config_->metadata_image_path());
  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

