5#include "flutter/shell/platform/fuchsia/flutter/flatland_connection.h"
7#include <fuchsia/scenic/scheduling/cpp/fidl.h>
8#include <fuchsia/ui/composition/cpp/fidl.h>
9#include <lib/async-testing/test_loop.h>
10#include <lib/async/cpp/task.h>
11#include <zircon/rights.h>
12#include <zircon/types.h>
17#include "flutter/fml/logging.h"
18#include "flutter/fml/time/time_delta.h"
19#include "flutter/fml/time/time_point.h"
20#include "gtest/gtest.h"
29 return ::testing::UnitTest::GetInstance()->current_test_info()->name();
32void AwaitVsyncChecked(FlatlandConnection& flatland_connection,
33 bool& condition_variable,
35 flatland_connection.AwaitVsync(
39 expected_frame_delta);
40 condition_variable =
true;
44void AwaitVsyncChecked(FlatlandConnection& flatland_connection,
45 bool& condition_variable,
47 flatland_connection.AwaitVsync(
50 EXPECT_EQ(frame_end, expected_frame_end);
51 condition_variable =
true;
55std::vector<fuchsia::scenic::scheduling::PresentationInfo>
56CreateFuturePresentationInfos(
const fml::TimePoint& presentation_time_1,
58 fuchsia::scenic::scheduling::PresentationInfo info_1;
59 info_1.set_presentation_time(
61 std::vector<fuchsia::scenic::scheduling::PresentationInfo> infos;
62 infos.push_back(std::move(info_1));
63 fuchsia::scenic::scheduling::PresentationInfo info_2;
64 info_2.set_presentation_time(
66 infos.push_back(std::move(info_2));
75 : session_subloop_(loop_.StartNewLoop()),
77 fake_flatland_.ConnectFlatland(session_subloop_->dispatcher())) {}
80 async::TestLoop&
loop() {
return loop_; }
83 return session_subloop_->dispatcher();
88 fidl::InterfaceHandle<fuchsia::ui::composition::Flatland>
91 return std::move(flatland_handle_);
98 fuchsia::ui::composition::OnNextFrameBeginValues on_next_frame_begin_values;
99 on_next_frame_begin_values.set_additional_present_credits(
100 num_present_credits);
101 on_next_frame_begin_values.set_future_presentation_infos(
102 CreateFuturePresentationInfos(presentation_time_1,
103 presentation_time_2));
105 std::move(on_next_frame_begin_values));
116 async::TestLoop loop_;
117 std::unique_ptr<async::LoopInterface> session_subloop_;
121 fidl::InterfaceHandle<fuchsia::ui::composition::Flatland> flatland_handle_;
129 debug_name, TakeFlatlandHandle(), []() {
FAIL(); },
130 [](
auto...) {
FAIL(); }, loop().dispatcher());
131 EXPECT_EQ(fake_flatland().debug_name(),
"");
134 bool await_vsync_fired =
false;
135 AwaitVsyncChecked(flatland_connection, await_vsync_fired,
140 loop().RunUntilIdle();
141 EXPECT_EQ(fake_flatland().debug_name(), debug_name);
146 bool error_fired =
false;
147 fml::closure on_session_error = [&error_fired]() { error_fired =
true; };
153 [](
auto...) {
FAIL(); }, loop().dispatcher());
154 EXPECT_FALSE(error_fired);
158 fake_flatland().Disconnect(
159 fuchsia::ui::composition::FlatlandError::BAD_OPERATION);
160 loop().RunUntilIdle();
166 size_t presents_called = 0u;
167 zx_handle_t release_fence_handle;
168 fake_flatland().SetPresentHandler([&presents_called,
169 &release_fence_handle](
auto present_args) {
171 release_fence_handle = present_args.release_fences().
empty()
173 : present_args.release_fences().front().get();
178 size_t vsyncs_handled = 0u;
187 std::move(on_frame_presented), loop().dispatcher());
188 EXPECT_EQ(presents_called, 0u);
189 EXPECT_EQ(vsyncs_handled, 0u);
192 loop().RunUntilIdle();
193 EXPECT_EQ(presents_called, 0u);
194 EXPECT_EQ(vsyncs_handled, 0u);
197 bool await_vsync_fired =
false;
198 AwaitVsyncChecked(flatland_connection, await_vsync_fired,
204 await_vsync_fired =
false;
207 const zx_handle_t first_release_fence_handle = first_release_fence.get();
208 flatland_connection.EnqueueReleaseFence(std::move(first_release_fence));
209 flatland_connection.Present();
210 loop().RunUntilIdle();
211 EXPECT_EQ(presents_called, 1u);
212 EXPECT_EQ(release_fence_handle, ZX_HANDLE_INVALID);
213 EXPECT_EQ(vsyncs_handled, 0u);
214 EXPECT_FALSE(await_vsync_fired);
220 fuchsia::ui::composition::OnNextFrameBeginValues on_next_frame_begin_values;
221 on_next_frame_begin_values.set_additional_present_credits(3);
222 on_next_frame_begin_values.set_future_presentation_infos(
223 CreateFuturePresentationInfos(kPresentationTime1, kPresentationTime2));
224 fake_flatland().FireOnNextFrameBeginEvent(
225 std::move(on_next_frame_begin_values));
226 loop().RunUntilIdle();
227 AwaitVsyncChecked(flatland_connection, await_vsync_fired, kPresentationTime1);
231 fake_flatland().FireOnFramePresentedEvent(
232 fuchsia::scenic::scheduling::FramePresentedInfo());
233 loop().RunUntilIdle();
234 EXPECT_EQ(vsyncs_handled, 1u);
238 await_vsync_fired =
false;
239 flatland_connection.Present();
240 loop().RunUntilIdle();
241 EXPECT_EQ(presents_called, 2u);
242 EXPECT_EQ(release_fence_handle, first_release_fence_handle);
245 await_vsync_fired =
false;
246 AwaitVsyncChecked(flatland_connection, await_vsync_fired, kPresentationTime2);
252 size_t presents_called = 0u;
253 fake_flatland().SetPresentHandler(
254 [&presents_called](
auto present_args) { presents_called++; });
260 [](
auto...) {}, loop().dispatcher());
261 EXPECT_EQ(presents_called, 0u);
264 loop().RunUntilIdle();
265 EXPECT_EQ(presents_called, 0u);
268 bool await_vsync_callback_fired =
false;
269 AwaitVsyncChecked(flatland_connection, await_vsync_callback_fired,
274 bool await_vsync_secondary_callback_fired =
false;
275 flatland_connection.AwaitVsyncForSecondaryCallback(
278 await_vsync_secondary_callback_fired =
true;
285 size_t presents_called = 0u;
286 fake_flatland().SetPresentHandler(
287 [&presents_called](
auto present_args) { presents_called++; });
291 size_t vsyncs_handled = 0u;
300 std::move(on_frame_presented), loop().dispatcher());
301 EXPECT_EQ(presents_called, 0u);
302 EXPECT_EQ(vsyncs_handled, 0u);
305 loop().RunUntilIdle();
306 EXPECT_EQ(presents_called, 0u);
307 EXPECT_EQ(vsyncs_handled, 0u);
310 bool await_vsync_callback_fired =
false;
311 AwaitVsyncChecked(flatland_connection, await_vsync_callback_fired,
316 flatland_connection.Present();
317 loop().RunUntilIdle();
318 EXPECT_EQ(presents_called, 1u);
322 await_vsync_callback_fired =
false;
323 const auto kPresentationTime1 =
326 const auto kPresentationTime2 = kPresentationTime1 + kVsyncInterval;
327 OnNextFrameBegin(1, kPresentationTime1, kPresentationTime2);
328 loop().RunUntilIdle();
329 AwaitVsyncChecked(flatland_connection, await_vsync_callback_fired,
335 await_vsync_callback_fired =
false;
336 AwaitVsyncChecked(flatland_connection, await_vsync_callback_fired,
341 await_vsync_callback_fired =
false;
342 AwaitVsyncChecked(flatland_connection, await_vsync_callback_fired,
343 kPresentationTime2 + kVsyncInterval);
349 size_t num_presents_called = 0u;
350 size_t num_release_fences = 0u;
351 size_t num_acquire_fences = 0u;
353 auto reset_test_counters = [&num_presents_called, &num_acquire_fences,
354 &num_release_fences]() {
355 num_presents_called = 0u;
356 num_release_fences = 0u;
357 num_acquire_fences = 0u;
360 fake_flatland().SetPresentHandler(
361 [&num_presents_called, &num_acquire_fences, &num_release_fences](
362 fuchsia::ui::composition::PresentArgs present_args) {
363 num_presents_called++;
364 num_acquire_fences = present_args.acquire_fences().
size();
365 num_release_fences = present_args.release_fences().
size();
373 std::move(on_frame_presented), loop().dispatcher());
374 EXPECT_EQ(num_presents_called, 0u);
377 loop().RunUntilIdle();
378 EXPECT_EQ(num_presents_called, 0u);
382 loop().RunUntilIdle();
383 EXPECT_EQ(num_presents_called, 0u);
388 auto fire_callback = [dispatcher = loop().dispatcher(), &flatland_connection](
391 async::PostTask(dispatcher, [&flatland_connection]() {
396 flatland_connection.EnqueueAcquireFence(std::move(acquire_fence));
397 flatland_connection.EnqueueReleaseFence(std::move(release_fence));
398 flatland_connection.Present();
404 reset_test_counters();
405 flatland_connection.AwaitVsync(fire_callback);
406 loop().RunUntilIdle();
407 EXPECT_EQ(num_presents_called, 1u);
408 EXPECT_EQ(num_acquire_fences, 1u);
409 EXPECT_EQ(num_release_fences, 0u);
413 reset_test_counters();
414 flatland_connection.AwaitVsync(fire_callback);
416 loop().RunUntilIdle();
417 EXPECT_EQ(num_presents_called, 0u);
421 reset_test_counters();
423 loop().RunUntilIdle();
424 EXPECT_EQ(num_presents_called, 1u);
425 EXPECT_EQ(num_acquire_fences, 1u);
426 EXPECT_EQ(num_release_fences, 1u);
434 uint num_deferred_callbacks = 0;
439 num_deferred_callbacks++;
440 if (num_deferred_callbacks > num_onfb) {
442 for (uint
i = 0;
i < num_onfb + 1;
i++) {
443 fire_callback(now, now);
444 num_deferred_callbacks--;
449 reset_test_counters();
450 for (uint
i = 0;
i < num_onfb;
i++) {
451 flatland_connection.AwaitVsync(accumulating_fire_callback);
455 OnNextFrameBegin(
i == 0 ? 1 : 0);
456 loop().RunUntilIdle();
457 EXPECT_EQ(num_presents_called, 0u);
463 flatland_connection.AwaitVsync(accumulating_fire_callback);
465 loop().RunUntilIdle();
466 EXPECT_EQ(num_presents_called, 1u);
467 EXPECT_EQ(num_acquire_fences, 1u);
468 EXPECT_EQ(num_release_fences, 1u);
473 reset_test_counters();
476 loop().RunUntilIdle();
477 EXPECT_EQ(num_presents_called, 1u);
478 EXPECT_EQ(num_acquire_fences, num_onfb);
479 EXPECT_EQ(num_release_fences, 1u);
482 reset_test_counters();
483 flatland_connection.AwaitVsync(fire_callback);
485 loop().RunUntilIdle();
486 EXPECT_EQ(num_presents_called, 1u);
487 EXPECT_EQ(num_acquire_fences, 1u);
488 EXPECT_EQ(num_release_fences, num_onfb);
492 std::shared_ptr<std::vector<zx::event>>
fences;
498 auto fences = std::make_shared<std::vector<zx::event>>();
499 auto fences_dup = std::make_shared<std::vector<zx::event>>();
500 for (
size_t i = 0;
i < num_fences;
i++) {
503 EXPECT_EQ(status, ZX_OK);
506 status = fence.duplicate(ZX_RIGHT_SAME_RIGHTS, &fence_dup);
507 EXPECT_EQ(status, ZX_OK);
509 fences->push_back(std::move(fence));
510 fences_dup->push_back(std::move(fence_dup));
514 .fences_dup = fences_dup,
519 for (
auto& fence : *fences) {
520 const auto status = fence.signal(0, ZX_EVENT_SIGNALED);
521 ASSERT_EQ(status, ZX_OK);
526 for (
auto& fence : *fences) {
527 zx_signals_t ignored;
530 fence.wait_one(ZX_EVENT_SIGNALED, zx::time::infinite(), &ignored);
531 ASSERT_EQ(status, ZX_OK);
537 size_t num_presents_called = 0u;
538 size_t num_release_fences = 0u;
539 size_t num_acquire_fences = 0u;
541 auto reset_test_counters = [&num_presents_called, &num_acquire_fences,
542 &num_release_fences]() {
543 num_presents_called = 0u;
544 num_release_fences = 0u;
545 num_acquire_fences = 0u;
548 fuchsia::ui::composition::PresentArgs last_present_args;
549 fake_flatland().SetPresentHandler(
550 [&num_presents_called, &num_acquire_fences, &num_release_fences,
551 &last_present_args](fuchsia::ui::composition::PresentArgs present_args) {
552 num_presents_called++;
553 num_acquire_fences = present_args.acquire_fences().
size();
554 num_release_fences = present_args.release_fences().
size();
556 last_present_args = std::move(present_args);
564 std::move(on_frame_presented), subloop_dispatcher());
565 EXPECT_EQ(num_presents_called, 0u);
568 loop().RunUntilIdle();
569 EXPECT_EQ(num_presents_called, 0u);
573 loop().RunUntilIdle();
574 EXPECT_EQ(num_presents_called, 0u);
583 auto fire_callback = [dispatcher = loop().dispatcher(), &flatland_connection,
587 async::PostTask(dispatcher, [&flatland_connection, rf = rfd, af = afd]() {
588 for (
auto& fence : *rf) {
590 const auto status = fence.duplicate(ZX_RIGHT_SAME_RIGHTS, &fence_dup);
591 ASSERT_EQ(status, ZX_OK);
592 flatland_connection.EnqueueReleaseFence(std::move(fence_dup));
594 for (
auto& fence : *af) {
596 const auto status = fence.duplicate(ZX_RIGHT_SAME_RIGHTS, &fence_dup);
597 ASSERT_EQ(status, ZX_OK);
598 flatland_connection.EnqueueAcquireFence(std::move(fence_dup));
600 flatland_connection.Present();
608 reset_test_counters();
609 flatland_connection.AwaitVsync(fire_callback);
611 loop().RunUntilIdle();
613 EXPECT_EQ(num_presents_called, 1u);
614 EXPECT_EQ(num_acquire_fences, 16u);
615 EXPECT_EQ(num_release_fences, 0u);
618 reset_test_counters();
621 loop().RunUntilIdle();
623 flatland_connection.AwaitVsync([dispatcher = subloop_dispatcher(),
626 async::PostTask(dispatcher,
627 [&flatland_connection] { flatland_connection.Present(); });
629 loop().RunUntilIdle();
634 SignalAll(last_present_args.mutable_release_fences());
636 loop().RunUntilIdle();
640 EXPECT_EQ(num_presents_called, 1u);
641 EXPECT_EQ(num_acquire_fences, 0u);
642 EXPECT_EQ(num_release_fences, 16u);
void FireOnNextFrameBeginEvent(fuchsia::ui::composition::OnNextFrameBeginValues on_next_frame_begin_values)
void OnNextFrameBegin(int num_present_credits, const fml::TimePoint &presentation_time_1, const fml::TimePoint &presentation_time_2)
void OnNextFrameBegin(int num_present_credits)
FakeFlatland & fake_flatland()
~FlatlandConnectionTest() override=default
fidl::InterfaceHandle< fuchsia::ui::composition::Flatland > TakeFlatlandHandle()
async_dispatcher_t * subloop_dispatcher()
static constexpr TimeDelta FromSeconds(int64_t seconds)
constexpr int64_t ToNanoseconds() const
TimeDelta ToEpochDelta() const
#define FAIL(name, result)
EMSCRIPTEN_KEEPALIVE void empty()
#define FML_CHECK(condition)
std::string GetCurrentTestName()
Gets the name of the currently running test. This is useful in generating logs or assets based on tes...
void SignalAll(std::vector< zx::event > *fences)
void WaitAll(std::vector< zx::event > *fences)
FencesPair GetFencesPair(size_t num_fences)
TEST_F(FocusDelegateTest, WatchCallbackSeries)
static constexpr size_t kMaxFences
std::function< void(fuchsia::scenic::scheduling::FramePresentedInfo)> on_frame_presented_event
static constexpr fml::TimeDelta kInitialFlatlandVsyncOffset
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
std::function< void()> closure
std::shared_ptr< std::vector< zx::event > > fences
std::shared_ptr< std::vector< zx::event > > fences_dup
#define EXPECT_TRUE(handle)