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

#define RAPIDJSON_HAS_STDSTRING 1
#include "flutter/shell/common/shell.h"

#include <memory>
#include <sstream>
#include <utility>
#include <vector>

#include "flutter/assets/directory_asset_bundle.h"
#include "flutter/common/constants.h"
#include "flutter/common/graphics/persistent_cache.h"
#include "flutter/fml/base32.h"
#include "flutter/fml/file.h"
#include "flutter/fml/icu_util.h"
#include "flutter/fml/log_settings.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/message_loop.h"
#include "flutter/fml/paths.h"
#include "flutter/fml/trace_event.h"
#include "flutter/runtime/dart_vm.h"
#include "flutter/shell/common/base64.h"
#include "flutter/shell/common/engine.h"
#include "flutter/shell/common/skia_event_tracer_impl.h"
#include "flutter/shell/common/switches.h"
#include "flutter/shell/common/vsync_waiter.h"
#include "impeller/runtime_stage/runtime_stage.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include "third_party/dart/runtime/include/dart_tools_api.h"
#include "third_party/skia/include/codec/SkBmpDecoder.h"
#include "third_party/skia/include/codec/SkCodec.h"
#include "third_party/skia/include/codec/SkGifDecoder.h"
#include "third_party/skia/include/codec/SkIcoDecoder.h"
#include "third_party/skia/include/codec/SkJpegDecoder.h"
#include "third_party/skia/include/codec/SkPngDecoder.h"
#include "third_party/skia/include/codec/SkWbmpDecoder.h"
#include "third_party/skia/include/codec/SkWebpDecoder.h"
#include "third_party/skia/include/core/SkGraphics.h"
#include "third_party/tonic/common/log.h"

namespace flutter {

constexpr char kSkiaChannel[] = "flutter/skia";
constexpr char kSystemChannel[] = "flutter/system";
constexpr char kTypeKey[] = "type";
constexpr char kFontChange[] = "fontsChange";

namespace {

std::unique_ptr<Engine> CreateEngine(
    Engine::Delegate& delegate,
    const PointerDataDispatcherMaker& dispatcher_maker,
    DartVM& vm,
    const fml::RefPtr<const DartSnapshot>& isolate_snapshot,
    const TaskRunners& task_runners,
    const PlatformData& platform_data,
    const Settings& settings,
    std::unique_ptr<Animator> animator,
    const fml::WeakPtr<IOManager>& io_manager,
    const fml::RefPtr<SkiaUnrefQueue>& unref_queue,
    const fml::TaskRunnerAffineWeakPtr<SnapshotDelegate>& snapshot_delegate,
    const std::shared_ptr<VolatilePathTracker>& volatile_path_tracker,
    const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch,
    impeller::RuntimeStageBackend runtime_stage_backend) {
  return std::make_unique<Engine>(delegate,               //
                                  dispatcher_maker,       //
                                  vm,                     //
                                  isolate_snapshot,       //
                                  task_runners,           //
                                  platform_data,          //
                                  settings,               //
                                  std::move(animator),    //
                                  io_manager,             //
                                  unref_queue,            //
                                  snapshot_delegate,      //
                                  volatile_path_tracker,  //
                                  gpu_disabled_switch,    //
                                  runtime_stage_backend);
}

void RegisterCodecsWithSkia() {
  // These are in the order they will be attempted to be decoded from.
  // If we have data to back it up, we can order these by "frequency used in
  // the wild" for a very small performance bump, but for now we mirror the
  // order Skia had them in.
  SkCodecs::Register(SkPngDecoder::Decoder());
  SkCodecs::Register(SkJpegDecoder::Decoder());
  SkCodecs::Register(SkWebpDecoder::Decoder());
  SkCodecs::Register(SkGifDecoder::Decoder());
  SkCodecs::Register(SkBmpDecoder::Decoder());
  SkCodecs::Register(SkWbmpDecoder::Decoder());
  SkCodecs::Register(SkIcoDecoder::Decoder());
}

// Though there can be multiple shells, some settings apply to all components in
// the process. These have to be set up before the shell or any of its
// sub-components can be initialized. In a perfect world, this would be empty.
// TODO(chinmaygarde): The unfortunate side effect of this call is that settings
// that cause shell initialization failures will still lead to some of their
// settings being applied.
void PerformInitializationTasks(Settings& settings) {
  {
    fml::LogSettings log_settings;
    log_settings.min_log_level =
        settings.verbose_logging ? fml::kLogInfo : fml::kLogError;
    fml::SetLogSettings(log_settings);
  }

  static std::once_flag gShellSettingsInitialization = {};
  std::call_once(gShellSettingsInitialization, [&settings] {
    tonic::SetLogHandler(
        [](const char* message) { FML_LOG(ERROR) << message; });

    if (settings.trace_skia) {
      InitSkiaEventTracer(settings.trace_skia, settings.trace_skia_allowlist);
    }

    if (!settings.trace_allowlist.empty()) {
      fml::tracing::TraceSetAllowlist(settings.trace_allowlist);
    }

    if (!settings.skia_deterministic_rendering_on_cpu) {
      SkGraphics::Init();
    } else {
      FML_DLOG(INFO) << "Skia deterministic rendering is enabled.";
    }
    RegisterCodecsWithSkia();

    if (settings.icu_initialization_required) {
      if (!settings.icu_data_path.empty()) {
        fml::icu::InitializeICU(settings.icu_data_path);
      } else if (settings.icu_mapper) {
        fml::icu::InitializeICUFromMapping(settings.icu_mapper());
      } else {
        FML_DLOG(WARNING) << "Skipping ICU initialization in the shell.";
      }
    }
  });

#if !SLIMPELLER
  PersistentCache::SetCacheSkSL(settings.cache_sksl);
#endif  //  !SLIMPELLER
}

}  // namespace

std::pair<DartVMRef, fml::RefPtr<const DartSnapshot>>
Shell::InferVmInitDataFromSettings(Settings& settings) {
  // Always use the `vm_snapshot` and `isolate_snapshot` provided by the
  // settings to launch the VM.  If the VM is already running, the snapshot
  // arguments are ignored.
  auto vm_snapshot = DartSnapshot::VMSnapshotFromSettings(settings);
  auto isolate_snapshot = DartSnapshot::IsolateSnapshotFromSettings(settings);
  auto vm = DartVMRef::Create(settings, vm_snapshot, isolate_snapshot);

  // If the settings did not specify an `isolate_snapshot`, fall back to the
  // one the VM was launched with.
  if (!isolate_snapshot) {
    isolate_snapshot = vm->GetVMData()->GetIsolateSnapshot();
  }
  return {std::move(vm), isolate_snapshot};
}

std::unique_ptr<Shell> Shell::Create(
    const PlatformData& platform_data,
    const TaskRunners& task_runners,
    Settings settings,
    const Shell::CreateCallback<PlatformView>& on_create_platform_view,
    const Shell::CreateCallback<Rasterizer>& on_create_rasterizer,
    bool is_gpu_disabled) {
  // This must come first as it initializes tracing.
  PerformInitializationTasks(settings);

  TRACE_EVENT0("flutter", "Shell::Create");

  auto [vm, isolate_snapshot] = InferVmInitDataFromSettings(settings);
  auto resource_cache_limit_calculator =
      std::make_shared<ResourceCacheLimitCalculator>(
          settings.resource_cache_max_bytes_threshold);

  return CreateWithSnapshot(platform_data,                     //
                            task_runners,                      //
                            /*parent_thread_merger=*/nullptr,  //
                            /*parent_io_manager=*/nullptr,     //
                            resource_cache_limit_calculator,   //
                            settings,                          //
                            std::move(vm),                     //
                            std::move(isolate_snapshot),       //
                            on_create_platform_view,           //
                            on_create_rasterizer,              //
                            CreateEngine, is_gpu_disabled);
}

static impeller::RuntimeStageBackend DetermineRuntimeStageBackend(
    const std::shared_ptr<impeller::Context>& impeller_context) {
  if (!impeller_context) {
    return impeller::RuntimeStageBackend::kSkSL;
  }
  switch (impeller_context->GetBackendType()) {
    case impeller::Context::BackendType::kMetal:
      return impeller::RuntimeStageBackend::kMetal;
    case impeller::Context::BackendType::kOpenGLES:
      return impeller::RuntimeStageBackend::kOpenGLES;
    case impeller::Context::BackendType::kVulkan:
      return impeller::RuntimeStageBackend::kVulkan;
  }
}

std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
    DartVMRef vm,
    fml::RefPtr<fml::RasterThreadMerger> parent_merger,
    std::shared_ptr<ShellIOManager> parent_io_manager,
    const std::shared_ptr<ResourceCacheLimitCalculator>&
        resource_cache_limit_calculator,
    const TaskRunners& task_runners,
    const PlatformData& platform_data,
    const Settings& settings,
    fml::RefPtr<const DartSnapshot> isolate_snapshot,
    const Shell::CreateCallback<PlatformView>& on_create_platform_view,
    const Shell::CreateCallback<Rasterizer>& on_create_rasterizer,
    const Shell::EngineCreateCallback& on_create_engine,
    bool is_gpu_disabled) {
  if (!task_runners.IsValid()) {
    FML_LOG(ERROR) << "Task runners to run the shell were invalid.";
    return nullptr;
  }

  auto shell = std::unique_ptr<Shell>(
      new Shell(std::move(vm), task_runners, std::move(parent_merger),
                resource_cache_limit_calculator, settings,
                std::make_shared<VolatilePathTracker>(
                    task_runners.GetUITaskRunner(),
                    !settings.skia_deterministic_rendering_on_cpu),
                is_gpu_disabled));

  // Create the platform view on the platform thread (this thread).
  auto platform_view = on_create_platform_view(*shell.get());
  if (!platform_view || !platform_view->GetWeakPtr()) {
    return nullptr;
  }

  // Create the rasterizer on the raster thread.
  std::promise<std::unique_ptr<Rasterizer>> rasterizer_promise;
  auto rasterizer_future = rasterizer_promise.get_future();
  std::promise<fml::TaskRunnerAffineWeakPtr<SnapshotDelegate>>
      snapshot_delegate_promise;
  auto snapshot_delegate_future = snapshot_delegate_promise.get_future();
  fml::TaskRunner::RunNowOrPostTask(
      task_runners.GetRasterTaskRunner(),
      [&rasterizer_promise,  //
       &snapshot_delegate_promise,
       on_create_rasterizer,                                   //
       shell = shell.get(),                                    //
       impeller_context = platform_view->GetImpellerContext()  //
  ]() {
        TRACE_EVENT0("flutter", "ShellSetupGPUSubsystem");
        std::unique_ptr<Rasterizer> rasterizer(on_create_rasterizer(*shell));
        rasterizer->SetImpellerContext(impeller_context);
        snapshot_delegate_promise.set_value(rasterizer->GetSnapshotDelegate());
        rasterizer_promise.set_value(std::move(rasterizer));
      });

  // Ask the platform view for the vsync waiter. This will be used by the engine
  // to create the animator.
  auto vsync_waiter = platform_view->CreateVSyncWaiter();
  if (!vsync_waiter) {
    return nullptr;
  }

  // Create the IO manager on the IO thread. The IO manager must be initialized
  // first because it has state that the other subsystems depend on. It must
  // first be booted and the necessary references obtained to initialize the
  // other subsystems.
  std::promise<std::shared_ptr<ShellIOManager>> io_manager_promise;
  auto io_manager_future = io_manager_promise.get_future();
  std::promise<fml::WeakPtr<ShellIOManager>> weak_io_manager_promise;
  auto weak_io_manager_future = weak_io_manager_promise.get_future();
  std::promise<fml::RefPtr<SkiaUnrefQueue>> unref_queue_promise;
  auto unref_queue_future = unref_queue_promise.get_future();
  auto io_task_runner = shell->GetTaskRunners().GetIOTaskRunner();

  // The platform_view will be stored into shell's platform_view_ in
  // shell->Setup(std::move(platform_view), ...) at the end.
  PlatformView* platform_view_ptr = platform_view.get();
  fml::TaskRunner::RunNowOrPostTask(
      io_task_runner,
      [&io_manager_promise,                                               //
       &weak_io_manager_promise,                                          //
       &parent_io_manager,                                                //
       &unref_queue_promise,                                              //
       platform_view_ptr,                                                 //
       io_task_runner,                                                    //
       is_backgrounded_sync_switch = shell->GetIsGpuDisabledSyncSwitch()  //
  ]() {
        TRACE_EVENT0("flutter", "ShellSetupIOSubsystem");
        std::shared_ptr<ShellIOManager> io_manager;
        if (parent_io_manager) {
          io_manager = parent_io_manager;
        } else {
          io_manager = std::make_shared<ShellIOManager>(
              platform_view_ptr->CreateResourceContext(),  // resource context
              is_backgrounded_sync_switch,                 // sync switch
              io_task_runner,  // unref queue task runner
              platform_view_ptr->GetImpellerContext()  // impeller context
          );
        }
        weak_io_manager_promise.set_value(io_manager->GetWeakPtr());
        unref_queue_promise.set_value(io_manager->GetSkiaUnrefQueue());
        io_manager_promise.set_value(io_manager);
      });

  // Send dispatcher_maker to the engine constructor because shell won't have
  // platform_view set until Shell::Setup is called later.
  auto dispatcher_maker = platform_view->GetDispatcherMaker();

  // Create the engine on the UI thread.
  std::promise<std::unique_ptr<Engine>> engine_promise;
  auto engine_future = engine_promise.get_future();
  fml::TaskRunner::RunNowOrPostTask(
      shell->GetTaskRunners().GetUITaskRunner(),
      fml::MakeCopyable([&engine_promise,                                 //
                         shell = shell.get(),                             //
                         &dispatcher_maker,                               //
                         &platform_data,                                  //
                         isolate_snapshot = std::move(isolate_snapshot),  //
                         vsync_waiter = std::move(vsync_waiter),          //
                         &weak_io_manager_future,                         //
                         &snapshot_delegate_future,                       //
                         &unref_queue_future,                             //
                         &on_create_engine,
                         runtime_stage_backend = DetermineRuntimeStageBackend(
                             platform_view->GetImpellerContext())]() mutable {
        TRACE_EVENT0("flutter", "ShellSetupUISubsystem");
        const auto& task_runners = shell->GetTaskRunners();

        // The animator is owned by the UI thread but it gets its vsync pulses
        // from the platform.
        auto animator = std::make_unique<Animator>(*shell, task_runners,
                                                   std::move(vsync_waiter));

        engine_promise.set_value(on_create_engine(
            *shell,                               //
            dispatcher_maker,                     //
            *shell->GetDartVM(),                  //
            std::move(isolate_snapshot),          //
            task_runners,                         //
            platform_data,                        //
            shell->GetSettings(),                 //
            std::move(animator),                  //
            weak_io_manager_future.get(),         //
            unref_queue_future.get(),             //
            snapshot_delegate_future.get(),       //
            shell->volatile_path_tracker_,        //
            shell->is_gpu_disabled_sync_switch_,  //
            runtime_stage_backend                 //
            ));
      }));

  if (!shell->Setup(std::move(platform_view),  //
                    engine_future.get(),       //
                    rasterizer_future.get(),   //
                    io_manager_future.get())   //
  ) {
    return nullptr;
  }

  return shell;
}

