// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/ui/scenic/lib/allocation/allocator.h"

#include <lib/async/cpp/wait.h>
#include <lib/async/default.h>
#include <lib/fit/function.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/trace/event.h>

#include <memory>

#include "src/lib/fsl/handles/object_info.h"
#include "src/ui/scenic/lib/allocation/buffer_collection_importer.h"

using allocation::BufferCollectionUsage;
using fuchsia::ui::composition::RegisterBufferCollectionError;
using fuchsia::ui::composition::RegisterBufferCollectionUsages;

namespace allocation {

namespace {

RegisterBufferCollectionUsages UsageToUsages(
    fuchsia::ui::composition::RegisterBufferCollectionUsage usage) {
  switch (usage) {
    case fuchsia::ui::composition::RegisterBufferCollectionUsage::DEFAULT:
      return fuchsia::ui::composition::RegisterBufferCollectionUsages::DEFAULT;
    case fuchsia::ui::composition::RegisterBufferCollectionUsage::SCREENSHOT:
      return fuchsia::ui::composition::RegisterBufferCollectionUsages::SCREENSHOT;
  }
}

bool BufferCollectionTokenIsValid(
    fuchsia::sysmem::AllocatorSyncPtr& sysmem_allocator,
    const fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken>& token) {
  bool is_known = false;
  const auto status = sysmem_allocator->ValidateBufferCollectionToken(
      fsl::GetRelatedKoid(token.channel().get()), &is_known);
  return status == ZX_OK && is_known;
}

// Creates a vector of |num_tokens| duplicates of BufferCollectionTokenSyncPtr.
// Returns an empty vector if creation failed.
std::vector<fuchsia::sysmem::BufferCollectionTokenSyncPtr> CreateVectorOfTokens(
    fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken> token, const size_t num_tokens) {
  FX_DCHECK(num_tokens > 0);
  std::vector<fuchsia::sysmem::BufferCollectionTokenSyncPtr> tokens;
  tokens.emplace_back(token.BindSync());

  std::vector<fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken>> dup_tokens;
  if (tokens.front()->DuplicateSync(std::vector<zx_rights_t>(num_tokens - 1, ZX_RIGHT_SAME_RIGHTS),
                                    &dup_tokens) == ZX_OK) {
    for (auto& token : dup_tokens) {
      tokens.emplace_back(token.BindSync());
    }
  } else {
    tokens.clear();
  }

  return tokens;
}

struct ParsedArgs {
  zx_koid_t koid;
  RegisterBufferCollectionUsages buffer_collection_usages;
  fuchsia::ui::composition::BufferCollectionExportToken export_token;
  fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken> buffer_collection_token;
};

// Parses the FIDL struct, validating the arguments. Logs an error and returns std::nullopt on
// failure.
std::optional<ParsedArgs> ParseArgs(fuchsia::ui::composition::RegisterBufferCollectionArgs args) {
  // It's okay if there's no specified RegisterBufferCollectionUsage. In that case, assume it is
  // DEFAULT.
  if (!args.has_buffer_collection_token() || !args.has_export_token()) {
    FX_LOGS(ERROR) << "RegisterBufferCollection called with missing arguments";
    return std::nullopt;
  }

  if (!args.buffer_collection_token().is_valid()) {
    FX_LOGS(ERROR) << "RegisterBufferCollection called with invalid buffer collection token";
    return std::nullopt;
  }

  if (!args.export_token().value.is_valid()) {
    FX_LOGS(ERROR) << "RegisterBufferCollection called with invalid export token";
    return std::nullopt;
  }

  // Check if there is a valid peer.
  if (fsl::GetRelatedKoid(args.export_token().value.get()) == ZX_KOID_INVALID) {
    FX_LOGS(ERROR) << "RegisterBufferCollection called with no valid import tokens";
    return std::nullopt;
  }

  if (args.has_usages() && args.usages().has_unknown_bits()) {
    FX_LOGS(ERROR) << "Arguments contain unknown BufferCollectionUsage type";
    return std::nullopt;
  }

  // Grab object koid to be used as unique_id.
  const GlobalBufferCollectionId koid = fsl::GetKoid(args.export_token().value.get());
  FX_DCHECK(koid != ZX_KOID_INVALID);

  // If no usages are set we default to DEFAULT. Otherwise the newer "usages" value takes precedence
  // over the deprecated "usage" variant.
  RegisterBufferCollectionUsages buffer_collection_usages = RegisterBufferCollectionUsages::DEFAULT;
  if (args.has_usages()) {
    buffer_collection_usages = args.usages();
  } else if (args.has_usage()) {
    buffer_collection_usages = UsageToUsages(args.usage());
  }

  return ParsedArgs{
      .koid = koid,
      .buffer_collection_usages = buffer_collection_usages,
      .export_token = std::move(*args.mutable_export_token()),
      .buffer_collection_token = std::move(*args.mutable_buffer_collection_token()),
  };
}

}  // namespace

Allocator::Allocator(sys::ComponentContext* app_context,
                     const std::vector<std::shared_ptr<BufferCollectionImporter>>&
                         default_buffer_collection_importers,
                     const std::vector<std::shared_ptr<BufferCollectionImporter>>&
                         screenshot_buffer_collection_importers,
                     fuchsia::sysmem::AllocatorSyncPtr sysmem_allocator)
    : dispatcher_(async_get_default_dispatcher()),
      default_buffer_collection_importers_(default_buffer_collection_importers),
      screenshot_buffer_collection_importers_(screenshot_buffer_collection_importers),
      sysmem_allocator_(std::move(sysmem_allocator)),
      weak_factory_(this) {
  FX_DCHECK(app_context);
  app_context->outgoing()->AddPublicService(bindings_.GetHandler(this));
}

Allocator::~Allocator() {
  FX_DCHECK(dispatcher_ == async_get_default_dispatcher());

  // Allocator outlives |*_buffer_collection_importers_| instances, because we hold shared_ptrs. It
  // is safe to release all remaining buffer collections because there should be no more usage.
  while (!buffer_collections_.empty()) {
    ReleaseBufferCollection(buffer_collections_.begin()->first);
  }
}

void Allocator::RegisterBufferCollection(
    fuchsia::ui::composition::RegisterBufferCollectionArgs args,
    RegisterBufferCollectionCallback callback) {
  TRACE_DURATION("gfx", "allocation::Allocator::RegisterBufferCollection");
  FX_DCHECK(dispatcher_ == async_get_default_dispatcher());

  auto parsed_args = ParseArgs(std::move(args));
  if (!parsed_args) {
    callback(fpromise::error(RegisterBufferCollectionError::BAD_OPERATION));
    return;
  }

  auto& [koid, buffer_collection_usages, export_token, buffer_collection_token] =
      parsed_args.value();

  // Check if this export token has already been used.
  if (buffer_collections_.find(koid) != buffer_collections_.end()) {
    FX_LOGS(ERROR) << "RegisterBufferCollection called with pre-registered export token";
    callback(fpromise::error(RegisterBufferCollectionError::BAD_OPERATION));
    return;
  }

  if (!BufferCollectionTokenIsValid(sysmem_allocator_, buffer_collection_token)) {
    FX_LOGS(ERROR) << "RegisterBufferCollection called with a buffer collection token where "
                      "ValidateBufferCollectionToken() failed";
    callback(fpromise::error(RegisterBufferCollectionError::BAD_OPERATION));
    return;
  }

  const auto importers = GetImporters(buffer_collection_usages);
  // Create a token for each of the buffer collection importers.
  auto tokens = CreateVectorOfTokens(std::move(buffer_collection_token), importers.size());

  if (tokens.empty()) {
    FX_LOGS(ERROR) << "RegisterBufferCollection called with a buffer collection token where "
                      "Duplicate() failed";
    callback(fpromise::error(RegisterBufferCollectionError::BAD_OPERATION));
    return;
  }

  // Loop over each of the importers and provide each of them with a token from the vector we
  // created above.
  for (uint32_t i = 0; i < importers.size(); i++) {
    bool import_successful = false;
    {
      auto& [importer, usage] = importers.at(i);
      import_successful = importer.ImportBufferCollection(
          koid, sysmem_allocator_.get(), std::move(tokens[i]), usage, std::nullopt);
    }

    if (!import_successful) {
      // If any importers failed then clean up the ones that didn't before returning.
      for (uint32_t j = 0; j < i; j++) {
        auto& [importer, usage] = importers.at(j);
        importer.ReleaseBufferCollection(koid, usage);
      }
      FX_LOGS(ERROR) << "Failed to import the buffer collection to the BufferCollectionimporter.";
      callback(fpromise::error(RegisterBufferCollectionError::BAD_OPERATION));
      return;
    }
  }

  buffer_collections_[koid] = buffer_collection_usages;

  // Use a self-referencing async::WaitOnce to deregister buffer collections when all
  // BufferCollectionImportTokens are used, i.e. peers of eventpair are closed. Note that the
  // ownership of |export_token| is also passed, so that GetRelatedKoid() calls return valid koid.
  auto wait = std::make_shared<async::WaitOnce>(export_token.value.get(), ZX_EVENTPAIR_PEER_CLOSED);
  const zx_status_t status =
      wait->Begin(async_get_default_dispatcher(),
                  [keepalive_wait = wait, keepalive_export_token = std::move(export_token.value),
                   weak_ptr = weak_factory_.GetWeakPtr(),
                   koid = koid](async_dispatcher_t*, async::WaitOnce*, zx_status_t status,
                                const zx_packet_signal_t* /*signal*/) mutable {
                    FX_DCHECK(status == ZX_OK || status == ZX_ERR_CANCELED);
                    if (!weak_ptr)
                      return;
                    // Because Flatland::CreateImage() holds an import token, this
                    // is guaranteed to be called after all images are created, so
                    // it is safe to release buffer collection.
                    weak_ptr->ReleaseBufferCollection(koid);
                  });
  FX_DCHECK(status == ZX_OK);

  callback(fpromise::ok());
}

std::vector<std::pair<BufferCollectionImporter&, BufferCollectionUsage>> Allocator::GetImporters(
    const RegisterBufferCollectionUsages usages) const {
  std::vector<std::pair<BufferCollectionImporter&, BufferCollectionUsage>> importers;
  if (usages & RegisterBufferCollectionUsages::DEFAULT) {
    for (const auto& importer : default_buffer_collection_importers_) {
      importers.emplace_back(*importer, BufferCollectionUsage::kClientImage);
    }
  }
  if (usages & RegisterBufferCollectionUsages::SCREENSHOT) {
    for (const auto& importer : screenshot_buffer_collection_importers_) {
      importers.emplace_back(*importer, BufferCollectionUsage::kRenderTarget);
    }
  }

  return importers;
}

void Allocator::ReleaseBufferCollection(GlobalBufferCollectionId collection_id) {
  TRACE_DURATION("gfx", "allocation::Allocator::ReleaseBufferCollection");
  FX_DCHECK(dispatcher_ == async_get_default_dispatcher());

  const auto usages = buffer_collections_.at(collection_id);
  buffer_collections_.erase(collection_id);

  for (auto& [importer, usage] : GetImporters(usages)) {
    importer.ReleaseBufferCollection(collection_id, usage);
  }
}

}  // namespace allocation
