// Copyright 2019 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 "buffer_collection.h"

#include <fidl/fuchsia.sysmem/cpp/fidl.h>
#include <fidl/fuchsia.sysmem2/cpp/common_types.h>
#include <fidl/fuchsia.sysmem2/cpp/fidl.h>
#include <fidl/fuchsia.sysmem2/cpp/wire_types.h>
#include <lib/fidl/cpp/wire/vector_view.h>
#include <lib/fidl/cpp/wire_natural_conversions.h>
#include <lib/sysmem-version/sysmem-version.h>
#include <lib/trace/event.h>
#include <lib/zx/channel.h>
#include <lib/zx/object.h>
#include <zircon/compiler.h>
#include <zircon/errors.h>

#include <atomic>

#include <fbl/ref_ptr.h>

#include "buffer_collection_token.h"
#include "logical_buffer_collection.h"
#include "node_properties.h"
#include "utils.h"

namespace sysmem_service {

namespace {

using Error = fuchsia_sysmem2::Error;

// For max client vmo rights, we specify the RIGHT bits individually to avoid
// picking up any newly-added rights unintentionally.  This is based on
// ZX_DEFAULT_VMO_RIGHTS, but with a few rights removed.
const uint32_t kMaxClientVmoRights =
    // ZX_RIGHTS_BASIC includes ZX_RIGHT_INSPECT which is currently required by
    // at least starnix when mapping a VMO into a starnix-backed process.
    ZX_RIGHTS_BASIC |
    // ZX_RIGHTS_IO:
    ZX_RIGHT_READ | ZX_RIGHT_WRITE |
    // ZX_RIGHTS_PROPERTY allows a participant to set ZX_PROP_NAME for easier
    // memory metrics.  Nothing prevents participants from figting over the
    // name, though the kernel should make each set/get atomic with respect to
    // other set/get.  This relies on ZX_RIGHTS_PROPERTY not implying anything
    // that could be used as an attack vector between processes sharing a VMO.
    ZX_RIGHTS_PROPERTY |
    // We intentionally omit ZX_RIGHT_EXECUTE (indefinitely) and ZX_RIGHT_SIGNAL
    // (at least for now).
    //
    // Remaining bits of ZX_DEFAULT_VMO_RIGHTS (as of this writing):
    ZX_RIGHT_MAP;

}  // namespace

// static
BufferCollection& BufferCollection::EmplaceInTree(
    fbl::RefPtr<LogicalBufferCollection> logical_buffer_collection, BufferCollectionToken* token,
    const CollectionServerEnd& server_end) {
  // The token is passed in as a pointer because this method deletes token, but the caller must
  // provide non-nullptr token.
  ZX_DEBUG_ASSERT(token);
  // This conversion from unique_ptr<> to RefPtr<> will go away once we move BufferCollection to
  // LLCPP FIDL server binding.
  fbl::RefPtr<Node> node(
      fbl::AdoptRef(new BufferCollection(logical_buffer_collection, *token, server_end)));
  BufferCollection* buffer_collection_ptr = static_down_cast<BufferCollection*>(node.get());

  // Now that token has processed the rest of it's incoming messages and we're about to replace the
  // BufferCollectionToken with BufferCollection, we apply the allocator's ClientDebugInfo. This
  // queued/delayed apply is how we ensure that the allocator's ClientDebugInfo deterministically
  // takes priority over the token's ClientDebugInfo. This is desirable so that we see the
  // ClientDebugInfo set by the client that did the BindSharedCollection, which is typically the
  // current owner of the BufferCollection, and the client that will be sending SetConstraints.
  //
  // If no ClientDebugInfo is set on the allocator, the BufferCollection will inherit any
  // ClientDebugInfo that was previously set on the token.
  std::optional<ClientDebugInfo> allocator_client_debug_info =
      token->take_queued_allocator_client_debug_info();
  if (allocator_client_debug_info.has_value()) {
    token->node_properties().client_debug_info() = std::move(*allocator_client_debug_info);
    allocator_client_debug_info.reset();
  }

  // This also deletes token.
  token->node_properties().SetNode(std::move(node));
  return *buffer_collection_ptr;
}

BufferCollection::~BufferCollection() {
  TRACE_DURATION("gfx", "BufferCollection::~BufferCollection", "this", this,
                 "logical_buffer_collection", &logical_buffer_collection());
}

void BufferCollection::CloseServerBinding(zx_status_t epitaph) {
  if (server_binding_v1_.has_value()) {
    server_binding_v1_->Close(epitaph);
  }
  if (server_binding_v2_.has_value()) {
    server_binding_v2_->Close(ZX_ERR_INTERNAL);
  }
  server_binding_v1_ = {};
  server_binding_v2_ = {};
}

void BufferCollection::Bind(CollectionServerEnd collection_server_end) {
  Node::Bind(TakeNodeServerEnd(std::move(collection_server_end)));
}

void BufferCollection::BindInternalV1(zx::channel collection_request,
                                      ErrorHandlerWrapper error_handler_wrapper) {
  v1_server_.emplace(*this);
  server_binding_v1_ = fidl::BindServer(
      parent_sysmem()->loop_dispatcher(),
      fidl::ServerEnd<fuchsia_sysmem::BufferCollection>(std::move(collection_request)),
      &v1_server_.value(),
      [error_handler_wrapper = std::move(error_handler_wrapper)](
          BufferCollection::V1* collection, fidl::UnbindInfo info, CollectionServerEndV1 channel) {
        error_handler_wrapper(info);
      });
}

void BufferCollection::BindInternalV2(zx::channel collection_request,
                                      ErrorHandlerWrapper error_handler_wrapper) {
  v2_server_.emplace(*this);
  server_binding_v2_ = fidl::BindServer(
      parent_sysmem()->loop_dispatcher(),
      fidl::ServerEnd<fuchsia_sysmem2::BufferCollection>(std::move(collection_request)),
      &v2_server_.value(),
      [error_handler_wrapper = std::move(error_handler_wrapper)](
          BufferCollection::V2* collection, fidl::UnbindInfo info, CollectionServerEndV2 channel) {
        error_handler_wrapper(info);
      });
}

void BufferCollection::BindInternalCombinedV1AndV2(zx::channel server_end,
                                                   ErrorHandlerWrapper error_handler_wrapper) {
  ZX_PANIC("BufferCollection only serves V1 or V2 separately - never combined V1 and V2");
}

void BufferCollection::V1::Sync(SyncCompleter::Sync& completer) {
  parent_.SyncImpl(ConnectionVersion::kVersion1, completer);
}

void BufferCollection::V2::Sync(SyncCompleter::Sync& completer) {
  parent_.SyncImpl(ConnectionVersion::kVersion2, completer);
}

template <typename Completer>
bool BufferCollection::CommonSetConstraintsStage1(Completer& completer) {
  if (is_set_constraints_seen_) {
    FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
             "2nd SetConstraints() causes failure.");
    return false;
  }
  is_set_constraints_seen_ = true;
  if (is_done_) {
    FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
             "SetConstraints() when already is_done_");
    // We're failing async - no need to try to fail sync.
    return false;
  }
  return true;
}

