13#include "gmock/gmock.h"
23using ::testing::Invoke;
24using ::testing::ReturnRef;
40std::vector<const LayerTreeTask*> Sorted(
41 const std::vector<std::unique_ptr<LayerTreeTask>>& layer_tree_tasks) {
42 std::vector<const LayerTreeTask*> result;
43 result.reserve(layer_tree_tasks.size());
44 for (
auto& task_ptr : layer_tree_tasks) {
45 result.push_back(task_ptr.get());
47 std::sort(result.begin(), result.end(),
48 [](
const LayerTreeTask* a,
const LayerTreeTask* b) {
49 return a->view_id < b->view_id;
54class MockDelegate :
public Engine::Delegate {
57 OnEngineUpdateSemantics,
61 OnEngineSetApplicationLocale,
64 MOCK_METHOD(
void, OnEngineSetSemanticsTreeEnabled, (
bool), (
override));
66 OnEngineHandlePlatformMessage,
67 (std::unique_ptr<PlatformMessage>),
69 MOCK_METHOD(
void, OnPreEngineRestart, (), (
override));
70 MOCK_METHOD(
void, OnRootIsolateCreated, (), (
override));
72 UpdateIsolateDescription,
73 (
const std::string, int64_t),
75 MOCK_METHOD(
void, SetNeedsReportTimings, (
bool), (
override));
76 MOCK_METHOD(std::unique_ptr<std::vector<std::string>>,
77 ComputePlatformResolvedLocale,
78 (
const std::vector<std::string>&),
80 MOCK_METHOD(
void, RequestDartDeferredLibrary, (intptr_t), (
override));
82 MOCK_METHOD(
const std::shared_ptr<PlatformMessageHandler>&,
83 GetPlatformMessageHandler,
86 MOCK_METHOD(
void, OnEngineChannelUpdate, (std::string,
bool), (
override));
92 RequestViewFocusChange,
93 (
const ViewFocusChangeRequest&),
97class MockAnimatorDelegate :
public Animator::Delegate {
101 OnAnimatorBeginFrame,
105 OnAnimatorNotifyIdle,
109 OnAnimatorUpdateLatestFrameTargetTime,
114 (std::shared_ptr<FramePipeline> pipeline),
117 OnAnimatorDrawLastLayerTrees,
118 (std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder),
125 HandlePlatformMessage,
126 (std::unique_ptr<PlatformMessage>
message),
129 DoesHandlePlatformMessageOnPlatformThread,
134 (
int response_id, std::unique_ptr<fml::Mapping> mapping),
142class EngineAnimatorTest :
public testing::FixtureTest {
146 ThreadHost::Type::kPlatform | ThreadHost::Type::kIo |
147 ThreadHost::Type::kUi | ThreadHost::Type::
kRaster),
149 "EngineAnimatorTest",
156 void PostUITaskSync(
const std::function<
void()>& function) {
166 void SetUp()
override {
191 using EngineCallback = std::function<void(Engine&)>;
193 [[nodiscard]]
static std::unique_ptr<EngineContext>
Create(
194 Engine::Delegate& delegate,
196 const TaskRunners& task_runners,
197 std::unique_ptr<Animator> animator) {
199 FML_CHECK(vm) <<
"Must be able to initialize the VM.";
202 EngineContext* raw_pointer =
203 new EngineContext(delegate, settings, task_runners, std::move(animator),
204 vm, isolate_snapshot);
205 return std::unique_ptr<EngineContext>(raw_pointer);
208 void Run(RunConfiguration configuration) {
209 PostSync(
task_runners_.GetUITaskRunner(), [
this, &configuration] {
210 Engine::RunStatus run_status = engine_->Run(std::move(configuration));
211 FML_CHECK(run_status == Engine::RunStatus::Success)
212 <<
"Engine failed to run.";
221 void EngineTaskSync(EngineCallback task) {
222 ASSERT_TRUE(engine_);
225 if (runner->RunsTasksOnCurrentThread()) {
228 PostSync(
task_runners_.GetUITaskRunner(), [&]() { task(*engine_); });
233 PostSync(
task_runners_.GetUITaskRunner(), [
this] { engine_.reset(); });
237 EngineContext(Engine::Delegate& delegate,
239 const TaskRunners& task_runners,
240 std::unique_ptr<Animator> animator,
244 PostSync(task_runners.GetUITaskRunner(), [
this, &settings, &animator,
245 &delegate, &isolate_snapshot] {
246 auto dispatcher_maker =
247 [](DefaultPointerDataDispatcher::Delegate& delegate) {
248 return std::make_unique<DefaultPointerDataDispatcher>(delegate);
250 std::promise<impeller::RuntimeStageBackend> rsb;
252 engine_ = std::make_unique<Engine>(
256 std::move(isolate_snapshot),
264 std::make_shared<fml::SyncSwitch>(),
271 std::unique_ptr<Engine> engine_;
278TEST_F(EngineAnimatorTest, AnimatorAcceptsMultipleRenders) {
279 MockAnimatorDelegate animator_delegate;
280 std::unique_ptr<EngineContext> engine_context;
282 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
283 std::make_shared<MockPlatformMessageHandler>();
284 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
285 .WillOnce(ReturnRef(platform_message_handler));
287 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
289 Invoke([&draw_latch](
const std::shared_ptr<FramePipeline>& pipeline) {
291 pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
292 auto tasks = Sorted(item->layer_tree_tasks);
293 EXPECT_EQ(tasks.size(), 2u);
294 EXPECT_EQ(tasks[0]->
view_id, 1);
295 EXPECT_EQ(tasks[1]->
view_id, 2);
297 EXPECT_EQ(status, PipelineConsumeResult::Done);
300 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
301 .WillOnce(Invoke([&engine_context](
fml::TimePoint frame_target_time,
302 uint64_t frame_number) {
304 engine.BeginFrame(frame_target_time, frame_number);
308 native_latch.
Reset();
309 AddNativeCallback(
"NotifyNative", [](
auto args) { native_latch.
Signal(); });
311 std::unique_ptr<Animator> animator;
313 [&animator, &animator_delegate, &task_runners =
task_runners_] {
314 animator = std::make_unique<Animator>(
315 animator_delegate, task_runners,
316 static_cast<std::unique_ptr<VsyncWaiter>>(
317 std::make_unique<testing::ConstantFiringVsyncWaiter>(
322 std::move(animator));
323 auto configuration = RunConfiguration::InferFromSettings(
settings_);
324 configuration.SetEntrypoint(
"onDrawFrameRenderAllViews");
325 engine_context->Run(std::move(configuration));
329 [](
bool added) { ASSERT_TRUE(added); });
331 [](
bool added) { ASSERT_TRUE(added); });
336 engine_context->EngineTaskSync(
341TEST_F(EngineAnimatorTest, IgnoresOutOfFrameRenders) {
342 MockAnimatorDelegate animator_delegate;
343 std::unique_ptr<EngineContext> engine_context;
345 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
346 std::make_shared<MockPlatformMessageHandler>();
347 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
348 .WillOnce(ReturnRef(platform_message_handler));
350 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
352 Invoke([&draw_latch](
const std::shared_ptr<FramePipeline>& pipeline) {
354 pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
357 EXPECT_EQ(item->layer_tree_tasks.size(), 1u);
358 EXPECT_EQ(item->layer_tree_tasks[0]->view_id, 2);
360 EXPECT_EQ(status, PipelineConsumeResult::Done);
363 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
364 .WillOnce(Invoke([&engine_context](
fml::TimePoint frame_target_time,
365 uint64_t frame_number) {
367 engine.BeginFrame(frame_target_time, frame_number);
371 std::unique_ptr<Animator> animator;
373 [&animator, &animator_delegate, &task_runners =
task_runners_] {
374 animator = std::make_unique<Animator>(
375 animator_delegate, task_runners,
376 static_cast<std::unique_ptr<VsyncWaiter>>(
377 std::make_unique<testing::ConstantFiringVsyncWaiter>(
382 std::move(animator));
386 [](
bool added) { ASSERT_TRUE(added); });
388 [](
bool added) { ASSERT_TRUE(added); });
391 auto configuration = RunConfiguration::InferFromSettings(
settings_);
392 configuration.SetEntrypoint(
"renderViewsInFrameAndOutOfFrame");
393 engine_context->Run(std::move(configuration));
398TEST_F(EngineAnimatorTest, IgnoresDuplicateRenders) {
399 MockAnimatorDelegate animator_delegate;
400 std::unique_ptr<EngineContext> engine_context;
402 std::vector<std::shared_ptr<Layer>> benchmark_layers;
403 auto capture_root_layer = [&benchmark_layers](Dart_NativeArguments
args) {
404 auto handle = Dart_GetNativeArgument(
args, 0);
406 Dart_Handle result = Dart_GetNativeInstanceField(
408 ASSERT_FALSE(Dart_IsError(result));
410 ASSERT_TRUE(scene_builder);
411 std::shared_ptr<ContainerLayer> root_layer =
413 ASSERT_TRUE(root_layer);
414 benchmark_layers = root_layer->layers();
417 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
418 std::make_shared<MockPlatformMessageHandler>();
419 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
420 .WillOnce(ReturnRef(platform_message_handler));
422 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
423 .WillOnce(Invoke([&draw_latch, &benchmark_layers](
424 const std::shared_ptr<FramePipeline>& pipeline) {
425 auto status = pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
426 EXPECT_EQ(item->layer_tree_tasks.size(), 1u);
429 item->layer_tree_tasks[0]->layer_tree->root_layer());
430 std::vector<std::shared_ptr<Layer>> result_layers =
432 EXPECT_EQ(result_layers.size(), benchmark_layers.size());
433 EXPECT_EQ(result_layers[0], benchmark_layers[0]);
435 EXPECT_EQ(status, PipelineConsumeResult::Done);
438 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
439 .WillOnce(Invoke([&engine_context](
fml::TimePoint frame_target_time,
440 uint64_t frame_number) {
442 engine.BeginFrame(frame_target_time, frame_number);
446 AddNativeCallback(
"CaptureRootLayer",
449 std::unique_ptr<Animator> animator;
451 [&animator, &animator_delegate, &task_runners =
task_runners_] {
452 animator = std::make_unique<Animator>(
453 animator_delegate, task_runners,
454 static_cast<std::unique_ptr<VsyncWaiter>>(
455 std::make_unique<testing::ConstantFiringVsyncWaiter>(
460 std::move(animator));
464 [](
bool added) { ASSERT_TRUE(added); });
467 auto configuration = RunConfiguration::InferFromSettings(
settings_);
468 configuration.SetEntrypoint(
"renderTwiceForOneView");
469 engine_context->Run(std::move(configuration));
474TEST_F(EngineAnimatorTest, AnimatorSubmitsImplicitViewBeforeDrawFrameEnds) {
475 MockAnimatorDelegate animator_delegate;
476 std::unique_ptr<EngineContext> engine_context;
478 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
479 std::make_shared<MockPlatformMessageHandler>();
480 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
481 .WillOnce(ReturnRef(platform_message_handler));
483 bool rasterization_started =
false;
484 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
485 .WillOnce(Invoke([&rasterization_started](
486 const std::shared_ptr<FramePipeline>& pipeline) {
487 rasterization_started =
true;
488 auto status = pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
489 EXPECT_EQ(item->layer_tree_tasks.size(), 1u);
492 EXPECT_EQ(status, PipelineConsumeResult::Done);
494 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
495 .WillRepeatedly(Invoke([&engine_context](
fml::TimePoint frame_target_time,
496 uint64_t frame_number) {
498 engine.BeginFrame(frame_target_time, frame_number);
502 std::unique_ptr<Animator> animator;
504 [&animator, &animator_delegate, &task_runners =
task_runners_] {
505 animator = std::make_unique<Animator>(
506 animator_delegate, task_runners,
507 static_cast<std::unique_ptr<VsyncWaiter>>(
508 std::make_unique<testing::ConstantFiringVsyncWaiter>(
512 native_latch.
Reset();
514 AddNativeCallback(
"NotifyNative",
516 EXPECT_EQ(rasterization_started,
true);
521 std::move(animator));
525 [](
bool added) { ASSERT_TRUE(added); });
528 auto configuration = RunConfiguration::InferFromSettings(
settings_);
529 configuration.SetEntrypoint(
"renderSingleViewAndCallAfterOnDrawFrame");
530 engine_context->Run(std::move(configuration));
538TEST_F(EngineAnimatorTest, AnimatorSubmitWarmUpImplicitView) {
539 MockAnimatorDelegate animator_delegate;
540 std::unique_ptr<EngineContext> engine_context;
542 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
543 std::make_shared<MockPlatformMessageHandler>();
544 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
545 .WillOnce(ReturnRef(platform_message_handler));
549 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
550 .WillOnce(Invoke([&draw_latch](
551 const std::shared_ptr<FramePipeline>& pipeline) {
552 auto status = pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
553 EXPECT_EQ(item->layer_tree_tasks.size(), 1u);
556 EXPECT_EQ(status, PipelineConsumeResult::Done);
559 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
561 Invoke([&engine_context, &continuation_ready_latch](
563 continuation_ready_latch.
Signal();
565 engine.BeginFrame(frame_target_time, frame_number);
569 std::unique_ptr<Animator> animator;
571 [&animator, &animator_delegate, &task_runners =
task_runners_] {
572 animator = std::make_unique<Animator>(
573 animator_delegate, task_runners,
574 static_cast<std::unique_ptr<VsyncWaiter>>(
575 std::make_unique<testing::ConstantFiringVsyncWaiter>(
580 std::move(animator));
586 engine.ScheduleFrame(
true);
590 [](
bool added) { ASSERT_TRUE(added); });
592 continuation_ready_latch.
Wait();
594 auto configuration = RunConfiguration::InferFromSettings(
settings_);
595 configuration.SetEntrypoint(
"renderWarmUpImplicitView");
596 engine_context->Run(std::move(configuration));
605TEST_F(EngineAnimatorTest, AnimatorSubmitPartialViewsForWarmUp) {
606 MockAnimatorDelegate animator_delegate;
607 std::unique_ptr<EngineContext> engine_context;
609 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
610 std::make_shared<MockPlatformMessageHandler>();
611 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
612 .WillOnce(ReturnRef(platform_message_handler));
616 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
618 Invoke([&draw_latch](
const std::shared_ptr<FramePipeline>& pipeline) {
620 pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
621 auto tasks = Sorted(item->layer_tree_tasks);
622 EXPECT_EQ(tasks.size(), 2u);
623 EXPECT_EQ(tasks[0]->
view_id, 1);
624 EXPECT_EQ(tasks[1]->
view_id, 2);
626 EXPECT_EQ(status, PipelineConsumeResult::Done);
629 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
631 Invoke([&engine_context, &continuation_ready_latch](
633 continuation_ready_latch.
Signal();
635 engine.BeginFrame(frame_target_time, frame_number);
639 std::unique_ptr<Animator> animator;
641 [&animator, &animator_delegate, &task_runners =
task_runners_] {
642 animator = std::make_unique<Animator>(
643 animator_delegate, task_runners,
644 static_cast<std::unique_ptr<VsyncWaiter>>(
645 std::make_unique<testing::ConstantFiringVsyncWaiter>(
650 std::move(animator));
654 engine.ScheduleFrame(
true);
657 [](
bool added) { ASSERT_TRUE(added); });
659 [](
bool added) { ASSERT_TRUE(added); });
661 [](
bool added) { ASSERT_TRUE(added); });
664 continuation_ready_latch.
Wait();
666 auto configuration = RunConfiguration::InferFromSettings(
settings_);
667 configuration.SetEntrypoint(
"renderWarmUpView1and2");
668 engine_context->Run(std::move(configuration));
TEST_F(FlutterDisplayLinkTest, ViewAddedToWindowFirst)
const std::vector< std::shared_ptr< Layer > > & layers() const
const std::vector< std::shared_ptr< ContainerLayer > > & layer_stack()
static std::pair< DartVMRef, fml::RefPtr< const DartSnapshot > > InferVmInitDataFromSettings(Settings &settings)
static void RunNowOrPostTask(const fml::RefPtr< fml::TaskRunner > &runner, const fml::closure &task)
@ kRaster
Suitable for thread which raster data.
std::shared_ptr< fml::ConcurrentTaskRunner > image_decoder_task_runner_
std::unique_ptr< RuntimeController > runtime_controller_
TaskRunners task_runners_
fml::TaskRunnerAffineWeakPtr< SnapshotDelegate > snapshot_delegate_
std::unique_ptr< Animator > animator_
PointerDataDispatcherMaker dispatcher_maker_
fml::WeakPtr< IOManager > io_manager_
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_BEGIN_DECLS GBytes * message
G_BEGIN_DECLS FlutterViewId view_id
#define FML_CHECK(condition)
Dart_NativeFunction function
constexpr int64_t kFlutterImplicitViewId
static void InvokePlatformMessageResponseCallback(JNIEnv *env, jobject jcaller, jlong shell_holder, jint responseId, jobject message, jint position)
std::unordered_map< int32_t, SemanticsNode > SemanticsNodeUpdates
static void InvokePlatformMessageEmptyResponseCallback(JNIEnv *env, jobject jcaller, jlong shell_holder, jint responseId)
std::unordered_map< int32_t, CustomAccessibilityAction > CustomAccessibilityActionUpdates
std::function< std::unique_ptr< PointerDataDispatcher >(PointerDataDispatcher::Delegate &)> PointerDataDispatcherMaker
Signature for constructing PointerDataDispatcher.
std::function< void()> closure
ScopedObject< Object > Create(CtorArgs &&... args)
#define CREATE_NATIVE_ENTRY(native_entry)