Flutter Engine
component.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 #include "component.h"
6 
7 #include <dlfcn.h>
8 #include <fuchsia/mem/cpp/fidl.h>
9 #include <lib/async-loop/cpp/loop.h>
10 #include <lib/async/cpp/task.h>
11 #include <lib/async/default.h>
12 #include <lib/fdio/directory.h>
13 #include <lib/fdio/namespace.h>
14 #include <lib/ui/scenic/cpp/view_ref_pair.h>
15 #include <lib/ui/scenic/cpp/view_token_pair.h>
16 #include <lib/vfs/cpp/composed_service_dir.h>
17 #include <lib/vfs/cpp/remote_dir.h>
18 #include <lib/vfs/cpp/service.h>
19 #include <sys/stat.h>
20 #include <zircon/dlfcn.h>
21 #include <zircon/status.h>
22 #include <zircon/types.h>
23 
24 #include <memory>
25 #include <regex>
26 #include <sstream>
27 
28 #include "flutter/fml/mapping.h"
29 #include "flutter/fml/synchronization/waitable_event.h"
30 #include "flutter/fml/unique_fd.h"
31 #include "flutter/runtime/dart_vm_lifecycle.h"
32 #include "flutter/shell/common/switches.h"
33 #include "lib/fdio/io.h"
38 #include "runtime/dart/utils/vmo.h"
39 
41 #include "task_observers.h"
42 #include "task_runner_adapter.h"
43 #include "thread.h"
44 
45 // TODO(kaushikiska): Use these constants from ::llcpp::fuchsia::io
46 // Can read from target object.
47 constexpr uint32_t OPEN_RIGHT_READABLE = 1u;
48 
49 // Connection can map target object executable.
50 constexpr uint32_t OPEN_RIGHT_EXECUTABLE = 8u;
51 
52 namespace flutter_runner {
53 
54 constexpr char kDataKey[] = "data";
55 constexpr char kAssetsKey[] = "assets";
56 constexpr char kTmpPath[] = "/tmp";
57 constexpr char kServiceRootPath[] = "/svc";
58 constexpr char kRunnerConfigPath[] = "/config/data/flutter_runner_config";
59 
60 // static
62  const fidl::VectorPtr<fuchsia::sys::ProgramMetadata>& program_metadata,
63  std::string* data_path,
64  std::string* assets_path) {
65  if (!program_metadata.has_value()) {
66  return;
67  }
68  for (const auto& pg : *program_metadata) {
69  if (pg.key.compare(kDataKey) == 0) {
70  *data_path = "pkg/" + pg.value;
71  } else if (pg.key.compare(kAssetsKey) == 0) {
72  *assets_path = "pkg/" + pg.value;
73  }
74  }
75 
76  // assets_path defaults to the same as data_path if omitted.
77  if (assets_path->empty()) {
78  *assets_path = *data_path;
79  }
80 }
81 
82 // static
84  TerminationCallback termination_callback,
85  fuchsia::sys::Package package,
86  fuchsia::sys::StartupInfo startup_info,
87  std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
88  fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) {
89  std::unique_ptr<Thread> thread = std::make_unique<Thread>();
90  std::unique_ptr<Application> application;
91 
93  async::PostTask(thread->dispatcher(), [&]() mutable {
94  application.reset(
95  new Application(std::move(termination_callback), std::move(package),
96  std::move(startup_info), runner_incoming_services,
97  std::move(controller)));
98  latch.Signal();
99  });
100 
101  latch.Wait();
102  return {.thread = std::move(thread), .application = std::move(application)};
103 }
104 
105 static std::string DebugLabelForURL(const std::string& url) {
106  auto found = url.rfind("/");
107  if (found == std::string::npos) {
108  return url;
109  } else {
110  return {url, found + 1};
111  }
112 }
113 
114 static std::unique_ptr<fml::FileMapping> MakeFileMapping(const char* path,
115  bool executable) {
116  uint32_t flags = OPEN_RIGHT_READABLE;
117  if (executable) {
118  flags |= OPEN_RIGHT_EXECUTABLE;
119  }
120 
121  int fd = 0;
122  // The returned file descriptor is compatible with standard posix operations
123  // such as close, mmap, etc. We only need to treat open/open_at specially.
124  zx_status_t status = fdio_open_fd(path, flags, &fd);
125 
126  if (status != ZX_OK) {
127  return nullptr;
128  }
129 
130  using Protection = fml::FileMapping::Protection;
131 
132  std::initializer_list<Protection> protection_execute = {Protection::kRead,
133  Protection::kExecute};
134  std::initializer_list<Protection> protection_read = {Protection::kRead};
135  auto mapping = std::make_unique<fml::FileMapping>(
136  fml::UniqueFD{fd}, executable ? protection_execute : protection_read);
137 
138  if (!mapping->IsValid()) {
139  return nullptr;
140  }
141 
142  return mapping;
143 }
144 
145 // Defaults to readonly. If executable is `true`, we treat it as `read + exec`.
146 static flutter::MappingCallback MakeDataFileMapping(const char* absolute_path,
147  bool executable = false) {
148  return [absolute_path, executable = executable](void) {
149  return MakeFileMapping(absolute_path, executable);
150  };
151 }
152 
153 Application::Application(
154  TerminationCallback termination_callback,
155  fuchsia::sys::Package package,
156  fuchsia::sys::StartupInfo startup_info,
157  std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
158  fidl::InterfaceRequest<fuchsia::sys::ComponentController>
159  application_controller_request)
160  : termination_callback_(std::move(termination_callback)),
161  debug_label_(DebugLabelForURL(startup_info.launch_info.url)),
162  application_controller_(this),
163  outgoing_dir_(new vfs::PseudoDir()),
164  runner_incoming_services_(runner_incoming_services),
165  weak_factory_(this) {
166  application_controller_.set_error_handler(
167  [this](zx_status_t status) { Kill(); });
168 
169  FML_DCHECK(fdio_ns_.is_valid());
170  // LaunchInfo::url non-optional.
171  auto& launch_info = startup_info.launch_info;
172 
173  // LaunchInfo::arguments optional.
174  if (auto& arguments = launch_info.arguments) {
175  settings_.dart_entrypoint_args = arguments.value();
176  }
177 
178  // Determine where data and assets are stored within /pkg.
179  std::string data_path;
180  std::string assets_path;
181  ParseProgramMetadata(startup_info.program_metadata, &data_path, &assets_path);
182 
183  if (data_path.empty()) {
184  FML_DLOG(ERROR) << "Could not find a /pkg/data directory for "
185  << package.resolved_url;
186  return;
187  }
188 
189  // Setup /tmp to be mapped to the process-local memfs.
191 
192  // LaunchInfo::flat_namespace optional.
193  for (size_t i = 0; i < startup_info.flat_namespace.paths.size(); ++i) {
194  const auto& path = startup_info.flat_namespace.paths.at(i);
195  if (path == kTmpPath) {
196  continue;
197  }
198 
199  zx::channel dir;
200  if (path == kServiceRootPath) {
201  svc_ = std::make_unique<sys::ServiceDirectory>(
202  std::move(startup_info.flat_namespace.directories.at(i)));
203  dir = svc_->CloneChannel().TakeChannel();
204  } else {
205  dir = std::move(startup_info.flat_namespace.directories.at(i));
206  }
207 
208  zx_handle_t dir_handle = dir.release();
209  if (fdio_ns_bind(fdio_ns_.get(), path.data(), dir_handle) != ZX_OK) {
210  FML_DLOG(ERROR) << "Could not bind path to namespace: " << path;
211  zx_handle_close(dir_handle);
212  }
213  }
214 
215  {
216  fml::UniqueFD ns_fd(fdio_ns_opendir(fdio_ns_.get()));
217  FML_DCHECK(ns_fd.is_valid());
218 
219  constexpr mode_t mode = O_RDONLY | O_DIRECTORY;
220 
221  application_assets_directory_.reset(
222  openat(ns_fd.get(), assets_path.c_str(), mode));
223  FML_DCHECK(application_assets_directory_.is_valid());
224 
225  application_data_directory_.reset(
226  openat(ns_fd.get(), data_path.c_str(), mode));
227  FML_DCHECK(application_data_directory_.is_valid());
228  }
229 
230  // TODO: LaunchInfo::out.
231 
232  // TODO: LaunchInfo::err.
233 
234  // LaunchInfo::service_request optional.
235  if (launch_info.directory_request) {
236  outgoing_dir_->Serve(fuchsia::io::OPEN_RIGHT_READABLE |
237  fuchsia::io::OPEN_RIGHT_WRITABLE |
238  fuchsia::io::OPEN_FLAG_DIRECTORY,
239  std::move(launch_info.directory_request));
240  }
241 
242  directory_request_ = directory_ptr_.NewRequest();
243 
244  fidl::InterfaceHandle<fuchsia::io::Directory> flutter_public_dir;
245  // TODO(anmittal): when fixing enumeration using new c++ vfs, make sure that
246  // flutter_public_dir is only accessed once we receive OnOpen Event.
247  // That will prevent FL-175 for public directory
248  auto request = flutter_public_dir.NewRequest().TakeChannel();
249  fdio_service_connect_at(directory_ptr_.channel().get(), "svc",
250  request.release());
251 
252  auto composed_service_dir = std::make_unique<vfs::ComposedServiceDir>();
253  composed_service_dir->set_fallback(std::move(flutter_public_dir));
254 
255  // Clone and check if client is servicing the directory.
256  directory_ptr_->Clone(fuchsia::io::OPEN_FLAG_DESCRIBE |
258  fuchsia::io::OPEN_RIGHT_WRITABLE,
259  cloned_directory_ptr_.NewRequest());
260 
261  cloned_directory_ptr_.events().OnOpen =
262  [this](zx_status_t status, std::unique_ptr<fuchsia::io::NodeInfo> info) {
263  cloned_directory_ptr_.Unbind();
264  if (status != ZX_OK) {
265  FML_LOG(ERROR) << "could not bind out directory for flutter app("
266  << debug_label_
267  << "): " << zx_status_get_string(status);
268  return;
269  }
270  const char* other_dirs[] = {"debug", "ctrl", "diagnostics"};
271  // add other directories as RemoteDirs.
272  for (auto& dir_str : other_dirs) {
273  fidl::InterfaceHandle<fuchsia::io::Directory> dir;
274  auto request = dir.NewRequest().TakeChannel();
275  auto status = fdio_service_connect_at(directory_ptr_.channel().get(),
276  dir_str, request.release());
277  if (status == ZX_OK) {
278  outgoing_dir_->AddEntry(
279  dir_str, std::make_unique<vfs::RemoteDir>(dir.TakeChannel()));
280  } else {
281  FML_LOG(ERROR) << "could not add out directory entry(" << dir_str
282  << ") for flutter app(" << debug_label_
283  << "): " << zx_status_get_string(status);
284  }
285  }
286  };
287 
288  cloned_directory_ptr_.set_error_handler(
289  [this](zx_status_t status) { cloned_directory_ptr_.Unbind(); });
290 
291  // TODO: LaunchInfo::additional_services optional.
292 
293  // All launch arguments have been read. Perform service binding and
294  // final settings configuration. The next call will be to create a view
295  // for this application.
296  composed_service_dir->AddService(
297  fuchsia::ui::app::ViewProvider::Name_,
298  std::make_unique<vfs::Service>(
299  [this](zx::channel channel, async_dispatcher_t* dispatcher) {
300  shells_bindings_.AddBinding(
301  this, fidl::InterfaceRequest<fuchsia::ui::app::ViewProvider>(
302  std::move(channel)));
303  }));
304 
305  outgoing_dir_->AddEntry("svc", std::move(composed_service_dir));
306 
307  // Setup the application controller binding.
308  if (application_controller_request) {
309  application_controller_.Bind(std::move(application_controller_request));
310  }
311 
312  // Compare flutter_jit_runner in BUILD.gn.
313  settings_.vm_snapshot_data =
314  MakeDataFileMapping("/pkg/data/vm_snapshot_data.bin");
315  settings_.vm_snapshot_instr =
316  MakeDataFileMapping("/pkg/data/vm_snapshot_instructions.bin", true);
317 
318  settings_.isolate_snapshot_data =
319  MakeDataFileMapping("/pkg/data/isolate_core_snapshot_data.bin");
321  "/pkg/data/isolate_core_snapshot_instructions.bin", true);
322 
323  {
324  // Check if we can use the snapshot with the framework already loaded.
325  std::string runner_framework;
326  std::string app_framework;
327  if (dart_utils::ReadFileToString("pkg/data/runner.frameworkversion",
328  &runner_framework) &&
329  dart_utils::ReadFileToStringAt(application_data_directory_.get(),
330  "app.frameworkversion",
331  &app_framework) &&
332  (runner_framework.compare(app_framework) == 0)) {
333  settings_.vm_snapshot_data =
334  MakeDataFileMapping("/pkg/data/framework_vm_snapshot_data.bin");
335  settings_.vm_snapshot_instr =
336  MakeDataFileMapping("/pkg/data/vm_snapshot_instructions.bin", true);
337 
339  "/pkg/data/framework_isolate_core_snapshot_data.bin");
341  "/pkg/data/isolate_core_snapshot_instructions.bin", true);
342 
343  FML_LOG(INFO) << "Using snapshot with framework for "
344  << package.resolved_url;
345  } else {
346  FML_LOG(INFO) << "Using snapshot without framework for "
347  << package.resolved_url;
348  }
349  }
350 
351  // Load and use runner-specific configuration, if it exists.
352  std::string json_string;
353  if (dart_utils::ReadFileToString(kRunnerConfigPath, &json_string)) {
354  product_config_ = FlutterRunnerProductConfiguration(json_string);
355  } else {
356  FML_LOG(WARNING) << "Failed to load runner configuration from "
357  << kRunnerConfigPath << "; using default config values.";
358  }
359 
360 #if defined(DART_PRODUCT)
361  settings_.enable_observatory = false;
362 #else
363  settings_.enable_observatory = true;
364 
365  // TODO(cbracken): pass this in as a param to allow 0.0.0.0, ::1, etc.
366  settings_.observatory_host = "127.0.0.1";
367 #endif
368 
369  // Controls whether category "skia" trace events are enabled.
370  settings_.trace_skia = true;
371 
372  settings_.verbose_logging = true;
373 
374  settings_.advisory_script_uri = debug_label_;
375 
376  settings_.advisory_script_entrypoint = debug_label_;
377 
378  settings_.icu_data_path = "";
379 
380  settings_.assets_dir = application_assets_directory_.get();
381 
382  // Compare flutter_jit_app in flutter_app.gni.
383  settings_.application_kernel_list_asset = "app.dilplist";
384 
385  settings_.log_tag = debug_label_ + std::string{"(flutter)"};
386 
387  // No asserts in debug or release product.
388  // No asserts in release with flutter_profile=true (non-product)
389  // Yes asserts in non-product debug.
390 #if !defined(DART_PRODUCT) && (!defined(FLUTTER_PROFILE) || !defined(NDEBUG))
391  // Debug mode
392  settings_.disable_dart_asserts = false;
393 #else
394  // Release mode
395  settings_.disable_dart_asserts = true;
396 #endif
397 
398  settings_.task_observer_add =
399  std::bind(&CurrentMessageLoopAddAfterTaskObserver, std::placeholders::_1,
400  std::placeholders::_2);
401 
402  settings_.task_observer_remove = std::bind(
403  &CurrentMessageLoopRemoveAfterTaskObserver, std::placeholders::_1);
404 
405  settings_.dart_flags = {"--no_causal_async_stacks", "--lazy_async_stacks"};
406 
407  // Don't collect CPU samples from Dart VM C++ code.
408  settings_.dart_flags.push_back("--no_profile_vm");
409 
410  // Scale back CPU profiler sampling period on ARM64 to avoid overloading
411  // the tracing engine.
412 #if defined(__aarch64__)
413  settings_.dart_flags.push_back("--profile_period=10000");
414 #endif // defined(__aarch64__)
415 
416  auto weak_application = weak_factory_.GetWeakPtr();
417  auto platform_task_runner =
418  CreateFMLTaskRunner(async_get_default_dispatcher());
419  const std::string component_url = package.resolved_url;
420  settings_.unhandled_exception_callback = [weak_application,
421  platform_task_runner,
422  runner_incoming_services,
423  component_url](
424  const std::string& error,
425  const std::string& stack_trace) {
426  if (weak_application) {
427  // TODO(cbracken): unsafe. The above check and the PostTask below are
428  // happening on the UI thread. If the Application dtor and thread
429  // termination happen (on the platform thread) between the previous
430  // line and the next line, a crash will occur since we'll be posting
431  // to a dead thread. See Runner::OnApplicationTerminate() in
432  // runner.cc.
433  platform_task_runner->PostTask([weak_application,
434  runner_incoming_services, component_url,
435  error, stack_trace]() {
436  if (weak_application) {
437  dart_utils::HandleException(runner_incoming_services, component_url,
438  error, stack_trace);
439  } else {
440  FML_LOG(WARNING)
441  << "Exception was thrown which was not caught in Flutter app: "
442  << error;
443  }
444  });
445  } else {
446  FML_LOG(WARNING)
447  << "Exception was thrown which was not caught in Flutter app: "
448  << error;
449  }
450  // Ideally we would return whether HandleException returned ZX_OK, but
451  // short of knowing if the exception was correctly handled, we return
452  // false to have the error and stack trace printed in the logs.
453  return false;
454  };
455 
456  AttemptVMLaunchWithCurrentSettings(settings_);
457 }
458 
459 Application::~Application() = default;
460 
461 const std::string& Application::GetDebugLabel() const {
462  return debug_label_;
463 }
464 
465 class FileInNamespaceBuffer final : public fml::Mapping {
466  public:
467  FileInNamespaceBuffer(int namespace_fd, const char* path, bool executable)
468  : address_(nullptr), size_(0) {
469  fuchsia::mem::Buffer buffer;
470  if (!dart_utils::VmoFromFilenameAt(namespace_fd, path, executable,
471  &buffer)) {
472  return;
473  }
474  if (buffer.size == 0) {
475  return;
476  }
477 
478  uint32_t flags = ZX_VM_PERM_READ;
479  if (executable) {
480  flags |= ZX_VM_PERM_EXECUTE;
481  }
482  uintptr_t addr;
483  zx_status_t status =
484  zx::vmar::root_self()->map(flags, 0, buffer.vmo, 0, buffer.size, &addr);
485  if (status != ZX_OK) {
486  FML_LOG(FATAL) << "Failed to map " << path << ": "
487  << zx_status_get_string(status);
488  }
489 
490  address_ = reinterpret_cast<void*>(addr);
491  size_ = buffer.size;
492  }
493 
495  if (address_ != nullptr) {
496  zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(address_),
497  size_);
498  address_ = nullptr;
499  size_ = 0;
500  }
501  }
502 
503  // |fml::Mapping|
504  const uint8_t* GetMapping() const override {
505  return reinterpret_cast<const uint8_t*>(address_);
506  }
507 
508  // |fml::Mapping|
509  size_t GetSize() const override { return size_; }
510 
511  private:
512  void* address_;
513  size_t size_;
514 
516 };
517 
518 std::unique_ptr<fml::Mapping> CreateWithContentsOfFile(int namespace_fd,
519  const char* file_path,
520  bool executable) {
521  FML_TRACE_EVENT("flutter", "LoadFile", "path", file_path);
522  auto source = std::make_unique<FileInNamespaceBuffer>(namespace_fd, file_path,
523  executable);
524  return source->GetMapping() == nullptr ? nullptr : std::move(source);
525 }
526 
527 void Application::AttemptVMLaunchWithCurrentSettings(
528  const flutter::Settings& settings) {
530  // We will be initializing the VM lazily in this case.
531  return;
532  }
533 
534  // Compare with flutter_aot_app in flutter_app.gni.
536 
537  std::shared_ptr<dart_utils::ElfSnapshot> snapshot =
538  std::make_shared<dart_utils::ElfSnapshot>();
539  if (snapshot->Load(application_data_directory_.get(),
540  "app_aot_snapshot.so")) {
541  const uint8_t* isolate_data = snapshot->IsolateData();
542  const uint8_t* isolate_instructions = snapshot->IsolateInstrs();
543  const uint8_t* vm_data = snapshot->VmData();
544  const uint8_t* vm_instructions = snapshot->VmInstrs();
545  if (isolate_data == nullptr || isolate_instructions == nullptr ||
546  vm_data == nullptr || vm_instructions == nullptr) {
547  FML_LOG(FATAL) << "ELF snapshot missing AOT symbols.";
548  return;
549  }
550  auto hold_snapshot = [snapshot](const uint8_t* _, size_t __) {};
551  vm_snapshot = fml::MakeRefCounted<flutter::DartSnapshot>(
552  std::make_shared<fml::NonOwnedMapping>(vm_data, 0, hold_snapshot),
553  std::make_shared<fml::NonOwnedMapping>(vm_instructions, 0,
554  hold_snapshot));
555  isolate_snapshot_ = fml::MakeRefCounted<flutter::DartSnapshot>(
556  std::make_shared<fml::NonOwnedMapping>(isolate_data, 0, hold_snapshot),
557  std::make_shared<fml::NonOwnedMapping>(isolate_instructions, 0,
558  hold_snapshot));
559  } else {
560  vm_snapshot = fml::MakeRefCounted<flutter::DartSnapshot>(
561  CreateWithContentsOfFile(application_data_directory_.get(),
562  "vm_snapshot_data.bin", false),
563  CreateWithContentsOfFile(application_data_directory_.get(),
564  "vm_snapshot_instructions.bin", true));
565 
566  isolate_snapshot_ = fml::MakeRefCounted<flutter::DartSnapshot>(
567  CreateWithContentsOfFile(application_data_directory_.get(),
568  "isolate_snapshot_data.bin", false),
569  CreateWithContentsOfFile(application_data_directory_.get(),
570  "isolate_snapshot_instructions.bin", true));
571  }
572 
574  std::move(vm_snapshot), //
575  isolate_snapshot_ //
576  );
577  FML_CHECK(vm) << "Mut be able to initialize the VM.";
578 }
579 
580 void Application::Kill() {
581  application_controller_.events().OnTerminated(
582  last_return_code_.second, fuchsia::sys::TerminationReason::EXITED);
583 
584  termination_callback_(this);
585  // WARNING: Don't do anything past this point as this instance may have been
586  // collected.
587 }
588 
589 void Application::Detach() {
590  application_controller_.set_error_handler(nullptr);
591 }
592 
593 void Application::OnEngineTerminate(const Engine* shell_holder) {
594  auto found = std::find_if(shell_holders_.begin(), shell_holders_.end(),
595  [shell_holder](const auto& holder) {
596  return holder.get() == shell_holder;
597  });
598 
599  if (found == shell_holders_.end()) {
600  return;
601  }
602 
603  // We may launch multiple shell in this application. However, we will
604  // terminate when the last shell goes away. The error code return to the
605  // application controller will be the last isolate that had an error.
606  auto return_code = shell_holder->GetEngineReturnCode();
607  if (return_code.has_value()) {
608  last_return_code_ = {true, return_code.value()};
609  }
610 
611  shell_holders_.erase(found);
612 
613  if (shell_holders_.size() == 0) {
614  Kill();
615  // WARNING: Don't do anything past this point because the delegate may have
616  // collected this instance via the termination callback.
617  }
618 }
619 
620 void Application::CreateView(
621  zx::eventpair token,
622  fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> /*incoming_services*/,
623  fidl::InterfaceHandle<
624  fuchsia::sys::ServiceProvider> /*outgoing_services*/) {
625  auto view_ref_pair = scenic::ViewRefPair::New();
626  CreateViewWithViewRef(std::move(token), std::move(view_ref_pair.control_ref),
627  std::move(view_ref_pair.view_ref));
628 }
629 
630 void Application::CreateViewWithViewRef(
631  zx::eventpair view_token,
632  fuchsia::ui::views::ViewRefControl control_ref,
633  fuchsia::ui::views::ViewRef view_ref) {
634  if (!svc_) {
635  FML_DLOG(ERROR)
636  << "Component incoming services was invalid when attempting to "
637  "create a shell for a view provider request.";
638  return;
639  }
640 
641  shell_holders_.emplace(std::make_unique<Engine>(
642  *this, // delegate
643  debug_label_, // thread label
644  svc_, // Component incoming services
645  runner_incoming_services_, // Runner incoming services
646  settings_, // settings
647  std::move(isolate_snapshot_), // isolate snapshot
648  scenic::ToViewToken(std::move(view_token)), // view token
649  scenic::ViewRefPair{
650  .control_ref = std::move(control_ref),
651  .view_ref = std::move(view_ref),
652  },
653  std::move(fdio_ns_), // FDIO namespace
654  std::move(directory_request_), // outgoing request
655  product_config_ // product configuration
656  ));
657 }
658 
659 #if !defined(DART_PRODUCT)
661  for (const auto& engine : shell_holders_) {
662  engine->WriteProfileToTrace();
663  }
664 }
665 #endif // !defined(DART_PRODUCT)
666 
667 } // namespace flutter_runner
MappingCallback isolate_snapshot_instr
Definition: settings.h:78
std::function< std::unique_ptr< fml::Mapping >(void)> MappingCallback
Definition: settings.h:56
Settings settings_
DEF_SWITCHES_START snapshot asset path
Definition: switches.h:32
std::string advisory_script_entrypoint
Definition: settings.h:122
constexpr uint32_t OPEN_RIGHT_EXECUTABLE
Definition: component.cc:50
fml::RefPtr< fml::TaskRunner > CreateFMLTaskRunner(async_dispatcher_t *dispatcher)
std::string application_kernel_list_asset
Definition: settings.h:90
#define FML_DCHECK(condition)
Definition: logging.h:86
std::vector< std::string > dart_entrypoint_args
Definition: settings.h:96
std::string advisory_script_uri
Definition: settings.h:119
void HandleException(std::shared_ptr<::sys::ServiceDirectory > services, const std::string &component_url, const std::string &error, const std::string &stack_trace)
FlMethodResponse GError ** error
fml::UniqueFD::element_type assets_dir
Definition: settings.h:211
bool ReadFileToStringAt(int dirfd, const std::string &path, std::string *result)
Definition: files.cc:60
void CurrentMessageLoopRemoveAfterTaskObserver(intptr_t key)
void CurrentMessageLoopAddAfterTaskObserver(intptr_t key, fit::closure observer)
MappingCallback vm_snapshot_data
Definition: settings.h:71
void reset(const T &value=Traits::InvalidValue())
Definition: unique_object.h:62
constexpr char kDataKey[]
Definition: component.cc:54
static std::string DebugLabelForURL(const std::string &url)
Definition: component.cc:105
FileInNamespaceBuffer(int namespace_fd, const char *path, bool executable)
Definition: component.cc:467
#define FML_LOG(severity)
Definition: logging.h:65
size_t GetSize() const override
Definition: component.cc:509
const T & get() const
Definition: unique_object.h:87
bool VmoFromFilenameAt(int dirfd, const std::string &filename, bool executable, fuchsia::mem::Buffer *buffer)
Definition: vmo.cc:76
static DartVMRef Create(Settings settings, fml::RefPtr< DartSnapshot > vm_snapshot=nullptr, fml::RefPtr< DartSnapshot > isolate_snapshot=nullptr)
bool is_valid() const
Definition: unique_object.h:89
bool verbose_logging
Definition: settings.h:199
constexpr char kTmpPath[]
Definition: component.cc:56
UnhandledExceptionCallback unhandled_exception_callback
Definition: settings.h:196
const std::string & GetDebugLabel() const
Definition: component.cc:461
bool ReadFileToString(const std::string &path, std::string *result)
Definition: files.cc:56
const uint8_t * GetMapping() const override
Definition: component.cc:504
fit::function< void(const Application *)> TerminationCallback
Definition: component.h:57
static bool IsRunningPrecompiledCode()
Checks if VM instances in the process can run precompiled code. This call can be made at any time and...
Definition: dart_vm.cc:199
static void ParseProgramMetadata(const fidl::VectorPtr< fuchsia::sys::ProgramMetadata > &program_metadata, std::string *data_path, std::string *assets_path)
Definition: component.cc:61
std::string observatory_host
Definition: settings.h:135
TaskObserverAdd task_observer_add
Definition: settings.h:168
std::vector< std::string > dart_flags
Definition: settings.h:94
std::string icu_data_path
Definition: settings.h:207
MappingCallback isolate_snapshot_data
Definition: settings.h:76
bool enable_observatory
Definition: settings.h:127
constexpr char kAssetsKey[]
Definition: component.cc:55
static flutter::MappingCallback MakeDataFileMapping(const char *absolute_path, bool executable=false)
Definition: component.cc:146
#define FML_CHECK(condition)
Definition: logging.h:68
bool disable_dart_asserts
Definition: settings.h:110
static std::unique_ptr< fml::FileMapping > MakeFileMapping(const char *path, bool executable)
Definition: component.cc:114
constexpr char kRunnerConfigPath[]
Definition: component.cc:58
constexpr char kServiceRootPath[]
Definition: component.cc:57
void WriteProfileToTrace() const
Definition: component.cc:660
MappingCallback vm_snapshot_instr
Definition: settings.h:73
#define FML_DLOG(severity)
Definition: logging.h:85
TaskObserverRemove task_observer_remove
Definition: settings.h:169
std::unique_ptr< fml::Mapping > CreateWithContentsOfFile(int namespace_fd, const char *file_path, bool executable)
Definition: component.cc:518
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:27
#define FML_TRACE_EVENT(category_group, name,...)
Definition: trace_event.h:71
static ActiveApplication Create(TerminationCallback termination_callback, fuchsia::sys::Package package, fuchsia::sys::StartupInfo startup_info, std::shared_ptr< sys::ServiceDirectory > runner_incoming_services, fidl::InterfaceRequest< fuchsia::sys::ComponentController > controller)
Definition: component.cc:83
std::optional< uint32_t > GetEngineReturnCode() const
Definition: engine.cc:403
std::string log_tag
Definition: settings.h:200
constexpr uint32_t OPEN_RIGHT_READABLE
Definition: component.cc:47
static void SetupComponent(fdio_ns_t *ns)
Definition: tempfs.cc:63
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