Flutter Engine
 
Loading...
Searching...
No Matches
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/fidl/cpp/client.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
30#include "flutter/fml/mapping.h"
41
42namespace flutter_runner {
43namespace {
44
45// "data" and "assets" are arguments that are specific to the Flutter runner.
46// They will likely go away if we migrate to the ELF runner.
47constexpr char kDataKey[] = "data";
48constexpr char kAssetsKey[] = "assets";
49
50// "args" are how the component specifies arguments to the runner.
51constexpr char kArgsKey[] = "args";
52constexpr char kOldGenHeapSizeKey[] = "old_gen_heap_size";
53constexpr char kExposeDirsKey[] = "expose_dirs";
54
55constexpr char kTmpPath[] = "/tmp";
56constexpr char kServiceRootPath[] = "/svc";
57constexpr char kRunnerConfigPath[] = "/config/data/flutter_runner_config";
58
59std::string DebugLabelForUrl(const std::string& url) {
60 auto found = url.rfind("/");
61 if (found == std::string::npos) {
62 return url;
63 } else {
64 return {url, found + 1};
65 }
66}
67
68/// Parses the |args| field from the "program" field into
69/// |metadata|.
70void ParseArgs(std::vector<std::string>& args, ProgramMetadata* metadata) {
71 // fml::CommandLine expects the first argument to be the name of the program,
72 // so we prepend a dummy argument so we can use fml::CommandLine to parse the
73 // arguments for us.
74 std::vector<std::string> command_line_args = {""};
75 command_line_args.insert(command_line_args.end(), args.begin(), args.end());
77 command_line_args.begin(), command_line_args.end());
78
79 std::string old_gen_heap_size_option;
80 if (parsed_args.GetOptionValue(kOldGenHeapSizeKey,
81 &old_gen_heap_size_option)) {
82 int64_t specified_old_gen_heap_size = strtol(
83 old_gen_heap_size_option.c_str(), nullptr /* endptr */, 10 /* base */);
84 if (specified_old_gen_heap_size != 0) {
85 metadata->old_gen_heap_size = specified_old_gen_heap_size;
86 } else {
87 FML_LOG(ERROR) << "Invalid old_gen_heap_size: "
88 << old_gen_heap_size_option;
89 }
90 }
91
92 std::string expose_dirs_option;
93 if (parsed_args.GetOptionValue(kExposeDirsKey, &expose_dirs_option)) {
94 // Parse the comma delimited string
95 std::vector<std::string> expose_dirs;
96 std::stringstream s(expose_dirs_option);
97 while (s.good()) {
98 std::string dir;
99 getline(s, dir, ','); // get first string delimited by comma
100 metadata->expose_dirs.push_back(dir);
101 }
102 }
103}
104
105} // namespace
106
108 const fuchsia::data::Dictionary& program_metadata) {
109 ProgramMetadata result;
110
111 for (const auto& entry : program_metadata.entries()) {
112 if (entry.key.compare(kDataKey) == 0 && entry.value != nullptr) {
113 result.data_path = "pkg/" + entry.value->str();
114 } else if (entry.key.compare(kAssetsKey) == 0 && entry.value != nullptr) {
115 result.assets_path = "pkg/" + entry.value->str();
116 } else if (entry.key.compare(kArgsKey) == 0 && entry.value != nullptr) {
117 ParseArgs(entry.value->str_vec(), &result);
118 }
119 }
120
121 // assets_path defaults to the same as data_path if omitted.
122 if (result.assets_path.empty()) {
123 result.assets_path = result.data_path;
124 }
125
126 return result;
127}
128
130 TerminationCallback termination_callback,
131 fuchsia::component::runner::ComponentStartInfo start_info,
132 std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
133 fidl::InterfaceRequest<fuchsia::component::runner::ComponentController>
134 controller) {
135 auto thread = std::make_unique<fml::Thread>();
136 std::unique_ptr<ComponentV2> component;
137
139 thread->GetTaskRunner()->PostTask([&]() mutable {
140 component.reset(
141 new ComponentV2(std::move(termination_callback), std::move(start_info),
142 runner_incoming_services, std::move(controller)));
143 latch.Signal();
144 });
145
146 latch.Wait();
147 return {.platform_thread = std::move(thread),
148 .component = std::move(component)};
149}
150
151ComponentV2::ComponentV2(
152 TerminationCallback termination_callback,
153 fuchsia::component::runner::ComponentStartInfo start_info,
154 std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
155 fidl::InterfaceRequest<fuchsia::component::runner::ComponentController>
156 component_controller_request)
157 : termination_callback_(std::move(termination_callback)),
158 debug_label_(DebugLabelForUrl(start_info.resolved_url())),
159 component_controller_(this),
160 outgoing_dir_(new vfs::PseudoDir()),
161 runtime_dir_(new vfs::PseudoDir()),
162 runner_incoming_services_(runner_incoming_services),
163 weak_factory_(this) {
164 component_controller_.set_error_handler([this](zx_status_t status) {
165 FML_LOG(ERROR) << "ComponentController binding error for component("
166 << debug_label_ << "): " << zx_status_get_string(status);
167 KillWithEpitaph(
168 zx_status_t(fuchsia::component::Error::INSTANCE_CANNOT_START));
169 });
170
171 FML_DCHECK(fdio_ns_.is_valid());
172
173 // TODO(fxb/88391): Dart launch arguments.
174 FML_LOG(WARNING) << "program() arguments are currently ignored (fxb/88391).";
175
176 ProgramMetadata metadata = ParseProgramMetadata(start_info.program());
177
178 if (metadata.data_path.empty()) {
179 FML_LOG(ERROR) << "Could not find a /pkg/data directory for "
180 << start_info.resolved_url();
181 return;
182 }
183
184 dart_utils::BindTemp(fdio_ns_.get());
185
186 // ComponentStartInfo::ns (optional)
187 if (start_info.has_ns()) {
188 for (auto& entry : *start_info.mutable_ns()) {
189 // /tmp/ is mapped separately to to a process-local virtual filesystem,
190 // so we ignore it here.
191 const auto& path = entry.path();
192 if (path == kTmpPath) {
193 continue;
194 }
195
196 // We should never receive namespace entries without a directory, but we
197 // check it anyways to avoid crashing if we do.
198 if (!entry.has_directory()) {
199 FML_LOG(ERROR) << "Namespace entry at path (" << path
200 << ") has no directory.";
201 continue;
202 }
203
204 zx::channel dir;
205 if (path == kServiceRootPath) {
206 svc_ = std::make_unique<sys::ServiceDirectory>(
207 std::move(*entry.mutable_directory()));
208 dir = svc_->CloneChannel().TakeChannel();
209 } else {
210 dir = entry.mutable_directory()->TakeChannel();
211 }
212
213 zx_handle_t dir_handle = dir.release();
214 if (fdio_ns_bind(fdio_ns_.get(), path.data(), dir_handle) != ZX_OK) {
215 FML_LOG(ERROR) << "Could not bind path to namespace: " << path;
216 zx_handle_close(dir_handle);
217 }
218 }
219 }
220
221 // Open the data and assets directories inside our namespace.
222 {
223 fml::UniqueFD ns_fd(fdio_ns_opendir(fdio_ns_.get()));
224 FML_DCHECK(ns_fd.is_valid());
225
226 constexpr mode_t mode = O_RDONLY | O_DIRECTORY;
227
228 component_assets_directory_.reset(
229 openat(ns_fd.get(), metadata.assets_path.c_str(), mode));
230 FML_DCHECK(component_assets_directory_.is_valid());
231
232 component_data_directory_.reset(
233 openat(ns_fd.get(), metadata.data_path.c_str(), mode));
234 FML_DCHECK(component_data_directory_.is_valid());
235 }
236
237 // ComponentStartInfo::runtime_dir (optional).
238 if (start_info.has_runtime_dir()) {
239 fidl::ServerEnd<fuchsia_io::Directory> server_end{
240 start_info.mutable_runtime_dir()->TakeChannel()};
241 runtime_dir_->Serve(
242 fuchsia_io::wire::kPermReadable | fuchsia_io::wire::kPermWritable,
243 std::move(server_end));
244 }
245
246 // ComponentStartInfo::outgoing_dir (optional).
247 if (start_info.has_outgoing_dir()) {
248 fidl::ServerEnd<fuchsia_io::Directory> server_end{
249 start_info.mutable_outgoing_dir()->TakeChannel()};
250 outgoing_dir_->Serve(
251 fuchsia_io::wire::kPermReadable | fuchsia_io::wire::kPermWritable,
252 std::move(server_end));
253 }
254
255 directory_request_ = directory_ptr_.NewRequest();
256
257 fuchsia::io::DirectoryHandle flutter_public_dir;
258 {
259 auto request = flutter_public_dir.NewRequest().TakeChannel();
260 const zx_status_t status =
261 fdio_open3_at(directory_ptr_.channel().get(), "svc",
262 uint64_t{fuchsia::io::PERM_READABLE}, request.release());
263 if (status != ZX_OK) {
264 FML_LOG(ERROR) << "Failed to open /svc in outgoing directory: "
265 << zx_status_get_string(status);
266 return;
267 }
268 }
269
270 auto composed_service_dir = std::make_unique<vfs::ComposedServiceDir>();
271 composed_service_dir->SetFallback(
272 fidl::ClientEnd<fuchsia_io::Directory>(flutter_public_dir.TakeChannel()));
273
274 // Request an event from the directory to ensure it is servicing requests.
275 directory_ptr_->Open(".",
276 fuchsia::io::Flags::PROTOCOL_NODE |
277 fuchsia::io::Flags::FLAG_SEND_REPRESENTATION,
278 {}, cloned_directory_ptr_.NewRequest().TakeChannel());
279
280 // Collect our standard set of directories along with directories that are
281 // included in the cml file to expose.
282 std::vector<std::string> other_dirs = {"debug", "ctrl"};
283 for (auto dir : metadata.expose_dirs) {
284 other_dirs.push_back(dir);
285 }
286
287 cloned_directory_ptr_.events().OnRepresentation = [this,
288 other_dirs](auto unused) {
289 cloned_directory_ptr_.Unbind();
290 // add other directories as RemoteDirs.
291 for (auto& dir_str : other_dirs) {
292 fuchsia::io::DirectoryHandle dir;
293 auto request = dir.NewRequest().TakeChannel();
294 const zx_status_t status =
295 fdio_open3_at(directory_ptr_.channel().get(), dir_str.c_str(),
296 uint64_t{fuchsia::io::Flags::PROTOCOL_DIRECTORY |
297 fuchsia::io::PERM_READABLE},
298 request.release());
299 if (status == ZX_OK) {
300 outgoing_dir_->AddEntry(
301 dir_str.c_str(),
302 std::make_unique<vfs::RemoteDir>(dir.TakeChannel()));
303 } else {
304 FML_LOG(ERROR) << "could not add out directory entry(" << dir_str
305 << ") for flutter component(" << debug_label_
306 << "): " << zx_status_get_string(status);
307 }
308 }
309 };
310
311 cloned_directory_ptr_.set_error_handler(
312 [this](zx_status_t status) { cloned_directory_ptr_.Unbind(); });
313
314 // TODO(fxb/89162): Close handles from ComponentStartInfo::numbered_handles
315 // since we're not using them. See documentation from ComponentController:
316 // https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/fidl/fuchsia.component.runner/component_runner.fidl;l=97;drc=e3b39f2b57e720770773b857feca4f770ee0619e
317
318 // TODO(fxb/89162): There's an OnPublishDiagnostics event we may want to
319 // fire for diagnostics. See documentation from ComponentController:
320 // https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/fidl/fuchsia.component.runner/component_runner.fidl;l=181;drc=e3b39f2b57e720770773b857feca4f770ee0619e
321
322 // All launch arguments have been read. Perform service binding and
323 // final settings configuration. The next call will be to create a view
324 // for this component.
325 composed_service_dir->AddService(
326 fuchsia::ui::app::ViewProvider::Name_,
327 std::make_unique<vfs::Service>(
328 [this](zx::channel channel, async_dispatcher_t* dispatcher) {
329 shells_bindings_.AddBinding(
330 this, fidl::InterfaceRequest<fuchsia::ui::app::ViewProvider>(
331 std::move(channel)));
332 }));
333 outgoing_dir_->AddEntry("svc", std::move(composed_service_dir));
334
335 // Setup the component controller binding.
336 if (component_controller_request) {
337 component_controller_.Bind(std::move(component_controller_request));
338 }
339
340 // Load and use runner-specific configuration, if it exists.
341 std::string json_string;
342 if (dart_utils::ReadFileToString(kRunnerConfigPath, &json_string)) {
343 product_config_ = FlutterRunnerProductConfiguration(json_string);
344 FML_LOG(INFO) << "Successfully loaded runner configuration: "
345 << json_string;
346 } else {
347 FML_LOG(WARNING) << "Failed to load runner configuration from "
348 << kRunnerConfigPath << "; using default config values.";
349 }
350
351 // Load VM and component bytecode.
352 // For AOT, compare with flutter_aot_app in flutter_app.gni.
353 // For JIT, compare flutter_jit_runner in BUILD.gn.
355 std::shared_ptr<dart_utils::ElfSnapshot> snapshot =
356 std::make_shared<dart_utils::ElfSnapshot>();
357 if (snapshot->Load(component_data_directory_.get(),
358 "app_aot_snapshot.so")) {
359 const uint8_t* isolate_data = snapshot->IsolateData();
360 const uint8_t* isolate_instructions = snapshot->IsolateInstrs();
361 const uint8_t* vm_data = snapshot->VmData();
362 const uint8_t* vm_instructions = snapshot->VmInstrs();
363 if (isolate_data == nullptr || isolate_instructions == nullptr ||
364 vm_data == nullptr || vm_instructions == nullptr) {
365 FML_LOG(FATAL) << "ELF snapshot missing AOT symbols.";
366 return;
367 }
368 auto hold_snapshot = [snapshot](const uint8_t* _, size_t __) {};
369 settings_.vm_snapshot_data = [hold_snapshot, vm_data]() {
370 return std::make_unique<fml::NonOwnedMapping>(vm_data, 0, hold_snapshot,
371 true /* dontneed_safe */);
372 };
373 settings_.vm_snapshot_instr = [hold_snapshot, vm_instructions]() {
374 return std::make_unique<fml::NonOwnedMapping>(
375 vm_instructions, 0, hold_snapshot, true /* dontneed_safe */);
376 };
377 settings_.isolate_snapshot_data = [hold_snapshot, isolate_data]() {
378 return std::make_unique<fml::NonOwnedMapping>(
379 isolate_data, 0, hold_snapshot, true /* dontneed_safe */);
380 };
381 settings_.isolate_snapshot_instr = [hold_snapshot,
382 isolate_instructions]() {
383 return std::make_unique<fml::NonOwnedMapping>(
384 isolate_instructions, 0, hold_snapshot, true /* dontneed_safe */);
385 };
386 isolate_snapshot_ = fml::MakeRefCounted<flutter::DartSnapshot>(
387 std::make_shared<fml::NonOwnedMapping>(isolate_data, 0, hold_snapshot,
388 true /* dontneed_safe */),
389 std::make_shared<fml::NonOwnedMapping>(isolate_instructions, 0,
390 hold_snapshot,
391 true /* dontneed_safe */));
392 } else {
393 const int namespace_fd = component_data_directory_.get();
394 settings_.vm_snapshot_data = [namespace_fd]() {
395 return LoadFile(namespace_fd, "vm_snapshot_data.bin",
396 false /* executable */);
397 };
398 settings_.vm_snapshot_instr = [namespace_fd]() {
399 return LoadFile(namespace_fd, "vm_snapshot_instructions.bin",
400 true /* executable */);
401 };
402 settings_.isolate_snapshot_data = [namespace_fd]() {
403 return LoadFile(namespace_fd, "isolate_snapshot_data.bin",
404 false /* executable */);
405 };
406 settings_.isolate_snapshot_instr = [namespace_fd]() {
407 return LoadFile(namespace_fd, "isolate_snapshot_instructions.bin",
408 true /* executable */);
409 };
410 }
411 } else {
412 settings_.vm_snapshot_data = []() {
413 return MakeFileMapping("/pkg/data/vm_snapshot_data.bin",
414 false /* executable */);
415 };
416 settings_.isolate_snapshot_data = []() {
417 return MakeFileMapping("/pkg/data/isolate_core_snapshot_data.bin",
418 false /* executable */);
419 };
420 }
421
422#if defined(DART_PRODUCT)
423 settings_.enable_vm_service = false;
424#else
425 settings_.enable_vm_service = true;
426
427 // TODO(cbracken): pass this in as a param to allow 0.0.0.0, ::1, etc.
428 settings_.vm_service_host = "127.0.0.1";
429#endif
430
431 // Controls whether category "skia" trace events are enabled.
432 settings_.trace_skia = true;
433
434 settings_.verbose_logging = true;
435
436 settings_.advisory_script_uri = debug_label_;
437
438 settings_.advisory_script_entrypoint = debug_label_;
439
440 settings_.icu_data_path = "";
441
442 settings_.assets_dir = component_assets_directory_.get();
443
444 // Compare flutter_jit_app in flutter_app.gni.
445 settings_.application_kernel_list_asset = "app.dilplist";
446
447 settings_.log_tag = debug_label_ + std::string{"(flutter)"};
448
449 if (metadata.old_gen_heap_size.has_value()) {
450 settings_.old_gen_heap_size = *metadata.old_gen_heap_size;
451 }
452
453 // No asserts in debug or release product.
454 // No asserts in release with flutter_profile=true (non-product)
455 // Yes asserts in non-product debug.
456#if !defined(DART_PRODUCT) && (!defined(FLUTTER_PROFILE) || !defined(NDEBUG))
457 // Debug mode
458 settings_.disable_dart_asserts = false;
459#else
460 // Release mode
461 settings_.disable_dart_asserts = true;
462#endif
463
464 // Do not leak the VM; allow it to shut down normally when the last shell
465 // terminates.
466 settings_.leak_vm = false;
467
468 settings_.task_observer_add =
470 std::placeholders::_1, std::placeholders::_2);
471
472 settings_.task_observer_remove =
474 std::placeholders::_1, std::placeholders::_2);
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_) {
622 FML_LOG(ERROR)
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
665 bool method_has_response) {
666 FML_LOG(ERROR) << "Unknown method called on ComponentV2. Ordinal: "
667 << ordinal;
668}
669
670} // namespace flutter_runner
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:176
static ProgramMetadata ParseProgramMetadata(const fuchsia::data::Dictionary &program_metadata)
void handle_unknown_method(uint64_t ordinal, bool method_has_response) override
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
bool GetOptionValue(std::string_view name, std::string *value) const
fml::RefPtr< fml::TaskRunner > GetTaskRunner() const
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
void reset(const T &value=Traits::InvalidValue())
bool is_valid() const
const T & get() const
FlutterEngine engine
Definition main.cc:84
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static constexpr char kArgsKey[]
const gchar * channel
G_BEGIN_DECLS GBytes * message
const uint8_t uint32_t uint32_t GError ** error
#define FML_VLOG(verbose_level)
Definition logging.h:117
#define FML_LOG(severity)
Definition logging.h:101
#define FML_DCHECK(condition)
Definition logging.h:122
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 switch_defs.h:52
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all 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
fml::TaskQueueId CurrentMessageLoopAddAfterTaskObserver(intptr_t key, fit::closure observer)
void CurrentMessageLoopRemoveAfterTaskObserver(fml::TaskQueueId queue_id, intptr_t key)
CommandLine CommandLineFromIterators(InputIterator first, InputIterator last)
Definition ref_ptr.h:261
std::string advisory_script_entrypoint
Definition settings.h:176
fml::UniqueFD::element_type assets_dir
Definition settings.h:331
std::string advisory_script_uri
Definition settings.h:173
LogMessageCallback log_message_callback
Definition settings.h:316
MappingCallback isolate_snapshot_instr
Definition settings.h:123
TaskObserverRemove task_observer_remove
Definition settings.h:282
MappingCallback isolate_snapshot_data
Definition settings.h:121
MappingCallback vm_snapshot_data
Definition settings.h:116
std::string vm_service_host
Definition settings.h:193
TaskObserverAdd task_observer_add
Definition settings.h:281
std::string application_kernel_list_asset
Definition settings.h:141
std::string log_tag
Definition settings.h:320
std::vector< std::string > dart_flags
Definition settings.h:145
std::string icu_data_path
Definition settings.h:327
bool disable_dart_asserts
Definition settings.h:162
UnhandledExceptionCallback unhandled_exception_callback
Definition settings.h:311
MappingCallback vm_snapshot_instr
Definition settings.h:118
int64_t old_gen_heap_size
Definition settings.h:352