std::unique_ptr<Shell> Shell::CreateWithSnapshot(
    const PlatformData& platform_data,
    const TaskRunners& task_runners,
    const fml::RefPtr<fml::RasterThreadMerger>& parent_thread_merger,
    const std::shared_ptr<ShellIOManager>& parent_io_manager,
    const std::shared_ptr<ResourceCacheLimitCalculator>&
        resource_cache_limit_calculator,
    Settings settings,
    DartVMRef vm,
    fml::RefPtr<const DartSnapshot> isolate_snapshot,
    const Shell::CreateCallback<PlatformView>& on_create_platform_view,
    const Shell::CreateCallback<Rasterizer>& on_create_rasterizer,
    const Shell::EngineCreateCallback& on_create_engine,
    bool is_gpu_disabled) {
  // This must come first as it initializes tracing.
  PerformInitializationTasks(settings);

  TRACE_EVENT0("flutter", "Shell::CreateWithSnapshot");

  const bool callbacks_valid =
      on_create_platform_view && on_create_rasterizer && on_create_engine;
  if (!task_runners.IsValid() || !callbacks_valid) {
    return nullptr;
  }

  fml::AutoResetWaitableEvent latch;
  std::unique_ptr<Shell> shell;
  auto platform_task_runner = task_runners.GetPlatformTaskRunner();
  fml::TaskRunner::RunNowOrPostTask(
      platform_task_runner,
      fml::MakeCopyable([&latch,                                             //
                         &shell,                                             //
                         parent_thread_merger,                               //
                         parent_io_manager,                                  //
                         resource_cache_limit_calculator,                    //
                         task_runners = task_runners,                        //
                         platform_data = platform_data,                      //
                         settings = settings,                                //
                         vm = std::move(vm),                                 //
                         isolate_snapshot = std::move(isolate_snapshot),     //
                         on_create_platform_view = on_create_platform_view,  //
                         on_create_rasterizer = on_create_rasterizer,        //
                         on_create_engine = on_create_engine,
                         is_gpu_disabled]() mutable {
        shell = CreateShellOnPlatformThread(std::move(vm),                    //
                                            parent_thread_merger,             //
                                            parent_io_manager,                //
                                            resource_cache_limit_calculator,  //
                                            task_runners,                     //
                                            platform_data,                    //
                                            settings,                         //
                                            std::move(isolate_snapshot),      //
                                            on_create_platform_view,          //
                                            on_create_rasterizer,             //
                                            on_create_engine, is_gpu_disabled);
        latch.Signal();
      }));
  latch.Wait();
  return shell;
}

Shell::Shell(DartVMRef vm,
             const TaskRunners& task_runners,
             fml::RefPtr<fml::RasterThreadMerger> parent_merger,
             const std::shared_ptr<ResourceCacheLimitCalculator>&
                 resource_cache_limit_calculator,
             const Settings& settings,
             std::shared_ptr<VolatilePathTracker> volatile_path_tracker,
             bool is_gpu_disabled)
    : task_runners_(task_runners),
      parent_raster_thread_merger_(std::move(parent_merger)),
      resource_cache_limit_calculator_(resource_cache_limit_calculator),
      settings_(settings),
      vm_(std::move(vm)),
      is_gpu_disabled_sync_switch_(new fml::SyncSwitch(is_gpu_disabled)),
      volatile_path_tracker_(std::move(volatile_path_tracker)),
      weak_factory_gpu_(nullptr),
      weak_factory_(this) {
  FML_CHECK(!settings.enable_software_rendering || !settings.enable_impeller)
      << "Software rendering is incompatible with Impeller.";
  if (!settings.enable_impeller && settings.warn_on_impeller_opt_out) {
    FML_LOG(IMPORTANT)
        << "[Action Required] The application opted out of Impeller by either "
           "using the --no-enable-impeller flag or FLTEnableImpeller=false "
           "plist flag. This option is going to go away in an upcoming Flutter "
           "release. Remove the explicit opt-out. If you need to opt-out, "
           "report a bug describing the issue.";
  }
  FML_CHECK(vm_) << "Must have access to VM to create a shell.";
  FML_DCHECK(task_runners_.IsValid());
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  display_manager_ = std::make_unique<DisplayManager>();
  resource_cache_limit_calculator->AddResourceCacheLimitItem(
      weak_factory_.GetWeakPtr());

  // Generate a WeakPtrFactory for use with the raster thread. This does not
  // need to wait on a latch because it can only ever be used from the raster
  // thread from this class, so we have ordering guarantees.
  fml::TaskRunner::RunNowOrPostTask(
      task_runners_.GetRasterTaskRunner(), fml::MakeCopyable([this]() mutable {
        this->weak_factory_gpu_ =
            std::make_unique<fml::TaskRunnerAffineWeakPtrFactory<Shell>>(this);
      }));

  // Install service protocol handlers.

  service_protocol_handlers_[ServiceProtocol::kScreenshotExtensionName] = {
      task_runners_.GetRasterTaskRunner(),
      std::bind(&Shell::OnServiceProtocolScreenshot, this,
                std::placeholders::_1, std::placeholders::_2)};
  service_protocol_handlers_[ServiceProtocol::kScreenshotSkpExtensionName] = {
      task_runners_.GetRasterTaskRunner(),
      std::bind(&Shell::OnServiceProtocolScreenshotSKP, this,
                std::placeholders::_1, std::placeholders::_2)};
  service_protocol_handlers_[ServiceProtocol::kRunInViewExtensionName] = {
      task_runners_.GetUITaskRunner(),
      std::bind(&Shell::OnServiceProtocolRunInView, this, std::placeholders::_1,
                std::placeholders::_2)};
  service_protocol_handlers_
      [ServiceProtocol::kFlushUIThreadTasksExtensionName] = {
          task_runners_.GetUITaskRunner(),
          std::bind(&Shell::OnServiceProtocolFlushUIThreadTasks, this,
                    std::placeholders::_1, std::placeholders::_2)};
  service_protocol_handlers_
      [ServiceProtocol::kSetAssetBundlePathExtensionName] = {
          task_runners_.GetUITaskRunner(),
          std::bind(&Shell::OnServiceProtocolSetAssetBundlePath, this,
                    std::placeholders::_1, std::placeholders::_2)};
  service_protocol_handlers_
      [ServiceProtocol::kGetDisplayRefreshRateExtensionName] = {
          task_runners_.GetUITaskRunner(),
          std::bind(&Shell::OnServiceProtocolGetDisplayRefreshRate, this,
                    std::placeholders::_1, std::placeholders::_2)};
  service_protocol_handlers_[ServiceProtocol::kGetSkSLsExtensionName] = {
      task_runners_.GetIOTaskRunner(),
      std::bind(&Shell::OnServiceProtocolGetSkSLs, this, std::placeholders::_1,
                std::placeholders::_2)};
  service_protocol_handlers_
      [ServiceProtocol::kEstimateRasterCacheMemoryExtensionName] = {
          task_runners_.GetRasterTaskRunner(),
          std::bind(&Shell::OnServiceProtocolEstimateRasterCacheMemory, this,
                    std::placeholders::_1, std::placeholders::_2)};
  service_protocol_handlers_
      [ServiceProtocol::kRenderFrameWithRasterStatsExtensionName] = {
          task_runners_.GetRasterTaskRunner(),
          std::bind(&Shell::OnServiceProtocolRenderFrameWithRasterStats, this,
                    std::placeholders::_1, std::placeholders::_2)};
  service_protocol_handlers_[ServiceProtocol::kReloadAssetFonts] = {
      task_runners_.GetPlatformTaskRunner(),
      std::bind(&Shell::OnServiceProtocolReloadAssetFonts, this,
                std::placeholders::_1, std::placeholders::_2)};
}

