Flutter Engine
The Flutter Engine
dart_runner.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 "dart_runner.h"
6
7#include <lib/async-loop/loop.h>
8#include <lib/async/default.h>
9#include <lib/vfs/cpp/pseudo_dir.h>
10#include <sys/stat.h>
11#include <zircon/status.h>
12#include <zircon/syscalls.h>
13
14#include <cerrno>
15#include <memory>
16#include <thread>
17#include <utility>
18
20#include "flutter/fml/command_line.h"
21#include "flutter/fml/logging.h"
22#include "flutter/fml/trace_event.h"
25#include "service_isolate.h"
26#include "third_party/dart/runtime/include/bin/dart_io_api.h"
29
30#if defined(AOT_RUNTIME)
31extern "C" uint8_t _kDartVmSnapshotData[];
32extern "C" uint8_t _kDartVmSnapshotInstructions[];
33#endif
34
35namespace dart_runner {
36
37namespace {
38
39const char* kDartVMArgs[] = {
40 // clang-format off
41
42 "--timeline_recorder=systrace",
43 "--timeline_streams=Compiler,Dart,Debugger,Embedder,GC,Isolate,VM",
44
45#if defined(AOT_RUNTIME)
46 "--precompilation",
47#else
48 "--enable_mirrors=false",
49#endif
50
51 // No asserts in debug or release product.
52 // No asserts in release with flutter_profile=true (non-product)
53 // Yes asserts in non-product debug.
54#if !defined(DART_PRODUCT) && (!defined(FLUTTER_PROFILE) || !defined(NDEBUG))
55 "--enable_asserts",
56#endif
57};
58
59Dart_Isolate IsolateGroupCreateCallback(const char* uri,
60 const char* name,
61 const char* package_root,
62 const char* package_config,
64 void* callback_data,
65 char** error) {
66 if (std::string(uri) == DART_VM_SERVICE_ISOLATE_NAME) {
67#if defined(DART_PRODUCT)
68 *error = strdup("The service isolate is not implemented in product mode");
69 return NULL;
70#else
71 return CreateServiceIsolate(uri, flags, error);
72#endif
73 }
74
75 *error = strdup("Isolate spawning is not implemented in dart_runner");
76 return NULL;
77}
78
79void IsolateShutdownCallback(void* isolate_group_data, void* isolate_data) {
80 // The service isolate (and maybe later the kernel isolate) doesn't have an
81 // async loop.
82 auto dispatcher = async_get_default_dispatcher();
83 auto loop = async_loop_from_dispatcher(dispatcher);
84 if (loop) {
87 if (queue) {
88 queue->Destroy();
89 }
90
91 async_loop_quit(loop);
92 }
93
94 auto state =
95 static_cast<std::shared_ptr<tonic::DartState>*>(isolate_group_data);
96 state->get()->SetIsShuttingDown();
97}
98
99void IsolateGroupCleanupCallback(void* isolate_group_data) {
100 delete static_cast<std::shared_ptr<tonic::DartState>*>(isolate_group_data);
101}
102
103// Runs the application for a Dart component.
104void RunApplication(
105 DartRunner* runner,
106 fuchsia::component::runner::ComponentStartInfo start_info,
107 std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
108 fidl::InterfaceRequest<fuchsia::component::runner::ComponentController>
109 controller) {
110 const int64_t start = Dart_TimelineGetMicros();
111
112 DartComponentController app(std::move(start_info), runner_incoming_services,
113 std::move(controller));
114 const bool success = app.SetUp();
115
116 const int64_t end = Dart_TimelineGetMicros();
118 "DartComponentController::SetUp", start, end, 0, nullptr,
119 Dart_Timeline_Event_Duration, 0, NULL, NULL);
120 if (success) {
121 app.Run();
122 }
123
124 if (Dart_CurrentIsolate()) {
126 }
127}
128
129void RunTestApplication(
130 DartRunner* runner,
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 fit::function<void(std::shared_ptr<DartTestComponentController>)>
136 component_created_callback,
137 fit::function<void(DartTestComponentController*)> done_callback) {
138 const int64_t start = Dart_TimelineGetMicros();
139
140 auto test_component = std::make_shared<DartTestComponentController>(
141 std::move(start_info), runner_incoming_services, std::move(controller),
142 std::move(done_callback));
143
144 component_created_callback(test_component);
145
146 // Start up the dart isolate and serve the suite protocol.
147 test_component->SetUp();
148
149 const int64_t end = Dart_TimelineGetMicros();
151 "DartTestComponentController::SetUp", start, end, 0, nullptr,
152 Dart_Timeline_Event_Duration, 0, NULL, NULL);
153}
154
155bool EntropySource(uint8_t* buffer, intptr_t count) {
156 zx_cprng_draw(buffer, count);
157 return true;
158}
159
160} // namespace
161
162// "args" are how the component specifies arguments to the runner.
163constexpr char kArgsKey[] = "args";
164
165/// Parses the |args| field from the "program" field to determine
166/// if a test component is being executed.
167bool IsTestProgram(const fuchsia::data::Dictionary& program_metadata) {
168 for (const auto& entry : program_metadata.entries()) {
169 if (entry.key.compare(kArgsKey) != 0 || entry.value == nullptr) {
170 continue;
171 }
172 auto args = entry.value->str_vec();
173
174 // fml::CommandLine expects the first argument to be the name of the
175 // program, so we prepend a dummy argument so we can use fml::CommandLine to
176 // parse the arguments for us.
177 std::vector<std::string> command_line_args = {""};
178 command_line_args.insert(command_line_args.end(), args.begin(), args.end());
180 command_line_args.begin(), command_line_args.end());
181
182 std::string is_test_str;
183 return parsed_args.GetOptionValue("is_test", &is_test_str) &&
184 is_test_str == "true";
185 }
186 return false;
187}
188
189DartRunner::DartRunner(sys::ComponentContext* context) : context_(context) {
190 context_->outgoing()
191 ->AddPublicService<fuchsia::component::runner::ComponentRunner>(
192 [this](fidl::InterfaceRequest<
193 fuchsia::component::runner::ComponentRunner> request) {
194 component_runner_bindings_.AddBinding(this, std::move(request));
195 });
196
197#if !defined(DART_PRODUCT)
198 // The VM service isolate uses the process-wide namespace. It writes the
199 // vm service protocol port under /tmp. The VMServiceObject exposes that
200 // port number to The Hub.
201 context_->outgoing()->debug_dir()->AddEntry(
203 std::make_unique<dart_utils::VMServiceObject>());
204
205#endif // !defined(DART_PRODUCT)
206
208
209 char* error =
210 Dart_SetVMFlags(dart_utils::ArraySize(kDartVMArgs), kDartVMArgs);
211 if (error) {
212 FML_LOG(FATAL) << "Dart_SetVMFlags failed: " << error;
213 }
214
217#if defined(AOT_RUNTIME)
218 params.vm_snapshot_data = ::_kDartVmSnapshotData;
219 params.vm_snapshot_instructions = ::_kDartVmSnapshotInstructions;
220#else
222 nullptr, "/pkg/data/vm_snapshot_data.bin", vm_snapshot_data_)) {
223 FML_LOG(FATAL) << "Failed to load vm snapshot data";
224 }
225 params.vm_snapshot_data = vm_snapshot_data_.address();
226#endif
227 params.create_group = IsolateGroupCreateCallback;
228 params.shutdown_isolate = IsolateShutdownCallback;
229 params.cleanup_group = IsolateGroupCleanupCallback;
230 params.entropy_source = EntropySource;
231#if !defined(DART_PRODUCT)
232 params.get_service_assets = GetVMServiceAssetsArchiveCallback;
233#endif
235 if (error)
236 FML_LOG(FATAL) << "Dart_Initialize failed: " << error;
237}
238
240 char* error = Dart_Cleanup();
241 if (error)
242 FML_LOG(FATAL) << "Dart_Cleanup failed: " << error;
243}
244
245void DartRunner::Start(
246 fuchsia::component::runner::ComponentStartInfo start_info,
247 fidl::InterfaceRequest<fuchsia::component::runner::ComponentController>
248 controller) {
249 // Parse the program field of the component's cml and check if it is a test
250 // component. If so, serve the |fuchsia.test.Suite| protocol from the
251 // component's outgoing directory, via DartTestComponentController.
252 if (IsTestProgram(start_info.program())) {
253 std::string url_copy = start_info.resolved_url();
254 TRACE_EVENT1("dart", "Start", "url", url_copy.c_str());
255 std::thread thread(
256 RunTestApplication, this, std::move(start_info), context_->svc(),
257 std::move(controller),
258 // component_created_callback
259 [this](std::shared_ptr<DartTestComponentController> ptr) {
260 test_components_.emplace(ptr.get(), std::move(ptr));
261 },
262 // done_callback
263 [this](DartTestComponentController* ptr) {
264 auto it = test_components_.find(ptr);
265 if (it != test_components_.end()) {
266 test_components_.erase(it);
267 }
268 });
269 thread.detach();
270 } else {
271 std::string url_copy = start_info.resolved_url();
272 TRACE_EVENT1("dart", "Start", "url", url_copy.c_str());
273 std::thread thread(RunApplication, this, std::move(start_info),
274 context_->svc(), std::move(controller));
275 thread.detach();
276 }
277}
278
279} // namespace dart_runner
int count
Definition: FontMgrTest.cpp:50
DartRunner(sys::ComponentContext *context)
Definition: dart_runner.cc:189
static bool LoadFromNamespace(fdio_ns_t *namespc, const std::string &path, MappedResource &resource, bool executable=false)
const uint8_t * address() const
static constexpr const char * kPortDirName
bool GetOptionValue(std::string_view name, std::string *value) const
Definition: command_line.cc:51
static DartMicrotaskQueue * GetForCurrentThread()
#define DART_INITIALIZE_PARAMS_CURRENT_VERSION
Definition: dart_api.h:840
DART_EXPORT void Dart_ShutdownIsolate(void)
struct _Dart_Isolate * Dart_Isolate
Definition: dart_api.h:88
DART_EXPORT DART_WARN_UNUSED_RESULT char * Dart_Initialize(Dart_InitializeParams *params)
DART_EXPORT Dart_Isolate Dart_CurrentIsolate(void)
DART_EXPORT DART_WARN_UNUSED_RESULT char * Dart_Cleanup(void)
#define DART_VM_SERVICE_ISOLATE_NAME
Definition: dart_api.h:3888
DART_EXPORT DART_WARN_UNUSED_RESULT char * Dart_SetVMFlags(int argc, const char **argv)
DART_EXPORT int64_t Dart_TimelineGetMicros()
@ Dart_Timeline_Event_Duration
DART_EXPORT void Dart_RecordTimelineEvent(const char *label, int64_t timestamp0, int64_t timestamp1_or_id, intptr_t flow_id_count, const int64_t *flow_ids, Dart_Timeline_Event_Type type, intptr_t argument_count, const char **argument_names, const char **argument_values)
const EmbeddedViewParams * params
VkQueue queue
Definition: main.cc:55
#define FATAL(error)
AtkStateType state
FlutterSemanticsFlag flags
glong glong end
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
const uint8_t uint32_t uint32_t GError ** error
#define FML_LOG(severity)
Definition: logging.h:82
Dart_NativeFunction function
Definition: fuchsia.cc:51
void BootstrapDartIo()
constexpr char kArgsKey[]
Definition: dart_runner.cc:163
bool IsTestProgram(const fuchsia::data::Dictionary &program_metadata)
Definition: dart_runner.cc:167
Dart_Handle GetVMServiceAssetsArchiveCallback()
Dart_Isolate CreateServiceIsolate(const char *uri, Dart_IsolateFlags *flags_unused, char **error)
size_t ArraySize(T(&array)[SIZE])
Definition: inlines.h:11
sys::ComponentContext * ComponentContext()
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
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 buffer
Definition: switches.h:126
char * strdup(const char *str1)
CommandLine CommandLineFromIterators(InputIterator first, InputIterator last)
Definition: command_line.h:204
#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val)
Definition: trace_event.h:141