From cd83fb33bcf2a918f12443d45ee8a5bdd6b6808c Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Mon, 15 Nov 2021 15:33:26 -0800 Subject: [PATCH 01/17] Add embedder API for replacing the default asset manager --- shell/platform/embedder/embedder.h | 55 ++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index e8b769ef4cbef..b0c0a2e7f5d6d 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -1345,12 +1345,62 @@ typedef void (*FlutterLogMessageCallback)(const char* /* tag */, /// FlutterEngine instance in AOT mode. typedef struct _FlutterEngineAOTData* FlutterEngineAOTData; +/// An immutable buffer of potentially shared data. +typedef struct { + /// The size of the struct. Must be sizeof(FlutterEngineMapping). + size_t struct_size; + + /// A pointer to the data accessed by the Flutter Engine. The data will not be + /// mutated by the Flutter Engine, and must not be mutated by the Embedder until + /// the mapping is destroyed. + const uint8_t* data; + /// The size of the data backed by this mapping. The data must be valid for + /// reading until this point. Bytes past the end are undefined and not accessed + /// by the Engine. + size_t data_size; + + /// An opaque baton passed back to the embedder when the destruction_callback is + /// invoked. The engine does not interpret this field in any way. + void* user_data; + /// Called once by the engine to destroy this mapping. The `user_data` specified + /// above is passed in as the only argument. This call may mutate/free/unmap the + /// data, as it will no longer be accessed by the Flutter Engine. + VoidCallback destruction_callback; +} FlutterEngineMapping; + +/// Callback for fetching assets for a `FlutterEngineAssetResolver`. +/// +/// This may be called by multiple threads. +/// +/// The `asset_name` parameter contains the path to the asset to load. +/// `user_data` is the user data from `FlutterEngineAssetResolver`, registered via +/// `FlutterProjectArgs`. +/// +/// If the asset was found and successfully loaded, return a valid +/// `FlutterEngineMapping`. Otherwise return NULL to indicate an error occurred +/// while loading the asset. +typedef FlutterEngineMapping* (*FlutterAssetResolverGetAssetCallback)(const char* /* asset_name */, + void* /* user_data */); + +/// Resolves assets on the behalf of the Flutter Engine, instead of accessing the +/// filesystem directly. +typedef struct { + /// The size of the struct. Must be sizeof(FlutterEngineAssetResolver). + size_t struct_size; + + /// Required. Gets and returns an asset if available. See the documentation on + /// `FlutterAssetResolverGetAssetCallback` for more information. + FlutterAssetResolverGetAssetCallback get_asset; +} FlutterEngineAssetResolver; + typedef struct { /// The size of this struct. Must be sizeof(FlutterProjectArgs). size_t struct_size; /// The path to the Flutter assets directory containing project assets. The /// string can be collected after the call to `FlutterEngineRun` returns. The /// string must be NULL terminated. + /// + /// If `asset_resolver` is provided, this path is ignored and may be NULL. const char* assets_path; /// The path to the Dart file containing the `main` entry point. /// The string can be collected after the call to `FlutterEngineRun` returns. @@ -1589,6 +1639,11 @@ typedef struct { // // The first argument is the `user_data` from `FlutterEngineInitialize`. OnPreEngineRestartCallback on_pre_engine_restart_callback; + + /// An asset resolver that fetches assets for the Engine. + /// + /// If provided, this replaces the default asset resolver. + const FlutterEngineAssetResolver* asset_resolver; } FlutterProjectArgs; #ifndef FLUTTER_ENGINE_NO_PROTOTYPES From 910bb88c42656978e1637c7ba263f51148c1eb47 Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Mon, 15 Nov 2021 15:49:09 -0800 Subject: [PATCH 02/17] Add EmbedderMapping --- shell/platform/embedder/BUILD.gn | 2 + shell/platform/embedder/embedder_mapping.cc | 58 +++++++++++++++++++++ shell/platform/embedder/embedder_mapping.h | 17 ++++++ 3 files changed, 77 insertions(+) create mode 100644 shell/platform/embedder/embedder_mapping.cc create mode 100644 shell/platform/embedder/embedder_mapping.h diff --git a/shell/platform/embedder/BUILD.gn b/shell/platform/embedder/BUILD.gn index 529f48a7ebd41..b07e1bfa387b4 100644 --- a/shell/platform/embedder/BUILD.gn +++ b/shell/platform/embedder/BUILD.gn @@ -44,6 +44,8 @@ template("embedder_source_set") { "embedder_include2.c", "embedder_layers.cc", "embedder_layers.h", + "embedder_mapping.cc", + "embedder_mapping.h", "embedder_platform_message_response.cc", "embedder_platform_message_response.h", "embedder_render_target.cc", diff --git a/shell/platform/embedder/embedder_mapping.cc b/shell/platform/embedder/embedder_mapping.cc new file mode 100644 index 0000000000000..6588a7369f42e --- /dev/null +++ b/shell/platform/embedder/embedder_mapping.cc @@ -0,0 +1,58 @@ +// 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/shell/platform/embedder/embedder_mapping.h" +#include "flutter/shell/platform/embedder/embedder_struct_macros.h" + +namespace flutter { + +class EmbedderMapping final : public fml::Mapping { + public: + EmbedderMapping(const uint8_t* data, + size_t size, + void* user_data, + VoidCallback destruction_callback) + : data_(data), + size_(size), + user_data_(user_data), + destruction_callback_(destruction_callback) {} + + ~EmbedderMapping() override { + if (destruction_callback_) destruction_callback_(user_data_); + } + + // |Mapping| + size_t GetSize() const override { + return size_; + } + + // |Mapping| + const uint8_t* GetMapping() const override { + return data_; + } + + // |Mapping| + bool IsDontNeedSafe() const override { + return false; + } + +private: + const uint8_t* data_; + size_t size_; + void* user_data_; + VoidCallback destruction_callback_; + + FML_DISALLOW_COPY_AND_ASSIGN(EmbedderMapping); +}; + +std::unique_ptr CreateEmbedderMapping(const FlutterEngineMapping* mapping) { + return std::make_unique( + SAFE_ACCESS(mapping, data, nullptr), + SAFE_ACCESS(mapping, data_size, 0), + SAFE_ACCESS(mapping, user_data, nullptr), + SAFE_ACCESS(mapping, destruction_callback, nullptr) + ); +} + +} // namespace flutter diff --git a/shell/platform/embedder/embedder_mapping.h b/shell/platform/embedder/embedder_mapping.h new file mode 100644 index 0000000000000..85658a3aaa51e --- /dev/null +++ b/shell/platform/embedder/embedder_mapping.h @@ -0,0 +1,17 @@ +// 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 FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_MAPPING_H_ +#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_MAPPING_H_ + +#include "flutter/fml/mapping.h" +#include "flutter/shell/platform/embedder/embedder.h" + +namespace flutter { + +std::unique_ptr CreateEmbedderMapping(const FlutterEngineMapping* mapping); + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_MAPPING_H_ From d5eef2b011f510d70b7b89e2e3104b80c1884434 Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Tue, 16 Nov 2021 13:52:40 -0800 Subject: [PATCH 03/17] Create mappings instead of returning info struct --- shell/platform/embedder/embedder.cc | 15 ++++++++++++ shell/platform/embedder/embedder.h | 27 +++++++++++++++++++-- shell/platform/embedder/embedder_mapping.cc | 4 +-- shell/platform/embedder/embedder_mapping.h | 2 +- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index f8496ffc0b0a9..be951f030fb34 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -49,6 +49,7 @@ extern const intptr_t kPlatformStrongDillSize; #include "flutter/shell/platform/embedder/embedder.h" #include "flutter/shell/platform/embedder/embedder_engine.h" #include "flutter/shell/platform/embedder/embedder_external_texture_resolver.h" +#include "flutter/shell/platform/embedder/embedder_mapping.h" #include "flutter/shell/platform/embedder/embedder_platform_message_response.h" #include "flutter/shell/platform/embedder/embedder_render_target.h" #include "flutter/shell/platform/embedder/embedder_struct_macros.h" @@ -2360,6 +2361,19 @@ FlutterEngineResult FlutterEngineNotifyDisplayUpdate( } } +FlutterEngineResult FlutterEngineCreateMapping( + const FlutterEngineMappingCreateInfo* create_info, + FlutterEngineMapping* out_mapping) { + if (SAFE_ACCESS(create_info, data, nullptr) == nullptr && SAFE_ACCESS(create_info, data_size, 0) > 0) { + return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid mapping specified."); + } + + auto mapping = flutter::CreateEmbedderMapping(create_info); + *out_mapping = reinterpret_cast(mapping.release()); + + return kSuccess; +} + FlutterEngineResult FlutterEngineGetProcAddresses( FlutterEngineProcTable* table) { if (!table) { @@ -2410,6 +2424,7 @@ FlutterEngineResult FlutterEngineGetProcAddresses( SET_PROC(PostCallbackOnAllNativeThreads, FlutterEnginePostCallbackOnAllNativeThreads); SET_PROC(NotifyDisplayUpdate, FlutterEngineNotifyDisplayUpdate); + SET_PROC(CreateMapping, FlutterEngineCreateMapping); #undef SET_PROC return kSuccess; diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index b0c0a2e7f5d6d..22048c4eab516 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -1366,7 +1366,9 @@ typedef struct { /// above is passed in as the only argument. This call may mutate/free/unmap the /// data, as it will no longer be accessed by the Flutter Engine. VoidCallback destruction_callback; -} FlutterEngineMapping; +} FlutterEngineMappingCreateInfo; + +typedef struct FlutterEngineMappingPrivate* FlutterEngineMapping; /// Callback for fetching assets for a `FlutterEngineAssetResolver`. /// @@ -1379,7 +1381,7 @@ typedef struct { /// If the asset was found and successfully loaded, return a valid /// `FlutterEngineMapping`. Otherwise return NULL to indicate an error occurred /// while loading the asset. -typedef FlutterEngineMapping* (*FlutterAssetResolverGetAssetCallback)(const char* /* asset_name */, +typedef FlutterEngineMapping (*FlutterAssetResolverGetAssetCallback)(const char* /* asset_name */, void* /* user_data */); /// Resolves assets on the behalf of the Flutter Engine, instead of accessing the @@ -2306,6 +2308,23 @@ FlutterEngineResult FlutterEngineNotifyDisplayUpdate( const FlutterEngineDisplay* displays, size_t display_count); +//------------------------------------------------------------------------------ +/// @brief Creates a `FlutterEngineMapping` using the given creation info. +/// The backing memory is never mutated by the Engine, and must not +/// be mutated by the embedder until the mapping is destroyed. +/// The engine may access the mapping from multiple threads, and may +/// destroy the mapping from any thread. +/// +/// @param[in] create_info Struct describing the mapping to create. +/// @param[out] out_mapping The created mapping, if successful. +/// +/// @return Whether the mapping was successfully created. +/// +FLUTTER_EXPORT +FlutterEngineResult FlutterEngineCreateMapping( + const FlutterEngineMappingCreateInfo* create_info, + FlutterEngineMapping* out_mapping); + #endif // !FLUTTER_ENGINE_NO_PROTOTYPES // Typedefs for the function pointers in FlutterEngineProcTable. @@ -2422,6 +2441,9 @@ typedef FlutterEngineResult (*FlutterEngineNotifyDisplayUpdateFnPtr)( FlutterEngineDisplaysUpdateType update_type, const FlutterEngineDisplay* displays, size_t display_count); +typedef FlutterEngineResult (*FlutterEngineCreateMappingFnPtr)( + const FlutterEngineMappingCreateInfo* create_info, + FlutterEngineMapping* out_mapping); /// Function-pointer-based versions of the APIs above. typedef struct { @@ -2466,6 +2488,7 @@ typedef struct { FlutterEnginePostCallbackOnAllNativeThreadsFnPtr PostCallbackOnAllNativeThreads; FlutterEngineNotifyDisplayUpdateFnPtr NotifyDisplayUpdate; + FlutterEngineCreateMappingFnPtr CreateMapping; } FlutterEngineProcTable; //------------------------------------------------------------------------------ diff --git a/shell/platform/embedder/embedder_mapping.cc b/shell/platform/embedder/embedder_mapping.cc index 6588a7369f42e..55917ff94cd34 100644 --- a/shell/platform/embedder/embedder_mapping.cc +++ b/shell/platform/embedder/embedder_mapping.cc @@ -42,11 +42,11 @@ class EmbedderMapping final : public fml::Mapping { size_t size_; void* user_data_; VoidCallback destruction_callback_; - + FML_DISALLOW_COPY_AND_ASSIGN(EmbedderMapping); }; -std::unique_ptr CreateEmbedderMapping(const FlutterEngineMapping* mapping) { +std::unique_ptr CreateEmbedderMapping(const FlutterEngineMappingCreateInfo* mapping) { return std::make_unique( SAFE_ACCESS(mapping, data, nullptr), SAFE_ACCESS(mapping, data_size, 0), diff --git a/shell/platform/embedder/embedder_mapping.h b/shell/platform/embedder/embedder_mapping.h index 85658a3aaa51e..2315939af6e77 100644 --- a/shell/platform/embedder/embedder_mapping.h +++ b/shell/platform/embedder/embedder_mapping.h @@ -10,7 +10,7 @@ namespace flutter { -std::unique_ptr CreateEmbedderMapping(const FlutterEngineMapping* mapping); +std::unique_ptr CreateEmbedderMapping(const FlutterEngineMappingCreateInfo* mapping); } // namespace flutter From 7719dcf7bb523757c379e41a7e2b0b82ef02d229 Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Wed, 17 Nov 2021 14:32:00 -0800 Subject: [PATCH 04/17] Update embedder API --- shell/platform/embedder/embedder.h | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index 22048c4eab516..b6946962936ba 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -1381,6 +1381,11 @@ typedef struct FlutterEngineMappingPrivate* FlutterEngineMapping; /// If the asset was found and successfully loaded, return a valid /// `FlutterEngineMapping`. Otherwise return NULL to indicate an error occurred /// while loading the asset. +/// +/// Note that the returned `FlutterEngineMapping` is owned by the Engine and should +/// be cached or reused. Each callback invocation must return a new +/// FlutterEngineMapping. Multiple mappings may refer to the same area in memory, +/// proper book-keeping is up to the embedder. typedef FlutterEngineMapping (*FlutterAssetResolverGetAssetCallback)(const char* /* asset_name */, void* /* user_data */); @@ -1390,6 +1395,10 @@ typedef struct { /// The size of the struct. Must be sizeof(FlutterEngineAssetResolver). size_t struct_size; + /// An opaque baton passed back to the embedder when a callback is + /// invoked. The engine does not interpret this field in any way. + void* user_data; + /// Required. Gets and returns an asset if available. See the documentation on /// `FlutterAssetResolverGetAssetCallback` for more information. FlutterAssetResolverGetAssetCallback get_asset; @@ -1402,7 +1411,11 @@ typedef struct { /// string can be collected after the call to `FlutterEngineRun` returns. The /// string must be NULL terminated. /// - /// If `asset_resolver` is provided, this path is ignored and may be NULL. + /// If `asset_resolver` is provided, may be NULL. + /// + /// If both `asset_resolver` and `assets_path` are provided, the `asset_resolver` + /// comes first in the asset search order, then `assets_path`. This effectively + /// makes `asset_resolver` an overlay over `assets_path`. const char* assets_path; /// The path to the Dart file containing the `main` entry point. /// The string can be collected after the call to `FlutterEngineRun` returns. @@ -1644,7 +1657,11 @@ typedef struct { /// An asset resolver that fetches assets for the Engine. /// - /// If provided, this replaces the default asset resolver. + /// If `assets_path` is provided, may be NULL. + /// + /// If both `asset_resolver` and `assets_path` are provided, the `asset_resolver` + /// comes first in the asset search order, then `assets_path`. This effectively + /// makes `asset_resolver` an overlay over `assets_path`. const FlutterEngineAssetResolver* asset_resolver; } FlutterProjectArgs; From 9b58de042b40200ddac799cf1764346ec6779184 Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Wed, 17 Nov 2021 14:32:32 -0800 Subject: [PATCH 05/17] Add support for embedder-provided asset resolvers --- assets/asset_resolver.h | 3 +- shell/platform/embedder/BUILD.gn | 2 + shell/platform/embedder/embedder.cc | 41 +++++++++---- .../embedder/embedder_asset_resolver.cc | 58 +++++++++++++++++++ .../embedder/embedder_asset_resolver.h | 17 ++++++ 5 files changed, 110 insertions(+), 11 deletions(-) create mode 100644 shell/platform/embedder/embedder_asset_resolver.cc create mode 100644 shell/platform/embedder/embedder_asset_resolver.h diff --git a/assets/asset_resolver.h b/assets/asset_resolver.h index 4bf1eeb23e6f1..e5da2a2eb4a9a 100644 --- a/assets/asset_resolver.h +++ b/assets/asset_resolver.h @@ -26,7 +26,8 @@ class AssetResolver { enum AssetResolverType { kAssetManager, kApkAssetProvider, - kDirectoryAssetBundle + kDirectoryAssetBundle, + kEmbedderAssetResolver }; virtual bool IsValid() const = 0; diff --git a/shell/platform/embedder/BUILD.gn b/shell/platform/embedder/BUILD.gn index b07e1bfa387b4..aacf0f2aafdc6 100644 --- a/shell/platform/embedder/BUILD.gn +++ b/shell/platform/embedder/BUILD.gn @@ -32,6 +32,8 @@ template("embedder_source_set") { source_set(target_name) { sources = [ "embedder.cc", + "embedder_asset_resolver.cc", + "embedder_asset_resolver.h", "embedder_engine.cc", "embedder_engine.h", "embedder_external_texture_resolver.cc", diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index be951f030fb34..80d736e0cfb03 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -47,6 +47,7 @@ extern const intptr_t kPlatformStrongDillSize; #include "flutter/shell/common/rasterizer.h" #include "flutter/shell/common/switches.h" #include "flutter/shell/platform/embedder/embedder.h" +#include "flutter/shell/platform/embedder/embedder_asset_resolver.h" #include "flutter/shell/platform/embedder/embedder_engine.h" #include "flutter/shell/platform/embedder/embedder_external_texture_resolver.h" #include "flutter/shell/platform/embedder/embedder_mapping.h" @@ -927,10 +928,10 @@ FlutterEngineResult FlutterEngineInitialize(size_t version, "The Flutter project arguments were missing."); } - if (SAFE_ACCESS(args, assets_path, nullptr) == nullptr) { + if (SAFE_ACCESS(args, assets_path, nullptr) == nullptr && SAFE_ACCESS(args, asset_resolver, nullptr) == nullptr) { return LOG_EMBEDDER_ERROR( kInvalidArguments, - "The assets path in the Flutter project arguments was missing."); + "The assets path or asset resolver in the Flutter project arguments was missing."); } if (SAFE_ACCESS(args, main_path__unused__, nullptr) != nullptr) { @@ -988,19 +989,22 @@ FlutterEngineResult FlutterEngineInitialize(size_t version, PopulateSnapshotMappingCallbacks(args, settings); settings.icu_data_path = icu_data_path; - settings.assets_path = args->assets_path; + if (args->assets_path) settings.assets_path = args->assets_path; settings.leak_vm = !SAFE_ACCESS(args, shutdown_dart_vm_when_done, false); settings.old_gen_heap_size = SAFE_ACCESS(args, dart_old_gen_heap_size, -1); if (!flutter::DartVM::IsRunningPrecompiledCode()) { // Verify the assets path contains Dart 2 kernel assets. + // NOTE: This check is skipped if using a custom asset resolver. const std::string kApplicationKernelSnapshotFileName = "kernel_blob.bin"; - std::string application_kernel_path = fml::paths::JoinPaths( - {settings.assets_path, kApplicationKernelSnapshotFileName}); - if (!fml::IsFile(application_kernel_path)) { - return LOG_EMBEDDER_ERROR( - kInvalidArguments, - "Not running in AOT mode but could not resolve the kernel binary."); + if (args->assets_path) { + std::string application_kernel_path = fml::paths::JoinPaths( + {settings.assets_path, kApplicationKernelSnapshotFileName}); + if (!fml::IsFile(application_kernel_path)) { + return LOG_EMBEDDER_ERROR( + kInvalidArguments, + "Not running in AOT mode but could not resolve the kernel binary."); + } } settings.application_kernel_asset = kApplicationKernelSnapshotFileName; } @@ -1297,8 +1301,25 @@ FlutterEngineResult FlutterEngineInitialize(size_t version, "Task runner configuration was invalid."); } + auto asset_manager = std::make_shared(); + + if (SAFE_ACCESS(args, asset_resolver, nullptr) != nullptr) { + asset_manager->PushBack(flutter::CreateEmbedderAssetResolver(args->asset_resolver)); + } + + if (args->assets_path) { + asset_manager->PushBack(std::make_unique( + fml::OpenDirectory(args->assets_path, false, + fml::FilePermission::kRead), + true)); + } + auto run_configuration = - flutter::RunConfiguration::InferFromSettings(settings); + flutter::RunConfiguration( + flutter::IsolateConfiguration::InferFromSettings(settings, asset_manager, + nullptr), + asset_manager + ); if (SAFE_ACCESS(args, custom_dart_entrypoint, nullptr) != nullptr) { auto dart_entrypoint = std::string{args->custom_dart_entrypoint}; diff --git a/shell/platform/embedder/embedder_asset_resolver.cc b/shell/platform/embedder/embedder_asset_resolver.cc new file mode 100644 index 0000000000000..43ad9080826ec --- /dev/null +++ b/shell/platform/embedder/embedder_asset_resolver.cc @@ -0,0 +1,58 @@ +// 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/shell/platform/embedder/embedder_asset_resolver.h" +#include "flutter/shell/platform/embedder/embedder_struct_macros.h" + +namespace flutter { + +class EmbedderAssetResolver final : public flutter::AssetResolver { + public: + explicit EmbedderAssetResolver(void* user_data, + FlutterAssetResolverGetAssetCallback get_asset) + : user_data_(user_data), + get_asset_(get_asset) {} + + ~EmbedderAssetResolver() override {} + + // |AssetResolver| + bool IsValid() const override { + return true; + } + + // |AssetResolver| + bool IsValidAfterAssetManagerChange() const override { + return true; + } + + // |AssetResolver| + AssetResolverType GetType() const override { + return AssetResolverType::kEmbedderAssetResolver; + } + + // |AssetResolver| + std::unique_ptr GetAsMapping(const std::string& asset_name) const override { + if (!get_asset_) { + return std::unique_ptr(); + } + + FlutterEngineMapping mapping = get_asset_(asset_name.c_str(), user_data_); + return std::unique_ptr(reinterpret_cast(mapping)); + } + +private: + void* user_data_; + FlutterAssetResolverGetAssetCallback get_asset_; + + FML_DISALLOW_COPY_AND_ASSIGN(EmbedderAssetResolver); +}; + +std::unique_ptr CreateEmbedderAssetResolver(const FlutterEngineAssetResolver* resolver) { + return std::make_unique( + SAFE_ACCESS(resolver, user_data, nullptr), + SAFE_ACCESS(resolver, get_asset, nullptr) + ); +} + +} // namespace flutter diff --git a/shell/platform/embedder/embedder_asset_resolver.h b/shell/platform/embedder/embedder_asset_resolver.h new file mode 100644 index 0000000000000..2b2c9d058c0f2 --- /dev/null +++ b/shell/platform/embedder/embedder_asset_resolver.h @@ -0,0 +1,17 @@ +// 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 FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_ASSET_RESOLVER_H_ +#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_ASSET_RESOLVER_H_ + +#include "flutter/assets/asset_resolver.h" +#include "flutter/shell/platform/embedder/embedder.h" + +namespace flutter { + +std::unique_ptr CreateEmbedderAssetResolver(const FlutterEngineAssetResolver* resolver); + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_ASSET_RESOLVER_H_ From 8eb8d57eefa72e0a38fce45910b9e949eb6b3181 Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Wed, 17 Nov 2021 14:38:07 -0800 Subject: [PATCH 06/17] Add tests for custom asset resolvers --- shell/platform/embedder/fixtures/main.dart | 22 +++++ .../embedder/tests/embedder_config_builder.cc | 5 + .../embedder/tests/embedder_config_builder.h | 3 + .../embedder/tests/embedder_unittests.cc | 98 +++++++++++++++++++ 4 files changed, 128 insertions(+) diff --git a/shell/platform/embedder/fixtures/main.dart b/shell/platform/embedder/fixtures/main.dart index 5196f37727597..7649378e75144 100644 --- a/shell/platform/embedder/fixtures/main.dart +++ b/shell/platform/embedder/fixtures/main.dart @@ -299,6 +299,28 @@ void null_platform_messages() { signalNativeTest(); } +const String channel = 'flutter/assets'; +ByteData encodePath(String path) => ByteData.sublistView(utf8.encoder.convert(path)); + +void handleAssetReply(ByteData? reply) { + if (reply != null) { + signalNativeCount(reply.lengthInBytes); + signalNativeMessage(utf8.decode(Uint8List.sublistView(reply))); + } else { + signalNativeCount(-1); + } +} + +@pragma('vm:entry-point') +void existing_asset() { + PlatformDispatcher.instance.sendPlatformMessage(channel, encodePath('existing_asset'), handleAssetReply); +} + +@pragma('vm:entry-point') +void invalid_asset() { + PlatformDispatcher.instance.sendPlatformMessage(channel, encodePath('invalid_asset'), handleAssetReply); +} + Picture CreateSimplePicture() { Paint blackPaint = Paint(); PictureRecorder baseRecorder = PictureRecorder(); diff --git a/shell/platform/embedder/tests/embedder_config_builder.cc b/shell/platform/embedder/tests/embedder_config_builder.cc index d04188e0d3070..fcd1bb683373c 100644 --- a/shell/platform/embedder/tests/embedder_config_builder.cc +++ b/shell/platform/embedder/tests/embedder_config_builder.cc @@ -174,6 +174,11 @@ void EmbedderConfigBuilder::SetAssetsPath() { project_args_.assets_path = context_.GetAssetsPath().c_str(); } +void EmbedderConfigBuilder::SetAssetResolver(const FlutterEngineAssetResolver* resolver) { + asset_resolver_ = *resolver; + project_args_.asset_resolver = &asset_resolver_; +} + void EmbedderConfigBuilder::SetSnapshots() { if (auto mapping = context_.GetVMSnapshotData()) { project_args_.vm_snapshot_data = mapping->GetMapping(); diff --git a/shell/platform/embedder/tests/embedder_config_builder.h b/shell/platform/embedder/tests/embedder_config_builder.h index ee1fb514bb611..1938299d2d390 100644 --- a/shell/platform/embedder/tests/embedder_config_builder.h +++ b/shell/platform/embedder/tests/embedder_config_builder.h @@ -65,6 +65,8 @@ class EmbedderConfigBuilder { void SetAssetsPath(); + void SetAssetResolver(const FlutterEngineAssetResolver* resolver); + void SetSnapshots(); void SetAOTDataElf(); @@ -124,6 +126,7 @@ class EmbedderConfigBuilder { std::string dart_entrypoint_; FlutterCustomTaskRunners custom_task_runners_ = {}; FlutterCompositor compositor_ = {}; + FlutterEngineAssetResolver asset_resolver_ = {}; std::vector command_line_arguments_; std::vector dart_entrypoint_arguments_; std::string log_tag_; diff --git a/shell/platform/embedder/tests/embedder_unittests.cc b/shell/platform/embedder/tests/embedder_unittests.cc index 3108cff91e200..55b6efcb13349 100644 --- a/shell/platform/embedder/tests/embedder_unittests.cc +++ b/shell/platform/embedder/tests/embedder_unittests.cc @@ -474,6 +474,104 @@ TEST_F(EmbedderTest, InvalidPlatformMessages) { ASSERT_EQ(result, kInvalidArguments); } +//------------------------------------------------------------------------------ +/// Tests that an asset can be loaded from a custom asset resolver. +/// +TEST_F(EmbedderTest, CustomAssetResolverReturnsValidAsset) { + auto& context = GetEmbedderContext(EmbedderTestContextType::kSoftwareContext); + EmbedderConfigBuilder builder(context); + builder.SetSoftwareRendererConfig(); + builder.SetDartEntrypoint("existing_asset"); + + fml::AutoResetWaitableEvent destroy; + + FlutterEngineAssetResolver resolver = {}; + resolver.struct_size = sizeof(FlutterEngineAssetResolver); + resolver.user_data = reinterpret_cast(&destroy); + resolver.get_asset = [](const char* asset, void* user_data) -> FlutterEngineMapping { + if (strcmp(asset, "existing_asset") == 0) { + // Return an asset with the string "hello" as its contents. + // When the mapping is destroyed (on GC or Engine shutdown) the + // `destroy` event is signaled. + FlutterEngineMappingCreateInfo create_info = {}; + FlutterEngineMapping out = nullptr; + create_info.struct_size = sizeof(FlutterEngineMappingCreateInfo); + create_info.data = reinterpret_cast("hello"); + create_info.data_size = 5; + create_info.user_data = user_data; + create_info.destruction_callback = [](void* user_data) { + reinterpret_cast(user_data)->Signal(); + }; + auto result = FlutterEngineCreateMapping(&create_info, &out); + EXPECT_EQ(result, kSuccess); + return out; + } + return nullptr; + }; + + builder.SetAssetResolver(&resolver); + + fml::AutoResetWaitableEvent message; + context.AddNativeCallback( + "SignalNativeCount", + CREATE_NATIVE_ENTRY([](Dart_NativeArguments args) { + auto count = tonic::DartConverter::FromDart( + Dart_GetNativeArgument(args, 0)); + // Dart should receive a 5 byte message reply. + EXPECT_EQ(5, count); + })); + context.AddNativeCallback( + "SignalNativeMessage", + CREATE_NATIVE_ENTRY(([&message](Dart_NativeArguments args) { + auto received_message = tonic::DartConverter::FromDart( + Dart_GetNativeArgument(args, 0)); + // The message received from the asset channel should be the string "hello". + EXPECT_EQ("hello", received_message); + message.Signal(); + }))); + + { + auto engine = builder.LaunchEngine(); + ASSERT_TRUE(engine.is_valid()); + message.Wait(); + } + // Before or during Engine shutdown, the mapping should be destroyed. + destroy.Wait(); +} + +//------------------------------------------------------------------------------ +/// Tests that an asset that aren't found return null responses. +/// +TEST_F(EmbedderTest, CustomAssetResolverReturnsInvalidAsset) { + auto& context = GetEmbedderContext(EmbedderTestContextType::kSoftwareContext); + EmbedderConfigBuilder builder(context); + builder.SetSoftwareRendererConfig(); + builder.SetDartEntrypoint("invalid_asset"); + + FlutterEngineAssetResolver resolver = {}; + resolver.struct_size = sizeof(FlutterEngineAssetResolver); + resolver.get_asset = [](const char* asset, void* user_data) -> FlutterEngineMapping { + return nullptr; + }; + + builder.SetAssetResolver(&resolver); + + fml::AutoResetWaitableEvent message; + context.AddNativeCallback( + "SignalNativeCount", + CREATE_NATIVE_ENTRY([&message](Dart_NativeArguments args) { + auto count = tonic::DartConverter::FromDart( + Dart_GetNativeArgument(args, 0)); + // Dart should receive a null reply. + EXPECT_EQ(-1, count); + message.Signal(); + })); + + auto engine = builder.LaunchEngine(); + ASSERT_TRUE(engine.is_valid()); + message.Wait(); +} + //------------------------------------------------------------------------------ /// Tests that setting a custom log callback works as expected and defaults to /// using tag "flutter". From 50429c059b8cf8264bed8415abc83d47d21165db Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Wed, 17 Nov 2021 17:07:12 -0800 Subject: [PATCH 07/17] Fix formatting --- shell/platform/embedder/embedder.cc | 28 ++++----- shell/platform/embedder/embedder.h | 58 ++++++++++--------- .../embedder/embedder_asset_resolver.cc | 33 +++++------ .../embedder/embedder_asset_resolver.h | 3 +- shell/platform/embedder/embedder_mapping.cc | 32 +++++----- shell/platform/embedder/embedder_mapping.h | 3 +- .../embedder/tests/embedder_config_builder.cc | 3 +- .../embedder/tests/embedder_unittests.cc | 12 ++-- 8 files changed, 87 insertions(+), 85 deletions(-) diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index 80d736e0cfb03..dcfbcee9a83bf 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -928,10 +928,11 @@ FlutterEngineResult FlutterEngineInitialize(size_t version, "The Flutter project arguments were missing."); } - if (SAFE_ACCESS(args, assets_path, nullptr) == nullptr && SAFE_ACCESS(args, asset_resolver, nullptr) == nullptr) { - return LOG_EMBEDDER_ERROR( - kInvalidArguments, - "The assets path or asset resolver in the Flutter project arguments was missing."); + if (SAFE_ACCESS(args, assets_path, nullptr) == nullptr && + SAFE_ACCESS(args, asset_resolver, nullptr) == nullptr) { + return LOG_EMBEDDER_ERROR(kInvalidArguments, + "The assets path or asset resolver in the " + "Flutter project arguments was missing."); } if (SAFE_ACCESS(args, main_path__unused__, nullptr) != nullptr) { @@ -989,7 +990,8 @@ FlutterEngineResult FlutterEngineInitialize(size_t version, PopulateSnapshotMappingCallbacks(args, settings); settings.icu_data_path = icu_data_path; - if (args->assets_path) settings.assets_path = args->assets_path; + if (args->assets_path) + settings.assets_path = args->assets_path; settings.leak_vm = !SAFE_ACCESS(args, shutdown_dart_vm_when_done, false); settings.old_gen_heap_size = SAFE_ACCESS(args, dart_old_gen_heap_size, -1); @@ -1304,7 +1306,8 @@ FlutterEngineResult FlutterEngineInitialize(size_t version, auto asset_manager = std::make_shared(); if (SAFE_ACCESS(args, asset_resolver, nullptr) != nullptr) { - asset_manager->PushBack(flutter::CreateEmbedderAssetResolver(args->asset_resolver)); + asset_manager->PushBack( + flutter::CreateEmbedderAssetResolver(args->asset_resolver)); } if (args->assets_path) { @@ -1314,12 +1317,10 @@ FlutterEngineResult FlutterEngineInitialize(size_t version, true)); } - auto run_configuration = - flutter::RunConfiguration( - flutter::IsolateConfiguration::InferFromSettings(settings, asset_manager, - nullptr), - asset_manager - ); + auto run_configuration = flutter::RunConfiguration( + flutter::IsolateConfiguration::InferFromSettings(settings, asset_manager, + nullptr), + asset_manager); if (SAFE_ACCESS(args, custom_dart_entrypoint, nullptr) != nullptr) { auto dart_entrypoint = std::string{args->custom_dart_entrypoint}; @@ -2385,7 +2386,8 @@ FlutterEngineResult FlutterEngineNotifyDisplayUpdate( FlutterEngineResult FlutterEngineCreateMapping( const FlutterEngineMappingCreateInfo* create_info, FlutterEngineMapping* out_mapping) { - if (SAFE_ACCESS(create_info, data, nullptr) == nullptr && SAFE_ACCESS(create_info, data_size, 0) > 0) { + if (SAFE_ACCESS(create_info, data, nullptr) == nullptr && + SAFE_ACCESS(create_info, data_size, 0) > 0) { return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid mapping specified."); } diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index b6946962936ba..256621144a906 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -1345,26 +1345,27 @@ typedef void (*FlutterLogMessageCallback)(const char* /* tag */, /// FlutterEngine instance in AOT mode. typedef struct _FlutterEngineAOTData* FlutterEngineAOTData; -/// An immutable buffer of potentially shared data. +/// An immutable buffer of potentially shared data. typedef struct { /// The size of the struct. Must be sizeof(FlutterEngineMapping). size_t struct_size; /// A pointer to the data accessed by the Flutter Engine. The data will not be - /// mutated by the Flutter Engine, and must not be mutated by the Embedder until - /// the mapping is destroyed. + /// mutated by the Flutter Engine, and must not be mutated by the Embedder + /// until the mapping is destroyed. const uint8_t* data; /// The size of the data backed by this mapping. The data must be valid for - /// reading until this point. Bytes past the end are undefined and not accessed - /// by the Engine. + /// reading until this point. Bytes past the end are undefined and not + /// accessed by the Engine. size_t data_size; - /// An opaque baton passed back to the embedder when the destruction_callback is - /// invoked. The engine does not interpret this field in any way. + /// An opaque baton passed back to the embedder when the destruction_callback + /// is invoked. The engine does not interpret this field in any way. void* user_data; - /// Called once by the engine to destroy this mapping. The `user_data` specified - /// above is passed in as the only argument. This call may mutate/free/unmap the - /// data, as it will no longer be accessed by the Flutter Engine. + /// Called once by the engine to destroy this mapping. The `user_data` + /// specified above is passed in as the only argument. This call may + /// mutate/free/unmap the data, as it will no longer be accessed by the + /// Flutter Engine. VoidCallback destruction_callback; } FlutterEngineMappingCreateInfo; @@ -1375,22 +1376,23 @@ typedef struct FlutterEngineMappingPrivate* FlutterEngineMapping; /// This may be called by multiple threads. /// /// The `asset_name` parameter contains the path to the asset to load. -/// `user_data` is the user data from `FlutterEngineAssetResolver`, registered via -/// `FlutterProjectArgs`. +/// `user_data` is the user data from `FlutterEngineAssetResolver`, registered +/// via `FlutterProjectArgs`. /// /// If the asset was found and successfully loaded, return a valid -/// `FlutterEngineMapping`. Otherwise return NULL to indicate an error occurred +/// `FlutterEngineMapping`. Otherwise return NULL to indicate an error occurred /// while loading the asset. /// -/// Note that the returned `FlutterEngineMapping` is owned by the Engine and should -/// be cached or reused. Each callback invocation must return a new -/// FlutterEngineMapping. Multiple mappings may refer to the same area in memory, -/// proper book-keeping is up to the embedder. -typedef FlutterEngineMapping (*FlutterAssetResolverGetAssetCallback)(const char* /* asset_name */, - void* /* user_data */); +/// Note that the returned `FlutterEngineMapping` is owned by the Engine and +/// should be cached or reused. Each callback invocation must return a new +/// FlutterEngineMapping. Multiple mappings may refer to the same area in +/// memory, proper book-keeping is up to the embedder. +typedef FlutterEngineMapping (*FlutterAssetResolverGetAssetCallback)( + const char* /* asset_name */, + void* /* user_data */); -/// Resolves assets on the behalf of the Flutter Engine, instead of accessing the -/// filesystem directly. +/// Resolves assets on the behalf of the Flutter Engine, instead of accessing +/// the filesystem directly. typedef struct { /// The size of the struct. Must be sizeof(FlutterEngineAssetResolver). size_t struct_size; @@ -1413,9 +1415,10 @@ typedef struct { /// /// If `asset_resolver` is provided, may be NULL. /// - /// If both `asset_resolver` and `assets_path` are provided, the `asset_resolver` - /// comes first in the asset search order, then `assets_path`. This effectively - /// makes `asset_resolver` an overlay over `assets_path`. + /// If both `asset_resolver` and `assets_path` are provided, the + /// `asset_resolver` comes first in the asset search order, then + /// `assets_path`. This effectively makes `asset_resolver` an overlay over + /// `assets_path`. const char* assets_path; /// The path to the Dart file containing the `main` entry point. /// The string can be collected after the call to `FlutterEngineRun` returns. @@ -1659,9 +1662,10 @@ typedef struct { /// /// If `assets_path` is provided, may be NULL. /// - /// If both `asset_resolver` and `assets_path` are provided, the `asset_resolver` - /// comes first in the asset search order, then `assets_path`. This effectively - /// makes `asset_resolver` an overlay over `assets_path`. + /// If both `asset_resolver` and `assets_path` are provided, the + /// `asset_resolver` comes first in the asset search order, then + /// `assets_path`. This effectively makes `asset_resolver` an overlay over + /// `assets_path`. const FlutterEngineAssetResolver* asset_resolver; } FlutterProjectArgs; diff --git a/shell/platform/embedder/embedder_asset_resolver.cc b/shell/platform/embedder/embedder_asset_resolver.cc index 43ad9080826ec..191b35e6fc378 100644 --- a/shell/platform/embedder/embedder_asset_resolver.cc +++ b/shell/platform/embedder/embedder_asset_resolver.cc @@ -8,23 +8,18 @@ namespace flutter { class EmbedderAssetResolver final : public flutter::AssetResolver { - public: + public: explicit EmbedderAssetResolver(void* user_data, FlutterAssetResolverGetAssetCallback get_asset) - : user_data_(user_data), - get_asset_(get_asset) {} - + : user_data_(user_data), get_asset_(get_asset) {} + ~EmbedderAssetResolver() override {} // |AssetResolver| - bool IsValid() const override { - return true; - } + bool IsValid() const override { return true; } // |AssetResolver| - bool IsValidAfterAssetManagerChange() const override { - return true; - } + bool IsValidAfterAssetManagerChange() const override { return true; } // |AssetResolver| AssetResolverType GetType() const override { @@ -32,27 +27,29 @@ class EmbedderAssetResolver final : public flutter::AssetResolver { } // |AssetResolver| - std::unique_ptr GetAsMapping(const std::string& asset_name) const override { + std::unique_ptr GetAsMapping( + const std::string& asset_name) const override { if (!get_asset_) { return std::unique_ptr(); } FlutterEngineMapping mapping = get_asset_(asset_name.c_str(), user_data_); - return std::unique_ptr(reinterpret_cast(mapping)); + return std::unique_ptr( + reinterpret_cast(mapping)); } -private: + private: void* user_data_; FlutterAssetResolverGetAssetCallback get_asset_; - + FML_DISALLOW_COPY_AND_ASSIGN(EmbedderAssetResolver); }; -std::unique_ptr CreateEmbedderAssetResolver(const FlutterEngineAssetResolver* resolver) { +std::unique_ptr CreateEmbedderAssetResolver( + const FlutterEngineAssetResolver* resolver) { return std::make_unique( - SAFE_ACCESS(resolver, user_data, nullptr), - SAFE_ACCESS(resolver, get_asset, nullptr) - ); + SAFE_ACCESS(resolver, user_data, nullptr), + SAFE_ACCESS(resolver, get_asset, nullptr)); } } // namespace flutter diff --git a/shell/platform/embedder/embedder_asset_resolver.h b/shell/platform/embedder/embedder_asset_resolver.h index 2b2c9d058c0f2..34edd86bfdcf1 100644 --- a/shell/platform/embedder/embedder_asset_resolver.h +++ b/shell/platform/embedder/embedder_asset_resolver.h @@ -10,7 +10,8 @@ namespace flutter { -std::unique_ptr CreateEmbedderAssetResolver(const FlutterEngineAssetResolver* resolver); +std::unique_ptr CreateEmbedderAssetResolver( + const FlutterEngineAssetResolver* resolver); } // namespace flutter diff --git a/shell/platform/embedder/embedder_mapping.cc b/shell/platform/embedder/embedder_mapping.cc index 55917ff94cd34..ec6e981668cc6 100644 --- a/shell/platform/embedder/embedder_mapping.cc +++ b/shell/platform/embedder/embedder_mapping.cc @@ -8,7 +8,7 @@ namespace flutter { class EmbedderMapping final : public fml::Mapping { - public: + public: EmbedderMapping(const uint8_t* data, size_t size, void* user_data, @@ -17,27 +17,22 @@ class EmbedderMapping final : public fml::Mapping { size_(size), user_data_(user_data), destruction_callback_(destruction_callback) {} - + ~EmbedderMapping() override { - if (destruction_callback_) destruction_callback_(user_data_); + if (destruction_callback_) + destruction_callback_(user_data_); } // |Mapping| - size_t GetSize() const override { - return size_; - } + size_t GetSize() const override { return size_; } // |Mapping| - const uint8_t* GetMapping() const override { - return data_; - } + const uint8_t* GetMapping() const override { return data_; } // |Mapping| - bool IsDontNeedSafe() const override { - return false; - } + bool IsDontNeedSafe() const override { return false; } -private: + private: const uint8_t* data_; size_t size_; void* user_data_; @@ -46,13 +41,12 @@ class EmbedderMapping final : public fml::Mapping { FML_DISALLOW_COPY_AND_ASSIGN(EmbedderMapping); }; -std::unique_ptr CreateEmbedderMapping(const FlutterEngineMappingCreateInfo* mapping) { +std::unique_ptr CreateEmbedderMapping( + const FlutterEngineMappingCreateInfo* mapping) { return std::make_unique( - SAFE_ACCESS(mapping, data, nullptr), - SAFE_ACCESS(mapping, data_size, 0), - SAFE_ACCESS(mapping, user_data, nullptr), - SAFE_ACCESS(mapping, destruction_callback, nullptr) - ); + SAFE_ACCESS(mapping, data, nullptr), SAFE_ACCESS(mapping, data_size, 0), + SAFE_ACCESS(mapping, user_data, nullptr), + SAFE_ACCESS(mapping, destruction_callback, nullptr)); } } // namespace flutter diff --git a/shell/platform/embedder/embedder_mapping.h b/shell/platform/embedder/embedder_mapping.h index 2315939af6e77..0ff69b603d03b 100644 --- a/shell/platform/embedder/embedder_mapping.h +++ b/shell/platform/embedder/embedder_mapping.h @@ -10,7 +10,8 @@ namespace flutter { -std::unique_ptr CreateEmbedderMapping(const FlutterEngineMappingCreateInfo* mapping); +std::unique_ptr CreateEmbedderMapping( + const FlutterEngineMappingCreateInfo* mapping); } // namespace flutter diff --git a/shell/platform/embedder/tests/embedder_config_builder.cc b/shell/platform/embedder/tests/embedder_config_builder.cc index fcd1bb683373c..95bf7c5269fa4 100644 --- a/shell/platform/embedder/tests/embedder_config_builder.cc +++ b/shell/platform/embedder/tests/embedder_config_builder.cc @@ -174,7 +174,8 @@ void EmbedderConfigBuilder::SetAssetsPath() { project_args_.assets_path = context_.GetAssetsPath().c_str(); } -void EmbedderConfigBuilder::SetAssetResolver(const FlutterEngineAssetResolver* resolver) { +void EmbedderConfigBuilder::SetAssetResolver( + const FlutterEngineAssetResolver* resolver) { asset_resolver_ = *resolver; project_args_.asset_resolver = &asset_resolver_; } diff --git a/shell/platform/embedder/tests/embedder_unittests.cc b/shell/platform/embedder/tests/embedder_unittests.cc index 55b6efcb13349..89efc60c76b1d 100644 --- a/shell/platform/embedder/tests/embedder_unittests.cc +++ b/shell/platform/embedder/tests/embedder_unittests.cc @@ -488,7 +488,8 @@ TEST_F(EmbedderTest, CustomAssetResolverReturnsValidAsset) { FlutterEngineAssetResolver resolver = {}; resolver.struct_size = sizeof(FlutterEngineAssetResolver); resolver.user_data = reinterpret_cast(&destroy); - resolver.get_asset = [](const char* asset, void* user_data) -> FlutterEngineMapping { + resolver.get_asset = [](const char* asset, + void* user_data) -> FlutterEngineMapping { if (strcmp(asset, "existing_asset") == 0) { // Return an asset with the string "hello" as its contents. // When the mapping is destroyed (on GC or Engine shutdown) the @@ -513,8 +514,7 @@ TEST_F(EmbedderTest, CustomAssetResolverReturnsValidAsset) { fml::AutoResetWaitableEvent message; context.AddNativeCallback( - "SignalNativeCount", - CREATE_NATIVE_ENTRY([](Dart_NativeArguments args) { + "SignalNativeCount", CREATE_NATIVE_ENTRY([](Dart_NativeArguments args) { auto count = tonic::DartConverter::FromDart( Dart_GetNativeArgument(args, 0)); // Dart should receive a 5 byte message reply. @@ -525,7 +525,8 @@ TEST_F(EmbedderTest, CustomAssetResolverReturnsValidAsset) { CREATE_NATIVE_ENTRY(([&message](Dart_NativeArguments args) { auto received_message = tonic::DartConverter::FromDart( Dart_GetNativeArgument(args, 0)); - // The message received from the asset channel should be the string "hello". + // The message received from the asset channel should be the string + // "hello". EXPECT_EQ("hello", received_message); message.Signal(); }))); @@ -550,7 +551,8 @@ TEST_F(EmbedderTest, CustomAssetResolverReturnsInvalidAsset) { FlutterEngineAssetResolver resolver = {}; resolver.struct_size = sizeof(FlutterEngineAssetResolver); - resolver.get_asset = [](const char* asset, void* user_data) -> FlutterEngineMapping { + resolver.get_asset = [](const char* asset, + void* user_data) -> FlutterEngineMapping { return nullptr; }; From 769c6cf37632928b867719e8967c52eaf733badc Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Thu, 18 Nov 2021 15:03:01 -0800 Subject: [PATCH 08/17] Update licenses --- ci/licenses_golden/licenses_flutter | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index e0b43fca37cf5..88bc5d164105f 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1296,6 +1296,8 @@ FILE: ../../../flutter/shell/platform/embedder/assets/EmbedderInfo.plist FILE: ../../../flutter/shell/platform/embedder/assets/embedder.modulemap FILE: ../../../flutter/shell/platform/embedder/embedder.cc FILE: ../../../flutter/shell/platform/embedder/embedder.h +FILE: ../../../flutter/shell/platform/embedder/embedder_asset_resolver.cc +FILE: ../../../flutter/shell/platform/embedder/embedder_asset_resolver.h FILE: ../../../flutter/shell/platform/embedder/embedder_engine.cc FILE: ../../../flutter/shell/platform/embedder/embedder_engine.h FILE: ../../../flutter/shell/platform/embedder/embedder_external_texture_gl.cc @@ -1312,6 +1314,8 @@ FILE: ../../../flutter/shell/platform/embedder/embedder_include.c FILE: ../../../flutter/shell/platform/embedder/embedder_include2.c FILE: ../../../flutter/shell/platform/embedder/embedder_layers.cc FILE: ../../../flutter/shell/platform/embedder/embedder_layers.h +FILE: ../../../flutter/shell/platform/embedder/embedder_mapping.cc +FILE: ../../../flutter/shell/platform/embedder/embedder_mapping.h FILE: ../../../flutter/shell/platform/embedder/embedder_platform_message_response.cc FILE: ../../../flutter/shell/platform/embedder/embedder_platform_message_response.h FILE: ../../../flutter/shell/platform/embedder/embedder_render_target.cc From 8d1f18f372b11dee3fd13432c191e54dd78a6224 Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Wed, 12 Jan 2022 13:02:30 -0800 Subject: [PATCH 09/17] Rename FlutterEngineMapping to FlutterMapping --- shell/platform/embedder/embedder.cc | 6 ++--- shell/platform/embedder/embedder.h | 24 +++++++++---------- .../embedder/embedder_asset_resolver.cc | 2 +- shell/platform/embedder/embedder_mapping.cc | 2 +- shell/platform/embedder/embedder_mapping.h | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index dcfbcee9a83bf..7a2d0e00933b8 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -2384,15 +2384,15 @@ FlutterEngineResult FlutterEngineNotifyDisplayUpdate( } FlutterEngineResult FlutterEngineCreateMapping( - const FlutterEngineMappingCreateInfo* create_info, - FlutterEngineMapping* out_mapping) { + const FlutterMappingCreateInfo* create_info, + FlutterMapping* out_mapping) { if (SAFE_ACCESS(create_info, data, nullptr) == nullptr && SAFE_ACCESS(create_info, data_size, 0) > 0) { return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid mapping specified."); } auto mapping = flutter::CreateEmbedderMapping(create_info); - *out_mapping = reinterpret_cast(mapping.release()); + *out_mapping = reinterpret_cast(mapping.release()); return kSuccess; } diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index 256621144a906..330f37ad48b82 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -1347,7 +1347,7 @@ typedef struct _FlutterEngineAOTData* FlutterEngineAOTData; /// An immutable buffer of potentially shared data. typedef struct { - /// The size of the struct. Must be sizeof(FlutterEngineMapping). + /// The size of the struct. Must be sizeof(FlutterMapping). size_t struct_size; /// A pointer to the data accessed by the Flutter Engine. The data will not be @@ -1367,9 +1367,9 @@ typedef struct { /// mutate/free/unmap the data, as it will no longer be accessed by the /// Flutter Engine. VoidCallback destruction_callback; -} FlutterEngineMappingCreateInfo; +} FlutterMappingCreateInfo; -typedef struct FlutterEngineMappingPrivate* FlutterEngineMapping; +typedef struct FlutterMappingPrivate* FlutterMapping; /// Callback for fetching assets for a `FlutterEngineAssetResolver`. /// @@ -1380,14 +1380,14 @@ typedef struct FlutterEngineMappingPrivate* FlutterEngineMapping; /// via `FlutterProjectArgs`. /// /// If the asset was found and successfully loaded, return a valid -/// `FlutterEngineMapping`. Otherwise return NULL to indicate an error occurred +/// `FlutterMapping`. Otherwise return NULL to indicate an error occurred /// while loading the asset. /// -/// Note that the returned `FlutterEngineMapping` is owned by the Engine and +/// Note that the returned `FlutterMapping` is owned by the Engine and /// should be cached or reused. Each callback invocation must return a new -/// FlutterEngineMapping. Multiple mappings may refer to the same area in +/// FlutterMapping. Multiple mappings may refer to the same area in /// memory, proper book-keeping is up to the embedder. -typedef FlutterEngineMapping (*FlutterAssetResolverGetAssetCallback)( +typedef FlutterMapping (*FlutterAssetResolverGetAssetCallback)( const char* /* asset_name */, void* /* user_data */); @@ -2330,7 +2330,7 @@ FlutterEngineResult FlutterEngineNotifyDisplayUpdate( size_t display_count); //------------------------------------------------------------------------------ -/// @brief Creates a `FlutterEngineMapping` using the given creation info. +/// @brief Creates a `FlutterMapping` using the given creation info. /// The backing memory is never mutated by the Engine, and must not /// be mutated by the embedder until the mapping is destroyed. /// The engine may access the mapping from multiple threads, and may @@ -2343,8 +2343,8 @@ FlutterEngineResult FlutterEngineNotifyDisplayUpdate( /// FLUTTER_EXPORT FlutterEngineResult FlutterEngineCreateMapping( - const FlutterEngineMappingCreateInfo* create_info, - FlutterEngineMapping* out_mapping); + const FlutterMappingCreateInfo* create_info, + FlutterMapping* out_mapping); #endif // !FLUTTER_ENGINE_NO_PROTOTYPES @@ -2463,8 +2463,8 @@ typedef FlutterEngineResult (*FlutterEngineNotifyDisplayUpdateFnPtr)( const FlutterEngineDisplay* displays, size_t display_count); typedef FlutterEngineResult (*FlutterEngineCreateMappingFnPtr)( - const FlutterEngineMappingCreateInfo* create_info, - FlutterEngineMapping* out_mapping); + const FlutterMappingCreateInfo* create_info, + FlutterMapping* out_mapping); /// Function-pointer-based versions of the APIs above. typedef struct { diff --git a/shell/platform/embedder/embedder_asset_resolver.cc b/shell/platform/embedder/embedder_asset_resolver.cc index 191b35e6fc378..ea960c0c20b63 100644 --- a/shell/platform/embedder/embedder_asset_resolver.cc +++ b/shell/platform/embedder/embedder_asset_resolver.cc @@ -33,7 +33,7 @@ class EmbedderAssetResolver final : public flutter::AssetResolver { return std::unique_ptr(); } - FlutterEngineMapping mapping = get_asset_(asset_name.c_str(), user_data_); + FlutterMapping mapping = get_asset_(asset_name.c_str(), user_data_); return std::unique_ptr( reinterpret_cast(mapping)); } diff --git a/shell/platform/embedder/embedder_mapping.cc b/shell/platform/embedder/embedder_mapping.cc index ec6e981668cc6..e8ceb19dcb33a 100644 --- a/shell/platform/embedder/embedder_mapping.cc +++ b/shell/platform/embedder/embedder_mapping.cc @@ -42,7 +42,7 @@ class EmbedderMapping final : public fml::Mapping { }; std::unique_ptr CreateEmbedderMapping( - const FlutterEngineMappingCreateInfo* mapping) { + const FlutterMappingCreateInfo* mapping) { return std::make_unique( SAFE_ACCESS(mapping, data, nullptr), SAFE_ACCESS(mapping, data_size, 0), SAFE_ACCESS(mapping, user_data, nullptr), diff --git a/shell/platform/embedder/embedder_mapping.h b/shell/platform/embedder/embedder_mapping.h index 0ff69b603d03b..ec6eddaadc6e2 100644 --- a/shell/platform/embedder/embedder_mapping.h +++ b/shell/platform/embedder/embedder_mapping.h @@ -11,7 +11,7 @@ namespace flutter { std::unique_ptr CreateEmbedderMapping( - const FlutterEngineMappingCreateInfo* mapping); + const FlutterMappingCreateInfo* mapping); } // namespace flutter From dbae453ab8f4126dacbd7d1c0ec236cf2c384895 Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Thu, 13 Jan 2022 12:28:19 -0800 Subject: [PATCH 10/17] Add DestroyMapping and GetMappingData, improve docs --- shell/platform/embedder/embedder.cc | 12 +++++ shell/platform/embedder/embedder.h | 56 ++++++++++++++++++--- shell/platform/embedder/embedder_mapping.cc | 6 +-- 3 files changed, 64 insertions(+), 10 deletions(-) diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index 7a2d0e00933b8..acec04d6264ab 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -2397,6 +2397,16 @@ FlutterEngineResult FlutterEngineCreateMapping( return kSuccess; } +void FlutterEngineDestroyMapping(FlutterMapping mapping) { + delete reinterpret_cast(mapping); +} + +const uint8_t* FlutterEngineGetMappingData(FlutterMapping mapping, size_t* out_size) { + auto fml_mapping = reinterpret_cast(mapping); + if (out_size != nullptr) *out_size = fml_mapping->GetSize(); + return fml_mapping->GetMapping(); +} + FlutterEngineResult FlutterEngineGetProcAddresses( FlutterEngineProcTable* table) { if (!table) { @@ -2448,6 +2458,8 @@ FlutterEngineResult FlutterEngineGetProcAddresses( FlutterEnginePostCallbackOnAllNativeThreads); SET_PROC(NotifyDisplayUpdate, FlutterEngineNotifyDisplayUpdate); SET_PROC(CreateMapping, FlutterEngineCreateMapping); + SET_PROC(DestroyMapping, FlutterEngineDestroyMapping); + SET_PROC(GetMappingData, FlutterEngineGetMappingData); #undef SET_PROC return kSuccess; diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index 330f37ad48b82..b868bf303a038 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -1345,6 +1345,16 @@ typedef void (*FlutterLogMessageCallback)(const char* /* tag */, /// FlutterEngine instance in AOT mode. typedef struct _FlutterEngineAOTData* FlutterEngineAOTData; +// Callback called by the Engine to destroy a previously created FlutterMapping. +// +// The callback may be called on any thread, so it must be thread-safe. +// +// The `data`, `data_size`, and `user_data` parameters are the same values passed +// in `FlutterEngineCreateMapping`. +typedef void (*FlutterMappingDestroyCallback)(const uint8_t* /* data */, + size_t /* data_size */, + void* /* user_data */); + /// An immutable buffer of potentially shared data. typedef struct { /// The size of the struct. Must be sizeof(FlutterMapping). @@ -1362,11 +1372,11 @@ typedef struct { /// An opaque baton passed back to the embedder when the destruction_callback /// is invoked. The engine does not interpret this field in any way. void* user_data; - /// Called once by the engine to destroy this mapping. The `user_data` - /// specified above is passed in as the only argument. This call may + /// Called once by the engine to destroy this mapping. The `data`, `data_size`, + /// and `user_data` are passed into the given callback. This call may /// mutate/free/unmap the data, as it will no longer be accessed by the /// Flutter Engine. - VoidCallback destruction_callback; + FlutterMappingDestroyCallback destruction_callback; } FlutterMappingCreateInfo; typedef struct FlutterMappingPrivate* FlutterMapping; @@ -1384,9 +1394,9 @@ typedef struct FlutterMappingPrivate* FlutterMapping; /// while loading the asset. /// /// Note that the returned `FlutterMapping` is owned by the Engine and -/// should be cached or reused. Each callback invocation must return a new +/// shouldn't be cached or reused. Each callback invocation MUST return a new /// FlutterMapping. Multiple mappings may refer to the same area in -/// memory, proper book-keeping is up to the embedder. +/// memory, but proper book-keeping is up to the Embedder. typedef FlutterMapping (*FlutterAssetResolverGetAssetCallback)( const char* /* asset_name */, void* /* user_data */); @@ -2331,9 +2341,14 @@ FlutterEngineResult FlutterEngineNotifyDisplayUpdate( //------------------------------------------------------------------------------ /// @brief Creates a `FlutterMapping` using the given creation info. +/// The returned mapping is owned by the Embedder until passed to the +/// Engine. +/// +/// When owned by the Engine: +/// /// The backing memory is never mutated by the Engine, and must not -/// be mutated by the embedder until the mapping is destroyed. -/// The engine may access the mapping from multiple threads, and may +/// be mutated by the Embedder until the mapping is destroyed. +/// The Engine may access the mapping from multiple threads, and may /// destroy the mapping from any thread. /// /// @param[in] create_info Struct describing the mapping to create. @@ -2346,6 +2361,29 @@ FlutterEngineResult FlutterEngineCreateMapping( const FlutterMappingCreateInfo* create_info, FlutterMapping* out_mapping); +//------------------------------------------------------------------------------ +/// @brief Destroys a `FlutterMapping` owned by the Embedder. +/// This may be called by any thread, as long as the Engine doesn't +/// own the mapping. +/// +/// @param[in] mapping The mapping owned by the Embedder to destroy. +/// +FLUTTER_EXPORT +void FlutterEngineDestroyMapping(FlutterMapping mapping); + +//------------------------------------------------------------------------------ +/// @brief Gets the data and size of a `FlutterMapping`. +/// The mapping must be owned by the Embedder. +/// +/// @param[in] mapping The mapping to get the data and size of. +/// @param[out] out_size Returns the mapping's size, if provided. +/// May be NULL. +/// +/// @return The address to the mapping's data. +/// +FLUTTER_EXPORT +const uint8_t* FlutterEngineGetMappingData(FlutterMapping mapping, size_t* out_size); + #endif // !FLUTTER_ENGINE_NO_PROTOTYPES // Typedefs for the function pointers in FlutterEngineProcTable. @@ -2465,6 +2503,8 @@ typedef FlutterEngineResult (*FlutterEngineNotifyDisplayUpdateFnPtr)( typedef FlutterEngineResult (*FlutterEngineCreateMappingFnPtr)( const FlutterMappingCreateInfo* create_info, FlutterMapping* out_mapping); +typedef void (*FlutterEngineDestroyMappingFnPtr)(FlutterMapping mapping); +typedef const uint8_t* (*FlutterEngineGetMappingDataFnPtr)(FlutterMapping mapping, size_t* out_size); /// Function-pointer-based versions of the APIs above. typedef struct { @@ -2510,6 +2550,8 @@ typedef struct { PostCallbackOnAllNativeThreads; FlutterEngineNotifyDisplayUpdateFnPtr NotifyDisplayUpdate; FlutterEngineCreateMappingFnPtr CreateMapping; + FlutterEngineDestroyMappingFnPtr DestroyMapping; + FlutterEngineGetMappingDataFnPtr GetMappingData; } FlutterEngineProcTable; //------------------------------------------------------------------------------ diff --git a/shell/platform/embedder/embedder_mapping.cc b/shell/platform/embedder/embedder_mapping.cc index e8ceb19dcb33a..56ec35fde6f7c 100644 --- a/shell/platform/embedder/embedder_mapping.cc +++ b/shell/platform/embedder/embedder_mapping.cc @@ -12,7 +12,7 @@ class EmbedderMapping final : public fml::Mapping { EmbedderMapping(const uint8_t* data, size_t size, void* user_data, - VoidCallback destruction_callback) + FlutterMappingDestroyCallback destruction_callback) : data_(data), size_(size), user_data_(user_data), @@ -20,7 +20,7 @@ class EmbedderMapping final : public fml::Mapping { ~EmbedderMapping() override { if (destruction_callback_) - destruction_callback_(user_data_); + destruction_callback_(data_, size_, user_data_); } // |Mapping| @@ -36,7 +36,7 @@ class EmbedderMapping final : public fml::Mapping { const uint8_t* data_; size_t size_; void* user_data_; - VoidCallback destruction_callback_; + FlutterMappingDestroyCallback destruction_callback_; FML_DISALLOW_COPY_AND_ASSIGN(EmbedderMapping); }; From 775ecf5bd260876fa60ee16d3af6931ad1db042f Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Thu, 13 Jan 2022 12:30:54 -0800 Subject: [PATCH 11/17] Update formatting --- shell/platform/embedder/embedder.cc | 6 ++++-- shell/platform/embedder/embedder.h | 25 ++++++++++++++----------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index acec04d6264ab..b359a650aa63a 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -2401,9 +2401,11 @@ void FlutterEngineDestroyMapping(FlutterMapping mapping) { delete reinterpret_cast(mapping); } -const uint8_t* FlutterEngineGetMappingData(FlutterMapping mapping, size_t* out_size) { +const uint8_t* FlutterEngineGetMappingData(FlutterMapping mapping, + size_t* out_size) { auto fml_mapping = reinterpret_cast(mapping); - if (out_size != nullptr) *out_size = fml_mapping->GetSize(); + if (out_size != nullptr) + *out_size = fml_mapping->GetSize(); return fml_mapping->GetMapping(); } diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index b868bf303a038..6a2e2655defe7 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -1349,8 +1349,8 @@ typedef struct _FlutterEngineAOTData* FlutterEngineAOTData; // // The callback may be called on any thread, so it must be thread-safe. // -// The `data`, `data_size`, and `user_data` parameters are the same values passed -// in `FlutterEngineCreateMapping`. +// The `data`, `data_size`, and `user_data` parameters are the same values +// passed in `FlutterEngineCreateMapping`. typedef void (*FlutterMappingDestroyCallback)(const uint8_t* /* data */, size_t /* data_size */, void* /* user_data */); @@ -1372,9 +1372,9 @@ typedef struct { /// An opaque baton passed back to the embedder when the destruction_callback /// is invoked. The engine does not interpret this field in any way. void* user_data; - /// Called once by the engine to destroy this mapping. The `data`, `data_size`, - /// and `user_data` are passed into the given callback. This call may - /// mutate/free/unmap the data, as it will no longer be accessed by the + /// Called once by the engine to destroy this mapping. The `data`, + /// `data_size`, and `user_data` are passed into the given callback. This call + /// may mutate/free/unmap the data, as it will no longer be accessed by the /// Flutter Engine. FlutterMappingDestroyCallback destruction_callback; } FlutterMappingCreateInfo; @@ -2341,11 +2341,11 @@ FlutterEngineResult FlutterEngineNotifyDisplayUpdate( //------------------------------------------------------------------------------ /// @brief Creates a `FlutterMapping` using the given creation info. -/// The returned mapping is owned by the Embedder until passed to the -/// Engine. -/// +/// The returned mapping is owned by the Embedder until passed to +/// the Engine. +/// /// When owned by the Engine: -/// +/// /// The backing memory is never mutated by the Engine, and must not /// be mutated by the Embedder until the mapping is destroyed. /// The Engine may access the mapping from multiple threads, and may @@ -2382,7 +2382,8 @@ void FlutterEngineDestroyMapping(FlutterMapping mapping); /// @return The address to the mapping's data. /// FLUTTER_EXPORT -const uint8_t* FlutterEngineGetMappingData(FlutterMapping mapping, size_t* out_size); +const uint8_t* FlutterEngineGetMappingData(FlutterMapping mapping, + size_t* out_size); #endif // !FLUTTER_ENGINE_NO_PROTOTYPES @@ -2504,7 +2505,9 @@ typedef FlutterEngineResult (*FlutterEngineCreateMappingFnPtr)( const FlutterMappingCreateInfo* create_info, FlutterMapping* out_mapping); typedef void (*FlutterEngineDestroyMappingFnPtr)(FlutterMapping mapping); -typedef const uint8_t* (*FlutterEngineGetMappingDataFnPtr)(FlutterMapping mapping, size_t* out_size); +typedef const uint8_t* (*FlutterEngineGetMappingDataFnPtr)( + FlutterMapping mapping, + size_t* out_size); /// Function-pointer-based versions of the APIs above. typedef struct { From ae18e7e6610ac25d322832b786638da752e368df Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Thu, 13 Jan 2022 12:42:38 -0800 Subject: [PATCH 12/17] Use NonOwnedMapping instead of subclass --- shell/platform/embedder/embedder_mapping.cc | 46 ++++----------------- 1 file changed, 9 insertions(+), 37 deletions(-) diff --git a/shell/platform/embedder/embedder_mapping.cc b/shell/platform/embedder/embedder_mapping.cc index 56ec35fde6f7c..2c627ba26a87b 100644 --- a/shell/platform/embedder/embedder_mapping.cc +++ b/shell/platform/embedder/embedder_mapping.cc @@ -7,46 +7,18 @@ namespace flutter { -class EmbedderMapping final : public fml::Mapping { - public: - EmbedderMapping(const uint8_t* data, - size_t size, - void* user_data, - FlutterMappingDestroyCallback destruction_callback) - : data_(data), - size_(size), - user_data_(user_data), - destruction_callback_(destruction_callback) {} - - ~EmbedderMapping() override { - if (destruction_callback_) - destruction_callback_(data_, size_, user_data_); - } - - // |Mapping| - size_t GetSize() const override { return size_; } - - // |Mapping| - const uint8_t* GetMapping() const override { return data_; } - - // |Mapping| - bool IsDontNeedSafe() const override { return false; } - - private: - const uint8_t* data_; - size_t size_; - void* user_data_; - FlutterMappingDestroyCallback destruction_callback_; - - FML_DISALLOW_COPY_AND_ASSIGN(EmbedderMapping); -}; - std::unique_ptr CreateEmbedderMapping( const FlutterMappingCreateInfo* mapping) { - return std::make_unique( + auto user_data = SAFE_ACCESS(mapping, user_data, nullptr); + auto destruction_callback = + SAFE_ACCESS(mapping, destruction_callback, nullptr); + return std::make_unique( SAFE_ACCESS(mapping, data, nullptr), SAFE_ACCESS(mapping, data_size, 0), - SAFE_ACCESS(mapping, user_data, nullptr), - SAFE_ACCESS(mapping, destruction_callback, nullptr)); + [user_data, destruction_callback](const uint8_t* data, size_t size) { + if (destruction_callback) { + destruction_callback(data, size, user_data); + } + }); } } // namespace flutter From b37a1a13721f1c54c48d3a3d020ed3c978f46113 Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Tue, 18 Jan 2022 14:32:19 -0800 Subject: [PATCH 13/17] Remove embedder_mapping.cc --- shell/platform/embedder/BUILD.gn | 2 -- shell/platform/embedder/embedder.cc | 19 ++++++++++++---- shell/platform/embedder/embedder.h | 2 +- shell/platform/embedder/embedder_mapping.cc | 24 --------------------- shell/platform/embedder/embedder_mapping.h | 18 ---------------- 5 files changed, 16 insertions(+), 49 deletions(-) delete mode 100644 shell/platform/embedder/embedder_mapping.cc delete mode 100644 shell/platform/embedder/embedder_mapping.h diff --git a/shell/platform/embedder/BUILD.gn b/shell/platform/embedder/BUILD.gn index aacf0f2aafdc6..9caf914af3a08 100644 --- a/shell/platform/embedder/BUILD.gn +++ b/shell/platform/embedder/BUILD.gn @@ -46,8 +46,6 @@ template("embedder_source_set") { "embedder_include2.c", "embedder_layers.cc", "embedder_layers.h", - "embedder_mapping.cc", - "embedder_mapping.h", "embedder_platform_message_response.cc", "embedder_platform_message_response.h", "embedder_render_target.cc", diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index b359a650aa63a..22cd912142e19 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -50,7 +50,6 @@ extern const intptr_t kPlatformStrongDillSize; #include "flutter/shell/platform/embedder/embedder_asset_resolver.h" #include "flutter/shell/platform/embedder/embedder_engine.h" #include "flutter/shell/platform/embedder/embedder_external_texture_resolver.h" -#include "flutter/shell/platform/embedder/embedder_mapping.h" #include "flutter/shell/platform/embedder/embedder_platform_message_response.h" #include "flutter/shell/platform/embedder/embedder_render_target.h" #include "flutter/shell/platform/embedder/embedder_struct_macros.h" @@ -2386,12 +2385,24 @@ FlutterEngineResult FlutterEngineNotifyDisplayUpdate( FlutterEngineResult FlutterEngineCreateMapping( const FlutterMappingCreateInfo* create_info, FlutterMapping* out_mapping) { - if (SAFE_ACCESS(create_info, data, nullptr) == nullptr && - SAFE_ACCESS(create_info, data_size, 0) > 0) { + auto data = SAFE_ACCESS(create_info, data, nullptr); + auto data_size = SAFE_ACCESS(create_info, data_size, 0); + if (data == nullptr && data_size > 0) { return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid mapping specified."); } - auto mapping = flutter::CreateEmbedderMapping(create_info); + auto user_data = SAFE_ACCESS(create_info, user_data, nullptr); + auto destruction_callback = + SAFE_ACCESS(create_info, destruction_callback, nullptr); + + auto mapping = std::make_unique( + data, data_size, + [user_data, destruction_callback](const uint8_t* data, size_t size) { + if (destruction_callback) { + destruction_callback(data, size, user_data); + } + }); + *out_mapping = reinterpret_cast(mapping.release()); return kSuccess; diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index 6a2e2655defe7..bbd251a1fb598 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -1357,7 +1357,7 @@ typedef void (*FlutterMappingDestroyCallback)(const uint8_t* /* data */, /// An immutable buffer of potentially shared data. typedef struct { - /// The size of the struct. Must be sizeof(FlutterMapping). + /// The size of the struct. Must be sizeof(FlutterMappingCreateInfo). size_t struct_size; /// A pointer to the data accessed by the Flutter Engine. The data will not be diff --git a/shell/platform/embedder/embedder_mapping.cc b/shell/platform/embedder/embedder_mapping.cc deleted file mode 100644 index 2c627ba26a87b..0000000000000 --- a/shell/platform/embedder/embedder_mapping.cc +++ /dev/null @@ -1,24 +0,0 @@ -// 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/shell/platform/embedder/embedder_mapping.h" -#include "flutter/shell/platform/embedder/embedder_struct_macros.h" - -namespace flutter { - -std::unique_ptr CreateEmbedderMapping( - const FlutterMappingCreateInfo* mapping) { - auto user_data = SAFE_ACCESS(mapping, user_data, nullptr); - auto destruction_callback = - SAFE_ACCESS(mapping, destruction_callback, nullptr); - return std::make_unique( - SAFE_ACCESS(mapping, data, nullptr), SAFE_ACCESS(mapping, data_size, 0), - [user_data, destruction_callback](const uint8_t* data, size_t size) { - if (destruction_callback) { - destruction_callback(data, size, user_data); - } - }); -} - -} // namespace flutter diff --git a/shell/platform/embedder/embedder_mapping.h b/shell/platform/embedder/embedder_mapping.h deleted file mode 100644 index ec6eddaadc6e2..0000000000000 --- a/shell/platform/embedder/embedder_mapping.h +++ /dev/null @@ -1,18 +0,0 @@ -// 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 FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_MAPPING_H_ -#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_MAPPING_H_ - -#include "flutter/fml/mapping.h" -#include "flutter/shell/platform/embedder/embedder.h" - -namespace flutter { - -std::unique_ptr CreateEmbedderMapping( - const FlutterMappingCreateInfo* mapping); - -} // namespace flutter - -#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_MAPPING_H_ From 558803ef9b35da565a3e91a07bc3c3d1a3c02c5f Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Wed, 19 Jan 2022 11:35:18 -0800 Subject: [PATCH 14/17] Use callback for embedder asset resolver --- shell/platform/embedder/embedder.cc | 16 +++++++++++++++- .../embedder/embedder_asset_resolver.cc | 17 ++++++----------- .../platform/embedder/embedder_asset_resolver.h | 6 +++++- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index 22cd912142e19..0b8376ef1d495 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -1305,8 +1305,22 @@ FlutterEngineResult FlutterEngineInitialize(size_t version, auto asset_manager = std::make_shared(); if (SAFE_ACCESS(args, asset_resolver, nullptr) != nullptr) { + auto resolver = args->asset_resolver; + + auto user_data = SAFE_ACCESS(resolver, user_data, nullptr); + auto get_asset = SAFE_ACCESS(resolver, get_asset, nullptr); + + if (get_asset == nullptr) { + return LOG_EMBEDDER_ERROR(kInvalidArguments, + "Asset Resolver get_asset is null."); + } + asset_manager->PushBack( - flutter::CreateEmbedderAssetResolver(args->asset_resolver)); + flutter::CreateEmbedderAssetResolver([=](const char* asset_name) { + FlutterMapping mapping = get_asset(asset_name, user_data); + return std::unique_ptr( + reinterpret_cast(mapping)); + })); } if (args->assets_path) { diff --git a/shell/platform/embedder/embedder_asset_resolver.cc b/shell/platform/embedder/embedder_asset_resolver.cc index ea960c0c20b63..46d2695848bb7 100644 --- a/shell/platform/embedder/embedder_asset_resolver.cc +++ b/shell/platform/embedder/embedder_asset_resolver.cc @@ -9,9 +9,8 @@ namespace flutter { class EmbedderAssetResolver final : public flutter::AssetResolver { public: - explicit EmbedderAssetResolver(void* user_data, - FlutterAssetResolverGetAssetCallback get_asset) - : user_data_(user_data), get_asset_(get_asset) {} + explicit EmbedderAssetResolver(EmbedderAssetResolverGetAsset get_asset) + : get_asset_(get_asset) {} ~EmbedderAssetResolver() override {} @@ -33,23 +32,19 @@ class EmbedderAssetResolver final : public flutter::AssetResolver { return std::unique_ptr(); } - FlutterMapping mapping = get_asset_(asset_name.c_str(), user_data_); - return std::unique_ptr( - reinterpret_cast(mapping)); + return get_asset_(asset_name.c_str()); } private: - void* user_data_; - FlutterAssetResolverGetAssetCallback get_asset_; + EmbedderAssetResolverGetAsset get_asset_; FML_DISALLOW_COPY_AND_ASSIGN(EmbedderAssetResolver); }; std::unique_ptr CreateEmbedderAssetResolver( - const FlutterEngineAssetResolver* resolver) { + EmbedderAssetResolverGetAsset get_asset) { return std::make_unique( - SAFE_ACCESS(resolver, user_data, nullptr), - SAFE_ACCESS(resolver, get_asset, nullptr)); + std::move(get_asset)); } } // namespace flutter diff --git a/shell/platform/embedder/embedder_asset_resolver.h b/shell/platform/embedder/embedder_asset_resolver.h index 34edd86bfdcf1..8b7609792905d 100644 --- a/shell/platform/embedder/embedder_asset_resolver.h +++ b/shell/platform/embedder/embedder_asset_resolver.h @@ -5,13 +5,17 @@ #ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_ASSET_RESOLVER_H_ #define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_ASSET_RESOLVER_H_ +#include + #include "flutter/assets/asset_resolver.h" #include "flutter/shell/platform/embedder/embedder.h" namespace flutter { +using EmbedderAssetResolverGetAsset = std::function(const char* /* asset_name */)>; + std::unique_ptr CreateEmbedderAssetResolver( - const FlutterEngineAssetResolver* resolver); + EmbedderAssetResolverGetAsset get_asset); } // namespace flutter From 726a752daaf0c8ba14b2b19922bfd133230e2c9e Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Wed, 19 Jan 2022 11:37:54 -0800 Subject: [PATCH 15/17] Fix test --- shell/platform/embedder/tests/embedder_unittests.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/shell/platform/embedder/tests/embedder_unittests.cc b/shell/platform/embedder/tests/embedder_unittests.cc index 89efc60c76b1d..84fee78df70a0 100644 --- a/shell/platform/embedder/tests/embedder_unittests.cc +++ b/shell/platform/embedder/tests/embedder_unittests.cc @@ -489,18 +489,18 @@ TEST_F(EmbedderTest, CustomAssetResolverReturnsValidAsset) { resolver.struct_size = sizeof(FlutterEngineAssetResolver); resolver.user_data = reinterpret_cast(&destroy); resolver.get_asset = [](const char* asset, - void* user_data) -> FlutterEngineMapping { + void* user_data) -> FlutterMapping { if (strcmp(asset, "existing_asset") == 0) { // Return an asset with the string "hello" as its contents. // When the mapping is destroyed (on GC or Engine shutdown) the // `destroy` event is signaled. - FlutterEngineMappingCreateInfo create_info = {}; - FlutterEngineMapping out = nullptr; - create_info.struct_size = sizeof(FlutterEngineMappingCreateInfo); + FlutterMappingCreateInfo create_info = {}; + FlutterMapping out = nullptr; + create_info.struct_size = sizeof(FlutterMappingCreateInfo); create_info.data = reinterpret_cast("hello"); create_info.data_size = 5; create_info.user_data = user_data; - create_info.destruction_callback = [](void* user_data) { + create_info.destruction_callback = [](const uint8_t* data, size_t size, void* user_data) { reinterpret_cast(user_data)->Signal(); }; auto result = FlutterEngineCreateMapping(&create_info, &out); @@ -552,7 +552,7 @@ TEST_F(EmbedderTest, CustomAssetResolverReturnsInvalidAsset) { FlutterEngineAssetResolver resolver = {}; resolver.struct_size = sizeof(FlutterEngineAssetResolver); resolver.get_asset = [](const char* asset, - void* user_data) -> FlutterEngineMapping { + void* user_data) -> FlutterMapping { return nullptr; }; From cafb95de5fe73aaea009f60cd24e77b4b089e046 Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Wed, 19 Jan 2022 12:03:03 -0800 Subject: [PATCH 16/17] Fix and format --- shell/platform/embedder/embedder.cc | 2 +- shell/platform/embedder/embedder_asset_resolver.cc | 9 ++++----- shell/platform/embedder/embedder_asset_resolver.h | 3 ++- shell/platform/embedder/tests/embedder_unittests.cc | 3 ++- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index 0b8376ef1d495..c7f8c1fa6f030 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -1319,7 +1319,7 @@ FlutterEngineResult FlutterEngineInitialize(size_t version, flutter::CreateEmbedderAssetResolver([=](const char* asset_name) { FlutterMapping mapping = get_asset(asset_name, user_data); return std::unique_ptr( - reinterpret_cast(mapping)); + reinterpret_cast(mapping)); })); } diff --git a/shell/platform/embedder/embedder_asset_resolver.cc b/shell/platform/embedder/embedder_asset_resolver.cc index 46d2695848bb7..6000f06e3ce12 100644 --- a/shell/platform/embedder/embedder_asset_resolver.cc +++ b/shell/platform/embedder/embedder_asset_resolver.cc @@ -12,10 +12,10 @@ class EmbedderAssetResolver final : public flutter::AssetResolver { explicit EmbedderAssetResolver(EmbedderAssetResolverGetAsset get_asset) : get_asset_(get_asset) {} - ~EmbedderAssetResolver() override {} + ~EmbedderAssetResolver() = default; // |AssetResolver| - bool IsValid() const override { return true; } + bool IsValid() const override { return (bool)get_asset_; } // |AssetResolver| bool IsValidAfterAssetManagerChange() const override { return true; } @@ -29,7 +29,7 @@ class EmbedderAssetResolver final : public flutter::AssetResolver { std::unique_ptr GetAsMapping( const std::string& asset_name) const override { if (!get_asset_) { - return std::unique_ptr(); + return nullptr; } return get_asset_(asset_name.c_str()); @@ -43,8 +43,7 @@ class EmbedderAssetResolver final : public flutter::AssetResolver { std::unique_ptr CreateEmbedderAssetResolver( EmbedderAssetResolverGetAsset get_asset) { - return std::make_unique( - std::move(get_asset)); + return std::make_unique(std::move(get_asset)); } } // namespace flutter diff --git a/shell/platform/embedder/embedder_asset_resolver.h b/shell/platform/embedder/embedder_asset_resolver.h index 8b7609792905d..df73ee8baad25 100644 --- a/shell/platform/embedder/embedder_asset_resolver.h +++ b/shell/platform/embedder/embedder_asset_resolver.h @@ -12,7 +12,8 @@ namespace flutter { -using EmbedderAssetResolverGetAsset = std::function(const char* /* asset_name */)>; +using EmbedderAssetResolverGetAsset = + std::function(const char* /* asset_name */)>; std::unique_ptr CreateEmbedderAssetResolver( EmbedderAssetResolverGetAsset get_asset); diff --git a/shell/platform/embedder/tests/embedder_unittests.cc b/shell/platform/embedder/tests/embedder_unittests.cc index 84fee78df70a0..390d017b45708 100644 --- a/shell/platform/embedder/tests/embedder_unittests.cc +++ b/shell/platform/embedder/tests/embedder_unittests.cc @@ -500,7 +500,8 @@ TEST_F(EmbedderTest, CustomAssetResolverReturnsValidAsset) { create_info.data = reinterpret_cast("hello"); create_info.data_size = 5; create_info.user_data = user_data; - create_info.destruction_callback = [](const uint8_t* data, size_t size, void* user_data) { + create_info.destruction_callback = [](const uint8_t* data, size_t size, + void* user_data) { reinterpret_cast(user_data)->Signal(); }; auto result = FlutterEngineCreateMapping(&create_info, &out); From e5bef6e4f9d63e634be74b108b5eaf6a37a1303f Mon Sep 17 00:00:00 2001 From: Dwayne Slater Date: Wed, 19 Jan 2022 14:12:53 -0800 Subject: [PATCH 17/17] Update generated licenses --- ci/licenses_golden/licenses_flutter | 2 -- 1 file changed, 2 deletions(-) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 88bc5d164105f..70aa98611bd53 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1314,8 +1314,6 @@ FILE: ../../../flutter/shell/platform/embedder/embedder_include.c FILE: ../../../flutter/shell/platform/embedder/embedder_include2.c FILE: ../../../flutter/shell/platform/embedder/embedder_layers.cc FILE: ../../../flutter/shell/platform/embedder/embedder_layers.h -FILE: ../../../flutter/shell/platform/embedder/embedder_mapping.cc -FILE: ../../../flutter/shell/platform/embedder/embedder_mapping.h FILE: ../../../flutter/shell/platform/embedder/embedder_platform_message_response.cc FILE: ../../../flutter/shell/platform/embedder/embedder_platform_message_response.h FILE: ../../../flutter/shell/platform/embedder/embedder_render_target.cc