/*
 * Copyright (C) 2017 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 <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>

#include <algorithm>
#include <fstream>
#include <iomanip>
#include <memory>
#include <sstream>
#include <string>
#include <vector>

#include <gflags/gflags.h>
#include <glog/logging.h>

#include "common/libs/fs/shared_select.h"
#include "common/libs/strings/str_split.h"
#include "common/vsoc/lib/vsoc_memory.h"
#include "common/vsoc/shm/screen_layout.h"
#include "host/commands/launch/pre_launch_initializers.h"
#include "host/libs/config/file_partition.h"
#include "host/libs/config/guest_config.h"
#include "host/libs/config/host_config.h"
#include "host/libs/ivserver/ivserver.h"
#include "host/libs/ivserver/options.h"
#include "host/libs/monitor/kernel_log_server.h"
#include "host/libs/usbip/server.h"
#include "host/libs/vadb/virtual_adb_server.h"

namespace {
std::string StringFromEnv(const char* varname, std::string defval) {
  const char* const valstr = getenv(varname);
  if (!valstr) {
    return defval;
  }
  return valstr;
}
}  // namespace

#define VIRSH_OPTIONS_PLACEHOLDER "<virsh_options>"

using vsoc::GetPerInstanceDefault;
using vsoc::GetDefaultPerInstancePath;

DEFINE_string(cache_image, "", "Location of the cache partition image.");
DEFINE_int32(cpus, 2, "Virtual CPU count.");
DEFINE_string(data_image, "", "Location of the data partition image.");
DEFINE_string(data_policy, "use_existing", "How to handle userdata partition."
            " Either 'use_existing', 'create_if_missing', or 'always_create'.");
DEFINE_int32(blank_data_image_mb, 0,
             "The size of the blank data image to generate, MB.");
DEFINE_string(blank_data_image_fmt, "ext4",
              "The fs format for the blank data image. Used with mkfs.");

DECLARE_int32(dpi);
DECLARE_int32(x_res);
DECLARE_int32(y_res);
DECLARE_int32(num_screen_buffers);

DEFINE_bool(disable_app_armor_security, false,
            "Disable AppArmor security in libvirt. For debug only.");
DEFINE_bool(disable_dac_security, false,
            "Disable DAC security in libvirt. For debug only.");
DEFINE_string(extra_kernel_command_line, "",
              "Additional flags to put on the kernel command line");
DECLARE_int32(instance);
DEFINE_string(initrd, "", "Location of cuttlefish initrd file.");
DEFINE_string(kernel, "", "Location of cuttlefish kernel file.");
DEFINE_string(kernel_command_line, "",
              "Location of a text file with the kernel command line.");
DEFINE_string(hypervisor_uri, "qemu:///system", "Hypervisor cannonical uri.");
DEFINE_string(launch_command,
              "virsh " VIRSH_OPTIONS_PLACEHOLDER " create /dev/fd/0",
              "Command to start an instance. If <virsh_options> is present it "
              "will be replaced by options to the virsh command");
DEFINE_bool(log_xml, false, "Log the XML machine configuration");
DEFINE_int32(memory_mb, 2048,
             "Total amount of memory available for guest, MB.");
std::string g_default_mempath{GetPerInstanceDefault("/var/run/shm/cvd-")};
DEFINE_string(mempath, g_default_mempath.c_str(),
              "Target location for the shmem file.");
std::string g_default_mobile_interface{GetPerInstanceDefault("cvd-mobile-")};
DEFINE_string(mobile_interface, g_default_mobile_interface.c_str(),
              "Network interface to use for mobile networking");
std::string g_default_qemusocket = GetDefaultPerInstancePath("ivshmem_socket_qemu");
DEFINE_string(qemusocket, g_default_qemusocket.c_str(), "QEmu socket path");
std::string g_default_serial_number{GetPerInstanceDefault("CUTTLEFISHCVD")};
DEFINE_string(serial_number, g_default_serial_number.c_str(),
              "Serial number to use for the device");
DEFINE_string(system_image_dir,
              StringFromEnv("ANDROID_PRODUCT_OUT", StringFromEnv("HOME", ".")),
              "Location of the system partition images.");
DEFINE_string(vendor_image, "", "Location of the vendor partition image.");

DEFINE_bool(deprecated_boot_completed, false, "Log boot completed message to"
            " host kernel. This is only used during transition of our clients."
            " Will be deprecated soon.");
DEFINE_bool(start_vnc_server, true, "Whether to start the vnc server process.");
DEFINE_string(vnc_server_binary,
              StringFromEnv("ANDROID_HOST_OUT", StringFromEnv("HOME", ".")) +
                  "/bin/vnc_server",
              "Location of the vnc server binary.");
DEFINE_int32(vnc_server_port, GetPerInstanceDefault(6444),
             "The port on which the vnc server should listen");
DEFINE_string(socket_forward_proxy_binary,
              StringFromEnv("ANDROID_HOST_OUT", StringFromEnv("HOME", ".")) +
                  "/bin/socket_forward_proxy",
              "Location of the socket_forward_proxy binary.");
DEFINE_string(adb_mode, "tunnel",
              "Mode for adb connection. Can be usb for usb forwarding, or "
              "tunnel for tcp connection. If using tunnel, you may have to "
              "run 'adb kill-server' to get the device to show up.");
DEFINE_int32(vhci_port, GetPerInstanceDefault(0), "VHCI port to use for usb");
DEFINE_bool(start_wifi_relay, true, "Whether to start the wifi_relay process.");
DEFINE_string(wifi_relay_binary,
              StringFromEnv("ANDROID_HOST_OUT", StringFromEnv("HOME", ".")) +
                  "/bin/wifi_relay",
              "Location of the wifi_relay binary.");
std::string g_default_wifi_interface{GetPerInstanceDefault("cvd-wifi-")};
DEFINE_string(wifi_interface, g_default_wifi_interface.c_str(),
              "Network interface to use for wifi");

DECLARE_string(uuid);

namespace {
const std::string kDataPolicyUseExisting = "use_existing";
const std::string kDataPolicyCreateIfMissing = "create_if_missing";
const std::string kDataPolicyAlwaysCreate = "always_create";

constexpr char kAdbModeTunnel[] = "tunnel";
constexpr char kAdbModeUsb[] = "usb";

std::string GetVirshOptions() {
  return std::string("-c ").append(FLAGS_hypervisor_uri);
}

// VirtualUSBManager manages virtual USB device presence for Cuttlefish.
class VirtualUSBManager {
 public:
  VirtualUSBManager(const std::string& usbsocket, int vhci_port,
                    const std::string& android_usbipsocket)
      : adb_{usbsocket, vhci_port, android_usbipsocket},
        usbip_{android_usbipsocket, adb_.Pool()} {}

  ~VirtualUSBManager() = default;

  // Initialize Virtual USB and start USB management thread.
  void Start() {
    CHECK(adb_.Init()) << "Could not initialize Virtual ADB server";
    CHECK(usbip_.Init()) << "Could not start USB/IP server";
    std::thread([this] { Thread(); }).detach();
  }

 private:
  void Thread() {
    for (;;) {
      cvd::SharedFDSet fd_read;
      fd_read.Zero();

      adb_.BeforeSelect(&fd_read);
      usbip_.BeforeSelect(&fd_read);

      int ret = cvd::Select(&fd_read, nullptr, nullptr, nullptr);
      if (ret <= 0) continue;

      adb_.AfterSelect(fd_read);
      usbip_.AfterSelect(fd_read);
    }
  }

  vadb::VirtualADBServer adb_;
  vadb::usbip::Server usbip_;

  VirtualUSBManager(const VirtualUSBManager&) = delete;
  VirtualUSBManager& operator=(const VirtualUSBManager&) = delete;
};

// IVServerManager takes care of serving shared memory segments between
// Cuttlefish and host-side daemons.
class IVServerManager {
 public:
  IVServerManager()
      : server_(ivserver::IVServerOptions(FLAGS_mempath,
                                          FLAGS_qemusocket,
                                          vsoc::GetDomain())) {}

  ~IVServerManager() = default;

  // Start IVServer thread.
  void Start() {
    std::thread([this] { server_.Serve(); }).detach();
  }

 private:
  ivserver::IVServer server_;

  IVServerManager(const IVServerManager&) = delete;
  IVServerManager& operator=(const IVServerManager&) = delete;
};

// KernelLogMonitor receives and monitors kernel log for Cuttlefish.
class KernelLogMonitor {
 public:
  KernelLogMonitor(const std::string& socket_name,
                   const std::string& log_name,
                   bool deprecated_boot_completed)
      : klog_{socket_name, log_name, deprecated_boot_completed} {}

  ~KernelLogMonitor() = default;

  void Start() {
    CHECK(klog_.Init()) << "Could not initialize kernel log server";
    std::thread([this] { Thread(); }).detach();
  }

 private:
  void Thread() {
    for (;;) {
      cvd::SharedFDSet fd_read;
      fd_read.Zero();

      klog_.BeforeSelect(&fd_read);

      int ret = cvd::Select(&fd_read, nullptr, nullptr, nullptr);
      if (ret <= 0) continue;

      klog_.AfterSelect(fd_read);
    }
  }

  monitor::KernelLogServer klog_;

  KernelLogMonitor(const KernelLogMonitor&) = delete;
  KernelLogMonitor& operator=(const KernelLogMonitor&) = delete;
};

void subprocess(const char* const* command,
                const char* const* envp,
                bool wait_for_child = true) {
  pid_t pid = fork();
  if (!pid) {
    int rval = execve(command[0], const_cast<char* const*>(command),
                      const_cast<char* const*>(envp));
    // No need for an if: if exec worked it wouldn't have returned
    LOG(ERROR) << "exec of " << command[0] << " failed (" << strerror(errno)
               << ")";
    exit(rval);
  }
  if (pid == -1) {
    LOG(ERROR) << "fork of " << command[0] << " failed (" << strerror(errno)
               << ")";
  }
  if (pid > 0) {
    if (wait_for_child) {
      waitpid(pid, 0, 0);
    } else {
      LOG(INFO) << "Started " << command[0] << ", pid: " << pid;
    }
  }
}

void CreateBlankImage(
    const std::string& image, int image_mb, const std::string& image_fmt) {
  LOG(INFO) << "Creating " << image;
  std::string of = "of=";
  of += image;
  std::string count = "count=";
  count += std::to_string(image_mb);
  const char* dd_command[]{
    "/bin/dd", "if=/dev/zero", of.c_str(), "bs=1M", count.c_str(), NULL};
  subprocess(dd_command, NULL);
  const char* mkfs_command[]{
    "/sbin/mkfs", "-t", image_fmt.c_str(), image.c_str(), NULL};
  const char* envp[]{"PATH=/sbin", NULL};
  subprocess(mkfs_command, envp);
}

void RemoveFile(const std::string& file) {
  LOG(INFO) << "Removing " << file;
  const char* rm_command[]{
    "/bin/rm", "-f", file.c_str(), NULL};
  subprocess(rm_command, NULL);
}

std::string GetGuestPortArg() {
  constexpr int kEmulatorPort = 5555;
  return std::string{"--guest_ports="} + std::to_string(kEmulatorPort);
}

std::string GetHostPortArg() {
  constexpr int kFirstHostPort = 6520;
  return std::string{"--host_ports="} +
      std::to_string(vsoc::GetPerInstanceDefault(kFirstHostPort));
}

std::string GetDomainArg() {
  return std::string{"--domain="} + vsoc::GetDomain();
}

std::string GetInstanceArg() {
  return std::string{"--instance="} + std::to_string(FLAGS_instance);
}

void ValidateAdbModeFlag() {
  CHECK(FLAGS_adb_mode == kAdbModeUsb ||
        FLAGS_adb_mode == kAdbModeTunnel) << "invalid --adb_mode";
}

bool AdbTunnelEnabled() {
  return FLAGS_adb_mode == kAdbModeTunnel;
}

bool AdbUsbEnabled() {
  return FLAGS_adb_mode == kAdbModeUsb;
}

void LaunchSocketForwardProxyIfEnabled() {
  if (AdbTunnelEnabled()) {
    auto guest_port_arg = GetGuestPortArg();
    auto host_port_arg = GetHostPortArg();
    auto domain_arg = GetDomainArg();
    auto instance_arg = GetInstanceArg();

    const char* const socket_proxy[] = {
      FLAGS_socket_forward_proxy_binary.c_str(),
      guest_port_arg.c_str(),
      host_port_arg.c_str(),
      domain_arg.c_str(),
      instance_arg.c_str(),
      NULL
    };
    subprocess(socket_proxy, nullptr, false);
  }
}

void LaunchVNCServerIfEnabled() {
  if (FLAGS_start_vnc_server) {
    // Launch the vnc server, don't wait for it to complete
    auto port_options = "-port=" + std::to_string(FLAGS_vnc_server_port);
    auto domain_arg = GetDomainArg();
    auto instance_arg = GetInstanceArg();
    const char* vnc_command[] = {
      FLAGS_vnc_server_binary.c_str(),
      port_options.c_str(),
      domain_arg.c_str(),
      instance_arg.c_str(),
      NULL
    };
    subprocess(vnc_command, NULL, false);
  }
}

void LaunchWifiRelayIfEnabled() {
  if (FLAGS_start_wifi_relay) {
    // Launch the wifi relay, don't wait for it to complete
    auto domain_arg = GetDomainArg();
    auto instance_arg = GetInstanceArg();

    const char* relay_command[] = {
        "/usr/bin/sudo",
        FLAGS_wifi_relay_binary.c_str(),
        domain_arg.c_str(),
        instance_arg.c_str(),
        NULL
    };

    subprocess(relay_command, NULL /* envp */, false /* wait_for_child */);
  }
}

}  // anonymous namespace

