mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Add call to Dart_NotifyDestroyed when the flutter view is destroyed. (flutter/engine#37539)
* Add calls to Dart_NotifyDestroyed when the flutter view is destroyed. * Add unit test case. * Format. * Ensure the destroy task runs. * Address code review comments.
This commit is contained in:
parent
62002a345b
commit
7296b2b66d
@ -235,6 +235,19 @@ bool RuntimeController::NotifyIdle(fml::TimePoint deadline) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RuntimeController::NotifyDestroyed() {
|
||||
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
|
||||
if (!root_isolate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tonic::DartState::Scope scope(root_isolate);
|
||||
|
||||
Dart_NotifyDestroyed();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RuntimeController::DispatchPlatformMessage(
|
||||
std::unique_ptr<PlatformMessage> message) {
|
||||
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
|
||||
|
||||
@ -360,6 +360,17 @@ class RuntimeController : public PlatformConfigurationClient {
|
||||
///
|
||||
virtual bool NotifyIdle(fml::TimePoint deadline);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Notify the Dart VM that the attached flutter view has been
|
||||
/// destroyed. This gives the Dart VM to perform some cleanup
|
||||
/// activities e.g: perform garbage collection to free up any
|
||||
/// unused memory.
|
||||
///
|
||||
/// NotifyDestroyed is advisory. The VM may or may not perform any clean up
|
||||
/// activities.
|
||||
///
|
||||
virtual bool NotifyDestroyed();
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Returns if the root isolate is running. The isolate must be
|
||||
/// transitioned to the running phase manually. The isolate can
|
||||
|
||||
@ -266,6 +266,11 @@ void Engine::NotifyIdle(fml::TimePoint deadline) {
|
||||
runtime_controller_->NotifyIdle(deadline);
|
||||
}
|
||||
|
||||
void Engine::NotifyDestroyed() {
|
||||
TRACE_EVENT0("flutter", "Engine::NotifyDestroyed");
|
||||
runtime_controller_->NotifyDestroyed();
|
||||
}
|
||||
|
||||
std::optional<uint32_t> Engine::GetUIIsolateReturnCode() {
|
||||
return runtime_controller_->GetRootIsolateReturnCode();
|
||||
}
|
||||
|
||||
@ -554,6 +554,13 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
|
||||
///
|
||||
void NotifyIdle(fml::TimePoint deadline);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Notifies the engine that the attached flutter view has been
|
||||
/// destroyed.
|
||||
/// This enables the engine to notify the Dart VM so it can do
|
||||
/// some cleanp activities.
|
||||
void NotifyDestroyed();
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Dart code cannot fully measure the time it takes for a
|
||||
/// specific frame to be rendered. This is because Dart code only
|
||||
|
||||
@ -212,6 +212,11 @@ void performanceModeImpactsNotifyIdle() {
|
||||
PlatformDispatcher.instance.requestDartPerformanceMode(DartPerformanceMode.balanced);
|
||||
}
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void callNotifyDestroyed() {
|
||||
notifyDestroyed();
|
||||
}
|
||||
|
||||
@pragma('vm:external-name', 'NotifyMessage')
|
||||
external void notifyMessage(String string);
|
||||
|
||||
@ -424,6 +429,8 @@ Future<void> runCallback(IsolateParam param) async {
|
||||
@pragma('vm:entry-point')
|
||||
@pragma('vm:external-name', 'NotifyNativeBool')
|
||||
external void notifyNativeBool(bool value);
|
||||
@pragma('vm:external-name', 'NotifyDestroyed')
|
||||
external void notifyDestroyed();
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
Future<void> testPluginUtilitiesCallbackHandle() async {
|
||||
|
||||
@ -851,6 +851,14 @@ void Shell::OnPlatformViewDestroyed() {
|
||||
// This incorrect assumption can lead to deadlock.
|
||||
rasterizer_->DisableThreadMergerIfNeeded();
|
||||
|
||||
// Notify the Dart VM that the PlatformView has been destroyed and some
|
||||
// cleanup activity can be done (e.g: garbage collect the Dart heap).
|
||||
task_runners_.GetUITaskRunner()->PostTask([engine = engine_->GetWeakPtr()]() {
|
||||
if (engine) {
|
||||
engine->NotifyDestroyed();
|
||||
}
|
||||
});
|
||||
|
||||
// Note:
|
||||
// This is a synchronous operation because certain platforms depend on
|
||||
// setup/suspension of all activities that may be interacting with the GPU in
|
||||
|
||||
@ -3932,6 +3932,40 @@ TEST_F(ShellTest, NotifyIdleNotCalledInLatencyMode) {
|
||||
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
|
||||
}
|
||||
|
||||
TEST_F(ShellTest, NotifyDestroyed) {
|
||||
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
|
||||
Settings settings = CreateSettingsForFixture();
|
||||
ThreadHost thread_host("io.flutter.test." + GetCurrentTestName() + ".",
|
||||
ThreadHost::Type::Platform | ThreadHost::UI |
|
||||
ThreadHost::IO | ThreadHost::RASTER);
|
||||
auto platform_task_runner = thread_host.platform_thread->GetTaskRunner();
|
||||
TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
|
||||
thread_host.raster_thread->GetTaskRunner(),
|
||||
thread_host.ui_thread->GetTaskRunner(),
|
||||
thread_host.io_thread->GetTaskRunner());
|
||||
auto shell = CreateShell(settings, task_runners);
|
||||
ASSERT_TRUE(DartVMRef::IsInstanceRunning());
|
||||
ASSERT_TRUE(ValidateShell(shell.get()));
|
||||
|
||||
fml::CountDownLatch latch(1);
|
||||
AddNativeCallback("NotifyDestroyed", CREATE_NATIVE_ENTRY([&](auto args) {
|
||||
auto runtime_controller = const_cast<RuntimeController*>(
|
||||
shell->GetEngine()->GetRuntimeController());
|
||||
bool success = runtime_controller->NotifyDestroyed();
|
||||
EXPECT_TRUE(success);
|
||||
latch.CountDown();
|
||||
}));
|
||||
|
||||
auto configuration = RunConfiguration::InferFromSettings(settings);
|
||||
configuration.SetEntrypoint("callNotifyDestroyed");
|
||||
RunEngine(shell.get(), std::move(configuration));
|
||||
|
||||
latch.Wait();
|
||||
|
||||
DestroyShell(std::move(shell), task_runners);
|
||||
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user