void BufferCollection::V1::SetConstraints(SetConstraintsRequest& request,
                                          SetConstraintsCompleter::Sync& completer) {
  TRACE_DURATION("gfx", "BufferCollection::V1::SetConstraints", "this", this,
                 "logical_buffer_collection", &parent_.logical_buffer_collection());
  std::optional<fuchsia_sysmem::BufferCollectionConstraints> local_constraints(
      std::move(request.constraints()));

  if (!parent_.CommonSetConstraintsStage1(completer)) {
    return;
  }

  if (!request.has_constraints()) {
    // Not needed.
    local_constraints.reset();
  }

  ZX_DEBUG_ASSERT(!parent_.has_constraints());
  ZX_DEBUG_ASSERT(request.has_constraints() == local_constraints.has_value());

  {  // scope result
    auto result = sysmem::V2CopyFromV1BufferCollectionConstraints(
        local_constraints.has_value() ? &local_constraints.value() : nullptr);
    if (!result.is_ok()) {
      parent_.FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
                       "V2CopyFromV1BufferCollectionConstraints() failed");
      return;
    }
    ZX_DEBUG_ASSERT(!result.value().IsEmpty() || !local_constraints.has_value());
    parent_.node_properties().SetBufferCollectionConstraints(result.take_value());
  }  // ~result

  if (parent_.logical_buffer_collection().is_verbose_logging()) {
    parent_.node_properties().LogInfo(FROM_HERE, "BufferCollection::V1::SetConstraints()");
    parent_.node_properties().LogConstraints(FROM_HERE);
  }

  // LogicalBufferCollection will ask for constraints when it needs them,
  // possibly during this call if this is the last participant to report
  // having initial constraints.
  //
  // The LogicalBufferCollection cares if this BufferCollection view has null
  // constraints, but only later when it asks for the specific constraints.
  parent_.logical_buffer_collection().OnDependencyReady();
  // |this| may be gone at this point, if the allocation failed.  Regardless,
  // SetConstraints() worked, so ZX_OK.
}

void BufferCollection::V2::SetConstraints(SetConstraintsRequest& request,
                                          SetConstraintsCompleter::Sync& completer) {
  TRACE_DURATION("gfx", "BufferCollection::V2::SetConstraints", "this", this,
                 "logical_buffer_collection", &parent_.logical_buffer_collection());

  if (!parent_.CommonSetConstraintsStage1(completer)) {
    return;
  }

  ZX_DEBUG_ASSERT(!parent_.has_constraints());

  // Normalize non-set constraints to constraints with every field non-set.  These are semantically
  // equivalent.
  fuchsia_sysmem2::BufferCollectionConstraints local_constraints;
  if (request.constraints().has_value()) {
    local_constraints = std::move(request.constraints().value());
  }

  parent_.node_properties().SetBufferCollectionConstraints(std::move(local_constraints));

  if (parent_.logical_buffer_collection().is_verbose_logging()) {
    parent_.node_properties().LogInfo(FROM_HERE, "BufferCollection::V2::SetConstraints()");
    parent_.node_properties().LogConstraints(FROM_HERE);
  }

  // LogicalBufferCollection will ask for constraints when it needs them,
  // possibly during this call if this is the last participant to report
  // having initial constraints.
  //
  // The LogicalBufferCollection cares if this BufferCollection view has null
  // constraints, but only later when it asks for the specific constraints.
  parent_.logical_buffer_collection().OnDependencyReady();
  // |this| may be gone at this point, if the allocation failed.  Regardless,
  // SetConstraints() worked, so ZX_OK.
}