int main(int argc, char** argv) {
  ::android::base::InitLogging(argv, android::base::StderrLogger);
  google::ParseCommandLineFlags(&argc, &argv, true);
  ValidateAdbModeFlag();

  LOG_IF(FATAL, FLAGS_system_image_dir.empty())
      << "--system_image_dir must be specified.";

  std::string per_instance_dir = vsoc::GetDefaultPerInstanceDir();
  struct stat unused;
  if ((stat(per_instance_dir.c_str(), &unused) == -1) && (errno == ENOENT)) {
    LOG(INFO) << "Setting up " << per_instance_dir;
    const char* mkdir_command[]{
        "/usr/bin/sudo",          "/bin/mkdir", "-m", "0775",
        per_instance_dir.c_str(), NULL};
    subprocess(mkdir_command, NULL);
    std::string owner_group{getenv("USER")};
    owner_group += ":libvirt-qemu";
    const char* chown_command[]{"/usr/bin/sudo", "/bin/chown",
                                owner_group.c_str(), per_instance_dir.c_str(),
                                NULL};
    subprocess(chown_command, NULL);
  }

  // If user did not specify location of either of these files, expect them to
  // be placed in --system_image_dir location.
  if (FLAGS_kernel.empty()) {
    FLAGS_kernel = FLAGS_system_image_dir + "/kernel";
  }

  if (FLAGS_kernel_command_line.empty()) {
    FLAGS_kernel_command_line = FLAGS_system_image_dir + "/cmdline";
  }

  if (FLAGS_initrd.empty()) {
    FLAGS_initrd = FLAGS_system_image_dir + "/ramdisk.img";
  }

  if (FLAGS_cache_image.empty()) {
    FLAGS_cache_image = FLAGS_system_image_dir + "/cache.img";
  }

  if (FLAGS_data_policy == kDataPolicyCreateIfMissing) {
    FLAGS_data_image = FLAGS_system_image_dir + "/userdata_blank.img";
    if (FLAGS_blank_data_image_mb <= 0) {
      LOG(FATAL) << "You should use -blank_data_image_mb with -data_policy="
                 << kDataPolicyCreateIfMissing;
    }
    // Create a blank data image if the image doesn't exist yet
    if ((stat(FLAGS_data_image.c_str(), &unused) == -1) && (errno == ENOENT)) {
      CreateBlankImage(
          FLAGS_data_image, FLAGS_blank_data_image_mb, FLAGS_blank_data_image_fmt);
    } else {
      LOG(INFO) << FLAGS_data_image << " exists. Not creating it.";
    }
  } else if (FLAGS_data_policy == kDataPolicyAlwaysCreate) {
    FLAGS_data_image = FLAGS_system_image_dir + "/userdata_blank.img";
    if (FLAGS_blank_data_image_mb <= 0) {
      LOG(FATAL) << "You should use -blank_data_image_mb with -data_policy="
                 << kDataPolicyAlwaysCreate;
    }
    RemoveFile(FLAGS_data_image);
    CreateBlankImage(
        FLAGS_data_image, FLAGS_blank_data_image_mb, FLAGS_blank_data_image_fmt);
  } else if (FLAGS_data_policy == kDataPolicyUseExisting) {
    // Do nothing. Use FLAGS_data_image.
    if (FLAGS_blank_data_image_mb > 0) {
      LOG(FATAL) << "You should NOT use -blank_data_image_mb with -data_policy="
                 << kDataPolicyUseExisting;
    }
  } else {
    LOG(FATAL) << "Invalid data_policy: " << FLAGS_data_policy;
  }

  if (FLAGS_data_image.empty()) {
    FLAGS_data_image = FLAGS_system_image_dir + "/userdata.img";
  }

  if (FLAGS_vendor_image.empty()) {
    FLAGS_vendor_image = FLAGS_system_image_dir + "/vendor.img";
  }

  // Each of these calls is free to fail and terminate launch if file does not
  // exist or could not be created.
  auto system_partition = config::FilePartition::ReuseExistingFile(
      FLAGS_system_image_dir + "/system.img");
  auto data_partition =
      config::FilePartition::ReuseExistingFile(FLAGS_data_image);
  auto cache_partition =
      config::FilePartition::ReuseExistingFile(FLAGS_cache_image);
  auto vendor_partition =
      config::FilePartition::ReuseExistingFile(FLAGS_vendor_image);

  std::ostringstream cmdline;
  std::ifstream t(FLAGS_kernel_command_line);
  if (!t) {
    LOG(FATAL) << "Unable to open " << FLAGS_kernel_command_line;
  }
  cmdline << t.rdbuf();
  t.close();
  cmdline << " androidboot.serialno=" << FLAGS_serial_number;
  cmdline << " androidboot.lcd_density=" << FLAGS_dpi;
  if (FLAGS_extra_kernel_command_line.size()) {
    cmdline << " " << FLAGS_extra_kernel_command_line;
  }

  std::string entropy_source = "/dev/urandom";
  auto& memory_layout = *vsoc::VSoCMemoryLayout::Get();

  config::GuestConfig cfg;
  cfg.SetID(FLAGS_instance)
      .SetVCPUs(FLAGS_cpus)
      .SetMemoryMB(FLAGS_memory_mb)
      .SetKernelName(FLAGS_kernel)
      .SetInitRDName(FLAGS_initrd)
      .SetKernelArgs(cmdline.str())
      .SetIVShMemSocketPath(FLAGS_qemusocket)
      .SetIVShMemVectorCount(memory_layout.GetRegions().size())
      .SetSystemPartitionPath(system_partition->GetName())
      .SetCachePartitionPath(cache_partition->GetName())
      .SetDataPartitionPath(data_partition->GetName())
      .SetVendorPartitionPath(vendor_partition->GetName())
      .SetMobileBridgeName(FLAGS_mobile_interface)
      .SetEntropySource(entropy_source)
      .SetDisableDACSecurity(FLAGS_disable_dac_security)
      .SetDisableAppArmorSecurity(FLAGS_disable_app_armor_security)
      .SetUUID(FLAGS_uuid)
      .SetWifiBridgeName(FLAGS_wifi_interface);
  if(AdbUsbEnabled()) {
    cfg.SetUSBV1SocketName(
        GetDefaultPerInstancePath(cfg.GetInstanceName() + "-usb"));
  }
  cfg.SetKernelLogSocketName(
      GetDefaultPerInstancePath(cfg.GetInstanceName() + "-kernel-log"));

  std::string xml = cfg.Build();
  if (FLAGS_log_xml) {
    LOG(INFO) << "Using XML:\n" << xml;
  }

  VirtualUSBManager vadb(cfg.GetUSBV1SocketName(), FLAGS_vhci_port,
                         GetPerInstanceDefault("android_usbip"));
  vadb.Start();

  // TODO(b/79170615) These values need to go to the config object/file and the
  // region resizing be done by the ivserver process (or maybe the config
  // library to ensure all processes have the correct value?)
  size_t screen_size =
      memory_layout
          .GetRegionByName(vsoc::layout::screen::ScreenLayout::region_name)
          ->region_size();
  auto actual_width = ((FLAGS_x_res * 4) + 15) & ~15;  // aligned to 16
  screen_size += FLAGS_num_screen_buffers *
                 (actual_width * FLAGS_y_res + 16 /* padding */);
  screen_size += (FLAGS_num_screen_buffers - 1) * 4096; /* Guard pages */
  memory_layout.ResizeRegion(vsoc::layout::screen::ScreenLayout::region_name,
                             screen_size);
  // TODO(b/79170615) Resize gralloc region too.

  IVServerManager ivshmem;
  ivshmem.Start();
  KernelLogMonitor kmon(cfg.GetKernelLogSocketName(),
                        GetDefaultPerInstancePath("kernel.log"),
                        FLAGS_deprecated_boot_completed);
  kmon.Start();

  sleep(1);

  // Initialize the regions that require it before the VM starts.
  PreLaunchInitializers::Initialize();

  std::string launch_command = FLAGS_launch_command;
  auto pos = launch_command.find(VIRSH_OPTIONS_PLACEHOLDER);
  if (pos != std::string::npos) {
    launch_command.replace(
        pos, sizeof(VIRSH_OPTIONS_PLACEHOLDER) - 1, GetVirshOptions());
  }

  FILE* launch = popen(launch_command.c_str(), "w");
  if (!launch) {
    LOG(FATAL) << "Unable to execute " << launch_command;
  }
  int rval = fputs(xml.c_str(), launch);
  if (rval == EOF) {
    LOG(FATAL) << "Launch command exited while accepting XML";
  }
  int exit_code = pclose(launch);
  if (exit_code) {
    LOG(FATAL) << "Launch command exited with status " << exit_code;
  }

  LaunchSocketForwardProxyIfEnabled();
  LaunchVNCServerIfEnabled();
  LaunchWifiRelayIfEnabled();

  pause();
}
