5#include "flutter/shell/common/engine.h"
9#include "flutter/common/constants.h"
10#include "flutter/lib/ui/compositing/scene_builder.h"
11#include "flutter/shell/common/shell_test.h"
12#include "flutter/testing/fixture_test.h"
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());
47 [](
const LayerTreeTask*
a,
const LayerTreeTask*
b) {
48 return a->view_id < b->view_id;
53class MockDelegate :
public Engine::Delegate {
56 OnEngineUpdateSemantics,
60 OnEngineHandlePlatformMessage,
61 (std::unique_ptr<PlatformMessage>),
63 MOCK_METHOD(
void, OnPreEngineRestart, (), (
override));
64 MOCK_METHOD(
void, OnRootIsolateCreated, (), (
override));
66 UpdateIsolateDescription,
67 (
const std::string, int64_t),
69 MOCK_METHOD(
void, SetNeedsReportTimings, (
bool), (
override));
70 MOCK_METHOD(std::unique_ptr<std::vector<std::string>>,
71 ComputePlatformResolvedLocale,
72 (
const std::vector<std::string>&),
74 MOCK_METHOD(
void, RequestDartDeferredLibrary, (intptr_t), (
override));
76 MOCK_METHOD(
const std::shared_ptr<PlatformMessageHandler>&,
77 GetPlatformMessageHandler,
80 MOCK_METHOD(
void, OnEngineChannelUpdate, (std::string,
bool), (
override));
87class MockAnimatorDelegate :
public Animator::Delegate {
99 OnAnimatorUpdateLatestFrameTargetTime,
104 (std::shared_ptr<FramePipeline> pipeline),
107 OnAnimatorDrawLastLayerTrees,
108 (std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder),
115 HandlePlatformMessage,
116 (std::unique_ptr<PlatformMessage>
message),
119 DoesHandlePlatformMessageOnPlatformThread,
124 (
int response_id, std::unique_ptr<fml::Mapping> mapping),
132class EngineAnimatorTest :
public testing::FixtureTest {
136 ThreadHost::
Type::kPlatform | ThreadHost::
Type::kIo |
139 "EngineAnimatorTest",
156 void SetUp()
override {
183 [[nodiscard]]
static std::unique_ptr<EngineContext>
Create(
184 Engine::Delegate& delegate,
186 const TaskRunners& task_runners,
187 std::unique_ptr<Animator> animator) {
189 FML_CHECK(vm) <<
"Must be able to initialize the VM.";
192 EngineContext* raw_pointer =
193 new EngineContext(delegate,
settings, task_runners, std::move(animator),
194 vm, isolate_snapshot);
195 return std::unique_ptr<EngineContext>(raw_pointer);
198 void Run(RunConfiguration configuration) {
200 Engine::RunStatus run_status = engine_->Run(std::move(configuration));
201 FML_CHECK(run_status == Engine::RunStatus::Success)
202 <<
"Engine failed to run.";
211 void EngineTaskSync(EngineCallback task) {
212 ASSERT_TRUE(engine_);
215 if (runner->RunsTasksOnCurrentThread()) {
227 EngineContext(Engine::Delegate& delegate,
229 const TaskRunners& task_runners,
230 std::unique_ptr<Animator> animator,
235 &delegate, &isolate_snapshot] {
236 auto dispatcher_maker =
237 [](DefaultPointerDataDispatcher::Delegate& delegate) {
238 return std::make_unique<DefaultPointerDataDispatcher>(delegate);
240 engine_ = std::make_unique<Engine>(
244 std::move(isolate_snapshot),
253 std::make_shared<fml::SyncSwitch>());
259 std::unique_ptr<Engine> engine_;
266TEST_F(EngineAnimatorTest, AnimatorAcceptsMultipleRenders) {
267 MockAnimatorDelegate animator_delegate;
268 std::unique_ptr<EngineContext> engine_context;
270 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
271 std::make_shared<MockPlatformMessageHandler>();
272 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
273 .WillOnce(ReturnRef(platform_message_handler));
275 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
277 Invoke([&draw_latch](
const std::shared_ptr<FramePipeline>& pipeline) {
279 pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
280 auto tasks = Sorted(item->layer_tree_tasks);
281 EXPECT_EQ(tasks.size(), 2u);
282 EXPECT_EQ(tasks[0]->view_id, 1);
283 EXPECT_EQ(tasks[1]->view_id, 2);
285 EXPECT_EQ(status, PipelineConsumeResult::Done);
288 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
290 uint64_t frame_number) {
292 engine.BeginFrame(frame_target_time, frame_number);
296 native_latch.
Reset();
297 AddNativeCallback(
"NotifyNative", [](
auto args) { native_latch.
Signal(); });
299 std::unique_ptr<Animator> animator;
301 [&animator, &animator_delegate, &task_runners =
task_runners_] {
302 animator = std::make_unique<Animator>(
303 animator_delegate, task_runners,
304 static_cast<std::unique_ptr<VsyncWaiter>>(
305 std::make_unique<testing::ConstantFiringVsyncWaiter>(
310 std::move(animator));
311 auto configuration = RunConfiguration::InferFromSettings(
settings_);
312 configuration.SetEntrypoint(
"onDrawFrameRenderAllViews");
313 engine_context->Run(std::move(configuration));
317 [](
bool added) { ASSERT_TRUE(added); });
319 [](
bool added) { ASSERT_TRUE(added); });
324 engine_context->EngineTaskSync(
329TEST_F(EngineAnimatorTest, IgnoresOutOfFrameRenders) {
330 MockAnimatorDelegate animator_delegate;
331 std::unique_ptr<EngineContext> engine_context;
333 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
334 std::make_shared<MockPlatformMessageHandler>();
335 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
336 .WillOnce(ReturnRef(platform_message_handler));
338 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
340 Invoke([&draw_latch](
const std::shared_ptr<FramePipeline>& pipeline) {
342 pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
345 EXPECT_EQ(item->layer_tree_tasks.size(), 1u);
346 EXPECT_EQ(item->layer_tree_tasks[0]->view_id, 2);
348 EXPECT_EQ(status, PipelineConsumeResult::Done);
351 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
353 uint64_t frame_number) {
355 engine.BeginFrame(frame_target_time, frame_number);
359 std::unique_ptr<Animator> animator;
361 [&animator, &animator_delegate, &task_runners =
task_runners_] {
362 animator = std::make_unique<Animator>(
363 animator_delegate, task_runners,
364 static_cast<std::unique_ptr<VsyncWaiter>>(
365 std::make_unique<testing::ConstantFiringVsyncWaiter>(
370 std::move(animator));
374 [](
bool added) { ASSERT_TRUE(added); });
376 [](
bool added) { ASSERT_TRUE(added); });
379 auto configuration = RunConfiguration::InferFromSettings(
settings_);
380 configuration.SetEntrypoint(
"renderViewsInFrameAndOutOfFrame");
381 engine_context->Run(std::move(configuration));
386TEST_F(EngineAnimatorTest, IgnoresDuplicateRenders) {
387 MockAnimatorDelegate animator_delegate;
388 std::unique_ptr<EngineContext> engine_context;
390 std::vector<std::shared_ptr<Layer>> benchmark_layers;
398 ASSERT_TRUE(scene_builder);
399 std::shared_ptr<ContainerLayer> root_layer =
401 ASSERT_TRUE(root_layer);
402 benchmark_layers = root_layer->layers();
405 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
406 std::make_shared<MockPlatformMessageHandler>();
407 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
408 .WillOnce(ReturnRef(platform_message_handler));
410 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
411 .WillOnce(
Invoke([&draw_latch, &benchmark_layers](
412 const std::shared_ptr<FramePipeline>& pipeline) {
413 auto status = pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
414 EXPECT_EQ(item->layer_tree_tasks.size(), 1u);
417 item->layer_tree_tasks[0]->layer_tree->root_layer());
418 std::vector<std::shared_ptr<Layer>> result_layers =
420 EXPECT_EQ(result_layers.size(), benchmark_layers.size());
421 EXPECT_EQ(result_layers[0], benchmark_layers[0]);
423 EXPECT_EQ(status, PipelineConsumeResult::Done);
426 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
428 uint64_t frame_number) {
430 engine.BeginFrame(frame_target_time, frame_number);
434 AddNativeCallback(
"CaptureRootLayer",
437 std::unique_ptr<Animator> animator;
439 [&animator, &animator_delegate, &task_runners =
task_runners_] {
440 animator = std::make_unique<Animator>(
441 animator_delegate, task_runners,
442 static_cast<std::unique_ptr<VsyncWaiter>>(
443 std::make_unique<testing::ConstantFiringVsyncWaiter>(
448 std::move(animator));
452 [](
bool added) { ASSERT_TRUE(added); });
455 auto configuration = RunConfiguration::InferFromSettings(
settings_);
456 configuration.SetEntrypoint(
"renderTwiceForOneView");
457 engine_context->Run(std::move(configuration));
462TEST_F(EngineAnimatorTest, AnimatorSubmitsImplicitViewBeforeDrawFrameEnds) {
463 MockAnimatorDelegate animator_delegate;
464 std::unique_ptr<EngineContext> engine_context;
466 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
467 std::make_shared<MockPlatformMessageHandler>();
468 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
469 .WillOnce(ReturnRef(platform_message_handler));
471 bool rasterization_started =
false;
472 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
473 .WillOnce(
Invoke([&rasterization_started](
474 const std::shared_ptr<FramePipeline>& pipeline) {
475 rasterization_started =
true;
476 auto status = pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
477 EXPECT_EQ(item->layer_tree_tasks.size(), 1u);
480 EXPECT_EQ(status, PipelineConsumeResult::Done);
482 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
484 uint64_t frame_number) {
486 engine.BeginFrame(frame_target_time, frame_number);
490 std::unique_ptr<Animator> animator;
492 [&animator, &animator_delegate, &task_runners =
task_runners_] {
493 animator = std::make_unique<Animator>(
494 animator_delegate, task_runners,
495 static_cast<std::unique_ptr<VsyncWaiter>>(
496 std::make_unique<testing::ConstantFiringVsyncWaiter>(
500 native_latch.
Reset();
502 AddNativeCallback(
"NotifyNative",
504 EXPECT_EQ(rasterization_started,
true);
509 std::move(animator));
513 [](
bool added) { ASSERT_TRUE(added); });
516 auto configuration = RunConfiguration::InferFromSettings(
settings_);
517 configuration.SetEntrypoint(
"renderSingleViewAndCallAfterOnDrawFrame");
518 engine_context->Run(std::move(configuration));
526TEST_F(EngineAnimatorTest, AnimatorSubmitWarmUpImplicitView) {
527 MockAnimatorDelegate animator_delegate;
528 std::unique_ptr<EngineContext> engine_context;
530 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
531 std::make_shared<MockPlatformMessageHandler>();
532 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
533 .WillOnce(ReturnRef(platform_message_handler));
537 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
538 .WillOnce(
Invoke([&draw_latch](
539 const std::shared_ptr<FramePipeline>& pipeline) {
540 auto status = pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
541 EXPECT_EQ(item->layer_tree_tasks.size(), 1u);
544 EXPECT_EQ(status, PipelineConsumeResult::Done);
547 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
549 Invoke([&engine_context, &continuation_ready_latch](
551 continuation_ready_latch.
Signal();
553 engine.BeginFrame(frame_target_time, frame_number);
557 std::unique_ptr<Animator> animator;
559 [&animator, &animator_delegate, &task_runners =
task_runners_] {
560 animator = std::make_unique<Animator>(
561 animator_delegate, task_runners,
562 static_cast<std::unique_ptr<VsyncWaiter>>(
563 std::make_unique<testing::ConstantFiringVsyncWaiter>(
568 std::move(animator));
574 engine.ScheduleFrame(
true);
578 [](
bool added) { ASSERT_TRUE(added); });
580 continuation_ready_latch.
Wait();
582 auto configuration = RunConfiguration::InferFromSettings(
settings_);
583 configuration.SetEntrypoint(
"renderWarmUpImplicitView");
584 engine_context->Run(std::move(configuration));
593TEST_F(EngineAnimatorTest, AnimatorSubmitPartialViewsForWarmUp) {
594 MockAnimatorDelegate animator_delegate;
595 std::unique_ptr<EngineContext> engine_context;
597 std::shared_ptr<PlatformMessageHandler> platform_message_handler =
598 std::make_shared<MockPlatformMessageHandler>();
599 EXPECT_CALL(
delegate_, GetPlatformMessageHandler)
600 .WillOnce(ReturnRef(platform_message_handler));
604 EXPECT_CALL(animator_delegate, OnAnimatorDraw)
606 Invoke([&draw_latch](
const std::shared_ptr<FramePipeline>& pipeline) {
608 pipeline->Consume([&](std::unique_ptr<FrameItem> item) {
609 auto tasks = Sorted(item->layer_tree_tasks);
610 EXPECT_EQ(tasks.size(), 2u);
611 EXPECT_EQ(tasks[0]->view_id, 1);
612 EXPECT_EQ(tasks[1]->view_id, 2);
614 EXPECT_EQ(status, PipelineConsumeResult::Done);
617 EXPECT_CALL(animator_delegate, OnAnimatorBeginFrame)
619 Invoke([&engine_context, &continuation_ready_latch](
621 continuation_ready_latch.
Signal();
623 engine.BeginFrame(frame_target_time, frame_number);
627 std::unique_ptr<Animator> animator;
629 [&animator, &animator_delegate, &task_runners =
task_runners_] {
630 animator = std::make_unique<Animator>(
631 animator_delegate, task_runners,
632 static_cast<std::unique_ptr<VsyncWaiter>>(
633 std::make_unique<testing::ConstantFiringVsyncWaiter>(
638 std::move(animator));
642 engine.ScheduleFrame(
true);
645 [](
bool added) { ASSERT_TRUE(added); });
647 [](
bool added) { ASSERT_TRUE(added); });
649 [](
bool added) { ASSERT_TRUE(added); });
652 continuation_ready_latch.
Wait();
654 auto configuration = RunConfiguration::InferFromSettings(
settings_);
655 configuration.SetEntrypoint(
"renderWarmUpView1and2");
656 engine_context->Run(std::move(configuration));
static sk_sp< Effect > Create()
static std::vector< SkPDFIndirectReference > sort(const THashSet< SkPDFIndirectReference > &src)
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)
struct _Dart_Handle * Dart_Handle
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, int index)
DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj, int index, intptr_t *value)
struct _Dart_NativeArguments * Dart_NativeArguments
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
static constexpr FlutterViewId kFlutterImplicitViewId
@ 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
#define FML_CHECK(condition)
Dart_NativeFunction function
ObjectPtr Invoke(const Library &lib, const char *name)
static void PostSync(const fml::RefPtr< fml::TaskRunner > &task_runner, const fml::closure &task)
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.
TEST_F(EngineAnimatorTest, AnimatorSubmitPartialViewsForWarmUp)
std::function< void()> closure
#define CREATE_NATIVE_ENTRY(native_entry)