Skip to content

Commit

Permalink
Implement SpawnEngine of FlutterTizenEngine
Browse files Browse the repository at this point in the history
Signed-off-by: swan.seo <[email protected]>
  • Loading branch information
Swanseo0 committed Jun 14, 2023
1 parent 7ac0c65 commit 9d7ed65
Show file tree
Hide file tree
Showing 11 changed files with 289 additions and 38 deletions.
34 changes: 34 additions & 0 deletions flutter/shell/platform/embedder/embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -2169,6 +2169,32 @@ FlutterEngineResult FlutterEngineRun(size_t version,
engine_out);

//------------------------------------------------------------------------------
/// @brief Spawn a Flutter engine instance. It is implemented by modifying
/// `FlutterInitiaize`. Unlike `FlutterEngineInitialize`,
/// `FlutterEngineSpawn` uses the shell of given spawner engine to
/// spawn a engine instance.
///
/// @param[in] version The Flutter embedder API version. Must be
/// FLUTTER_ENGINE_VERSION.
/// @param[in] config The renderer configuration.
/// @param[in] args The Flutter project arguments.
/// @param user_data A user data baton passed back to embedders in
/// callbacks.
/// @param[in] spawner The spawner engine handle.
/// @param[out] engine_out The engine handle on successful engine creation.
///
/// @return The result of the call to run the Flutter engine.
///
FLUTTER_EXPORT
FlutterEngineResult FlutterEngineSpawn(size_t version,
const FlutterRendererConfig* config,
const FlutterProjectArgs* args,
void* user_data,
FLUTTER_API_SYMBOL(FlutterEngine)
spawner,
FLUTTER_API_SYMBOL(FlutterEngine) *
engine_out);
//------------------------------------------------------------------------------
/// @brief Shuts down a Flutter engine instance. The engine handle is no
/// longer valid for any calls in the embedder API after this point.
/// Making additional calls with this handle is undefined behavior.
Expand Down Expand Up @@ -2805,6 +2831,13 @@ typedef FlutterEngineResult (*FlutterEngineRunFnPtr)(
const FlutterProjectArgs* args,
void* user_data,
FLUTTER_API_SYMBOL(FlutterEngine) * engine_out);
typedef FlutterEngineResult (*FlutterEngineSpawnFnPtr)(
size_t version,
const FlutterRendererConfig* config,
const FlutterProjectArgs* args,
void* user_data,
FLUTTER_API_SYMBOL(FlutterEngine) engine_spawner,
FLUTTER_API_SYMBOL(FlutterEngine) * engine_out);
typedef FlutterEngineResult (*FlutterEngineShutdownFnPtr)(
FLUTTER_API_SYMBOL(FlutterEngine) engine);
typedef FlutterEngineResult (*FlutterEngineInitializeFnPtr)(
Expand Down Expand Up @@ -2922,6 +2955,7 @@ typedef struct {
FlutterEngineCreateAOTDataFnPtr CreateAOTData;
FlutterEngineCollectAOTDataFnPtr CollectAOTData;
FlutterEngineRunFnPtr Run;
FlutterEngineSpawnFnPtr Spawn;
FlutterEngineShutdownFnPtr Shutdown;
FlutterEngineInitializeFnPtr Initialize;
FlutterEngineDeinitializeFnPtr Deinitialize;
Expand Down
1 change: 1 addition & 0 deletions flutter/shell/platform/tizen/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ template("embedder") {
"flutter_tizen.cc",
"flutter_tizen_elementary.cc",
"flutter_tizen_engine.cc",
"flutter_tizen_engine_group.cc",
"flutter_tizen_texture_registrar.cc",
"flutter_tizen_view.cc",
"logger.cc",
Expand Down
44 changes: 25 additions & 19 deletions flutter/shell/platform/tizen/flutter_tizen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/tizen/flutter_project_bundle.h"
#include "flutter/shell/platform/tizen/flutter_tizen_engine.h"
#include "flutter/shell/platform/tizen/flutter_tizen_engine_group.h"
#include "flutter/shell/platform/tizen/flutter_tizen_view.h"
#include "flutter/shell/platform/tizen/logger.h"
#include "flutter/shell/platform/tizen/public/flutter_platform_view.h"
Expand Down Expand Up @@ -63,29 +64,35 @@ FlutterDesktopViewRef HandleForView(flutter::FlutterTizenView* view) {
FlutterDesktopEngineRef FlutterDesktopEngineCreate(
const FlutterDesktopEngineProperties& engine_properties) {
flutter::FlutterProjectBundle project(engine_properties);
if (project.HasArgument("--verbose-logging")) {
flutter::Logger::SetLoggingLevel(flutter::kLogLevelDebug);
}
std::string logging_port;
if (project.GetArgumentValue("--tizen-logging-port", &logging_port)) {
flutter::Logger::SetLoggingPort(std::stoi(logging_port));
flutter::FlutterTizenEngineGroup& engine_group =
flutter::FlutterTizenEngineGroup::GetInstance();
if (!engine_group.GetEngineCount()) {
if (project.HasArgument("--verbose-logging")) {
flutter::Logger::SetLoggingLevel(flutter::kLogLevelDebug);
}
std::string logging_port;
if (project.GetArgumentValue("--tizen-logging-port", &logging_port)) {
flutter::Logger::SetLoggingPort(std::stoi(logging_port));
}
flutter::Logger::Start();
}
flutter::Logger::Start();

auto engine = std::make_unique<flutter::FlutterTizenEngine>(project);
return HandleForEngine(engine.release());
auto* engine = engine_group.MakeEngineWithProject(project);
return HandleForEngine(engine);
}

bool FlutterDesktopEngineRun(const FlutterDesktopEngineRef engine) {
return EngineFromHandle(engine)->RunEngine();
return EngineFromHandle(engine)->RunOrSpawnEngine();
}

void FlutterDesktopEngineShutdown(FlutterDesktopEngineRef engine_ref) {
flutter::Logger::Stop();

flutter::FlutterTizenEngine* engine = EngineFromHandle(engine_ref);
engine->StopEngine();
delete engine;
flutter::FlutterTizenEngineGroup& engine_group =
flutter::FlutterTizenEngineGroup::GetInstance();
engine_group.StopEngine(engine->id());

if (!engine_group.GetEngineCount()) {
flutter::Logger::Stop();
}
}

FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetView(
Expand Down Expand Up @@ -220,12 +227,11 @@ FlutterDesktopViewRef FlutterDesktopViewCreateFromNewWindow(

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

// Take ownership of the engine, starting it if necessary.
view->SetEngine(
std::unique_ptr<flutter::FlutterTizenEngine>(EngineFromHandle(engine)));
// Starting it if necessary.
view->SetEngine(EngineFromHandle(engine));
view->CreateRenderSurface(window_properties.renderer_type);
if (!view->engine()->IsRunning()) {
if (!view->engine()->RunEngine()) {
if (!view->engine()->RunOrSpawnEngine()) {
return nullptr;
}
}
Expand Down
7 changes: 3 additions & 4 deletions flutter/shell/platform/tizen/flutter_tizen_elementary.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,11 @@ FlutterDesktopViewRef FlutterDesktopViewCreateFromElmParent(
auto view =
std::make_unique<flutter::FlutterTizenView>(std::move(tizen_view));

// Take ownership of the engine, starting it if necessary.
view->SetEngine(
std::unique_ptr<flutter::FlutterTizenEngine>(EngineFromHandle(engine)));
// Starting it if necessary.
view->SetEngine(EngineFromHandle(engine));
view->CreateRenderSurface(FlutterDesktopRendererType::kEvasGL);
if (!view->engine()->IsRunning()) {
if (!view->engine()->RunEngine()) {
if (!view->engine()->RunOrSpawnEngine()) {
return nullptr;
}
}
Expand Down
142 changes: 139 additions & 3 deletions flutter/shell/platform/tizen/flutter_tizen_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "flutter/shell/platform/tizen/flutter_platform_node_delegate_tizen.h"
#include "flutter/shell/platform/tizen/tizen_renderer_egl.h"
#endif
#include "flutter/shell/platform/tizen/flutter_tizen_engine_group.h"
#include "flutter/shell/platform/tizen/flutter_tizen_view.h"
#include "flutter/shell/platform/tizen/logger.h"
#include "flutter/shell/platform/tizen/system_utils.h"
Expand Down Expand Up @@ -100,6 +101,14 @@ void FlutterTizenEngine::CreateRenderer(
#endif
}

bool FlutterTizenEngine::RunOrSpawnEngine() {
if (FlutterTizenEngineGroup::GetInstance().GetEngineCount() <= 1) {
return RunEngine();
} else {
return SpawnEngine();
}
}

bool FlutterTizenEngine::RunEngine() {
if (engine_ != nullptr) {
FT_LOG(Error) << "The engine has already started.";
Expand Down Expand Up @@ -259,6 +268,132 @@ bool FlutterTizenEngine::RunEngine() {
return true;
}

bool FlutterTizenEngine::SpawnEngine() {
if (engine_ != nullptr) {
FT_LOG(Error) << "The engine has already started.";
return false;
}
if (IsHeaded() && !renderer_->IsValid()) {
FT_LOG(Error) << "The display was not valid.";
return false;
}

if (!project_->HasValidPaths()) {
FT_LOG(Error) << "Missing or unresolvable path to assets.";
return false;
}
std::string assets_path_string = project_->assets_path().u8string();
std::string icu_path_string = project_->icu_path().u8string();
if (embedder_api_.RunsAOTCompiledDartCode()) {
aot_data_ = project_->LoadAotData(embedder_api_);
if (!aot_data_) {
FT_LOG(Error) << "Unable to start engine without AOT data.";
return false;
}
}

// FlutterProjectArgs is expecting a full argv, so when processing it for
// flags the first item is treated as the executable and ignored. Add a dummy
// value so that all provided arguments are used.
std::vector<std::string> engine_args = project_->engine_arguments();
std::vector<const char*> engine_argv = {"placeholder"};
std::transform(
engine_args.begin(), engine_args.end(), std::back_inserter(engine_argv),
[](const std::string& arg) -> const char* { return arg.c_str(); });

const std::vector<std::string>& entrypoint_args =
project_->dart_entrypoint_arguments();
std::vector<const char*> entrypoint_argv;
std::transform(
entrypoint_args.begin(), entrypoint_args.end(),
std::back_inserter(entrypoint_argv),
[](const std::string& arg) -> const char* { return arg.c_str(); });

FlutterProjectArgs args = {};
args.struct_size = sizeof(FlutterProjectArgs);
args.assets_path = assets_path_string.c_str();
args.icu_data_path = icu_path_string.c_str();
args.command_line_argc = static_cast<int>(engine_argv.size());
args.command_line_argv =
engine_argv.size() > 0 ? engine_argv.data() : nullptr;
args.dart_entrypoint_argc = static_cast<int>(entrypoint_argv.size());
args.dart_entrypoint_argv =
entrypoint_argv.size() > 0 ? entrypoint_argv.data() : nullptr;
args.platform_message_callback =
[](const FlutterPlatformMessage* engine_message, void* user_data) {
if (engine_message->struct_size != sizeof(FlutterPlatformMessage)) {
FT_LOG(Error) << "Invalid message size received. Expected: "
<< sizeof(FlutterPlatformMessage) << ", but received "
<< engine_message->struct_size;
return;
}
auto* engine = static_cast<FlutterTizenEngine*>(user_data);
FlutterDesktopMessage message =
engine->ConvertToDesktopMessage(*engine_message);
engine->message_dispatcher_->HandleMessage(message);
};
if (aot_data_) {
args.aot_data = aot_data_.get();
}
if (!project_->custom_dart_entrypoint().empty()) {
args.custom_dart_entrypoint = project_->custom_dart_entrypoint().c_str();
}
#ifndef WEARABLE_PROFILE
args.update_semantics_callback2 = [](const FlutterSemanticsUpdate2* update,
void* user_data) {
auto* engine = static_cast<FlutterTizenEngine*>(user_data);
engine->OnUpdateSemantics(update);
};

if (IsHeaded() && dynamic_cast<TizenRendererEgl*>(renderer_.get())) {
vsync_waiter_ = std::make_unique<TizenVsyncWaiter>(this);
args.vsync_callback = [](void* user_data, intptr_t baton) -> void {
auto* engine = static_cast<FlutterTizenEngine*>(user_data);
engine->vsync_waiter_->AsyncWaitForVsync(baton);
};
}
#endif

auto* spawner = FlutterTizenEngineGroup::GetInstance().GetEngineSpawner();
FlutterRendererConfig renderer_config = GetRendererConfig();
FlutterEngineResult result =
embedder_api_.Spawn(FLUTTER_ENGINE_VERSION, &renderer_config, &args, this,
spawner->engine_, &engine_);

if (result != kSuccess || engine_ == nullptr) {
FT_LOG(Error) << "Failed to start the Flutter engine with error: "
<< result;
return false;
}

internal_plugin_registrar_ =
std::make_unique<PluginRegistrar>(plugin_registrar_.get());
accessibility_channel_ = std::make_unique<AccessibilityChannel>(
internal_plugin_registrar_->messenger());
app_control_channel_ = std::make_unique<AppControlChannel>(
internal_plugin_registrar_->messenger());
lifecycle_channel_ = std::make_unique<LifecycleChannel>(
internal_plugin_registrar_->messenger());
settings_channel_ = std::make_unique<SettingsChannel>(
internal_plugin_registrar_->messenger());

if (IsHeaded()) {
texture_registrar_ = std::make_unique<FlutterTizenTextureRegistrar>(this);
key_event_channel_ = std::make_unique<KeyEventChannel>(
internal_plugin_registrar_->messenger(),
[this](const FlutterKeyEvent& event, FlutterKeyEventCallback callback,
void* user_data) { SendKeyEvent(event, callback, user_data); });
navigation_channel_ = std::make_unique<NavigationChannel>(
internal_plugin_registrar_->messenger());
}

accessibility_settings_ = std::make_unique<AccessibilitySettings>(this);

SetupLocales();

return true;
}

bool FlutterTizenEngine::StopEngine() {
if (engine_) {
for (const auto& [callback, registrar] :
Expand Down Expand Up @@ -371,9 +506,10 @@ void FlutterTizenEngine::SetupLocales() {
// Convert the locale list to the locale pointer list that must be provided.
std::vector<const FlutterLocale*> flutter_locale_list;
flutter_locale_list.reserve(flutter_locales.size());
std::transform(flutter_locales.begin(), flutter_locales.end(),
std::back_inserter(flutter_locale_list),
[](const auto& arg) -> const auto* { return &arg; });
std::transform(
flutter_locales.begin(), flutter_locales.end(),
std::back_inserter(flutter_locale_list),
[](const auto& arg) -> const auto* { return &arg; });

embedder_api_.UpdateLocales(engine_, flutter_locale_list.data(),
flutter_locale_list.size());
Expand Down
10 changes: 10 additions & 0 deletions flutter/shell/platform/tizen/flutter_tizen_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ class FlutterTizenEngine {
// Returns false if the engine couldn't be started.
bool RunEngine();

bool RunOrSpawnEngine();

bool SpawnEngine();

// Returns true if the engine is currently running.
bool IsRunning() { return engine_ != nullptr; }

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

void SetId(uint32_t id) { id_ = id; }

uint32_t id() { return id_; }

FlutterDesktopMessengerRef messenger() { return messenger_.get(); }

IncomingMessageDispatcher* message_dispatcher() {
Expand Down Expand Up @@ -275,6 +283,8 @@ class FlutterTizenEngine {
// The vsync waiter for the embedder.
std::unique_ptr<TizenVsyncWaiter> vsync_waiter_;
#endif

uint32_t id_;
};

} // namespace flutter
Expand Down
34 changes: 34 additions & 0 deletions flutter/shell/platform/tizen/flutter_tizen_engine_group.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "flutter/shell/platform/tizen/flutter_tizen_engine_group.h"

namespace flutter {

FlutterTizenEngine* FlutterTizenEngineGroup::MakeEngineWithProject(
const FlutterProjectBundle& project) {
std::unique_ptr<FlutterTizenEngine> engine =
std::make_unique<flutter::FlutterTizenEngine>(project);

static uint32_t engine_id = 0;
engine->SetId(engine_id++);

engines_.push_back(std::move(engine));
return engines_.back().get();
}

FlutterTizenEngine* FlutterTizenEngineGroup::GetEngineSpawner() {
return engines_[0].get();
}

int FlutterTizenEngineGroup::GetEngineCount() {
return engines_.size();
}

void FlutterTizenEngineGroup::StopEngine(uint32_t id) {
for (auto it = engines_.begin(); it != engines_.end(); ++it) {
if (id == it->get()->id()) {
engines_.erase(it);
return;
}
}
}

} // namespace flutter
Loading

0 comments on commit 9d7ed65

Please sign in to comment.