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