// Copyright 2018 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/bin/app.h"

#include <fuchsia/stash/cpp/fidl.h>
#include <fuchsia/vulkan/loader/cpp/fidl.h>
#include <lib/syslog/cpp/macros.h>

#include <optional>

#include "lib/service/llcpp/service.h"
#include "rapidjson/document.h"
#include "src/lib/files/file.h"
#include "src/ui/lib/escher/vk/pipeline_builder.h"
#include "src/ui/scenic/lib/display/display_power_manager.h"
#include "src/ui/scenic/lib/flatland/engine/engine_types.h"
#include "src/ui/scenic/lib/flatland/renderer/vk_renderer.h"
#include "src/ui/scenic/lib/gfx/api/internal_snapshot_impl.h"
#include "src/ui/scenic/lib/gfx/gfx_system.h"
#include "src/ui/scenic/lib/scheduling/frame_metrics_registry.cb.h"
#include "src/ui/scenic/lib/scheduling/windowed_frame_predictor.h"
#include "src/ui/scenic/lib/screen_capture/screen_capture.h"
#include "src/ui/scenic/lib/screen_capture/screen_capture_buffer_collection_importer.h"
#include "src/ui/scenic/lib/utils/helpers.h"
#include "src/ui/scenic/lib/utils/metrics_impl.h"
#include "src/ui/scenic/lib/view_tree/snapshot_dump.h"

