Skip to content

Commit 757f930

Browse files
committed
Implement SpawnEngine of FlutterTizenEngine
Signed-off-by: swan.seo <[email protected]>
1 parent 7ac0c65 commit 757f930

11 files changed

+287
-37
lines changed

flutter/shell/platform/embedder/embedder.h

+34
Original file line numberDiff line numberDiff line change
@@ -2169,6 +2169,32 @@ FlutterEngineResult FlutterEngineRun(size_t version,
21692169
engine_out);
21702170

21712171
//------------------------------------------------------------------------------
2172+
/// @brief Spawn a Flutter engine instance. It is implemented by modifying
2173+
/// `FlutterInitiaize`. Unlike `FlutterEngineInitialize`,
2174+
/// `FlutterEngineSpawn` uses the shell of given spawner engine to
2175+
/// spawn a engine instance.
2176+
///
2177+
/// @param[in] version The Flutter embedder API version. Must be
2178+
/// FLUTTER_ENGINE_VERSION.
2179+
/// @param[in] config The renderer configuration.
2180+
/// @param[in] args The Flutter project arguments.
2181+
/// @param user_data A user data baton passed back to embedders in
2182+
/// callbacks.
2183+
/// @param[in] spawner The spawner engine handle.
2184+
/// @param[out] engine_out The engine handle on successful engine creation.
2185+
///
2186+
/// @return The result of the call to run the Flutter engine.
2187+
///
2188+
FLUTTER_EXPORT
2189+
FlutterEngineResult FlutterEngineSpawn(size_t version,
2190+
const FlutterRendererConfig* config,
2191+
const FlutterProjectArgs* args,
2192+
void* user_data,
2193+
FLUTTER_API_SYMBOL(FlutterEngine)
2194+
spawner,
2195+
FLUTTER_API_SYMBOL(FlutterEngine) *
2196+
engine_out);
2197+
//------------------------------------------------------------------------------
21722198
/// @brief Shuts down a Flutter engine instance. The engine handle is no
21732199
/// longer valid for any calls in the embedder API after this point.
21742200
/// Making additional calls with this handle is undefined behavior.
@@ -2805,6 +2831,13 @@ typedef FlutterEngineResult (*FlutterEngineRunFnPtr)(
28052831
const FlutterProjectArgs* args,
28062832
void* user_data,
28072833
FLUTTER_API_SYMBOL(FlutterEngine) * engine_out);
2834+
typedef FlutterEngineResult (*FlutterEngineSpawnFnPtr)(
2835+
size_t version,
2836+
const FlutterRendererConfig* config,
2837+
const FlutterProjectArgs* args,
2838+
void* user_data,
2839+
FLUTTER_API_SYMBOL(FlutterEngine) engine_spawner,
2840+
FLUTTER_API_SYMBOL(FlutterEngine) * engine_out);
28082841
typedef FlutterEngineResult (*FlutterEngineShutdownFnPtr)(
28092842
FLUTTER_API_SYMBOL(FlutterEngine) engine);
28102843
typedef FlutterEngineResult (*FlutterEngineInitializeFnPtr)(
@@ -2922,6 +2955,7 @@ typedef struct {
29222955
FlutterEngineCreateAOTDataFnPtr CreateAOTData;
29232956
FlutterEngineCollectAOTDataFnPtr CollectAOTData;
29242957
FlutterEngineRunFnPtr Run;
2958+
FlutterEngineSpawnFnPtr Spawn;
29252959
FlutterEngineShutdownFnPtr Shutdown;
29262960
FlutterEngineInitializeFnPtr Initialize;
29272961
FlutterEngineDeinitializeFnPtr Deinitialize;

flutter/shell/platform/tizen/BUILD.gn

+1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ template("embedder") {
9999
"flutter_tizen.cc",
100100
"flutter_tizen_elementary.cc",
101101
"flutter_tizen_engine.cc",
102+
"flutter_tizen_engine_group.cc",
102103
"flutter_tizen_texture_registrar.cc",
103104
"flutter_tizen_view.cc",
104105
"logger.cc",

flutter/shell/platform/tizen/flutter_tizen.cc

+25-19
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "flutter/shell/platform/embedder/embedder.h"
1212
#include "flutter/shell/platform/tizen/flutter_project_bundle.h"
1313
#include "flutter/shell/platform/tizen/flutter_tizen_engine.h"
14+
#include "flutter/shell/platform/tizen/flutter_tizen_engine_group.h"
1415
#include "flutter/shell/platform/tizen/flutter_tizen_view.h"
1516
#include "flutter/shell/platform/tizen/logger.h"
1617
#include "flutter/shell/platform/tizen/public/flutter_platform_view.h"
@@ -63,29 +64,35 @@ FlutterDesktopViewRef HandleForView(flutter::FlutterTizenView* view) {
6364
FlutterDesktopEngineRef FlutterDesktopEngineCreate(
6465
const FlutterDesktopEngineProperties& engine_properties) {
6566
flutter::FlutterProjectBundle project(engine_properties);
66-
if (project.HasArgument("--verbose-logging")) {
67-
flutter::Logger::SetLoggingLevel(flutter::kLogLevelDebug);
68-
}
69-
std::string logging_port;
70-
if (project.GetArgumentValue("--tizen-logging-port", &logging_port)) {
71-
flutter::Logger::SetLoggingPort(std::stoi(logging_port));
67+
flutter::FlutterTizenEngineGroup& engine_group =
68+
flutter::FlutterTizenEngineGroup::GetInstance();
69+
if (!engine_group.GetEngineCount()) {
70+
if (project.HasArgument("--verbose-logging")) {
71+
flutter::Logger::SetLoggingLevel(flutter::kLogLevelDebug);
72+
}
73+
std::string logging_port;
74+
if (project.GetArgumentValue("--tizen-logging-port", &logging_port)) {
75+
flutter::Logger::SetLoggingPort(std::stoi(logging_port));
76+
}
77+
flutter::Logger::Start();
7278
}
73-
flutter::Logger::Start();
74-
75-
auto engine = std::make_unique<flutter::FlutterTizenEngine>(project);
76-
return HandleForEngine(engine.release());
79+
auto* engine = engine_group.MakeEngineWithProject(project);
80+
return HandleForEngine(engine);
7781
}
7882

7983
bool FlutterDesktopEngineRun(const FlutterDesktopEngineRef engine) {
80-
return EngineFromHandle(engine)->RunEngine();
84+
return EngineFromHandle(engine)->RunOrSpawnEngine();
8185
}
8286

8387
void FlutterDesktopEngineShutdown(FlutterDesktopEngineRef engine_ref) {
84-
flutter::Logger::Stop();
85-
8688
flutter::FlutterTizenEngine* engine = EngineFromHandle(engine_ref);
87-
engine->StopEngine();
88-
delete engine;
89+
flutter::FlutterTizenEngineGroup& engine_group =
90+
flutter::FlutterTizenEngineGroup::GetInstance();
91+
engine_group.StopEngine(engine->id());
92+
93+
if (!engine_group.GetEngineCount()) {
94+
flutter::Logger::Stop();
95+
}
8996
}
9097

9198
FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetView(
@@ -220,12 +227,11 @@ FlutterDesktopViewRef FlutterDesktopViewCreateFromNewWindow(
220227

221228
auto view = std::make_unique<flutter::FlutterTizenView>(std::move(window));
222229

223-
// Take ownership of the engine, starting it if necessary.
224-
view->SetEngine(
225-
std::unique_ptr<flutter::FlutterTizenEngine>(EngineFromHandle(engine)));
230+
// Starting it if necessary.
231+
view->SetEngine(EngineFromHandle(engine));
226232
view->CreateRenderSurface(window_properties.renderer_type);
227233
if (!view->engine()->IsRunning()) {
228-
if (!view->engine()->RunEngine()) {
234+
if (!view->engine()->RunOrSpawnEngine()) {
229235
return nullptr;
230236
}
231237
}

flutter/shell/platform/tizen/flutter_tizen_elementary.cc

+3-4
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,11 @@ FlutterDesktopViewRef FlutterDesktopViewCreateFromElmParent(
3333
auto view =
3434
std::make_unique<flutter::FlutterTizenView>(std::move(tizen_view));
3535

36-
// Take ownership of the engine, starting it if necessary.
37-
view->SetEngine(
38-
std::unique_ptr<flutter::FlutterTizenEngine>(EngineFromHandle(engine)));
36+
// Starting it if necessary.
37+
view->SetEngine(EngineFromHandle(engine));
3938
view->CreateRenderSurface(FlutterDesktopRendererType::kEvasGL);
4039
if (!view->engine()->IsRunning()) {
41-
if (!view->engine()->RunEngine()) {
40+
if (!view->engine()->RunOrSpawnEngine()) {
4241
return nullptr;
4342
}
4443
}

flutter/shell/platform/tizen/flutter_tizen_engine.cc

+137-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "flutter/shell/platform/tizen/flutter_platform_node_delegate_tizen.h"
1515
#include "flutter/shell/platform/tizen/tizen_renderer_egl.h"
1616
#endif
17+
#include "flutter/shell/platform/tizen/flutter_tizen_engine_group.h"
1718
#include "flutter/shell/platform/tizen/flutter_tizen_view.h"
1819
#include "flutter/shell/platform/tizen/logger.h"
1920
#include "flutter/shell/platform/tizen/system_utils.h"
@@ -100,6 +101,14 @@ void FlutterTizenEngine::CreateRenderer(
100101
#endif
101102
}
102103

104+
bool FlutterTizenEngine::RunOrSpawnEngine() {
105+
if (FlutterTizenEngineGroup::GetInstance().GetEngineCount() <= 1) {
106+
return RunEngine();
107+
} else {
108+
return SpawnEngine();
109+
}
110+
}
111+
103112
bool FlutterTizenEngine::RunEngine() {
104113
if (engine_ != nullptr) {
105114
FT_LOG(Error) << "The engine has already started.";
@@ -259,6 +268,132 @@ bool FlutterTizenEngine::RunEngine() {
259268
return true;
260269
}
261270

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+
262397
bool FlutterTizenEngine::StopEngine() {
263398
if (engine_) {
264399
for (const auto& [callback, registrar] :
@@ -372,8 +507,8 @@ void FlutterTizenEngine::SetupLocales() {
372507
std::vector<const FlutterLocale*> flutter_locale_list;
373508
flutter_locale_list.reserve(flutter_locales.size());
374509
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; });
377512

378513
embedder_api_.UpdateLocales(engine_, flutter_locale_list.data(),
379514
flutter_locale_list.size());

flutter/shell/platform/tizen/flutter_tizen_engine.h

+10
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ class FlutterTizenEngine {
6868
// Returns false if the engine couldn't be started.
6969
bool RunEngine();
7070

71+
bool RunOrSpawnEngine();
72+
73+
bool SpawnEngine();
74+
7175
// Returns true if the engine is currently running.
7276
bool IsRunning() { return engine_ != nullptr; }
7377

@@ -81,6 +85,10 @@ class FlutterTizenEngine {
8185
// headless engines.
8286
FlutterTizenView* view() { return view_; }
8387

88+
void SetId(uint32_t id) { id_ = id; }
89+
90+
uint32_t id() { return id_; }
91+
8492
FlutterDesktopMessengerRef messenger() { return messenger_.get(); }
8593

8694
IncomingMessageDispatcher* message_dispatcher() {
@@ -275,6 +283,8 @@ class FlutterTizenEngine {
275283
// The vsync waiter for the embedder.
276284
std::unique_ptr<TizenVsyncWaiter> vsync_waiter_;
277285
#endif
286+
287+
uint32_t id_;
278288
};
279289

280290
} // namespace flutter
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#include "flutter/shell/platform/tizen/flutter_tizen_engine_group.h"
2+
3+
namespace flutter {
4+
5+
FlutterTizenEngine* FlutterTizenEngineGroup::MakeEngineWithProject(
6+
const FlutterProjectBundle& project) {
7+
std::unique_ptr<FlutterTizenEngine> engine =
8+
std::make_unique<flutter::FlutterTizenEngine>(project);
9+
10+
static uint32_t engine_id = 0;
11+
engine->SetId(engine_id++);
12+
13+
engines_.push_back(std::move(engine));
14+
return engines_.back().get();
15+
}
16+
17+
FlutterTizenEngine* FlutterTizenEngineGroup::GetEngineSpawner() {
18+
return engines_[0].get();
19+
}
20+
21+
int FlutterTizenEngineGroup::GetEngineCount() {
22+
return engines_.size();
23+
}
24+
25+
void FlutterTizenEngineGroup::StopEngine(uint32_t id) {
26+
for (auto it = engines_.begin(); it != engines_.end(); ++it) {
27+
if (id == it->get()->id()) {
28+
engines_.erase(it);
29+
return;
30+
}
31+
}
32+
}
33+
34+
} // namespace flutter

0 commit comments

Comments
 (0)