Shell::~Shell() {
#if !SLIMPELLER
  PersistentCache::GetCacheForProcess()->RemoveWorkerTaskRunner(
      task_runners_.GetIOTaskRunner());
#endif  //  !SLIMPELLER

  vm_->GetServiceProtocol()->RemoveHandler(this);

  fml::AutoResetWaitableEvent platiso_latch, ui_latch, gpu_latch,
      platform_latch, io_latch;

  fml::TaskRunner::RunNowOrPostTask(
      task_runners_.GetPlatformTaskRunner(),
      fml::MakeCopyable([this, &platiso_latch]() mutable {
        engine_->ShutdownPlatformIsolates();
        platiso_latch.Signal();
      }));
  platiso_latch.Wait();

  fml::TaskRunner::RunNowOrPostTask(
      task_runners_.GetUITaskRunner(),
      fml::MakeCopyable([this, &ui_latch]() mutable {
        engine_.reset();
        ui_latch.Signal();
      }));
  ui_latch.Wait();

  fml::TaskRunner::RunNowOrPostTask(
      task_runners_.GetRasterTaskRunner(),
      fml::MakeCopyable(
          [this, rasterizer = std::move(rasterizer_), &gpu_latch]() mutable {
            rasterizer.reset();
            this->weak_factory_gpu_.reset();
            gpu_latch.Signal();
          }));
  gpu_latch.Wait();

  fml::TaskRunner::RunNowOrPostTask(
      task_runners_.GetIOTaskRunner(),
      fml::MakeCopyable([io_manager = std::move(io_manager_),
                         platform_view = platform_view_.get(),
                         &io_latch]() mutable {
        io_manager.reset();
        if (platform_view) {
          platform_view->ReleaseResourceContext();
        }
        io_latch.Signal();
      }));

  io_latch.Wait();

  // The platform view must go last because it may be holding onto platform side
  // counterparts to resources owned by subsystems running on other threads. For
  // example, the NSOpenGLContext on the Mac.
  fml::TaskRunner::RunNowOrPostTask(
      task_runners_.GetPlatformTaskRunner(),
      fml::MakeCopyable([platform_view = std::move(platform_view_),
                         &platform_latch]() mutable {
        platform_view.reset();
        platform_latch.Signal();
      }));
  platform_latch.Wait();
}

std::unique_ptr<Shell> Shell::Spawn(
    RunConfiguration run_configuration,
    const std::string& initial_route,
    const CreateCallback<PlatformView>& on_create_platform_view,
    const CreateCallback<Rasterizer>& on_create_rasterizer) const {
  FML_DCHECK(task_runners_.IsValid());
  // It's safe to store this value since it is set on the platform thread.
  bool is_gpu_disabled = false;
  GetIsGpuDisabledSyncSwitch()->Execute(
      fml::SyncSwitch::Handlers()
          .SetIfFalse([&is_gpu_disabled] { is_gpu_disabled = false; })
          .SetIfTrue([&is_gpu_disabled] { is_gpu_disabled = true; }));
  std::unique_ptr<Shell> result = CreateWithSnapshot(
      PlatformData{}, task_runners_, rasterizer_->GetRasterThreadMerger(),
      io_manager_, resource_cache_limit_calculator_, GetSettings(), vm_,
      vm_->GetVMData()->GetIsolateSnapshot(), on_create_platform_view,
      on_create_rasterizer,
      [engine = this->engine_.get(), initial_route](
          Engine::Delegate& delegate,
          const PointerDataDispatcherMaker& dispatcher_maker, DartVM& vm,
          const fml::RefPtr<const DartSnapshot>& isolate_snapshot,
          const TaskRunners& task_runners, const PlatformData& platform_data,
          const Settings& settings, std::unique_ptr<Animator> animator,
          const fml::WeakPtr<IOManager>& io_manager,
          const fml::RefPtr<SkiaUnrefQueue>& unref_queue,
          fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
          const std::shared_ptr<VolatilePathTracker>& volatile_path_tracker,
          const std::shared_ptr<fml::SyncSwitch>& is_gpu_disabled_sync_switch,
          impeller::RuntimeStageBackend runtime_stage_backend) {
        return engine->Spawn(
            /*delegate=*/delegate,
            /*dispatcher_maker=*/dispatcher_maker,
            /*settings=*/settings,
            /*animator=*/std::move(animator),
            /*initial_route=*/initial_route,
            /*io_manager=*/io_manager,
            /*snapshot_delegate=*/std::move(snapshot_delegate),
            /*gpu_disabled_switch=*/is_gpu_disabled_sync_switch);
      },
      is_gpu_disabled);
  result->RunEngine(std::move(run_configuration));
  return result;
}

void Shell::NotifyLowMemoryWarning() const {
  auto trace_id = fml::tracing::TraceNonce();
  TRACE_EVENT_ASYNC_BEGIN0("flutter", "Shell::NotifyLowMemoryWarning",
                           trace_id);
  // This does not require a current isolate but does require a running VM.
  // Since a valid shell will not be returned to the embedder without a valid
  // DartVMRef, we can be certain that this is a safe spot to assume a VM is
  // running.
  ::Dart_NotifyLowMemory();

  task_runners_.GetRasterTaskRunner()->PostTask(
      [rasterizer = rasterizer_->GetWeakPtr(), trace_id = trace_id]() {
        if (rasterizer) {
          rasterizer->NotifyLowMemoryWarning();
        }
        TRACE_EVENT_ASYNC_END0("flutter", "Shell::NotifyLowMemoryWarning",
                               trace_id);
      });
  // The IO Manager uses resource cache limits of 0, so it is not necessary
  // to purge them.
}

void Shell::RunEngine(RunConfiguration run_configuration) {
  RunEngine(std::move(run_configuration), nullptr);
}

void Shell::RunEngine(
    RunConfiguration run_configuration,
    const std::function<void(Engine::RunStatus)>& result_callback) {
  auto result = [platform_runner = task_runners_.GetPlatformTaskRunner(),
                 result_callback](Engine::RunStatus run_result) {
    if (!result_callback) {
      return;
    }
    platform_runner->PostTask(
        [result_callback, run_result]() { result_callback(run_result); });
  };
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  fml::TaskRunner::RunNowOrPostTask(
      task_runners_.GetUITaskRunner(),
      fml::MakeCopyable(
          [run_configuration = std::move(run_configuration),
           weak_engine = weak_engine_, result]() mutable {
            if (!weak_engine) {
              FML_LOG(ERROR)
                  << "Could not launch engine with configuration - no engine.";
              result(Engine::RunStatus::Failure);
              return;
            }
            auto run_result = weak_engine->Run(std::move(run_configuration));
            if (run_result == flutter::Engine::RunStatus::Failure) {
              FML_LOG(ERROR) << "Could not launch engine with configuration.";
            }

            result(run_result);
          }));
}

std::optional<DartErrorCode> Shell::GetUIIsolateLastError() const {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());

  if (!weak_engine_) {
    return std::nullopt;
  }
  switch (weak_engine_->GetUIIsolateLastError()) {
    case tonic::kCompilationErrorType:
      return DartErrorCode::CompilationError;
    case tonic::kApiErrorType:
      return DartErrorCode::ApiError;
    case tonic::kUnknownErrorType:
      return DartErrorCode::UnknownError;
    case tonic::kNoError:
      return DartErrorCode::NoError;
  }
  return DartErrorCode::UnknownError;
}

bool Shell::EngineHasLivePorts() const {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());

  if (!weak_engine_) {
    return false;
  }

  return weak_engine_->UIIsolateHasLivePorts();
}

bool Shell::IsSetup() const {
  return is_set_up_;
}

bool Shell::Setup(std::unique_ptr<PlatformView> platform_view,
                  std::unique_ptr<Engine> engine,
                  std::unique_ptr<Rasterizer> rasterizer,
                  const std::shared_ptr<ShellIOManager>& io_manager) {
  if (is_set_up_) {
    return false;
  }

  if (!platform_view || !engine || !rasterizer || !io_manager) {
    return false;
  }

  platform_view_ = std::move(platform_view);
  platform_message_handler_ = platform_view_->GetPlatformMessageHandler();
  route_messages_through_platform_thread_.store(true);
  task_runners_.GetPlatformTaskRunner()->PostTask(
      [self = weak_factory_.GetWeakPtr()] {
        if (self) {
          self->route_messages_through_platform_thread_.store(false);
        }
      });
  engine_ = std::move(engine);
  rasterizer_ = std::move(rasterizer);
  io_manager_ = io_manager;

  // Set the external view embedder for the rasterizer.
  auto view_embedder = platform_view_->CreateExternalViewEmbedder();
  rasterizer_->SetExternalViewEmbedder(view_embedder);
  rasterizer_->SetSnapshotSurfaceProducer(
      platform_view_->CreateSnapshotSurfaceProducer());

  // The weak ptr must be generated in the platform thread which owns the unique
  // ptr.
  weak_engine_ = engine_->GetWeakPtr();
  weak_rasterizer_ = rasterizer_->GetWeakPtr();
  weak_platform_view_ = platform_view_->GetWeakPtr();

  // Add the implicit view with empty metrics.
  engine_->AddView(kFlutterImplicitViewId, ViewportMetrics{}, [](bool added) {
    FML_DCHECK(added) << "Failed to add the implicit view";
  });

  // Setup the time-consuming default font manager right after engine created.
  if (!settings_.prefetched_default_font_manager) {
    fml::TaskRunner::RunNowOrPostTask(task_runners_.GetUITaskRunner(),
                                      [engine = weak_engine_] {
                                        if (engine) {
                                          engine->SetupDefaultFontManager();
                                        }
                                      });
  }

  is_set_up_ = true;

#if !SLIMPELLER
  PersistentCache::GetCacheForProcess()->AddWorkerTaskRunner(
      task_runners_.GetIOTaskRunner());

  PersistentCache::GetCacheForProcess()->SetIsDumpingSkp(
      settings_.dump_skp_on_shader_compilation);

  if (settings_.purge_persistent_cache) {
    PersistentCache::GetCacheForProcess()->Purge();
  }
#endif  //  !SLIMPELLER

  return true;
}