namespace {

// App installs the loader manifest FS at this path so it can use
// fsl::DeviceWatcher on it.
static const char* kDependencyPath = "/gpu-manifest-fs";

// Populates a ConfigValues struct by reading a config file and retrieving
// overrides from the stash.
scenic_impl::ConfigValues GetConfig(sys::ComponentContext* app_context) {
  scenic_impl::ConfigValues values;

  using GetValueCallback = std::function<void(const std::string&, fuchsia::stash::Value&)>;
  std::unordered_map<std::string, GetValueCallback> config{
      {
          "frame_scheduler_min_predicted_frame_duration_in_us",
          [&values](auto& key, auto& value) {
            FX_CHECK(value.is_intval()) << key << " must be an integer";
            FX_CHECK(value.intval() >= 0) << key << " must be greater than 0";
            values.min_predicted_frame_duration = zx::usec(value.intval());
          },
      },
      {
          "i_can_haz_flatland",
          [&values](auto& key, auto& value) {
            FX_CHECK(value.is_boolval()) << key << " must be a boolean";
            values.i_can_haz_flatland = value.boolval();
          },
      },
      {
          "enable_allocator_for_flatland",
          [&values](auto& key, auto& value) {
            FX_CHECK(value.is_boolval()) << key << " must be a boolean";
            values.enable_allocator_for_flatland = value.boolval();
          },
      },
      {
          "pointer_auto_focus",
          [&values](auto& key, auto& value) {
            FX_CHECK(value.is_boolval()) << key << " must be a boolean";
            values.pointer_auto_focus_on = value.boolval();
          },
      },
      {
          "flatland_buffer_collection_import_mode",
          [&values](auto& key, auto& value) {
            FX_CHECK(value.is_stringval()) << key << " must be a string";
            values.flatland_buffer_collection_import_mode =
                flatland::StringToBufferCollectionImportMode(value.stringval());
          },
      },
      {
          "i_can_haz_display_id",
          [&values](auto& key, auto& value) {
            FX_CHECK(value.is_intval()) << key << " must be an integer";
            values.i_can_haz_display_id = value.intval();
          },
      },
      {
          "i_can_haz_display_mode",
          [&values](auto& key, auto& value) {
            FX_CHECK(value.is_intval()) << key << " must be an integer";
            values.i_can_haz_display_mode = value.intval();
          },
      },
  };

  async::Loop stash_loop(&kAsyncLoopConfigNeverAttachToThread);
  fuchsia::stash::StorePtr store;
  fuchsia::stash::StoreAccessorPtr accessor;
  zx_status_t status = app_context->svc()->Connect(store.NewRequest(stash_loop.dispatcher()));
  if (status == ZX_OK) {
    store->Identify("stash_ctl");
    store->CreateAccessor(true, accessor.NewRequest(stash_loop.dispatcher()));
  } else {
    FX_LOGS(INFO) << "Unable to access /svc/" << fuchsia::stash::Store::Name_
                  << "; using only config file";
  }

  // Request all stash values asynchronously. We do this before reading the
  // config file so we hide the cost of the asynchronous requests behind the
  // synchronous filesystem server request.
  for (auto& [key, callback] : config) {
    accessor->GetValue(key, [&key = key, &callback = callback](auto value) {
      if (value) {
        callback(key, *value);
      };
    });
  }

  std::string config_string;
  if (files::ReadFileToString("/config/data/scenic_config", &config_string)) {
    FX_LOGS(INFO) << "Found config file at /config/data/scenic_config";
    rapidjson::Document document;
    document.Parse(config_string);
    for (auto& [key, callback] : config) {
      if (document.HasMember(key)) {
        auto& json_value = document[key];

        fuchsia::stash::Value value;
        if (json_value.IsInt()) {
          value = fuchsia::stash::Value::WithIntval(json_value.GetInt());
        } else if (json_value.IsBool()) {
          value = fuchsia::stash::Value::WithBoolval(json_value.GetBool());
        } else if (json_value.IsString()) {
          value = fuchsia::stash::Value::WithStringval(json_value.GetString());
        } else {
          FX_CHECK(false) << "Unsupported type for '" << key << "'";
        }
        callback(key, value);
      }
    }
  } else {
    FX_LOGS(INFO) << "No config file found at /config/data/scenic_config; using default values";
  }

  // Wait for each stash value to be returned. These should have arrived while
  // reading the config file.
  //
  // Note: The order of these operations means that the stash will override any
  // values set by the config file.
  for (auto& _ : config) {
    // Only run the loop if the accessor is still bound.
    if (!accessor) {
      break;
    }
    stash_loop.Run(zx::time::infinite(), /*once*/ true);
  }

  FX_LOGS(INFO) << "Scenic min_predicted_frame_duration(us): "
                << values.min_predicted_frame_duration.to_usecs();
  FX_LOGS(INFO) << "i_can_haz_flatland: " << values.i_can_haz_flatland;
  FX_LOGS(INFO) << "enable_allocator_for_flatland: " << values.enable_allocator_for_flatland;
  FX_LOGS(INFO) << "Scenic pointer auto focus: " << values.pointer_auto_focus_on;
  FX_LOGS(INFO) << "flatland_buffer_collection_import_mode: "
                << StringFromBufferCollectionImportMode(
                       values.flatland_buffer_collection_import_mode);
  FX_LOGS(INFO) << "Scenic i_can_haz_display_id: " << values.i_can_haz_display_id.value_or(0);
  FX_LOGS(INFO) << "Scenic i_can_haz_display_mode: " << values.i_can_haz_display_mode.value_or(0);

  return values;
}

}  // namespace