template <typename Completer>
bool BufferCollection::CommonWaitForAllBuffersAllocatedStage1(
    bool enforce_set_constraints_before_wait, Completer& completer,
    trace_async_id_t* out_event_id) {
  if (is_done_) {
    FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
             "BufferCollection::WaitForAllBuffersAllocated() when already is_done_");
    return false;
  }
  if (!is_set_constraints_seen_) {
    if (enforce_set_constraints_before_wait) {
      // This is enforced for sysmem2, but not for sysmem(1), due to legacy missing check in sysmem1
      // timeframe.
      logical_buffer_collection().LogClientError(
          FROM_HERE, &node_properties(),
          "#############################################################################################");
      FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
               "WaitForAllBuffersAllocated before SetConstraints not permitted (in sysmem2)");
      return false;
    } else {
      // TODO(b/301844809): The referenced bug has the known client(s) that trigger this log output.
      // Currently this logs at INFO to avoid annoying test runs.
      logical_buffer_collection().LogClientInfo(
          FROM_HERE, &node_properties(),
          "#############################################################################################");
      logical_buffer_collection().LogClientInfo(
          FROM_HERE, &node_properties(),
          "WaitForAllBuffersAllocated before SetConstraints not permitted in sysmem2; please fix client.");
      logical_buffer_collection().LogClientInfo(
          FROM_HERE, &node_properties(),
          "WaitForAllBuffersAllocated before SetConstraints - allowing because this channel is sysmem(1)");
      logical_buffer_collection().LogClientInfo(
          FROM_HERE, &node_properties(),
          "#############################################################################################");
    }
  }
  if (!node_properties().is_weak_ok() && node_properties().is_weak()) {
    // If this failure happens, the client should make sure to also pay attention to close_weak_asap
    // ZX_EVENTPAIR_PEER_CLOSED, in addition to sending SetWeakOk().
    FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
             "weak BufferCollection needs SetWeakOk before WaitForAllBuffersAllocated");
    return false;
  }
  wait_for_buffers_seen_ = true;
  trace_async_id_t current_event_id = TRACE_NONCE();
  TRACE_ASYNC_BEGIN("gfx", "BufferCollection::WaitForAllBuffersAllocated async", current_event_id,
                    "this", this, "logical_buffer_collection", &logical_buffer_collection());
  *out_event_id = current_event_id;
  return true;
}

void BufferCollection::V1::WaitForBuffersAllocated(
    WaitForBuffersAllocatedCompleter::Sync& completer) {
  TRACE_DURATION("gfx", "BufferCollection::V1::WaitForBuffersAllocated", "this", this,
                 "logical_buffer_collection", &parent_.logical_buffer_collection());

  trace_async_id_t current_event_id;
  if (!parent_.CommonWaitForAllBuffersAllocatedStage1(false, completer, &current_event_id)) {
    return;
  }

  parent_.pending_wait_for_buffers_allocated_v1_.emplace_back(
      std::make_pair(current_event_id, completer.ToAsync()));
  // The allocation is a one-shot (once true, remains true) and may already be done, in which case
  // this immediately completes txn.
  parent_.MaybeCompleteWaitForBuffersAllocated();
}

void BufferCollection::V2::WaitForAllBuffersAllocated(
    WaitForAllBuffersAllocatedCompleter::Sync& completer) {
  TRACE_DURATION("gfx", "BufferCollection::V2::WaitForAllBuffersAllocated", "this", this,
                 "logical_buffer_collection", &parent_.logical_buffer_collection());

  trace_async_id_t current_event_id = TRACE_NONCE();
  if (!parent_.CommonWaitForAllBuffersAllocatedStage1(true, completer, &current_event_id)) {
    return;
  }

  parent_.pending_wait_for_buffers_allocated_v2_.emplace_back(
      std::make_pair(current_event_id, completer.ToAsync()));
  // The allocation is a one-shot (once true, remains true) and may already be done, in which case
  // this immediately completes txn.
  parent_.MaybeCompleteWaitForBuffersAllocated();
}

template <typename Completer>
bool BufferCollection::CommonCheckAllBuffersAllocatedStage1(
    Completer& completer, std::optional<fuchsia_sysmem2::Error>* result) {
  if (is_done_) {
    FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
             "BufferCollectionToken::V1::CheckBuffersAllocated() when "
             "already is_done_");
    // We're failing async - no need to try to fail sync.
    return false;
  }
  if (!logical_allocation_result_.has_value()) {
    *result = fuchsia_sysmem2::Error::kPending;
    return true;
  }
  // Buffer collection has either been allocated or failed.
  *result = logical_allocation_result_->maybe_error;
  return true;
}

void BufferCollection::V1::CheckBuffersAllocated(CheckBuffersAllocatedCompleter::Sync& completer) {
  std::optional<fuchsia_sysmem2::Error> result;
  if (!parent_.CommonCheckAllBuffersAllocatedStage1(completer, &result)) {
    return;
  }

  zx_status_t v1_status;
  if (!result.has_value()) {
    v1_status = ZX_OK;
  } else {
    v1_status = sysmem::V1CopyFromV2Error(*result);
  }

  completer.Reply(v1_status);
}

