/*
 * Copyright (C) 2007 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 "minadbd_services.h"

#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <thread>
#include <unordered_set>

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

#include "adb.h"
#include "adb_unique_fd.h"
#include "adb_utils.h"
#include "fdevent.h"
#include "fuse_adb_provider.h"
#include "fuse_sideload.h"
#include "minadbd_types.h"
#include "services.h"
#include "sysdeps.h"

static int minadbd_socket = -1;
static bool rescue_mode = false;
static std::string sideload_mount_point = FUSE_SIDELOAD_HOST_MOUNTPOINT;

void SetMinadbdSocketFd(int socket_fd) {
  minadbd_socket = socket_fd;
}

void SetMinadbdRescueMode(bool rescue) {
  rescue_mode = rescue;
}

void SetSideloadMountPoint(const std::string& path) {
  sideload_mount_point = path;
}

static bool WriteCommandToFd(MinadbdCommands cmd, int fd) {
  char message[kMinadbdMessageSize];
  memcpy(message, kMinadbdCommandPrefix, strlen(kMinadbdStatusPrefix));
  android::base::put_unaligned(message + strlen(kMinadbdStatusPrefix), cmd);

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

// Blocks and reads the command status from |fd|. Returns false if the received message has a
// format error.
static bool WaitForCommandStatus(int fd, MinadbdCommandStatus* status) {
  char buffer[kMinadbdMessageSize];
  if (!android::base::ReadFully(fd, buffer, kMinadbdMessageSize)) {
    PLOG(ERROR) << "Failed to response status from socket";
    exit(kMinadbdSocketIOError);
  }

  std::string message(buffer, buffer + kMinadbdMessageSize);
  if (!android::base::StartsWith(message, kMinadbdStatusPrefix)) {
    LOG(ERROR) << "Failed to parse status in " << message;
    return false;
  }

  *status = android::base::get_unaligned<MinadbdCommandStatus>(
      message.substr(strlen(kMinadbdStatusPrefix)).c_str());
  return true;
}

static MinadbdErrorCode RunAdbFuseSideload(int sfd, const std::string& args,
                                           MinadbdCommandStatus* status) {
  auto pieces = android::base::Split(args, ":");
  int64_t file_size;
  int block_size;
  if (pieces.size() != 2 || !android::base::ParseInt(pieces[0], &file_size) || file_size <= 0 ||
      !android::base::ParseInt(pieces[1], &block_size) || block_size <= 0) {
    LOG(ERROR) << "bad sideload-host arguments: " << args;
    return kMinadbdPackageSizeError;
  }

  LOG(INFO) << "sideload-host file size " << file_size << ", block size " << block_size;

  if (!WriteCommandToFd(MinadbdCommands::kInstall, minadbd_socket)) {
    return kMinadbdSocketIOError;
  }

  auto adb_data_reader = std::make_unique<FuseAdbDataProvider>(sfd, file_size, block_size);
  if (int result = run_fuse_sideload(std::move(adb_data_reader), sideload_mount_point.c_str());
      result != 0) {
    LOG(ERROR) << "Failed to start fuse";
    return kMinadbdFuseStartError;
  }

  if (!WaitForCommandStatus(minadbd_socket, status)) {
    return kMinadbdMessageFormatError;
  }

  // Signal host-side adb to stop. For sideload mode, we always send kSideloadServiceExitSuccess
  // (i.e. "DONEDONE") regardless of the install result. For rescue mode, we send failure message on
  // install error.
  if (!rescue_mode || *status == MinadbdCommandStatus::kSuccess) {
    if (!android::base::WriteFully(sfd, kSideloadServiceExitSuccess,
                                   strlen(kSideloadServiceExitSuccess))) {
      return kMinadbdHostSocketIOError;
    }
  } else {
    if (!android::base::WriteFully(sfd, kSideloadServiceExitFailure,
                                   strlen(kSideloadServiceExitFailure))) {
      return kMinadbdHostSocketIOError;
    }
  }

  return kMinadbdSuccess;
}

// Sideload service always exits after serving an install command.
static void SideloadHostService(unique_fd sfd, const std::string& args) {
  MinadbdCommandStatus status;
  exit(RunAdbFuseSideload(sfd.get(), args, &status));
}

// Rescue service waits for the next command after an install command.
static void RescueInstallHostService(unique_fd sfd, const std::string& args) {
  MinadbdCommandStatus status;
  if (auto result = RunAdbFuseSideload(sfd.get(), args, &status); result != kMinadbdSuccess) {
    exit(result);
  }
}

static void RescueGetpropHostService(unique_fd sfd, const std::string& prop) {
  static const std::unordered_set<std::string> kGetpropAllowedProps = {
    "ro.build.fingerprint",
    "ro.build.date.utc",
  };
  auto allowed = kGetpropAllowedProps.find(prop) != kGetpropAllowedProps.end();
  if (!allowed) {
    return;
  }

  auto result = android::base::GetProperty(prop, "");
  if (result.empty()) {
    return;
  }
  if (!android::base::WriteFully(sfd, result.data(), result.size())) {
    exit(kMinadbdHostSocketIOError);
  }
}

unique_fd daemon_service_to_fd(std::string_view name, atransport* /* transport */) {
  if (rescue_mode) {
    if (ConsumePrefix(&name, "rescue-install:")) {
      // rescue-install:<file-size>:<block-size>
      std::string args(name);
      return create_service_thread(
          "rescue-install", std::bind(RescueInstallHostService, std::placeholders::_1, args));
    } else if (ConsumePrefix(&name, "rescue-getprop:")) {
      // rescue-getprop:<prop>
      std::string args(name);
      return create_service_thread(
          "rescue-getprop", std::bind(RescueGetpropHostService, std::placeholders::_1, args));
    }
    return unique_fd{};
  }

  if (name.starts_with("sideload:")) {
    // This exit status causes recovery to print a special error message saying to use a newer adb
    // (that supports sideload-host).
    exit(kMinadbdAdbVersionError);
  } else if (ConsumePrefix(&name, "sideload-host:")) {
    // sideload-host:<file-size>:<block-size>
    std::string args(name);
    return create_service_thread("sideload-host",
                                 std::bind(SideloadHostService, std::placeholders::_1, args));
  }
  return unique_fd{};
}
