diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 508b8e9847425..cd2513e472e4a 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1449,6 +1449,7 @@ FILE: ../../../flutter/shell/platform/fuchsia/flutter/thread.h FILE: ../../../flutter/shell/platform/fuchsia/flutter/unique_fdio_ns.h FILE: ../../../flutter/shell/platform/fuchsia/flutter/vsync_waiter.cc FILE: ../../../flutter/shell/platform/fuchsia/flutter/vsync_waiter.h +FILE: ../../../flutter/shell/platform/fuchsia/flutter/vsync_waiter_unittest.cc FILE: ../../../flutter/shell/platform/fuchsia/flutter/vulkan_surface.cc FILE: ../../../flutter/shell/platform/fuchsia/flutter/vulkan_surface.h FILE: ../../../flutter/shell/platform/fuchsia/flutter/vulkan_surface_pool.cc diff --git a/shell/platform/fuchsia/flutter/BUILD.gn b/shell/platform/fuchsia/flutter/BUILD.gn index 5e36a86fa661b..ed7475caea5ff 100644 --- a/shell/platform/fuchsia/flutter/BUILD.gn +++ b/shell/platform/fuchsia/flutter/BUILD.gn @@ -449,6 +449,9 @@ executable("flutter_runner_unittests") { "tests/engine_unittests.cc", "tests/flutter_runner_product_configuration_unittests.cc", "tests/gfx_session_connection_unittests.cc", + "tests/pointer_event_utility.cc", + "tests/pointer_event_utility.h", + "vsync_waiter_unittest.cc", ] # This is needed for //third_party/googletest for linking zircon symbols. diff --git a/shell/platform/fuchsia/flutter/vsync_waiter.cc b/shell/platform/fuchsia/flutter/vsync_waiter.cc index c66e12690e310..aa7d3c2ebfe0e 100644 --- a/shell/platform/fuchsia/flutter/vsync_waiter.cc +++ b/shell/platform/fuchsia/flutter/vsync_waiter.cc @@ -30,10 +30,17 @@ VsyncWaiter::VsyncWaiter(AwaitVsyncCallback await_vsync_callback, weak_factory_(this) { fire_callback_callback_ = [this](fml::TimePoint frame_start, fml::TimePoint frame_end) { - // Note: It is VERY important to set |pause_secondary_tasks| to false, else - // Animator will almost immediately crash on Fuchsia. - // FML_LOG(INFO) << "CRASH:: VsyncWaiter about to FireCallback"; - FireCallback(frame_start, frame_end, /*pause_secondary_tasks=*/false); + task_runners_.GetUITaskRunner()->PostTaskForTime( + [frame_start, frame_end, weak_this = weak_ui_]() { + if (weak_this) { + // Note: It is VERY important to set |pause_secondary_tasks| to + // false, else Animator will almost immediately crash on Fuchsia. + // FML_LOG(INFO) << "CRASH:: VsyncWaiter about to FireCallback"; + weak_this->FireCallback(frame_start, frame_end, + /*pause_secondary_tasks*/ false); + } + }, + frame_start); }; // Generate a WeakPtrFactory for use with the UI thread. This does not need @@ -41,8 +48,9 @@ VsyncWaiter::VsyncWaiter(AwaitVsyncCallback await_vsync_callback, // thread so we have ordering guarantees (see ::AwaitVSync()) fml::TaskRunner::RunNowOrPostTask( task_runners_.GetUITaskRunner(), fml::MakeCopyable([this]() mutable { - this->weak_factory_ui_ = + weak_factory_ui_ = std::make_unique>(this); + weak_ui_ = weak_factory_ui_->GetWeakPtr(); })); } diff --git a/shell/platform/fuchsia/flutter/vsync_waiter.h b/shell/platform/fuchsia/flutter/vsync_waiter.h index 1e92064c8735b..ce46b90d362a7 100644 --- a/shell/platform/fuchsia/flutter/vsync_waiter.h +++ b/shell/platform/fuchsia/flutter/vsync_waiter.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_VSYNC_WAITER_H_ -#define FLUTTER_SHELL_PLATFORM_FUCHSIA_VSYNC_WAITER_H_ +#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_VSYNC_WAITER_H_ +#define FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_VSYNC_WAITER_H_ #include @@ -46,6 +46,7 @@ class VsyncWaiter final : public flutter::VsyncWaiter { AwaitVsyncForSecondaryCallbackCallback await_vsync_for_secondary_callback_callback_; + fml::WeakPtr weak_ui_; std::unique_ptr> weak_factory_ui_; fml::WeakPtrFactory weak_factory_; @@ -54,4 +55,4 @@ class VsyncWaiter final : public flutter::VsyncWaiter { } // namespace flutter_runner -#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_VSYNC_WAITER_H_ +#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_VSYNC_WAITER_H_ diff --git a/shell/platform/fuchsia/flutter/vsync_waiter_unittest.cc b/shell/platform/fuchsia/flutter/vsync_waiter_unittest.cc new file mode 100644 index 0000000000000..f01a2a02c90c4 --- /dev/null +++ b/shell/platform/fuchsia/flutter/vsync_waiter_unittest.cc @@ -0,0 +1,63 @@ +// 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. + +#include + +#include + +#include "flutter/fml/task_runner.h" +#include "flutter/shell/common/thread_host.h" +#include "fml/make_copyable.h" +#include "fml/message_loop.h" +#include "fml/synchronization/waitable_event.h" +#include "fml/time/time_delta.h" +#include "fml/time/time_point.h" +#include "vsync_waiter.h" + +namespace flutter_runner { + +TEST(VSyncWaiterFuchsia, FrameScheduledForStartTime) { + using flutter::ThreadHost; + std::string prefix = "vsync_waiter_test"; + + fml::MessageLoop::EnsureInitializedForCurrentThread(); + auto platform_task_runner = fml::MessageLoop::GetCurrent().GetTaskRunner(); + + ThreadHost thread_host = + ThreadHost(prefix, flutter::ThreadHost::Type::RASTER | + flutter::ThreadHost::Type::UI | + flutter::ThreadHost::Type::IO); + const flutter::TaskRunners task_runners( + prefix, // Dart thread labels + platform_task_runner, // platform + thread_host.raster_thread->GetTaskRunner(), // raster + thread_host.ui_thread->GetTaskRunner(), // ui + thread_host.io_thread->GetTaskRunner() // io + ); + + // await vsync will invoke the callback right away, but vsync waiter will post + // the task for frame_start time. + VsyncWaiter vsync_waiter( + [](FireCallbackCallback callback) { + const auto now = fml::TimePoint::Now(); + const auto frame_start = now + fml::TimeDelta::FromMilliseconds(20); + const auto frame_end = now + fml::TimeDelta::FromMilliseconds(36); + callback(frame_start, frame_end); + }, + /*secondary callback*/ nullptr, task_runners); + + fml::AutoResetWaitableEvent latch; + task_runners.GetUITaskRunner()->PostTask([&]() { + vsync_waiter.AsyncWaitForVsync( + [&](std::unique_ptr recorder) { + const auto now = fml::TimePoint::Now(); + EXPECT_GT(now, recorder->GetVsyncStartTime()); + latch.Signal(); + }); + }); + + latch.Wait(); +} + +} // namespace flutter_runner