void BufferCollection::V2::CheckAllBuffersAllocated(
    CheckAllBuffersAllocatedCompleter::Sync& completer) {
  std::optional<fuchsia_sysmem2::Error> result;
  if (!parent_.CommonCheckAllBuffersAllocatedStage1(completer, &result)) {
    return;
  }
  if (!result.has_value()) {
    completer.Reply(fit::ok());
  } else {
    completer.Reply(fit::error(*result));
  }
}

template <typename Completer>
bool BufferCollection::CommonAttachTokenStage1(uint32_t rights_attenuation_mask,
                                               Completer& completer,
                                               NodeProperties** out_node_properties) {
  if (is_done_) {
    // This is Release() followed by AttachToken(), which is not permitted and causes the
    // BufferCollection to fail.
    FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
             "BufferCollection::AttachToken() attempted when is_done_");
    return false;
  }

  if (rights_attenuation_mask == 0) {
    FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
             "rights_attenuation_mask of 0 is forbidden");
    return false;
  }

  // The child created by NewChild() below will be strong not weak because of this check. Any
  // SetWeak later on a descendant will fail a different check.
  if (node_properties().is_weak()) {
    // If this is needed in a real scenario, please reach out.
    FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
             "AttachToken on weak collection not (yet?) supported");
    return false;
  }

  NodeProperties* new_node_properties = node_properties().NewChild(&logical_buffer_collection());

  // These defaults can be overriden by Allocator.SetDebugClientInfo() called before
  // BindSharedCollection().
  if (!new_node_properties->client_debug_info().name.empty()) {
    // This can be overriden via Allocator::SetDebugClientInfo(), but in case that's not called,
    // this default may help clarify where the new token / BufferCollection channel came from.
    new_node_properties->client_debug_info().name =
        new_node_properties->client_debug_info().name + " then AttachToken()";
  } else {
    new_node_properties->client_debug_info().name = "from AttachToken()";
  }

  if (rights_attenuation_mask != ZX_RIGHT_SAME_RIGHTS) {
    new_node_properties->rights_attenuation_mask() &= rights_attenuation_mask;
  }

  // All AttachToken() tokesn are ErrorPropagationMode::kDoNotPropagate from the start.
  new_node_properties->error_propagation_mode() = ErrorPropagationMode::kDoNotPropagate;

  *out_node_properties = new_node_properties;

  return true;
}

void BufferCollection::V1::AttachToken(AttachTokenRequest& request,
                                       AttachTokenCompleter::Sync& completer) {
  TRACE_DURATION("gfx", "BufferCollection::V1::AttachToken", "this", this,
                 "logical_buffer_collection", &parent_.logical_buffer_collection());

  NodeProperties* new_node_properties;
  if (!parent_.CommonAttachTokenStage1(request.rights_attenuation_mask(), completer,
                                       &new_node_properties)) {
    return;
  }

  parent_.logical_buffer_collection().CreateBufferCollectionTokenV1(
      parent_.shared_logical_buffer_collection(), new_node_properties,
      std::move(request.token_request()));
}

void BufferCollection::V2::AttachToken(AttachTokenRequest& request,
                                       AttachTokenCompleter::Sync& completer) {
  TRACE_DURATION("gfx", "BufferCollection::V2::AttachToken", "this", this,
                 "logical_buffer_collection", &parent_.logical_buffer_collection());

  if (!request.rights_attenuation_mask().has_value()) {
    parent_.FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
                     "V2::AttachToken() requires rights_attenuation_mask set");
    return;
  }

  if (!request.token_request().has_value()) {
    parent_.FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
                     "V2::AttachToken() requires token_request set");
    return;
  }

  NodeProperties* new_node_properties;
  if (!parent_.CommonAttachTokenStage1(request.rights_attenuation_mask().value(), completer,
                                       &new_node_properties)) {
    return;
  }

  parent_.logical_buffer_collection().CreateBufferCollectionTokenV2(
      parent_.shared_logical_buffer_collection(), new_node_properties,
      std::move(request.token_request().value()));
}

template <typename Completer>
void BufferCollection::CommonAttachLifetimeTracking(zx::eventpair server_end,
                                                    uint32_t buffers_remaining,
                                                    Completer& completer) {
  TRACE_DURATION("gfx", "BufferCollection::AttachLifetimeTracking", "this", this,
                 "logical_buffer_collection", &logical_buffer_collection());
  if (is_done_) {
    // This is Release() followed by AttachLifetimeTracking() which is not permitted and causes the
    // BufferCollection to fail.
    FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
             "BufferCollection::AttachLifetimeTracking() attempted when is_done_");
    return;
  }
  pending_lifetime_tracking_.emplace_back(PendingLifetimeTracking{
      .server_end = std::move(server_end), .buffers_remaining = buffers_remaining});
  MaybeFlushPendingLifetimeTracking();
}

void BufferCollection::V1::AttachLifetimeTracking(
    AttachLifetimeTrackingRequest& request, AttachLifetimeTrackingCompleter::Sync& completer) {
  parent_.CommonAttachLifetimeTracking(std::move(request.server_end()), request.buffers_remaining(),
                                       completer);
}