namespace scenic_impl {

DisplayInfoDelegate::DisplayInfoDelegate(std::shared_ptr<display::Display> display_)
    : display_(display_) {
  FX_CHECK(display_);
}

void DisplayInfoDelegate::GetDisplayInfo(
    fuchsia::ui::scenic::Scenic::GetDisplayInfoCallback callback) {
  auto info = ::fuchsia::ui::gfx::DisplayInfo();
  info.width_in_px = display_->width_in_px();
  info.height_in_px = display_->height_in_px();

  callback(std::move(info));
}

void DisplayInfoDelegate::GetDisplayOwnershipEvent(
    fuchsia::ui::scenic::Scenic::GetDisplayOwnershipEventCallback callback) {
  // These constants are defined as raw hex in the FIDL file, so we confirm here that they are the
  // same values as the expected constants in the ZX headers.
  static_assert(fuchsia::ui::scenic::displayNotOwnedSignal == ZX_USER_SIGNAL_0, "Bad constant");
  static_assert(fuchsia::ui::scenic::displayOwnedSignal == ZX_USER_SIGNAL_1, "Bad constant");

  zx::event dup;
  if (display_->ownership_event().duplicate(ZX_RIGHTS_BASIC, &dup) != ZX_OK) {
    FX_LOGS(ERROR) << "Display ownership event duplication error.";
    callback(zx::event());
  } else {
    callback(std::move(dup));
  }
}

App::App(std::unique_ptr<sys::ComponentContext> app_context, inspect::Node inspect_node,
         fpromise::promise<ui_display::DisplayControllerHandles> dc_handles_promise,
         fit::closure quit_callback)
    : executor_(async_get_default_dispatcher()),
      app_context_(std::move(app_context)),
      config_values_(GetConfig(app_context_.get())),
      // TODO(fxbug.dev/40997): subsystems requiring graceful shutdown *on a loop* should register
      // themselves. It is preferable to cleanly shutdown using destructors only, if possible.
      shutdown_manager_(
          ShutdownManager::New(async_get_default_dispatcher(), std::move(quit_callback))),
      metrics_logger_(
          async_get_default_dispatcher(),
          fidl::ClientEnd<fuchsia_io::Directory>(service::OpenServiceRoot()->TakeChannel())),
      scenic_(std::make_shared<Scenic>(
          app_context_.get(), std::move(inspect_node),
          [weak = std::weak_ptr<ShutdownManager>(shutdown_manager_)] {
            if (auto strong = weak.lock()) {
              strong->Shutdown(LifecycleControllerImpl::kShutdownTimeout);
            }
          },
          config_values_.i_can_haz_flatland)),
      uber_struct_system_(std::make_shared<flatland::UberStructSystem>()),
      link_system_(
          std::make_shared<flatland::LinkSystem>(uber_struct_system_->GetNextInstanceId())),
      flatland_presenter_(
          std::make_shared<flatland::DefaultFlatlandPresenter>(async_get_default_dispatcher())),
      annotation_registry_(app_context_.get()),
      lifecycle_controller_impl_(app_context_.get(),
                                 std::weak_ptr<ShutdownManager>(shutdown_manager_)) {
  FX_DCHECK(!device_watcher_);

  fpromise::bridge<escher::EscherUniquePtr> escher_bridge;
  fpromise::bridge<std::shared_ptr<display::Display>> display_bridge;

  auto vulkan_loader = app_context_->svc()->Connect<fuchsia::vulkan::loader::Loader>();
  fidl::InterfaceHandle<fuchsia::io::Directory> dir;
  vulkan_loader->ConnectToManifestFs(fuchsia::vulkan::loader::ConnectToManifestOptions{},
                                     dir.NewRequest().TakeChannel());

  fdio_ns_t* ns;
  zx_status_t status = fdio_ns_get_installed(&ns);
  FX_DCHECK(status == ZX_OK);
  status = fdio_ns_bind(ns, kDependencyPath, dir.TakeChannel().release());
  FX_DCHECK(status == ZX_OK);

  view_ref_installed_impl_.Publish(app_context_.get());

  // Wait for a Vulkan ICD to become advertised before trying to launch escher.
  device_watcher_ = fsl::DeviceWatcher::Create(
      kDependencyPath,
      [this, vulkan_loader = std::move(vulkan_loader),
       completer = std::move(escher_bridge.completer)](int dir_fd, std::string filename) mutable {
        auto escher = gfx::GfxSystem::CreateEscher(app_context_.get());
        if (!escher) {
          FX_LOGS(WARNING) << "Escher creation failed.";
          // This should almost never happen, but might if the device was removed quickly after it
          // was added or if the Vulkan driver doesn't actually work on this hardware. Retry when a
          // new device is added.
          return;
        }
        completer.complete_ok(std::move(escher));
        device_watcher_.reset();
      });

  FX_DCHECK(device_watcher_);

  // Instantiate DisplayManager and schedule a task to inject the display controller into it, once
  // it becomes available.
  display_manager_ = std::make_unique<display::DisplayManager>(
      config_values_.i_can_haz_display_id, config_values_.i_can_haz_display_mode,
      [this, completer = std::move(display_bridge.completer)]() mutable {
        completer.complete_ok(display_manager_->default_display_shared());
      });
  executor_.schedule_task(dc_handles_promise.then(
      [this](fpromise::result<ui_display::DisplayControllerHandles>& handles) {
        display_manager_->BindDefaultDisplayController(std::move(handles.value().controller),
                                                       std::move(handles.value().dc_device));
      }));

  // Schedule a task to finish initialization once all promises have been completed.
  // This closure is placed on |executor_|, which is owned by App, so it is safe to use |this|.
  auto p =
      fpromise::join_promises(escher_bridge.consumer.promise(), display_bridge.consumer.promise())
          .and_then(
              [this](std::tuple<fpromise::result<escher::EscherUniquePtr>,
                                fpromise::result<std::shared_ptr<display::Display>>>& results) {
                InitializeServices(std::move(std::get<0>(results).value()),
                                   std::move(std::get<1>(results).value()));
                // Should be run after all outgoing services are published.
                app_context_->outgoing()->ServeFromStartupInfo();
              });

  executor_.schedule_task(std::move(p));

#ifdef NDEBUG
  // TODO(fxbug.dev/48596): Scenic sometimes gets stuck for consecutive 60 seconds.
  // Here we set up a Watchdog polling Scenic status every 15 seconds.
  constexpr uint32_t kWatchdogWarningIntervalMs = 15000u;
  // On some devices, the time to start up Scenic may exceed 15 seconds.
  // In that case we should only send a warning, and we should only crash
  // Scenic if the main thread is blocked for longer time.
  constexpr uint32_t kWatchdogTimeoutMs = 45000u;

#else  // !defined(NDEBUG)
  // We set a higher warning interval and timeout length for debug builds,
  // since these builds could be slower than the default release ones.
  constexpr uint32_t kWatchdogWarningIntervalMs = 30000u;
  constexpr uint32_t kWatchdogTimeoutMs = 90000u;

#endif  // NDEBUG

  watchdog_ = std::make_unique<async_watchdog::Watchdog>(
      "Scenic main thread", kWatchdogWarningIntervalMs, kWatchdogTimeoutMs,
      async_get_default_dispatcher());
}

void App::InitializeServices(escher::EscherUniquePtr escher,
                             std::shared_ptr<display::Display> display) {
  TRACE_DURATION("gfx", "App::InitializeServices");

  if (!display) {
    FX_LOGS(ERROR) << "No default display, Graphics system exiting";
    shutdown_manager_->Shutdown(LifecycleControllerImpl::kShutdownTimeout);
    return;
  }

  if (!escher || !escher->device()) {
    FX_LOGS(ERROR) << "No Vulkan on device, Graphics system exiting.";
    shutdown_manager_->Shutdown(LifecycleControllerImpl::kShutdownTimeout);
    return;
  }

  escher_ = std::move(escher);

  CreateFrameScheduler(display->vsync_timing());
  InitializeGraphics(display);
  InitializeInput();
  InitializeHeartbeat();
}

App::~App() {
  fdio_ns_t* ns;
  zx_status_t status = fdio_ns_get_installed(&ns);
  FX_DCHECK(status == ZX_OK);
  status = fdio_ns_unbind(ns, kDependencyPath);
  FX_DCHECK(status == ZX_OK);
}

void App::CreateFrameScheduler(std::shared_ptr<const scheduling::VsyncTiming> vsync_timing) {
  TRACE_DURATION("gfx", "App::CreateFrameScheduler");
  frame_scheduler_ = std::make_shared<scheduling::DefaultFrameScheduler>(
      std::move(vsync_timing),
      std::make_unique<scheduling::WindowedFramePredictor>(
          config_values_.min_predicted_frame_duration,
          scheduling::DefaultFrameScheduler::kInitialRenderDuration,
          scheduling::DefaultFrameScheduler::kInitialUpdateDuration),
      scenic_->inspect_node()->CreateChild("FrameScheduler"), &metrics_logger_);
}

void App::InitializeGraphics(std::shared_ptr<display::Display> display) {
  TRACE_DURATION("gfx", "App::InitializeGraphics");
  FX_LOGS(INFO) << "App::InitializeGraphics() " << display->width_in_px() << "x"
                << display->height_in_px() << "px  " << display->width_in_mm() << "x"
                << display->height_in_mm() << "mm";

  // Replace Escher's default pipeline builder with one which will log to Cobalt upon each
  // unexpected lazy pipeline creation.  This allows us to detect when this slips through our
  // testing and occurs in the wild.  In order to detect problems ASAP during development, debug
  // builds CHECK instead of logging to Cobalt.
  {
    auto pipeline_builder = std::make_unique<escher::PipelineBuilder>(escher_->vk_device());
    pipeline_builder->set_log_pipeline_creation_callback(
        [metrics_logger = &metrics_logger_](const vk::GraphicsPipelineCreateInfo* graphics_info,
                                            const vk::ComputePipelineCreateInfo* compute_info) {
          // TODO(fxbug.dev/49972): pre-warm compute pipelines in addition to graphics pipelines.
          if (compute_info) {
            FX_LOGS(WARNING) << "Unexpected lazy creation of Vulkan compute pipeline.";
            return;
          }

#if !defined(NDEBUG)
          FX_CHECK(false)  // debug builds should crash for early detection
#else
          FX_LOGS(WARNING)  // release builds should log to Cobalt, see below.
#endif
              << "Unexpected lazy creation of Vulkan pipeline.";

          metrics_logger->LogRareEvent(
              cobalt_registry::ScenicRareEventMigratedMetricDimensionEvent::LazyPipelineCreation);
        });
    escher_->set_pipeline_builder(std::move(pipeline_builder));
  }

  auto gfx_buffer_collection_importer =
      std::make_shared<gfx::GfxBufferCollectionImporter>(escher_->GetWeakPtr());
  {
    TRACE_DURATION("gfx", "App::InitializeServices[engine]");
    engine_ = std::make_shared<gfx::Engine>(escher_->GetWeakPtr(), gfx_buffer_collection_importer,
                                            scenic_->inspect_node()->CreateChild("Engine"));
  }

  scenic_->SetFrameScheduler(frame_scheduler_);
  annotation_registry_.InitializeWithGfxAnnotationManager(engine_->annotation_manager());

  image_pipe_updater_ = std::make_shared<gfx::ImagePipeUpdater>(frame_scheduler_);
  auto gfx = scenic_->RegisterSystem<gfx::GfxSystem>(engine_.get(), &sysmem_,
                                                     display_manager_.get(), image_pipe_updater_);
  FX_DCHECK(gfx);

  scenic_->SetScreenshotDelegate(gfx.get());
  singleton_display_service_ = std::make_unique<display::SingletonDisplayService>(display);
  singleton_display_service_->AddPublicService(scenic_->app_context()->outgoing().get());
  display_info_delegate_ = std::make_unique<DisplayInfoDelegate>(display);
  scenic_->SetDisplayInfoDelegate(display_info_delegate_.get());

  flatland_presenter_->SetFrameScheduler(frame_scheduler_);

  // Create the snapshotter and pass it to scenic.
  auto snapshotter =
      std::make_unique<gfx::InternalSnapshotImpl>(engine_->scene_graph(), escher_->GetWeakPtr());
  scenic_->InitializeSnapshotService(std::move(snapshotter));
  scenic_->SetRegisterViewFocuser(
      [this](zx_koid_t view_ref_koid, fidl::InterfaceRequest<fuchsia::ui::views::Focuser> focuser) {
        focus_manager_->RegisterViewFocuser(view_ref_koid, std::move(focuser));
      });
  auto flatland_renderer = std::make_shared<flatland::VkRenderer>(escher_->GetWeakPtr());

  // Flatland compositor must be made first; it is needed by the manager and the engine.
  {
    TRACE_DURATION("gfx", "App::InitializeServices[flatland_display_compositor]");

    flatland_compositor_ = std::make_shared<flatland::DisplayCompositor>(
        async_get_default_dispatcher(), display_manager_->default_display_controller(),
        flatland_renderer, utils::CreateSysmemAllocatorSyncPtr("flatland::DisplayCompositor"),
        config_values_.flatland_buffer_collection_import_mode);
  }

  // Flatland manager depends on compositor, and is required by engine.
  {
    TRACE_DURATION("gfx", "App::InitializeServices[flatland_manager]");

    std::vector<std::shared_ptr<allocation::BufferCollectionImporter>> importers{
        flatland_compositor_};

    flatland_manager_ = std::make_shared<flatland::FlatlandManager>(
        async_get_default_dispatcher(), flatland_presenter_, uber_struct_system_, link_system_,
        display, std::move(importers),
        /*register_view_focuser*/
        [this](fidl::InterfaceRequest<fuchsia::ui::views::Focuser> focuser,
               zx_koid_t view_ref_koid) {
          focus_manager_->RegisterViewFocuser(view_ref_koid, std::move(focuser));
        },
        /*register_view_ref_focused*/
        [this](fidl::InterfaceRequest<fuchsia::ui::views::ViewRefFocused> vrf,
               zx_koid_t view_ref_koid) {
          focus_manager_->RegisterViewRefFocused(view_ref_koid, std::move(vrf));
        },
        /*register_touch_source*/
        [this](fidl::InterfaceRequest<fuchsia::ui::pointer::TouchSource> touch_source,
               zx_koid_t view_ref_koid) {
          input_->RegisterTouchSource(std::move(touch_source), view_ref_koid);
        },
        /*register_mouse_source*/
        [this](fidl::InterfaceRequest<fuchsia::ui::pointer::MouseSource> mouse_source,
               zx_koid_t view_ref_koid) {
          input_->RegisterMouseSource(std::move(mouse_source), view_ref_koid);
        });

    // TODO(fxbug.dev/67206): these should be moved into FlatlandManager.
    {
      fit::function<void(fidl::InterfaceRequest<fuchsia::ui::composition::Flatland>)> handler =
          fit::bind_member(flatland_manager_.get(), &flatland::FlatlandManager::CreateFlatland);
      zx_status_t status = app_context_->outgoing()->AddPublicService(std::move(handler));
      FX_DCHECK(status == ZX_OK);
    }
    {
      fit::function<void(fidl::InterfaceRequest<fuchsia::ui::composition::FlatlandDisplay>)>
          handler = fit::bind_member(flatland_manager_.get(),
                                     &flatland::FlatlandManager::CreateFlatlandDisplay);
      zx_status_t status = app_context_->outgoing()->AddPublicService(std::move(handler));
      FX_DCHECK(status == ZX_OK);
    }
  }

  auto screen_capture_buffer_collection_importer =
      std::make_shared<screen_capture::ScreenCaptureBufferCollectionImporter>(flatland_renderer);

  // Allocator service needs Flatland DisplayCompositor to act as a BufferCollectionImporter.
  {
    std::vector<std::shared_ptr<allocation::BufferCollectionImporter>> default_importers;
    std::vector<std::shared_ptr<allocation::BufferCollectionImporter>> screen_capture_importers;
    default_importers.push_back(gfx_buffer_collection_importer);
    screen_capture_importers.push_back(screen_capture_buffer_collection_importer);

    if (config_values_.enable_allocator_for_flatland && flatland_compositor_)
      default_importers.push_back(flatland_compositor_);

    allocator_ = std::make_shared<allocation::Allocator>(
        app_context_.get(), default_importers, screen_capture_importers,
        utils::CreateSysmemAllocatorSyncPtr("ScenicAllocator"));
  }

  // Flatland engine requires FlatlandManager and DisplayCompositor to be constructed first.
  {
    TRACE_DURATION("gfx", "App::InitializeServices[flatland_engine]");

    flatland_engine_ = std::make_shared<flatland::Engine>(
        flatland_compositor_, flatland_presenter_, uber_struct_system_, link_system_,
        scenic_->inspect_node()->CreateChild("FlatlandEngine"), [this] {
          FX_DCHECK(flatland_manager_);
          const auto display = flatland_manager_->GetPrimaryFlatlandDisplayForRendering();
          return display ? std::optional<flatland::TransformHandle>(display->root_transform())
                         : std::nullopt;
        });

    fit::function<void(fidl::InterfaceRequest<fuchsia::ui::display::color::Converter>)> handler =
        fit::bind_member(flatland_engine_.get(), &flatland::Engine::SetColorConversionInterface);
    zx_status_t status = app_context_->outgoing()->AddPublicService(std::move(handler));
    FX_DCHECK(status == ZX_OK);

    frame_renderer_ = std::make_shared<TemporaryFrameRendererDelegator>(flatland_manager_,
                                                                        flatland_engine_, engine_);
  }

  // Make ScreenCaptureManager.
  {
    TRACE_DURATION("gfx", "App::InitializeServices[screen_capture_manager]");

    std::vector<std::shared_ptr<allocation::BufferCollectionImporter>> importers;
    importers.push_back(screen_capture_buffer_collection_importer);

    // Capture flatland_manager since the primary display may not have been initialized yet.
    screen_capture_manager_ = std::make_unique<screen_capture::ScreenCaptureManager>(
        flatland_engine_, flatland_renderer, flatland_manager_, std::move(importers));

    fit::function<void(fidl::InterfaceRequest<fuchsia::ui::composition::ScreenCapture>)> handler =
        fit::bind_member(screen_capture_manager_.get(),
                         &screen_capture::ScreenCaptureManager::CreateClient);
    zx_status_t status = app_context_->outgoing()->AddPublicService(std::move(handler));
    FX_DCHECK(status == ZX_OK);
  }

  {
    TRACE_DURATION("gfx", "App::InitializeServices[display_power]");
    display_power_manager_ = std::make_unique<display::DisplayPowerManager>(display_manager_.get());
    zx_status_t status =
        app_context_->outgoing()->AddPublicService(display_power_manager_->GetHandler());
    FX_DCHECK(status == ZX_OK);
  }

  geometry_provider_manager_ = std::make_shared<view_tree::GeometryProviderManager>();

  observer_registry_ = std::make_unique<view_tree::Registry>(geometry_provider_manager_);
  observer_registry_->Publish(app_context_.get());
}

void App::InitializeInput() {
  TRACE_DURATION("gfx", "App::InitializeInput");
  input_ = scenic_->RegisterSystem<input::InputSystem>(
      engine_->scene_graph(),
      /*request_focus*/ [this,
                         use_auto_focus = config_values_.pointer_auto_focus_on](zx_koid_t koid) {
        if (!use_auto_focus)
          return;

        const auto& focus_chain = focus_manager_->focus_chain();
        if (!focus_chain.empty()) {
          const zx_koid_t requestor = focus_chain[0];
          const zx_koid_t request = koid != ZX_KOID_INVALID ? koid : requestor;
          focus_manager_->RequestFocus(requestor, request);
        }
      });
  FX_DCHECK(input_);
  scenic_->SetRegisterTouchSource(
      [this](fidl::InterfaceRequest<fuchsia::ui::pointer::TouchSource> touch_source,
             zx_koid_t vrf) { input_->RegisterTouchSource(std::move(touch_source), vrf); });
  scenic_->SetRegisterMouseSource(
      [this](fidl::InterfaceRequest<fuchsia::ui::pointer::MouseSource> mouse_source,
             zx_koid_t vrf) { input_->RegisterMouseSource(std::move(mouse_source), vrf); });

  focus_manager_ = std::make_unique<focus::FocusManager>(
      scenic_->inspect_node()->CreateChild("FocusManager"),
      /*legacy_focus_listener*/ [this](zx_koid_t old_focus, zx_koid_t new_focus) {
        engine_->scene_graph()->OnNewFocusedView(old_focus, new_focus);
      });
  scenic_->SetViewRefFocusedRegisterFunction(
      [this](zx_koid_t koid, fidl::InterfaceRequest<fuchsia::ui::views::ViewRefFocused> vrf) {
        focus_manager_->RegisterViewRefFocused(koid, std::move(vrf));
      });
  focus_manager_->Publish(*app_context_);
}

void App::InitializeHeartbeat() {
  TRACE_DURATION("gfx", "App::InitializeHeartbeat");
  {  // Initialize ViewTreeSnapshotter

    // These callbacks are be called once per frame (at the end of OnCpuWorkDone()) and the results
    // used to build the ViewTreeSnapshot.
    // We create one per compositor.
    std::vector<view_tree::SubtreeSnapshotGenerator> subtrees_generator_callbacks;
    subtrees_generator_callbacks.emplace_back([this] {
      if (auto display = flatland_manager_->GetPrimaryFlatlandDisplayForRendering()) {
        return flatland_engine_->GenerateViewTreeSnapshot(display->root_transform());
      } else {
        return view_tree::SubtreeSnapshot{};  // Empty snapshot.
      }
    });
    // The i_can_haz_flatland flag is about eager-forcing of Flatland.
    // If true, then we KNOW that GFX should *not* run. Workstation is true.
    // if false, then either system could legitimately run. This flag is false for tests and
    // GFX-based products.
    if (!config_values_.i_can_haz_flatland) {
      subtrees_generator_callbacks.emplace_back(
          [this] { return engine_->scene_graph()->view_tree().Snapshot(); });
    }

    // All subscriber callbacks get called with the new snapshot every time one is generated (once
    // per frame).
    std::vector<view_tree::ViewTreeSnapshotter::Subscriber> subscribers;
    subscribers.push_back(
        {.on_new_view_tree =
             [this](auto snapshot) { input_->OnNewViewTreeSnapshot(std::move(snapshot)); },
         .dispatcher = async_get_default_dispatcher()});

    subscribers.push_back(
        {.on_new_view_tree =
             [this](auto snapshot) { focus_manager_->OnNewViewTreeSnapshot(std::move(snapshot)); },
         .dispatcher = async_get_default_dispatcher()});

    subscribers.push_back({.on_new_view_tree =
                               [this](auto snapshot) {
                                 view_ref_installed_impl_.OnNewViewTreeSnapshot(
                                     std::move(snapshot));
                               },
                           .dispatcher = async_get_default_dispatcher()});

    subscribers.push_back({.on_new_view_tree =
                               [this](auto snapshot) {
                                 geometry_provider_manager_->OnNewViewTreeSnapshot(
                                     std::move(snapshot));
                               },
                           .dispatcher = async_get_default_dispatcher()});

    if (enable_snapshot_dump_) {
      subscribers.push_back({.on_new_view_tree =
                                 [](auto snapshot) {
                                   view_tree::SnapshotDump::OnNewViewTreeSnapshot(
                                       std::move(snapshot));
                                 },
                             .dispatcher = async_get_default_dispatcher()});
    }

    view_tree_snapshotter_ = std::make_shared<view_tree::ViewTreeSnapshotter>(
        std::move(subtrees_generator_callbacks), std::move(subscribers));
  }

  // |session_updaters| will be updated in submission order.
  frame_scheduler_->Initialize(
      /*frame_renderer*/ frame_renderer_,
      /*session_updaters*/ {scenic_, image_pipe_updater_, flatland_manager_, flatland_presenter_,
                            view_tree_snapshotter_});
}

}  // namespace scenic_impl
