@@ -514,6 +514,84 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) {
514514 EXPECT_CALL (*jni_mock, FlutterViewEndFrame ());
515515 embedder->EndFrame (/* should_resubmit_frame=*/ false , raster_thread_merger);
516516 }
517+
518+ {
519+ // ------------------ Fourth frame ------------------ //
520+ // In this frame we will simulate two Android views appearing on the screen
521+ // with a rect intersecting both of them
522+
523+ EXPECT_CALL (*jni_mock, FlutterViewBeginFrame ());
524+ embedder->BeginFrame (frame_size, nullptr , 1.5 , raster_thread_merger);
525+
526+ // Add first Android view.
527+ // It will be located at (100,100) and will be 100x100.
528+ MutatorsStack stack1;
529+ SkMatrix matrix1 = SkMatrix::Translate (100 , 100 );
530+ auto view_params_1 = std::make_unique<EmbeddedViewParams>(
531+ matrix1, SkSize::Make (100 , 100 ), stack1);
532+ embedder->PrerollCompositeEmbeddedView (0 , std::move (view_params_1));
533+
534+ // Add second Android view.
535+ // It will be located at (300,100) and will be 100x100.
536+ MutatorsStack stack2;
537+ SkMatrix matrix2 = SkMatrix::Translate (300 , 100 );
538+ auto view_params_2 = std::make_unique<EmbeddedViewParams>(
539+ matrix2, SkSize::Make (100 , 100 ), stack2);
540+ embedder->PrerollCompositeEmbeddedView (1 , std::move (view_params_2));
541+
542+ // This is the recording canvas flow writes to.
543+ auto canvas = embedder->CompositeEmbeddedView (1 ).canvas ;
544+
545+ auto rect_paint = SkPaint ();
546+ rect_paint.setColor (SkColors::kCyan );
547+ rect_paint.setStyle (SkPaint::Style::kFill_Style );
548+
549+ // This simulates Flutter UI that intersects with the two Android views.
550+ // Since we will compute the intersection for each android view in turn, and
551+ // finally merge The final size of the overlay will be smaller than the
552+ // width and height of the rect.
553+ canvas->drawRect (SkRect::MakeXYWH (150 , 50 , 200 , 200 ), rect_paint);
554+
555+ // Create a new overlay surface.
556+ EXPECT_CALL (*jni_mock, FlutterViewCreateOverlaySurface ())
557+ .WillOnce (Return (
558+ ByMove (std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
559+ 1 , window))));
560+
561+ // The JNI call to display the Android view.
562+ EXPECT_CALL (*jni_mock, FlutterViewOnDisplayPlatformView (
563+ 0 , 100 , 100 , 100 , 100 , 100 , 100 , stack1));
564+
565+ // The JNI call to display the Android view.
566+ EXPECT_CALL (*jni_mock, FlutterViewOnDisplayPlatformView (
567+ 0 , 300 , 100 , 100 , 100 , 100 , 100 , stack2));
568+
569+ // The JNI call to display the overlay surface.
570+ EXPECT_CALL (*jni_mock,
571+ FlutterViewDisplayOverlaySurface (1 , 150 , 100 , 200 , 100 ));
572+
573+ auto did_submit_frame = false ;
574+ auto surface_frame = std::make_unique<SurfaceFrame>(
575+ SkSurface::MakeNull (1000 , 1000 ), framebuffer_info,
576+ [&did_submit_frame](const SurfaceFrame& surface_frame,
577+ SkCanvas* canvas) mutable {
578+ if (canvas != nullptr ) {
579+ did_submit_frame = true ;
580+ }
581+ return true ;
582+ },
583+ /* frame_size=*/ SkISize::Make (800 , 600 ));
584+
585+ embedder->SubmitFrame (gr_context.get (), std::move (surface_frame));
586+ // Doesn't submit frame if there aren't Android views in the previous frame.
587+ EXPECT_FALSE (did_submit_frame);
588+ // Resubmits frame.
589+ auto postpreroll_result = embedder->PostPrerollAction (raster_thread_merger);
590+ ASSERT_EQ (PostPrerollResult::kResubmitFrame , postpreroll_result);
591+
592+ EXPECT_CALL (*jni_mock, FlutterViewEndFrame ());
593+ embedder->EndFrame (/* should_resubmit_frame=*/ false , raster_thread_merger);
594+ }
517595}
518596
519597TEST (AndroidExternalViewEmbedder, SubmitFrameOverlayComposition) {
0 commit comments