void BufferCollection::V2::AttachLifetimeTracking(
    AttachLifetimeTrackingRequest& request, AttachLifetimeTrackingCompleter::Sync& completer) {
  if (!request.server_end().has_value()) {
    parent_.FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
                     "AttachLifetimeTracking() requires server_end set");
    return;
  }
  if (!request.buffers_remaining().has_value()) {
    parent_.FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
                     "AttachLifetimeTracking() requires buffers_remaining set");
    return;
  }
  parent_.CommonAttachLifetimeTracking(std::move(request.server_end().value()),
                                       request.buffers_remaining().value(), completer);
}

void BufferCollection::V1::SetVerboseLogging(SetVerboseLoggingCompleter::Sync& completer) {
  parent_.SetVerboseLoggingImpl(ConnectionVersion::kVersion1, completer);
}

void BufferCollection::V2::SetVerboseLogging(SetVerboseLoggingCompleter::Sync& completer) {
  parent_.SetVerboseLoggingImpl(ConnectionVersion::kVersion2, completer);
}

void BufferCollection::V1::GetNodeRef(GetNodeRefCompleter::Sync& completer) {
  parent_.GetNodeRefImplV1(completer);
}

void BufferCollection::V2::GetNodeRef(GetNodeRefCompleter::Sync& completer) {
  parent_.GetNodeRefImplV2(completer);
}

void BufferCollection::V1::IsAlternateFor(IsAlternateForRequest& request,
                                          IsAlternateForCompleter::Sync& completer) {
  parent_.IsAlternateForImplV1(request, completer);
}

void BufferCollection::V2::IsAlternateFor(IsAlternateForRequest& request,
                                          IsAlternateForCompleter::Sync& completer) {
  parent_.IsAlternateForImplV2(request, completer);
}

void BufferCollection::V2::GetBufferCollectionId(GetBufferCollectionIdCompleter::Sync& completer) {
  parent_.GetBufferCollectionIdImplV2(completer);
}

void BufferCollection::V2::SetWeak(SetWeakCompleter::Sync& completer) {
  parent_.SetWeakImplV2(completer);
}

void BufferCollection::V2::AttachNodeTracking(AttachNodeTrackingRequest& request,
                                              AttachNodeTrackingCompleter::Sync& completer) {
  parent_.AttachNodeTrackingImpl(request, completer);
}

void BufferCollection::V2::SetWeakOk(SetWeakOkRequest& request,
                                     SetWeakOkCompleter::Sync& completer) {
  if (parent_.wait_for_buffers_seen_) {
    parent_.FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
                     "SetWeakOk() after WaitForAllBuffersAllocated()");
    return;
  }
  parent_.SetWeakOkImplV2(request, completer);
}

void BufferCollection::V2::handle_unknown_method(
    fidl::UnknownMethodMetadata<fuchsia_sysmem2::BufferCollection> metadata,
    fidl::UnknownMethodCompleter::Sync& completer) {
  parent_.FailSync(FROM_HERE, completer, Error::kProtocolDeviation,
                   "BufferCollection unknown method - ordinal: %" PRIx64, metadata.method_ordinal);
}

void BufferCollection::V1::Close(CloseCompleter::Sync& completer) {
  parent_.ReleaseImpl(ConnectionVersion::kVersion1, completer);
}

void BufferCollection::V2::Release(ReleaseCompleter::Sync& completer) {
  parent_.ReleaseImpl(ConnectionVersion::kVersion2, completer);
}

void BufferCollection::V1::SetName(SetNameRequest& request, SetNameCompleter::Sync& completer) {
  parent_.SetNameImplV1(request, completer);
}

void BufferCollection::V2::SetName(SetNameRequest& request, SetNameCompleter::Sync& completer) {
  parent_.SetNameImplV2(request, completer);
}

void BufferCollection::V1::SetDebugClientInfo(SetDebugClientInfoRequest& request,
                                              SetDebugClientInfoCompleter::Sync& completer) {
  parent_.SetDebugClientInfoImplV1(request, completer);
}

void BufferCollection::V2::SetDebugClientInfo(SetDebugClientInfoRequest& request,
                                              SetDebugClientInfoCompleter::Sync& completer) {
  parent_.SetDebugClientInfoImplV2(request, completer);
}

void BufferCollection::V1::SetDebugTimeoutLogDeadline(
    SetDebugTimeoutLogDeadlineRequest& request,
    SetDebugTimeoutLogDeadlineCompleter::Sync& completer) {
  parent_.SetDebugTimeoutLogDeadlineImplV1(request, completer);
}

void BufferCollection::V2::SetDebugTimeoutLogDeadline(
    SetDebugTimeoutLogDeadlineRequest& request,
    SetDebugTimeoutLogDeadlineCompleter::Sync& completer) {
  parent_.SetDebugTimeoutLogDeadlineImplV2(request, completer);
}

void BufferCollection::FailAsync(Location location, Error error, const char* format, ...) {
  va_list args;
  va_start(args, format);
  logical_buffer_collection().VLogClientError(location, &node_properties(), format, args);
  va_end(args);

  // Idempotent, so only close once.
  if (!server_binding_v1_.has_value() && !server_binding_v2_.has_value()) {
    return;
  }
  ZX_DEBUG_ASSERT(!!server_binding_v1_.has_value() ^ !!server_binding_v2_.has_value());

  zx_status_t epitaph = sysmem::V1CopyFromV2Error(error);
  async_failure_result_ = epitaph;

  if (server_binding_v1_.has_value()) {
    server_binding_v1_->Close(epitaph);
    server_binding_v1_ = {};
  } else {
    ZX_DEBUG_ASSERT(server_binding_v2_.has_value());
    server_binding_v2_->Close(ZX_ERR_INTERNAL);
    server_binding_v2_ = {};
  }
}