const Settings& Shell::GetSettings() const {
  return settings_;
}

const TaskRunners& Shell::GetTaskRunners() const {
  return task_runners_;
}

const fml::RefPtr<fml::RasterThreadMerger> Shell::GetParentRasterThreadMerger()
    const {
  return parent_raster_thread_merger_;
}

fml::TaskRunnerAffineWeakPtr<Rasterizer> Shell::GetRasterizer() const {
  FML_DCHECK(is_set_up_);
  return weak_rasterizer_;
}

fml::WeakPtr<Engine> Shell::GetEngine() {
  FML_DCHECK(is_set_up_);
  return weak_engine_;
}

fml::WeakPtr<PlatformView> Shell::GetPlatformView() {
  FML_DCHECK(is_set_up_);
  return weak_platform_view_;
}

fml::WeakPtr<ShellIOManager> Shell::GetIOManager() {
  FML_DCHECK(is_set_up_);
  return io_manager_->GetWeakPtr();
}

DartVM* Shell::GetDartVM() {
  return &vm_;
}

// |PlatformView::Delegate|
void Shell::OnPlatformViewCreated(std::unique_ptr<Surface> surface) {
  TRACE_EVENT0("flutter", "Shell::OnPlatformViewCreated");
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  // Prevent any request to change the thread configuration for raster and
  // platform queues while the platform view is being created.
  //
  // This prevents false positives such as this method starts assuming that the
  // raster and platform queues have a given thread configuration, but then the
  // configuration is changed by a task, and the assumption is no longer true.
  //
  // This incorrect assumption can lead to deadlock.
  // See `should_post_raster_task` for more.
  rasterizer_->DisableThreadMergerIfNeeded();

  // The normal flow executed by this method is that the platform thread is
  // starting the sequence and waiting on the latch. Later the UI thread posts
  // raster_task to the raster thread which signals the latch. If the raster and
  // the platform threads are the same this results in a deadlock as the
  // raster_task will never be posted to the platform/raster thread that is
  // blocked on a latch. To avoid the described deadlock, if the raster and the
  // platform threads are the same, should_post_raster_task will be false, and
  // then instead of posting a task to the raster thread, the ui thread just
  // signals the latch and the platform/raster thread follows with executing
  // raster_task.
  const bool should_post_raster_task =
      !task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread();

  auto raster_task = fml::MakeCopyable(
      [&waiting_for_first_frame = waiting_for_first_frame_,  //
       rasterizer = rasterizer_->GetWeakPtr(),               //
       surface = std::move(surface)                          //
  ]() mutable {
        if (rasterizer) {
          // Enables the thread merger which may be used by the external view
          // embedder.
          rasterizer->EnableThreadMergerIfNeeded();
          rasterizer->Setup(std::move(surface));
        }

        waiting_for_first_frame.store(true);
      });

  auto ui_task = [engine = engine_->GetWeakPtr()] {
    if (engine) {
      engine->ScheduleFrame();
    }
  };

  // Threading: Capture platform view by raw pointer and not the weak pointer.
  // We are going to use the pointer on the IO thread which is not safe with a
  // weak pointer. However, we are preventing the platform view from being
  // collected by using a latch.
  auto* platform_view = platform_view_.get();
  FML_DCHECK(platform_view);
  fml::AutoResetWaitableEvent latch;

  auto io_task = [io_manager = io_manager_->GetWeakPtr(), platform_view,
                  ui_task_runner = task_runners_.GetUITaskRunner(), ui_task,
                  raster_task_runner = task_runners_.GetRasterTaskRunner(),
                  raster_task, should_post_raster_task, &latch] {
    if (io_manager && !io_manager->GetResourceContext()) {
      sk_sp<GrDirectContext> resource_context =
          platform_view->CreateResourceContext();
      io_manager->NotifyResourceContextAvailable(resource_context);
    }
    // Step 1: Post a task on the UI thread to tell the engine that it has
    // an output surface.
    fml::TaskRunner::RunNowOrPostTask(ui_task_runner, ui_task);

    // Step 2: Tell the raster thread that it should create a surface for
    // its rasterizer.
    if (should_post_raster_task) {
      fml::TaskRunner::RunNowOrPostTask(raster_task_runner, raster_task);
    }
    latch.Signal();
  };

  fml::TaskRunner::RunNowOrPostTask(task_runners_.GetIOTaskRunner(), io_task);

  latch.Wait();
  if (!should_post_raster_task) {
    // See comment on should_post_raster_task, in this case the raster_task
    // wasn't executed, and we just run it here as the platform thread
    // is the raster thread.
    raster_task();
  }
}

// |PlatformView::Delegate|
void Shell::OnPlatformViewDestroyed() {
  TRACE_EVENT0("flutter", "Shell::OnPlatformViewDestroyed");
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  // Prevent any request to change the thread configuration for raster and
  // platform queues while the platform view is being destroyed.
  //
  // This prevents false positives such as this method starts assuming that the
  // raster and platform queues have a given thread configuration, but then the
  // configuration is changed by a task, and the assumption is no longer true.
  //
  // This incorrect assumption can lead to deadlock.
  rasterizer_->DisableThreadMergerIfNeeded();

  // Notify the Dart VM that the PlatformView has been destroyed and some
  // cleanup activity can be done (e.g: garbage collect the Dart heap).
  task_runners_.GetUITaskRunner()->PostTask([engine = engine_->GetWeakPtr()]() {
    if (engine) {
      engine->NotifyDestroyed();
    }
  });

  // Note:
  // This is a synchronous operation because certain platforms depend on
  // setup/suspension of all activities that may be interacting with the GPU in
  // a synchronous fashion.
  // The UI thread does not need to be serialized here - there is sufficient
  // guardrailing in the rasterizer to allow the UI thread to post work to it
  // even after the surface has been torn down.

  fml::AutoResetWaitableEvent latch;

  auto io_task = [io_manager = io_manager_.get(), &latch]() {
    // Execute any pending Skia object deletions while GPU access is still
    // allowed.
    io_manager->GetIsGpuDisabledSyncSwitch()->Execute(
        fml::SyncSwitch::Handlers().SetIfFalse(
            [&] { io_manager->GetSkiaUnrefQueue()->Drain(); }));
    // Step 4: All done. Signal the latch that the platform thread is waiting
    // on.
    latch.Signal();
  };

  auto raster_task = [rasterizer = rasterizer_->GetWeakPtr(),
                      io_task_runner = task_runners_.GetIOTaskRunner(),
                      io_task]() {
    if (rasterizer) {
      // Enables the thread merger which is required prior tearing down the
      // rasterizer. If the raster and platform threads are merged, tearing down
      // the rasterizer unmerges the threads.
      rasterizer->EnableThreadMergerIfNeeded();
      rasterizer->Teardown();
    }
    // Step 2: Tell the IO thread to complete its remaining work.
    fml::TaskRunner::RunNowOrPostTask(io_task_runner, io_task);
  };

  // Step 1: Post a task to the Raster thread (possibly this thread) to tell the
  // rasterizer the output surface is going away.
  fml::TaskRunner::RunNowOrPostTask(task_runners_.GetRasterTaskRunner(),
                                    raster_task);
  latch.Wait();
  // On Android, the external view embedder may post a task to the platform
  // thread, and wait until it completes if overlay surfaces must be released.
  // However, the platform thread might be blocked when Dart is initializing.
  // In this situation, calling TeardownExternalViewEmbedder is safe because no
  // platform views have been created before Flutter renders the first frame.
  // Overall, the longer term plan is to remove this implementation once
  // https://github.com/flutter/flutter/issues/96679 is fixed.
  rasterizer_->TeardownExternalViewEmbedder();
}

// |PlatformView::Delegate|
void Shell::OnPlatformViewScheduleFrame() {
  TRACE_EVENT0("flutter", "Shell::OnPlatformViewScheduleFrame");
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  task_runners_.GetUITaskRunner()->PostTask([engine = engine_->GetWeakPtr()]() {
    if (engine) {
      engine->ScheduleFrame();
    }
  });
}

// |PlatformView::Delegate|
void Shell::OnPlatformViewSetViewportMetrics(int64_t view_id,
                                             const ViewportMetrics& metrics) {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  if (metrics.device_pixel_ratio <= 0 || metrics.physical_width <= 0 ||
      metrics.physical_height <= 0) {
    // Ignore invalid view-port metrics.
    return;
  }

  // This is the formula Android uses.
  // https://android.googlesource.com/platform/frameworks/base/+/39ae5bac216757bc201490f4c7b8c0f63006c6cd/libs/hwui/renderthread/CacheManager.cpp#45
  resource_cache_limit_ =
      metrics.physical_width * metrics.physical_height * 12 * 4;
  size_t resource_cache_max_bytes =
      resource_cache_limit_calculator_->GetResourceCacheMaxBytes();
  task_runners_.GetRasterTaskRunner()->PostTask(
      [rasterizer = rasterizer_->GetWeakPtr(), resource_cache_max_bytes] {
        if (rasterizer) {
          rasterizer->SetResourceCacheMaxBytes(resource_cache_max_bytes, false);
        }
      });

  task_runners_.GetUITaskRunner()->PostTask(
      [engine = engine_->GetWeakPtr(), view_id, metrics]() {
        if (engine) {
          engine->SetViewportMetrics(view_id, metrics);
        }
      });

  {
    std::scoped_lock<std::mutex> lock(resize_mutex_);
    expected_frame_sizes_[view_id] =
        SkISize::Make(metrics.physical_width, metrics.physical_height);
    device_pixel_ratio_ = metrics.device_pixel_ratio;
  }
}

// |PlatformView::Delegate|
void Shell::OnPlatformViewDispatchPlatformMessage(
    std::unique_ptr<PlatformMessage> message) {
  FML_DCHECK(is_set_up_);
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
  if (!task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()) {
    std::scoped_lock lock(misbehaving_message_channels_mutex_);
    auto inserted = misbehaving_message_channels_.insert(message->channel());
    if (inserted.second) {
      FML_LOG(ERROR)
          << "The '" << message->channel()
          << "' channel sent a message from native to Flutter on a "
             "non-platform thread. Platform channel messages must be sent on "
             "the platform thread. Failure to do so may result in data loss or "
             "crashes, and must be fixed in the plugin or application code "
             "creating that channel.\n"
             "See https://docs.flutter.dev/platform-integration/"
             "platform-channels#channels-and-platform-threading for more "
             "information.";
    }
  }
#endif  // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG

  // The static leak checker gets confused by the use of fml::MakeCopyable.
  // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
  task_runners_.GetUITaskRunner()->PostTask(fml::MakeCopyable(
      [engine = engine_->GetWeakPtr(), message = std::move(message)]() mutable {
        if (engine) {
          engine->DispatchPlatformMessage(std::move(message));
        }
      }));
}

