Flutter Engine
The Flutter Engine
component_v2.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_v2.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/io.h>
14#include <lib/fdio/namespace.h>
15#include <lib/vfs/cpp/composed_service_dir.h>
16#include <lib/vfs/cpp/remote_dir.h>
17#include <lib/vfs/cpp/service.h>
18#include <sys/stat.h>
19#include <zircon/dlfcn.h>
20#include <zircon/status.h>
21#include <zircon/types.h>
22
23#include <memory>
24#include <regex>
25#include <sstream>
26
28#include "flutter/fml/command_line.h"
29#include "flutter/fml/mapping.h"
30#include "flutter/fml/platform/fuchsia/task_observers.h"
31#include "flutter/fml/synchronization/waitable_event.h"
32#include "flutter/fml/unique_fd.h"
33#include "flutter/runtime/dart_vm_lifecycle.h"
34#include "flutter/shell/common/switches.h"
40
41namespace flutter_runner {
42namespace {
43
44// "data" and "assets" are arguments that are specific to the Flutter runner.
45// They will likely go away if we migrate to the ELF runner.
46constexpr char kDataKey[] = "data";
47constexpr char kAssetsKey[] = "assets";
48
49// "args" are how the component specifies arguments to the runner.
50constexpr char kArgsKey[] = "args";
51constexpr char kOldGenHeapSizeKey[] = "old_gen_heap_size";
52constexpr char kExposeDirsKey[] = "expose_dirs";
53
54constexpr char kTmpPath[] = "/tmp";
55constexpr char kServiceRootPath[] = "/svc";
56constexpr char kRunnerConfigPath[] = "/config/data/flutter_runner_config";
57
58std::string DebugLabelForUrl(const std::string& url) {
59 auto found = url.rfind("/");
60 if (found == std::string::npos) {
61 return url;
62 } else {
63 return {url, found + 1};
64 }
65}
66
67/// Parses the |args| field from the "program" field into
68/// |metadata|.
69void ParseArgs(std::vector<std::string>& args, ProgramMetadata* metadata) {
70 // fml::CommandLine expects the first argument to be the name of the program,
71 // so we prepend a dummy argument so we can use fml::CommandLine to parse the
72 // arguments for us.
73 std::vector<std::string> command_line_args = {""};
74 command_line_args.insert(command_line_args.end(), args.begin(), args.end());
76 command_line_args.begin(), command_line_args.end());
77
78 std::string old_gen_heap_size_option;
79 if (parsed_args.GetOptionValue(kOldGenHeapSizeKey,
80 &old_gen_heap_size_option)) {
81 int64_t specified_old_gen_heap_size = strtol(
82 old_gen_heap_size_option.c_str(), nullptr /* endptr */, 10 /* base */);
83 if (specified_old_gen_heap_size != 0) {
84 metadata->old_gen_heap_size = specified_old_gen_heap_size;
85 } else {
86 FML_LOG(ERROR) << "Invalid old_gen_heap_size: "
87 << old_gen_heap_size_option;
88 }
89 }
90
91 std::string expose_dirs_option;
92 if (parsed_args.GetOptionValue(kExposeDirsKey, &expose_dirs_option)) {
93 // Parse the comma delimited string
94 std::vector<std::string> expose_dirs;
95 std::stringstream s(expose_dirs_option);
96 while (s.good()) {
97 std::string dir;
98 getline(s, dir, ','); // get first string delimited by comma
99 metadata->expose_dirs.push_back(dir);
100 }
101 }
102}
103
104} // namespace
105
107 const fuchsia::data::Dictionary& program_metadata) {
109
110 for (const auto& entry : program_metadata.entries()) {
111 if (entry.key.compare(kDataKey) == 0 && entry.value != nullptr) {
112 result.data_path = "pkg/" + entry.value->str();
113 } else if (entry.key.compare(kAssetsKey) == 0 && entry.value != nullptr) {
114 result.assets_path = "pkg/" + entry.value->str();
115 } else if (entry.key.compare(kArgsKey) == 0 && entry.value != nullptr) {
116 ParseArgs(entry.value->str_vec(), &result);
117 }
118 }
119
120 // assets_path defaults to the same as data_path if omitted.
121 if (result.assets_path.empty()) {
122 result.assets_path = result.data_path;
123 }
124
125 return result;
126}
127
129 TerminationCallback termination_callback,
130 fuchsia::component::runner::ComponentStartInfo start_info,
131 std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
132 fidl::InterfaceRequest<fuchsia::component::runner::ComponentController>
133 controller) {
134 auto thread = std::make_unique<fml::Thread>();
135 std::unique_ptr<ComponentV2> component;
136
138 thread->GetTaskRunner()->PostTask([&]() mutable {
139 component.reset(
140 new ComponentV2(std::move(termination_callback), std::move(start_info),
141 runner_incoming_services, std::move(controller)));
142 latch.Signal();
143 });
144
145 latch.Wait();
146 return {.platform_thread = std::move(thread),
147 .component = std::move(component)};
148}
149
150ComponentV2::ComponentV2(
151 TerminationCallback termination_callback,
152 fuchsia::component::runner::ComponentStartInfo start_info,
153 std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
154 fidl::InterfaceRequest<fuchsia::component::runner::ComponentController>
155 component_controller_request)
156 : termination_callback_(std::move(termination_callback)),
157 debug_label_(DebugLabelForUrl(start_info.resolved_url())),
158 component_controller_(this),
159 outgoing_dir_(new vfs::PseudoDir()),
160 runtime_dir_(new vfs::PseudoDir()),
161 runner_incoming_services_(runner_incoming_services),
162 weak_factory_(this) {
163 component_controller_.set_error_handler([this](zx_status_t status) {
164 FML_LOG(ERROR) << "ComponentController binding error for component("
165 << debug_label_ << "): " << zx_status_get_string(status);
166 KillWithEpitaph(
167 zx_status_t(fuchsia::component::Error::INSTANCE_CANNOT_START));
168 });
169
170 FML_DCHECK(fdio_ns_.is_valid());
171
172 // TODO(fxb/88391): Dart launch arguments.
173 FML_LOG(WARNING) << "program() arguments are currently ignored (fxb/88391).";
174
175 ProgramMetadata metadata = ParseProgramMetadata(start_info.program());
176
177 if (metadata.data_path.empty()) {
178 FML_LOG(ERROR) << "Could not find a /pkg/data directory for "
179 << start_info.resolved_url();
180 return;
181 }
182
183 dart_utils::BindTemp(fdio_ns_.get());
184
185 // ComponentStartInfo::ns (optional)
186 if (start_info.has_ns()) {
187 for (auto& entry : *start_info.mutable_ns()) {
188 // /tmp/ is mapped separately to to a process-local virtual filesystem,
189 // so we ignore it here.
190 const auto& path = entry.path();
191 if (path == kTmpPath) {
192 continue;
193 }
194
195 // We should never receive namespace entries without a directory, but we
196 // check it anyways to avoid crashing if we do.
197 if (!entry.has_directory()) {
198 FML_LOG(ERROR) << "Namespace entry at path (" << path
199 << ") has no directory.";
200 continue;
201 }
202
203 zx::channel dir;
204 if (path == kServiceRootPath) {
205 svc_ = std::make_unique<sys::ServiceDirectory>(
206 std::move(*entry.mutable_directory()));
207 dir = svc_->CloneChannel().TakeChannel();
208 } else {
209 dir = entry.mutable_directory()->TakeChannel();
210 }
211
212 zx_handle_t dir_handle = dir.release();
213 if (fdio_ns_bind(fdio_ns_.get(), path.data(), dir_handle) != ZX_OK) {
214 FML_LOG(ERROR) << "Could not bind path to namespace: " << path;
215 zx_handle_close(dir_handle);
216 }
217 }
218 }
219
220 // Open the data and assets directories inside our namespace.
221 {
222 fml::UniqueFD ns_fd(fdio_ns_opendir(fdio_ns_.get()));
223 FML_DCHECK(ns_fd.is_valid());
224
225 constexpr mode_t mode = O_RDONLY | O_DIRECTORY;
226
227 component_assets_directory_.reset(
228 openat(ns_fd.get(), metadata.assets_path.c_str(), mode));
229 FML_DCHECK(component_assets_directory_.is_valid());
230
231 component_data_directory_.reset(
232 openat(ns_fd.get(), metadata.data_path.c_str(), mode));
233 FML_DCHECK(component_data_directory_.is_valid());
234 }
235
236 // ComponentStartInfo::runtime_dir (optional).
237 if (start_info.has_runtime_dir()) {
238 runtime_dir_->Serve(fuchsia::io::OpenFlags::RIGHT_READABLE |
239 fuchsia::io::OpenFlags::RIGHT_WRITABLE |
240 fuchsia::io::OpenFlags::DIRECTORY,
241 start_info.mutable_runtime_dir()->TakeChannel());
242 }
243
244 // ComponentStartInfo::outgoing_dir (optional).
245 if (start_info.has_outgoing_dir()) {
246 outgoing_dir_->Serve(fuchsia::io::OpenFlags::RIGHT_READABLE |
247 fuchsia::io::OpenFlags::RIGHT_WRITABLE |
248 fuchsia::io::OpenFlags::DIRECTORY,
249 start_info.mutable_outgoing_dir()->TakeChannel());
250 }
251
252 directory_request_ = directory_ptr_.NewRequest();
253
254 fuchsia::io::DirectoryHandle flutter_public_dir;
255 // TODO(anmittal): when fixing enumeration using new c++ vfs, make sure that
256 // flutter_public_dir is only accessed once we receive OnOpen Event.
257 // That will prevent FL-175 for public directory
258 auto request = flutter_public_dir.NewRequest().TakeChannel();
259 fdio_service_connect_at(directory_ptr_.channel().get(), "svc",
260 request.release());
261
262#pragma clang diagnostic push
263#pragma clang diagnostic ignored "-Wdeprecated-declarations"
264
265 auto composed_service_dir = std::make_unique<vfs::ComposedServiceDir>();
266 composed_service_dir->set_fallback(std::move(flutter_public_dir));
267
268#pragma clang diagnostic pop
269
270 // Clone and check if client is servicing the directory.
271 directory_ptr_->Clone(fuchsia::io::OpenFlags::DESCRIBE |
272 fuchsia::io::OpenFlags::CLONE_SAME_RIGHTS,
273 cloned_directory_ptr_.NewRequest());
274
275 // Collect our standard set of directories along with directories that are
276 // included in the cml file to expose.
277 std::vector<std::string> other_dirs = {"debug", "ctrl"};
278 for (auto dir : metadata.expose_dirs) {
279 other_dirs.push_back(dir);
280 }
281
282 cloned_directory_ptr_.events().OnOpen = [this, other_dirs](zx_status_t status,
283 auto unused) {
284 cloned_directory_ptr_.Unbind();
285 if (status != ZX_OK) {
286 FML_LOG(ERROR) << "could not bind out directory for flutter component("
287 << debug_label_ << "): " << zx_status_get_string(status);
288 return;
289 }
290
291 // add other directories as RemoteDirs.
292 for (auto& dir_str : other_dirs) {
293 fuchsia::io::DirectoryHandle dir;
294 auto request = dir.NewRequest().TakeChannel();
295 auto status = fdio_open_at(
296 directory_ptr_.channel().get(), dir_str.c_str(),
297 static_cast<uint32_t>(fuchsia::io::OpenFlags::DIRECTORY |
298 fuchsia::io::OpenFlags::RIGHT_READABLE),
299 request.release());
300 if (status == ZX_OK) {
301 outgoing_dir_->AddEntry(
302 dir_str.c_str(),
303 std::make_unique<vfs::RemoteDir>(dir.TakeChannel()));
304 } else {
305 FML_LOG(ERROR) << "could not add out directory entry(" << dir_str
306 << ") for flutter component(" << debug_label_
307 << "): " << zx_status_get_string(status);
308 }
309 }
310 };
311
312 cloned_directory_ptr_.set_error_handler(
313 [this](zx_status_t status) { cloned_directory_ptr_.Unbind(); });
314
315 // TODO(fxb/89162): Close handles from ComponentStartInfo::numbered_handles
316 // since we're not using them. See documentation from ComponentController:
317 // https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/fidl/fuchsia.component.runner/component_runner.fidl;l=97;drc=e3b39f2b57e720770773b857feca4f770ee0619e
318
319 // TODO(fxb/89162): There's an OnPublishDiagnostics event we may want to
320 // fire for diagnostics. See documentation from ComponentController:
321 // https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/fidl/fuchsia.component.runner/component_runner.fidl;l=181;drc=e3b39f2b57e720770773b857feca4f770ee0619e
322
323 // All launch arguments have been read. Perform service binding and
324 // final settings configuration. The next call will be to create a view
325 // for this component.
326 composed_service_dir->AddService(
327 fuchsia::ui::app::ViewProvider::Name_,
328 std::make_unique<vfs::Service>(
329 [this](zx::channel channel, async_dispatcher_t* dispatcher) {
330 shells_bindings_.AddBinding(
331 this, fidl::InterfaceRequest<fuchsia::ui::app::ViewProvider>(
332 std::move(channel)));
333 }));
334 outgoing_dir_->AddEntry("svc", std::move(composed_service_dir));
335
336 // Setup the component controller binding.
337 if (component_controller_request) {
338 component_controller_.Bind(std::move(component_controller_request));
339 }
340
341 // Load and use runner-specific configuration, if it exists.
342 std::string json_string;
343 if (dart_utils::ReadFileToString(kRunnerConfigPath, &json_string)) {
344 product_config_ = FlutterRunnerProductConfiguration(json_string);
345 FML_LOG(INFO) << "Successfully loaded runner configuration: "
346 << json_string;
347 } else {
348 FML_LOG(WARNING) << "Failed to load runner configuration from "
349 << kRunnerConfigPath << "; using default config values.";
350 }
351
352 // Load VM and component bytecode.
353 // For AOT, compare with flutter_aot_app in flutter_app.gni.
354 // For JIT, compare flutter_jit_runner in BUILD.gn.
356 std::shared_ptr<dart_utils::ElfSnapshot> snapshot =
357 std::make_shared<dart_utils::ElfSnapshot>();
358 if (snapshot->Load(component_data_directory_.get(),
359 "app_aot_snapshot.so")) {
360 const uint8_t* isolate_data = snapshot->IsolateData();
361 const uint8_t* isolate_instructions = snapshot->IsolateInstrs();
362 const uint8_t* vm_data = snapshot->VmData();
363 const uint8_t* vm_instructions = snapshot->VmInstrs();
364 if (isolate_data == nullptr || isolate_instructions == nullptr ||
365 vm_data == nullptr || vm_instructions == nullptr) {
366 FML_LOG(FATAL) << "ELF snapshot missing AOT symbols.";
367 return;
368 }
369 auto hold_snapshot = [snapshot](const uint8_t* _, size_t __) {};
370 settings_.vm_snapshot_data = [hold_snapshot, vm_data]() {
371 return std::make_unique<fml::NonOwnedMapping>(vm_data, 0, hold_snapshot,
372 true /* dontneed_safe */);
373 };
374 settings_.vm_snapshot_instr = [hold_snapshot, vm_instructions]() {
375 return std::make_unique<fml::NonOwnedMapping>(
376 vm_instructions, 0, hold_snapshot, true /* dontneed_safe */);
377 };
378 settings_.isolate_snapshot_data = [hold_snapshot, isolate_data]() {
379 return std::make_unique<fml::NonOwnedMapping>(
380 isolate_data, 0, hold_snapshot, true /* dontneed_safe */);
381 };
382 settings_.isolate_snapshot_instr = [hold_snapshot,
383 isolate_instructions]() {
384 return std::make_unique<fml::NonOwnedMapping>(
385 isolate_instructions, 0, hold_snapshot, true /* dontneed_safe */);
386 };
387 isolate_snapshot_ = fml::MakeRefCounted<flutter::DartSnapshot>(
388 std::make_shared<fml::NonOwnedMapping>(isolate_data, 0, hold_snapshot,
389 true /* dontneed_safe */),
390 std::make_shared<fml::NonOwnedMapping>(isolate_instructions, 0,
391 hold_snapshot,
392 true /* dontneed_safe */));
393 } else {
394 const int namespace_fd = component_data_directory_.get();
395 settings_.vm_snapshot_data = [namespace_fd]() {
396 return LoadFile(namespace_fd, "vm_snapshot_data.bin",
397 false /* executable */);
398 };
399 settings_.vm_snapshot_instr = [namespace_fd]() {
400 return LoadFile(namespace_fd, "vm_snapshot_instructions.bin",
401 true /* executable */);
402 };
403 settings_.isolate_snapshot_data = [namespace_fd]() {
404 return LoadFile(namespace_fd, "isolate_snapshot_data.bin",
405 false /* executable */);
406 };
407 settings_.isolate_snapshot_instr = [namespace_fd]() {
408 return LoadFile(namespace_fd, "isolate_snapshot_instructions.bin",
409 true /* executable */);
410 };
411 }
412 } else {
413 settings_.vm_snapshot_data = []() {
414 return MakeFileMapping("/pkg/data/vm_snapshot_data.bin",
415 false /* executable */);
416 };
417 settings_.isolate_snapshot_data = []() {
418 return MakeFileMapping("/pkg/data/isolate_core_snapshot_data.bin",
419 false /* executable */);
420 };
421 }
422
423#if defined(DART_PRODUCT)
424 settings_.enable_vm_service = false;
425#else
426 settings_.enable_vm_service = true;
427
428 // TODO(cbracken): pass this in as a param to allow 0.0.0.0, ::1, etc.
429 settings_.vm_service_host = "127.0.0.1";
430#endif
431
432 // Controls whether category "skia" trace events are enabled.
433 settings_.trace_skia = true;
434
435 settings_.verbose_logging = true;
436
437 settings_.advisory_script_uri = debug_label_;
438
439 settings_.advisory_script_entrypoint = debug_label_;
440
441 settings_.icu_data_path = "";
442
443 settings_.assets_dir = component_assets_directory_.get();
444
445 // Compare flutter_jit_app in flutter_app.gni.
446 settings_.application_kernel_list_asset = "app.dilplist";
447
448 settings_.log_tag = debug_label_ + std::string{"(flutter)"};
449
450 if (metadata.old_gen_heap_size.has_value()) {
451 settings_.old_gen_heap_size = *metadata.old_gen_heap_size;
452 }
453
454 // No asserts in debug or release product.
455 // No asserts in release with flutter_profile=true (non-product)
456 // Yes asserts in non-product debug.
457#if !defined(DART_PRODUCT) && (!defined(FLUTTER_PROFILE) || !defined(NDEBUG))
458 // Debug mode
459 settings_.disable_dart_asserts = false;
460#else
461 // Release mode
462 settings_.disable_dart_asserts = true;
463#endif
464
465 // Do not leak the VM; allow it to shut down normally when the last shell
466 // terminates.
467 settings_.leak_vm = false;
468
469 settings_.task_observer_add =
471 std::placeholders::_1, std::placeholders::_2);
472
473 settings_.task_observer_remove = std::bind(
474 &fml::CurrentMessageLoopRemoveAfterTaskObserver, std::placeholders::_1);
475
476 settings_.log_message_callback = [](const std::string& tag,
477 const std::string& message) {
478 if (!tag.empty()) {
479 std::cout << tag << ": ";
480 }
481 std::cout << message << std::endl;
482 };
483
484 settings_.dart_flags = {};
485
486 // Don't collect CPU samples from Dart VM C++ code.
487 settings_.dart_flags.push_back("--no_profile_vm");
488
489 // Scale back CPU profiler sampling period on ARM64 to avoid overloading
490 // the tracing engine.
491#if defined(__aarch64__)
492 settings_.dart_flags.push_back("--profile_period=10000");
493#endif // defined(__aarch64__)
494
495 auto platform_task_runner = fml::MessageLoop::GetCurrent().GetTaskRunner();
496 const std::string component_url = start_info.resolved_url();
497 settings_.unhandled_exception_callback = [weak = weak_factory_.GetWeakPtr(),
498 platform_task_runner,
499 runner_incoming_services,
500 component_url](
501 const std::string& error,
502 const std::string& stack_trace) {
503 if (weak) {
504 // TODO(cbracken): unsafe. The above check and the PostTask below are
505 // happening on the UI thread. If the Component dtor and thread
506 // termination happen (on the platform thread) between the previous
507 // line and the next line, a crash will occur since we'll be posting
508 // to a dead thread. See Runner::OnComponentV2Terminate() in
509 // runner.cc.
510 platform_task_runner->PostTask([weak, runner_incoming_services,
511 component_url, error, stack_trace]() {
512 if (weak) {
513 dart_utils::HandleException(runner_incoming_services, component_url,
514 error, stack_trace);
515 } else {
516 FML_LOG(WARNING)
517 << "Exception was thrown which was not caught in Flutter app: "
518 << error;
519 }
520 });
521 } else {
522 FML_LOG(WARNING)
523 << "Exception was thrown which was not caught in Flutter app: "
524 << error;
525 }
526 // Ideally we would return whether HandleException returned ZX_OK, but
527 // short of knowing if the exception was correctly handled, we return
528 // false to have the error and stack trace printed in the logs.
529 return false;
530 };
531}
532
533ComponentV2::~ComponentV2() = default;
534
535const std::string& ComponentV2::GetDebugLabel() const {
536 return debug_label_;
537}
538
539void ComponentV2::Kill() {
540 FML_VLOG(1) << "received Kill event";
541
542 // From the documentation for ComponentController, ZX_OK should be sent when
543 // the ComponentController receives a termination request. However, if the
544 // component exited with a non-zero return code, we indicate this by sending
545 // an INTERNAL epitaph instead.
546 //
547 // TODO(fxb/86666): Communicate return code from the ComponentController once
548 // v2 has support.
549 auto [got_return_code, return_code] = last_return_code_;
550 if (got_return_code && return_code == 0) {
551 KillWithEpitaph(ZX_OK);
552 } else {
553 if (got_return_code) {
554 FML_LOG(ERROR) << "Component exited with non-zero return code: "
555 << return_code;
556 } else {
557 FML_LOG(ERROR) << "Failed to get return code for component";
558 }
559
560 KillWithEpitaph(zx_status_t(fuchsia::component::Error::INTERNAL));
561 }
562
563 // WARNING: Don't do anything past this point as this instance may have been
564 // collected.
565}
566
567void ComponentV2::KillWithEpitaph(zx_status_t epitaph_status) {
568 component_controller_.set_error_handler(nullptr);
569 component_controller_.Close(epitaph_status);
570
571 termination_callback_(this);
572 // WARNING: Don't do anything past this point as this instance may have been
573 // collected.
574}
575
576void ComponentV2::Stop() {
577 FML_VLOG(1) << "received Stop event";
578
579 // TODO(fxb/89162): Any other cleanup logic we should do that's appropriate
580 // for Stop but not for Kill?
581 KillWithEpitaph(ZX_OK);
582}
583
584void ComponentV2::OnEngineTerminate(const Engine* shell_holder) {
585 auto found = std::find_if(shell_holders_.begin(), shell_holders_.end(),
586 [shell_holder](const auto& holder) {
587 return holder.get() == shell_holder;
588 });
589
590 if (found == shell_holders_.end()) {
591 // This indicates a deeper issue with memory management and should never
592 // happen.
593 FML_LOG(ERROR) << "Tried to terminate an unregistered shell holder.";
594 FML_DCHECK(false);
595
596 return;
597 }
598
599 // We may launch multiple shells in this component. However, we will
600 // terminate when the last shell goes away. The error code returned to the
601 // component controller will be the last isolate that had an error.
602 auto return_code = shell_holder->GetEngineReturnCode();
603 if (return_code.has_value()) {
604 last_return_code_ = {true, return_code.value()};
605 } else {
606 FML_LOG(ERROR) << "Failed to get return code from terminated shell holder.";
607 }
608
609 shell_holders_.erase(found);
610
611 if (shell_holders_.empty()) {
612 FML_VLOG(1) << "Killing component because all shell holders have been "
613 "terminated.";
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
620void ComponentV2::CreateView2(fuchsia::ui::app::CreateView2Args view_args) {
621 if (!svc_) {
623 << "Component incoming services was invalid when attempting to "
624 "create a shell for a view provider request.";
625 return;
626 }
627
628 fuchsia::ui::views::ViewRefControl view_ref_control;
629 fuchsia::ui::views::ViewRef view_ref;
630 auto status = zx::eventpair::create(
631 /*options*/ 0u, &view_ref_control.reference, &view_ref.reference);
632 ZX_ASSERT(status == ZX_OK);
633 view_ref_control.reference.replace(
634 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
635 &view_ref_control.reference);
636 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
637 auto view_ref_pair =
638 std::make_pair(std::move(view_ref_control), std::move(view_ref));
639
640 shell_holders_.emplace(std::make_unique<Engine>(
641 *this, // delegate
642 debug_label_, // thread label
643 svc_, // Component incoming services
644 runner_incoming_services_, // Runner incoming services
645 settings_, // settings
646 std::move(
647 *view_args.mutable_view_creation_token()), // view creation token
648 std::move(view_ref_pair), // view ref pair
649 std::move(fdio_ns_), // FDIO namespace
650 std::move(directory_request_), // outgoing request
651 product_config_, // product configuration
652 std::vector<std::string>() // dart entrypoint args
653 ));
654}
655
656#if !defined(DART_PRODUCT)
658 for (const auto& engine : shell_holders_) {
659 engine->WriteProfileToTrace();
660 }
661}
662#endif // !defined(DART_PRODUCT)
663
664} // namespace flutter_runner
static bool unused
#define __
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:205
static ProgramMetadata ParseProgramMetadata(const fuchsia::data::Dictionary &program_metadata)
static ActiveComponentV2 Create(TerminationCallback termination_callback, fuchsia::component::runner::ComponentStartInfo start_info, std::shared_ptr< sys::ServiceDirectory > runner_incoming_services, fidl::InterfaceRequest< fuchsia::component::runner::ComponentController > controller)
const std::string & GetDebugLabel() const
fit::function< void(const ComponentV2 *)> TerminationCallback
Definition: component_v2.h:61
bool GetOptionValue(std::string_view name, std::string *value) const
Definition: command_line.cc:51
fml::RefPtr< fml::TaskRunner > GetTaskRunner() const
Definition: message_loop.cc:56
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
Definition: message_loop.cc:19
void reset(const T &value=Traits::InvalidValue())
Definition: unique_object.h:62
bool is_valid() const
Definition: unique_object.h:89
const T & get() const
Definition: unique_object.h:87
FlutterEngine engine
Definition: main.cc:68
struct MyStruct s
#define FATAL(error)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static constexpr char kArgsKey[]
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
#define FML_VLOG(verbose_level)
Definition: logging.h:98
#define FML_LOG(severity)
Definition: logging.h:82
#define FML_DCHECK(condition)
Definition: logging.h:103
Win32Message message
def ParseArgs(args)
Definition: copy_tree.py:14
bool ReadFileToString(const std::string &path, std::string *result)
Definition: files.cc:56
void HandleException(std::shared_ptr<::sys::ServiceDirectory > services, const std::string &component_url, const std::string &error, const std::string &stack_trace)
void BindTemp(fdio_ns_t *ns)
Definition: tempfs.cc:23
std::unique_ptr< fml::FileMapping > MakeFileMapping(const char *path, bool executable)
std::unique_ptr< fml::Mapping > LoadFile(int namespace_fd, const char *path, bool executable)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
Definition: switches.h:145
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228
void CurrentMessageLoopAddAfterTaskObserver(intptr_t key, fit::closure observer)
void CurrentMessageLoopRemoveAfterTaskObserver(intptr_t key)
CommandLine CommandLineFromIterators(InputIterator first, InputIterator last)
Definition: command_line.h:204
Definition: ref_ptr.h:256
std::string advisory_script_entrypoint
Definition: settings.h:180
fml::UniqueFD::element_type assets_dir
Definition: settings.h:323
std::string advisory_script_uri
Definition: settings.h:177
LogMessageCallback log_message_callback
Definition: settings.h:308
MappingCallback isolate_snapshot_instr
Definition: settings.h:129
TaskObserverRemove task_observer_remove
Definition: settings.h:274
MappingCallback isolate_snapshot_data
Definition: settings.h:127
MappingCallback vm_snapshot_data
Definition: settings.h:122
bool enable_vm_service
Definition: settings.h:189
std::string vm_service_host
Definition: settings.h:197
TaskObserverAdd task_observer_add
Definition: settings.h:273
std::string application_kernel_list_asset
Definition: settings.h:147
std::string log_tag
Definition: settings.h:312
bool verbose_logging
Definition: settings.h:311
std::vector< std::string > dart_flags
Definition: settings.h:151
std::string icu_data_path
Definition: settings.h:319
bool disable_dart_asserts
Definition: settings.h:167
UnhandledExceptionCallback unhandled_exception_callback
Definition: settings.h:303
MappingCallback vm_snapshot_instr
Definition: settings.h:124
int64_t old_gen_heap_size
Definition: settings.h:344
int_closure create
#define ERROR(message)
Definition: elf_loader.cc:260