From 20d6b1c0fa4073e373bc914716799851ceef5d30 Mon Sep 17 00:00:00 2001 From: Kaushik Iska Date: Mon, 19 Apr 2021 11:22:30 -0700 Subject: [PATCH] Start microtasks only for non-tests This is because tests don't really wait for vsync to complete Fixes: https://github.com/flutter/flutter/issues/69694 See: https://github.com/flutter/engine/pull/25307#issuecomment-822504192 --- shell/common/shell_test.cc | 2 +- shell/common/shell_unittests.cc | 1 + shell/common/vsync_waiter.cc | 24 +++++++++++++++++-- shell/common/vsync_waiter.h | 6 ++++- shell/common/vsync_waiter_fallback.cc | 9 ++++--- shell/common/vsync_waiter_fallback.h | 4 +++- .../ios/framework/Source/vsync_waiter_ios.mm | 3 ++- .../platform/fuchsia/flutter/vsync_waiter.cc | 2 +- 8 files changed, 41 insertions(+), 10 deletions(-) diff --git a/shell/common/shell_test.cc b/shell/common/shell_test.cc index 380da75ec7b74..9f086bd23b09e 100644 --- a/shell/common/shell_test.cc +++ b/shell/common/shell_test.cc @@ -323,7 +323,7 @@ std::unique_ptr ShellTest::CreateShell( std::make_unique(task_runners, vsync_clock)); } else { return static_cast>( - std::make_unique(task_runners)); + std::make_unique(task_runners, true)); } }; return Shell::Create( diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index 0daddce767641..d1364f19d57d9 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -1335,6 +1335,7 @@ TEST_F(ShellTest, ReportTimingsIsCalledImmediatelyAfterTheFirstFrame) { }; AddNativeCallback("NativeReportTimingsCallback", CREATE_NATIVE_ENTRY(nativeTimingCallback)); + ASSERT_TRUE(configuration.IsValid()); RunEngine(shell.get(), std::move(configuration)); for (int i = 0; i < 10; i += 1) { diff --git a/shell/common/vsync_waiter.cc b/shell/common/vsync_waiter.cc index 886f6724db61c..40ced727abcfe 100644 --- a/shell/common/vsync_waiter.cc +++ b/shell/common/vsync_waiter.cc @@ -91,7 +91,8 @@ void VsyncWaiter::ScheduleSecondaryCallback(uintptr_t id, } void VsyncWaiter::FireCallback(fml::TimePoint frame_start_time, - fml::TimePoint frame_target_time) { + fml::TimePoint frame_target_time, + bool pause_secondary_tasks) { Callback callback; std::vector secondary_callbacks; @@ -114,6 +115,9 @@ void VsyncWaiter::FireCallback(fml::TimePoint frame_start_time, if (callback) { auto flow_identifier = fml::tracing::TraceNonce(); + if (pause_secondary_tasks) { + PauseDartMicroTasks(); + } // The base trace ensures that flows have a root to begin from if one does // not exist. The trace viewer will ignore traces that have no base event @@ -124,11 +128,15 @@ void VsyncWaiter::FireCallback(fml::TimePoint frame_start_time, TRACE_FLOW_BEGIN("flutter", kVsyncFlowName, flow_identifier); task_runners_.GetUITaskRunner()->PostTaskForTime( - [callback, flow_identifier, frame_start_time, frame_target_time]() { + [this, callback, flow_identifier, frame_start_time, frame_target_time, + pause_secondary_tasks]() { FML_TRACE_EVENT("flutter", kVsyncTraceName, "StartTime", frame_start_time, "TargetTime", frame_target_time); callback(frame_start_time, frame_target_time); TRACE_FLOW_END("flutter", kVsyncFlowName, flow_identifier); + if (pause_secondary_tasks) { + ResumeDartMicroTasks(); + } }, frame_start_time); } @@ -139,4 +147,16 @@ void VsyncWaiter::FireCallback(fml::TimePoint frame_start_time, } } +void VsyncWaiter::PauseDartMicroTasks() { + auto ui_task_queue_id = task_runners_.GetUITaskRunner()->GetTaskQueueId(); + auto task_queues = fml::MessageLoopTaskQueues::GetInstance(); + task_queues->PauseSecondarySource(ui_task_queue_id); +} + +void VsyncWaiter::ResumeDartMicroTasks() { + auto ui_task_queue_id = task_runners_.GetUITaskRunner()->GetTaskQueueId(); + auto task_queues = fml::MessageLoopTaskQueues::GetInstance(); + task_queues->ResumeSecondarySource(ui_task_queue_id); +} + } // namespace flutter diff --git a/shell/common/vsync_waiter.h b/shell/common/vsync_waiter.h index 084399011df4b..d593c7014b073 100644 --- a/shell/common/vsync_waiter.h +++ b/shell/common/vsync_waiter.h @@ -49,13 +49,17 @@ class VsyncWaiter : public std::enable_shared_from_this { virtual void AwaitVSync() = 0; void FireCallback(fml::TimePoint frame_start_time, - fml::TimePoint frame_target_time); + fml::TimePoint frame_target_time, + bool pause_secondary_tasks = true); private: std::mutex callback_mutex_; Callback callback_; std::unordered_map secondary_callbacks_; + void PauseDartMicroTasks(); + void ResumeDartMicroTasks(); + FML_DISALLOW_COPY_AND_ASSIGN(VsyncWaiter); }; diff --git a/shell/common/vsync_waiter_fallback.cc b/shell/common/vsync_waiter_fallback.cc index 514dc02fac5e6..8bf51c5ce2f4e 100644 --- a/shell/common/vsync_waiter_fallback.cc +++ b/shell/common/vsync_waiter_fallback.cc @@ -21,8 +21,11 @@ static fml::TimePoint SnapToNextTick(fml::TimePoint value, } // namespace -VsyncWaiterFallback::VsyncWaiterFallback(TaskRunners task_runners) - : VsyncWaiter(std::move(task_runners)), phase_(fml::TimePoint::Now()) {} +VsyncWaiterFallback::VsyncWaiterFallback(TaskRunners task_runners, + bool for_testing) + : VsyncWaiter(std::move(task_runners)), + phase_(fml::TimePoint::Now()), + for_testing_(for_testing) {} VsyncWaiterFallback::~VsyncWaiterFallback() = default; @@ -36,7 +39,7 @@ void VsyncWaiterFallback::AwaitVSync() { auto next = SnapToNextTick(fml::TimePoint::Now(), phase_, kSingleFrameInterval); - FireCallback(next, next + kSingleFrameInterval); + FireCallback(next, next + kSingleFrameInterval, !for_testing_); } } // namespace flutter diff --git a/shell/common/vsync_waiter_fallback.h b/shell/common/vsync_waiter_fallback.h index 5226dda019504..b2ae63f72045b 100644 --- a/shell/common/vsync_waiter_fallback.h +++ b/shell/common/vsync_waiter_fallback.h @@ -15,12 +15,14 @@ namespace flutter { /// A |VsyncWaiter| that will fire at 60 fps irrespective of the vsync. class VsyncWaiterFallback final : public VsyncWaiter { public: - VsyncWaiterFallback(TaskRunners task_runners); + explicit VsyncWaiterFallback(TaskRunners task_runners, + bool for_testing = false); ~VsyncWaiterFallback() override; private: fml::TimePoint phase_; + const bool for_testing_; // |VsyncWaiter| void AwaitVSync() override; diff --git a/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm b/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm index d71ecd7d783df..37d9b23c0c7f9 100644 --- a/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm +++ b/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm @@ -23,7 +23,8 @@ callback:std::bind(&VsyncWaiterIOS::FireCallback, this, std::placeholders::_1, - std::placeholders::_2)]) {} + std::placeholders::_2, + true)]) {} VsyncWaiterIOS::~VsyncWaiterIOS() { // This way, we will get no more callbacks from the display link that holds a weak (non-nilling) diff --git a/shell/platform/fuchsia/flutter/vsync_waiter.cc b/shell/platform/fuchsia/flutter/vsync_waiter.cc index 5a8fe59be137d..fd8f60122a0fa 100644 --- a/shell/platform/fuchsia/flutter/vsync_waiter.cc +++ b/shell/platform/fuchsia/flutter/vsync_waiter.cc @@ -197,7 +197,7 @@ void VsyncWaiter::FireCallbackNow() { } fml::TimePoint previous_vsync = next_vsync - vsync_info.presentation_interval; - FireCallback(previous_vsync, next_vsync); + FireCallback(previous_vsync, next_vsync, false); } } // namespace flutter_runner