13#include "gmock/gmock.h"
23using ::testing::ReturnRef;
39std::vector<const LayerTreeTask*> Sorted(
40 const std::vector<std::unique_ptr<LayerTreeTask>>& layer_tree_tasks) {
41 std::vector<const LayerTreeTask*> result;
42 result.reserve(layer_tree_tasks.size());
43 for (
auto& task_ptr : layer_tree_tasks) {
44 result.push_back(task_ptr.get());
46 std::sort(result.begin(), result.end(),
47 [](
const LayerTreeTask* a,
const LayerTreeTask* b) {
48 return a->view_id < b->view_id;
53class MockDelegate :
public Engine::Delegate {
56 OnEngineUpdateSemantics,
60 OnEngineSetApplicationLocale,
63 MOCK_METHOD(
void, OnEngineSetSemanticsTreeEnabled, (
bool), (
override));
65 OnEngineHandlePlatformMessage,
66 (std::unique_ptr<PlatformMessage>),
68 MOCK_METHOD(
void, OnPreEngineRestart, (), (
override));
69 MOCK_METHOD(
void, OnRootIsolateCreated, (), (
override));
71 UpdateIsolateDescription,
72 (
const std::string, int64_t),
74 MOCK_METHOD(
void, SetNeedsReportTimings, (
bool), (
override));
75 MOCK_METHOD(std::unique_ptr<std::vector<std::string>>,
76 ComputePlatformResolvedLocale,
77 (
const std::vector<std::string>&),
79 MOCK_METHOD(
void, RequestDartDeferredLibrary, (intptr_t), (
override));
81 MOCK_METHOD(
const std::shared_ptr<PlatformMessageHandler>&,
82 GetPlatformMessageHandler,
85 MOCK_METHOD(
void, OnEngineChannelUpdate, (std::string,
bool), (
override));
91 RequestViewFocusChange,
92 (
const ViewFocusChangeRequest&),
96class MockAnimatorDelegate :
public Animator::Delegate {
100 OnAnimatorBeginFrame,
104 OnAnimatorNotifyIdle,
108 OnAnimatorUpdateLatestFrameTargetTime,
113 (std::shared_ptr<FramePipeline> pipeline),
116 OnAnimatorDrawLastLayerTrees,
117 (std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder),
124 HandlePlatformMessage,
125 (std::unique_ptr<PlatformMessage>
message),
128 DoesHandlePlatformMessageOnPlatformThread,
133 (
int response_id, std::unique_ptr<fml::Mapping> mapping),
141class EngineAnimatorTest :
public testing::FixtureTest {
145 ThreadHost::Type::kPlatform | ThreadHost::Type::kIo |
146 ThreadHost::Type::kUi | ThreadHost::Type::
kRaster),
148 "EngineAnimatorTest",
155 void PostUITaskSync(
const std::function<
void()>& function) {
165 void SetUp()
override {
190 using EngineCallback = std::function<void(Engine&)>;
192 [[nodiscard]]
static std::unique_ptr<EngineContext>
Create(
193 Engine::Delegate& delegate,
195 const TaskRunners& task_runners,
196 std::unique_ptr<Animator> animator) {
198 FML_CHECK(vm) <<
"Must be able to initialize the VM.";
201 EngineContext* raw_pointer =
202 new EngineContext(delegate, settings, task_runners, std::move(animator),
203 vm, isolate_snapshot);
204 return std::unique_ptr<EngineContext>(raw_pointer);
207 void Run(RunConfiguration configuration) {
208 PostSync(
task_runners_.GetUITaskRunner(), [
this, &configuration] {
209 Engine::RunStatus run_status = engine_->Run(std::move(configuration));
210 FML_CHECK(run_status == Engine::RunStatus::Success)
211 <<
"Engine failed to run.";
220 void EngineTaskSync(EngineCallback task) {
221 ASSERT_TRUE(engine_);
224 if (runner->RunsTasksOnCurrentThread()) {
227 PostSync(
task_runners_.GetUITaskRunner(), [&]() { task(*engine_); });
232 PostSync(
task_runners_.GetUITaskRunner(), [
this] { engine_.reset(); });
236 EngineContext(Engine::Delegate& delegate,
238 const TaskRunners& task_runners,
239 std::unique_ptr<Animator> animator,
243 PostSync(task_runners.GetUITaskRunner(), [
this, &settings, &animator,
244 &delegate, &isolate_snapshot] {
245 auto dispatcher_maker =
246 [](DefaultPointerDataDispatcher::Delegate& delegate) {
247 return std::make_unique<DefaultPointerDataDispatcher>(delegate);
249 std::promise<impeller::RuntimeStageBackend> rsb;
251 engine_ = std::make_unique<Engine>(
255 std::move(isolate_snapshot),
263 std::make_shared<fml::SyncSwitch>(),
270 std::unique_ptr<Engine> engine_;
277TEST_F(EngineAnimatorTest, AnimatorAcceptsMultipleRenders) {
278 MockAnimatorDelegate animator_delegate;
279 std::unique_ptr<EngineContext> engine_context;
281 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
282 std::make_shared<MockPlatformMessageHandler>();
283 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
284 .WillOnce(ReturnRef(platform_message_handler));
286 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
287 .WillOnce([&draw_latch](
const std::shared_ptr<FramePipeline>& pipeline) {
288 auto status = pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
289 auto tasks = Sorted(item->layer_tree_tasks);
290 EXPECT_EQ(tasks.size(), 2u);
291 EXPECT_EQ(tasks[0]->
view_id, 1);
292 EXPECT_EQ(tasks[1]->
view_id, 2);
294 EXPECT_EQ(status, PipelineConsumeResult::Done);
297 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
299 uint64_t frame_number) {
301 engine.BeginFrame(frame_target_time, frame_number);
305 native_latch.
Reset();
306 AddNativeCallback(
"NotifyNative", [](
auto args) { native_latch.
Signal(); });
308 std::unique_ptr<Animator> animator;
310 [&animator, &animator_delegate, &task_runners =
task_runners_] {
311 animator = std::make_unique<Animator>(
312 animator_delegate, task_runners,
313 static_cast<std::unique_ptr<VsyncWaiter>>(
314 std::make_unique<testing::ConstantFiringVsyncWaiter>(
319 std::move(animator));
320 auto configuration = RunConfiguration::InferFromSettings(
settings_);
321 configuration.SetEntrypoint(
"onDrawFrameRenderAllViews");
322 engine_context->Run(std::move(configuration));
326 [](
bool added) { ASSERT_TRUE(added); });
328 [](
bool added) { ASSERT_TRUE(added); });
333 engine_context->EngineTaskSync(
338TEST_F(EngineAnimatorTest, IgnoresOutOfFrameRenders) {
339 MockAnimatorDelegate animator_delegate;
340 std::unique_ptr<EngineContext> engine_context;
342 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
343 std::make_shared<MockPlatformMessageHandler>();
344 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
345 .WillOnce(ReturnRef(platform_message_handler));
347 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
348 .WillOnce([&draw_latch](
const std::shared_ptr<FramePipeline>& pipeline) {
349 auto status = pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
352 EXPECT_EQ(item->layer_tree_tasks.size(), 1u);
353 EXPECT_EQ(item->layer_tree_tasks[0]->view_id, 2);
355 EXPECT_EQ(status, PipelineConsumeResult::Done);
358 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
360 uint64_t frame_number) {
362 engine.BeginFrame(frame_target_time, frame_number);
366 std::unique_ptr<Animator> animator;
368 [&animator, &animator_delegate, &task_runners =
task_runners_] {
369 animator = std::make_unique<Animator>(
370 animator_delegate, task_runners,
371 static_cast<std::unique_ptr<VsyncWaiter>>(
372 std::make_unique<testing::ConstantFiringVsyncWaiter>(
377 std::move(animator));
381 [](
bool added) { ASSERT_TRUE(added); });
383 [](
bool added) { ASSERT_TRUE(added); });
386 auto configuration = RunConfiguration::InferFromSettings(
settings_);
387 configuration.SetEntrypoint(
"renderViewsInFrameAndOutOfFrame");
388 engine_context->Run(std::move(configuration));
393TEST_F(EngineAnimatorTest, IgnoresDuplicateRenders) {
394 MockAnimatorDelegate animator_delegate;
395 std::unique_ptr<EngineContext> engine_context;
397 std::vector<std::shared_ptr<Layer>> benchmark_layers;
398 auto capture_root_layer = [&benchmark_layers](Dart_NativeArguments
args) {
399 auto handle = Dart_GetNativeArgument(
args, 0);
401 Dart_Handle result = Dart_GetNativeInstanceField(
403 ASSERT_FALSE(Dart_IsError(result));
405 ASSERT_TRUE(scene_builder);
406 std::shared_ptr<ContainerLayer> root_layer =
408 ASSERT_TRUE(root_layer);
409 benchmark_layers = root_layer->layers();
412 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
413 std::make_shared<MockPlatformMessageHandler>();
414 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
415 .WillOnce(ReturnRef(platform_message_handler));
417 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
418 .WillOnce([&draw_latch, &benchmark_layers](
419 const std::shared_ptr<FramePipeline>& pipeline) {
420 auto status = pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
421 EXPECT_EQ(item->layer_tree_tasks.size(), 1u);
424 item->layer_tree_tasks[0]->layer_tree->root_layer());
425 std::vector<std::shared_ptr<Layer>> result_layers =
427 EXPECT_EQ(result_layers.size(), benchmark_layers.size());
428 EXPECT_EQ(result_layers[0], benchmark_layers[0]);
430 EXPECT_EQ(status, PipelineConsumeResult::Done);
433 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
435 uint64_t frame_number) {
437 engine.BeginFrame(frame_target_time, frame_number);
441 AddNativeCallback(
"CaptureRootLayer",
444 std::unique_ptr<Animator> animator;
446 [&animator, &animator_delegate, &task_runners =
task_runners_] {
447 animator = std::make_unique<Animator>(
448 animator_delegate, task_runners,
449 static_cast<std::unique_ptr<VsyncWaiter>>(
450 std::make_unique<testing::ConstantFiringVsyncWaiter>(
455 std::move(animator));
459 [](
bool added) { ASSERT_TRUE(added); });
462 auto configuration = RunConfiguration::InferFromSettings(
settings_);
463 configuration.SetEntrypoint(
"renderTwiceForOneView");
464 engine_context->Run(std::move(configuration));
469TEST_F(EngineAnimatorTest, AnimatorSubmitsImplicitViewBeforeDrawFrameEnds) {
470 MockAnimatorDelegate animator_delegate;
471 std::unique_ptr<EngineContext> engine_context;
473 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
474 std::make_shared<MockPlatformMessageHandler>();
475 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
476 .WillOnce(ReturnRef(platform_message_handler));
478 bool rasterization_started =
false;
479 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
480 .WillOnce([&rasterization_started](
481 const std::shared_ptr<FramePipeline>& pipeline) {
482 rasterization_started =
true;
483 auto status = pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
484 EXPECT_EQ(item->layer_tree_tasks.size(), 1u);
487 EXPECT_EQ(status, PipelineConsumeResult::Done);
489 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
490 .WillRepeatedly([&engine_context](
fml::TimePoint frame_target_time,
491 uint64_t frame_number) {
493 engine.BeginFrame(frame_target_time, frame_number);
497 std::unique_ptr<Animator> animator;
499 [&animator, &animator_delegate, &task_runners =
task_runners_] {
500 animator = std::make_unique<Animator>(
501 animator_delegate, task_runners,
502 static_cast<std::unique_ptr<VsyncWaiter>>(
503 std::make_unique<testing::ConstantFiringVsyncWaiter>(
507 native_latch.
Reset();
509 AddNativeCallback(
"NotifyNative",
511 EXPECT_EQ(rasterization_started,
true);
516 std::move(animator));
520 [](
bool added) { ASSERT_TRUE(added); });
523 auto configuration = RunConfiguration::InferFromSettings(
settings_);
524 configuration.SetEntrypoint(
"renderSingleViewAndCallAfterOnDrawFrame");
525 engine_context->Run(std::move(configuration));
533TEST_F(EngineAnimatorTest, AnimatorSubmitWarmUpImplicitView) {
534 MockAnimatorDelegate animator_delegate;
535 std::unique_ptr<EngineContext> engine_context;
537 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
538 std::make_shared<MockPlatformMessageHandler>();
539 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
540 .WillOnce(ReturnRef(platform_message_handler));
544 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
545 .WillOnce([&draw_latch](
const std::shared_ptr<FramePipeline>& pipeline) {
546 auto status = pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
547 EXPECT_EQ(item->layer_tree_tasks.size(), 1u);
550 EXPECT_EQ(status, PipelineConsumeResult::Done);
553 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
555 [&engine_context, &continuation_ready_latch](
557 continuation_ready_latch.
Signal();
559 engine.BeginFrame(frame_target_time, frame_number);
563 std::unique_ptr<Animator> animator;
565 [&animator, &animator_delegate, &task_runners =
task_runners_] {
566 animator = std::make_unique<Animator>(
567 animator_delegate, task_runners,
568 static_cast<std::unique_ptr<VsyncWaiter>>(
569 std::make_unique<testing::ConstantFiringVsyncWaiter>(
574 std::move(animator));
580 engine.ScheduleFrame(
true);
584 [](
bool added) { ASSERT_TRUE(added); });
586 continuation_ready_latch.
Wait();
588 auto configuration = RunConfiguration::InferFromSettings(
settings_);
589 configuration.SetEntrypoint(
"renderWarmUpImplicitView");
590 engine_context->Run(std::move(configuration));
599TEST_F(EngineAnimatorTest, AnimatorSubmitPartialViewsForWarmUp) {
600 MockAnimatorDelegate animator_delegate;
601 std::unique_ptr<EngineContext> engine_context;
603 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
604 std::make_shared<MockPlatformMessageHandler>();
605 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
606 .WillOnce(ReturnRef(platform_message_handler));
610 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
611 .WillOnce([&draw_latch](
const std::shared_ptr<FramePipeline>& pipeline) {
612 auto status = pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
613 auto tasks = Sorted(item->layer_tree_tasks);
614 EXPECT_EQ(tasks.size(), 2u);
615 EXPECT_EQ(tasks[0]->
view_id, 1);
616 EXPECT_EQ(tasks[1]->
view_id, 2);
618 EXPECT_EQ(status, PipelineConsumeResult::Done);
621 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
623 [&engine_context, &continuation_ready_latch](
625 continuation_ready_latch.
Signal();
627 engine.BeginFrame(frame_target_time, frame_number);
631 std::unique_ptr<Animator> animator;
633 [&animator, &animator_delegate, &task_runners =
task_runners_] {
634 animator = std::make_unique<Animator>(
635 animator_delegate, task_runners,
636 static_cast<std::unique_ptr<VsyncWaiter>>(
637 std::make_unique<testing::ConstantFiringVsyncWaiter>(
642 std::move(animator));
646 engine.ScheduleFrame(
true);
649 [](
bool added) { ASSERT_TRUE(added); });
651 [](
bool added) { ASSERT_TRUE(added); });
653 [](
bool added) { ASSERT_TRUE(added); });
656 continuation_ready_latch.
Wait();
658 auto configuration = RunConfiguration::InferFromSettings(
settings_);
659 configuration.SetEntrypoint(
"renderWarmUpView1and2");
660 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 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)