Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 3c0da65

Browse files
author
Jonah Williams
authored
Allow hot reload without syncing all asset files to devFS (#21436)
Always add the asset resolver from the configuration settings directory when restarting or recreating the asset manager
1 parent 69cbb2b commit 3c0da65

File tree

4 files changed

+84
-0
lines changed

4 files changed

+84
-0
lines changed

shell/common/fixtures/shell_test.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,19 @@ void localtimesMatch() {
163163
// formatting since package:intl is not available.
164164
notifyLocalTime(timeStr.split(":")[0]);
165165
}
166+
167+
void notifyCanAccessResource(bool success) native 'NotifyCanAccessResource';
168+
169+
void notifySetAssetBundlePath() native 'NotifySetAssetBundlePath';
170+
171+
@pragma('vm:entry-point')
172+
void canAccessResourceFromAssetDir() async {
173+
notifySetAssetBundlePath();
174+
window.sendPlatformMessage(
175+
'flutter/assets',
176+
Uint8List.fromList(utf8.encode('kernel_blob.bin')).buffer.asByteData(),
177+
(ByteData byteData) {
178+
notifyCanAccessResource(byteData != null);
179+
},
180+
);
181+
}

shell/common/shell.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,6 +1404,7 @@ bool Shell::OnServiceProtocolRunInView(
14041404
configuration.AddAssetResolver(
14051405
std::make_unique<DirectoryAssetBundle>(fml::OpenDirectory(
14061406
asset_directory_path.c_str(), false, fml::FilePermission::kRead)));
1407+
configuration.AddAssetResolver(RestoreOriginalAssetResolver());
14071408

14081409
auto& allocator = response->GetAllocator();
14091410
response->SetObject();
@@ -1516,6 +1517,7 @@ bool Shell::OnServiceProtocolSetAssetBundlePath(
15161517

15171518
auto asset_manager = std::make_shared<AssetManager>();
15181519

1520+
asset_manager->PushFront(RestoreOriginalAssetResolver());
15191521
asset_manager->PushFront(std::make_unique<DirectoryAssetBundle>(
15201522
fml::OpenDirectory(params.at("assetDirectory").data(), false,
15211523
fml::FilePermission::kRead)));
@@ -1622,4 +1624,16 @@ void Shell::OnDisplayUpdates(DisplayUpdateType update_type,
16221624
display_manager_->HandleDisplayUpdates(update_type, displays);
16231625
}
16241626

1627+
// Add the original asset directory to the resolvers so that unmodified assets
1628+
// bundled with the application specific format (APK, IPA) can be used without
1629+
// syncing to the Dart devFS.
1630+
std::unique_ptr<DirectoryAssetBundle> Shell::RestoreOriginalAssetResolver() {
1631+
if (fml::UniqueFD::traits_type::IsValid(settings_.assets_dir)) {
1632+
return std::make_unique<DirectoryAssetBundle>(
1633+
fml::Duplicate(settings_.assets_dir));
1634+
}
1635+
return std::make_unique<DirectoryAssetBundle>(fml::OpenDirectory(
1636+
settings_.assets_path.c_str(), false, fml::FilePermission::kRead));
1637+
};
1638+
16251639
} // namespace flutter

shell/common/shell.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <string_view>
1111
#include <unordered_map>
1212

13+
#include "flutter/assets/directory_asset_bundle.h"
1314
#include "flutter/common/settings.h"
1415
#include "flutter/common/task_runners.h"
1516
#include "flutter/flow/surface.h"
@@ -612,6 +613,10 @@ class Shell final : public PlatformView::Delegate,
612613
const ServiceProtocol::Handler::ServiceProtocolMap& params,
613614
rapidjson::Document* response);
614615

616+
// Creates an asset bundle from the original settings asset path or
617+
// directory.
618+
std::unique_ptr<DirectoryAssetBundle> RestoreOriginalAssetResolver();
619+
615620
// For accessing the Shell via the raster thread, necessary for various
616621
// rasterizer callbacks.
617622
std::unique_ptr<fml::TaskRunnerAffineWeakPtrFactory<Shell>> weak_factory_gpu_;

shell/common/shell_unittests.cc

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2135,5 +2135,54 @@ TEST_F(ShellTest, IgnoresInvalidMetrics) {
21352135
DestroyShell(std::move(shell), std::move(task_runners));
21362136
}
21372137

2138+
TEST_F(ShellTest, OnServiceProtocolSetAssetBundlePathWorks) {
2139+
Settings settings = CreateSettingsForFixture();
2140+
std::unique_ptr<Shell> shell = CreateShell(settings);
2141+
RunConfiguration configuration =
2142+
RunConfiguration::InferFromSettings(settings);
2143+
configuration.SetEntrypoint("canAccessResourceFromAssetDir");
2144+
2145+
// Verify isolate can load a known resource with the
2146+
// default asset directory - kernel_blob.bin
2147+
fml::AutoResetWaitableEvent latch;
2148+
2149+
// Callback used to signal whether the resource was loaded successfully.
2150+
bool can_access_resource = false;
2151+
auto native_can_access_resource = [&can_access_resource,
2152+
&latch](Dart_NativeArguments args) {
2153+
Dart_Handle exception = nullptr;
2154+
can_access_resource =
2155+
tonic::DartConverter<bool>::FromArguments(args, 0, exception);
2156+
latch.Signal();
2157+
};
2158+
AddNativeCallback("NotifyCanAccessResource",
2159+
CREATE_NATIVE_ENTRY(native_can_access_resource));
2160+
2161+
// Callback used to delay the asset load until after the service
2162+
// protocol method has finished.
2163+
auto native_notify_set_asset_bundle_path =
2164+
[&shell](Dart_NativeArguments args) {
2165+
// Update the asset directory to a bonus path.
2166+
ServiceProtocol::Handler::ServiceProtocolMap params;
2167+
params["assetDirectory"] = "assetDirectory";
2168+
rapidjson::Document document;
2169+
OnServiceProtocol(shell.get(), ServiceProtocolEnum::kSetAssetBundlePath,
2170+
shell->GetTaskRunners().GetUITaskRunner(), params,
2171+
&document);
2172+
rapidjson::StringBuffer buffer;
2173+
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
2174+
document.Accept(writer);
2175+
};
2176+
AddNativeCallback("NotifySetAssetBundlePath",
2177+
CREATE_NATIVE_ENTRY(native_notify_set_asset_bundle_path));
2178+
2179+
RunEngine(shell.get(), std::move(configuration));
2180+
2181+
latch.Wait();
2182+
ASSERT_TRUE(can_access_resource);
2183+
2184+
DestroyShell(std::move(shell));
2185+
}
2186+
21382187
} // namespace testing
21392188
} // namespace flutter

0 commit comments

Comments
 (0)