template <typename Completer>
void BufferCollection::FailSync(Location location, Completer& completer, Error error,
                                const char* format, ...) {
  va_list args;
  va_start(args, format);
  logical_buffer_collection().VLogClientError(location, &node_properties(), format, args);
  va_end(args);

  zx_status_t epitaph = sysmem::V1CopyFromV2Error(error);

  if (server_binding_v1_.has_value()) {
    completer.Close(epitaph);
  } else {
    completer.Close(ZX_ERR_INTERNAL);
  }

  async_failure_result_ = epitaph;
}

fpromise::result<fuchsia_sysmem2::BufferCollectionInfo> BufferCollection::CloneResultForSendingV2(
    const fuchsia_sysmem2::BufferCollectionInfo& buffer_collection_info) {
  uint32_t vmo_rights_mask = GetClientVmoRights();
  ZX_DEBUG_ASSERT(has_constraints());
  // We want to provide VMOs if there's any real usage or IsNoneUsagePermitAllocation.
  bool is_usage = constraints().usage().has_value() &&
                  (IsAnyUsage(constraints().usage().value()) ||
                   IsNoneUsagePermitAllocation(constraints().usage().value()));
  if (!is_usage || node_properties().is_weak()) {
    // By specifying 0 for rights, the V2CloneBufferCollectionInfo() below won't dup any VMO handles
    // (and won't create any child VMOs).
    vmo_rights_mask = 0;
  }
#if ZX_DEBUG_ASSERT_IMPLEMENTED
  {
    if (!node_properties().is_weak()) {
      bool found_missing = false;
      for (auto& buffer : *buffer_collection_info.buffers()) {
        // Because this node isn't weak, this node is owning all these sysmem strong VMOs.
        if (!buffer.vmo().has_value() || !buffer.vmo()->is_valid()) {
          found_missing = true;
          break;
        }
      }
      ZX_DEBUG_ASSERT(!found_missing);
    }
  }
#endif
  auto clone_result = sysmem::V2CloneBufferCollectionInfo(buffer_collection_info, vmo_rights_mask);
  if (!clone_result.is_ok()) {
    FailAsync(FROM_HERE, Error::kUnspecified,
              "CloneResultForSendingV1() V2CloneBufferCollectionInfo() failed - status: %d",
              clone_result.error());
    return fpromise::error();
  }
  auto v2_b = clone_result.take_value();
  if (node_properties().is_weak()) {
    // replace no-vmo VmoBuffer(s) with VmoBuffer(s) having both a sysmem weak VMO handle (if
    // is_usage) and a close_weak_asap client end
    for (uint32_t buffer_index = 0; buffer_index < buffer_collection_info.buffers()->size();
         ++buffer_index) {
      fuchsia_sysmem2::VmoBuffer vmo_buffer = std::move(v2_b.buffers()->at(buffer_index));
      if (is_usage) {
        // If zero strong VMO handles remain, this will be success but with no VMO handle.
        auto weak_vmo_result = logical_buffer_collection().CreateWeakVmo(
            buffer_index, node_properties().client_debug_info());
        if (weak_vmo_result.is_error()) {
          FailAsync(FROM_HERE, Error::kUnspecified, "CreateWeakVmo() failed");
          return fpromise::error();
        }
        // This is moving std::optional<zx::vmo>; if zero strong VMO handles remain, the moved-into
        // optional will be !has_value().
        vmo_buffer.vmo() = std::move(weak_vmo_result).value();
      } else {
        ZX_DEBUG_ASSERT(!vmo_buffer.vmo().has_value());
      }
      auto close_weak_asap = logical_buffer_collection().DupCloseWeakAsapClientEnd(buffer_index);
      if (close_weak_asap.is_error()) {
        FailAsync(FROM_HERE, Error::kUnspecified, "DupCloseWeakAsapClientEnd() failed");
        return fpromise::error();
      }
      // This is moving std::optional<zx::eventpair>; if zero strong VMO handles remain, the
      // moved-into optional will be !has_value().
      vmo_buffer.close_weak_asap() = std::move(close_weak_asap.value());
      // If we're giving out a sysmem weak VMO handle then we're also giving out a close_weak_asap,
      // since any client holding a sysmem weak VMO handle needs to know when to close that handle
      // asap.
      ZX_DEBUG_ASSERT(!vmo_buffer.vmo().has_value() || vmo_buffer.close_weak_asap().has_value());
      auto attenuated_vmo_buffer_result =
          sysmem::V2CloneVmoBuffer(vmo_buffer, GetClientVmoRights());
      if (attenuated_vmo_buffer_result.is_error()) {
        FailAsync(FROM_HERE, Error::kUnspecified, "V2CloneVmoBuffer failed");
        return fpromise::error();
      }
      auto& attenuated_vmo_buffer = attenuated_vmo_buffer_result.value();
      v2_b.buffers()->at(buffer_index) = std::move(attenuated_vmo_buffer);
    }
  }
  return fpromise::ok(std::move(v2_b));
}

