Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement FlutterTizenEngine spawn #20

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
135 changes: 135 additions & 0 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
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