// |PlatformView::Delegate|
void Shell::OnPlatformViewDispatchPointerDataPacket(
    std::unique_ptr<PointerDataPacket> packet) {
  TRACE_EVENT0_WITH_FLOW_IDS(
      "flutter", "Shell::OnPlatformViewDispatchPointerDataPacket",
      /*flow_id_count=*/1, /*flow_ids=*/&next_pointer_flow_id_);
  TRACE_FLOW_BEGIN("flutter", "PointerEvent", next_pointer_flow_id_);
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
  task_runners_.GetUITaskRunner()->PostTask(
      fml::MakeCopyable([engine = weak_engine_, packet = std::move(packet),
                         flow_id = next_pointer_flow_id_]() mutable {
        if (engine) {
          engine->DispatchPointerDataPacket(std::move(packet), flow_id);
        }
      }));
  next_pointer_flow_id_++;
}

// |PlatformView::Delegate|
void Shell::OnPlatformViewDispatchSemanticsAction(int32_t node_id,
                                                  SemanticsAction action,
                                                  fml::MallocMapping args) {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  task_runners_.GetUITaskRunner()->PostTask(
      fml::MakeCopyable([engine = engine_->GetWeakPtr(), node_id, action,
                         args = std::move(args)]() mutable {
        if (engine) {
          engine->DispatchSemanticsAction(node_id, action, std::move(args));
        }
      }));
}

// |PlatformView::Delegate|
void Shell::OnPlatformViewSetSemanticsEnabled(bool enabled) {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  task_runners_.GetUITaskRunner()->PostTask(
      [engine = engine_->GetWeakPtr(), enabled] {
        if (engine) {
          engine->SetSemanticsEnabled(enabled);
        }
      });
}

// |PlatformView::Delegate|
void Shell::OnPlatformViewSetAccessibilityFeatures(int32_t flags) {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  task_runners_.GetUITaskRunner()->PostTask(
      [engine = engine_->GetWeakPtr(), flags] {
        if (engine) {
          engine->SetAccessibilityFeatures(flags);
        }
      });
}

// |PlatformView::Delegate|
void Shell::OnPlatformViewRegisterTexture(
    std::shared_ptr<flutter::Texture> texture) {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  task_runners_.GetRasterTaskRunner()->PostTask(
      [rasterizer = rasterizer_->GetWeakPtr(), texture] {
        if (rasterizer) {
          if (auto registry = rasterizer->GetTextureRegistry()) {
            registry->RegisterTexture(texture);
          }
        }
      });
}

// |PlatformView::Delegate|
void Shell::OnPlatformViewUnregisterTexture(int64_t texture_id) {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  task_runners_.GetRasterTaskRunner()->PostTask(
      [rasterizer = rasterizer_->GetWeakPtr(), texture_id]() {
        if (rasterizer) {
          if (auto registry = rasterizer->GetTextureRegistry()) {
            registry->UnregisterTexture(texture_id);
          }
        }
      });
}

// |PlatformView::Delegate|
void Shell::OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  // Tell the rasterizer that one of its textures has a new frame available.
  task_runners_.GetRasterTaskRunner()->PostTask(
      [rasterizer = rasterizer_->GetWeakPtr(), texture_id]() {
        if (!rasterizer) {
          return;
        }
        auto registry = rasterizer->GetTextureRegistry();

        if (!registry) {
          return;
        }

        auto texture = registry->GetTexture(texture_id);

        if (!texture) {
          return;
        }

        texture->MarkNewFrameAvailable();
      });

  // Schedule a new frame without having to rebuild the layer tree.
  task_runners_.GetUITaskRunner()->PostTask([engine = engine_->GetWeakPtr()]() {
    if (engine) {
      engine->ScheduleFrame(false);
    }
  });
}

// |PlatformView::Delegate|
void Shell::OnPlatformViewSetNextFrameCallback(const fml::closure& closure) {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  task_runners_.GetRasterTaskRunner()->PostTask(
      [rasterizer = rasterizer_->GetWeakPtr(), closure = closure]() {
        if (rasterizer) {
          rasterizer->SetNextFrameCallback(closure);
        }
      });
}

// |PlatformView::Delegate|
const Settings& Shell::OnPlatformViewGetSettings() const {
  return settings_;
}

// |Animator::Delegate|
void Shell::OnAnimatorBeginFrame(fml::TimePoint frame_target_time,
                                 uint64_t frame_number) {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());

  // record the target time for use by rasterizer.
  {
    std::scoped_lock time_recorder_lock(time_recorder_mutex_);
    latest_frame_target_time_.emplace(frame_target_time);
  }
  if (engine_) {
    engine_->BeginFrame(frame_target_time, frame_number);
  }
}

// |Animator::Delegate|
void Shell::OnAnimatorNotifyIdle(fml::TimeDelta deadline) {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());

  if (engine_) {
    engine_->NotifyIdle(deadline);
    volatile_path_tracker_->OnFrame();
  }
}

void Shell::OnAnimatorUpdateLatestFrameTargetTime(
    fml::TimePoint frame_target_time) {
  FML_DCHECK(is_set_up_);

  // record the target time for use by rasterizer.
  {
    std::scoped_lock time_recorder_lock(time_recorder_mutex_);
    if (!latest_frame_target_time_) {
      latest_frame_target_time_ = frame_target_time;
    } else if (latest_frame_target_time_ < frame_target_time) {
      latest_frame_target_time_ = frame_target_time;
    }
  }
}

// |Animator::Delegate|
void Shell::OnAnimatorDraw(std::shared_ptr<FramePipeline> pipeline) {
  FML_DCHECK(is_set_up_);

  task_runners_.GetRasterTaskRunner()->PostTask(fml::MakeCopyable(
      [&waiting_for_first_frame = waiting_for_first_frame_,
       &waiting_for_first_frame_condition = waiting_for_first_frame_condition_,
       rasterizer = rasterizer_->GetWeakPtr(),
       weak_pipeline = std::weak_ptr<FramePipeline>(pipeline)]() mutable {
        if (rasterizer) {
          std::shared_ptr<FramePipeline> pipeline = weak_pipeline.lock();
          if (pipeline) {
            rasterizer->Draw(pipeline);
          }

          if (waiting_for_first_frame.load()) {
            waiting_for_first_frame.store(false);
            waiting_for_first_frame_condition.notify_all();
          }
        }
      }));
}

// |Animator::Delegate|
void Shell::OnAnimatorDrawLastLayerTrees(
    std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder) {
  FML_DCHECK(is_set_up_);

  auto task = fml::MakeCopyable(
      [rasterizer = rasterizer_->GetWeakPtr(),
       frame_timings_recorder = std::move(frame_timings_recorder)]() mutable {
        if (rasterizer) {
          rasterizer->DrawLastLayerTrees(std::move(frame_timings_recorder));
        }
      });

  task_runners_.GetRasterTaskRunner()->PostTask(task);
}

// |Engine::Delegate|
void Shell::OnEngineUpdateSemantics(SemanticsNodeUpdates update,
                                    CustomAccessibilityActionUpdates actions) {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());

  task_runners_.GetPlatformTaskRunner()->PostTask(
      [view = platform_view_->GetWeakPtr(), update = std::move(update),
       actions = std::move(actions)] {
        if (view) {
          view->UpdateSemantics(update, actions);
        }
      });
}

// |Engine::Delegate|
void Shell::OnEngineHandlePlatformMessage(
    std::unique_ptr<PlatformMessage> message) {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());

  if (message->channel() == kSkiaChannel) {
    HandleEngineSkiaMessage(std::move(message));
    return;
  }

  if (platform_message_handler_) {
    if (route_messages_through_platform_thread_ &&
        !platform_message_handler_
             ->DoesHandlePlatformMessageOnPlatformThread()) {
#if _WIN32
      // On Windows capturing a TaskRunner with a TaskRunner will cause an
      // uncaught exception in process shutdown because of the deletion order of
      // global variables. See also
      // https://github.com/flutter/flutter/issues/111575.
      // This won't be an issue until Windows supports background platform
      // channels (https://github.com/flutter/flutter/issues/93945). Then this
      // can potentially be addressed by capturing a weak_ptr to an object that
      // retains the ui TaskRunner, instead of the TaskRunner directly.
      FML_DCHECK(false);
#endif
      // We route messages through the platform thread temporarily when the
      // shell is being initialized to be backwards compatible with setting
      // message handlers in the same event as starting the isolate, but after
      // it is started.
      auto ui_task_runner = task_runners_.GetUITaskRunner();
      task_runners_.GetPlatformTaskRunner()->PostTask(fml::MakeCopyable(
          [weak_platform_message_handler =
               std::weak_ptr<PlatformMessageHandler>(platform_message_handler_),
           message = std::move(message), ui_task_runner]() mutable {
            ui_task_runner->PostTask(
                fml::MakeCopyable([weak_platform_message_handler,
                                   message = std::move(message)]() mutable {
                  auto platform_message_handler =
                      weak_platform_message_handler.lock();
                  if (platform_message_handler) {
                    platform_message_handler->HandlePlatformMessage(
                        std::move(message));
                  }
                }));
          }));
    } else {
      platform_message_handler_->HandlePlatformMessage(std::move(message));
    }
  } else {
    task_runners_.GetPlatformTaskRunner()->PostTask(
        fml::MakeCopyable([view = platform_view_->GetWeakPtr(),
                           message = std::move(message)]() mutable {
          if (view) {
            view->HandlePlatformMessage(std::move(message));
          }
        }));
  }
}

void Shell::OnEngineChannelUpdate(std::string name, bool listening) {
  FML_DCHECK(is_set_up_);

  task_runners_.GetPlatformTaskRunner()->PostTask(
      [view = platform_view_->GetWeakPtr(), name = std::move(name), listening] {
        if (view) {
          view->SendChannelUpdate(name, listening);
        }
      });
}

void Shell::HandleEngineSkiaMessage(std::unique_ptr<PlatformMessage> message) {
  const auto& data = message->data();

  rapidjson::Document document;
  document.Parse(reinterpret_cast<const char*>(data.GetMapping()),
                 data.GetSize());
  if (document.HasParseError() || !document.IsObject()) {
    return;
  }
  auto root = document.GetObject();
  auto method = root.FindMember("method");
  if (method->value != "Skia.setResourceCacheMaxBytes") {
    return;
  }
  auto args = root.FindMember("args");
  if (args == root.MemberEnd() || !args->value.IsInt()) {
    return;
  }

  task_runners_.GetRasterTaskRunner()->PostTask(
      [rasterizer = rasterizer_->GetWeakPtr(), max_bytes = args->value.GetInt(),
       response = message->response()] {
        if (rasterizer) {
          rasterizer->SetResourceCacheMaxBytes(static_cast<size_t>(max_bytes),
                                               true);
        }
        if (response) {
          // The framework side expects this to be valid json encoded as a list.
          // Return `[true]` to signal success.
          std::vector<uint8_t> data = {'[', 't', 'r', 'u', 'e', ']'};
          response->Complete(
              std::make_unique<fml::DataMapping>(std::move(data)));
        }
      });
}

