// Copyright 2022 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/input/touch_system.h"

#include <fidl/fuchsia.ui.pointer/cpp/fidl.h>
#include <fidl/fuchsia.ui.pointer/cpp/hlcpp_conversion.h>
#include <fuchsia/ui/input/cpp/fidl.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/trace/event.h>
#include <zircon/status.h>

#include <src/lib/fostr/fidl/fuchsia/ui/input/accessibility/formatting.h>
#include <src/lib/fostr/fidl/fuchsia/ui/input/formatting.h>

#include "src/lib/fsl/handles/object_info.h"
#include "src/ui/scenic/lib/input/constants.h"
#include "src/ui/scenic/lib/input/internal_pointer_event.h"
#include "src/ui/scenic/lib/input/touch_source.h"
#include "src/ui/scenic/lib/input/touch_source_with_local_hit.h"
#include "src/ui/scenic/lib/utils/helpers.h"
#include "src/ui/scenic/lib/utils/math.h"

#include <glm/glm.hpp>

namespace scenic_impl::input {

using AccessibilityPointerEvent = fuchsia::ui::input::accessibility::PointerEvent;
using fuchsia::ui::input::InputEvent;
using fuchsia::ui::input::PointerEvent;
using fuchsia::ui::input::PointerEventType;

namespace {

// Helper function to build an AccessibilityPointerEvent when there is a
// registered accessibility listener.
AccessibilityPointerEvent BuildAccessibilityPointerEvent(const InternalTouchEvent& internal_event,
                                                         const glm::vec2& ndc_point,
                                                         const glm::vec2& local_point,
                                                         uint64_t viewref_koid) {
  AccessibilityPointerEvent event;
  event.set_event_time(internal_event.timestamp);
  event.set_device_id(internal_event.device_id);
  event.set_pointer_id(internal_event.pointer_id);
  event.set_type(fuchsia::ui::input::PointerEventType::TOUCH);
  event.set_phase(InternalPhaseToGfxPhase(internal_event.phase));
  event.set_ndc_point({ndc_point.x, ndc_point.y});
  event.set_viewref_koid(viewref_koid);
  if (viewref_koid != ZX_KOID_INVALID) {
    event.set_local_point({local_point.x, local_point.y});
  }
  return event;
}

// Takes an InternalTouchEvent and returns a point in (Vulkan) Normalized Device Coordinates,
// in relation to the viewport. Intended for magnification
// TODO(https://fxbug.dev/42127641): Only here to allow the legacy a11y flow. Remove along with the legacy a11y
// code.
glm::vec2 GetViewportNDCPoint(const InternalTouchEvent& internal_event) {
  const float width = internal_event.viewport.extents.max.x - internal_event.viewport.extents.min.x;
  const float height =
      internal_event.viewport.extents.max.y - internal_event.viewport.extents.min.y;
  return {
      width > 0 ? 2.f * internal_event.position_in_viewport.x / width - 1 : 0,
      height > 0 ? 2.f * internal_event.position_in_viewport.y / height - 1 : 0,
  };
}

}  // namespace

TouchSystem::TouchSystem(sys::ComponentContext* context,
                         std::shared_ptr<const view_tree::Snapshot>& view_tree_snapshot,
                         HitTester& hit_tester, inspect::Node& parent_node)
    : view_tree_snapshot_(view_tree_snapshot),
      hit_tester_(hit_tester),
      contender_inspector_(parent_node.CreateChild("GestureContenders")) {
  a11y_pointer_event_registry_.emplace(
      context,
      /*on_register=*/
      [this] {
        FX_CHECK(!contenders_.count(a11y_contender_id_))
            << "on_disconnect must be called before registering a new listener";

        auto a11y_contender = std::make_unique<A11yLegacyContender>(
            /*respond*/
            [this](StreamId stream_id, GestureResponse response) {
              RecordGestureDisambiguationResponse(stream_id, a11y_contender_id_, {response});
            },
            /*deliver_to_client*/
            [this](const InternalTouchEvent& event) {
              std::vector<fuchsia::ui::input::accessibility::PointerEvent> a11y_events;
              a11y_events.push_back(CreateAccessibilityEvent(event));
              // Add in legacy UP and DOWN phases for ADD and REMOVE events respectively.
              const auto& original_event = a11y_events.front();
              if (original_event.phase() == fuchsia::ui::input::PointerEventPhase::ADD) {
                auto it = a11y_events.insert(a11y_events.end(), fidl::Clone(original_event));
                it->set_phase(fuchsia::ui::input::PointerEventPhase::DOWN);
              } else if (original_event.phase() == fuchsia::ui::input::PointerEventPhase::REMOVE) {
                auto it = a11y_events.insert(a11y_events.begin(), fidl::Clone(original_event));
                it->set_phase(fuchsia::ui::input::PointerEventPhase::UP);
              }

              for (auto& a11y_event : a11y_events) {
                accessibility_pointer_event_listener()->OnEvent(std::move(a11y_event));
              }
            },
            contender_inspector_);
        accessibility_pointer_event_listener().events().OnStreamHandled =
            [a11y_contender = a11y_contender.get()](
                uint32_t device_id, uint32_t pointer_id,
                fuchsia::ui::input::accessibility::EventHandling handled) {
              a11y_contender->OnStreamHandled(pointer_id, handled);
            };

        const auto [_, success] =
            contenders_.emplace(a11y_contender_id_, std::move(a11y_contender));
        FX_DCHECK(success) << "Duplicate A11yLegacyContender";
        FX_LOGS(INFO) << "A11yLegacyContender created.";
      },
      /*on_disconnect=*/
      [this] {
        FX_CHECK(contenders_.count(a11y_contender_id_)) << "can not disconnect before registering";
        // The listener disconnected. Release held events, delete the buffer.
        accessibility_pointer_event_listener().events().OnStreamHandled = nullptr;
        EraseContender(a11y_contender_id_, ZX_KOID_INVALID);
        FX_LOGS(INFO) << "A11yLegacyContender destroyed";
      });
  context->outgoing()->AddPublicService(local_hit_upgrade_registry_.GetHandler(this));
}

zx_koid_t TouchSystem::FindViewRefKoidOfRelatedChannel(
    const fidl::InterfaceHandle<fuchsia::ui::pointer::TouchSource>& original) const {
  const zx_koid_t related_koid = fsl::GetRelatedKoid(original.channel().get());
  const auto it = std::find_if(
      contenders_.begin(), contenders_.end(),
      [related_koid](const auto& kv) { return kv.second->channel_koid() == related_koid; });
  return it == contenders_.end() ? ZX_KOID_INVALID : it->second->view_ref_koid_;
}

void TouchSystem::Upgrade(fidl::InterfaceHandle<fuchsia::ui::pointer::TouchSource> original,
                          fuchsia::ui::pointer::augment::LocalHit::UpgradeCallback callback) {
  // TODO(https://fxbug.dev/42165040): This currently requires the client to wait until the TouchSource has
  // been hooked up before making the Upgrade() call. This is not a great user experience. Change
  // this so we cache the channel if it arrives too early.
  const zx_koid_t view_ref_koid = FindViewRefKoidOfRelatedChannel(original);
  if (view_ref_koid == ZX_KOID_INVALID) {
    auto error = fuchsia::ui::pointer::augment::ErrorForLocalHit::New();
    error->error_reason = fuchsia::ui::pointer::augment::ErrorReason::DENIED;
    error->original = std::move(original);
    callback({}, std::move(error));
    return;
  }

  // Delete the contender for the old channel.
  EraseContender(viewrefs_to_contender_ids_.at(view_ref_koid), view_ref_koid);

  // Create the new channel contender.
  const ContenderId contender_id = next_contender_id_++;
  fidl::InterfaceHandle<fuchsia::ui::pointer::augment::TouchSourceWithLocalHit> handle;
  {
    const auto [_, success] = contenders_.emplace(
        contender_id,
        std::make_unique<TouchSourceWithLocalHit>(
            view_ref_koid, handle.NewRequest(),
            /*respond*/
            [this, contender_id](StreamId stream_id,
                                 const std::vector<GestureResponse>& responses) {
              RecordGestureDisambiguationResponse(stream_id, contender_id, responses);
            },
            /*error_handler*/
            [this, contender_id, view_ref_koid] { EraseContender(contender_id, view_ref_koid); },
            /*get_local_hit*/
            [this](const InternalTouchEvent& event) {
              // Perform a semantic hit test to find the top view a11y cares about.
              // TODO(https://fxbug.dev/42057941): If we have more than one TouchSourceWithLocalHit client,
              // this hit test will be done multiple times per injectiom redundantly. We might need
              // to improve this in the future, but as long as we're only expecting the one client
              // this is fine.
              const zx_koid_t top_koid = hit_tester_.TopHitTest(event, /*semantic_hit_test*/ true);
              glm::vec2 local_point = glm::vec2(0.f, 0.f);
              if (top_koid != ZX_KOID_INVALID) {
                const std::array<float, 9> top_view_from_viewport_transform =
                    GetDestinationFromViewportTransform(event, top_koid, *view_tree_snapshot_);
                local_point = utils::TransformPointerCoords(
                    event.position_in_viewport,
                    utils::ColumnMajorMat3ArrayToMat4(top_view_from_viewport_transform));
              }
              return std::pair<zx_koid_t, std::array<float, 2>>{top_koid,
                                                                {local_point.x, local_point.y}};
            },
            contender_inspector_));
    FX_CHECK(success);
  }
  {
    const auto [_, success] = viewrefs_to_contender_ids_.emplace(view_ref_koid, contender_id);
    FX_CHECK(success);
  }

  // Return the new channel.
  callback(std::move(handle), nullptr);
}

fuchsia::ui::input::accessibility::PointerEvent TouchSystem::CreateAccessibilityEvent(
    const InternalTouchEvent& event) {
  // Find top-hit target and send it to accessibility.
  const zx_koid_t view_ref_koid = hit_tester_.TopHitTest(event, /*semantic_hit_test*/ true);

  glm::vec2 top_hit_view_local;
  if (view_ref_koid != ZX_KOID_INVALID) {
    std::optional<glm::mat4> view_from_context =
        view_tree_snapshot_->GetDestinationViewFromSourceViewTransform(
            /*source*/ event.context, /*destination*/ view_ref_koid);
    FX_DCHECK(view_from_context)
        << "could only happen if the view_tree_view_tree_snapshot_ was updated "
           "between the event arriving and now";

    const glm::mat4 view_from_viewport =
        view_from_context.value() * event.viewport.context_from_viewport_transform;
    top_hit_view_local =
        utils::TransformPointerCoords(event.position_in_viewport, view_from_viewport);
  }
  const glm::vec2 ndc = GetViewportNDCPoint(event);

  return BuildAccessibilityPointerEvent(event, ndc, top_hit_view_local, view_ref_koid);
}

void TouchSystem::RegisterTouchSource(
    fidl::InterfaceRequest<fuchsia::ui::pointer::TouchSource> touch_source_request,
    zx_koid_t client_view_ref_koid) {
  RegisterTouchSource(fidl::HLCPPToNatural(std::move(touch_source_request)), client_view_ref_koid);
}

void TouchSystem::RegisterTouchSource(
    fidl::ServerEnd<fuchsia_ui_pointer::TouchSource> touch_source_server_end,
    zx_koid_t client_view_ref_koid) {
  FX_DCHECK(client_view_ref_koid != ZX_KOID_INVALID);
  const ContenderId contender_id = next_contender_id_++;

  // Note: These closure must'nt be called in the constructor, since they depend on the
  // |contenders_| map, which isn't filled until after construction completes.
  {
    const auto [_, success] = contenders_.emplace(
        contender_id, std::make_unique<TouchSource>(
                          client_view_ref_koid, std::move(touch_source_server_end),
                          /*respond*/
                          [this, contender_id](StreamId stream_id,
                                               const std::vector<GestureResponse>& responses) {
                            RecordGestureDisambiguationResponse(stream_id, contender_id, responses);
                          },
                          /*error_handler*/
                          [this, contender_id, client_view_ref_koid] {
                            EraseContender(contender_id, client_view_ref_koid);
                          },
                          contender_inspector_));
    FX_DCHECK(success);
  }
  {
    const auto [_, success] =
        viewrefs_to_contender_ids_.emplace(client_view_ref_koid, contender_id);
    FX_DCHECK(success);
  }
}

void TouchSystem::InjectTouchEventExclusive(const InternalTouchEvent& event, StreamId stream_id) {
  if (view_tree_snapshot_->view_tree.count(event.target) == 0 &&
      view_tree_snapshot_->unconnected_views.count(event.target) == 0) {
    FX_DCHECK(contenders_.count(static_cast<int>(event.target)) == 0);
    return;
  }
  FX_DCHECK(event.phase == Phase::kCancel ||
            view_tree_snapshot_->IsDescendant(event.target, event.context))
      << "Should never allow injection of non-cancel events into broken scene graph";

  auto it = viewrefs_to_contender_ids_.find(event.target);
  if (it != viewrefs_to_contender_ids_.end()) {
    auto& contender = *contenders_.at(it->second);
    // Calling EndContest() before the first event causes them to be combined in the first message
    // to the client.
    if (event.phase == Phase::kAdd) {
      contender.EndContest(stream_id, /*awarded_win=*/true);
    }

    // If the target is not in the view tree then this must be a cancel event and we don't need to
    // (and can't) supply correct transforms and bounding boxes.
    if (view_tree_snapshot_->view_tree.count(event.target) == 0) {
      FX_DCHECK(event.phase == Phase::kCancel);
      contender.UpdateStream(stream_id, event, /*is_end_of_stream=*/true, /*bounding_box=*/{});
    } else {
      contender.UpdateStream(
          stream_id,
          EventWithReceiverFromViewportTransform(event, event.target, *view_tree_snapshot_),
          /*is_end_of_stream=*/event.phase == Phase::kRemove || event.phase == Phase::kCancel,
          view_tree_snapshot_->view_tree.at(event.target).bounding_box);
    }
  } else {
    FX_NOTREACHED();
  }
}

// The touch state machine comprises ADD/DOWN/MOVE*/UP/REMOVE. Some notes:
//  - We assume one touchscreen device, and use the device-assigned finger ID.
//  - Touch ADD associates the following ADD/DOWN/MOVE*/UP/REMOVE event sequence
//    with the set of clients available at that time. To enable gesture
//    disambiguation, we perform parallel dispatch to all clients.
//  - Touch DOWN triggers a focus change, honoring the "may receive focus" property.
//  - Touch REMOVE drops the association between event stream and client.
void TouchSystem::InjectTouchEventHitTested(const InternalTouchEvent& event, StreamId stream_id) {
  // New stream. Collect contenders and set up a new arena.
  if (event.phase == Phase::kAdd) {
    std::vector<ContenderId> contenders = CollectContenders(stream_id, event);
    if (!contenders.empty()) {
      const bool is_single_contender = contenders.size() == 1;
      const ContenderId front_contender = contenders.front();
      const auto [it, success] =
          gesture_arenas_.emplace(stream_id, GestureArena{std::move(contenders)});
      FX_DCHECK(success);
      // If there's only a single contender then the contest is already decided
      FX_DCHECK(it->second.contest_has_ended() == is_single_contender);
      if (it->second.contest_has_ended()) {
        contenders_.at(front_contender)->EndContest(stream_id, /*awarded_win*/ true);
      }
    }
  }

  // No arena means the contest is over and no one won.
  if (!gesture_arenas_.count(stream_id)) {
    return;
  }

  UpdateGestureContest(event, stream_id);
}

static bool IsRootOrDirectChildOfRoot(zx_koid_t koid, const view_tree::Snapshot& snapshot) {
  if (snapshot.root == koid) {
    return true;
  }
  if (snapshot.view_tree.count(koid) == 0) {
    return false;
  }

  return snapshot.view_tree.at(koid).parent == snapshot.root;
}

std::vector<zx_koid_t> TouchSystem::GetAncestorChainTopToBottom(zx_koid_t bottom,
                                                                zx_koid_t top) const {
  if (bottom == top) {
    return {bottom};
  }

  // Get ancestors bottom closest to furthest.
  std::vector<zx_koid_t> ancestors = view_tree_snapshot_->GetAncestorsOf(bottom);
  FX_DCHECK(ancestors.empty() || std::any_of(ancestors.begin(), ancestors.end(),
                                             [top](const zx_koid_t koid) { return koid == top; }))
      << "|top| must be an ancestor of |bottom|";

  // Remove all ancestors after |top|.
  for (auto it = ancestors.begin(); it != ancestors.end(); ++it) {
    if (*it == top) {
      ancestors.erase(++it, ancestors.end());
      break;
    }
  }

  // Reverse the list and add |bottom| to the end.
  std::reverse(ancestors.begin(), ancestors.end());
  ancestors.emplace_back(bottom);
  FX_DCHECK(ancestors.front() == top);

  return ancestors;
}

std::vector<ContenderId> TouchSystem::CollectContenders(StreamId stream_id,
                                                        const InternalTouchEvent& event) {
  std::vector<ContenderId> contenders;

  // Add an A11yLegacyContender if the injection context is the root of the ViewTree.
  // TODO(https://fxbug.dev/42127641): Remove when a11y is a native GD client.
  if (contenders_.count(a11y_contender_id_) &&
      IsRootOrDirectChildOfRoot(event.context, *view_tree_snapshot_)) {
    contenders.push_back(a11y_contender_id_);
  }

  const zx_koid_t top_koid = hit_tester_.TopHitTest(event, /*semantic_hit_test*/ false);
  if (top_koid != ZX_KOID_INVALID) {
    // Find TouchSource contenders in priority order from furthest (valid) ancestor to top hit view.
    const std::vector<zx_koid_t> ancestors = GetAncestorChainTopToBottom(top_koid, event.target);
    for (const auto koid : ancestors) {
      // If a touch contender doesn't exist it means the client didn't provide a TouchSource
      // endpoint.
      const auto it = viewrefs_to_contender_ids_.find(koid);
      if (it != viewrefs_to_contender_ids_.end()) {
        const ContenderId contender_id = it->second;
        FX_DCHECK(contenders_.count(contender_id));
        contenders.push_back(contender_id);
      }
    }
  }

  return contenders;
}

void TouchSystem::UpdateGestureContest(const InternalTouchEvent& event, StreamId stream_id) {
  const auto arena_it = gesture_arenas_.find(stream_id);
  if (arena_it == gesture_arenas_.end()) {
    // Contest already ended, with no winner.
    return;
  }
  auto& arena = arena_it->second;

  const bool is_end_of_stream = event.phase == Phase::kRemove || event.phase == Phase::kCancel;
  arena.UpdateStream(/*length*/ 1, is_end_of_stream);

  // Update remaining contenders.
  // Copy the vector to avoid problems if the arena is destroyed inside of UpdateStream().
  const std::vector<ContenderId> contenders = arena.contenders();
  const glm::mat4 world_from_viewport_transform =
      view_tree_snapshot_->GetWorldFromViewTransform(event.context).value() *
      event.viewport.context_from_viewport_transform;
  for (const auto contender_id : contenders) {
    // Don't use the arena obtained above the loop, because it may have been removed from
    // gesture_arenas_ in a previous loop iteration.
    // TODO(https://fxbug.dev/42171409): it would be nice to restructure the code so that the arena can be
    // obtained once at the top of this method, and guaranteed to be safe to reuse thereafter.
    const auto arena_it = gesture_arenas_.find(stream_id);
    if (arena_it == gesture_arenas_.end()) {
      // Break out of the loop: if we didn't find the arena in this iteration, we won't find it in
      // subsequent iterations either.
      break;
    }
    if (arena_it->second.contest_has_ended() && !arena_it->second.contains(contender_id)) {
      // Contest ended with this contender not being the winner; no need to consider it further.
      continue;
    }
    const auto it = contenders_.find(contender_id);
    if (it == contenders_.end()) {
      // This contender is no longer present, probably because the client has disconnected.
      // TODO(https://fxbug.dev/42171409): the contender is still in the arena, though.  Can this cause
      // problems (such as the arena contest never completing), or will the arena soon finish and be
      // deleted anyway?
      continue;
    }

    GestureContender& contender = *it->second;
    const zx_koid_t view_ref_koid = contender.view_ref_koid_;
    if (view_tree_snapshot_->view_tree.count(view_ref_koid) != 0) {
      // Everything is fine. Send as normal.
      contender.UpdateStream(stream_id,
                             EventWithReceiverFromViewportTransform(
                                 event, /*destination=*/view_ref_koid, *view_tree_snapshot_),
                             is_end_of_stream,
                             view_tree_snapshot_->view_tree.at(view_ref_koid).bounding_box);
    } else if (contender_id == a11y_contender_id_) {
      // TODO(https://fxbug.dev/42127641): A11yLegacyContender doesn't need correct transforms or view bounds.
      // Remove this branch when legacy a11y api goes away.
      contender.UpdateStream(stream_id, event, is_end_of_stream, /*bounding_box=*/{});
    } else {
      // Contender not in the view tree -> cancel the rest of the stream for that contender.
      auto& arena = arena_it->second;
      if (!arena.contest_has_ended()) {
        // Contest ongoing -> just send a no response on behalf of |contender_id|.
        RecordGestureDisambiguationResponse(stream_id, contender_id, {GestureResponse::kNo});
        FX_DCHECK(gesture_arenas_.count(stream_id) == 0 || !arena.contains(contender_id));
      } else {
        // Contest ended -> Need to send an explicit "cancel" event to the contender.
        FX_DCHECK(arena.contenders().size() == 1 && arena.contains(contender_id));
        FX_DCHECK(event.phase != Phase::kAdd);
        InternalTouchEvent event_copy = event;
        event_copy.phase = Phase::kCancel;
        contender.UpdateStream(stream_id, event_copy, /*is_end_of_stream=*/true,
                               /*bounding_box=*/{});
        // The contest is definitely over, so we can manually destroy the arena here.
        gesture_arenas_.erase(stream_id);
        break;
      }
    }
  }

  DestroyArenaIfComplete(stream_id);
}

void TouchSystem::RecordGestureDisambiguationResponse(
    StreamId stream_id, ContenderId contender_id, const std::vector<GestureResponse>& responses) {
  auto arena_it = gesture_arenas_.find(stream_id);
  if (arena_it == gesture_arenas_.end() || !arena_it->second.contains(contender_id)) {
    return;
  }
  auto& arena = arena_it->second;

  // No need to record after the contest has ended.
  if (!arena.contest_has_ended()) {
    // Update the arena.
    const ContestResults result = arena.RecordResponses(contender_id, responses);
    for (auto loser_id : result.losers) {
      // Need to check for existence, since a loser could be the result of a NO response upon
      // destruction.
      auto contender = contenders_.find(loser_id);
      if (contender != contenders_.end()) {
        contenders_.at(loser_id)->EndContest(stream_id, /*awarded_win*/ false);
      }
    }
    if (result.winner) {
      FX_DCHECK(arena.contenders().size() == 1u);
      contenders_.at(result.winner.value())->EndContest(stream_id, /*awarded_win*/ true);
    }
  }

  DestroyArenaIfComplete(stream_id);
}

void TouchSystem::DestroyArenaIfComplete(StreamId stream_id) {
  const auto arena_it = gesture_arenas_.find(stream_id);
  if (arena_it == gesture_arenas_.end()) {
    return;
  }

  const auto& arena = arena_it->second;

  // This branch will eventually be taken for every arena.
  // TODO(https://fxbug.dev/42171409): can we elaborate on why this is true?
  if (arena.contenders().empty() || (arena.contest_has_ended() && arena.stream_has_ended())) {
    gesture_arenas_.erase(stream_id);
  }
}

void TouchSystem::EraseContender(ContenderId contender_id, zx_koid_t view_ref_koid) {
  {
    const size_t success = contenders_.erase(contender_id);
    FX_DCHECK(success) << "Contender " << contender_id << " did not exist";
  }
  // TODO(https://fxbug.dev/42142976): ZX_KOID_INVALID is only passed in by legacy contenders. Remove this
  // check when they go away.
  if (view_ref_koid != ZX_KOID_INVALID) {
    const size_t success = viewrefs_to_contender_ids_.erase(view_ref_koid);
    FX_DCHECK(success) << "ViewRef " << view_ref_koid << " was not mapped to a ContenderId";
  }

  // Remove from any contests it may still be a part of.
  // Note: Need to finish walking the arena map before we start calling RecordGDResponse() since
  // it may invalidate the iterator.
  std::vector<StreamId> ongoing_streams;
  for (const auto& [stream_id, arena] : gesture_arenas_) {
    const auto contenders = arena.contenders();
    if (std::count(contenders.begin(), contenders.end(), contender_id)) {
      ongoing_streams.push_back(stream_id);
    }
  }
  for (const auto stream_id : ongoing_streams) {
    RecordGestureDisambiguationResponse(stream_id, contender_id, {GestureResponse::kNo});
  }
}

}  // namespace scenic_impl::input
