-
Notifications
You must be signed in to change notification settings - Fork 6k
Preserve specified AssetResolvers when performing a hot restart or updating the asset directory #21611
Preserve specified AssetResolvers when performing a hot restart or updating the asset directory #21611
Changes from 6 commits
ff717e6
bfa9783
13fb0c1
6810d05
4bfc73a
27b200a
5a4d2ab
980ecb7
2e94df6
5f920da
9a8269f
c336ec7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,17 @@ class AssetResolver { | |
|
|
||
| virtual bool IsValid() const = 0; | ||
|
|
||
| //---------------------------------------------------------------------------- | ||
| /// @brief Certain asset resolvers need to be preserved when the asset | ||
| /// directory is updated or the isolate recreated. While some | ||
| /// could be recated from the settings object, the Android | ||
| /// specific asset resolvers require a reference to the JNI to | ||
| /// create. | ||
| /// | ||
| /// @return Returns whether this resolver should be preserved. | ||
| /// | ||
| virtual bool ShouldPreserve() const = 0; | ||
|
||
|
|
||
| [[nodiscard]] virtual std::unique_ptr<fml::Mapping> GetAsMapping( | ||
| const std::string& asset_name) const = 0; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,11 +12,13 @@ | |
|
|
||
| namespace flutter { | ||
|
|
||
| DirectoryAssetBundle::DirectoryAssetBundle(fml::UniqueFD descriptor) | ||
| DirectoryAssetBundle::DirectoryAssetBundle(fml::UniqueFD descriptor, | ||
| bool should_preserve) | ||
| : descriptor_(std::move(descriptor)) { | ||
| if (!fml::IsDirectory(descriptor_)) { | ||
| return; | ||
| } | ||
| should_preserve_ = should_preserve; | ||
| is_valid_ = true; | ||
| } | ||
|
|
||
|
|
@@ -27,6 +29,11 @@ bool DirectoryAssetBundle::IsValid() const { | |
| return is_valid_; | ||
| } | ||
|
|
||
| // |AssetResolver| | ||
| bool DirectoryAssetBundle::ShouldPreserve() const { | ||
| return should_preserve_; | ||
|
||
| } | ||
|
|
||
| // |AssetResolver| | ||
| std::unique_ptr<fml::Mapping> DirectoryAssetBundle::GetAsMapping( | ||
| const std::string& asset_name) const { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,17 +14,21 @@ namespace flutter { | |
|
|
||
| class DirectoryAssetBundle : public AssetResolver { | ||
| public: | ||
| explicit DirectoryAssetBundle(fml::UniqueFD descriptor); | ||
| explicit DirectoryAssetBundle(fml::UniqueFD descriptor, bool should_preserve); | ||
|
||
|
|
||
| ~DirectoryAssetBundle() override; | ||
|
|
||
| private: | ||
| const fml::UniqueFD descriptor_; | ||
| bool is_valid_ = false; | ||
| bool should_preserve_ = false; | ||
|
|
||
| // |AssetResolver| | ||
| bool IsValid() const override; | ||
|
|
||
| // |AssetResolver| | ||
| bool ShouldPreserve() const override; | ||
|
|
||
| // |AssetResolver| | ||
| std::unique_ptr<fml::Mapping> GetAsMapping( | ||
| const std::string& asset_name) const override; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1401,10 +1401,20 @@ bool Shell::OnServiceProtocolRunInView( | |
| configuration.SetEntrypointAndLibrary(engine_->GetLastEntrypoint(), | ||
| engine_->GetLastEntrypointLibrary()); | ||
|
|
||
| configuration.AddAssetResolver( | ||
| std::make_unique<DirectoryAssetBundle>(fml::OpenDirectory( | ||
| asset_directory_path.c_str(), false, fml::FilePermission::kRead))); | ||
| configuration.AddAssetResolver(RestoreOriginalAssetResolver()); | ||
| configuration.AddAssetResolver(std::make_unique<DirectoryAssetBundle>( | ||
| fml::OpenDirectory(asset_directory_path.c_str(), false, | ||
| fml::FilePermission::kRead), | ||
| false)); | ||
|
|
||
| // Preserve any original asset resolvers to avoid syncing unchanged assets | ||
| // over the DevFS connection. | ||
| auto old_resolvers = engine_->GetAssetManager()->TakeResolvers(); | ||
| for (uint64_t i = 0; i < old_resolvers.size(); i++) { | ||
|
||
| auto old_resolver = std::move(old_resolvers[i]); | ||
| if (old_resolver->ShouldPreserve()) { | ||
| configuration.AddAssetResolver(std::move(old_resolver)); | ||
| } | ||
| } | ||
|
|
||
| auto& allocator = response->GetAllocator(); | ||
| response->SetObject(); | ||
|
|
@@ -1517,10 +1527,20 @@ bool Shell::OnServiceProtocolSetAssetBundlePath( | |
|
|
||
| auto asset_manager = std::make_shared<AssetManager>(); | ||
|
|
||
| asset_manager->PushFront(RestoreOriginalAssetResolver()); | ||
| asset_manager->PushFront(std::make_unique<DirectoryAssetBundle>( | ||
| fml::OpenDirectory(params.at("assetDirectory").data(), false, | ||
| fml::FilePermission::kRead))); | ||
| fml::FilePermission::kRead), | ||
| false)); | ||
|
|
||
| // Preserve any original asset resolvers to avoid syncing unchanged assets | ||
| // over the DevFS connection. | ||
| auto old_resolvers = engine_->GetAssetManager()->TakeResolvers(); | ||
| for (uint64_t i = 0; i < old_resolvers.size(); i++) { | ||
|
||
| auto old_resolver = std::move(old_resolvers[i]); | ||
| if (old_resolver->ShouldPreserve()) { | ||
| asset_manager->PushBack(std::move(old_resolver)); | ||
| } | ||
| } | ||
|
|
||
| if (engine_->UpdateAssetManager(std::move(asset_manager))) { | ||
| response->AddMember("type", "Success", allocator); | ||
|
|
@@ -1624,16 +1644,4 @@ void Shell::OnDisplayUpdates(DisplayUpdateType update_type, | |
| display_manager_->HandleDisplayUpdates(update_type, displays); | ||
| } | ||
|
|
||
| // Add the original asset directory to the resolvers so that unmodified assets | ||
| // bundled with the application specific format (APK, IPA) can be used without | ||
| // syncing to the Dart devFS. | ||
| std::unique_ptr<DirectoryAssetBundle> Shell::RestoreOriginalAssetResolver() { | ||
| if (fml::UniqueFD::traits_type::IsValid(settings_.assets_dir)) { | ||
| return std::make_unique<DirectoryAssetBundle>( | ||
| fml::Duplicate(settings_.assets_dir)); | ||
| } | ||
| return std::make_unique<DirectoryAssetBundle>(fml::OpenDirectory( | ||
| settings_.assets_path.c_str(), false, fml::FilePermission::kRead)); | ||
| }; | ||
|
|
||
| } // namespace flutter | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No idea if this is reasonable :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure that this is correct because resolvers_ is an lvalue here.
This is behaviorally the same as making a copy of the deque and clearing the original, but the compiler should be able to optimize this to not do the copy now.
@jason-simmons or @chinmaygarde could verify that though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even with the copy, the most frequent number of elements seems to be 1, and with this change that will grow to 2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case I wasn't clear, this way of doing things avoids a copy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahh ... good, right :)