|
14 | 14 | #include "flutter/shell/platform/tizen/flutter_platform_node_delegate_tizen.h"
|
15 | 15 | #include "flutter/shell/platform/tizen/tizen_renderer_egl.h"
|
16 | 16 | #endif
|
| 17 | +#include "flutter/shell/platform/tizen/flutter_tizen_engine_group.h" |
17 | 18 | #include "flutter/shell/platform/tizen/flutter_tizen_view.h"
|
18 | 19 | #include "flutter/shell/platform/tizen/logger.h"
|
19 | 20 | #include "flutter/shell/platform/tizen/system_utils.h"
|
@@ -100,6 +101,14 @@ void FlutterTizenEngine::CreateRenderer(
|
100 | 101 | #endif
|
101 | 102 | }
|
102 | 103 |
|
| 104 | +bool FlutterTizenEngine::RunOrSpawnEngine() { |
| 105 | + if (FlutterTizenEngineGroup::GetInstance().GetEngineCount() <= 1) { |
| 106 | + return RunEngine(); |
| 107 | + } else { |
| 108 | + return SpawnEngine(); |
| 109 | + } |
| 110 | +} |
| 111 | + |
103 | 112 | bool FlutterTizenEngine::RunEngine() {
|
104 | 113 | if (engine_ != nullptr) {
|
105 | 114 | FT_LOG(Error) << "The engine has already started.";
|
@@ -259,6 +268,132 @@ bool FlutterTizenEngine::RunEngine() {
|
259 | 268 | return true;
|
260 | 269 | }
|
261 | 270 |
|
| 271 | +bool FlutterTizenEngine::SpawnEngine() { |
| 272 | + if (engine_ != nullptr) { |
| 273 | + FT_LOG(Error) << "The engine has already started."; |
| 274 | + return false; |
| 275 | + } |
| 276 | + if (IsHeaded() && !renderer_->IsValid()) { |
| 277 | + FT_LOG(Error) << "The display was not valid."; |
| 278 | + return false; |
| 279 | + } |
| 280 | + |
| 281 | + if (!project_->HasValidPaths()) { |
| 282 | + FT_LOG(Error) << "Missing or unresolvable path to assets."; |
| 283 | + return false; |
| 284 | + } |
| 285 | + std::string assets_path_string = project_->assets_path().u8string(); |
| 286 | + std::string icu_path_string = project_->icu_path().u8string(); |
| 287 | + if (embedder_api_.RunsAOTCompiledDartCode()) { |
| 288 | + aot_data_ = project_->LoadAotData(embedder_api_); |
| 289 | + if (!aot_data_) { |
| 290 | + FT_LOG(Error) << "Unable to start engine without AOT data."; |
| 291 | + return false; |
| 292 | + } |
| 293 | + } |
| 294 | + |
| 295 | + // FlutterProjectArgs is expecting a full argv, so when processing it for |
| 296 | + // flags the first item is treated as the executable and ignored. Add a dummy |
| 297 | + // value so that all provided arguments are used. |
| 298 | + std::vector<std::string> engine_args = project_->engine_arguments(); |
| 299 | + std::vector<const char*> engine_argv = {"placeholder"}; |
| 300 | + std::transform( |
| 301 | + engine_args.begin(), engine_args.end(), std::back_inserter(engine_argv), |
| 302 | + [](const std::string& arg) -> const char* { return arg.c_str(); }); |
| 303 | + |
| 304 | + const std::vector<std::string>& entrypoint_args = |
| 305 | + project_->dart_entrypoint_arguments(); |
| 306 | + std::vector<const char*> entrypoint_argv; |
| 307 | + std::transform( |
| 308 | + entrypoint_args.begin(), entrypoint_args.end(), |
| 309 | + std::back_inserter(entrypoint_argv), |
| 310 | + [](const std::string& arg) -> const char* { return arg.c_str(); }); |
| 311 | + |
| 312 | + FlutterProjectArgs args = {}; |
| 313 | + args.struct_size = sizeof(FlutterProjectArgs); |
| 314 | + args.assets_path = assets_path_string.c_str(); |
| 315 | + args.icu_data_path = icu_path_string.c_str(); |
| 316 | + args.command_line_argc = static_cast<int>(engine_argv.size()); |
| 317 | + args.command_line_argv = |
| 318 | + engine_argv.size() > 0 ? engine_argv.data() : nullptr; |
| 319 | + args.dart_entrypoint_argc = static_cast<int>(entrypoint_argv.size()); |
| 320 | + args.dart_entrypoint_argv = |
| 321 | + entrypoint_argv.size() > 0 ? entrypoint_argv.data() : nullptr; |
| 322 | + args.platform_message_callback = |
| 323 | + [](const FlutterPlatformMessage* engine_message, void* user_data) { |
| 324 | + if (engine_message->struct_size != sizeof(FlutterPlatformMessage)) { |
| 325 | + FT_LOG(Error) << "Invalid message size received. Expected: " |
| 326 | + << sizeof(FlutterPlatformMessage) << ", but received " |
| 327 | + << engine_message->struct_size; |
| 328 | + return; |
| 329 | + } |
| 330 | + auto* engine = static_cast<FlutterTizenEngine*>(user_data); |
| 331 | + FlutterDesktopMessage message = |
| 332 | + engine->ConvertToDesktopMessage(*engine_message); |
| 333 | + engine->message_dispatcher_->HandleMessage(message); |
| 334 | + }; |
| 335 | + if (aot_data_) { |
| 336 | + args.aot_data = aot_data_.get(); |
| 337 | + } |
| 338 | + if (!project_->custom_dart_entrypoint().empty()) { |
| 339 | + args.custom_dart_entrypoint = project_->custom_dart_entrypoint().c_str(); |
| 340 | + } |
| 341 | +#ifndef WEARABLE_PROFILE |
| 342 | + args.update_semantics_callback2 = [](const FlutterSemanticsUpdate2* update, |
| 343 | + void* user_data) { |
| 344 | + auto* engine = static_cast<FlutterTizenEngine*>(user_data); |
| 345 | + engine->OnUpdateSemantics(update); |
| 346 | + }; |
| 347 | + |
| 348 | + if (IsHeaded() && dynamic_cast<TizenRendererEgl*>(renderer_.get())) { |
| 349 | + vsync_waiter_ = std::make_unique<TizenVsyncWaiter>(this); |
| 350 | + args.vsync_callback = [](void* user_data, intptr_t baton) -> void { |
| 351 | + auto* engine = static_cast<FlutterTizenEngine*>(user_data); |
| 352 | + engine->vsync_waiter_->AsyncWaitForVsync(baton); |
| 353 | + }; |
| 354 | + } |
| 355 | +#endif |
| 356 | + |
| 357 | + auto* spawner = FlutterTizenEngineGroup::GetInstance().GetEngineSpawner(); |
| 358 | + FlutterRendererConfig renderer_config = GetRendererConfig(); |
| 359 | + FlutterEngineResult result = |
| 360 | + embedder_api_.Spawn(FLUTTER_ENGINE_VERSION, &renderer_config, &args, this, |
| 361 | + spawner->engine_, &engine_); |
| 362 | + |
| 363 | + if (result != kSuccess || engine_ == nullptr) { |
| 364 | + FT_LOG(Error) << "Failed to start the Flutter engine with error: " |
| 365 | + << result; |
| 366 | + return false; |
| 367 | + } |
| 368 | + |
| 369 | + internal_plugin_registrar_ = |
| 370 | + std::make_unique<PluginRegistrar>(plugin_registrar_.get()); |
| 371 | + accessibility_channel_ = std::make_unique<AccessibilityChannel>( |
| 372 | + internal_plugin_registrar_->messenger()); |
| 373 | + app_control_channel_ = std::make_unique<AppControlChannel>( |
| 374 | + internal_plugin_registrar_->messenger()); |
| 375 | + lifecycle_channel_ = std::make_unique<LifecycleChannel>( |
| 376 | + internal_plugin_registrar_->messenger()); |
| 377 | + settings_channel_ = std::make_unique<SettingsChannel>( |
| 378 | + internal_plugin_registrar_->messenger()); |
| 379 | + |
| 380 | + if (IsHeaded()) { |
| 381 | + texture_registrar_ = std::make_unique<FlutterTizenTextureRegistrar>(this); |
| 382 | + key_event_channel_ = std::make_unique<KeyEventChannel>( |
| 383 | + internal_plugin_registrar_->messenger(), |
| 384 | + [this](const FlutterKeyEvent& event, FlutterKeyEventCallback callback, |
| 385 | + void* user_data) { SendKeyEvent(event, callback, user_data); }); |
| 386 | + navigation_channel_ = std::make_unique<NavigationChannel>( |
| 387 | + internal_plugin_registrar_->messenger()); |
| 388 | + } |
| 389 | + |
| 390 | + accessibility_settings_ = std::make_unique<AccessibilitySettings>(this); |
| 391 | + |
| 392 | + SetupLocales(); |
| 393 | + |
| 394 | + return true; |
| 395 | +} |
| 396 | + |
262 | 397 | bool FlutterTizenEngine::StopEngine() {
|
263 | 398 | if (engine_) {
|
264 | 399 | for (const auto& [callback, registrar] :
|
@@ -372,8 +507,8 @@ void FlutterTizenEngine::SetupLocales() {
|
372 | 507 | std::vector<const FlutterLocale*> flutter_locale_list;
|
373 | 508 | flutter_locale_list.reserve(flutter_locales.size());
|
374 | 509 | std::transform(flutter_locales.begin(), flutter_locales.end(),
|
375 |
| - std::back_inserter(flutter_locale_list), |
376 |
| - [](const auto& arg) -> const auto* { return &arg; }); |
| 510 | + std::back_inserter(flutter_locale_list), |
| 511 | + [](const auto& arg) -> const auto* { return &arg; }); |
377 | 512 |
|
378 | 513 | embedder_api_.UpdateLocales(engine_, flutter_locale_list.data(),
|
379 | 514 | flutter_locale_list.size());
|
|
0 commit comments