• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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