Flutter Engine
shell.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #define RAPIDJSON_HAS_STDSTRING 1
6 #include "flutter/shell/common/shell.h"
7 
8 #include <memory>
9 #include <sstream>
10 #include <vector>
11 
12 #include "flutter/assets/directory_asset_bundle.h"
13 #include "flutter/common/graphics/persistent_cache.h"
14 #include "flutter/fml/base32.h"
15 #include "flutter/fml/file.h"
16 #include "flutter/fml/icu_util.h"
17 #include "flutter/fml/log_settings.h"
18 #include "flutter/fml/logging.h"
19 #include "flutter/fml/make_copyable.h"
20 #include "flutter/fml/message_loop.h"
21 #include "flutter/fml/paths.h"
22 #include "flutter/fml/trace_event.h"
23 #include "flutter/fml/unique_fd.h"
24 #include "flutter/runtime/dart_vm.h"
25 #include "flutter/shell/common/engine.h"
26 #include "flutter/shell/common/skia_event_tracer_impl.h"
27 #include "flutter/shell/common/switches.h"
28 #include "flutter/shell/common/vsync_waiter.h"
29 #include "rapidjson/stringbuffer.h"
30 #include "rapidjson/writer.h"
31 #include "third_party/dart/runtime/include/dart_tools_api.h"
32 #include "third_party/skia/include/core/SkGraphics.h"
33 #include "third_party/skia/include/utils/SkBase64.h"
35 
36 namespace flutter {
37 
38 constexpr char kSkiaChannel[] = "flutter/skia";
39 constexpr char kSystemChannel[] = "flutter/system";
40 constexpr char kTypeKey[] = "type";
41 constexpr char kFontChange[] = "fontsChange";
42 
43 namespace {
44 
45 std::unique_ptr<Engine> CreateEngine(
46  Engine::Delegate& delegate,
47  const PointerDataDispatcherMaker& dispatcher_maker,
48  DartVM& vm,
49  fml::RefPtr<const DartSnapshot> isolate_snapshot,
50  TaskRunners task_runners,
51  const PlatformData& platform_data,
52  Settings settings,
53  std::unique_ptr<Animator> animator,
54  fml::WeakPtr<IOManager> io_manager,
55  fml::RefPtr<SkiaUnrefQueue> unref_queue,
56  fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
57  std::shared_ptr<VolatilePathTracker> volatile_path_tracker) {
58  return std::make_unique<Engine>(delegate, //
59  dispatcher_maker, //
60  vm, //
61  isolate_snapshot, //
62  task_runners, //
63  platform_data, //
64  settings, //
65  std::move(animator), //
66  io_manager, //
67  unref_queue, //
68  snapshot_delegate, //
69  volatile_path_tracker);
70 }
71 
72 // Though there can be multiple shells, some settings apply to all components in
73 // the process. These have to be set up before the shell or any of its
74 // sub-components can be initialized. In a perfect world, this would be empty.
75 // TODO(chinmaygarde): The unfortunate side effect of this call is that settings
76 // that cause shell initialization failures will still lead to some of their
77 // settings being applied.
78 void PerformInitializationTasks(Settings& settings) {
79  {
80  fml::LogSettings log_settings;
81  log_settings.min_log_level =
83  fml::SetLogSettings(log_settings);
84  }
85 
86  static std::once_flag gShellSettingsInitialization = {};
87  std::call_once(gShellSettingsInitialization, [&settings] {
88  if (settings.engine_start_timestamp.count() == 0) {
89  settings.engine_start_timestamp =
90  std::chrono::microseconds(Dart_TimelineGetMicros());
91  }
92 
94  [](const char* message) { FML_LOG(ERROR) << message; });
95 
96  if (settings.trace_skia) {
98  }
99 
100  if (!settings.trace_allowlist.empty()) {
102  }
103 
104  if (!settings.skia_deterministic_rendering_on_cpu) {
105  SkGraphics::Init();
106  } else {
107  FML_DLOG(INFO) << "Skia deterministic rendering is enabled.";
108  }
109 
110  if (settings.icu_initialization_required) {
111  if (settings.icu_data_path.size() != 0) {
113  } else if (settings.icu_mapper) {
115  } else {
116  FML_DLOG(WARNING) << "Skipping ICU initialization in the shell.";
117  }
118  }
119  });
120 
122 }
123 
124 } // namespace
125 
126 std::unique_ptr<Shell> Shell::Create(
127  const PlatformData& platform_data,
128  TaskRunners task_runners,
129  Settings settings,
130  const Shell::CreateCallback<PlatformView>& on_create_platform_view,
131  const Shell::CreateCallback<Rasterizer>& on_create_rasterizer,
132  bool is_gpu_disabled) {
133  // This must come first as it initializes tracing.
134  PerformInitializationTasks(settings);
135 
136  TRACE_EVENT0("flutter", "Shell::Create");
137 
138  // Always use the `vm_snapshot` and `isolate_snapshot` provided by the
139  // settings to launch the VM. If the VM is already running, the snapshot
140  // arguments are ignored.
141  auto vm_snapshot = DartSnapshot::VMSnapshotFromSettings(settings);
142  auto isolate_snapshot = DartSnapshot::IsolateSnapshotFromSettings(settings);
143  auto vm = DartVMRef::Create(settings, vm_snapshot, isolate_snapshot);
144  FML_CHECK(vm) << "Must be able to initialize the VM.";
145 
146  // If the settings did not specify an `isolate_snapshot`, fall back to the
147  // one the VM was launched with.
148  if (!isolate_snapshot) {
149  isolate_snapshot = vm->GetVMData()->GetIsolateSnapshot();
150  }
151  return CreateWithSnapshot(std::move(platform_data), //
152  std::move(task_runners), //
153  /*parent_merger=*/nullptr, //
154  std::move(settings), //
155  std::move(vm), //
156  std::move(isolate_snapshot), //
157  std::move(on_create_platform_view), //
158  std::move(on_create_rasterizer), //
159  CreateEngine, is_gpu_disabled);
160 }
161 
162 std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
163  DartVMRef vm,
165  TaskRunners task_runners,
166  const PlatformData& platform_data,
167  Settings settings,
168  fml::RefPtr<const DartSnapshot> isolate_snapshot,
169  const Shell::CreateCallback<PlatformView>& on_create_platform_view,
170  const Shell::CreateCallback<Rasterizer>& on_create_rasterizer,
171  const Shell::EngineCreateCallback& on_create_engine,
172  bool is_gpu_disabled) {
173  if (!task_runners.IsValid()) {
174  FML_LOG(ERROR) << "Task runners to run the shell were invalid.";
175  return nullptr;
176  }
177 
178  auto shell = std::unique_ptr<Shell>(
179  new Shell(std::move(vm), task_runners, parent_merger, settings,
180  std::make_shared<VolatilePathTracker>(
181  task_runners.GetUITaskRunner(),
183  is_gpu_disabled));
184 
185  // Create the rasterizer on the raster thread.
186  std::promise<std::unique_ptr<Rasterizer>> rasterizer_promise;
187  auto rasterizer_future = rasterizer_promise.get_future();
188  std::promise<fml::WeakPtr<SnapshotDelegate>> snapshot_delegate_promise;
189  auto snapshot_delegate_future = snapshot_delegate_promise.get_future();
191  task_runners.GetRasterTaskRunner(), [&rasterizer_promise, //
192  &snapshot_delegate_promise,
193  on_create_rasterizer, //
194  shell = shell.get() //
195  ]() {
196  TRACE_EVENT0("flutter", "ShellSetupGPUSubsystem");
197  std::unique_ptr<Rasterizer> rasterizer(on_create_rasterizer(*shell));
198  snapshot_delegate_promise.set_value(rasterizer->GetSnapshotDelegate());
199  rasterizer_promise.set_value(std::move(rasterizer));
200  });
201 
202  // Create the platform view on the platform thread (this thread).
203  auto platform_view = on_create_platform_view(*shell.get());
204  if (!platform_view || !platform_view->GetWeakPtr()) {
205  return nullptr;
206  }
207 
208  // Ask the platform view for the vsync waiter. This will be used by the engine
209  // to create the animator.
210  auto vsync_waiter = platform_view->CreateVSyncWaiter();
211  if (!vsync_waiter) {
212  return nullptr;
213  }
214 
215  // Create the IO manager on the IO thread. The IO manager must be initialized
216  // first because it has state that the other subsystems depend on. It must
217  // first be booted and the necessary references obtained to initialize the
218  // other subsystems.
219  std::promise<std::unique_ptr<ShellIOManager>> io_manager_promise;
220  auto io_manager_future = io_manager_promise.get_future();
221  std::promise<fml::WeakPtr<ShellIOManager>> weak_io_manager_promise;
222  auto weak_io_manager_future = weak_io_manager_promise.get_future();
223  std::promise<fml::RefPtr<SkiaUnrefQueue>> unref_queue_promise;
224  auto unref_queue_future = unref_queue_promise.get_future();
225  auto io_task_runner = shell->GetTaskRunners().GetIOTaskRunner();
226 
227  // TODO(gw280): The WeakPtr here asserts that we are derefing it on the
228  // same thread as it was created on. We are currently on the IO thread
229  // inside this lambda but we need to deref the PlatformView, which was
230  // constructed on the platform thread.
231  //
232  // https://github.com/flutter/flutter/issues/42948
234  io_task_runner,
235  [&io_manager_promise, //
236  &weak_io_manager_promise, //
237  &unref_queue_promise, //
238  platform_view = platform_view->GetWeakPtr(), //
239  io_task_runner, //
240  is_backgrounded_sync_switch = shell->GetIsGpuDisabledSyncSwitch() //
241  ]() {
242  TRACE_EVENT0("flutter", "ShellSetupIOSubsystem");
243  auto io_manager = std::make_unique<ShellIOManager>(
244  platform_view.getUnsafe()->CreateResourceContext(),
245  is_backgrounded_sync_switch, io_task_runner);
246  weak_io_manager_promise.set_value(io_manager->GetWeakPtr());
247  unref_queue_promise.set_value(io_manager->GetSkiaUnrefQueue());
248  io_manager_promise.set_value(std::move(io_manager));
249  });
250 
251  // Send dispatcher_maker to the engine constructor because shell won't have
252  // platform_view set until Shell::Setup is called later.
253  auto dispatcher_maker = platform_view->GetDispatcherMaker();
254 
255  // Create the engine on the UI thread.
256  std::promise<std::unique_ptr<Engine>> engine_promise;
257  auto engine_future = engine_promise.get_future();
259  shell->GetTaskRunners().GetUITaskRunner(),
260  fml::MakeCopyable([&engine_promise, //
261  shell = shell.get(), //
262  &dispatcher_maker, //
263  &platform_data, //
264  isolate_snapshot = std::move(isolate_snapshot), //
265  vsync_waiter = std::move(vsync_waiter), //
266  &weak_io_manager_future, //
267  &snapshot_delegate_future, //
268  &unref_queue_future, //
269  &on_create_engine]() mutable {
270  TRACE_EVENT0("flutter", "ShellSetupUISubsystem");
271  const auto& task_runners = shell->GetTaskRunners();
272 
273  // The animator is owned by the UI thread but it gets its vsync pulses
274  // from the platform.
275  auto animator = std::make_unique<Animator>(*shell, task_runners,
276  std::move(vsync_waiter));
277 
278  engine_promise.set_value(
279  on_create_engine(*shell, //
280  dispatcher_maker, //
281  *shell->GetDartVM(), //
282  std::move(isolate_snapshot), //
283  task_runners, //
284  platform_data, //
285  shell->GetSettings(), //
286  std::move(animator), //
287  weak_io_manager_future.get(), //
288  unref_queue_future.get(), //
289  snapshot_delegate_future.get(), //
290  shell->volatile_path_tracker_));
291  }));
292 
293  if (!shell->Setup(std::move(platform_view), //
294  engine_future.get(), //
295  rasterizer_future.get(), //
296  io_manager_future.get()) //
297  ) {
298  return nullptr;
299  }
300 
301  return shell;
302 }
303 
304 std::unique_ptr<Shell> Shell::CreateWithSnapshot(
305  const PlatformData& platform_data,
306  TaskRunners task_runners,
307  fml::RefPtr<fml::RasterThreadMerger> parent_thread_merger,
308  Settings settings,
309  DartVMRef vm,
310  fml::RefPtr<const DartSnapshot> isolate_snapshot,
311  const Shell::CreateCallback<PlatformView>& on_create_platform_view,
312  const Shell::CreateCallback<Rasterizer>& on_create_rasterizer,
313  const Shell::EngineCreateCallback& on_create_engine,
314  bool is_gpu_disabled) {
315  // This must come first as it initializes tracing.
316  PerformInitializationTasks(settings);
317 
318  TRACE_EVENT0("flutter", "Shell::CreateWithSnapshot");
319 
320  const bool callbacks_valid =
321  on_create_platform_view && on_create_rasterizer && on_create_engine;
322  if (!task_runners.IsValid() || !callbacks_valid) {
323  return nullptr;
324  }
325 
327  std::unique_ptr<Shell> shell;
329  task_runners.GetPlatformTaskRunner(),
331  [&latch, //
332  &shell, //
333  parent_thread_merger, //
334  task_runners = std::move(task_runners), //
335  platform_data = std::move(platform_data), //
336  settings = std::move(settings), //
337  vm = std::move(vm), //
338  isolate_snapshot = std::move(isolate_snapshot), //
339  on_create_platform_view = std::move(on_create_platform_view), //
340  on_create_rasterizer = std::move(on_create_rasterizer), //
341  on_create_engine = std::move(on_create_engine),
342  is_gpu_disabled]() mutable {
343  shell = CreateShellOnPlatformThread(
344  std::move(vm), //
345  parent_thread_merger, //
346  std::move(task_runners), //
347  std::move(platform_data), //
348  std::move(settings), //
349  std::move(isolate_snapshot), //
350  std::move(on_create_platform_view), //
351  std::move(on_create_rasterizer), //
352  std::move(on_create_engine), is_gpu_disabled);
353  latch.Signal();
354  }));
355  latch.Wait();
356  return shell;
357 }
358 
359 Shell::Shell(DartVMRef vm,
360  TaskRunners task_runners,
362  Settings settings,
363  std::shared_ptr<VolatilePathTracker> volatile_path_tracker,
364  bool is_gpu_disabled)
365  : task_runners_(std::move(task_runners)),
366  parent_raster_thread_merger_(parent_merger),
367  settings_(std::move(settings)),
368  vm_(std::move(vm)),
369  is_gpu_disabled_sync_switch_(new fml::SyncSwitch(is_gpu_disabled)),
370  volatile_path_tracker_(std::move(volatile_path_tracker)),
371  weak_factory_gpu_(nullptr),
372  weak_factory_(this) {
373  FML_CHECK(vm_) << "Must have access to VM to create a shell.";
374  FML_DCHECK(task_runners_.IsValid());
376 
377  display_manager_ = std::make_unique<DisplayManager>();
378 
379  // Generate a WeakPtrFactory for use with the raster thread. This does not
380  // need to wait on a latch because it can only ever be used from the raster
381  // thread from this class, so we have ordering guarantees.
383  task_runners_.GetRasterTaskRunner(), fml::MakeCopyable([this]() mutable {
384  this->weak_factory_gpu_ =
385  std::make_unique<fml::TaskRunnerAffineWeakPtrFactory<Shell>>(this);
386  }));
387 
388  // Install service protocol handlers.
389 
390  service_protocol_handlers_[ServiceProtocol::kScreenshotExtensionName] = {
391  task_runners_.GetRasterTaskRunner(),
392  std::bind(&Shell::OnServiceProtocolScreenshot, this,
393  std::placeholders::_1, std::placeholders::_2)};
394  service_protocol_handlers_[ServiceProtocol::kScreenshotSkpExtensionName] = {
395  task_runners_.GetRasterTaskRunner(),
396  std::bind(&Shell::OnServiceProtocolScreenshotSKP, this,
397  std::placeholders::_1, std::placeholders::_2)};
398  service_protocol_handlers_[ServiceProtocol::kRunInViewExtensionName] = {
399  task_runners_.GetUITaskRunner(),
400  std::bind(&Shell::OnServiceProtocolRunInView, this, std::placeholders::_1,
401  std::placeholders::_2)};
402  service_protocol_handlers_
404  task_runners_.GetUITaskRunner(),
405  std::bind(&Shell::OnServiceProtocolFlushUIThreadTasks, this,
406  std::placeholders::_1, std::placeholders::_2)};
407  service_protocol_handlers_
409  task_runners_.GetUITaskRunner(),
410  std::bind(&Shell::OnServiceProtocolSetAssetBundlePath, this,
411  std::placeholders::_1, std::placeholders::_2)};
412  service_protocol_handlers_
414  task_runners_.GetUITaskRunner(),
415  std::bind(&Shell::OnServiceProtocolGetDisplayRefreshRate, this,
416  std::placeholders::_1, std::placeholders::_2)};
417  service_protocol_handlers_[ServiceProtocol::kGetSkSLsExtensionName] = {
418  task_runners_.GetIOTaskRunner(),
419  std::bind(&Shell::OnServiceProtocolGetSkSLs, this, std::placeholders::_1,
420  std::placeholders::_2)};
421  service_protocol_handlers_
423  task_runners_.GetRasterTaskRunner(),
424  std::bind(&Shell::OnServiceProtocolEstimateRasterCacheMemory, this,
425  std::placeholders::_1, std::placeholders::_2)};
426 }
427 
430  task_runners_.GetIOTaskRunner());
431 
432  vm_->GetServiceProtocol()->RemoveHandler(this);
433 
434  fml::AutoResetWaitableEvent ui_latch, gpu_latch, platform_latch, io_latch;
435 
437  task_runners_.GetUITaskRunner(),
438  fml::MakeCopyable([this, &ui_latch]() mutable {
439  engine_.reset();
440  ui_latch.Signal();
441  }));
442  ui_latch.Wait();
443 
445  task_runners_.GetRasterTaskRunner(),
447  [this, rasterizer = std::move(rasterizer_), &gpu_latch]() mutable {
448  rasterizer.reset();
449  this->weak_factory_gpu_.reset();
450  gpu_latch.Signal();
451  }));
452  gpu_latch.Wait();
453 
455  task_runners_.GetIOTaskRunner(),
456  fml::MakeCopyable([io_manager = std::move(io_manager_),
457  platform_view = platform_view_.get(),
458  &io_latch]() mutable {
459  io_manager.reset();
460  if (platform_view) {
461  platform_view->ReleaseResourceContext();
462  }
463  io_latch.Signal();
464  }));
465 
466  io_latch.Wait();
467 
468  // The platform view must go last because it may be holding onto platform side
469  // counterparts to resources owned by subsystems running on other threads. For
470  // example, the NSOpenGLContext on the Mac.
472  task_runners_.GetPlatformTaskRunner(),
473  fml::MakeCopyable([platform_view = std::move(platform_view_),
474  &platform_latch]() mutable {
475  platform_view.reset();
476  platform_latch.Signal();
477  }));
478  platform_latch.Wait();
479 }
480 
481 std::unique_ptr<Shell> Shell::Spawn(
482  RunConfiguration run_configuration,
483  const std::string& initial_route,
484  const CreateCallback<PlatformView>& on_create_platform_view,
485  const CreateCallback<Rasterizer>& on_create_rasterizer) const {
486  FML_DCHECK(task_runners_.IsValid());
487  auto shell_maker = [&](bool is_gpu_disabled) {
488  std::unique_ptr<Shell> result(CreateWithSnapshot(
489  PlatformData{}, task_runners_, rasterizer_->GetRasterThreadMerger(),
490  GetSettings(), vm_, vm_->GetVMData()->GetIsolateSnapshot(),
491  on_create_platform_view, on_create_rasterizer,
492  [engine = this->engine_.get(), initial_route](
493  Engine::Delegate& delegate,
494  const PointerDataDispatcherMaker& dispatcher_maker, DartVM& vm,
495  fml::RefPtr<const DartSnapshot> isolate_snapshot,
496  TaskRunners task_runners, const PlatformData& platform_data,
497  Settings settings, std::unique_ptr<Animator> animator,
498  fml::WeakPtr<IOManager> io_manager,
499  fml::RefPtr<SkiaUnrefQueue> unref_queue,
500  fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
501  std::shared_ptr<VolatilePathTracker> volatile_path_tracker) {
502  return engine->Spawn(/*delegate=*/delegate,
503  /*dispatcher_maker=*/dispatcher_maker,
504  /*settings=*/settings,
505  /*animator=*/std::move(animator),
506  /*initial_route=*/initial_route);
507  },
508  is_gpu_disabled));
509  return result;
510  };
511  std::unique_ptr<Shell> result;
512  GetIsGpuDisabledSyncSwitch()->Execute(
514  .SetIfFalse([&] { result = shell_maker(false); })
515  .SetIfTrue([&] { result = shell_maker(true); }));
516  result->shared_resource_context_ = io_manager_->GetSharedResourceContext();
517  result->RunEngine(std::move(run_configuration));
518  return result;
519 }
520 
522  auto trace_id = fml::tracing::TraceNonce();
523  TRACE_EVENT_ASYNC_BEGIN0("flutter", "Shell::NotifyLowMemoryWarning",
524  trace_id);
525  // This does not require a current isolate but does require a running VM.
526  // Since a valid shell will not be returned to the embedder without a valid
527  // DartVMRef, we can be certain that this is a safe spot to assume a VM is
528  // running.
529  ::Dart_NotifyLowMemory();
530 
531  task_runners_.GetRasterTaskRunner()->PostTask(
532  [rasterizer = rasterizer_->GetWeakPtr(), trace_id = trace_id]() {
533  if (rasterizer) {
534  rasterizer->NotifyLowMemoryWarning();
535  }
536  TRACE_EVENT_ASYNC_END0("flutter", "Shell::NotifyLowMemoryWarning",
537  trace_id);
538  });
539  // The IO Manager uses resource cache limits of 0, so it is not necessary
540  // to purge them.
541 }
542 
543 void Shell::RunEngine(RunConfiguration run_configuration) {
544  RunEngine(std::move(run_configuration), nullptr);
545 }
546 
548  RunConfiguration run_configuration,
549  const std::function<void(Engine::RunStatus)>& result_callback) {
550  auto result = [platform_runner = task_runners_.GetPlatformTaskRunner(),
551  result_callback](Engine::RunStatus run_result) {
552  if (!result_callback) {
553  return;
554  }
555  platform_runner->PostTask(
556  [result_callback, run_result]() { result_callback(run_result); });
557  };
558  FML_DCHECK(is_setup_);
560 
562  task_runners_.GetUITaskRunner(),
564  [run_configuration = std::move(run_configuration),
565  weak_engine = weak_engine_, result]() mutable {
566  if (!weak_engine) {
567  FML_LOG(ERROR)
568  << "Could not launch engine with configuration - no engine.";
570  return;
571  }
572  auto run_result = weak_engine->Run(std::move(run_configuration));
573  if (run_result == flutter::Engine::RunStatus::Failure) {
574  FML_LOG(ERROR) << "Could not launch engine with configuration.";
575  }
576  result(run_result);
577  }));
578 }
579 
580 std::optional<DartErrorCode> Shell::GetUIIsolateLastError() const {
581  FML_DCHECK(is_setup_);
583 
584  if (!weak_engine_) {
585  return std::nullopt;
586  }
587  switch (weak_engine_->GetUIIsolateLastError()) {
594  case tonic::kNoError:
595  return DartErrorCode::NoError;
596  }
598 }
599 
601  FML_DCHECK(is_setup_);
603 
604  if (!weak_engine_) {
605  return false;
606  }
607 
608  return weak_engine_->UIIsolateHasLivePorts();
609 }
610 
611 bool Shell::IsSetup() const {
612  return is_setup_;
613 }
614 
615 bool Shell::Setup(std::unique_ptr<PlatformView> platform_view,
616  std::unique_ptr<Engine> engine,
617  std::unique_ptr<Rasterizer> rasterizer,
618  std::unique_ptr<ShellIOManager> io_manager) {
619  if (is_setup_) {
620  return false;
621  }
622 
623  if (!platform_view || !engine || !rasterizer || !io_manager) {
624  return false;
625  }
626 
627  platform_view_ = std::move(platform_view);
628  platform_message_handler_ = platform_view_->GetPlatformMessageHandler();
629  engine_ = std::move(engine);
630  rasterizer_ = std::move(rasterizer);
631  io_manager_ = std::move(io_manager);
632 
633  // Set the external view embedder for the rasterizer.
634  auto view_embedder = platform_view_->CreateExternalViewEmbedder();
635  rasterizer_->SetExternalViewEmbedder(view_embedder);
636  rasterizer_->SetSnapshotSurfaceProducer(
637  platform_view_->CreateSnapshotSurfaceProducer());
638 
639  // The weak ptr must be generated in the platform thread which owns the unique
640  // ptr.
641  weak_engine_ = engine_->GetWeakPtr();
642  weak_rasterizer_ = rasterizer_->GetWeakPtr();
643  weak_platform_view_ = platform_view_->GetWeakPtr();
644 
645  // Setup the time-consuming default font manager right after engine created.
646  if (!settings_.prefetched_default_font_manager) {
648  [engine = weak_engine_] {
649  if (engine) {
650  engine->SetupDefaultFontManager();
651  }
652  });
653  }
654 
655  is_setup_ = true;
656 
658  task_runners_.GetIOTaskRunner());
659 
662 
663  if (settings_.purge_persistent_cache) {
665  }
666 
667  return true;
668 }
669 
670 const Settings& Shell::GetSettings() const {
671  return settings_;
672 }
673 
675  return task_runners_;
676 }
677 
679  const {
680  return parent_raster_thread_merger_;
681 }
682 
684  FML_DCHECK(is_setup_);
685  return weak_rasterizer_;
686 }
687 
689  FML_DCHECK(is_setup_);
690  return weak_engine_;
691 }
692 
694  FML_DCHECK(is_setup_);
695  return weak_platform_view_;
696 }
697 
699  FML_DCHECK(is_setup_);
700  return io_manager_->GetWeakPtr();
701 }
702 
704  return &vm_;
705 }
706 
707 // |PlatformView::Delegate|
708 void Shell::OnPlatformViewCreated(std::unique_ptr<Surface> surface) {
709  TRACE_EVENT0("flutter", "Shell::OnPlatformViewCreated");
710  FML_DCHECK(is_setup_);
712 
713  // Prevent any request to change the thread configuration for raster and
714  // platform queues while the platform view is being created.
715  //
716  // This prevents false positives such as this method starts assuming that the
717  // raster and platform queues have a given thread configuration, but then the
718  // configuration is changed by a task, and the assumption is no longer true.
719  //
720  // This incorrect assumption can lead to deadlock.
721  // See `should_post_raster_task` for more.
722  rasterizer_->DisableThreadMergerIfNeeded();
723 
724  // The normal flow executed by this method is that the platform thread is
725  // starting the sequence and waiting on the latch. Later the UI thread posts
726  // raster_task to the raster thread which signals the latch. If the raster and
727  // the platform threads are the same this results in a deadlock as the
728  // raster_task will never be posted to the platform/raster thread that is
729  // blocked on a latch. To avoid the described deadlock, if the raster and the
730  // platform threads are the same, should_post_raster_task will be false, and
731  // then instead of posting a task to the raster thread, the ui thread just
732  // signals the latch and the platform/raster thread follows with executing
733  // raster_task.
734  const bool should_post_raster_task =
735  !task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread();
736 
738  auto raster_task =
739  fml::MakeCopyable([&waiting_for_first_frame = waiting_for_first_frame_,
740  rasterizer = rasterizer_->GetWeakPtr(), //
741  surface = std::move(surface)]() mutable {
742  if (rasterizer) {
743  // Enables the thread merger which may be used by the external view
744  // embedder.
745  rasterizer->EnableThreadMergerIfNeeded();
746  rasterizer->Setup(std::move(surface));
747  }
748 
749  waiting_for_first_frame.store(true);
750  });
751 
752  // TODO(91717): This probably isn't necessary. The engine should be able to
753  // handle things here via normal lifecycle messages.
754  // https://github.com/flutter/flutter/issues/91717
755  auto ui_task = [engine = engine_->GetWeakPtr()] {
756  if (engine) {
757  engine->OnOutputSurfaceCreated();
758  }
759  };
760 
761  // Threading: Capture platform view by raw pointer and not the weak pointer.
762  // We are going to use the pointer on the IO thread which is not safe with a
763  // weak pointer. However, we are preventing the platform view from being
764  // collected by using a latch.
765  auto* platform_view = platform_view_.get();
766 
767  FML_DCHECK(platform_view);
768 
769  auto io_task = [io_manager = io_manager_->GetWeakPtr(), platform_view,
770  ui_task_runner = task_runners_.GetUITaskRunner(), ui_task,
771  shared_resource_context = shared_resource_context_,
772  raster_task_runner = task_runners_.GetRasterTaskRunner(),
773  raster_task, should_post_raster_task, &latch] {
774  if (io_manager && !io_manager->GetResourceContext()) {
775  sk_sp<GrDirectContext> resource_context;
776  if (shared_resource_context) {
777  resource_context = shared_resource_context;
778  } else {
779  resource_context = platform_view->CreateResourceContext();
780  }
781  io_manager->NotifyResourceContextAvailable(resource_context);
782  }
783  // Step 1: Post a task on the UI thread to tell the engine that it has
784  // an output surface.
785  fml::TaskRunner::RunNowOrPostTask(ui_task_runner, ui_task);
786 
787  // Step 2: Tell the raster thread that it should create a surface for
788  // its rasterizer.
789  if (should_post_raster_task) {
790  fml::TaskRunner::RunNowOrPostTask(raster_task_runner, raster_task);
791  }
792  latch.Signal();
793  };
794 
795  fml::TaskRunner::RunNowOrPostTask(task_runners_.GetIOTaskRunner(), io_task);
796 
797  latch.Wait();
798  if (!should_post_raster_task) {
799  // See comment on should_post_raster_task, in this case the raster_task
800  // wasn't executed, and we just run it here as the platform thread
801  // is the raster thread.
802  raster_task();
803  }
804 }
805 
806 // |PlatformView::Delegate|
807 void Shell::OnPlatformViewDestroyed() {
808  TRACE_EVENT0("flutter", "Shell::OnPlatformViewDestroyed");
809  FML_DCHECK(is_setup_);
811 
812  // Prevent any request to change the thread configuration for raster and
813  // platform queues while the platform view is being destroyed.
814  //
815  // This prevents false positives such as this method starts assuming that the
816  // raster and platform queues have a given thread configuration, but then the
817  // configuration is changed by a task, and the assumption is no longer true.
818  //
819  // This incorrect assumption can lead to deadlock.
820  rasterizer_->DisableThreadMergerIfNeeded();
821 
822  // Note:
823  // This is a synchronous operation because certain platforms depend on
824  // setup/suspension of all activities that may be interacting with the GPU in
825  // a synchronous fashion.
826  // The UI thread does not need to be serialized here - there is sufficient
827  // guardrailing in the rasterizer to allow the UI thread to post work to it
828  // even after the surface has been torn down.
829 
831 
832  auto io_task = [io_manager = io_manager_.get(), &latch]() {
833  // Execute any pending Skia object deletions while GPU access is still
834  // allowed.
835  io_manager->GetIsGpuDisabledSyncSwitch()->Execute(
836  fml::SyncSwitch::Handlers().SetIfFalse(
837  [&] { io_manager->GetSkiaUnrefQueue()->Drain(); }));
838  // Step 4: All done. Signal the latch that the platform thread is waiting
839  // on.
840  latch.Signal();
841  };
842 
843  auto raster_task = [rasterizer = rasterizer_->GetWeakPtr(),
844  io_task_runner = task_runners_.GetIOTaskRunner(),
845  io_task]() {
846  if (rasterizer) {
847  // Enables the thread merger which is required prior tearing down the
848  // rasterizer. If the raster and platform threads are merged, tearing down
849  // the rasterizer unmerges the threads.
850  rasterizer->EnableThreadMergerIfNeeded();
851  rasterizer->Teardown();
852  }
853  // Step 3: Tell the IO thread to complete its remaining work.
854  fml::TaskRunner::RunNowOrPostTask(io_task_runner, io_task);
855  };
856 
857  // TODO(91717): This probably isn't necessary. The engine should be able to
858  // handle things here via normal lifecycle messages.
859  // https://github.com/flutter/flutter/issues/91717
860  auto ui_task = [engine = engine_->GetWeakPtr()]() {
861  if (engine) {
862  engine->OnOutputSurfaceDestroyed();
863  }
864  };
865 
866  // Step 1: Post a task onto the UI thread to tell the engine that its output
867  // surface is about to go away.
868  fml::TaskRunner::RunNowOrPostTask(task_runners_.GetUITaskRunner(), ui_task);
869 
870  // Step 2: Post a task to the Raster thread (possibly this thread) to tell the
871  // rasterizer the output surface is going away.
873  raster_task);
874  latch.Wait();
875 }
876 
877 // |PlatformView::Delegate|
878 void Shell::OnPlatformViewSetViewportMetrics(const ViewportMetrics& metrics) {
879  FML_DCHECK(is_setup_);
881 
882  if (metrics.device_pixel_ratio <= 0 || metrics.physical_width <= 0 ||
883  metrics.physical_height <= 0) {
884  FML_DLOG(ERROR)
885  << "Embedding reported invalid ViewportMetrics, ignoring update."
886  << "\nphysical_width: " << metrics.physical_width
887  << "\nphysical_height: " << metrics.physical_height
888  << "\ndevice_pixel_ratio: " << metrics.device_pixel_ratio;
889  return;
890  }
891 
892  // This is the formula Android uses.
893  // https://android.googlesource.com/platform/frameworks/base/+/master/libs/hwui/renderthread/CacheManager.cpp#41
894  size_t max_bytes = metrics.physical_width * metrics.physical_height * 12 * 4;
895  task_runners_.GetRasterTaskRunner()->PostTask(
896  [rasterizer = rasterizer_->GetWeakPtr(), max_bytes] {
897  if (rasterizer) {
898  rasterizer->SetResourceCacheMaxBytes(max_bytes, false);
899  }
900  });
901 
902  task_runners_.GetUITaskRunner()->PostTask(
903  [engine = engine_->GetWeakPtr(), metrics]() {
904  if (engine) {
905  engine->SetViewportMetrics(metrics);
906  }
907  });
908 
909  {
910  std::scoped_lock<std::mutex> lock(resize_mutex_);
911  expected_frame_size_ =
912  SkISize::Make(metrics.physical_width, metrics.physical_height);
913  }
914 }
915 
916 // |PlatformView::Delegate|
917 void Shell::OnPlatformViewDispatchPlatformMessage(
918  std::unique_ptr<PlatformMessage> message) {
919  FML_DCHECK(is_setup_);
921 
922  task_runners_.GetUITaskRunner()->PostTask(fml::MakeCopyable(
923  [engine = engine_->GetWeakPtr(), message = std::move(message)]() mutable {
924  if (engine) {
925  engine->DispatchPlatformMessage(std::move(message));
926  }
927  }));
928 }
929 
930 // |PlatformView::Delegate|
931 void Shell::OnPlatformViewDispatchPointerDataPacket(
932  std::unique_ptr<PointerDataPacket> packet) {
933  TRACE_EVENT0("flutter", "Shell::OnPlatformViewDispatchPointerDataPacket");
934  TRACE_FLOW_BEGIN("flutter", "PointerEvent", next_pointer_flow_id_);
935  FML_DCHECK(is_setup_);
937  task_runners_.GetUITaskRunner()->PostTask(
938  fml::MakeCopyable([engine = weak_engine_, packet = std::move(packet),
939  flow_id = next_pointer_flow_id_]() mutable {
940  if (engine) {
941  engine->DispatchPointerDataPacket(std::move(packet), flow_id);
942  }
943  }));
944  next_pointer_flow_id_++;
945 }
946 
947 // |PlatformView::Delegate|
948 void Shell::OnPlatformViewDispatchKeyDataPacket(
949  std::unique_ptr<KeyDataPacket> packet,
950  std::function<void(bool /* handled */)> callback) {
951  TRACE_EVENT0("flutter", "Shell::OnPlatformViewDispatchKeyDataPacket");
952  FML_DCHECK(is_setup_);
954 
955  task_runners_.GetUITaskRunner()->PostTask(
956  fml::MakeCopyable([engine = weak_engine_, packet = std::move(packet),
957  callback = std::move(callback)]() mutable {
958  if (engine) {
959  engine->DispatchKeyDataPacket(std::move(packet), std::move(callback));
960  }
961  }));
962 }
963 
964 // |PlatformView::Delegate|
965 void Shell::OnPlatformViewDispatchSemanticsAction(int32_t id,
968  FML_DCHECK(is_setup_);
970 
971  task_runners_.GetUITaskRunner()->PostTask(
972  fml::MakeCopyable([engine = engine_->GetWeakPtr(), id, action,
973  args = std::move(args)]() mutable {
974  if (engine) {
975  engine->DispatchSemanticsAction(id, action, std::move(args));
976  }
977  }));
978 }
979 
980 // |PlatformView::Delegate|
981 void Shell::OnPlatformViewSetSemanticsEnabled(bool enabled) {
982  FML_DCHECK(is_setup_);
984 
985  task_runners_.GetUITaskRunner()->PostTask(
986  [engine = engine_->GetWeakPtr(), enabled] {
987  if (engine) {
988  engine->SetSemanticsEnabled(enabled);
989  }
990  });
991 }
992 
993 // |PlatformView::Delegate|
994 void Shell::OnPlatformViewSetAccessibilityFeatures(int32_t flags) {
995  FML_DCHECK(is_setup_);
997 
998  task_runners_.GetUITaskRunner()->PostTask(
999  [engine = engine_->GetWeakPtr(), flags] {
1000  if (engine) {
1001  engine->SetAccessibilityFeatures(flags);
1002  }
1003  });
1004 }
1005 
1006 // |PlatformView::Delegate|
1007 void Shell::OnPlatformViewRegisterTexture(
1008  std::shared_ptr<flutter::Texture> texture) {
1009  FML_DCHECK(is_setup_);
1011 
1012  task_runners_.GetRasterTaskRunner()->PostTask(
1013  [rasterizer = rasterizer_->GetWeakPtr(), texture] {
1014  if (rasterizer) {
1015  if (auto* registry = rasterizer->GetTextureRegistry()) {
1016  registry->RegisterTexture(texture);
1017  }
1018  }
1019  });
1020 }
1021 
1022 // |PlatformView::Delegate|
1023 void Shell::OnPlatformViewUnregisterTexture(int64_t texture_id) {
1024  FML_DCHECK(is_setup_);
1026 
1027  task_runners_.GetRasterTaskRunner()->PostTask(
1028  [rasterizer = rasterizer_->GetWeakPtr(), texture_id]() {
1029  if (rasterizer) {
1030  if (auto* registry = rasterizer->GetTextureRegistry()) {
1031  registry->UnregisterTexture(texture_id);
1032  }
1033  }
1034  });
1035 }
1036 
1037 // |PlatformView::Delegate|
1038 void Shell::OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) {
1039  FML_DCHECK(is_setup_);
1041 
1042  // Tell the rasterizer that one of its textures has a new frame available.
1043  task_runners_.GetRasterTaskRunner()->PostTask(
1044  [rasterizer = rasterizer_->GetWeakPtr(), texture_id]() {
1045  auto* registry = rasterizer->GetTextureRegistry();
1046 
1047  if (!registry) {
1048  return;
1049  }
1050 
1051  auto texture = registry->GetTexture(texture_id);
1052 
1053  if (!texture) {
1054  return;
1055  }
1056 
1057  texture->MarkNewFrameAvailable();
1058  });
1059 
1060  // Schedule a new frame without having to rebuild the layer tree.
1061  task_runners_.GetUITaskRunner()->PostTask([engine = engine_->GetWeakPtr()]() {
1062  if (engine) {
1063  engine->ScheduleFrame(false);
1064  }
1065  });
1066 }
1067 
1068 // |PlatformView::Delegate|
1069 void Shell::OnPlatformViewSetNextFrameCallback(const fml::closure& closure) {
1070  FML_DCHECK(is_setup_);
1072 
1073  task_runners_.GetRasterTaskRunner()->PostTask(
1074  [rasterizer = rasterizer_->GetWeakPtr(), closure = closure]() {
1075  if (rasterizer) {
1076  rasterizer->SetNextFrameCallback(std::move(closure));
1077  }
1078  });
1079 }
1080 
1081 // |Animator::Delegate|
1082 void Shell::OnAnimatorBeginFrame(fml::TimePoint frame_target_time,
1083  uint64_t frame_number) {
1084  FML_DCHECK(is_setup_);
1086 
1087  // record the target time for use by rasterizer.
1088  {
1089  std::scoped_lock time_recorder_lock(time_recorder_mutex_);
1090  latest_frame_target_time_.emplace(frame_target_time);
1091  }
1092  if (engine_) {
1093  engine_->BeginFrame(frame_target_time, frame_number);
1094  }
1095 }
1096 
1097 // |Animator::Delegate|
1098 void Shell::OnAnimatorNotifyIdle(int64_t deadline) {
1099  FML_DCHECK(is_setup_);
1101 
1102  if (engine_) {
1103  engine_->NotifyIdle(deadline);
1104  volatile_path_tracker_->OnFrame();
1105  }
1106 }
1107 
1108 // |Animator::Delegate|
1109 void Shell::OnAnimatorDraw(
1110  std::shared_ptr<Pipeline<flutter::LayerTree>> pipeline,
1111  std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder) {
1112  FML_DCHECK(is_setup_);
1113 
1114  // record the target time for use by rasterizer.
1115  {
1116  std::scoped_lock time_recorder_lock(time_recorder_mutex_);
1117  const fml::TimePoint frame_target_time =
1118  frame_timings_recorder->GetVsyncTargetTime();
1119  if (!latest_frame_target_time_) {
1120  latest_frame_target_time_ = frame_target_time;
1121  } else if (latest_frame_target_time_ < frame_target_time) {
1122  latest_frame_target_time_ = frame_target_time;
1123  }
1124  }
1125 
1126  auto discard_callback = [this](flutter::LayerTree& tree) {
1127  std::scoped_lock<std::mutex> lock(resize_mutex_);
1128  return !expected_frame_size_.isEmpty() &&
1129  tree.frame_size() != expected_frame_size_;
1130  };
1131 
1133  [&waiting_for_first_frame = waiting_for_first_frame_,
1134  &waiting_for_first_frame_condition = waiting_for_first_frame_condition_,
1135  rasterizer = rasterizer_->GetWeakPtr(),
1136  weak_pipeline = std::weak_ptr<Pipeline<LayerTree>>(pipeline),
1137  discard_callback = std::move(discard_callback),
1138  frame_timings_recorder = std::move(frame_timings_recorder)]() mutable {
1139  if (rasterizer) {
1140  std::shared_ptr<Pipeline<LayerTree>> pipeline = weak_pipeline.lock();
1141  if (pipeline) {
1142  rasterizer->Draw(std::move(frame_timings_recorder),
1143  std::move(pipeline), std::move(discard_callback));
1144  }
1145 
1146  if (waiting_for_first_frame.load()) {
1147  waiting_for_first_frame.store(false);
1148  waiting_for_first_frame_condition.notify_all();
1149  }
1150  }
1151  }));
1152 }
1153 
1154 // |Animator::Delegate|
1155 void Shell::OnAnimatorDrawLastLayerTree(
1156  std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder) {
1157  FML_DCHECK(is_setup_);
1158 
1159  auto task = fml::MakeCopyable(
1160  [rasterizer = rasterizer_->GetWeakPtr(),
1161  frame_timings_recorder = std::move(frame_timings_recorder)]() mutable {
1162  if (rasterizer) {
1163  rasterizer->DrawLastLayerTree(std::move(frame_timings_recorder));
1164  }
1165  });
1166 
1167  task_runners_.GetRasterTaskRunner()->PostTask(task);
1168 }
1169 
1170 // |Engine::Delegate|
1171 void Shell::OnEngineUpdateSemantics(SemanticsNodeUpdates update,
1173  FML_DCHECK(is_setup_);
1175 
1176  task_runners_.GetPlatformTaskRunner()->PostTask(
1177  [view = platform_view_->GetWeakPtr(), update = std::move(update),
1178  actions = std::move(actions)] {
1179  if (view) {
1180  view->UpdateSemantics(std::move(update), std::move(actions));
1181  }
1182  });
1183 }
1184 
1185 // |Engine::Delegate|
1186 void Shell::OnEngineHandlePlatformMessage(
1187  std::unique_ptr<PlatformMessage> message) {
1188  FML_DCHECK(is_setup_);
1190 
1191  if (message->channel() == kSkiaChannel) {
1192  HandleEngineSkiaMessage(std::move(message));
1193  return;
1194  }
1195 
1196  if (platform_message_handler_) {
1197  platform_message_handler_->HandlePlatformMessage(std::move(message));
1198  } else {
1199  task_runners_.GetPlatformTaskRunner()->PostTask(
1200  fml::MakeCopyable([view = platform_view_->GetWeakPtr(),
1201  message = std::move(message)]() mutable {
1202  if (view) {
1203  view->HandlePlatformMessage(std::move(message));
1204  }
1205  }));
1206  }
1207 }
1208 
1209 void Shell::HandleEngineSkiaMessage(std::unique_ptr<PlatformMessage> message) {
1210  const auto& data = message->data();
1211 
1212  rapidjson::Document document;
1213  document.Parse(reinterpret_cast<const char*>(data.GetMapping()),
1214  data.GetSize());
1215  if (document.HasParseError() || !document.IsObject())
1216  return;
1217  auto root = document.GetObject();
1218  auto method = root.FindMember("method");
1219  if (method->value != "Skia.setResourceCacheMaxBytes")
1220  return;
1221  auto args = root.FindMember("args");
1222  if (args == root.MemberEnd() || !args->value.IsInt())
1223  return;
1224 
1225  task_runners_.GetRasterTaskRunner()->PostTask(
1226  [rasterizer = rasterizer_->GetWeakPtr(), max_bytes = args->value.GetInt(),
1227  response = std::move(message->response())] {
1228  if (rasterizer) {
1229  rasterizer->SetResourceCacheMaxBytes(static_cast<size_t>(max_bytes),
1230  true);
1231  }
1232  if (response) {
1233  // The framework side expects this to be valid json encoded as a list.
1234  // Return `[true]` to signal success.
1235  std::vector<uint8_t> data = {'[', 't', 'r', 'u', 'e', ']'};
1236  response->Complete(
1237  std::make_unique<fml::DataMapping>(std::move(data)));
1238  }
1239  });
1240 }
1241 
1242 // |Engine::Delegate|
1243 void Shell::OnPreEngineRestart() {
1244  FML_DCHECK(is_setup_);
1246 
1249  task_runners_.GetPlatformTaskRunner(),
1250  [view = platform_view_->GetWeakPtr(), &latch]() {
1251  if (view) {
1252  view->OnPreEngineRestart();
1253  }
1254  latch.Signal();
1255  });
1256  // This is blocking as any embedded platform views has to be flushed before
1257  // we re-run the Dart code.
1258  latch.Wait();
1259 }
1260 
1261 // |Engine::Delegate|
1262 void Shell::OnRootIsolateCreated() {
1263  if (is_added_to_service_protocol_) {
1264  return;
1265  }
1266  auto description = GetServiceProtocolDescription();
1268  task_runners_.GetPlatformTaskRunner(),
1269  [self = weak_factory_.GetWeakPtr(),
1270  description = std::move(description)]() {
1271  if (self) {
1272  self->vm_->GetServiceProtocol()->AddHandler(self.get(), description);
1273  }
1274  });
1275  is_added_to_service_protocol_ = true;
1276 }
1277 
1278 // |Engine::Delegate|
1279 void Shell::UpdateIsolateDescription(const std::string isolate_name,
1280  int64_t isolate_port) {
1281  Handler::Description description(isolate_port, isolate_name);
1282  vm_->GetServiceProtocol()->SetHandlerDescription(this, description);
1283 }
1284 
1285 void Shell::SetNeedsReportTimings(bool value) {
1286  needs_report_timings_ = value;
1287 }
1288 
1289 // |Engine::Delegate|
1290 std::unique_ptr<std::vector<std::string>> Shell::ComputePlatformResolvedLocale(
1291  const std::vector<std::string>& supported_locale_data) {
1292  return platform_view_->ComputePlatformResolvedLocales(supported_locale_data);
1293 }
1294 
1295 void Shell::LoadDartDeferredLibrary(
1296  intptr_t loading_unit_id,
1297  std::unique_ptr<const fml::Mapping> snapshot_data,
1298  std::unique_ptr<const fml::Mapping> snapshot_instructions) {
1299  task_runners_.GetUITaskRunner()->PostTask(fml::MakeCopyable(
1300  [engine = engine_->GetWeakPtr(), loading_unit_id,
1301  data = std::move(snapshot_data),
1302  instructions = std::move(snapshot_instructions)]() mutable {
1303  if (engine) {
1304  engine->LoadDartDeferredLibrary(loading_unit_id, std::move(data),
1305  std::move(instructions));
1306  }
1307  }));
1308 }
1309 
1310 void Shell::LoadDartDeferredLibraryError(intptr_t loading_unit_id,
1311  const std::string error_message,
1312  bool transient) {
1313  engine_->LoadDartDeferredLibraryError(loading_unit_id, error_message,
1314  transient);
1315 }
1316 
1317 void Shell::UpdateAssetResolverByType(
1318  std::unique_ptr<AssetResolver> updated_asset_resolver,
1320  engine_->GetAssetManager()->UpdateResolverByType(
1321  std::move(updated_asset_resolver), type);
1322 }
1323 
1324 // |Engine::Delegate|
1325 void Shell::RequestDartDeferredLibrary(intptr_t loading_unit_id) {
1326  task_runners_.GetPlatformTaskRunner()->PostTask(
1327  [view = platform_view_->GetWeakPtr(), loading_unit_id] {
1328  if (view) {
1329  view->RequestDartDeferredLibrary(loading_unit_id);
1330  }
1331  });
1332 }
1333 
1334 void Shell::ReportTimings() {
1335  FML_DCHECK(is_setup_);
1337 
1338  auto timings = std::move(unreported_timings_);
1339  unreported_timings_ = {};
1340  task_runners_.GetUITaskRunner()->PostTask([timings, engine = weak_engine_] {
1341  if (engine) {
1342  engine->ReportTimings(std::move(timings));
1343  }
1344  });
1345 }
1346 
1347 size_t Shell::UnreportedFramesCount() const {
1348  // Check that this is running on the raster thread to avoid race conditions.
1350  FML_DCHECK(unreported_timings_.size() % (FrameTiming::kStatisticsCount) == 0);
1351  return unreported_timings_.size() / (FrameTiming::kStatisticsCount);
1352 }
1353 
1354 void Shell::OnFrameRasterized(const FrameTiming& timing) {
1355  FML_DCHECK(is_setup_);
1357 
1358  // The C++ callback defined in settings.h and set by Flutter runner. This is
1359  // independent of the timings report to the Dart side.
1360  if (settings_.frame_rasterized_callback) {
1361  settings_.frame_rasterized_callback(timing);
1362  }
1363 
1364  if (!needs_report_timings_) {
1365  return;
1366  }
1367 
1368  size_t old_count = unreported_timings_.size();
1369  for (auto phase : FrameTiming::kPhases) {
1370  unreported_timings_.push_back(
1371  timing.Get(phase).ToEpochDelta().ToMicroseconds());
1372  }
1373  unreported_timings_.push_back(timing.GetLayerCacheCount());
1374  unreported_timings_.push_back(timing.GetLayerCacheBytes());
1375  unreported_timings_.push_back(timing.GetPictureCacheCount());
1376  unreported_timings_.push_back(timing.GetPictureCacheBytes());
1377  unreported_timings_.push_back(timing.GetFrameNumber());
1378  FML_DCHECK(unreported_timings_.size() ==
1379  old_count + FrameTiming::kStatisticsCount);
1380 
1381  // In tests using iPhone 6S with profile mode, sending a batch of 1 frame or a
1382  // batch of 100 frames have roughly the same cost of less than 0.1ms. Sending
1383  // a batch of 500 frames costs about 0.2ms. The 1 second threshold usually
1384  // kicks in before we reaching the following 100 frames threshold. The 100
1385  // threshold here is mainly for unit tests (so we don't have to write a
1386  // 1-second unit test), and make sure that our vector won't grow too big with
1387  // future 120fps, 240fps, or 1000fps displays.
1388  //
1389  // In the profile/debug mode, the timings are used by development tools which
1390  // require a latency of no more than 100ms. Hence we lower that 1-second
1391  // threshold to 100ms because performance overhead isn't that critical in
1392  // those cases.
1393  if (!first_frame_rasterized_ || UnreportedFramesCount() >= 100) {
1394  first_frame_rasterized_ = true;
1395  ReportTimings();
1396  } else if (!frame_timings_report_scheduled_) {
1397 #if FLUTTER_RELEASE
1398  constexpr int kBatchTimeInMilliseconds = 1000;
1399 #else
1400  constexpr int kBatchTimeInMilliseconds = 100;
1401 #endif
1402 
1403  // Also make sure that frame times get reported with a max latency of 1
1404  // second. Otherwise, the timings of last few frames of an animation may
1405  // never be reported until the next animation starts.
1406  frame_timings_report_scheduled_ = true;
1407  task_runners_.GetRasterTaskRunner()->PostDelayedTask(
1408  [self = weak_factory_gpu_->GetWeakPtr()]() {
1409  if (!self) {
1410  return;
1411  }
1412  self->frame_timings_report_scheduled_ = false;
1413  if (self->UnreportedFramesCount() > 0) {
1414  self->ReportTimings();
1415  }
1416  },
1417  fml::TimeDelta::FromMilliseconds(kBatchTimeInMilliseconds));
1418  }
1419 }
1420 
1421 fml::Milliseconds Shell::GetFrameBudget() {
1422  double display_refresh_rate = display_manager_->GetMainDisplayRefreshRate();
1423  if (display_refresh_rate > 0) {
1424  return fml::RefreshRateToFrameBudget(display_refresh_rate);
1425  } else {
1426  return fml::kDefaultFrameBudget;
1427  }
1428 }
1429 
1430 fml::TimePoint Shell::GetLatestFrameTargetTime() const {
1431  std::scoped_lock time_recorder_lock(time_recorder_mutex_);
1432  FML_CHECK(latest_frame_target_time_.has_value())
1433  << "GetLatestFrameTargetTime called before OnAnimatorBeginFrame";
1434  return latest_frame_target_time_.value();
1435 }
1436 
1437 // |ServiceProtocol::Handler|
1438 fml::RefPtr<fml::TaskRunner> Shell::GetServiceProtocolHandlerTaskRunner(
1439  std::string_view method) const {
1440  FML_DCHECK(is_setup_);
1441  auto found = service_protocol_handlers_.find(method);
1442  if (found != service_protocol_handlers_.end()) {
1443  return found->second.first;
1444  }
1445  return task_runners_.GetUITaskRunner();
1446 }
1447 
1448 // |ServiceProtocol::Handler|
1449 bool Shell::HandleServiceProtocolMessage(
1450  std::string_view method, // one if the extension names specified above.
1451  const ServiceProtocolMap& params,
1452  rapidjson::Document* response) {
1453  auto found = service_protocol_handlers_.find(method);
1454  if (found != service_protocol_handlers_.end()) {
1455  return found->second.second(params, response);
1456  }
1457  return false;
1458 }
1459 
1460 // |ServiceProtocol::Handler|
1461 ServiceProtocol::Handler::Description Shell::GetServiceProtocolDescription()
1462  const {
1464 
1465  if (!weak_engine_) {
1467  }
1468 
1469  return {
1470  weak_engine_->GetUIIsolateMainPort(),
1471  weak_engine_->GetUIIsolateName(),
1472  };
1473 }
1474 
1475 static void ServiceProtocolParameterError(rapidjson::Document* response,
1476  std::string error_details) {
1477  auto& allocator = response->GetAllocator();
1478  response->SetObject();
1479  const int64_t kInvalidParams = -32602;
1480  response->AddMember("code", kInvalidParams, allocator);
1481  response->AddMember("message", "Invalid params", allocator);
1482  {
1483  rapidjson::Value details(rapidjson::kObjectType);
1484  details.AddMember("details", error_details, allocator);
1485  response->AddMember("data", details, allocator);
1486  }
1487 }
1488 
1489 static void ServiceProtocolFailureError(rapidjson::Document* response,
1490  std::string message) {
1491  auto& allocator = response->GetAllocator();
1492  response->SetObject();
1493  const int64_t kJsonServerError = -32000;
1494  response->AddMember("code", kJsonServerError, allocator);
1495  response->AddMember("message", message, allocator);
1496 }
1497 
1498 // Service protocol handler
1499 bool Shell::OnServiceProtocolScreenshot(
1501  rapidjson::Document* response) {
1503  auto screenshot = rasterizer_->ScreenshotLastLayerTree(
1505  if (screenshot.data) {
1506  response->SetObject();
1507  auto& allocator = response->GetAllocator();
1508  response->AddMember("type", "Screenshot", allocator);
1509  rapidjson::Value image;
1510  image.SetString(static_cast<const char*>(screenshot.data->data()),
1511  screenshot.data->size(), allocator);
1512  response->AddMember("screenshot", image, allocator);
1513  return true;
1514  }
1515  ServiceProtocolFailureError(response, "Could not capture image screenshot.");
1516  return false;
1517 }
1518 
1519 // Service protocol handler
1520 bool Shell::OnServiceProtocolScreenshotSKP(
1522  rapidjson::Document* response) {
1524  auto screenshot = rasterizer_->ScreenshotLastLayerTree(
1526  if (screenshot.data) {
1527  response->SetObject();
1528  auto& allocator = response->GetAllocator();
1529  response->AddMember("type", "ScreenshotSkp", allocator);
1530  rapidjson::Value skp;
1531  skp.SetString(static_cast<const char*>(screenshot.data->data()),
1532  screenshot.data->size(), allocator);
1533  response->AddMember("skp", skp, allocator);
1534  return true;
1535  }
1536  ServiceProtocolFailureError(response, "Could not capture SKP screenshot.");
1537  return false;
1538 }
1539 
1540 // Service protocol handler
1541 bool Shell::OnServiceProtocolRunInView(
1543  rapidjson::Document* response) {
1545 
1546  if (params.count("mainScript") == 0) {
1548  "'mainScript' parameter is missing.");
1549  return false;
1550  }
1551 
1552  if (params.count("assetDirectory") == 0) {
1554  "'assetDirectory' parameter is missing.");
1555  return false;
1556  }
1557 
1558  std::string main_script_path =
1559  fml::paths::FromURI(params.at("mainScript").data());
1560  std::string asset_directory_path =
1561  fml::paths::FromURI(params.at("assetDirectory").data());
1562 
1563  auto main_script_file_mapping =
1564  std::make_unique<fml::FileMapping>(fml::OpenFile(
1565  main_script_path.c_str(), false, fml::FilePermission::kRead));
1566 
1567  auto isolate_configuration = IsolateConfiguration::CreateForKernel(
1568  std::move(main_script_file_mapping));
1569 
1570  RunConfiguration configuration(std::move(isolate_configuration));
1571 
1572  configuration.SetEntrypointAndLibrary(engine_->GetLastEntrypoint(),
1573  engine_->GetLastEntrypointLibrary());
1574 
1575  configuration.AddAssetResolver(std::make_unique<DirectoryAssetBundle>(
1576  fml::OpenDirectory(asset_directory_path.c_str(), false,
1578  false));
1579 
1580  // Preserve any original asset resolvers to avoid syncing unchanged assets
1581  // over the DevFS connection.
1582  auto old_asset_manager = engine_->GetAssetManager();
1583  if (old_asset_manager != nullptr) {
1584  for (auto& old_resolver : old_asset_manager->TakeResolvers()) {
1585  if (old_resolver->IsValidAfterAssetManagerChange()) {
1586  configuration.AddAssetResolver(std::move(old_resolver));
1587  }
1588  }
1589  }
1590 
1591  auto& allocator = response->GetAllocator();
1592  response->SetObject();
1593  if (engine_->Restart(std::move(configuration))) {
1594  response->AddMember("type", "Success", allocator);
1595  auto new_description = GetServiceProtocolDescription();
1596  rapidjson::Value view(rapidjson::kObjectType);
1597  new_description.Write(this, view, allocator);
1598  response->AddMember("view", view, allocator);
1599  return true;
1600  } else {
1601  FML_DLOG(ERROR) << "Could not run configuration in engine.";
1602  ServiceProtocolFailureError(response,
1603  "Could not run configuration in engine.");
1604  return false;
1605  }
1606 
1607  FML_DCHECK(false);
1608  return false;
1609 }
1610 
1611 // Service protocol handler
1612 bool Shell::OnServiceProtocolFlushUIThreadTasks(
1614  rapidjson::Document* response) {
1616  // This API should not be invoked by production code.
1617  // It can potentially starve the service isolate if the main isolate pauses
1618  // at a breakpoint or is in an infinite loop.
1619  //
1620  // It should be invoked from the VM Service and and blocks it until UI thread
1621  // tasks are processed.
1622  response->SetObject();
1623  response->AddMember("type", "Success", response->GetAllocator());
1624  return true;
1625 }
1626 
1627 bool Shell::OnServiceProtocolGetDisplayRefreshRate(
1629  rapidjson::Document* response) {
1631  response->SetObject();
1632  response->AddMember("type", "DisplayRefreshRate", response->GetAllocator());
1633  response->AddMember("fps", display_manager_->GetMainDisplayRefreshRate(),
1634  response->GetAllocator());
1635  return true;
1636 }
1637 
1639  return display_manager_->GetMainDisplayRefreshRate();
1640 }
1641 
1643  int32_t priority) {
1645  FML_DCHECK(is_setup_);
1646 
1648  task_runners_.GetUITaskRunner(),
1649  [engine = engine_->GetWeakPtr(), factory = std::move(factory),
1650  priority]() {
1651  if (engine) {
1652  engine->GetImageGeneratorRegistry()->AddFactory(factory, priority);
1653  }
1654  });
1655 }
1656 
1657 bool Shell::OnServiceProtocolGetSkSLs(
1659  rapidjson::Document* response) {
1661  response->SetObject();
1662  response->AddMember("type", "GetSkSLs", response->GetAllocator());
1663 
1664  rapidjson::Value shaders_json(rapidjson::kObjectType);
1666  std::vector<PersistentCache::SkSLCache> sksls = persistent_cache->LoadSkSLs();
1667  for (const auto& sksl : sksls) {
1668  size_t b64_size =
1669  SkBase64::Encode(sksl.value->data(), sksl.value->size(), nullptr);
1670  sk_sp<SkData> b64_data = SkData::MakeUninitialized(b64_size + 1);
1671  char* b64_char = static_cast<char*>(b64_data->writable_data());
1672  SkBase64::Encode(sksl.value->data(), sksl.value->size(), b64_char);
1673  b64_char[b64_size] = 0; // make it null terminated for printing
1674  rapidjson::Value shader_value(b64_char, response->GetAllocator());
1675  std::string_view key_view(reinterpret_cast<const char*>(sksl.key->data()),
1676  sksl.key->size());
1677  auto encode_result = fml::Base32Encode(key_view);
1678  if (!encode_result.first) {
1679  continue;
1680  }
1681  rapidjson::Value shader_key(encode_result.second, response->GetAllocator());
1682  shaders_json.AddMember(shader_key, shader_value, response->GetAllocator());
1683  }
1684  response->AddMember("SkSLs", shaders_json, response->GetAllocator());
1685  return true;
1686 }
1687 
1688 bool Shell::OnServiceProtocolEstimateRasterCacheMemory(
1690  rapidjson::Document* response) {
1692  const auto& raster_cache = rasterizer_->compositor_context()->raster_cache();
1693  response->SetObject();
1694  response->AddMember("type", "EstimateRasterCacheMemory",
1695  response->GetAllocator());
1696  response->AddMember<uint64_t>("layerBytes",
1697  raster_cache.EstimateLayerCacheByteSize(),
1698  response->GetAllocator());
1699  response->AddMember<uint64_t>("pictureBytes",
1700  raster_cache.EstimatePictureCacheByteSize(),
1701  response->GetAllocator());
1702  return true;
1703 }
1704 
1705 // Service protocol handler
1706 bool Shell::OnServiceProtocolSetAssetBundlePath(
1708  rapidjson::Document* response) {
1710 
1711  if (params.count("assetDirectory") == 0) {
1713  "'assetDirectory' parameter is missing.");
1714  return false;
1715  }
1716 
1717  auto& allocator = response->GetAllocator();
1718  response->SetObject();
1719 
1720  auto asset_manager = std::make_shared<AssetManager>();
1721 
1722  asset_manager->PushFront(std::make_unique<DirectoryAssetBundle>(
1723  fml::OpenDirectory(params.at("assetDirectory").data(), false,
1725  false));
1726 
1727  // Preserve any original asset resolvers to avoid syncing unchanged assets
1728  // over the DevFS connection.
1729  auto old_asset_manager = engine_->GetAssetManager();
1730  if (old_asset_manager != nullptr) {
1731  for (auto& old_resolver : old_asset_manager->TakeResolvers()) {
1732  if (old_resolver->IsValidAfterAssetManagerChange()) {
1733  asset_manager->PushBack(std::move(old_resolver));
1734  }
1735  }
1736  }
1737 
1738  if (engine_->UpdateAssetManager(std::move(asset_manager))) {
1739  response->AddMember("type", "Success", allocator);
1740  auto new_description = GetServiceProtocolDescription();
1741  rapidjson::Value view(rapidjson::kObjectType);
1742  new_description.Write(this, view, allocator);
1743  response->AddMember("view", view, allocator);
1744  return true;
1745  } else {
1746  FML_DLOG(ERROR) << "Could not update asset directory.";
1747  ServiceProtocolFailureError(response, "Could not update asset directory.");
1748  return false;
1749  }
1750 
1751  FML_DCHECK(false);
1752  return false;
1753 }
1754 
1756  Rasterizer::ScreenshotType screenshot_type,
1757  bool base64_encode) {
1758  TRACE_EVENT0("flutter", "Shell::Screenshot");
1760  Rasterizer::Screenshot screenshot;
1762  task_runners_.GetRasterTaskRunner(), [&latch, //
1763  rasterizer = GetRasterizer(), //
1764  &screenshot, //
1765  screenshot_type, //
1766  base64_encode //
1767  ]() {
1768  if (rasterizer) {
1769  screenshot = rasterizer->ScreenshotLastLayerTree(screenshot_type,
1770  base64_encode);
1771  }
1772  latch.Signal();
1773  });
1774  latch.Wait();
1775  return screenshot;
1776 }
1777 
1779  FML_DCHECK(is_setup_);
1780  if (task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread() ||
1781  task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread()) {
1783  "WaitForFirstFrame called from thread that can't wait "
1784  "because it is responsible for generating the frame.");
1785  }
1786 
1787  // Check for overflow.
1788  auto now = std::chrono::steady_clock::now();
1789  auto max_duration = std::chrono::steady_clock::time_point::max() - now;
1790  auto desired_duration = std::chrono::milliseconds(timeout.ToMilliseconds());
1791  auto duration =
1792  now + (desired_duration > max_duration ? max_duration : desired_duration);
1793 
1794  std::unique_lock<std::mutex> lock(waiting_for_first_frame_mutex_);
1795  bool success = waiting_for_first_frame_condition_.wait_until(
1796  lock, duration, [&waiting_for_first_frame = waiting_for_first_frame_] {
1797  return !waiting_for_first_frame.load();
1798  });
1799  if (success) {
1800  return fml::Status();
1801  } else {
1803  }
1804 }
1805 
1807  FML_DCHECK(is_setup_);
1809 
1810  if (!engine_) {
1811  return false;
1812  }
1813  engine_->SetupDefaultFontManager();
1814  engine_->GetFontCollection().GetFontCollection()->ClearFontFamilyCache();
1815  // After system fonts are reloaded, we send a system channel message
1816  // to notify flutter framework.
1817  rapidjson::Document document;
1818  document.SetObject();
1819  auto& allocator = document.GetAllocator();
1820  rapidjson::Value message_value;
1821  message_value.SetString(kFontChange, allocator);
1822  document.AddMember(kTypeKey, message_value, allocator);
1823 
1824  rapidjson::StringBuffer buffer;
1825  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
1826  document.Accept(writer);
1827  std::string message = buffer.GetString();
1828  std::unique_ptr<PlatformMessage> fontsChangeMessage =
1829  std::make_unique<flutter::PlatformMessage>(
1831  fml::MallocMapping::Copy(message.c_str(), message.length()), nullptr);
1832 
1833  OnPlatformViewDispatchPlatformMessage(std::move(fontsChangeMessage));
1834  return true;
1835 }
1836 
1837 std::shared_ptr<const fml::SyncSwitch> Shell::GetIsGpuDisabledSyncSwitch()
1838  const {
1839  return is_gpu_disabled_sync_switch_;
1840 }
1841 
1843  switch (availability) {
1845  is_gpu_disabled_sync_switch_->SetSwitch(false);
1846  return;
1850  task_runners_.GetIOTaskRunner(),
1851  [io_manager = io_manager_.get(), &latch]() {
1852  io_manager->GetSkiaUnrefQueue()->Drain();
1853  latch.Signal();
1854  });
1855  latch.Wait();
1856  }
1857  // FALLTHROUGH
1859  is_gpu_disabled_sync_switch_->SetSwitch(true);
1860  return;
1861  default:
1862  FML_DCHECK(false);
1863  }
1864 }
1865 
1867  std::vector<Display> displays) {
1868  display_manager_->HandleDisplayUpdates(update_type, displays);
1869 }
1870 
1871 fml::TimePoint Shell::GetCurrentTimePoint() {
1872  return fml::TimePoint::Now();
1873 }
1874 
1875 const std::shared_ptr<PlatformMessageHandler>&
1877  return platform_message_handler_;
1878 }
1879 
1880 } // namespace flutter
G_BEGIN_DECLS FlValue * args
KeyCallType type
static const std::string_view kGetDisplayRefreshRateExtensionName
G_BEGIN_DECLS FlTexture * texture
bool IsValid() const
Definition: task_runners.cc:46
While the engine operates entirely on the UI task runner, it needs the capabilities of the other comp...
Definition: engine.h:140
std::function< std::unique_ptr< T >(Shell &)> CreateCallback
Definition: shell.h:114
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:90
std::map< std::string_view, std::string_view > ServiceProtocolMap
std::shared_ptr< ServiceProtocol > GetServiceProtocol() const
The service protocol instance associated with this running Dart VM instance. This object manages nati...
Definition: dart_vm.cc:496
static const std::string_view kRunInViewExtensionName
#define FML_DCHECK(condition)
Definition: logging.h:86
std::unique_ptr< flutter::PlatformViewIOS > platform_view
bool skia_deterministic_rendering_on_cpu
Definition: settings.h:249
constexpr int64_t ToMilliseconds() const
Definition: time_delta.h:63
static fml::RefPtr< const DartSnapshot > IsolateSnapshotFromSettings(const Settings &settings)
From the fields present in the given settings object, infer the isolate snapshot. ...
void SetLogSettings(const LogSettings &settings)
Definition: log_settings.cc:28
const TaskRunners & GetTaskRunners() const override
If callers wish to interact directly with any shell subcomponents, they must (on the platform thread)...
Definition: shell.cc:674
fml::WeakPtr< Engine > GetEngine()
Engines may only be accessed on the UI thread. This method is deprecated, and implementers should ins...
Definition: shell.cc:688
uint64_t GetLayerCacheCount() const
Definition: settings.h:49
static void RunNowOrPostTask(fml::RefPtr< fml::TaskRunner > runner, const fml::closure &task)
Definition: task_runner.cc:55
void InitializeICU(const std::string &icu_data_path)
Definition: icu_util.cc:103
The Dart error code for an API error.
void InitializeICUFromMapping(std::unique_ptr< Mapping > mapping)
Definition: icu_util.cc:114
Dart_NativeFunction function
Definition: fuchsia.cc:51
bool EngineHasLivePorts() const
Used by embedders to check if the Engine is running and has any live ports remaining. For example, the Flutter tester uses this method to check whether it should continue to wait for a running test or not.
Definition: shell.cc:600
fml::RefPtr< fml::TaskRunner > GetPlatformTaskRunner() const
Definition: task_runners.cc:30
std::unordered_map< int32_t, SemanticsNode > SemanticsNodeUpdates
int64_t texture_id
GAsyncResult * result
TimeDelta ToEpochDelta() const
Definition: time_point.h:47
bool prefetched_default_font_manager
Definition: settings.h:186
#define FML_LOG(severity)
Definition: logging.h:65
static void SetCacheSkSL(bool value)
static std::unique_ptr< IsolateConfiguration > CreateForKernel(std::unique_ptr< const fml::Mapping > kernel)
Creates a JIT isolate configuration using the specified snapshot. This is a convenience method for th...
std::function< std::unique_ptr< PointerDataDispatcher >(PointerDataDispatcher::Delegate &)> PointerDataDispatcherMaker
Signature for constructing PointerDataDispatcher.
#define TRACE_EVENT_ASYNC_BEGIN0(category_group, name, id)
Definition: trace_event.h:104
fml::RefPtr< fml::TaskRunner > GetRasterTaskRunner() const
Definition: task_runners.cc:42
uint64_t GetPictureCacheBytes() const
Definition: settings.h:52
uint64_t GetPictureCacheCount() const
Definition: settings.h:51
FlKeyEvent FlKeyResponderAsyncCallback callback
void SetLogHandler(std::function< void(const char *)> handler)
Definition: log.cc:46
void AddWorkerTaskRunner(fml::RefPtr< fml::TaskRunner > task_runner)
static DartVMRef Create(Settings settings, fml::RefPtr< const DartSnapshot > vm_snapshot=nullptr, fml::RefPtr< const DartSnapshot > isolate_snapshot=nullptr)
void SetGpuAvailability(GpuAvailability availability)
Marks the GPU as available or unavailable.
Definition: shell.cc:1842
constexpr char kSkiaChannel[]
Definition: shell.cc:38
fml::UniqueFD OpenDirectory(const char *path, bool create_if_necessary, FilePermission permission)
Definition: file_posix.cc:96
static const std::string_view kScreenshotExtensionName
std::optional< std::vector< std::string > > trace_skia_allowlist
Definition: settings.h:133
std::unique_ptr< Shell > Spawn(RunConfiguration run_configuration, const std::string &initial_route, const CreateCallback< PlatformView > &on_create_platform_view, const CreateCallback< Rasterizer > &on_create_rasterizer) const
Creates one Shell from another Shell where the created Shell takes the opportunity to share any inter...
Definition: shell.cc:481
The Dart error code for an unknown error.
bool verbose_logging
Definition: settings.h:250
static const std::string_view kFlushUIThreadTasksExtensionName
uint64_t GetFrameNumber() const
Definition: settings.h:47
static constexpr Phase kPhases[kCount]
Definition: settings.h:36
AssetResolverType
Identifies the type of AssetResolver an instance is.
std::string FromURI(const std::string &uri)
Definition: paths_posix.cc:53
std::function< void()> closure
Definition: closure.h:14
void RunEngine(RunConfiguration run_configuration)
Starts an isolate for the given RunConfiguration.
Definition: shell.cc:543
internal::CopyableLambda< T > MakeCopyable(T lambda)
Definition: make_copyable.h:57
void InitSkiaEventTracer(bool enabled, const std::optional< std::vector< std::string >> &allowlist)
Indicates that GPU operations should be permitted.
fml::WeakPtr< ShellIOManager > GetIOManager()
The IO Manager may only be accessed on the IO task runner.
Definition: shell.cc:698
#define TRACE_FLOW_BEGIN(category, name, id)
Definition: trace_event.h:130
std::chrono::microseconds engine_start_timestamp
Definition: settings.h:288
A POD type used to return the screenshot data along with the size of the frame.
Definition: rasterizer.h:275
uint8_t value
void OnDisplayUpdates(DisplayUpdateType update_type, std::vector< Display > displays)
Notifies the display manager of the updates.
Definition: shell.cc:1866
ScreenshotType
The type of the screenshot to obtain of the previously rendered layer tree.
Definition: rasterizer.h:245
constexpr int64_t ToMicroseconds() const
Definition: time_delta.h:62
void RemoveWorkerTaskRunner(fml::RefPtr< fml::TaskRunner > task_runner)
const fml::RefPtr< fml::RasterThreadMerger > GetParentRasterThreadMerger() const override
Getting the raster thread merger from parent shell, it can be a null RefPtr when it&#39;s a root Shell or...
Definition: shell.cc:678
fml::TaskRunnerAffineWeakPtr< Rasterizer > GetRasterizer() const
Rasterizers may only be accessed on the raster task runner.
Definition: shell.cc:683
uint64_t GetLayerCacheBytes() const
Definition: settings.h:50
Specifies all the configuration required by the runtime library to launch the root isolate...
Milliseconds RefreshRateToFrameBudget(T refresh_rate)
Definition: time_delta.h:24
std::pair< bool, std::string > Base32Encode(std::string_view input)
Definition: base32.cc:14
const std::shared_ptr< PlatformMessageHandler > & GetPlatformMessageHandler() const
Returns the delegate object that handles PlatformMessage&#39;s from Flutter to the host platform (and its...
Definition: shell.cc:1876
double GetMainDisplayRefreshRate()
Queries the DisplayManager for the main display refresh rate.
Definition: shell.cc:1638
constexpr char kSystemChannel[]
Definition: shell.cc:39
SemanticsAction action
void NotifyLowMemoryWarning() const
Used by embedders to notify that there is a low memory warning. The shell will attempt to purge cache...
Definition: shell.cc:521
constexpr char kFontChange[]
Definition: shell.cc:41
void SetEntrypointAndLibrary(std::string entrypoint, std::string library)
Specifies the main Dart entrypoint and the library to find that entrypoint in. By default...
void TraceSetAllowlist(const std::vector< std::string > &allowlist)
Definition: trace_event.cc:294
static std::unique_ptr< Shell > Create(const PlatformData &platform_data, TaskRunners task_runners, Settings settings, const CreateCallback< PlatformView > &on_create_platform_view, const CreateCallback< Rasterizer > &on_create_rasterizer, bool is_gpu_disabled=false)
Creates a shell instance using the provided settings. The callbacks to create the various shell subco...
Definition: shell.cc:126
bool dump_skp_on_shader_compilation
Definition: settings.h:136
fml::Status WaitForFirstFrame(fml::TimeDelta timeout)
Pauses the calling thread until the first frame is presented.
Definition: shell.cc:1778
fml::RefPtr< fml::TaskRunner > GetIOTaskRunner() const
Definition: task_runners.cc:38
fml::RefPtr< fml::TaskRunner > GetUITaskRunner() const
Definition: task_runners.cc:34
fml::WeakPtr< PlatformView > GetPlatformView()
Platform views may only be accessed on the platform task runner.
Definition: shell.cc:693
std::string icu_data_path
Definition: settings.h:258
static MallocMapping Copy(const T *begin, const T *end)
Definition: mapping.h:147
#define TRACE_EVENT_ASYNC_END0(category_group, name, id)
Definition: trace_event.h:107
bool AddAssetResolver(std::unique_ptr< AssetResolver > resolver)
Asset managers maintain a list of resolvers that are checked in order when attempting to locate an as...
std::function< std::shared_ptr< ImageGenerator >(sk_sp< SkData > buffer)> ImageGeneratorFactory
ImageGeneratorFactory is the top level primitive for specifying an image decoder in Flutter...
constexpr LogSeverity LOG_ERROR
Definition: log_level.h:15
static void ServiceProtocolFailureError(rapidjson::Document *response, std::string message)
Definition: shell.cc:1489
void SetIsDumpingSkp(bool value)
std::function< std::unique_ptr< Engine > Engine::Delegate &delegate, const PointerDataDispatcherMaker &dispatcher_maker, DartVM &vm, fml::RefPtr< const DartSnapshot > isolate_snapshot, TaskRunners task_runners, const PlatformData &platform_data, Settings settings, std::unique_ptr< Animator > animator, fml::WeakPtr< IOManager > io_manager, fml::RefPtr< SkiaUnrefQueue > unref_queue, fml::WeakPtr< SnapshotDelegate > snapshot_delegate, std::shared_ptr< VolatilePathTracker > volatile_path_tracker)> EngineCreateCallback
Definition: shell.h:128
GpuAvailability
Values for |Shell::SetGpuAvailability|.
Definition: shell.h:58
Describes a running instance of the Dart VM. There may only be one running instance of the Dart VM in...
Definition: dart_vm.h:61
static PersistentCache * GetCacheForProcess()
#define FML_CHECK(condition)
Definition: logging.h:68
FlView * view
A Mapping like NonOwnedMapping, but uses Free as its release proc.
Definition: mapping.h:129
static void ServiceProtocolParameterError(rapidjson::Document *response, std::string error_details)
Definition: shell.cc:1475
LogSeverity min_log_level
Definition: log_settings.h:25
constexpr LogSeverity LOG_INFO
Definition: log_level.h:13
static const uint8_t buffer[]
static constexpr TimeDelta FromMilliseconds(int64_t millis)
Definition: time_delta.h:46
DartVM * GetDartVM()
Get a pointer to the Dart VM used by this running shell instance.
Definition: shell.cc:703
constexpr Milliseconds kDefaultFrameBudget
Definition: time_delta.h:21
fml::UniqueFD OpenFile(const char *path, bool create_if_necessary, FilePermission permission)
This can open a directory on POSIX, but not on Windows.
Definition: file_posix.cc:65
virtual bool RunsTasksOnCurrentThread()
Definition: task_runner.cc:43
fml::TimePoint Get(Phase phase) const
Definition: settings.h:42
std::vector< SkSLCache > LoadSkSLs() const
Load all the SkSL shader caches in the right directory.
bool IsSetup() const
Used by embedders to check if all shell subcomponents are initialized. It is the embedder&#39;s responsib...
Definition: shell.cc:611
int32_t id
#define FML_DLOG(severity)
Definition: logging.h:85
RunStatus
Indicates the result of the call to Engine::Run.
Definition: engine.h:80
bool icu_initialization_required
Definition: settings.h:257
size_t TraceNonce()
Definition: trace_event.cc:298
MappingCallback icu_mapper
Definition: settings.h:259
std::unordered_map< int32_t, CustomAccessibilityAction > CustomAccessibilityActionUpdates
const Settings & GetSettings() const
Definition: shell.cc:670
std::shared_ptr< const DartVMData > GetVMData() const
The VM and isolate snapshots used by this running Dart VM instance.
Definition: dart_vm.cc:488
std::shared_ptr< const fml::SyncSwitch > GetIsGpuDisabledSyncSwitch() const override
Accessor for the disable GPU SyncSwitch.
Definition: shell.cc:1837
The Dart error code for a compilation error.
static const std::string_view kScreenshotSkpExtensionName
void RegisterImageDecoder(ImageGeneratorFactory factory, int32_t priority)
Install a new factory that can match against and decode image data.
Definition: shell.cc:1642
virtual void PostTask(const fml::closure &task) override
Definition: task_runner.cc:24
std::vector< std::string > trace_allowlist
Definition: settings.h:132
bool ReloadSystemFonts()
Used by embedders to reload the system fonts in FontCollection. It also clears the cached font famili...
Definition: shell.cc:1806
std::chrono::duration< double, std::milli > Milliseconds
Definition: time_delta.h:18
static TimePoint Now()
Definition: time_point.cc:39
virtual void PostDelayedTask(const fml::closure &task, fml::TimeDelta delay)
Definition: task_runner.cc:33
~Shell()
Destroys the shell. This is a synchronous operation and synchronous barrier blocks are introduced on ...
Definition: shell.cc:428
constexpr char kTypeKey[]
Definition: shell.cc:40
bool purge_persistent_cache
Definition: settings.h:138
static const std::string_view kSetAssetBundlePathExtensionName
DEF_SWITCHES_START snapshot asset Path to the directory containing the four files specified by VmSnapshotInstructions and IsolateSnapshotInstructions vm snapshot The VM instructions snapshot that will be memory mapped as read and executable SnapshotAssetPath must be present isolate snapshot The isolate instructions snapshot that will be memory mapped as read and executable SnapshotAssetPath must be present icu symbol Prefix for the symbols representing ICU data linked into the Flutter library dart flags
Definition: switches.h:66
FrameRasterizedCallback frame_rasterized_callback
Definition: settings.h:268
std::optional< DartErrorCode > GetUIIsolateLastError() const
Used by embedders to get the last error from the Dart UI Isolate, if one exists.
Definition: shell.cc:580
Rasterizer::Screenshot Screenshot(Rasterizer::ScreenshotType type, bool base64_encode)
Captures a screenshot and optionally Base64 encodes the data of the last layer tree rendered by the r...
Definition: shell.cc:1755
static const std::string_view kGetSkSLsExtensionName
static constexpr int kStatisticsCount
Definition: settings.h:40
No error has occurred.
static const std::string_view kEstimateRasterCacheMemoryExtensionName
Represents the 2 code paths available when calling |SyncSwitch::Execute|.
Definition: sync_switch.h:24
static fml::RefPtr< const DartSnapshot > VMSnapshotFromSettings(const Settings &settings)
From the fields present in the given settings object, infer the core snapshot.