/*
 * Copyright (C) 2012 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 "install/adb_install.h"

#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <atomic>
#include <functional>
#include <map>
#include <utility>
#include <vector>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/memory.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>

#include "fuse_sideload.h"
#include "install/install.h"
#include "install/wipe_data.h"
#include "minadbd/types.h"
#include "otautil/sysutil.h"
#include "recovery_ui/device.h"
#include "recovery_ui/ui.h"

// A CommandFunction returns a pair of (result, should_continue), which indicates the command
// execution result and whether it should proceed to the next iteration. The execution result will
// always be sent to the minadbd side.
using CommandFunction = std::function<std::pair<bool, bool>()>;

static bool SetUsbConfig(const std::string& state) {
  android::base::SetProperty("sys.usb.config", state);
  return android::base::WaitForProperty("sys.usb.state", state);
}

// Parses the minadbd command in |message|; returns MinadbdCommand::kError upon errors.
static MinadbdCommand ParseMinadbdCommand(const std::string& message) {
  if (!android::base::StartsWith(message, kMinadbdCommandPrefix)) {
    LOG(ERROR) << "Failed to parse command in message " << message;
    return MinadbdCommand::kError;
  }

  auto cmd_code_string = message.substr(strlen(kMinadbdCommandPrefix));
  auto cmd_code = android::base::get_unaligned<uint32_t>(cmd_code_string.c_str());
  if (cmd_code >= static_cast<uint32_t>(MinadbdCommand::kError)) {
    LOG(ERROR) << "Unsupported command code: " << cmd_code;
    return MinadbdCommand::kError;
  }

  return static_cast<MinadbdCommand>(cmd_code);
}

static bool WriteStatusToFd(MinadbdCommandStatus status, int fd) {
  char message[kMinadbdMessageSize];
  memcpy(message, kMinadbdStatusPrefix, strlen(kMinadbdStatusPrefix));
  android::base::put_unaligned(message + strlen(kMinadbdStatusPrefix), status);

  if (!android::base::WriteFully(fd, message, kMinadbdMessageSize)) {
    PLOG(ERROR) << "Failed to write message " << message;
    return false;
  }
  return true;
}

// Installs the package from FUSE. Returns the installation result and whether it should continue
// waiting for new commands.
static auto AdbInstallPackageHandler(Device* device, InstallResult* result) {
  // How long (in seconds) we wait for the package path to be ready. It doesn't need to be too long
  // because the minadbd service has already issued an install command. FUSE_SIDELOAD_HOST_PATHNAME
  // will start to exist once the host connects and starts serving a package. Poll for its
  // appearance. (Note that inotify doesn't work with FUSE.)
  auto ui = device->GetUI();
  constexpr int ADB_INSTALL_TIMEOUT = 15;
  bool should_continue = true;
  *result = INSTALL_ERROR;
  for (int i = 0; i < ADB_INSTALL_TIMEOUT; ++i) {
    struct stat st;
    if (stat(FUSE_SIDELOAD_HOST_PATHNAME, &st) != 0) {
      if (errno == ENOENT && i < ADB_INSTALL_TIMEOUT - 1) {
        sleep(1);
        continue;
      } else {
        should_continue = false;
        ui->Print("\nTimed out waiting for fuse to be ready.\n\n");
        break;
      }
    }
    ui->CancelWaitKey();

    auto package =
        Package::CreateFilePackage(FUSE_SIDELOAD_HOST_PATHNAME,
                                   std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1));
    *result = InstallPackage(package.get(), FUSE_SIDELOAD_HOST_PATHNAME, false, 0, device);
    break;
  }

  // Calling stat() on this magic filename signals the FUSE to exit.
  struct stat st;
  stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st);
  return std::make_pair(*result == INSTALL_SUCCESS, should_continue);
}

static auto AdbRebootHandler(MinadbdCommand command, InstallResult* result,
                             Device::BuiltinAction* reboot_action) {
  // Use Device::REBOOT_{FASTBOOT,RECOVERY,RESCUE}, instead of the ones with ENTER_. This allows
  // rebooting back into fastboot/recovery/rescue mode through bootloader, which may use a newly
  // installed bootloader/recovery image.
  switch (command) {
    case MinadbdCommand::kRebootBootloader:
      *reboot_action = Device::REBOOT_BOOTLOADER;
      break;
    case MinadbdCommand::kRebootFastboot:
      *reboot_action = Device::REBOOT_FASTBOOT;
      break;
    case MinadbdCommand::kRebootRecovery:
      *reboot_action = Device::REBOOT_RECOVERY;
      break;
    case MinadbdCommand::kRebootRescue:
      *reboot_action = Device::REBOOT_RESCUE;
      break;
    case MinadbdCommand::kRebootAndroid:
    default:
      *reboot_action = Device::REBOOT;
      break;
  }
  *result = INSTALL_REBOOT;
  return std::make_pair(true, false);
}

// Parses and executes the command from minadbd. Returns whether the caller should keep waiting for
// next command.
static bool HandleMessageFromMinadbd(int socket_fd,
                                     const std::map<MinadbdCommand, CommandFunction>& command_map) {
  char buffer[kMinadbdMessageSize];
  if (!android::base::ReadFully(socket_fd, buffer, kMinadbdMessageSize)) {
    PLOG(ERROR) << "Failed to read message from minadbd";
    return false;
  }

  std::string message(buffer, buffer + kMinadbdMessageSize);
  auto command_type = ParseMinadbdCommand(message);
  if (command_type == MinadbdCommand::kError) {
    return false;
  }
  if (command_map.find(command_type) == command_map.end()) {
    LOG(ERROR) << "Unsupported command: "
               << android::base::get_unaligned<unsigned int>(
                      message.substr(strlen(kMinadbdCommandPrefix)).c_str());
    return false;
  }

  // We have received a valid command, execute the corresponding function.
  const auto& command_func = command_map.at(command_type);
  const auto [result, should_continue] = command_func();
  LOG(INFO) << "Command " << static_cast<uint32_t>(command_type) << " finished with " << result;
  if (!WriteStatusToFd(result ? MinadbdCommandStatus::kSuccess : MinadbdCommandStatus::kFailure,
                       socket_fd)) {
    return false;
  }
  return should_continue;
}

// TODO(xunchang) add a wrapper function and kill the minadbd service there.
static void ListenAndExecuteMinadbdCommands(
    RecoveryUI* ui, pid_t minadbd_pid, android::base::unique_fd&& socket_fd,
    const std::map<MinadbdCommand, CommandFunction>& command_map) {
  android::base::unique_fd epoll_fd(epoll_create1(O_CLOEXEC));
  if (epoll_fd == -1) {
    PLOG(ERROR) << "Failed to create epoll";
    kill(minadbd_pid, SIGKILL);
    return;
  }

  constexpr int EPOLL_MAX_EVENTS = 10;
  struct epoll_event ev = {};
  ev.events = EPOLLIN | EPOLLHUP;
  ev.data.fd = socket_fd.get();
  struct epoll_event events[EPOLL_MAX_EVENTS];
  if (epoll_ctl(epoll_fd.get(), EPOLL_CTL_ADD, socket_fd.get(), &ev) == -1) {
    PLOG(ERROR) << "Failed to add socket fd to epoll";
    kill(minadbd_pid, SIGKILL);
    return;
  }

  // Set the timeout to be 300s when waiting for minadbd commands.
  constexpr int TIMEOUT_MILLIS = 300 * 1000;
  while (true) {
    // Reset the progress bar and the background image before each command.
    ui->SetProgressType(RecoveryUI::EMPTY);
    ui->SetBackground(RecoveryUI::NO_COMMAND);

    // Poll for the status change of the socket_fd, and handle the message if the fd is ready to
    // read.
    int event_count =
        TEMP_FAILURE_RETRY(epoll_wait(epoll_fd.get(), events, EPOLL_MAX_EVENTS, TIMEOUT_MILLIS));
    if (event_count == -1) {
      PLOG(ERROR) << "Failed to wait for epoll events";
      kill(minadbd_pid, SIGKILL);
      return;
    }
    if (event_count == 0) {
      LOG(ERROR) << "Timeout waiting for messages from minadbd";
      kill(minadbd_pid, SIGKILL);
      return;
    }

    for (int n = 0; n < event_count; n++) {
      if (events[n].events & EPOLLHUP) {
        LOG(INFO) << "Socket has been closed";
        kill(minadbd_pid, SIGKILL);
        return;
      }
      if (!HandleMessageFromMinadbd(socket_fd.get(), command_map)) {
        kill(minadbd_pid, SIGKILL);
        return;
      }
    }
  }
}

// Recovery starts minadbd service as a child process, and spawns another thread to listen for the
// message from minadbd through a socket pair. Here is an example to execute one command from adb
// host.
//  a. recovery                    b. listener thread               c. minadbd service
//
//  a1. create socket pair
//  a2. fork minadbd service
//                                                                c3. wait for the adb commands
//                                                                    from host
//                                                                c4. after receiving host commands:
//                                                                  1) set up pre-condition (i.e.
//                                                                     start fuse for adb sideload)
//                                                                  2) issue command through
//                                                                     socket.
//                                                                  3) wait for result
//  a5. start listener thread
//                               b6. listen for message from
//                                   minadbd in a loop.
//                               b7. After receiving a minadbd
//                                   command from socket
//                                 1) execute the command function
//                                 2) send the result back to
//                                    minadbd
//  ......
//                                                                 c8. exit upon receiving the
//                                                                     result
// a9.  wait for listener thread
//      to exit.
//
// a10. wait for minadbd to
//      exit
//                               b11. exit the listening loop
//
static void CreateMinadbdServiceAndExecuteCommands(
    Device* device, const std::map<MinadbdCommand, CommandFunction>& command_map,
    bool rescue_mode) {
  signal(SIGPIPE, SIG_IGN);

  android::base::unique_fd recovery_socket;
  android::base::unique_fd minadbd_socket;
  if (!android::base::Socketpair(AF_UNIX, SOCK_STREAM, 0, &recovery_socket, &minadbd_socket)) {
    PLOG(ERROR) << "Failed to create socket";
    return;
  }

  pid_t child = fork();
  if (child == -1) {
    PLOG(ERROR) << "Failed to fork child process";
    return;
  }
  if (child == 0) {
    recovery_socket.reset();
    std::vector<std::string> minadbd_commands = {
      "/system/bin/minadbd",
      "--socket_fd",
      std::to_string(minadbd_socket.release()),
    };
    if (rescue_mode) {
      minadbd_commands.push_back("--rescue");
    }
    auto exec_args = StringVectorToNullTerminatedArray(minadbd_commands);
    execv(exec_args[0], exec_args.data());
    _exit(EXIT_FAILURE);
  }

  minadbd_socket.reset();

  // We need to call SetUsbConfig() after forking minadbd service. Because the function waits for
  // the usb state to be updated, which depends on sys.usb.ffs.ready=1 set in the adb daemon.
  if (!SetUsbConfig("sideload")) {
    LOG(ERROR) << "Failed to set usb config to sideload";
    return;
  }

  RecoveryUI* ui = device->GetUI();
  std::thread listener_thread(ListenAndExecuteMinadbdCommands, ui, child,
                              std::move(recovery_socket), std::ref(command_map));

  if (ui->IsTextVisible()) {
    std::vector<std::string> headers{ rescue_mode ? "Rescue mode" : "ADB Sideload" };
    std::vector<std::string> entries{ "Cancel" };
    size_t chosen_item = ui->ShowMenu(
        headers, entries, 0, true,
        std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));

    if (chosen_item != Device::kDoSideload) {
      // Kill minadbd if 'cancel' was selected, to abort sideload.
      kill(child, SIGKILL);
    }
  }

  if (listener_thread.joinable()) {
    listener_thread.join();
  }

  int status;
  waitpid(child, &status, 0);
  if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
    if (WEXITSTATUS(status) == MinadbdErrorCode::kMinadbdAdbVersionError) {
      LOG(ERROR) << "\nYou need adb 1.0.32 or newer to sideload\nto this device.\n";
    } else if (!WIFSIGNALED(status)) {
      LOG(ERROR) << "\n(adbd status " << WEXITSTATUS(status) << ")";
    }
  }

  signal(SIGPIPE, SIG_DFL);
}

InstallResult ApplyFromAdb(Device* device, bool rescue_mode, Device::BuiltinAction* reboot_action) {
  // Save the usb state to restore after the sideload operation.
  std::string usb_state = android::base::GetProperty("sys.usb.state", "none");
  // Clean up state and stop adbd.
  if (usb_state != "none" && !SetUsbConfig("none")) {
    LOG(ERROR) << "Failed to clear USB config";
    return INSTALL_ERROR;
  }

  RecoveryUI* ui = device->GetUI();

  InstallResult install_result = INSTALL_NONE;
  std::map<MinadbdCommand, CommandFunction> command_map{
    { MinadbdCommand::kInstall, std::bind(&AdbInstallPackageHandler, device, &install_result) },
    { MinadbdCommand::kRebootAndroid, std::bind(&AdbRebootHandler, MinadbdCommand::kRebootAndroid,
                                                &install_result, reboot_action) },
    { MinadbdCommand::kRebootBootloader,
      std::bind(&AdbRebootHandler, MinadbdCommand::kRebootBootloader, &install_result,
                reboot_action) },
    { MinadbdCommand::kRebootFastboot, std::bind(&AdbRebootHandler, MinadbdCommand::kRebootFastboot,
                                                 &install_result, reboot_action) },
    { MinadbdCommand::kRebootRecovery, std::bind(&AdbRebootHandler, MinadbdCommand::kRebootRecovery,
                                                 &install_result, reboot_action) },
    { MinadbdCommand::kRebootRescue,
      std::bind(&AdbRebootHandler, MinadbdCommand::kRebootRescue, &install_result, reboot_action) },
  };

  if (!rescue_mode) {
    ui->Print(
        "\n\nNow send the package you want to apply\n"
        "to the device with \"adb sideload <filename>\"...\n");
  } else {
    command_map.emplace(MinadbdCommand::kWipeData, [&device]() {
      bool result = WipeData(device);
      return std::make_pair(result, true);
    });
    command_map.emplace(MinadbdCommand::kNoOp, []() { return std::make_pair(true, true); });

    ui->Print("\n\nWaiting for rescue commands...\n");
  }

  CreateMinadbdServiceAndExecuteCommands(device, command_map, rescue_mode);

  // Clean up before switching to the older state, for example setting the state
  // to none sets sys/class/android_usb/android0/enable to 0.
  if (!SetUsbConfig("none")) {
    LOG(ERROR) << "Failed to clear USB config";
  }

  if (usb_state != "none") {
    if (!SetUsbConfig(usb_state)) {
      LOG(ERROR) << "Failed to set USB config to " << usb_state;
    }
  }

  return install_result;
}