// |Engine::Delegate|
void Shell::OnPreEngineRestart() {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());

  fml::AutoResetWaitableEvent latch;
  fml::TaskRunner::RunNowOrPostTask(
      task_runners_.GetPlatformTaskRunner(),
      [view = platform_view_->GetWeakPtr(), &latch]() {
        if (view) {
          view->OnPreEngineRestart();
        }
        latch.Signal();
      });
  // This is blocking as any embedded platform views has to be flushed before
  // we re-run the Dart code.
  latch.Wait();
}

// |Engine::Delegate|
void Shell::OnRootIsolateCreated() {
  if (is_added_to_service_protocol_) {
    return;
  }
  auto description = GetServiceProtocolDescription();
  fml::TaskRunner::RunNowOrPostTask(
      task_runners_.GetPlatformTaskRunner(),
      [self = weak_factory_.GetWeakPtr(),
       description = std::move(description)]() {
        if (self) {
          self->vm_->GetServiceProtocol()->AddHandler(self.get(), description);
        }
      });
  is_added_to_service_protocol_ = true;
}

// |Engine::Delegate|
void Shell::UpdateIsolateDescription(const std::string isolate_name,
                                     int64_t isolate_port) {
  Handler::Description description(isolate_port, isolate_name);
  vm_->GetServiceProtocol()->SetHandlerDescription(this, description);
}

void Shell::SetNeedsReportTimings(bool value) {
  needs_report_timings_ = value;
}

// |Engine::Delegate|
std::unique_ptr<std::vector<std::string>> Shell::ComputePlatformResolvedLocale(
    const std::vector<std::string>& supported_locale_data) {
  return platform_view_->ComputePlatformResolvedLocales(supported_locale_data);
}

void Shell::LoadDartDeferredLibrary(
    intptr_t loading_unit_id,
    std::unique_ptr<const fml::Mapping> snapshot_data,
    std::unique_ptr<const fml::Mapping> snapshot_instructions) {
  task_runners_.GetUITaskRunner()->PostTask(fml::MakeCopyable(
      [engine = engine_->GetWeakPtr(), loading_unit_id,
       data = std::move(snapshot_data),
       instructions = std::move(snapshot_instructions)]() mutable {
        if (engine) {
          engine->LoadDartDeferredLibrary(loading_unit_id, std::move(data),
                                          std::move(instructions));
        }
      }));
}

void Shell::LoadDartDeferredLibraryError(intptr_t loading_unit_id,
                                         const std::string error_message,
                                         bool transient) {
  fml::TaskRunner::RunNowOrPostTask(
      task_runners_.GetUITaskRunner(),
      [engine = weak_engine_, loading_unit_id, error_message, transient] {
        if (engine) {
          engine->LoadDartDeferredLibraryError(loading_unit_id, error_message,
                                               transient);
        }
      });
}

void Shell::UpdateAssetResolverByType(
    std::unique_ptr<AssetResolver> updated_asset_resolver,
    AssetResolver::AssetResolverType type) {
  fml::TaskRunner::RunNowOrPostTask(
      task_runners_.GetUITaskRunner(),
      fml::MakeCopyable(
          [engine = weak_engine_, type,
           asset_resolver = std::move(updated_asset_resolver)]() mutable {
            if (engine) {
              engine->GetAssetManager()->UpdateResolverByType(
                  std::move(asset_resolver), type);
            }
          }));
}

// |Engine::Delegate|
void Shell::RequestDartDeferredLibrary(intptr_t loading_unit_id) {
  task_runners_.GetPlatformTaskRunner()->PostTask(
      [view = platform_view_->GetWeakPtr(), loading_unit_id] {
        if (view) {
          view->RequestDartDeferredLibrary(loading_unit_id);
        }
      });
}

// |Engine::Delegate|
double Shell::GetScaledFontSize(double unscaled_font_size,
                                int configuration_id) const {
  return platform_view_->GetScaledFontSize(unscaled_font_size,
                                           configuration_id);
}

void Shell::ReportTimings() {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread());

  auto timings = std::move(unreported_timings_);
  unreported_timings_ = {};
  task_runners_.GetUITaskRunner()->PostTask([timings, engine = weak_engine_] {
    if (engine) {
      engine->ReportTimings(timings);
    }
  });
}

size_t Shell::UnreportedFramesCount() const {
  // Check that this is running on the raster thread to avoid race conditions.
  FML_DCHECK(task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread());
  FML_DCHECK(unreported_timings_.size() % (FrameTiming::kStatisticsCount) == 0);
  return unreported_timings_.size() / (FrameTiming::kStatisticsCount);
}

void Shell::OnFrameRasterized(const FrameTiming& timing) {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread());

  // The C++ callback defined in settings.h and set by Flutter runner. This is
  // independent of the timings report to the Dart side.
  if (settings_.frame_rasterized_callback) {
    settings_.frame_rasterized_callback(timing);
  }

  if (!needs_report_timings_) {
    return;
  }

  size_t old_count = unreported_timings_.size();
  (void)old_count;
  for (auto phase : FrameTiming::kPhases) {
    unreported_timings_.push_back(
        timing.Get(phase).ToEpochDelta().ToMicroseconds());
  }
  unreported_timings_.push_back(timing.GetLayerCacheCount());
  unreported_timings_.push_back(timing.GetLayerCacheBytes());
  unreported_timings_.push_back(timing.GetPictureCacheCount());
  unreported_timings_.push_back(timing.GetPictureCacheBytes());
  unreported_timings_.push_back(timing.GetFrameNumber());
  FML_DCHECK(unreported_timings_.size() ==
             old_count + FrameTiming::kStatisticsCount);

  // In tests using iPhone 6S with profile mode, sending a batch of 1 frame or a
  // batch of 100 frames have roughly the same cost of less than 0.1ms. Sending
  // a batch of 500 frames costs about 0.2ms. The 1 second threshold usually
  // kicks in before we reaching the following 100 frames threshold. The 100
  // threshold here is mainly for unit tests (so we don't have to write a
  // 1-second unit test), and make sure that our vector won't grow too big with
  // future 120fps, 240fps, or 1000fps displays.
  //
  // In the profile/debug mode, the timings are used by development tools which
  // require a latency of no more than 100ms. Hence we lower that 1-second
  // threshold to 100ms because performance overhead isn't that critical in
  // those cases.
  if (!first_frame_rasterized_ || UnreportedFramesCount() >= 100) {
    first_frame_rasterized_ = true;
    ReportTimings();
  } else if (!frame_timings_report_scheduled_) {
#if FLUTTER_RELEASE
    constexpr int kBatchTimeInMilliseconds = 1000;
#else
    constexpr int kBatchTimeInMilliseconds = 100;
#endif

    // Also make sure that frame times get reported with a max latency of 1
    // second. Otherwise, the timings of last few frames of an animation may
    // never be reported until the next animation starts.
    frame_timings_report_scheduled_ = true;
    task_runners_.GetRasterTaskRunner()->PostDelayedTask(
        [self = weak_factory_gpu_->GetWeakPtr()]() {
          if (!self) {
            return;
          }
          self->frame_timings_report_scheduled_ = false;
          if (self->UnreportedFramesCount() > 0) {
            self->ReportTimings();
          }
        },
        fml::TimeDelta::FromMilliseconds(kBatchTimeInMilliseconds));
  }
}

fml::Milliseconds Shell::GetFrameBudget() {
  double display_refresh_rate = display_manager_->GetMainDisplayRefreshRate();
  if (display_refresh_rate > 0) {
    return fml::RefreshRateToFrameBudget(display_refresh_rate);
  } else {
    return fml::kDefaultFrameBudget;
  }
}

fml::TimePoint Shell::GetLatestFrameTargetTime() const {
  std::scoped_lock time_recorder_lock(time_recorder_mutex_);
  FML_CHECK(latest_frame_target_time_.has_value())
      << "GetLatestFrameTargetTime called before OnAnimatorBeginFrame";
  // Covered by FML_CHECK().
  // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
  return latest_frame_target_time_.value();
}

// |Rasterizer::Delegate|
bool Shell::ShouldDiscardLayerTree(int64_t view_id,
                                   const flutter::LayerTree& tree) {
  std::scoped_lock<std::mutex> lock(resize_mutex_);
  auto expected_frame_size = ExpectedFrameSize(view_id);
  return !expected_frame_size.isEmpty() &&
         tree.frame_size() != expected_frame_size;
}

// |ServiceProtocol::Handler|
fml::RefPtr<fml::TaskRunner> Shell::GetServiceProtocolHandlerTaskRunner(
    std::string_view method) const {
  FML_DCHECK(is_set_up_);
  auto found = service_protocol_handlers_.find(method);
  if (found != service_protocol_handlers_.end()) {
    return found->second.first;
  }
  return task_runners_.GetUITaskRunner();
}

// |ServiceProtocol::Handler|
bool Shell::HandleServiceProtocolMessage(
    std::string_view method,  // one if the extension names specified above.
    const ServiceProtocolMap& params,
    rapidjson::Document* response) {
  auto found = service_protocol_handlers_.find(method);
  if (found != service_protocol_handlers_.end()) {
    return found->second.second(params, response);
  }
  return false;
}

// |ServiceProtocol::Handler|
ServiceProtocol::Handler::Description Shell::GetServiceProtocolDescription()
    const {
  FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());

  if (!weak_engine_) {
    return ServiceProtocol::Handler::Description();
  }

  return {
      weak_engine_->GetUIIsolateMainPort(),
      weak_engine_->GetUIIsolateName(),
  };
}

static void ServiceProtocolParameterError(rapidjson::Document* response,
                                          std::string error_details) {
  auto& allocator = response->GetAllocator();
  response->SetObject();
  const int64_t kInvalidParams = -32602;
  response->AddMember("code", kInvalidParams, allocator);
  response->AddMember("message", "Invalid params", allocator);
  {
    rapidjson::Value details(rapidjson::kObjectType);
    details.AddMember("details", std::move(error_details), allocator);
    response->AddMember("data", details, allocator);
  }
}

static void ServiceProtocolFailureError(rapidjson::Document* response,
                                        std::string message) {
  auto& allocator = response->GetAllocator();
  response->SetObject();
  const int64_t kJsonServerError = -32000;
  response->AddMember("code", kJsonServerError, allocator);
  response->AddMember("message", std::move(message), allocator);
}

// Service protocol handler
bool Shell::OnServiceProtocolScreenshot(
    const ServiceProtocol::Handler::ServiceProtocolMap& params,
    rapidjson::Document* response) {
  FML_DCHECK(task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread());
  auto screenshot = rasterizer_->ScreenshotLastLayerTree(
      Rasterizer::ScreenshotType::CompressedImage, true);
  if (screenshot.data) {
    response->SetObject();
    auto& allocator = response->GetAllocator();
    response->AddMember("type", "Screenshot", allocator);
    rapidjson::Value image;
    image.SetString(static_cast<const char*>(screenshot.data->data()),
                    screenshot.data->size(), allocator);
    response->AddMember("screenshot", image, allocator);
    return true;
  }
  ServiceProtocolFailureError(response, "Could not capture image screenshot.");
  return false;
}

