Skip to content

Commit

Permalink
Refactor using FlutterProjectBundle
Browse files Browse the repository at this point in the history
  • Loading branch information
swift-kim committed Jul 2, 2021
1 parent 044ba9f commit e27569b
Show file tree
Hide file tree
Showing 6 changed files with 199 additions and 68 deletions.
1 change: 1 addition & 0 deletions shell/platform/tizen/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ template("embedder_for_profile") {
"channels/text_input_channel.cc",
"external_texture_pixel_gl.cc",
"external_texture_surface_gl.cc",
"flutter_project_bundle.cc",
"flutter_tizen.cc",
"flutter_tizen_engine.cc",
"flutter_tizen_texture_registrar.cc",
Expand Down
78 changes: 78 additions & 0 deletions shell/platform/tizen/flutter_project_bundle.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright 2021 Samsung Electronics Co., Ltd. All rights reserved.
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter_project_bundle.h"

#include <filesystem>

#include "flutter/shell/platform/common/path_utils.h"
#include "flutter/shell/platform/tizen/tizen_log.h"

namespace flutter {

FlutterProjectBundle::FlutterProjectBundle(
const FlutterDesktopEngineProperties& properties)
: assets_path_(properties.assets_path),
icu_path_(properties.icu_data_path) {
if (properties.aot_library_path != nullptr) {
aot_library_path_ = std::filesystem::path(properties.aot_library_path);
}

// Resolve any relative paths.
if (assets_path_.is_relative() || icu_path_.is_relative() ||
(!aot_library_path_.empty() && aot_library_path_.is_relative())) {
std::filesystem::path executable_location = GetExecutableDirectory();
if (executable_location.empty()) {
FT_LOGE("Unable to find executable location to resolve resource paths.");
assets_path_ = std::filesystem::path();
icu_path_ = std::filesystem::path();
} else {
assets_path_ = std::filesystem::path(executable_location) / assets_path_;
icu_path_ = std::filesystem::path(executable_location) / icu_path_;
if (!aot_library_path_.empty()) {
aot_library_path_ =
std::filesystem::path(executable_location) / aot_library_path_;
}
}
}

switches_.insert(switches_.end(), properties.switches,
properties.switches + properties.switches_count);
}

bool FlutterProjectBundle::HasValidPaths() {
return !assets_path_.empty() && !icu_path_.empty();
}

// Attempts to load AOT data from the given path, which must be absolute and
// non-empty. Logs and returns nullptr on failure.
UniqueAotDataPtr FlutterProjectBundle::LoadAotData(
const FlutterEngineProcTable& engine_procs) {
if (aot_library_path_.empty()) {
FT_LOGE(
"Attempted to load AOT data, but no aot_library_path was provided.");
return UniqueAotDataPtr(nullptr, nullptr);
}
if (!std::filesystem::exists(aot_library_path_)) {
FT_LOGE("Can't load AOT data from %s; no such file.",
aot_library_path_.u8string().c_str());
return UniqueAotDataPtr(nullptr, nullptr);
}
std::string path_string = aot_library_path_.u8string();
FlutterEngineAOTDataSource source = {};
source.type = kFlutterEngineAOTDataSourceTypeElfPath;
source.elf_path = path_string.c_str();
FlutterEngineAOTData data = nullptr;
auto result = engine_procs.CreateAOTData(&source, &data);
if (result != kSuccess) {
FT_LOGE("Failed to load AOT data from: %s", path_string.c_str());
return UniqueAotDataPtr(nullptr, nullptr);
}
return UniqueAotDataPtr(data, engine_procs.CollectAOTData);
}

FlutterProjectBundle::~FlutterProjectBundle() {}

} // namespace flutter
62 changes: 62 additions & 0 deletions shell/platform/tizen/flutter_project_bundle.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2021 Samsung Electronics Co., Ltd. All rights reserved.
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef EMBEDDER_FLUTTER_PROJECT_BUNDLE_H_
#define EMBEDDER_FLUTTER_PROJECT_BUNDLE_H_

#include <filesystem>
#include <string>
#include <vector>

#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/tizen/public/flutter_tizen.h"

namespace flutter {

using UniqueAotDataPtr =
std::unique_ptr<_FlutterEngineAOTData, FlutterEngineCollectAOTDataFnPtr>;

// The data associated with a Flutter project needed to run it in an engine.
class FlutterProjectBundle {
public:
// Creates a new project bundle from the given properties.
//
// Treats any relative paths as relative to the directory of this executable.
explicit FlutterProjectBundle(
const FlutterDesktopEngineProperties& properties);

~FlutterProjectBundle();

// Whether or not the bundle is valid. This does not check that the paths
// exist, or contain valid data, just that paths were able to be constructed.
bool HasValidPaths();

// Returns the path to the assets directory.
const std::filesystem::path& assets_path() { return assets_path_; }

// Returns the path to the ICU data file.
const std::filesystem::path& icu_path() { return icu_path_; }

// Returns any switches that should be passed to the engine.
const std::vector<std::string> switches() { return switches_; }

// Attempts to load AOT data for this bundle. The returned data must be
// retained until any engine instance it is passed to has been shut down.
//
// Logs and returns nullptr on failure.
UniqueAotDataPtr LoadAotData(const FlutterEngineProcTable& engine_procs);

private:
std::filesystem::path assets_path_;
std::filesystem::path icu_path_;
std::vector<std::string> switches_;

// Path to the AOT library file, if any.
std::filesystem::path aot_library_path_;
};

} // namespace flutter

#endif // EMBEDDER_FLUTTER_PROJECT_BUNDLE_H_
6 changes: 4 additions & 2 deletions shell/platform/tizen/flutter_tizen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "flutter/shell/platform/common/client_wrapper/include/flutter/plugin_registrar.h"
#include "flutter/shell/platform/common/client_wrapper/include/flutter/standard_message_codec.h"
#include "flutter/shell/platform/common/incoming_message_dispatcher.h"
#include "flutter/shell/platform/tizen/flutter_project_bundle.h"
#include "flutter/shell/platform/tizen/flutter_tizen_engine.h"
#include "flutter/shell/platform/tizen/public/flutter_platform_view.h"
#include "flutter/shell/platform/tizen/tizen_log.h"
Expand All @@ -29,8 +30,9 @@ FlutterDesktopEngineRef FlutterDesktopRunEngine(
bool headed) {
flutter::StartLogging();

auto engine = std::make_unique<flutter::FlutterTizenEngine>(headed);
if (!engine->RunEngine(engine_properties)) {
flutter::FlutterProjectBundle project(engine_properties);
auto engine = std::make_unique<flutter::FlutterTizenEngine>(project, headed);
if (!engine->RunEngine()) {
FT_LOGE("Failed to run the Flutter engine.");
return nullptr;
}
Expand Down
79 changes: 31 additions & 48 deletions shell/platform/tizen/flutter_tizen_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

#include "flutter_tizen_engine.h"

#include <filesystem>
#include <algorithm>
#include <string>
#include <vector>

Expand Down Expand Up @@ -33,7 +33,10 @@ constexpr double kProfileFactor = 1.0;

} // namespace

FlutterTizenEngine::FlutterTizenEngine(bool headed) {
FlutterTizenEngine::FlutterTizenEngine(const FlutterProjectBundle& project,
bool headed)
: project_(std::make_unique<FlutterProjectBundle>(project)),
aot_data_(nullptr, nullptr) {
embedder_api_.struct_size = sizeof(FlutterEngineProcTable);
FlutterEngineGetProcAddresses(&embedder_api_);

Expand Down Expand Up @@ -88,52 +91,38 @@ void FlutterTizenEngine::NotifyLowMemoryWarning() {
embedder_api_.NotifyLowMemoryWarning(engine_);
}

// Attempts to load AOT data from the given path, which must be absolute and
// non-empty. Logs and returns nullptr on failure.
UniqueAotDataPtr FlutterTizenEngine::LoadAotData(std::string aot_data_path) {
if (aot_data_path.empty()) {
FT_LOGE(
"Attempted to load AOT data, but no aot_library_path was provided.");
return nullptr;
}
if (!std::filesystem::exists(aot_data_path)) {
FT_LOGE("Can't load AOT data from %s; no such file.",
aot_data_path.c_str());
return nullptr;
}
FlutterEngineAOTDataSource source = {};
source.type = kFlutterEngineAOTDataSourceTypeElfPath;
source.elf_path = aot_data_path.c_str();
FlutterEngineAOTData data = nullptr;
auto result = embedder_api_.CreateAOTData(&source, &data);
if (result != kSuccess) {
FT_LOGE("Failed to load AOT data from: %s", aot_data_path.c_str());
return nullptr;
}
return UniqueAotDataPtr(data);
}

bool FlutterTizenEngine::RunEngine(
const FlutterDesktopEngineProperties& engine_properties) {
bool FlutterTizenEngine::RunEngine() {
if (IsHeaded() && !renderer->IsValid()) {
FT_LOGE("The display was not valid.");
return false;
}

if (!project_->HasValidPaths()) {
FT_LOGE("Missing or unresolvable paths 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_LOGE("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> switches = project_->switches();
std::vector<const char*> argv = {"placeholder"};
if (engine_properties.switches_count > 0) {
argv.insert(argv.end(), &engine_properties.switches[0],
&engine_properties.switches[engine_properties.switches_count]);
}
std::transform(
switches.begin(), switches.end(), std::back_inserter(argv),
[](const std::string& arg) -> const char* { return arg.c_str(); });

for (size_t i = 0; i < engine_properties.switches_count; ++i) {
auto str = std::string{engine_properties.switches[i]};
if (str.find("verbose-logging") != std::string::npos) {
SetMinLoggingLevel(DLOG_INFO);
}
if (std::find(switches.begin(), switches.end(), "verbose-logging") !=
switches.end()) {
SetMinLoggingLevel(DLOG_INFO);
}

// Configure task runners.
Expand Down Expand Up @@ -173,10 +162,10 @@ bool FlutterTizenEngine::RunEngine(

FlutterProjectArgs args = {};
args.struct_size = sizeof(FlutterProjectArgs);
args.assets_path = engine_properties.assets_path;
args.icu_data_path = engine_properties.icu_data_path;
args.assets_path = assets_path_string.c_str();
args.icu_data_path = icu_path_string.c_str();
args.command_line_argc = static_cast<int>(argv.size());
args.command_line_argv = &argv[0];
args.command_line_argv = argv.size() > 0 ? argv.data() : nullptr;
args.platform_message_callback =
[](const FlutterPlatformMessage* engine_message, void* user_data) {
if (engine_message->struct_size != sizeof(FlutterPlatformMessage)) {
Expand All @@ -198,13 +187,7 @@ bool FlutterTizenEngine::RunEngine(
};
}
#endif

if (embedder_api_.RunsAOTCompiledDartCode()) {
aot_data_ = LoadAotData(engine_properties.aot_library_path);
if (!aot_data_) {
FT_LOGE("Unable to start engine without AOT data.");
return false;
}
if (aot_data_) {
args.aot_data = aot_data_.get();
}

Expand Down
41 changes: 23 additions & 18 deletions shell/platform/tizen/flutter_tizen_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#ifndef EMBEDDER_FLUTTER_TIZEN_ENGINE_H_
#define EMBEDDER_FLUTTER_TIZEN_ENGINE_H_

#include <map>
#include <memory>

#include "flutter/shell/platform/common/client_wrapper/include/flutter/plugin_registrar.h"
Expand All @@ -20,6 +19,7 @@
#include "flutter/shell/platform/tizen/channels/platform_view_channel.h"
#include "flutter/shell/platform/tizen/channels/settings_channel.h"
#include "flutter/shell/platform/tizen/channels/text_input_channel.h"
#include "flutter/shell/platform/tizen/flutter_project_bundle.h"
#include "flutter/shell/platform/tizen/flutter_tizen_texture_registrar.h"
#include "flutter/shell/platform/tizen/key_event_handler.h"
#include "flutter/shell/platform/tizen/public/flutter_tizen.h"
Expand Down Expand Up @@ -47,27 +47,25 @@ struct FlutterDesktopMessenger {

namespace flutter {

// Custom deleter for FlutterEngineAOTData.
struct AOTDataDeleter {
void operator()(FlutterEngineAOTData aot_data) {
FlutterEngineCollectAOTData(aot_data);
}
};

using UniqueAotDataPtr = std::unique_ptr<_FlutterEngineAOTData, AOTDataDeleter>;

// Manages state associated with the underlying FlutterEngine.
class FlutterTizenEngine : public TizenRenderer::Delegate {
public:
explicit FlutterTizenEngine(bool headed);
// Creates a new Flutter engine object configured to run |project|.
explicit FlutterTizenEngine(const FlutterProjectBundle& project, bool headed);

virtual ~FlutterTizenEngine();

// Prevent copying.
FlutterTizenEngine(FlutterTizenEngine const&) = delete;
FlutterTizenEngine& operator=(FlutterTizenEngine const&) = delete;

// Sets up an instance of TizenRenderer.
void InitializeRenderer();
bool RunEngine(const FlutterDesktopEngineProperties& engine_properties);

// Starts running the engine.
bool RunEngine();

// Stops the engine.
bool StopEngine();

// Returns the currently configured Plugin Registrar.
Expand Down Expand Up @@ -140,15 +138,25 @@ class FlutterTizenEngine : public TizenRenderer::Delegate {

private:
bool IsHeaded() { return renderer != nullptr; }
UniqueAotDataPtr LoadAotData(std::string aot_data_path);

FlutterDesktopMessage ConvertToDesktopMessage(
const FlutterPlatformMessage& engine_message);

// Creates and returns a FlutterRendererConfig depending on the current
// display mode (headed or headless).
// The user_data received by the render callbacks refers to the
// FlutterTizenEngine.
FlutterRendererConfig GetRendererConfig();

// The handle to the embedder.h engine instance.
FLUTTER_API_SYMBOL(FlutterEngine) engine_ = nullptr;

FlutterEngineProcTable embedder_api_ = {};

// The Flutter engine instance.
FLUTTER_API_SYMBOL(FlutterEngine) engine_;
std::unique_ptr<FlutterProjectBundle> project_;

// AOT data for this engine instance, if applicable.
UniqueAotDataPtr aot_data_;

// The handlers listening to platform events.
std::unique_ptr<KeyEventHandler> key_event_handler_;
Expand Down Expand Up @@ -180,9 +188,6 @@ class FlutterTizenEngine : public TizenRenderer::Delegate {
std::unique_ptr<TizenVsyncWaiter> tizen_vsync_waiter_;
#endif

// AOT data for this engine instance, if applicable.
UniqueAotDataPtr aot_data_;

// The current renderer transformation.
FlutterTransformation transformation_;
};
Expand Down

0 comments on commit e27569b

Please sign in to comment.