Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
external_view_embedder_unittests.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#define FML_USED_ON_EMBEDDER
6
7#include <memory>
8
10
15#include "flutter/fml/thread.h"
21
22#include "gmock/gmock.h"
23#include "gtest/gtest.h"
24#include "third_party/skia/include/core/SkSurface.h"
25#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h"
26
27namespace flutter {
28namespace testing {
29
30using ::testing::_;
31using ::testing::ByMove;
32using ::testing::Return;
33
34constexpr int64_t kImplicitViewId = 0;
35
37 public:
39 std::function<std::unique_ptr<AndroidSurface>(void)>;
40 explicit TestAndroidSurfaceFactory(TestSurfaceProducer&& surface_producer) {
41 surface_producer_ = surface_producer;
42 }
43
44 ~TestAndroidSurfaceFactory() override = default;
45
46 std::unique_ptr<AndroidSurface> CreateSurface() override {
47 return surface_producer_();
48 }
49
50 private:
51 TestSurfaceProducer surface_producer_;
52};
53
54class SurfaceMock : public Surface {
55 public:
56 MOCK_METHOD(bool, IsValid, (), (override));
57
58 MOCK_METHOD(std::unique_ptr<SurfaceFrame>,
60 (const DlISize& size),
61 (override));
62
63 MOCK_METHOD(DlMatrix, GetRootTransformation, (), (const, override));
64
65 MOCK_METHOD(GrDirectContext*, GetContext, (), (override));
66
67 MOCK_METHOD(std::unique_ptr<GLContextResult>,
69 (),
70 (override));
71};
72
74 fml::Thread* rasterizer_thread = nullptr) {
75 // Assume the current thread is the platform thread.
77 auto platform_queue_id = fml::MessageLoop::GetCurrentTaskQueueId();
78
79 if (!rasterizer_thread) {
80 return fml::MakeRefCounted<fml::RasterThreadMerger>(platform_queue_id,
81 platform_queue_id);
82 }
83 auto rasterizer_queue_id =
84 rasterizer_thread->GetTaskRunner()->GetTaskQueueId();
85 return fml::MakeRefCounted<fml::RasterThreadMerger>(platform_queue_id,
86 rasterizer_queue_id);
87}
88
90 fml::Thread* platform_thread) {
91 auto platform_queue_id = platform_thread->GetTaskRunner()->GetTaskQueueId();
92
93 // Assume the current thread is the raster thread.
95 auto rasterizer_queue_id = fml::MessageLoop::GetCurrentTaskQueueId();
96
97 return fml::MakeRefCounted<fml::RasterThreadMerger>(platform_queue_id,
98 rasterizer_queue_id);
99}
100
103 auto& loop = fml::MessageLoop::GetCurrent();
104 return {
105 "test",
106 loop.GetTaskRunner(), // platform
107 loop.GetTaskRunner(), // raster
108 loop.GetTaskRunner(), // ui
109 loop.GetTaskRunner() // io
110 };
111}
112
113TEST(AndroidExternalViewEmbedder, CompositeEmbeddedView) {
114 auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware);
115 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
116 android_context, nullptr, nullptr, GetTaskRunnersForFixture());
117
118 ASSERT_EQ(nullptr, embedder->CompositeEmbeddedView(0));
119 embedder->PrerollCompositeEmbeddedView(
120 0, std::make_unique<EmbeddedViewParams>());
121 ASSERT_NE(nullptr, embedder->CompositeEmbeddedView(0));
122
123 ASSERT_EQ(nullptr, embedder->CompositeEmbeddedView(1));
124 embedder->PrerollCompositeEmbeddedView(
125 1, std::make_unique<EmbeddedViewParams>());
126 ASSERT_NE(nullptr, embedder->CompositeEmbeddedView(1));
127}
128
130 auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware);
131 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
132 android_context, nullptr, nullptr, GetTaskRunnersForFixture());
133
134 embedder->PrerollCompositeEmbeddedView(
135 0, std::make_unique<EmbeddedViewParams>());
136 embedder->CancelFrame();
137
138 ASSERT_EQ(embedder->CompositeEmbeddedView(0), nullptr);
139}
140
141TEST(AndroidExternalViewEmbedder, RasterizerRunsOnPlatformThread) {
142 auto jni_mock = std::make_shared<JNIMock>();
143 auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware);
144 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
145 android_context, jni_mock, nullptr, GetTaskRunnersForFixture());
146
147 fml::Thread rasterizer_thread("rasterizer");
148 auto raster_thread_merger =
149 GetThreadMergerFromPlatformThread(&rasterizer_thread);
150 ASSERT_FALSE(raster_thread_merger->IsMerged());
151
152 EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
153 embedder->BeginFrame(nullptr, raster_thread_merger);
154 embedder->PrepareFlutterView(DlISize(10, 20), 1.0);
155
156 // Push a platform view.
157 embedder->PrerollCompositeEmbeddedView(
158 0, std::make_unique<EmbeddedViewParams>());
159
160 auto postpreroll_result = embedder->PostPrerollAction(raster_thread_merger);
161 ASSERT_EQ(PostPrerollResult::kSkipAndRetryFrame, postpreroll_result);
162
163 EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
164 embedder->EndFrame(/*should_resubmit_frame=*/true, raster_thread_merger);
165
166 ASSERT_TRUE(raster_thread_merger->IsMerged());
167
168 int pending_frames = 0;
169 while (raster_thread_merger->IsMerged()) {
170 raster_thread_merger->DecrementLease();
171 pending_frames++;
172 }
173 ASSERT_EQ(10, pending_frames); // kDefaultMergedLeaseDuration
174}
175
176TEST(AndroidExternalViewEmbedder, RasterizerRunsOnRasterizerThread) {
177 auto jni_mock = std::make_shared<JNIMock>();
178 auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware);
179 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
180 android_context, jni_mock, nullptr, GetTaskRunnersForFixture());
181
182 fml::Thread rasterizer_thread("rasterizer");
183 auto raster_thread_merger =
184 GetThreadMergerFromPlatformThread(&rasterizer_thread);
185 ASSERT_FALSE(raster_thread_merger->IsMerged());
186
187 PostPrerollResult result = embedder->PostPrerollAction(raster_thread_merger);
188 ASSERT_EQ(PostPrerollResult::kSuccess, result);
189
190 EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
191 embedder->EndFrame(/*should_resubmit_frame=*/true, raster_thread_merger);
192
193 ASSERT_FALSE(raster_thread_merger->IsMerged());
194}
195
197 auto jni_mock = std::make_shared<JNIMock>();
198
199 auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware);
200 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
201 android_context, jni_mock, nullptr, GetTaskRunnersForFixture());
202 fml::Thread rasterizer_thread("rasterizer");
203 auto raster_thread_merger =
204 GetThreadMergerFromPlatformThread(&rasterizer_thread);
205
206 EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
207 embedder->BeginFrame(nullptr, raster_thread_merger);
208 embedder->PrepareFlutterView(DlISize(100, 100), 1.5);
209
210 MutatorsStack stack;
211 DlMatrix matrix;
212 // The framework always push a scale matrix based on the screen ratio.
213 matrix = matrix * DlMatrix::MakeScale({1.5, 1.5, 1});
214 matrix = matrix * DlMatrix::MakeTranslation({10, 20});
215 auto view_params =
216 std::make_unique<EmbeddedViewParams>(matrix, DlSize(30, 40), stack);
217
218 auto view_id = 0;
219 embedder->PrerollCompositeEmbeddedView(view_id, std::move(view_params));
220 ASSERT_EQ(DlRect::MakeXYWH(15, 30, 45, 60), embedder->GetViewRect(view_id));
221}
222
223TEST(AndroidExternalViewEmbedder, PlatformViewRectChangedParams) {
224 auto jni_mock = std::make_shared<JNIMock>();
225
226 auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware);
227 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
228 android_context, jni_mock, nullptr, GetTaskRunnersForFixture());
229 fml::Thread rasterizer_thread("rasterizer");
230 auto raster_thread_merger =
231 GetThreadMergerFromPlatformThread(&rasterizer_thread);
232
233 EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
234 embedder->BeginFrame(nullptr, raster_thread_merger);
235 embedder->PrepareFlutterView(DlISize(100, 100), 1.5);
236
237 auto view_id = 0;
238
239 MutatorsStack stack1;
240 DlMatrix matrix1;
241 // The framework always push a scale matrix based on the screen ratio.
242 matrix1 =
243 DlMatrix::MakeScale({1.5, 1.5, 1}) * DlMatrix::MakeTranslation({10, 20});
244 auto view_params_1 =
245 std::make_unique<EmbeddedViewParams>(matrix1, DlSize(30, 40), stack1);
246
247 embedder->PrerollCompositeEmbeddedView(view_id, std::move(view_params_1));
248
249 MutatorsStack stack2;
250 DlMatrix matrix2;
251 // The framework always push a scale matrix based on the screen ratio.
252 matrix2 = matrix2 * DlMatrix::MakeScale({1.5, 1.5, 1});
253 matrix2 = matrix2 * DlMatrix::MakeTranslation({50, 60});
254 auto view_params_2 =
255 std::make_unique<EmbeddedViewParams>(matrix2, DlSize(70, 80), stack2);
256
257 embedder->PrerollCompositeEmbeddedView(view_id, std::move(view_params_2));
258
259 ASSERT_EQ(DlRect::MakeXYWH(75, 90, 105, 120), embedder->GetViewRect(view_id));
260}
261
263 auto jni_mock = std::make_shared<JNIMock>();
264 auto android_context =
265 std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
266
267 auto window = fml::MakeRefCounted<AndroidNativeWindow>(nullptr);
268 auto gr_context = GrDirectContext::MakeMock(nullptr);
269 auto frame_size = DlISize(1000, 1000);
270 SurfaceFrame::FramebufferInfo framebuffer_info;
271 auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
272 [gr_context, window, frame_size, framebuffer_info]() {
273 auto surface_frame_1 = std::make_unique<SurfaceFrame>(
274 SkSurfaces::Null(1000, 1000), framebuffer_info,
275 [](const SurfaceFrame& surface_frame, DlCanvas* canvas) {
276 return true;
277 },
278 [](const SurfaceFrame& surface_frame) { return true; },
279 /*frame_size=*/DlISize(800, 600));
280 auto surface_frame_2 = std::make_unique<SurfaceFrame>(
281 SkSurfaces::Null(1000, 1000), framebuffer_info,
282 [](const SurfaceFrame& surface_frame, DlCanvas* canvas) {
283 return true;
284 },
285 [](const SurfaceFrame& surface_frame) { return true; },
286 /*frame_size=*/DlISize(800, 600));
287
288 auto surface_mock = std::make_unique<SurfaceMock>();
289 EXPECT_CALL(*surface_mock, AcquireFrame(frame_size))
290 .Times(2 /* frames */)
291 .WillOnce(Return(ByMove(std::move(surface_frame_1))))
292 .WillOnce(Return(ByMove(std::move(surface_frame_2))));
293
294 auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
295 EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true));
296
297 EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get()))
298 .WillOnce(Return(ByMove(std::move(surface_mock))));
299
300 EXPECT_CALL(*android_surface_mock, SetNativeWindow(window, _));
301
302 return android_surface_mock;
303 });
304 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
305 *android_context, jni_mock, surface_factory, GetTaskRunnersForFixture());
306
307 auto raster_thread_merger = GetThreadMergerFromPlatformThread();
308
309 // ------------------ First frame ------------------ //
310 {
311 auto did_submit_frame = false;
312 auto surface_frame = std::make_unique<SurfaceFrame>(
313 SkSurfaces::Null(1000, 1000), framebuffer_info,
314 [&did_submit_frame](const SurfaceFrame& surface_frame,
315 DlCanvas* canvas) mutable {
316 if (canvas != nullptr) {
317 did_submit_frame = true;
318 }
319 return true;
320 },
321 [](const SurfaceFrame& surface_frame) { return true; },
322 /*frame_size=*/DlISize(800, 600));
323
324 embedder->SubmitFlutterView(kImplicitViewId, gr_context.get(), nullptr,
325 std::move(surface_frame));
326 // Submits frame if no Android view in the current frame.
327 EXPECT_TRUE(did_submit_frame);
328 // Doesn't resubmit frame.
329 auto postpreroll_result = embedder->PostPrerollAction(raster_thread_merger);
330 ASSERT_EQ(PostPrerollResult::kSuccess, postpreroll_result);
331
332 EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
333 embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
334 }
335
336 // ------------------ Second frame ------------------ //
337 {
338 EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
339 embedder->BeginFrame(nullptr, raster_thread_merger);
340 embedder->PrepareFlutterView(frame_size, 1.5);
341
342 // Add an Android view.
343 MutatorsStack stack1;
344 DlMatrix scale = DlMatrix::MakeScale({1.5, 1.5, 1});
345 DlMatrix trans = DlMatrix::MakeTranslation({100, 100});
346 DlMatrix matrix1 = scale * trans;
347 stack1.PushTransform(scale);
348 stack1.PushTransform(trans);
349 // TODO(egarciad): Investigate why Flow applies the device pixel ratio to
350 // the offsetPixels, but not the sizePoints.
351 auto view_params_1 =
352 std::make_unique<EmbeddedViewParams>(matrix1, DlSize(200, 200), stack1);
353
354 embedder->PrerollCompositeEmbeddedView(0, std::move(view_params_1));
355 // This is the recording canvas flow writes to.
356 auto canvas_1 = embedder->CompositeEmbeddedView(0);
357
358 DlPaint rect_paint;
359 rect_paint.setColor(DlColor::kCyan());
361
362 // This simulates Flutter UI that doesn't intersect with the Android view.
363 canvas_1->DrawRect(DlRect::MakeXYWH(0, 0, 50, 50), rect_paint);
364 // This simulates Flutter UI that intersects with the Android view.
365 canvas_1->DrawRect(DlRect::MakeXYWH(50, 50, 200, 200), rect_paint);
366 canvas_1->DrawRect(DlRect::MakeXYWH(150, 150, 100, 100), rect_paint);
367
368 // Create a new overlay surface.
369 EXPECT_CALL(*jni_mock, FlutterViewCreateOverlaySurface())
370 .WillOnce(Return(
371 ByMove(std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
372 0, window))));
373 // The JNI call to display the Android view.
374 EXPECT_CALL(*jni_mock, FlutterViewOnDisplayPlatformView(
375 0, 150, 150, 300, 300, 300, 300, stack1));
376 // The JNI call to display the overlay surface.
377 EXPECT_CALL(*jni_mock,
378 FlutterViewDisplayOverlaySurface(0, 150, 150, 100, 100));
379
380 auto did_submit_frame = false;
381 auto surface_frame = std::make_unique<SurfaceFrame>(
382 SkSurfaces::Null(1000, 1000), framebuffer_info,
383 [&did_submit_frame](const SurfaceFrame& surface_frame,
384 DlCanvas* canvas) mutable {
385 if (canvas != nullptr) {
386 did_submit_frame = true;
387 }
388 return true;
389 },
390 [](const SurfaceFrame& surface_frame) { return true; },
391 /*frame_size=*/DlISize(800, 600));
392
393 embedder->SubmitFlutterView(kImplicitViewId, gr_context.get(), nullptr,
394 std::move(surface_frame));
395 // Doesn't submit frame if there aren't Android views in the previous frame.
396 EXPECT_FALSE(did_submit_frame);
397 // Resubmits frame.
398 auto postpreroll_result = embedder->PostPrerollAction(raster_thread_merger);
399 ASSERT_EQ(PostPrerollResult::kResubmitFrame, postpreroll_result);
400
401 EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
402 embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
403 }
404
405 // ------------------ Third frame ------------------ //
406 {
407 EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
408 embedder->BeginFrame(nullptr, raster_thread_merger);
409 embedder->PrepareFlutterView(frame_size, 1.5);
410
411 // Add an Android view.
412 MutatorsStack stack1;
413 DlMatrix scale = DlMatrix::MakeScale({1.5, 1.5, 1});
414 DlMatrix trans = DlMatrix::MakeTranslation({100, 100});
415 DlMatrix matrix1 = scale * trans;
416 stack1.PushTransform(scale);
417 stack1.PushTransform(trans);
418 // TODO(egarciad): Investigate why Flow applies the device pixel ratio to
419 // the offsetPixels, but not the sizePoints.
420 auto view_params_1 =
421 std::make_unique<EmbeddedViewParams>(matrix1, DlSize(200, 200), stack1);
422
423 embedder->PrerollCompositeEmbeddedView(0, std::move(view_params_1));
424 // This is the recording canvas flow writes to.
425 auto canvas_1 = embedder->CompositeEmbeddedView(0);
426
427 DlPaint rect_paint;
428 rect_paint.setColor(DlColor::kCyan());
430
431 // This simulates Flutter UI that doesn't intersect with the Android view.
432 canvas_1->DrawRect(DlRect::MakeXYWH(0, 0, 50, 50), rect_paint);
433 // This simulates Flutter UI that intersects with the Android view.
434 canvas_1->DrawRect(DlRect::MakeXYWH(50, 50, 200, 200), rect_paint);
435 canvas_1->DrawRect(DlRect::MakeXYWH(150, 150, 100, 100), rect_paint);
436
437 // Don't create a new overlay surface since it's recycled from the first
438 // frame.
439 EXPECT_CALL(*jni_mock, FlutterViewCreateOverlaySurface()).Times(0);
440 // The JNI call to display the Android view.
441 EXPECT_CALL(*jni_mock, FlutterViewOnDisplayPlatformView(
442 0, 150, 150, 300, 300, 300, 300, stack1));
443 // The JNI call to display the overlay surface.
444 EXPECT_CALL(*jni_mock,
445 FlutterViewDisplayOverlaySurface(0, 150, 150, 100, 100));
446
447 auto did_submit_frame = false;
448 auto surface_frame = std::make_unique<SurfaceFrame>(
449 SkSurfaces::Null(1000, 1000), framebuffer_info,
450 [&did_submit_frame](const SurfaceFrame& surface_frame,
451 DlCanvas* canvas) mutable {
452 if (canvas != nullptr) {
453 did_submit_frame = true;
454 }
455 return true;
456 },
457 [](const SurfaceFrame& surface_frame) { return true; },
458 /*frame_size=*/DlISize(800, 600));
459 embedder->SubmitFlutterView(kImplicitViewId, gr_context.get(), nullptr,
460 std::move(surface_frame));
461 // Submits frame if there are Android views in the previous frame.
462 EXPECT_TRUE(did_submit_frame);
463 // Doesn't resubmit frame.
464 auto postpreroll_result = embedder->PostPrerollAction(raster_thread_merger);
465 ASSERT_EQ(PostPrerollResult::kSuccess, postpreroll_result);
466
467 EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
468 embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
469 }
470}
471
472TEST(AndroidExternalViewEmbedder, OverlayCoverTwoPlatformViews) {
473 // In this test we will simulate two Android views appearing on the screen
474 // with a rect intersecting both of them
475
476 auto jni_mock = std::make_shared<JNIMock>();
477 auto android_context =
478 std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
479
480 auto window = fml::MakeRefCounted<AndroidNativeWindow>(nullptr);
481 auto gr_context = GrDirectContext::MakeMock(nullptr);
482 auto frame_size = DlISize(1000, 1000);
483 SurfaceFrame::FramebufferInfo framebuffer_info;
484 auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
485 [gr_context, window, frame_size, framebuffer_info]() {
486 auto surface_frame_1 = std::make_unique<SurfaceFrame>(
487 SkSurfaces::Null(1000, 1000), framebuffer_info,
488 [](const SurfaceFrame& surface_frame, DlCanvas* canvas) {
489 return true;
490 },
491 [](const SurfaceFrame& surface_frame) { return true; },
492 /*frame_size=*/DlISize(800, 600));
493
494 auto surface_mock = std::make_unique<SurfaceMock>();
495 EXPECT_CALL(*surface_mock, AcquireFrame(frame_size))
496 .Times(1 /* frames */)
497 .WillOnce(Return(ByMove(std::move(surface_frame_1))));
498
499 auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
500 EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true));
501
502 EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get()))
503 .WillOnce(Return(ByMove(std::move(surface_mock))));
504
505 EXPECT_CALL(*android_surface_mock, SetNativeWindow(window, _));
506 return android_surface_mock;
507 });
508 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
509 *android_context, jni_mock, surface_factory, GetTaskRunnersForFixture());
510
511 auto raster_thread_merger = GetThreadMergerFromPlatformThread();
512
513 EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
514 embedder->BeginFrame(nullptr, raster_thread_merger);
515 embedder->PrepareFlutterView(frame_size, 1.5);
516
517 {
518 // Add first Android view.
519 DlMatrix matrix = DlMatrix::MakeTranslation({100, 100});
520 MutatorsStack stack;
521 embedder->PrerollCompositeEmbeddedView(
522 0,
523 std::make_unique<EmbeddedViewParams>(matrix, DlSize(100, 100), stack));
524 // The JNI call to display the Android view.
525 EXPECT_CALL(*jni_mock, FlutterViewOnDisplayPlatformView(
526 0, 100, 100, 100, 100, 150, 150, stack));
527 }
528
529 {
530 // Add second Android view.
531 DlMatrix matrix = DlMatrix::MakeTranslation({300, 100});
532 MutatorsStack stack;
533 embedder->PrerollCompositeEmbeddedView(
534 1,
535 std::make_unique<EmbeddedViewParams>(matrix, DlSize(100, 100), stack));
536 // The JNI call to display the Android view.
537 EXPECT_CALL(*jni_mock, FlutterViewOnDisplayPlatformView(
538 1, 300, 100, 100, 100, 150, 150, stack));
539 }
540 auto rect_paint = DlPaint();
541 rect_paint.setColor(DlColor::kCyan());
542 rect_paint.setDrawStyle(DlDrawStyle::kFill);
543
544 // This simulates Flutter UI that intersects with the two Android views.
545 // Since we will compute the intersection for each android view in turn, and
546 // finally merge The final size of the overlay will be smaller than the
547 // width and height of the rect.
548 embedder->CompositeEmbeddedView(1)->DrawRect(
549 DlRect::MakeXYWH(150, 50, 200, 200), rect_paint);
550
551 EXPECT_CALL(*jni_mock, FlutterViewCreateOverlaySurface())
552 .WillRepeatedly([&]() {
553 return std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
554 1, window);
555 });
556
557 // The JNI call to display the overlay surface.
558 EXPECT_CALL(*jni_mock,
559 FlutterViewDisplayOverlaySurface(1, 150, 100, 200, 100))
560 .Times(1);
561
562 auto surface_frame = std::make_unique<SurfaceFrame>(
563 SkSurfaces::Null(1000, 1000), framebuffer_info,
564 [](const SurfaceFrame& surface_frame, DlCanvas* canvas) mutable {
565 return true;
566 },
567 [](const SurfaceFrame& surface_frame) { return true; },
568 /*frame_size=*/DlISize(800, 600));
569
570 embedder->SubmitFlutterView(kImplicitViewId, gr_context.get(), nullptr,
571 std::move(surface_frame));
572
573 EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
574 embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
575}
576
577TEST(AndroidExternalViewEmbedder, SubmitFrameOverlayComposition) {
578 auto jni_mock = std::make_shared<JNIMock>();
579 auto android_context =
580 std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
581
582 auto window = fml::MakeRefCounted<AndroidNativeWindow>(nullptr);
583 auto gr_context = GrDirectContext::MakeMock(nullptr);
584 auto frame_size = DlISize(1000, 1000);
585 SurfaceFrame::FramebufferInfo framebuffer_info;
586 auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
587 [gr_context, window, frame_size, framebuffer_info]() {
588 auto surface_frame_1 = std::make_unique<SurfaceFrame>(
589 SkSurfaces::Null(1000, 1000), framebuffer_info,
590 [](const SurfaceFrame& surface_frame, DlCanvas* canvas) {
591 return true;
592 },
593 [](const SurfaceFrame& surface_frame) { return true; },
594 /*frame_size=*/DlISize(800, 600));
595
596 auto surface_mock = std::make_unique<SurfaceMock>();
597 EXPECT_CALL(*surface_mock, AcquireFrame(frame_size))
598 .Times(1 /* frames */)
599 .WillOnce(Return(ByMove(std::move(surface_frame_1))));
600
601 auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
602 EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true));
603
604 EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get()))
605 .WillOnce(Return(ByMove(std::move(surface_mock))));
606
607 EXPECT_CALL(*android_surface_mock, SetNativeWindow(window, _));
608 return android_surface_mock;
609 });
610 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
611 *android_context, jni_mock, surface_factory, GetTaskRunnersForFixture());
612
613 auto raster_thread_merger = GetThreadMergerFromPlatformThread();
614
615 EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
616 embedder->BeginFrame(nullptr, raster_thread_merger);
617 embedder->PrepareFlutterView(frame_size, 1.5);
618
619 {
620 // Add first Android view.
621 DlMatrix matrix;
622 MutatorsStack stack;
624
625 embedder->PrerollCompositeEmbeddedView(
626 0,
627 std::make_unique<EmbeddedViewParams>(matrix, DlSize(200, 200), stack));
628 EXPECT_CALL(*jni_mock, FlutterViewOnDisplayPlatformView(0, 0, 0, 200, 200,
629 300, 300, stack));
630 }
631
632 auto rect_paint = DlPaint();
633 rect_paint.setColor(DlColor::kCyan());
634 rect_paint.setDrawStyle(DlDrawStyle::kFill);
635
636 // This simulates Flutter UI that intersects with the first Android view.
637 embedder->CompositeEmbeddedView(0)->DrawRect(
638 DlRect::MakeXYWH(25, 25, 80, 150), rect_paint);
639
640 {
641 // Add second Android view.
642 DlMatrix matrix;
643 MutatorsStack stack;
645
646 embedder->PrerollCompositeEmbeddedView(
647 1,
648 std::make_unique<EmbeddedViewParams>(matrix, DlSize(100, 100), stack));
649 EXPECT_CALL(*jni_mock, FlutterViewOnDisplayPlatformView(1, 0, 0, 100, 100,
650 150, 150, stack));
651 }
652 // This simulates Flutter UI that intersects with the first and second Android
653 // views.
654 embedder->CompositeEmbeddedView(1)->DrawRect(DlRect::MakeXYWH(25, 25, 80, 50),
655 rect_paint);
656
657 embedder->CompositeEmbeddedView(1)->DrawRect(
658 DlRect::MakeXYWH(75, 75, 30, 100), rect_paint);
659
660 EXPECT_CALL(*jni_mock, FlutterViewCreateOverlaySurface())
661 .WillRepeatedly([&]() {
662 return std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
663 1, window);
664 });
665
666 EXPECT_CALL(*jni_mock, FlutterViewDisplayOverlaySurface(1, 25, 25, 80, 150))
667 .Times(2);
668
669 auto surface_frame = std::make_unique<SurfaceFrame>(
670 SkSurfaces::Null(1000, 1000), framebuffer_info,
671 [](const SurfaceFrame& surface_frame, DlCanvas* canvas) mutable {
672 return true;
673 },
674 [](const SurfaceFrame& surface_frame) { return true; },
675 /*frame_size=*/DlISize(800, 600));
676
677 embedder->SubmitFlutterView(kImplicitViewId, gr_context.get(), nullptr,
678 std::move(surface_frame));
679
680 EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
681 embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
682}
683
684TEST(AndroidExternalViewEmbedder, SubmitFramePlatformViewWithoutAnyOverlay) {
685 auto jni_mock = std::make_shared<JNIMock>();
686 auto android_context =
687 std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
688
689 auto window = fml::MakeRefCounted<AndroidNativeWindow>(nullptr);
690 auto gr_context = GrDirectContext::MakeMock(nullptr);
691 auto frame_size = DlISize(1000, 1000);
692 SurfaceFrame::FramebufferInfo framebuffer_info;
693 auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
694 [gr_context, window, frame_size, framebuffer_info]() {
695 auto surface_frame_1 = std::make_unique<SurfaceFrame>(
696 SkSurfaces::Null(1000, 1000), framebuffer_info,
697 [](const SurfaceFrame& surface_frame, DlCanvas* canvas) {
698 return true;
699 },
700 [](const SurfaceFrame& surface_frame) { return true; },
701 /*frame_size=*/DlISize(800, 600));
702
703 auto surface_mock = std::make_unique<SurfaceMock>();
704 EXPECT_CALL(*surface_mock, AcquireFrame(frame_size))
705 .Times(1 /* frames */)
706 .WillOnce(Return(ByMove(std::move(surface_frame_1))));
707
708 auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
709 EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true));
710
711 EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get()))
712 .WillOnce(Return(ByMove(std::move(surface_mock))));
713
714 EXPECT_CALL(*android_surface_mock, SetNativeWindow(window, _));
715 return android_surface_mock;
716 });
717 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
718 *android_context, jni_mock, surface_factory, GetTaskRunnersForFixture());
719
720 auto raster_thread_merger = GetThreadMergerFromPlatformThread();
721
722 EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
723 embedder->BeginFrame(nullptr, raster_thread_merger);
724 embedder->PrepareFlutterView(frame_size, 1.5);
725
726 {
727 // Add Android view.
728 DlMatrix matrix;
729 MutatorsStack stack;
731
732 embedder->PrerollCompositeEmbeddedView(
733 0,
734 std::make_unique<EmbeddedViewParams>(matrix, DlSize(200, 200), stack));
735 EXPECT_CALL(*jni_mock, FlutterViewOnDisplayPlatformView(0, 0, 0, 200, 200,
736 300, 300, stack));
737 }
738
739 EXPECT_CALL(*jni_mock, FlutterViewCreateOverlaySurface()).Times(0);
740
741 auto surface_frame = std::make_unique<SurfaceFrame>(
742 SkSurfaces::Null(1000, 1000), framebuffer_info,
743 [](const SurfaceFrame& surface_frame, DlCanvas* canvas) mutable {
744 return true;
745 },
746 [](const SurfaceFrame& surface_frame) { return true; },
747 /*frame_size=*/DlISize(800, 600));
748
749 embedder->SubmitFlutterView(kImplicitViewId, gr_context.get(), nullptr,
750 std::move(surface_frame));
751
752 EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
753 embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
754}
755
756TEST(AndroidExternalViewEmbedder, DoesNotCallJNIPlatformThreadOnlyMethods) {
757 auto jni_mock = std::make_shared<JNIMock>();
758
759 auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware);
760 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
761 android_context, jni_mock, nullptr, GetTaskRunnersForFixture());
762
763 // While on the raster thread, don't make JNI calls as these methods can only
764 // run on the platform thread.
765 fml::Thread platform_thread("platform");
766 auto raster_thread_merger = GetThreadMergerFromRasterThread(&platform_thread);
767
768 EXPECT_CALL(*jni_mock, FlutterViewBeginFrame()).Times(0);
769 embedder->BeginFrame(nullptr, raster_thread_merger);
770 embedder->PrepareFlutterView(DlISize(10, 20), 1.0);
771
772 EXPECT_CALL(*jni_mock, FlutterViewEndFrame()).Times(0);
773 embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
774}
775
776TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) {
777 auto jni_mock = std::make_shared<JNIMock>();
778
779 auto android_context =
780 std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
781 auto window = fml::MakeRefCounted<AndroidNativeWindow>(nullptr);
782 auto gr_context = GrDirectContext::MakeMock(nullptr);
783 auto frame_size = DlISize(1000, 1000);
784 SurfaceFrame::FramebufferInfo framebuffer_info;
785 auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
786 [gr_context, window, frame_size, framebuffer_info]() {
787 auto surface_frame_1 = std::make_unique<SurfaceFrame>(
788 SkSurfaces::Null(1000, 1000), framebuffer_info,
789 [](const SurfaceFrame& surface_frame, DlCanvas* canvas) {
790 return true;
791 },
792 [](const SurfaceFrame& surface_frame) { return true; },
793 /*frame_size=*/DlISize(800, 600));
794
795 auto surface_mock = std::make_unique<SurfaceMock>();
796 EXPECT_CALL(*surface_mock, AcquireFrame(frame_size))
797 .WillOnce(Return(ByMove(std::move(surface_frame_1))));
798
799 auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
800 EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true));
801
802 EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get()))
803 .WillOnce(Return(ByMove(std::move(surface_mock))));
804
805 EXPECT_CALL(*android_surface_mock, SetNativeWindow(window, _));
806
807 return android_surface_mock;
808 });
809
810 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
811 *android_context, jni_mock, surface_factory, GetTaskRunnersForFixture());
812 fml::Thread rasterizer_thread("rasterizer");
813 auto raster_thread_merger =
814 GetThreadMergerFromPlatformThread(&rasterizer_thread);
815
816 // ------------------ First frame ------------------ //
817 {
818 EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
819 embedder->BeginFrame(nullptr, raster_thread_merger);
820 embedder->PrepareFlutterView(frame_size, 1.5);
821
822 // Add an Android view.
823 MutatorsStack stack1;
824 // TODO(egarciad): Investigate why Flow applies the device pixel ratio to
825 // the offsetPixels, but not the sizePoints.
826 auto view_params_1 = std::make_unique<EmbeddedViewParams>(
827 DlMatrix(), DlSize(200, 200), stack1);
828
829 embedder->PrerollCompositeEmbeddedView(0, std::move(view_params_1));
830
831 // This simulates Flutter UI that intersects with the Android view.
832 embedder->CompositeEmbeddedView(0)->DrawRect(
833 DlRect::MakeXYWH(50, 50, 200, 200), DlPaint());
834
835 // Create a new overlay surface.
836 EXPECT_CALL(*jni_mock, FlutterViewCreateOverlaySurface())
837 .WillOnce(Return(
838 ByMove(std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
839 0, window))));
840 // The JNI call to display the Android view.
841 EXPECT_CALL(*jni_mock, FlutterViewOnDisplayPlatformView(0, 0, 0, 200, 200,
842 300, 300, stack1));
843 EXPECT_CALL(*jni_mock,
844 FlutterViewDisplayOverlaySurface(0, 50, 50, 150, 150));
845
846 SurfaceFrame::FramebufferInfo framebuffer_info;
847 auto surface_frame = std::make_unique<SurfaceFrame>(
848 SkSurfaces::Null(1000, 1000), framebuffer_info,
849 [](const SurfaceFrame& surface_frame, DlCanvas* canvas) {
850 return true;
851 },
852 [](const SurfaceFrame& surface_frame) { return true; },
853 /*frame_size=*/DlISize(800, 600));
854 embedder->SubmitFlutterView(kImplicitViewId, gr_context.get(), nullptr,
855 std::move(surface_frame));
856
857 EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
858 embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
859 }
860
861 EXPECT_CALL(*jni_mock, FlutterViewDestroyOverlaySurfaces());
862 EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
863 // Change the frame size.
864 embedder->BeginFrame(nullptr, raster_thread_merger);
865 embedder->PrepareFlutterView(DlISize(30, 40), 1.0);
866}
867
868TEST(AndroidExternalViewEmbedder, DoesNotDestroyOverlayLayersOnSizeChange) {
869 auto jni_mock = std::make_shared<JNIMock>();
870 auto android_context =
871 std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
872
873 auto window = fml::MakeRefCounted<AndroidNativeWindow>(nullptr);
874 auto gr_context = GrDirectContext::MakeMock(nullptr);
875 auto frame_size = DlISize(1000, 1000);
876 SurfaceFrame::FramebufferInfo framebuffer_info;
877 auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
878 [gr_context, window, frame_size, framebuffer_info]() {
879 auto surface_frame_1 = std::make_unique<SurfaceFrame>(
880 SkSurfaces::Null(1000, 1000), framebuffer_info,
881 [](const SurfaceFrame& surface_frame, DlCanvas* canvas) {
882 return true;
883 },
884 [](const SurfaceFrame& surface_frame) { return true; },
885 /*frame_size=*/DlISize(800, 600));
886
887 auto surface_mock = std::make_unique<SurfaceMock>();
888 EXPECT_CALL(*surface_mock, AcquireFrame(frame_size))
889 .WillOnce(Return(ByMove(std::move(surface_frame_1))));
890
891 auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
892 EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true));
893
894 EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get()))
895 .WillOnce(Return(ByMove(std::move(surface_mock))));
896
897 EXPECT_CALL(*android_surface_mock, SetNativeWindow(window, _));
898
899 return android_surface_mock;
900 });
901
902 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
903 *android_context, jni_mock, surface_factory, GetTaskRunnersForFixture());
904
905 // ------------------ First frame ------------------ //
906 {
907 fml::Thread rasterizer_thread("rasterizer");
908 auto raster_thread_merger =
909 GetThreadMergerFromPlatformThread(&rasterizer_thread);
910 EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
911 embedder->BeginFrame(nullptr, raster_thread_merger);
912 embedder->PrepareFlutterView(frame_size, 1.5);
913
914 // Add an Android view.
915 MutatorsStack stack1;
916 // TODO(egarciad): Investigate why Flow applies the device pixel ratio to
917 // the offsetPixels, but not the sizePoints.
918 auto view_params_1 = std::make_unique<EmbeddedViewParams>(
919 DlMatrix(), DlSize(200, 200), stack1);
920
921 embedder->PrerollCompositeEmbeddedView(0, std::move(view_params_1));
922
923 // This simulates Flutter UI that intersects with the Android view.
924 embedder->CompositeEmbeddedView(0)->DrawRect(
925 DlRect::MakeXYWH(50, 50, 200, 200), DlPaint());
926
927 // Create a new overlay surface.
928 EXPECT_CALL(*jni_mock, FlutterViewCreateOverlaySurface())
929 .WillOnce(Return(
930 ByMove(std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
931 0, window))));
932 // The JNI call to display the Android view.
933 EXPECT_CALL(*jni_mock, FlutterViewOnDisplayPlatformView(0, 0, 0, 200, 200,
934 300, 300, stack1));
935 EXPECT_CALL(*jni_mock,
936 FlutterViewDisplayOverlaySurface(0, 50, 50, 150, 150));
937
938 auto surface_frame = std::make_unique<SurfaceFrame>(
939 SkSurfaces::Null(1000, 1000), framebuffer_info,
940 [](const SurfaceFrame& surface_frame, DlCanvas* canvas) {
941 return true;
942 },
943 [](const SurfaceFrame& surface_frame) { return true; },
944 /*frame_size=*/DlISize(800, 600));
945 embedder->SubmitFlutterView(kImplicitViewId, gr_context.get(), nullptr,
946 std::move(surface_frame));
947
948 EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
949 embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
950 }
951
952 EXPECT_CALL(*jni_mock, FlutterViewDestroyOverlaySurfaces()).Times(1);
953 EXPECT_CALL(*jni_mock, FlutterViewBeginFrame()).Times(0);
954
955 fml::Thread platform_thread("platform");
956 embedder->BeginFrame(nullptr,
957 GetThreadMergerFromRasterThread(&platform_thread));
958 embedder->PrepareFlutterView(DlISize(30, 40), 1.0);
959}
960
961TEST(AndroidExternalViewEmbedder, SupportsDynamicThreadMerging) {
962 auto jni_mock = std::make_shared<JNIMock>();
963 auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware);
964 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
965 android_context, jni_mock, nullptr, GetTaskRunnersForFixture());
966 ASSERT_TRUE(embedder->SupportsDynamicThreadMerging());
967}
968
969TEST(AndroidExternalViewEmbedder, DisableThreadMerger) {
970 auto jni_mock = std::make_shared<JNIMock>();
971 auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware);
972 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
973 android_context, jni_mock, nullptr, GetTaskRunnersForFixture());
974
975 fml::Thread platform_thread("platform");
976 auto raster_thread_merger = GetThreadMergerFromRasterThread(&platform_thread);
977 ASSERT_FALSE(raster_thread_merger->IsMerged());
978
979 // The shell may disable the thread merger during `OnPlatformViewDestroyed`.
980 raster_thread_merger->Disable();
981
982 EXPECT_CALL(*jni_mock, FlutterViewBeginFrame()).Times(0);
983
984 embedder->BeginFrame(nullptr, raster_thread_merger);
985 embedder->PrepareFlutterView(DlISize(10, 20), 1.0);
986 // Push a platform view.
987 embedder->PrerollCompositeEmbeddedView(
988 0, std::make_unique<EmbeddedViewParams>());
989
990 auto postpreroll_result = embedder->PostPrerollAction(raster_thread_merger);
991 ASSERT_EQ(PostPrerollResult::kSkipAndRetryFrame, postpreroll_result);
992
993 EXPECT_CALL(*jni_mock, FlutterViewEndFrame()).Times(0);
994 embedder->EndFrame(/*should_resubmit_frame=*/true, raster_thread_merger);
995
996 ASSERT_FALSE(raster_thread_merger->IsMerged());
997}
998
1000 auto jni_mock = std::make_shared<JNIMock>();
1001 auto android_context =
1002 std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
1003 auto window = fml::MakeRefCounted<AndroidNativeWindow>(nullptr);
1004 auto gr_context = GrDirectContext::MakeMock(nullptr);
1005 auto frame_size = DlISize(1000, 1000);
1006 auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
1007 [gr_context, window, frame_size]() {
1008 SurfaceFrame::FramebufferInfo framebuffer_info;
1009 auto surface_frame_1 = std::make_unique<SurfaceFrame>(
1010 SkSurfaces::Null(1000, 1000), framebuffer_info,
1011 [](const SurfaceFrame& surface_frame, DlCanvas* canvas) {
1012 return true;
1013 },
1014 [](const SurfaceFrame& surface_frame) { return true; },
1015 /*frame_size=*/DlISize(800, 600));
1016
1017 auto surface_mock = std::make_unique<SurfaceMock>();
1018 EXPECT_CALL(*surface_mock, AcquireFrame(frame_size))
1019 .WillOnce(Return(ByMove(std::move(surface_frame_1))));
1020
1021 auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
1022 EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true));
1023 EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get()))
1024 .WillOnce(Return(ByMove(std::move(surface_mock))));
1025
1026 return android_surface_mock;
1027 });
1028
1029 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
1030 *android_context, jni_mock, surface_factory, GetTaskRunnersForFixture());
1031 fml::Thread rasterizer_thread("rasterizer");
1032 auto raster_thread_merger =
1033 GetThreadMergerFromPlatformThread(&rasterizer_thread);
1034
1035 embedder->BeginFrame(nullptr, raster_thread_merger);
1036 embedder->PrepareFlutterView(frame_size, 1.5);
1037
1038 // Add an Android view.
1039 MutatorsStack stack;
1040 auto view_params =
1041 std::make_unique<EmbeddedViewParams>(DlMatrix(), DlSize(200, 200), stack);
1042
1043 embedder->PrerollCompositeEmbeddedView(0, std::move(view_params));
1044
1045 // This simulates Flutter UI that intersects with the Android view.
1046 embedder->CompositeEmbeddedView(0)->DrawRect(
1047 DlRect::MakeXYWH(50, 50, 200, 200), DlPaint());
1048
1049 // Create a new overlay surface.
1050 EXPECT_CALL(*jni_mock, FlutterViewCreateOverlaySurface())
1051 .WillOnce(Return(
1052 ByMove(std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
1053 0, window))));
1054
1055 SurfaceFrame::FramebufferInfo framebuffer_info;
1056 auto surface_frame = std::make_unique<SurfaceFrame>(
1057 SkSurfaces::Null(1000, 1000), framebuffer_info,
1058 [](const SurfaceFrame& surface_frame, DlCanvas* canvas) { return true; },
1059 [](const SurfaceFrame& surface_frame) { return true; },
1060 /*frame_size=*/DlISize(800, 600));
1061 embedder->SubmitFlutterView(kImplicitViewId, gr_context.get(), nullptr,
1062 std::move(surface_frame));
1063
1064 embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
1065
1066 EXPECT_CALL(*jni_mock, FlutterViewDestroyOverlaySurfaces());
1067 // Teardown.
1068 embedder->Teardown();
1069}
1070
1071TEST(AndroidExternalViewEmbedder, MaybeResizeSurfaceView) {
1072 auto jni_mock = std::make_shared<JNIMock>();
1073 auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware);
1074 ThreadHost thread_host("io.flutter.test." + GetCurrentTestName() + ".",
1077 TaskRunners task_runners(
1078 "test",
1079 thread_host.platform_thread->GetTaskRunner(), // platform
1080 thread_host.raster_thread->GetTaskRunner(), // raster
1081 thread_host.ui_thread->GetTaskRunner(), // ui
1082 thread_host.io_thread->GetTaskRunner() // io
1083 );
1084 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
1085 android_context, jni_mock, nullptr, task_runners);
1086
1087 fml::Thread rasterizer_thread("rasterizer");
1088 auto raster_thread_merger =
1089 GetThreadMergerFromPlatformThread(&rasterizer_thread);
1090 ASSERT_FALSE(raster_thread_merger->IsMerged());
1091
1092 EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
1093 embedder->BeginFrame(nullptr, raster_thread_merger);
1094
1095 EXPECT_CALL(*jni_mock, MaybeResizeSurfaceView(100, 200));
1096 embedder->PrepareFlutterView(DlISize(100, 200), 1.0);
1097
1100 [&latch]() { latch.Signal(); });
1101 latch.Wait();
1102}
1103
1104TEST(AndroidExternalViewEmbedder, TeardownDoesNotCallJNIMethod) {
1105 auto jni_mock = std::make_shared<JNIMock>();
1106 auto android_context =
1107 std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
1108 auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
1109 *android_context, jni_mock, nullptr, GetTaskRunnersForFixture());
1110
1111 EXPECT_CALL(*jni_mock, FlutterViewDestroyOverlaySurfaces()).Times(0);
1112 embedder->Teardown();
1113}
1114
1115} // namespace testing
1116} // namespace flutter
Holds state that is shared across Android surfaces.
Developer-facing API for rendering anything within the engine.
Definition dl_canvas.h:32
DlPaint & setColor(DlColor color)
Definition dl_paint.h:70
DlPaint & setDrawStyle(DlDrawStyle style)
Definition dl_paint.h:93
void PushTransform(const DlMatrix &matrix)
Abstract Base Class that represents where we will be rendering content.
Definition surface.h:26
virtual std::unique_ptr< SurfaceFrame > AcquireFrame(const DlISize &size)=0
virtual std::unique_ptr< GLContextResult > MakeRenderContextCurrent()
Definition surface.cc:13
virtual bool IsValid()=0
virtual GrDirectContext * GetContext()=0
virtual DlMatrix GetRootTransformation() const =0
fml::RefPtr< fml::TaskRunner > GetPlatformTaskRunner() const
MOCK_METHOD(GrDirectContext *, GetContext,(),(override))
MOCK_METHOD(bool, IsValid,(),(override))
MOCK_METHOD(std::unique_ptr< GLContextResult >, MakeRenderContextCurrent,(),(override))
MOCK_METHOD(std::unique_ptr< SurfaceFrame >, AcquireFrame,(const DlISize &size),(override))
MOCK_METHOD(DlMatrix, GetRootTransformation,(),(const, override))
TestAndroidSurfaceFactory(TestSurfaceProducer &&surface_producer)
std::unique_ptr< AndroidSurface > CreateSurface() override
std::function< std::unique_ptr< AndroidSurface >(void)> TestSurfaceProducer
static void EnsureInitializedForCurrentThread()
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
static TaskQueueId GetCurrentTaskQueueId()
static void RunNowOrPostTask(const fml::RefPtr< fml::TaskRunner > &runner, const fml::closure &task)
virtual TaskQueueId GetTaskQueueId()
fml::RefPtr< fml::TaskRunner > GetTaskRunner() const
Definition thread.cc:164
GLFWwindow * window
Definition main.cc:60
G_BEGIN_DECLS FlutterViewId view_id
std::string GetCurrentTestName()
Gets the name of the currently running test. This is useful in generating logs or assets based on tes...
Definition testing.cc:14
fml::RefPtr< fml::RasterThreadMerger > GetThreadMergerFromPlatformThread(fml::Thread *rasterizer_thread=nullptr)
TEST(NativeAssetsManagerTest, NoAvailableAssets)
fml::RefPtr< fml::RasterThreadMerger > GetThreadMergerFromRasterThread(fml::Thread *platform_thread)
constexpr int64_t kImplicitViewId
impeller::Matrix DlMatrix
impeller::ISize32 DlISize
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all 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
impeller::Size DlSize
@ kFill
fills interior of shapes
static constexpr DlColor kCyan()
Definition dl_color.h:74
The collection of all the threads used by the engine.
Definition thread_host.h:21
std::unique_ptr< fml::Thread > io_thread
Definition thread_host.h:86
std::unique_ptr< fml::Thread > platform_thread
Definition thread_host.h:83
std::unique_ptr< fml::Thread > raster_thread
Definition thread_host.h:85
std::unique_ptr< fml::Thread > ui_thread
Definition thread_host.h:84
A 4x4 matrix using column-major storage.
Definition matrix.h:37
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition matrix.h:95
static constexpr Matrix MakeScale(const Vector3 &s)
Definition matrix.h:104
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition rect.h:136