// Service protocol handler
bool Shell::OnServiceProtocolScreenshotSKP(
    const ServiceProtocol::Handler::ServiceProtocolMap& params,
    rapidjson::Document* response) {
  FML_DCHECK(task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread());
  if (settings_.enable_impeller) {
    ServiceProtocolFailureError(
        response, "Cannot capture SKP screenshot with Impeller enabled.");
    return false;
  }
  auto screenshot = rasterizer_->ScreenshotLastLayerTree(
      Rasterizer::ScreenshotType::SkiaPicture, true);
  if (screenshot.data) {
    response->SetObject();
    auto& allocator = response->GetAllocator();
    response->AddMember("type", "ScreenshotSkp", allocator);
    rapidjson::Value skp;
    skp.SetString(static_cast<const char*>(screenshot.data->data()),
                  screenshot.data->size(), allocator);
    response->AddMember("skp", skp, allocator);
    return true;
  }
  ServiceProtocolFailureError(response, "Could not capture SKP screenshot.");
  return false;
}

// Service protocol handler
bool Shell::OnServiceProtocolRunInView(
    const ServiceProtocol::Handler::ServiceProtocolMap& params,
    rapidjson::Document* response) {
  FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());

  if (params.count("mainScript") == 0) {
    ServiceProtocolParameterError(response,
                                  "'mainScript' parameter is missing.");
    return false;
  }

  if (params.count("assetDirectory") == 0) {
    ServiceProtocolParameterError(response,
                                  "'assetDirectory' parameter is missing.");
    return false;
  }

  std::string main_script_path =
      fml::paths::FromURI(params.at("mainScript").data());
  std::string asset_directory_path =
      fml::paths::FromURI(params.at("assetDirectory").data());

  auto main_script_file_mapping =
      std::make_unique<fml::FileMapping>(fml::OpenFile(
          main_script_path.c_str(), false, fml::FilePermission::kRead));

  auto isolate_configuration = IsolateConfiguration::CreateForKernel(
      std::move(main_script_file_mapping));

  RunConfiguration configuration(std::move(isolate_configuration));

  configuration.SetEntrypointAndLibrary(engine_->GetLastEntrypoint(),
                                        engine_->GetLastEntrypointLibrary());
  configuration.SetEntrypointArgs(engine_->GetLastEntrypointArgs());

  configuration.AddAssetResolver(std::make_unique<DirectoryAssetBundle>(
      fml::OpenDirectory(asset_directory_path.c_str(), false,
                         fml::FilePermission::kRead),
      false));

  // Preserve any original asset resolvers to avoid syncing unchanged assets
  // over the DevFS connection.
  auto old_asset_manager = engine_->GetAssetManager();
  if (old_asset_manager != nullptr) {
    for (auto& old_resolver : old_asset_manager->TakeResolvers()) {
      if (old_resolver->IsValidAfterAssetManagerChange()) {
        configuration.AddAssetResolver(std::move(old_resolver));
      }
    }
  }

  auto& allocator = response->GetAllocator();
  response->SetObject();
  if (engine_->Restart(std::move(configuration))) {
    response->AddMember("type", "Success", allocator);
    auto new_description = GetServiceProtocolDescription();
    rapidjson::Value view(rapidjson::kObjectType);
    new_description.Write(this, view, allocator);
    response->AddMember("view", view, allocator);
    return true;
  } else {
    FML_DLOG(ERROR) << "Could not run configuration in engine.";
    ServiceProtocolFailureError(response,
                                "Could not run configuration in engine.");
    return false;
  }

  FML_DCHECK(false);
  return false;
}

// Service protocol handler
bool Shell::OnServiceProtocolFlushUIThreadTasks(
    const ServiceProtocol::Handler::ServiceProtocolMap& params,
    rapidjson::Document* response) {
  FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());
  // This API should not be invoked by production code.
  // It can potentially starve the service isolate if the main isolate pauses
  // at a breakpoint or is in an infinite loop.
  //
  // It should be invoked from the VM Service and blocks it until UI thread
  // tasks are processed.
  response->SetObject();
  response->AddMember("type", "Success", response->GetAllocator());
  return true;
}

bool Shell::OnServiceProtocolGetDisplayRefreshRate(
    const ServiceProtocol::Handler::ServiceProtocolMap& params,
    rapidjson::Document* response) {
  FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());
  response->SetObject();
  response->AddMember("type", "DisplayRefreshRate", response->GetAllocator());
  response->AddMember("fps", display_manager_->GetMainDisplayRefreshRate(),
                      response->GetAllocator());
  return true;
}

double Shell::GetMainDisplayRefreshRate() {
  return display_manager_->GetMainDisplayRefreshRate();
}

void Shell::RegisterImageDecoder(ImageGeneratorFactory factory,
                                 int32_t priority) {
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
  FML_DCHECK(is_set_up_);

  fml::TaskRunner::RunNowOrPostTask(
      task_runners_.GetUITaskRunner(),
      [engine = engine_->GetWeakPtr(), factory = std::move(factory),
       priority]() {
        if (engine) {
          engine->GetImageGeneratorRegistry()->AddFactory(factory, priority);
        }
      });
}

bool Shell::OnServiceProtocolGetSkSLs(
    const ServiceProtocol::Handler::ServiceProtocolMap& params,
    rapidjson::Document* response) {
  FML_DCHECK(task_runners_.GetIOTaskRunner()->RunsTasksOnCurrentThread());
  response->SetObject();
  response->AddMember("type", "GetSkSLs", response->GetAllocator());

  rapidjson::Value shaders_json(rapidjson::kObjectType);
#if !SLIMPELLER
  PersistentCache* persistent_cache = PersistentCache::GetCacheForProcess();
  std::vector<PersistentCache::SkSLCache> sksls = persistent_cache->LoadSkSLs();
  for (const auto& sksl : sksls) {
    size_t b64_size = Base64::EncodedSize(sksl.value->size());
    sk_sp<SkData> b64_data = SkData::MakeUninitialized(b64_size + 1);
    char* b64_char = static_cast<char*>(b64_data->writable_data());
    Base64::Encode(sksl.value->data(), sksl.value->size(), b64_char);
    b64_char[b64_size] = 0;  // make it null terminated for printing
    rapidjson::Value shader_value(b64_char, response->GetAllocator());
    std::string_view key_view(reinterpret_cast<const char*>(sksl.key->data()),
                              sksl.key->size());
    auto encode_result = fml::Base32Encode(key_view);
    if (!encode_result.first) {
      continue;
    }
    rapidjson::Value shader_key(encode_result.second, response->GetAllocator());
    shaders_json.AddMember(shader_key, shader_value, response->GetAllocator());
  }
#endif  //  !SLIMPELLER
  response->AddMember("SkSLs", shaders_json, response->GetAllocator());
  return true;
}

bool Shell::OnServiceProtocolEstimateRasterCacheMemory(
    const ServiceProtocol::Handler::ServiceProtocolMap& params,
    rapidjson::Document* response) {
  FML_DCHECK(task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread());

  uint64_t layer_cache_byte_size = 0u;
  uint64_t picture_cache_byte_size = 0u;

#if !SLIMPELLER
  const auto& raster_cache = rasterizer_->compositor_context()->raster_cache();
  layer_cache_byte_size = raster_cache.EstimateLayerCacheByteSize();
  picture_cache_byte_size = raster_cache.EstimatePictureCacheByteSize();
#endif  //  !SLIMPELLER

  response->SetObject();
  response->AddMember("type", "EstimateRasterCacheMemory",
                      response->GetAllocator());
  response->AddMember<uint64_t>("layerBytes", layer_cache_byte_size,
                                response->GetAllocator());
  response->AddMember<uint64_t>("pictureBytes", picture_cache_byte_size,
                                response->GetAllocator());
  return true;
}

// Service protocol handler
bool Shell::OnServiceProtocolSetAssetBundlePath(
    const ServiceProtocol::Handler::ServiceProtocolMap& params,
    rapidjson::Document* response) {
  FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());

  if (params.count("assetDirectory") == 0) {
    ServiceProtocolParameterError(response,
                                  "'assetDirectory' parameter is missing.");
    return false;
  }

  auto& allocator = response->GetAllocator();
  response->SetObject();

  auto asset_manager = std::make_shared<AssetManager>();

  if (!asset_manager->PushFront(std::make_unique<DirectoryAssetBundle>(
          fml::OpenDirectory(params.at("assetDirectory").data(), false,
                             fml::FilePermission::kRead),
          false))) {
    // The new asset directory path was invalid.
    FML_DLOG(ERROR) << "Could not update asset directory.";
    ServiceProtocolFailureError(response, "Could not update asset directory.");
    return false;
  }

  // Preserve any original asset resolvers to avoid syncing unchanged assets
  // over the DevFS connection.
  auto old_asset_manager = engine_->GetAssetManager();
  if (old_asset_manager != nullptr) {
    for (auto& old_resolver : old_asset_manager->TakeResolvers()) {
      if (old_resolver->IsValidAfterAssetManagerChange()) {
        asset_manager->PushBack(std::move(old_resolver));
      }
    }
  }

  if (engine_->UpdateAssetManager(asset_manager)) {
    response->AddMember("type", "Success", allocator);
    auto new_description = GetServiceProtocolDescription();
    rapidjson::Value view(rapidjson::kObjectType);
    new_description.Write(this, view, allocator);
    response->AddMember("view", view, allocator);
    return true;
  } else {
    FML_DLOG(ERROR) << "Could not update asset directory.";
    ServiceProtocolFailureError(response, "Could not update asset directory.");
    return false;
  }

  FML_DCHECK(false);
  return false;
}

static rapidjson::Value SerializeLayerSnapshot(
    double device_pixel_ratio,
    const LayerSnapshotData& snapshot,
    rapidjson::Document* response) {
  auto& allocator = response->GetAllocator();
  rapidjson::Value result;
  result.SetObject();
  result.AddMember("layer_unique_id", snapshot.GetLayerUniqueId(), allocator);
  result.AddMember("duration_micros", snapshot.GetDuration().ToMicroseconds(),
                   allocator);

  const SkRect bounds = snapshot.GetBounds();
  result.AddMember("top", bounds.top(), allocator);
  result.AddMember("left", bounds.left(), allocator);
  result.AddMember("width", bounds.width(), allocator);
  result.AddMember("height", bounds.height(), allocator);

  sk_sp<SkData> snapshot_bytes = snapshot.GetSnapshot();
  if (snapshot_bytes) {
    rapidjson::Value image;
    image.SetArray();
    const uint8_t* data =
        reinterpret_cast<const uint8_t*>(snapshot_bytes->data());
    for (size_t i = 0; i < snapshot_bytes->size(); i++) {
      image.PushBack(data[i], allocator);
    }
    result.AddMember("snapshot", image, allocator);
  }
  return result;
}

