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