fpromise::result<fuchsia_sysmem::BufferCollectionInfo2> BufferCollection::CloneResultForSendingV1(
    const fuchsia_sysmem2::BufferCollectionInfo& buffer_collection_info) {
  if (node_properties().is_weak() && !node_properties().is_weak_ok_from_parent()) {
    // To avoid this failure case, consider migrating to sysmem2 (a sysmem (1) token client_end can
    // be used directly as a sysmem2 token).
    //
    // It doesn't work to set for_child_nodes_also true on a v2 Node then convert that Node to a v1
    // Node then get VMO handles via that v1 Node. Instead, an _ancestor_ v2 Node must have set
    // for_child_nodes_also true - only then can a descendant v1 Node be sent weak VMO handles.
    FailAsync(FROM_HERE, Error::kProtocolDeviation,
              "sysmem v1 can't do weak unless for_child_nodes_also=true from _ancestor_ v2 node");
    return fpromise::error();
  }
  auto v2_result = CloneResultForSendingV2(buffer_collection_info);
  if (!v2_result.is_ok()) {
    // FailAsync() already called.
    return fpromise::error();
  }
  auto v1_result = sysmem::V1MoveFromV2BufferCollectionInfo(v2_result.take_value());
  if (!v1_result.is_ok()) {
    FailAsync(FROM_HERE, Error::kProtocolDeviation,
              "CloneResultForSendingV1() V1MoveFromV2BufferCollectionInfo() failed");
    return fpromise::error();
  }
  return v1_result;
}

void BufferCollection::OnBuffersAllocated(const AllocationResult& allocation_result) {
  TRACE_DURATION("gfx", "BufferCollection::OnBuffersAllocated", "status",
                 allocation_result.maybe_error.has_value()
                     ? static_cast<uint32_t>(*allocation_result.maybe_error)
                     : ZX_OK);
  ZX_DEBUG_ASSERT(!logical_allocation_result_.has_value());

  ZX_DEBUG_ASSERT(!allocation_result.maybe_error.has_value() ==
                  !!allocation_result.buffer_collection_info);

  node_properties().SetBuffersLogicallyAllocated();

  logical_allocation_result_.emplace(allocation_result);

  // Any that are pending are completed by this call or something called
  // FailAsync().  It's fine for this method to ignore the fact that
  // FailAsync() may have already been called.  That's essentially the main
  // reason we have FailAsync() instead of Fail().
  MaybeCompleteWaitForBuffersAllocated();

  // If there are any, they'll be flushed to LogicalBufferCollection now.
  MaybeFlushPendingLifetimeTracking();
}

bool BufferCollection::has_constraints() { return node_properties().has_constraints(); }

const fuchsia_sysmem2::BufferCollectionConstraints& BufferCollection::constraints() {
  ZX_DEBUG_ASSERT(has_constraints());
  return *node_properties().buffer_collection_constraints();
}

fuchsia_sysmem2::BufferCollectionConstraints BufferCollection::CloneConstraints() {
  ZX_DEBUG_ASSERT(has_constraints());
  // copy / clone
  return constraints();
}

BufferCollection::BufferCollection(
    fbl::RefPtr<LogicalBufferCollection> logical_buffer_collection_param,
    const BufferCollectionToken& token, const CollectionServerEnd& server_end)
    : Node(std::move(logical_buffer_collection_param), &token.node_properties(),
           GetUnownedChannel(server_end)) {
  TRACE_DURATION("gfx", "BufferCollection::BufferCollection", "this", this,
                 "logical_buffer_collection", &this->logical_buffer_collection());
  ZX_DEBUG_ASSERT(shared_logical_buffer_collection());
  inspect_node_ =
      this->logical_buffer_collection().inspect_node().CreateChild(CreateUniqueName("collection-"));
}

// This method is only meant to be called from GetClientVmoRights().
uint32_t BufferCollection::GetUsageBasedRightsAttenuation() {
  // This method won't be called for participants without constraints.
  ZX_DEBUG_ASSERT(has_constraints());

  // We assume that read and map are both needed by all participants with any "usage".  Only
  // ZX_RIGHT_WRITE is controlled by usage.

  // It's not this method's job to attenuate down to kMaxClientVmoRights, so
  // let's not pretend like it is.
  uint32_t result = std::numeric_limits<uint32_t>::max();
  if (!constraints().usage().has_value() || !IsWriteUsage(*constraints().usage())) {
    result &= ~ZX_RIGHT_WRITE;
  }

  return result;
}

uint32_t BufferCollection::GetClientVmoRights() {
  return
      // max possible rights for a client to have
      kMaxClientVmoRights &
      // attenuate write if client doesn't need write
      GetUsageBasedRightsAttenuation() &
      // attenuate according to BufferCollectionToken.Duplicate() rights
      // parameter so that initiator and participant can distribute the token
      // and remove any unnecessary/unintended rights along the way.
      node_properties().rights_attenuation_mask();
}

