diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter index d1f2718bc0c..b6d5dbce78b 100755 --- a/engine/src/flutter/ci/licenses_golden/licenses_flutter +++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter @@ -327,7 +327,6 @@ FILE: ../../../flutter/lib/ui/fixtures/hello_loop_2.webp FILE: ../../../flutter/lib/ui/fixtures/ui_test.dart FILE: ../../../flutter/lib/ui/geometry.dart FILE: ../../../flutter/lib/ui/hash_codes.dart -FILE: ../../../flutter/lib/ui/hint_freed_delegate.h FILE: ../../../flutter/lib/ui/hooks.dart FILE: ../../../flutter/lib/ui/hooks_unittests.cc FILE: ../../../flutter/lib/ui/io_manager.h diff --git a/engine/src/flutter/lib/ui/fixtures/ui_test.dart b/engine/src/flutter/lib/ui/fixtures/ui_test.dart index ac6d5eb48b2..e599cece7e5 100644 --- a/engine/src/flutter/lib/ui/fixtures/ui_test.dart +++ b/engine/src/flutter/lib/ui/fixtures/ui_test.dart @@ -8,6 +8,10 @@ import 'dart:ui'; void main() {} +/// Mutiple tests use this to signal to the C++ side that they are ready for +/// validation. +void _finish() native 'Finish'; + @pragma('vm:entry-point') void validateSceneBuilderAndScene() { final SceneBuilder builder = SceneBuilder(); @@ -60,7 +64,6 @@ Future createSingleFrameCodec() async { _finish(); } void _validateCodec(Codec codec) native 'ValidateCodec'; -void _finish() native 'Finish'; @pragma('vm:entry-point') void createVertices() { @@ -232,8 +235,8 @@ void _validateExternal(Uint8List result) native 'ValidateExternal'; @pragma('vm:entry-point') Future pumpImage() async { - const int width = 6000; - const int height = 6000; + const int width = 60; + const int height = 60; final Completer completer = Completer(); decodeImageFromPixels( Uint8List.fromList(List.filled(width * height * 4, 0xFF)), @@ -243,34 +246,37 @@ Future pumpImage() async { (Image image) => completer.complete(image), ); final Image image = await completer.future; + late Picture picture; + late OffsetEngineLayer layer; - final FrameCallback renderBlank = (Duration duration) { + void renderBlank(Duration duration) { image.dispose(); + picture.dispose(); + layer.dispose(); final PictureRecorder recorder = PictureRecorder(); final Canvas canvas = Canvas(recorder); - canvas.drawRect(Rect.largest, Paint()); - final Picture picture = recorder.endRecording(); - + canvas.drawPaint(Paint()); + picture = recorder.endRecording(); final SceneBuilder builder = SceneBuilder(); + layer = builder.pushOffset(0, 0); builder.addPicture(Offset.zero, picture); final Scene scene = builder.build(); window.render(scene); scene.dispose(); - window.onBeginFrame = (Duration duration) { - window.onDrawFrame = _onBeginFrameDone; - }; - window.scheduleFrame(); - }; - final FrameCallback renderImage = (Duration duration) { + _finish(); + } + + void renderImage(Duration duration) { final PictureRecorder recorder = PictureRecorder(); final Canvas canvas = Canvas(recorder); canvas.drawImage(image, Offset.zero, Paint()); - final Picture picture = recorder.endRecording(); + picture = recorder.endRecording(); final SceneBuilder builder = SceneBuilder(); + layer = builder.pushOffset(0, 0); builder.addPicture(Offset.zero, picture); _captureImageAndPicture(image, picture); @@ -278,15 +284,15 @@ Future pumpImage() async { final Scene scene = builder.build(); window.render(scene); scene.dispose(); + window.onBeginFrame = renderBlank; window.scheduleFrame(); - }; + } window.onBeginFrame = renderImage; window.scheduleFrame(); } void _captureImageAndPicture(Image image, Picture picture) native 'CaptureImageAndPicture'; -Future _onBeginFrameDone() native 'OnBeginFrameDone'; @pragma('vm:entry-point') void hooksTests() { diff --git a/engine/src/flutter/lib/ui/hint_freed_delegate.h b/engine/src/flutter/lib/ui/hint_freed_delegate.h deleted file mode 100644 index 0e4a38b4145..00000000000 --- a/engine/src/flutter/lib/ui/hint_freed_delegate.h +++ /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. - -#ifndef FLUTTER_LIB_UI_HINT_FREED_DELEGATE_H_ -#define FLUTTER_LIB_UI_HINT_FREED_DELEGATE_H_ - -namespace flutter { - -class HintFreedDelegate { - public: - //---------------------------------------------------------------------------- - /// @brief Notifies the engine that native bytes might be freed if a - /// garbage collection ran at the next NotifyIdle period. - /// - /// @param[in] size The number of bytes freed. This size adds to any - /// previously supplied value, rather than replacing. - /// - virtual void HintFreed(size_t size) = 0; -}; - -} // namespace flutter - -#endif // FLUTTER_LIB_UI_HINT_FREED_DELEGATE_H_ diff --git a/engine/src/flutter/lib/ui/painting/engine_layer.cc b/engine/src/flutter/lib/ui/painting/engine_layer.cc index 45d41b12d75..0f3e0b73787 100644 --- a/engine/src/flutter/lib/ui/painting/engine_layer.cc +++ b/engine/src/flutter/lib/ui/painting/engine_layer.cc @@ -25,16 +25,6 @@ EngineLayer::EngineLayer(std::shared_ptr layer) EngineLayer::~EngineLayer() = default; -size_t EngineLayer::GetAllocationSize() const { - // TODO(dnfield): Remove this when scene disposal changes land in the - // framework. https://github.com/flutter/flutter/issues/81514 - - // Provide an approximation of the total memory impact of this object to the - // Dart GC. The ContainerLayer may hold references to a tree of other layers, - // which in turn may contain Skia objects. - return 3000; -}; - void EngineLayer::dispose() { layer_.reset(); ClearDartWrapper(); diff --git a/engine/src/flutter/lib/ui/painting/engine_layer.h b/engine/src/flutter/lib/ui/painting/engine_layer.h index 0a815af0975..87ae5ab173b 100644 --- a/engine/src/flutter/lib/ui/painting/engine_layer.h +++ b/engine/src/flutter/lib/ui/painting/engine_layer.h @@ -22,8 +22,6 @@ class EngineLayer : public RefCountedDartWrappable { public: ~EngineLayer() override; - size_t GetAllocationSize() const override; - static void MakeRetained(Dart_Handle dart_handle, std::shared_ptr layer) { auto engine_layer = fml::MakeRefCounted(layer); diff --git a/engine/src/flutter/lib/ui/painting/image.cc b/engine/src/flutter/lib/ui/painting/image.cc index 29e70e88fd0..58db76d4cde 100644 --- a/engine/src/flutter/lib/ui/painting/image.cc +++ b/engine/src/flutter/lib/ui/painting/image.cc @@ -44,12 +44,6 @@ Dart_Handle CanvasImage::toByteData(int format, Dart_Handle callback) { } void CanvasImage::dispose() { - // TODO(dnfield): Remove the hint freed delegate once Picture disposal is in - // the framework https://github.com/flutter/flutter/issues/81514 - auto hint_freed_delegate = UIDartState::Current()->GetHintFreedDelegate(); - if (hint_freed_delegate) { - hint_freed_delegate->HintFreed(GetAllocationSize()); - } image_.reset(); ClearDartWrapper(); } diff --git a/engine/src/flutter/lib/ui/painting/image_dispose_unittests.cc b/engine/src/flutter/lib/ui/painting/image_dispose_unittests.cc index 2734792444b..245d0a58ee6 100644 --- a/engine/src/flutter/lib/ui/painting/image_dispose_unittests.cc +++ b/engine/src/flutter/lib/ui/painting/image_dispose_unittests.cc @@ -30,23 +30,11 @@ class ImageDisposeTest : public ShellTest { // Used to wait on Dart callbacks or Shell task runner flushing fml::AutoResetWaitableEvent message_latch_; - fml::AutoResetWaitableEvent picture_finalizer_latch_; - static void picture_finalizer(void* isolate_callback_data, void* peer) { - auto latch = reinterpret_cast(peer); - latch->Signal(); - } - sk_sp current_picture_; sk_sp current_image_; }; -TEST_F(ImageDisposeTest, -#if defined(OS_FUCHSIA) - DISABLED_ImageReleasedAfterFrame -#else - ImageReleasedAfterFrame -#endif // defined(OS_FUCHSIA) -) { +TEST_F(ImageDisposeTest, ImageReleasedAfterFrameAndDisposePictureAndLayer) { auto native_capture_image_and_picture = [&](Dart_NativeArguments args) { auto image_handle = Dart_GetNativeArgument(args, 0); auto native_image_handle = @@ -60,12 +48,9 @@ TEST_F(ImageDisposeTest, ASSERT_FALSE(picture->picture()->unique()); current_image_ = image->image(); current_picture_ = picture->picture(); - - Dart_NewFinalizableHandle(Dart_GetNativeArgument(args, 1), - &picture_finalizer_latch_, 0, &picture_finalizer); }; - auto native_on_begin_frame_done = [&](Dart_NativeArguments args) { + auto native_finish = [&](Dart_NativeArguments args) { message_latch_.Signal(); }; @@ -80,8 +65,7 @@ TEST_F(ImageDisposeTest, AddNativeCallback("CaptureImageAndPicture", CREATE_NATIVE_ENTRY(native_capture_image_and_picture)); - AddNativeCallback("OnBeginFrameDone", - CREATE_NATIVE_ENTRY(native_on_begin_frame_done)); + AddNativeCallback("Finish", CREATE_NATIVE_ENTRY(native_finish)); std::unique_ptr shell = CreateShell(std::move(settings), task_runners); @@ -103,15 +87,8 @@ TEST_F(ImageDisposeTest, ASSERT_TRUE(current_picture_); ASSERT_TRUE(current_image_); - // Simulate a large notify idle, as the animator would do - // when it has no frames left. - // On slower machines, this is especially important - we capture that - // this happens normally in devicelab bnechmarks like large_image_changer. - NotifyIdle(shell.get(), Dart_TimelineGetMicros() + 100000); - - picture_finalizer_latch_.Wait(); - - // Force a drain the SkiaUnrefQueue. + // Force a drain the SkiaUnrefQueue. The engine does this normally as frames + // pump, but we force it here to make the test more deterministic. message_latch_.Reset(); task_runner->PostTask([&, io_manager = shell->GetIOManager()]() { io_manager->GetSkiaUnrefQueue()->Drain(); diff --git a/engine/src/flutter/lib/ui/ui_dart_state.cc b/engine/src/flutter/lib/ui/ui_dart_state.cc index a8c1347162a..71d02c7b73b 100644 --- a/engine/src/flutter/lib/ui/ui_dart_state.cc +++ b/engine/src/flutter/lib/ui/ui_dart_state.cc @@ -30,7 +30,6 @@ UIDartState::Context::Context(const TaskRunners& task_runners) UIDartState::Context::Context( const TaskRunners& task_runners, fml::WeakPtr snapshot_delegate, - fml::WeakPtr hint_freed_delegate, fml::WeakPtr io_manager, fml::RefPtr unref_queue, fml::WeakPtr image_decoder, @@ -40,7 +39,6 @@ UIDartState::Context::Context( std::shared_ptr volatile_path_tracker) : task_runners(task_runners), snapshot_delegate(snapshot_delegate), - hint_freed_delegate(hint_freed_delegate), io_manager(io_manager), unref_queue(unref_queue), image_decoder(image_decoder), @@ -169,10 +167,6 @@ fml::WeakPtr UIDartState::GetSnapshotDelegate() const { return context_.snapshot_delegate; } -fml::WeakPtr UIDartState::GetHintFreedDelegate() const { - return context_.hint_freed_delegate; -} - fml::WeakPtr UIDartState::GetResourceContext() const { if (!context_.io_manager) { return {}; diff --git a/engine/src/flutter/lib/ui/ui_dart_state.h b/engine/src/flutter/lib/ui/ui_dart_state.h index e72c05679fe..fb2baadb1aa 100644 --- a/engine/src/flutter/lib/ui/ui_dart_state.h +++ b/engine/src/flutter/lib/ui/ui_dart_state.h @@ -15,7 +15,6 @@ #include "flutter/fml/build_config.h" #include "flutter/fml/memory/weak_ptr.h" #include "flutter/fml/synchronization/waitable_event.h" -#include "flutter/lib/ui/hint_freed_delegate.h" #include "flutter/lib/ui/io_manager.h" #include "flutter/lib/ui/isolate_name_server/isolate_name_server.h" #include "flutter/lib/ui/painting/image_decoder.h" @@ -46,7 +45,6 @@ class UIDartState : public tonic::DartState { Context(const TaskRunners& task_runners, fml::WeakPtr snapshot_delegate, - fml::WeakPtr hint_freed_delegate, fml::WeakPtr io_manager, fml::RefPtr unref_queue, fml::WeakPtr image_decoder, @@ -65,10 +63,6 @@ class UIDartState : public tonic::DartState { /// of Flutter view hierarchies. fml::WeakPtr snapshot_delegate; - /// The delegate used by the isolate to hint the Dart VM when additional - /// memory may be freed if a GC ran at the next NotifyIdle. - fml::WeakPtr hint_freed_delegate; - /// The IO manager used by the isolate for asynchronous texture uploads. fml::WeakPtr io_manager; @@ -126,8 +120,6 @@ class UIDartState : public tonic::DartState { fml::WeakPtr GetSnapshotDelegate() const; - fml::WeakPtr GetHintFreedDelegate() const; - fml::WeakPtr GetResourceContext() const; fml::WeakPtr GetImageDecoder() const; diff --git a/engine/src/flutter/runtime/dart_isolate.cc b/engine/src/flutter/runtime/dart_isolate.cc index d8d716ec841..52aa2ffb4d3 100644 --- a/engine/src/flutter/runtime/dart_isolate.cc +++ b/engine/src/flutter/runtime/dart_isolate.cc @@ -82,7 +82,6 @@ std::weak_ptr DartIsolate::SpawnIsolate( const Settings& settings, std::unique_ptr platform_configuration, fml::WeakPtr snapshot_delegate, - fml::WeakPtr hint_freed_delegate, std::string advisory_script_uri, std::string advisory_script_entrypoint, Flags flags, @@ -103,7 +102,6 @@ std::weak_ptr DartIsolate::SpawnIsolate( std::move(isolate_configration), // UIDartState::Context{GetTaskRunners(), // snapshot_delegate, // - hint_freed_delegate, // GetIOManager(), // GetSkiaUnrefQueue(), // GetImageDecoder(), // diff --git a/engine/src/flutter/runtime/dart_isolate.h b/engine/src/flutter/runtime/dart_isolate.h index b41d1fb44a4..04ceb4edda7 100644 --- a/engine/src/flutter/runtime/dart_isolate.h +++ b/engine/src/flutter/runtime/dart_isolate.h @@ -15,7 +15,6 @@ #include "flutter/fml/compiler_specific.h" #include "flutter/fml/macros.h" #include "flutter/fml/mapping.h" -#include "flutter/lib/ui/hint_freed_delegate.h" #include "flutter/lib/ui/io_manager.h" #include "flutter/lib/ui/snapshot_delegate.h" #include "flutter/lib/ui/ui_dart_state.h" @@ -230,7 +229,6 @@ class DartIsolate : public UIDartState { const Settings& settings, std::unique_ptr platform_configuration, fml::WeakPtr snapshot_delegate, - fml::WeakPtr hint_freed_delegate, std::string advisory_script_uri, std::string advisory_script_entrypoint, Flags flags, diff --git a/engine/src/flutter/runtime/dart_isolate_unittests.cc b/engine/src/flutter/runtime/dart_isolate_unittests.cc index 262efa6d820..e23408b332b 100644 --- a/engine/src/flutter/runtime/dart_isolate_unittests.cc +++ b/engine/src/flutter/runtime/dart_isolate_unittests.cc @@ -114,7 +114,6 @@ TEST_F(DartIsolateTest, SpawnIsolate) { /*settings=*/vm_data->GetSettings(), /*platform_configuration=*/nullptr, /*snapshot_delegate=*/{}, - /*hint_freed_delegate=*/{}, /*advisory_script_uri=*/"main.dart", /*advisory_script_entrypoint=*/"main", /*flags=*/DartIsolate::Flags{}, diff --git a/engine/src/flutter/runtime/runtime_controller.cc b/engine/src/flutter/runtime/runtime_controller.cc index 3c77de4ffd2..1d622bbe3c2 100644 --- a/engine/src/flutter/runtime/runtime_controller.cc +++ b/engine/src/flutter/runtime/runtime_controller.cc @@ -195,7 +195,7 @@ bool RuntimeController::ReportTimings(std::vector timings) { return false; } -bool RuntimeController::NotifyIdle(int64_t deadline, size_t freed_hint) { +bool RuntimeController::NotifyIdle(int64_t deadline) { std::shared_ptr root_isolate = root_isolate_.lock(); if (!root_isolate) { return false; @@ -203,9 +203,6 @@ bool RuntimeController::NotifyIdle(int64_t deadline, size_t freed_hint) { tonic::DartState::Scope scope(root_isolate); - // Dart will use the freed hint at the next idle notification. Make sure to - // Update it with our latest value before calling NotifyIdle. - Dart_HintFreed(freed_hint); Dart_NotifyIdle(deadline); // Idle notifications being in isolate scope are part of the contract. diff --git a/engine/src/flutter/runtime/runtime_controller.h b/engine/src/flutter/runtime/runtime_controller.h index ba7794b2659..00e07be7680 100644 --- a/engine/src/flutter/runtime/runtime_controller.h +++ b/engine/src/flutter/runtime/runtime_controller.h @@ -341,12 +341,10 @@ class RuntimeController : public PlatformConfigurationClient { /// @param[in] deadline The deadline measures in microseconds against the /// system's monotonic time. The clock can be accessed via /// `Dart_TimelineGetMicros`. - /// @param[in] freed_hint A hint of the number of bytes potentially freed - /// since the last call to NotifyIdle if a GC were run. /// /// @return If the idle notification was forwarded to the running isolate. /// - virtual bool NotifyIdle(int64_t deadline, size_t freed_hint); + virtual bool NotifyIdle(int64_t deadline); //---------------------------------------------------------------------------- /// @brief Returns if the root isolate is running. The isolate must be diff --git a/engine/src/flutter/shell/common/engine.cc b/engine/src/flutter/shell/common/engine.cc index 3cca483b0c9..e6e22d41f34 100644 --- a/engine/src/flutter/shell/common/engine.cc +++ b/engine/src/flutter/shell/common/engine.cc @@ -98,7 +98,6 @@ Engine::Engine(Delegate& delegate, UIDartState::Context{ task_runners_, // task runners std::move(snapshot_delegate), // snapshot delegate - GetWeakPtr(), // hint freed delegate std::move(io_manager), // io manager std::move(unref_queue), // Skia unref queue image_decoder_.GetWeakPtr(), // image decoder @@ -231,27 +230,11 @@ void Engine::ReportTimings(std::vector timings) { runtime_controller_->ReportTimings(std::move(timings)); } -void Engine::HintFreed(size_t size) { - hint_freed_bytes_since_last_call_ += size; -} - void Engine::NotifyIdle(int64_t deadline) { auto trace_event = std::to_string(deadline - Dart_TimelineGetMicros()); TRACE_EVENT1("flutter", "Engine::NotifyIdle", "deadline_now_delta", trace_event.c_str()); - // Avoid asking the RuntimeController to call Dart_HintFreed more than once - // every 5 seconds. - // This is to avoid GCs happening too frequently e.g. when an animated GIF is - // playing and disposing of an image every frame. - fml::TimePoint now = delegate_.GetCurrentTimePoint(); - fml::TimeDelta delta = now - last_hint_freed_call_time_; - size_t hint_freed_bytes = 0; - if (delta.ToMilliseconds() > 5000 && hint_freed_bytes_since_last_call_ > 0) { - hint_freed_bytes = hint_freed_bytes_since_last_call_; - hint_freed_bytes_since_last_call_ = 0; - last_hint_freed_call_time_ = now; - } - runtime_controller_->NotifyIdle(deadline, hint_freed_bytes); + runtime_controller_->NotifyIdle(deadline); } std::optional Engine::GetUIIsolateReturnCode() { diff --git a/engine/src/flutter/shell/common/engine.h b/engine/src/flutter/shell/common/engine.h index 674ce8d519c..78bc730743d 100644 --- a/engine/src/flutter/shell/common/engine.h +++ b/engine/src/flutter/shell/common/engine.h @@ -13,7 +13,6 @@ #include "flutter/fml/macros.h" #include "flutter/fml/mapping.h" #include "flutter/fml/memory/weak_ptr.h" -#include "flutter/lib/ui/hint_freed_delegate.h" #include "flutter/lib/ui/painting/image_decoder.h" #include "flutter/lib/ui/painting/image_generator_registry.h" #include "flutter/lib/ui/semantics/custom_accessibility_action.h" @@ -73,9 +72,7 @@ namespace flutter { /// name and it does happen to be one of the older classes in the /// repository. /// -class Engine final : public RuntimeDelegate, - public HintFreedDelegate, - PointerDataDispatcher::Delegate { +class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate { public: //---------------------------------------------------------------------------- /// @brief Indicates the result of the call to `Engine::Run`. @@ -505,9 +502,6 @@ class Engine final : public RuntimeDelegate, /// void BeginFrame(fml::TimePoint frame_time); - // |HintFreedDelegate| - void HintFreed(size_t size) override; - //---------------------------------------------------------------------------- /// @brief Notifies the engine that the UI task runner is not expected to /// undertake a new frame workload till a specified timepoint. The @@ -924,8 +918,6 @@ class Engine final : public RuntimeDelegate, ImageDecoder image_decoder_; ImageGeneratorRegistry image_generator_registry_; TaskRunners task_runners_; - size_t hint_freed_bytes_since_last_call_ = 0; - fml::TimePoint last_hint_freed_call_time_; fml::WeakPtrFactory weak_factory_; // |RuntimeDelegate| diff --git a/engine/src/flutter/shell/common/engine_unittests.cc b/engine/src/flutter/shell/common/engine_unittests.cc index 18163e7d1c4..3a83cc7a868 100644 --- a/engine/src/flutter/shell/common/engine_unittests.cc +++ b/engine/src/flutter/shell/common/engine_unittests.cc @@ -71,7 +71,7 @@ class MockRuntimeController : public RuntimeController { MOCK_METHOD3(LoadDartDeferredLibraryError, void(intptr_t, const std::string, bool)); MOCK_CONST_METHOD0(GetDartVM, DartVM*()); - MOCK_METHOD2(NotifyIdle, bool(int64_t, size_t)); + MOCK_METHOD1(NotifyIdle, bool(int64_t)); }; std::unique_ptr MakePlatformMessage( @@ -302,51 +302,4 @@ TEST_F(EngineTest, PassesLoadDartDeferredLibraryErrorToRuntime) { }); } -TEST_F(EngineTest, NotifyIdleMoreThanOncePerFiveSeconds) { - PostUITaskSync([this] { - MockRuntimeDelegate client; - auto mock_runtime_controller = - std::make_unique(client, task_runners_); - - // Verify we get an initial call with the bytes, since it's 10 seconds. - EXPECT_CALL(*mock_runtime_controller, NotifyIdle(200, 100)).Times(1); - // Verify that we do not get called again, since it's only been 3 more - // seconds. - EXPECT_CALL(*mock_runtime_controller, NotifyIdle(400, 0)).Times(1); - // Verify that we get called again, since it's now been 6 seconds. - EXPECT_CALL(*mock_runtime_controller, NotifyIdle(600, 300 + 500)).Times(1); - // Set up mocking of the timepoint logic. Calls at 10, 13, and 16 seconds. - EXPECT_CALL(delegate_, GetCurrentTimePoint()) - .Times(3) - .WillOnce(::testing::Return( - fml::TimePoint::FromEpochDelta(fml::TimeDelta::FromSeconds(10)))) - .WillOnce(::testing::Return( - fml::TimePoint::FromEpochDelta(fml::TimeDelta::FromSeconds(13)))) - .WillOnce(::testing::Return( - fml::TimePoint::FromEpochDelta(fml::TimeDelta::FromSeconds(16)))); - - auto engine = std::make_unique( - /*delegate=*/delegate_, - /*dispatcher_maker=*/dispatcher_maker_, - /*image_decoder_task_runner=*/image_decoder_task_runner_, - /*task_runners=*/task_runners_, - /*settings=*/settings_, - /*animator=*/std::move(animator_), - /*io_manager=*/io_manager_, - /*font_collection=*/std::make_shared(), - /*runtime_controller=*/std::move(mock_runtime_controller)); - - // Verifications are above, since we std::moved the unique_ptr for the - // mock. - engine->HintFreed(100); - engine->NotifyIdle(200); - - engine->HintFreed(300); - engine->NotifyIdle(400); - - engine->HintFreed(500); - engine->NotifyIdle(600); - }); -} - } // namespace flutter