bool Shell::OnServiceProtocolRenderFrameWithRasterStats(
    const ServiceProtocol::Handler::ServiceProtocolMap& params,
    rapidjson::Document* response) {
  FML_DCHECK(task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread());

  // Impeller does not support this protocol method.
  if (io_manager_->GetImpellerContext()) {
    const char* error = "Raster status not supported on Impeller backend.";
    ServiceProtocolFailureError(response, error);
    return false;
  }

  // TODO(dkwingsmt): This method only handles view #0, including the snapshot
  // and the frame size. We need to adapt this method to multi-view.
  // https://github.com/flutter/flutter/issues/131892
  int64_t view_id = kFlutterImplicitViewId;
  if (auto last_layer_tree = rasterizer_->GetLastLayerTree(view_id)) {
    auto& allocator = response->GetAllocator();
    response->SetObject();
    response->AddMember("type", "RenderFrameWithRasterStats", allocator);

    // When rendering the last layer tree, we do not need to build a frame,
    // invariants in FrameTimingRecorder enforce that raster timings can not be
    // set before build-end.
    auto frame_timings_recorder = std::make_unique<FrameTimingsRecorder>();
    const auto now = fml::TimePoint::Now();
    frame_timings_recorder->RecordVsync(now, now);
    frame_timings_recorder->RecordBuildStart(now);
    frame_timings_recorder->RecordBuildEnd(now);

    last_layer_tree->enable_leaf_layer_tracing(true);
    rasterizer_->DrawLastLayerTrees(std::move(frame_timings_recorder));
    last_layer_tree->enable_leaf_layer_tracing(false);

    rapidjson::Value snapshots;
    snapshots.SetArray();

    LayerSnapshotStore& store =
        rasterizer_->compositor_context()->snapshot_store();
    for (const LayerSnapshotData& data : store) {
      snapshots.PushBack(
          SerializeLayerSnapshot(device_pixel_ratio_, data, response),
          allocator);
    }

    response->AddMember("snapshots", snapshots, allocator);

    const auto& frame_size = ExpectedFrameSize(view_id);
    response->AddMember("frame_width", frame_size.width(), allocator);
    response->AddMember("frame_height", frame_size.height(), allocator);

    return true;
  } else {
    const char* error =
        "Failed to render the last frame with raster stats."
        " Rasterizer does not hold a valid last layer tree."
        " This could happen if this method was invoked before a frame was "
        "rendered";
    FML_DLOG(ERROR) << error;
    ServiceProtocolFailureError(response, error);
    return false;
  }
}

void Shell::SendFontChangeNotification() {
  // After system fonts are reloaded, we send a system channel message
  // to notify flutter framework.
  rapidjson::Document document;
  document.SetObject();
  auto& allocator = document.GetAllocator();
  rapidjson::Value message_value;
  message_value.SetString(kFontChange, allocator);
  document.AddMember(kTypeKey, message_value, allocator);

  rapidjson::StringBuffer buffer;
  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
  document.Accept(writer);
  std::string message = buffer.GetString();
  std::unique_ptr<PlatformMessage> fontsChangeMessage =
      std::make_unique<flutter::PlatformMessage>(
          kSystemChannel,
          fml::MallocMapping::Copy(message.c_str(), message.length()), nullptr);
  OnPlatformViewDispatchPlatformMessage(std::move(fontsChangeMessage));
}

bool Shell::OnServiceProtocolReloadAssetFonts(
    const ServiceProtocol::Handler::ServiceProtocolMap& params,
    rapidjson::Document* response) {
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
  if (!engine_) {
    return false;
  }
  engine_->GetFontCollection().RegisterFonts(engine_->GetAssetManager());
  engine_->GetFontCollection().GetFontCollection()->ClearFontFamilyCache();
  SendFontChangeNotification();

  auto& allocator = response->GetAllocator();
  response->SetObject();
  response->AddMember("type", "Success", allocator);

  return true;
}

void Shell::OnPlatformViewAddView(int64_t view_id,
                                  const ViewportMetrics& viewport_metrics,
                                  AddViewCallback callback) {
  TRACE_EVENT0("flutter", "Shell::AddView");
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
  FML_DCHECK(view_id != kFlutterImplicitViewId)
      << "Unexpected request to add the implicit view #"
      << kFlutterImplicitViewId << ". This view should never be added.";

  task_runners_.GetUITaskRunner()->PostTask([engine = engine_->GetWeakPtr(),  //
                                             viewport_metrics,                //
                                             view_id,                         //
                                             callback = std::move(callback)   //
  ] {
    if (engine) {
      engine->AddView(view_id, viewport_metrics, callback);
    }
  });
}

void Shell::OnPlatformViewRemoveView(int64_t view_id,
                                     RemoveViewCallback callback) {
  TRACE_EVENT0("flutter", "Shell::RemoveView");
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
  FML_DCHECK(view_id != kFlutterImplicitViewId)
      << "Unexpected request to remove the implicit view #"
      << kFlutterImplicitViewId << ". This view should never be removed.";

  expected_frame_sizes_.erase(view_id);
  task_runners_.GetUITaskRunner()->PostTask(
      [&task_runners = task_runners_,           //
       engine = engine_->GetWeakPtr(),          //
       rasterizer = rasterizer_->GetWeakPtr(),  //
       view_id,                                 //
       callback = std::move(callback)           //
  ] {
        if (engine) {
          bool removed = engine->RemoveView(view_id);
          callback(removed);
        }
        // Don't wait for the raster task here, which only cleans up memory and
        // does not affect functionality. Make sure it is done after Dart
        // removes the view to avoid receiving another rasterization request
        // that adds back the view record.
        task_runners.GetRasterTaskRunner()->PostTask([rasterizer, view_id]() {
          if (rasterizer) {
            rasterizer->CollectView(view_id);
          }
        });
      });
}

Rasterizer::Screenshot Shell::Screenshot(
    Rasterizer::ScreenshotType screenshot_type,
    bool base64_encode) {
  if (settings_.enable_impeller) {
    switch (screenshot_type) {
      case Rasterizer::ScreenshotType::SkiaPicture:
        FML_LOG(ERROR)
            << "Impeller backend cannot produce ScreenshotType::SkiaPicture.";
        return {};
      case Rasterizer::ScreenshotType::UncompressedImage:
      case Rasterizer::ScreenshotType::CompressedImage:
      case Rasterizer::ScreenshotType::SurfaceData:
        break;
    }
  }
  TRACE_EVENT0("flutter", "Shell::Screenshot");
  fml::AutoResetWaitableEvent latch;
  Rasterizer::Screenshot screenshot;
  fml::TaskRunner::RunNowOrPostTask(
      task_runners_.GetRasterTaskRunner(), [&latch,                        //
                                            rasterizer = GetRasterizer(),  //
                                            &screenshot,                   //
                                            screenshot_type,               //
                                            base64_encode                  //
  ]() {
        if (rasterizer) {
          screenshot = rasterizer->ScreenshotLastLayerTree(screenshot_type,
                                                           base64_encode);
        }
        latch.Signal();
      });
  latch.Wait();
  return screenshot;
}

fml::Status Shell::WaitForFirstFrame(fml::TimeDelta timeout) {
  FML_DCHECK(is_set_up_);
  if (task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread() ||
      task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread()) {
    return fml::Status(fml::StatusCode::kFailedPrecondition,
                       "WaitForFirstFrame called from thread that can't wait "
                       "because it is responsible for generating the frame.");
  }

  // Check for overflow.
  auto now = std::chrono::steady_clock::now();
  auto max_duration = std::chrono::steady_clock::time_point::max() - now;
  auto desired_duration = std::chrono::milliseconds(timeout.ToMilliseconds());
  auto duration =
      now + (desired_duration > max_duration ? max_duration : desired_duration);

  std::unique_lock<std::mutex> lock(waiting_for_first_frame_mutex_);
  bool success = waiting_for_first_frame_condition_.wait_until(
      lock, duration, [&waiting_for_first_frame = waiting_for_first_frame_] {
        return !waiting_for_first_frame.load();
      });
  if (success) {
    return fml::Status();
  } else {
    return fml::Status(fml::StatusCode::kDeadlineExceeded, "timeout");
  }
}

bool Shell::ReloadSystemFonts() {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  if (!engine_) {
    return false;
  }
  engine_->SetupDefaultFontManager();
  engine_->GetFontCollection().GetFontCollection()->ClearFontFamilyCache();
  // After system fonts are reloaded, we send a system channel message
  // to notify flutter framework.
  SendFontChangeNotification();
  return true;
}

std::shared_ptr<const fml::SyncSwitch> Shell::GetIsGpuDisabledSyncSwitch()
    const {
  return is_gpu_disabled_sync_switch_;
}

void Shell::SetGpuAvailability(GpuAvailability availability) {
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
  switch (availability) {
    case GpuAvailability::kAvailable:
      is_gpu_disabled_sync_switch_->SetSwitch(false);
      return;
    case GpuAvailability::kFlushAndMakeUnavailable: {
      fml::AutoResetWaitableEvent latch;
      fml::TaskRunner::RunNowOrPostTask(
          task_runners_.GetIOTaskRunner(),
          [io_manager = io_manager_.get(), &latch]() {
            io_manager->GetSkiaUnrefQueue()->Drain();
            latch.Signal();
          });
      latch.Wait();
    }
      // FALLTHROUGH
    case GpuAvailability::kUnavailable:
      is_gpu_disabled_sync_switch_->SetSwitch(true);
      return;
    default:
      FML_DCHECK(false);
  }
}

void Shell::OnDisplayUpdates(std::vector<std::unique_ptr<Display>> displays) {
  FML_DCHECK(is_set_up_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  std::vector<DisplayData> display_data;
  display_data.reserve(displays.size());
  for (const auto& display : displays) {
    display_data.push_back(display->GetDisplayData());
  }
  task_runners_.GetUITaskRunner()->PostTask(
      [engine = engine_->GetWeakPtr(),
       display_data = std::move(display_data)]() {
        if (engine) {
          engine->SetDisplays(display_data);
        }
      });

  display_manager_->HandleDisplayUpdates(std::move(displays));
}

fml::TimePoint Shell::GetCurrentTimePoint() {
  return fml::TimePoint::Now();
}

const std::shared_ptr<PlatformMessageHandler>&
Shell::GetPlatformMessageHandler() const {
  return platform_message_handler_;
}

const std::weak_ptr<VsyncWaiter> Shell::GetVsyncWaiter() const {
  if (!engine_) {
    return {};
  }
  return engine_->GetVsyncWaiter();
}

const std::shared_ptr<fml::ConcurrentTaskRunner>
Shell::GetConcurrentWorkerTaskRunner() const {
  FML_DCHECK(vm_);
  if (!vm_) {
    return nullptr;
  }
  return vm_->GetConcurrentWorkerTaskRunner();
}

SkISize Shell::ExpectedFrameSize(int64_t view_id) {
  auto found = expected_frame_sizes_.find(view_id);
  if (found == expected_frame_sizes_.end()) {
    return SkISize::MakeEmpty();
  }
  return found->second;
}

}  // namespace flutter
