/*
 * 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 <sys/stat.h>
#include <sys/types.h>

#include <cassert>
#include <string>
#include <vector>

#include <android-base/strings.h>
#include <android-base/logging.h>
#include <vulkan/vulkan.h>

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

namespace cuttlefish {
namespace vm_manager {

namespace {

std::string GetControlSocketPath(const CuttlefishConfig& config) {
  return config.ForDefaultInstance()
      .PerInstanceInternalPath("crosvm_control.sock");
}

SharedFD AddTapFdParameter(Command* crosvm_cmd,
                                const std::string& tap_name) {
  auto tap_fd = 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();
  }
  return tap_fd;
}

bool ReleaseDhcpLeases(const std::string& lease_path, SharedFD tap_fd) {
  auto lease_file_fd = SharedFD::Open(lease_path, O_RDONLY);
  if (!lease_file_fd->IsOpen()) {
    LOG(ERROR) << "Could not open leases file \"" << lease_path << '"';
    return false;
  }
  bool success = true;
  auto dhcp_leases = ParseDnsmasqLeases(lease_file_fd);
  for (auto& lease : dhcp_leases) {
    std::uint8_t dhcp_server_ip[] = {192, 168, 96, (std::uint8_t) (ForCurrentInstance(1) * 4 - 3)};
    if (!ReleaseDhcp4(tap_fd, lease.mac_address, lease.ip_address, dhcp_server_ip)) {
      LOG(ERROR) << "Failed to release " << lease;
      success = false;
    } else {
      LOG(INFO) << "Successfully dropped " << lease;
    }
  }
  return success;
}

bool Stop() {
  auto config = CuttlefishConfig::Get();
  Command command(config->crosvm_binary());
  command.AddParameter("stop");
  command.AddParameter(GetControlSocketPath(*config));

  auto process = command.Start();

  return process.Wait() == 0;
}

}  // namespace

bool CrosvmManager::IsSupported() {
#ifdef __ANDROID__
  return true;
#else
  return HostSupportsQemuCli();
#endif
}

std::vector<std::string> CrosvmManager::ConfigureGpuMode(
    const std::string& gpu_mode) {
  // 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 (gpu_mode == kGpuModeGuestSwiftshader) {
    return {
        "androidboot.cpuvulkan.version=" + std::to_string(VK_API_VERSION_1_2),
        "androidboot.hardware.gralloc=minigbm",
        "androidboot.hardware.hwcomposer=ranchu",
        "androidboot.hardware.egl=angle",
        "androidboot.hardware.vulkan=pastel",
    };
  }

  if (gpu_mode == kGpuModeDrmVirgl) {
    return {
      "androidboot.cpuvulkan.version=0",
      "androidboot.hardware.gralloc=minigbm",
      "androidboot.hardware.hwcomposer=drm_minigbm",
      "androidboot.hardware.egl=mesa",
    };
  }
  if (gpu_mode == kGpuModeGfxStream) {
    return {
        "androidboot.cpuvulkan.version=0",
        "androidboot.hardware.gralloc=minigbm",
        "androidboot.hardware.hwcomposer=ranchu",
        "androidboot.hardware.egl=emulation",
        "androidboot.hardware.vulkan=ranchu",
        "androidboot.hardware.gltransport=virtio-gpu-asg",
    };
  }
  return {};
}

std::string CrosvmManager::ConfigureBootDevices(int num_disks) {
  // TODO There is no way to control this assignment with crosvm (yet)
  if (HostArch() == Arch::X86_64) {
    // crosvm has an additional PCI device for an ISA bridge
    return ConfigureMultipleBootDevices("pci0000:00/0000:00:", 1, num_disks);
  } else {
    // On ARM64 crosvm, block devices are on their own bridge, so we don't
    // need to calculate it, and the path is always the same
    return "androidboot.boot_devices=10000.pci";
  }
}

std::vector<Command> CrosvmManager::StartCommands(
    const CuttlefishConfig& config) {
  auto instance = config.ForDefaultInstance();
  Command crosvm_cmd(config.crosvm_binary(), [](Subprocess* proc) {
    auto stopped = Stop();
    if (stopped) {
      return true;
    }
    LOG(WARNING) << "Failed to stop VMM nicely, attempting to KILL";
    return KillSubprocess(proc);
  });

  int hvc_num = 0;
  int serial_num = 0;
  auto add_hvc_sink = [&crosvm_cmd, &hvc_num]() {
    crosvm_cmd.AddParameter("--serial=hardware=virtio-console,num=", ++hvc_num,
                            ",type=sink");
  };
  auto add_serial_sink = [&crosvm_cmd, &serial_num]() {
    crosvm_cmd.AddParameter("--serial=hardware=serial,num=", ++serial_num,
                            ",type=sink");
  };
  auto add_hvc_console = [&crosvm_cmd, &hvc_num](const std::string& output) {
    crosvm_cmd.AddParameter("--serial=hardware=virtio-console,num=", ++hvc_num,
                            ",type=file,path=", output, ",console=true");
  };
  auto add_serial_console_ro = [&crosvm_cmd,
                                &serial_num](const std::string& output) {
    crosvm_cmd.AddParameter("--serial=hardware=serial,num=", ++serial_num,
                            ",type=file,path=", output, ",earlycon=true");
  };
  auto add_serial_console = [&crosvm_cmd, &serial_num](
                                const std::string& output,
                                const std::string& input) {
    crosvm_cmd.AddParameter("--serial=hardware=serial,num=", ++serial_num,
                            ",type=file,path=", output, ",input=", input,
                            ",earlycon=true");
  };
  auto add_hvc_ro = [&crosvm_cmd, &hvc_num](const std::string& output) {
    crosvm_cmd.AddParameter("--serial=hardware=virtio-console,num=", ++hvc_num,
                            ",type=file,path=", output);
  };
  auto add_hvc = [&crosvm_cmd, &hvc_num](const std::string& output,
                                         const std::string& input) {
    crosvm_cmd.AddParameter("--serial=hardware=virtio-console,num=", ++hvc_num,
                            ",type=file,path=", output, ",input=", input);
  };
  // Deprecated; do not add any more users
  auto add_serial = [&crosvm_cmd, &serial_num](const std::string& output,
                                               const std::string& input) {
    crosvm_cmd.AddParameter("--serial=hardware=serial,num=", ++serial_num,
                            ",type=file,path=", output, ",input=", input);
  };

  crosvm_cmd.AddParameter("run");

  if (!config.smt()) {
    crosvm_cmd.AddParameter("--no-smt");
  }

  if (config.vhost_net()) {
    crosvm_cmd.AddParameter("--vhost-net");
  }

  if (config.protected_vm()) {
    crosvm_cmd.AddParameter("--protected-vm");
  }

  if (config.gdb_port() > 0) {
    CHECK(config.cpus() == 1) << "CPUs must be 1 for crosvm gdb mode";
    crosvm_cmd.AddParameter("--gdb=", config.gdb_port());
  }

  auto gpu_mode = config.gpu_mode();
  if (gpu_mode == kGpuModeGuestSwiftshader) {
    crosvm_cmd.AddParameter("--gpu=2D");
  } else if (gpu_mode == kGpuModeDrmVirgl || gpu_mode == kGpuModeGfxStream) {
    crosvm_cmd.AddParameter(gpu_mode == kGpuModeGfxStream ?
                                "--gpu=gfxstream," : "--gpu=",
                            "egl=true,surfaceless=true,glx=false,gles=true");
  }

  for (const auto& display_config : config.display_configs()) {
    crosvm_cmd.AddParameter("--gpu-display=", "width=", display_config.width,
                            ",", "height=", display_config.height);
  }

  crosvm_cmd.AddParameter("--wayland-sock=", instance.frames_socket_path());

  // crosvm_cmd.AddParameter("--null-audio");
  crosvm_cmd.AddParameter("--mem=", config.memory_mb());
  crosvm_cmd.AddParameter("--cpus=", config.cpus());

  auto disk_num = instance.virtual_disk_paths().size();
  CHECK_GE(VmManager::kMaxDisks, disk_num)
      << "Provided too many disks (" << disk_num << "), maximum "
      << VmManager::kMaxDisks << "supported";
  for (const auto& disk : instance.virtual_disk_paths()) {
    crosvm_cmd.AddParameter(config.protected_vm() ? "--disk=" :
                                                    "--rwdisk=", disk);
  }
  crosvm_cmd.AddParameter("--socket=", GetControlSocketPath(config));

  if (config.enable_vnc_server() || config.enable_webrtc()) {
    auto touch_type_parameter =
        config.enable_webrtc() ? "--multi-touch=" : "--single-touch=";

    auto display_configs = config.display_configs();
    CHECK_GE(display_configs.size(), 1);

    for (int i = 0; i < display_configs.size(); ++i) {
      auto display_config = display_configs[i];

      crosvm_cmd.AddParameter(touch_type_parameter,
                              instance.touch_socket_path(i), ":",
                              display_config.width, ":", display_config.height);
    }
    crosvm_cmd.AddParameter("--keyboard=", instance.keyboard_socket_path());
  }
  if (config.enable_webrtc()) {
    crosvm_cmd.AddParameter("--switches=", instance.switches_socket_path());
  }

  AddTapFdParameter(&crosvm_cmd, instance.mobile_tap_name());
  AddTapFdParameter(&crosvm_cmd, instance.ethernet_tap_name());
  auto wifi_tap = AddTapFdParameter(&crosvm_cmd, instance.wifi_tap_name());

  if (FileExists(instance.access_kregistry_path())) {
    crosvm_cmd.AddParameter("--rw-pmem-device=",
                            instance.access_kregistry_path());
  }

  if (FileExists(instance.pstore_path())) {
    crosvm_cmd.AddParameter("--pstore=path=", instance.pstore_path(),
                            ",size=", FileSize(instance.pstore_path()));
  }

  if (config.enable_sandbox()) {
    const bool seccomp_exists = DirectoryExists(config.seccomp_policy_dir());
    const std::string& var_empty_dir = kCrosvmVarEmptyDir;
    const bool var_empty_available = DirectoryExists(var_empty_dir);
    if (!var_empty_available || !seccomp_exists) {
      LOG(FATAL) << var_empty_dir << " is not an existing, empty directory."
                 << "seccomp-policy-dir, " << config.seccomp_policy_dir()
                 << " does not exist " << std::endl;
      return {};
    }
    crosvm_cmd.AddParameter("--seccomp-policy-dir=", config.seccomp_policy_dir());
  } else {
    crosvm_cmd.AddParameter("--disable-sandbox");
  }

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

  // Use a virtio-console instance for the main kernel console. All
  // messages will switch from earlycon to virtio-console after the driver
  // is loaded, and crosvm will append to the kernel log automatically
  add_hvc_console(instance.kernel_log_pipe_name());

  if (config.console()) {
    // stdin is the only currently supported way to write data to a serial port in
    // crosvm. A file (named pipe) is used here instead of stdout to ensure only
    // the serial port output is received by the console forwarder as crosvm may
    // print other messages to stdout.
    if (config.kgdb() || config.use_bootloader()) {
      add_serial_console(instance.console_out_pipe_name(),
                         instance.console_in_pipe_name());
      // In kgdb mode, we have the interactive console on ttyS0 (both Android's
      // console and kdb), so we can disable the virtio-console port usually
      // allocated to Android's serial console, and redirect it to a sink. This
      // ensures that that the PCI device assignments (and thus sepolicy) don't
      // have to change
      add_hvc_sink();
    } else {
      add_serial_sink();
      add_hvc(instance.console_out_pipe_name(),
              instance.console_in_pipe_name());
    }
  } else {
    // Use an 8250 UART (ISA or platform device) for earlycon, as the
    // virtio-console driver may not be available for early messages
    // In kgdb mode, earlycon is an interactive console, and so early
    // dmesg will go there instead of the kernel.log
    if (config.kgdb() || config.use_bootloader()) {
      add_serial_console_ro(instance.kernel_log_pipe_name());
    }

    // as above, create a fake virtio-console 'sink' port when the serial
    // console is disabled, so the PCI device ID assignments don't move
    // around
    add_hvc_sink();
  }

  if (config.enable_gnss_grpc_proxy()) {
    add_serial(instance.gnss_out_pipe_name(), instance.gnss_in_pipe_name());
  }

  SharedFD log_out_rd, log_out_wr;
  if (!SharedFD::Pipe(&log_out_rd, &log_out_wr)) {
    LOG(ERROR) << "Failed to create log pipe for crosvm's stdout/stderr: "
               << log_out_rd->StrError();
    return {};
  }
  crosvm_cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdOut, log_out_wr);
  crosvm_cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdErr, log_out_wr);

  Command log_tee_cmd(HostBinaryPath("log_tee"));
  log_tee_cmd.AddParameter("--process_name=crosvm");
  log_tee_cmd.AddParameter("--log_fd_in=", log_out_rd);

  // Serial port for logcat, redirected to a pipe
  add_hvc_ro(instance.logcat_pipe_name());

  add_hvc(instance.PerInstanceInternalPath("keymaster_fifo_vm.out"),
          instance.PerInstanceInternalPath("keymaster_fifo_vm.in"));
  add_hvc(instance.PerInstanceInternalPath("gatekeeper_fifo_vm.out"),
          instance.PerInstanceInternalPath("gatekeeper_fifo_vm.in"));

  if (config.enable_host_bluetooth()) {
    add_hvc(instance.PerInstanceInternalPath("bt_fifo_vm.out"),
            instance.PerInstanceInternalPath("bt_fifo_vm.in"));
  } else {
    add_hvc_sink();
  }
  for (auto i = 0; i < VmManager::kMaxDisks - disk_num; i++) {
    add_hvc_sink();
  }
  CHECK(hvc_num + disk_num == VmManager::kMaxDisks + VmManager::kDefaultNumHvcs)
      << "HVC count (" << hvc_num << ") + disk count (" << disk_num << ") "
      << "is not the expected total of "
      << VmManager::kMaxDisks + VmManager::kDefaultNumHvcs << " devices";

  if (config.enable_audio()) {
    crosvm_cmd.AddParameter("--sound=",
                            config.ForDefaultInstance().audio_server_path());
  }

  // TODO(b/162071003): virtiofs crashes without sandboxing, this should be fixed
  if (config.enable_sandbox()) {
    // Set up directory shared with virtiofs
    crosvm_cmd.AddParameter("--shared-dir=", instance.PerInstancePath(kSharedDirName),
                            ":shared:type=fs");
  }

  // This needs to be the last parameter
  crosvm_cmd.AddParameter("--bios=", config.bootloader());

  // Only run the leases workaround if we are not using the new network
  // bridge architecture - in that case, we have a wider DHCP address
  // space and stale leases should be much less of an issue
  if (!FileExists("/var/run/cuttlefish-dnsmasq-cvd-wbr.leases")) {
    // TODO(schuffelen): QEMU also needs this and this is not the best place for
    // this code. Find a better place to put it.
    auto lease_file =
        ForCurrentInstance("/var/run/cuttlefish-dnsmasq-cvd-wbr-") + ".leases";
    if (!ReleaseDhcpLeases(lease_file, wifi_tap)) {
      LOG(ERROR) << "Failed to release wifi DHCP leases. Connecting to the wifi "
                 << "network may not work.";
    }
  }

  std::vector<Command> ret;
  ret.push_back(std::move(crosvm_cmd));
  ret.push_back(std::move(log_tee_cmd));
  return ret;
}

} // namespace vm_manager
} // namespace cuttlefish