void BufferCollection::MaybeCompleteWaitForBuffersAllocated() {
  if (!logical_allocation_result_.has_value()) {
    // Everything is ok so far, but allocation isn't done yet.
    return;
  }
  while (!pending_wait_for_buffers_allocated_v1_.empty()) {
    auto [async_id, txn] = std::move(pending_wait_for_buffers_allocated_v1_.front());
    pending_wait_for_buffers_allocated_v1_.pop_front();

    fuchsia_sysmem::BufferCollectionInfo2 v1;
    if (!logical_allocation_result_->maybe_error.has_value()) {
      ZX_DEBUG_ASSERT(logical_allocation_result_->buffer_collection_info);
      auto v1_result = CloneResultForSendingV1(*logical_allocation_result_->buffer_collection_info);
      if (!v1_result.is_ok()) {
        // FailAsync() already called.
        return;
      }
      v1 = v1_result.take_value();
    }
    TRACE_ASYNC_END("gfx", "BufferCollection::WaitForAllBuffersAllocated async", async_id, "this",
                    this, "logical_buffer_collection", &logical_buffer_collection());

    fuchsia_sysmem::BufferCollectionWaitForBuffersAllocatedResponse response;
    if (logical_allocation_result_->maybe_error.has_value()) {
      response.status() = sysmem::V1CopyFromV2Error(*logical_allocation_result_->maybe_error);
    } else {
      response.status() = ZX_OK;
    }
    response.buffer_collection_info() = std::move(v1);
    txn.Reply(std::move(response));

    fidl::Status reply_status = txn.result_of_reply();
    if (!reply_status.ok()) {
      FailAsync(FROM_HERE, Error::kUnspecified,
                "fuchsia_sysmem_BufferCollectionWaitForBuffersAllocated_"
                "reply failed - status: %s",
                reply_status.FormatDescription().c_str());
      return;
    }
    // ~txn
  }
  while (!pending_wait_for_buffers_allocated_v2_.empty()) {
    auto [async_id, txn] = std::move(pending_wait_for_buffers_allocated_v2_.front());
    pending_wait_for_buffers_allocated_v2_.pop_front();

    fuchsia_sysmem2::BufferCollectionInfo v2;
    if (!logical_allocation_result_->maybe_error.has_value()) {
      ZX_DEBUG_ASSERT(logical_allocation_result_->buffer_collection_info);
      auto v2_result = CloneResultForSendingV2(*logical_allocation_result_->buffer_collection_info);
      if (!v2_result.is_ok()) {
        // FailAsync() already called.
        return;
      }
      v2 = v2_result.take_value();
    }
    TRACE_ASYNC_END("gfx", "BufferCollection::WaitForAllBuffersAllocated async", async_id, "this",
                    this, "logical_buffer_collection", &logical_buffer_collection());
    if (logical_allocation_result_->maybe_error.has_value()) {
      txn.Reply(fit::error(*logical_allocation_result_->maybe_error));
    } else {
      fuchsia_sysmem2::BufferCollectionWaitForAllBuffersAllocatedResponse response;
      response.buffer_collection_info() = std::move(v2);
      txn.Reply(fit::ok(std::move(response)));
    }
    fidl::Status reply_status = txn.result_of_reply();
    if (!reply_status.ok()) {
      FailAsync(FROM_HERE, Error::kUnspecified,
                "fuchsia_sysmem2::BufferCollectionWaitForBuffersAllocated "
                "reply failed - status: %s",
                reply_status.FormatDescription().c_str());
      return;
    }
    // ~txn
  }
}

void BufferCollection::MaybeFlushPendingLifetimeTracking() {
  if (!node_properties().buffers_logically_allocated()) {
    return;
  }
  if (logical_allocation_result_->maybe_error.has_value()) {
    // We close these immediately if logical allocation failed, regardless of
    // the number of buffers potentially allocated in the overall
    // LogicalBufferCollection.  This is for behavior consistency between
    // AttachToken() sub-trees and the root_.
    pending_lifetime_tracking_.clear();
    return;
  }
  for (auto& pending : pending_lifetime_tracking_) {
    logical_buffer_collection().AttachLifetimeTracking(std::move(pending.server_end),
                                                       pending.buffers_remaining);
  }
  pending_lifetime_tracking_.clear();
}

bool BufferCollection::ReadyForAllocation() { return has_constraints(); }

BufferCollectionToken* BufferCollection::buffer_collection_token() { return nullptr; }

const BufferCollectionToken* BufferCollection::buffer_collection_token() const { return nullptr; }

BufferCollection* BufferCollection::buffer_collection() { return this; }

const BufferCollection* BufferCollection::buffer_collection() const { return this; }

BufferCollectionTokenGroup* BufferCollection::buffer_collection_token_group() { return nullptr; }

const BufferCollectionTokenGroup* BufferCollection::buffer_collection_token_group() const {
  return nullptr;
}

OrphanedNode* BufferCollection::orphaned_node() { return nullptr; }

const OrphanedNode* BufferCollection::orphaned_node() const { return nullptr; }

bool BufferCollection::is_connected_type() const { return true; }

bool BufferCollection::is_currently_connected() const {
  return server_binding_v1_.has_value() || server_binding_v2_.has_value();
}

const char* BufferCollection::node_type_string() const { return "collection"; }

ConnectionVersion BufferCollection::connection_version() const {
  if (server_binding_v2_.has_value()) {
    return ConnectionVersion::kVersion2;
  }
  if (server_binding_v1_.has_value()) {
    return ConnectionVersion::kVersion1;
  }
  return ConnectionVersion::kNoConnection;
}

}  // namespace sysmem_service
