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 "flutter/runtime/runtime_controller.h"
6
7 #include "flutter/fml/message_loop.h"
8 #include "flutter/fml/trace_event.h"
9 #include "flutter/lib/ui/compositing/scene.h"
10 #include "flutter/lib/ui/ui_dart_state.h"
11 #include "flutter/lib/ui/window/window.h"
12 #include "flutter/runtime/runtime_delegate.h"
13
14 namespace flutter {
15
RuntimeController(RuntimeDelegate & p_client,DartVM * p_vm,fml::RefPtr<const DartSnapshot> p_isolate_snapshot,fml::RefPtr<const DartSnapshot> p_shared_snapshot,TaskRunners p_task_runners,fml::WeakPtr<IOManager> p_io_manager,fml::WeakPtr<ImageDecoder> p_image_decoder,std::string p_advisory_script_uri,std::string p_advisory_script_entrypoint,std::function<void (int64_t)> p_idle_notification_callback,fml::closure p_isolate_create_callback,fml::closure p_isolate_shutdown_callback)16 RuntimeController::RuntimeController(
17 RuntimeDelegate& p_client,
18 DartVM* p_vm,
19 fml::RefPtr<const DartSnapshot> p_isolate_snapshot,
20 fml::RefPtr<const DartSnapshot> p_shared_snapshot,
21 TaskRunners p_task_runners,
22 fml::WeakPtr<IOManager> p_io_manager,
23 fml::WeakPtr<ImageDecoder> p_image_decoder,
24 std::string p_advisory_script_uri,
25 std::string p_advisory_script_entrypoint,
26 std::function<void(int64_t)> p_idle_notification_callback,
27 fml::closure p_isolate_create_callback,
28 fml::closure p_isolate_shutdown_callback)
29 : RuntimeController(p_client,
30 p_vm,
31 std::move(p_isolate_snapshot),
32 std::move(p_shared_snapshot),
33 std::move(p_task_runners),
34 std::move(p_io_manager),
35 std::move(p_image_decoder),
36 std::move(p_advisory_script_uri),
37 std::move(p_advisory_script_entrypoint),
38 p_idle_notification_callback,
39 WindowData{/* default window data */},
40 p_isolate_create_callback,
41 p_isolate_shutdown_callback) {}
42
RuntimeController(RuntimeDelegate & p_client,DartVM * p_vm,fml::RefPtr<const DartSnapshot> p_isolate_snapshot,fml::RefPtr<const DartSnapshot> p_shared_snapshot,TaskRunners p_task_runners,fml::WeakPtr<IOManager> p_io_manager,fml::WeakPtr<ImageDecoder> p_image_decoder,std::string p_advisory_script_uri,std::string p_advisory_script_entrypoint,std::function<void (int64_t)> idle_notification_callback,WindowData p_window_data,fml::closure p_isolate_create_callback,fml::closure p_isolate_shutdown_callback)43 RuntimeController::RuntimeController(
44 RuntimeDelegate& p_client,
45 DartVM* p_vm,
46 fml::RefPtr<const DartSnapshot> p_isolate_snapshot,
47 fml::RefPtr<const DartSnapshot> p_shared_snapshot,
48 TaskRunners p_task_runners,
49 fml::WeakPtr<IOManager> p_io_manager,
50 fml::WeakPtr<ImageDecoder> p_image_decoder,
51 std::string p_advisory_script_uri,
52 std::string p_advisory_script_entrypoint,
53 std::function<void(int64_t)> idle_notification_callback,
54 WindowData p_window_data,
55 fml::closure p_isolate_create_callback,
56 fml::closure p_isolate_shutdown_callback)
57 : client_(p_client),
58 vm_(p_vm),
59 isolate_snapshot_(std::move(p_isolate_snapshot)),
60 shared_snapshot_(std::move(p_shared_snapshot)),
61 task_runners_(p_task_runners),
62 io_manager_(p_io_manager),
63 image_decoder_(p_image_decoder),
64 advisory_script_uri_(p_advisory_script_uri),
65 advisory_script_entrypoint_(p_advisory_script_entrypoint),
66 idle_notification_callback_(idle_notification_callback),
67 window_data_(std::move(p_window_data)),
68 isolate_create_callback_(p_isolate_create_callback),
69 isolate_shutdown_callback_(p_isolate_shutdown_callback) {
70 // Create the root isolate as soon as the runtime controller is initialized.
71 // It will be run at a later point when the engine provides a run
72 // configuration and then runs the isolate.
73 auto strong_root_isolate =
74 DartIsolate::CreateRootIsolate(vm_->GetVMData()->GetSettings(), //
75 isolate_snapshot_, //
76 shared_snapshot_, //
77 task_runners_, //
78 std::make_unique<Window>(this), //
79 io_manager_, //
80 image_decoder_, //
81 p_advisory_script_uri, //
82 p_advisory_script_entrypoint, //
83 nullptr, //
84 isolate_create_callback_, //
85 isolate_shutdown_callback_ //
86 )
87 .lock();
88
89 FML_CHECK(strong_root_isolate) << "Could not create root isolate.";
90
91 // The root isolate ivar is weak.
92 root_isolate_ = strong_root_isolate;
93
94 strong_root_isolate->SetReturnCodeCallback([this](uint32_t code) {
95 root_isolate_return_code_ = {true, code};
96 });
97
98 if (auto* window = GetWindowIfAvailable()) {
99 tonic::DartState::Scope scope(strong_root_isolate);
100 window->DidCreateIsolate();
101 if (!FlushRuntimeStateToIsolate()) {
102 FML_DLOG(ERROR) << "Could not setup initial isolate state.";
103 }
104 } else {
105 FML_DCHECK(false) << "RuntimeController created without window binding.";
106 }
107
108 FML_DCHECK(Dart_CurrentIsolate() == nullptr);
109 }
110
~RuntimeController()111 RuntimeController::~RuntimeController() {
112 FML_DCHECK(Dart_CurrentIsolate() == nullptr);
113 std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
114 if (root_isolate) {
115 root_isolate->SetReturnCodeCallback(nullptr);
116 auto result = root_isolate->Shutdown();
117 if (!result) {
118 FML_DLOG(ERROR) << "Could not shutdown the root isolate.";
119 }
120 root_isolate_ = {};
121 }
122 }
123
IsRootIsolateRunning() const124 bool RuntimeController::IsRootIsolateRunning() const {
125 std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
126 if (root_isolate) {
127 return root_isolate->GetPhase() == DartIsolate::Phase::Running;
128 }
129 return false;
130 }
131
Clone() const132 std::unique_ptr<RuntimeController> RuntimeController::Clone() const {
133 return std::unique_ptr<RuntimeController>(new RuntimeController(
134 client_, //
135 vm_, //
136 isolate_snapshot_, //
137 shared_snapshot_, //
138 task_runners_, //
139 io_manager_, //
140 image_decoder_, //
141 advisory_script_uri_, //
142 advisory_script_entrypoint_, //
143 idle_notification_callback_, //
144 window_data_, //
145 isolate_create_callback_, //
146 isolate_shutdown_callback_ //
147 ));
148 }
149
FlushRuntimeStateToIsolate()150 bool RuntimeController::FlushRuntimeStateToIsolate() {
151 return SetViewportMetrics(window_data_.viewport_metrics) &&
152 SetLocales(window_data_.locale_data) &&
153 SetSemanticsEnabled(window_data_.semantics_enabled) &&
154 SetAccessibilityFeatures(window_data_.accessibility_feature_flags_) &&
155 SetUserSettingsData(window_data_.user_settings_data) &&
156 SetLifecycleState(window_data_.lifecycle_state);
157 }
158
SetViewportMetrics(const ViewportMetrics & metrics)159 bool RuntimeController::SetViewportMetrics(const ViewportMetrics& metrics) {
160 window_data_.viewport_metrics = metrics;
161
162 if (auto* window = GetWindowIfAvailable()) {
163 window->UpdateWindowMetrics(metrics);
164 return true;
165 }
166 return false;
167 }
168
SetLocales(const std::vector<std::string> & locale_data)169 bool RuntimeController::SetLocales(
170 const std::vector<std::string>& locale_data) {
171 window_data_.locale_data = locale_data;
172
173 if (auto* window = GetWindowIfAvailable()) {
174 window->UpdateLocales(locale_data);
175 return true;
176 }
177
178 return false;
179 }
180
SetUserSettingsData(const std::string & data)181 bool RuntimeController::SetUserSettingsData(const std::string& data) {
182 window_data_.user_settings_data = data;
183
184 if (auto* window = GetWindowIfAvailable()) {
185 window->UpdateUserSettingsData(window_data_.user_settings_data);
186 return true;
187 }
188
189 return false;
190 }
191
SetLifecycleState(const std::string & data)192 bool RuntimeController::SetLifecycleState(const std::string& data) {
193 window_data_.lifecycle_state = data;
194
195 if (auto* window = GetWindowIfAvailable()) {
196 window->UpdateLifecycleState(window_data_.lifecycle_state);
197 return true;
198 }
199
200 return false;
201 }
202
SetSemanticsEnabled(bool enabled)203 bool RuntimeController::SetSemanticsEnabled(bool enabled) {
204 window_data_.semantics_enabled = enabled;
205
206 if (auto* window = GetWindowIfAvailable()) {
207 window->UpdateSemanticsEnabled(window_data_.semantics_enabled);
208 return true;
209 }
210
211 return false;
212 }
213
SetAccessibilityFeatures(int32_t flags)214 bool RuntimeController::SetAccessibilityFeatures(int32_t flags) {
215 window_data_.accessibility_feature_flags_ = flags;
216 if (auto* window = GetWindowIfAvailable()) {
217 window->UpdateAccessibilityFeatures(
218 window_data_.accessibility_feature_flags_);
219 return true;
220 }
221
222 return false;
223 }
224
BeginFrame(fml::TimePoint frame_time)225 bool RuntimeController::BeginFrame(fml::TimePoint frame_time) {
226 if (auto* window = GetWindowIfAvailable()) {
227 window->BeginFrame(frame_time);
228 return true;
229 }
230 return false;
231 }
232
ReportTimings(std::vector<int64_t> timings)233 bool RuntimeController::ReportTimings(std::vector<int64_t> timings) {
234 if (auto* window = GetWindowIfAvailable()) {
235 window->ReportTimings(std::move(timings));
236 return true;
237 }
238 return false;
239 }
240
NotifyIdle(int64_t deadline)241 bool RuntimeController::NotifyIdle(int64_t deadline) {
242 std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
243 if (!root_isolate) {
244 return false;
245 }
246
247 tonic::DartState::Scope scope(root_isolate);
248
249 Dart_NotifyIdle(deadline);
250
251 // Idle notifications being in isolate scope are part of the contract.
252 if (idle_notification_callback_) {
253 TRACE_EVENT0("flutter", "EmbedderIdleNotification");
254 idle_notification_callback_(deadline);
255 }
256 return true;
257 }
258
DispatchPlatformMessage(fml::RefPtr<PlatformMessage> message)259 bool RuntimeController::DispatchPlatformMessage(
260 fml::RefPtr<PlatformMessage> message) {
261 if (auto* window = GetWindowIfAvailable()) {
262 TRACE_EVENT1("flutter", "RuntimeController::DispatchPlatformMessage",
263 "mode", "basic");
264 window->DispatchPlatformMessage(std::move(message));
265 return true;
266 }
267 return false;
268 }
269
DispatchPointerDataPacket(const PointerDataPacket & packet)270 bool RuntimeController::DispatchPointerDataPacket(
271 const PointerDataPacket& packet) {
272 if (auto* window = GetWindowIfAvailable()) {
273 TRACE_EVENT1("flutter", "RuntimeController::DispatchPointerDataPacket",
274 "mode", "basic");
275 window->DispatchPointerDataPacket(packet);
276 return true;
277 }
278 return false;
279 }
280
DispatchSemanticsAction(int32_t id,SemanticsAction action,std::vector<uint8_t> args)281 bool RuntimeController::DispatchSemanticsAction(int32_t id,
282 SemanticsAction action,
283 std::vector<uint8_t> args) {
284 TRACE_EVENT1("flutter", "RuntimeController::DispatchSemanticsAction", "mode",
285 "basic");
286 if (auto* window = GetWindowIfAvailable()) {
287 window->DispatchSemanticsAction(id, action, std::move(args));
288 return true;
289 }
290 return false;
291 }
292
GetWindowIfAvailable()293 Window* RuntimeController::GetWindowIfAvailable() {
294 std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
295 return root_isolate ? root_isolate->window() : nullptr;
296 }
297
DefaultRouteName()298 std::string RuntimeController::DefaultRouteName() {
299 return client_.DefaultRouteName();
300 }
301
ScheduleFrame()302 void RuntimeController::ScheduleFrame() {
303 client_.ScheduleFrame();
304 }
305
Render(Scene * scene)306 void RuntimeController::Render(Scene* scene) {
307 client_.Render(scene->takeLayerTree());
308 }
309
UpdateSemantics(SemanticsUpdate * update)310 void RuntimeController::UpdateSemantics(SemanticsUpdate* update) {
311 if (window_data_.semantics_enabled) {
312 client_.UpdateSemantics(update->takeNodes(), update->takeActions());
313 }
314 }
315
HandlePlatformMessage(fml::RefPtr<PlatformMessage> message)316 void RuntimeController::HandlePlatformMessage(
317 fml::RefPtr<PlatformMessage> message) {
318 client_.HandlePlatformMessage(std::move(message));
319 }
320
GetFontCollection()321 FontCollection& RuntimeController::GetFontCollection() {
322 return client_.GetFontCollection();
323 }
324
UpdateIsolateDescription(const std::string isolate_name,int64_t isolate_port)325 void RuntimeController::UpdateIsolateDescription(const std::string isolate_name,
326 int64_t isolate_port) {
327 client_.UpdateIsolateDescription(isolate_name, isolate_port);
328 }
329
SetNeedsReportTimings(bool value)330 void RuntimeController::SetNeedsReportTimings(bool value) {
331 client_.SetNeedsReportTimings(value);
332 }
333
GetMainPort()334 Dart_Port RuntimeController::GetMainPort() {
335 std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
336 return root_isolate ? root_isolate->main_port() : ILLEGAL_PORT;
337 }
338
GetIsolateName()339 std::string RuntimeController::GetIsolateName() {
340 std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
341 return root_isolate ? root_isolate->debug_name() : "";
342 }
343
HasLivePorts()344 bool RuntimeController::HasLivePorts() {
345 std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
346 if (!root_isolate) {
347 return false;
348 }
349 tonic::DartState::Scope scope(root_isolate);
350 return Dart_HasLivePorts();
351 }
352
GetLastError()353 tonic::DartErrorHandleType RuntimeController::GetLastError() {
354 std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
355 return root_isolate ? root_isolate->GetLastError() : tonic::kNoError;
356 }
357
GetRootIsolate()358 std::weak_ptr<DartIsolate> RuntimeController::GetRootIsolate() {
359 return root_isolate_;
360 }
361
GetRootIsolateReturnCode()362 std::pair<bool, uint32_t> RuntimeController::GetRootIsolateReturnCode() {
363 return root_isolate_return_code_;
364 }
365
Locale(std::string language_code_,std::string country_code_,std::string script_code_,std::string variant_code_)366 RuntimeController::Locale::Locale(std::string language_code_,
367 std::string country_code_,
368 std::string script_code_,
369 std::string variant_code_)
370 : language_code(language_code_),
371 country_code(country_code_),
372 script_code(script_code_),
373 variant_code(variant_code_) {}
374
375 RuntimeController::Locale::~Locale() = default;
376
377 RuntimeController::WindowData::WindowData() = default;
378
379 RuntimeController::WindowData::WindowData(const WindowData& other) = default;
380
381 RuntimeController::WindowData::~WindowData() = default;
382
383 } // namespace flutter
384