1package io.flutter.embedding.engine.renderer;
3import static android.content.ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
4import static org.junit.Assert.assertArrayEquals;
5import static org.junit.Assert.assertEquals;
6import static org.junit.Assert.assertNotNull;
7import static org.junit.Assert.assertNull;
8import static org.mockito.ArgumentMatchers.any;
9import static org.mockito.ArgumentMatchers.anyFloat;
10import static org.mockito.ArgumentMatchers.anyInt;
11import static org.mockito.ArgumentMatchers.eq;
12import static org.mockito.Mockito.mock;
13import static org.mockito.Mockito.never;
14import static org.mockito.Mockito.spy;
15import static org.mockito.Mockito.times;
16import static org.mockito.Mockito.verify;
17import static org.robolectric.Shadows.shadowOf;
21import android.graphics.SurfaceTexture;
25import androidx.lifecycle.Lifecycle;
26import androidx.test.ext.junit.rules.ActivityScenarioRule;
27import androidx.test.ext.junit.runners.AndroidJUnit4;
28import io.flutter.embedding.android.FlutterActivity;
29import io.flutter.embedding.engine.FlutterJNI;
30import io.flutter.view.TextureRegistry;
31import java.util.concurrent.CountDownLatch;
32import java.util.concurrent.atomic.AtomicInteger;
33import org.junit.Before;
36import org.junit.runner.RunWith;
37import org.mockito.ArgumentCaptor;
38import org.robolectric.annotation.Config;
41@RunWith(AndroidJUnit4.class)
48 new ActivityScenarioRule<>(engineRule.makeIntent());
60 fakeFlutterJNI = engineRule.getFlutterJNI();
66 Surface fakeSurface = mock(Surface.class);
67 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
73 verify(fakeFlutterJNI,
times(1)).onSurfaceCreated(
eq(fakeSurface));
79 Surface fakeSurface = mock(Surface.class);
80 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
88 verify(fakeFlutterJNI,
times(1)).onSurfaceChanged(
eq(100),
eq(50));
94 Surface fakeSurface = mock(Surface.class);
95 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
103 verify(fakeFlutterJNI,
times(1)).onSurfaceDestroyed();
109 Surface fakeSurface = mock(Surface.class);
110 Surface fakeSurface2 = mock(Surface.class);
111 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
119 verify(fakeFlutterJNI,
times(1)).onSurfaceDestroyed();
125 Surface fakeSurface = mock(Surface.class);
126 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
134 verify(fakeFlutterJNI,
times(1)).onSurfaceDestroyed();
140 Surface fakeSurface = mock(Surface.class);
141 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
147 verify(fakeFlutterJNI,
times(1)).onSurfaceDestroyed();
153 Surface fakeSurface = mock(Surface.class);
154 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
160 verify(fakeFlutterJNI, never()).onSurfaceDestroyed();
166 Surface fakeSurface = mock(Surface.class);
167 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
169 FlutterRenderer.SurfaceTextureRegistryEntry entry =
177 verify(fakeFlutterJNI,
times(0)).markTextureFrameAvailable(
eq(entry.id()));
183 Surface fakeSurface = mock(Surface.class);
184 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
186 SurfaceTexture surfaceTexture =
new SurfaceTexture(0);
189 FlutterRenderer.SurfaceTextureRegistryEntry entry =
196 assertEquals(surfaceTexture, entry.surfaceTexture());
198 verify(fakeFlutterJNI,
times(1)).registerTexture(
eq(entry.id()),
eq(entry.textureWrapper()));
204 Surface fakeSurface = mock(Surface.class);
205 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
207 FlutterRenderer.SurfaceTextureRegistryEntry entry =
209 long id = entry.
id();
214 runFinalization(entry);
216 shadowOf(Looper.getMainLooper()).idle();
221 verify(fakeFlutterJNI,
times(1)).unregisterTexture(
eq(
id));
227 Surface fakeSurface = mock(Surface.class);
228 engineRule.setJniIsAttached(
false);
229 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
231 FlutterRenderer.SurfaceTextureRegistryEntry entry =
233 long id = entry.
id();
239 runFinalization(entry);
241 shadowOf(Looper.getMainLooper()).idle();
244 verify(fakeFlutterJNI,
times(0)).unregisterTexture(
eq(
id));
249 CountDownLatch latch =
new CountDownLatch(1);
250 Thread fakeFinalizer =
256 }
catch (Throwable
e) {
260 fakeFinalizer.start();
263 }
catch (InterruptedException
e) {
279 metrics.width = 1000;
280 metrics.height = 1000;
281 metrics.devicePixelRatio = 2;
284 new Rect(10, 20, 30, 40),
287 metrics.displayFeatures.add(
295 ArgumentCaptor<int[]> boundsCaptor = ArgumentCaptor.forClass(
int[].
class);
296 ArgumentCaptor<int[]> typeCaptor = ArgumentCaptor.forClass(
int[].
class);
297 ArgumentCaptor<int[]> stateCaptor = ArgumentCaptor.forClass(
int[].
class);
298 verify(fakeFlutterJNI)
316 boundsCaptor.capture(),
317 typeCaptor.capture(),
318 stateCaptor.capture());
320 assertArrayEquals(
new int[] {10, 20, 30, 40, 50, 60, 70, 80}, boundsCaptor.getValue());
324 FlutterRenderer.DisplayFeatureType.CUTOUT.encodedValue
326 typeCaptor.getValue());
330 FlutterRenderer.DisplayFeatureState.UNKNOWN.encodedValue
332 stateCaptor.getValue());
338 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
340 AtomicInteger invocationCount =
new AtomicInteger(0);
341 final TextureRegistry.OnFrameConsumedListener listener = invocationCount::incrementAndGet;
343 FlutterRenderer.SurfaceTextureRegistryEntry entry =
348 entry.textureWrapper().updateTexImage();
351 assertEquals(1, invocationCount.get());
357 FlutterRenderer flutterRenderer = spy(engineRule.getFlutterEngine().getRenderer());
360 FlutterRenderer.SurfaceTextureRegistryEntry entry =
364 verify(flutterRenderer,
times(1)).addOnTrimMemoryListener(entry);
370 FlutterRenderer flutterRenderer = spy(engineRule.getFlutterEngine().getRenderer());
371 FlutterRenderer.SurfaceTextureRegistryEntry entry =
378 verify(flutterRenderer,
times(1)).removeOnTrimMemoryListener(entry);
384 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
386 AtomicInteger invocationCount =
new AtomicInteger(0);
387 final TextureRegistry.OnTrimMemoryListener listener =
388 level -> invocationCount.incrementAndGet();
390 FlutterRenderer.SurfaceTextureRegistryEntry entry =
398 assertEquals(1, invocationCount.get());
404 Surface fakeSurface = mock(Surface.class);
405 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
415 verify(fakeFlutterJNI,
times(1)).onSurfaceDestroyed();
420 Surface fakeSurface = mock(Surface.class);
421 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
424 verify(fakeFlutterJNI,
times(1)).onSurfaceCreated(
eq(fakeSurface));
429 Surface fakeSurface = mock(Surface.class);
430 Surface fakeSurface2 = mock(Surface.class);
431 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
438 verify(fakeFlutterJNI,
times(1)).onSurfaceCreated(
eq(fakeSurface));
439 verify(fakeFlutterJNI,
times(0)).onSurfaceWindowChanged(
eq(fakeSurface));
443 verify(fakeFlutterJNI,
times(1)).onSurfaceCreated(
eq(fakeSurface));
444 verify(fakeFlutterJNI,
times(0)).onSurfaceWindowChanged(
eq(fakeSurface));
445 verify(fakeFlutterJNI,
times(0)).onSurfaceCreated(
eq(fakeSurface2));
446 verify(fakeFlutterJNI,
times(1)).onSurfaceWindowChanged(
eq(fakeSurface2));
449 verify(fakeFlutterJNI,
times(1)).onSurfaceCreated(
eq(fakeSurface));
450 verify(fakeFlutterJNI,
times(1)).onSurfaceWindowChanged(
eq(fakeSurface));
451 verify(fakeFlutterJNI,
times(0)).onSurfaceCreated(
eq(fakeSurface2));
452 verify(fakeFlutterJNI,
times(1)).onSurfaceWindowChanged(
eq(fakeSurface2));
457 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
459 FlutterRenderer.ImageReaderSurfaceProducer
texture =
464 assertNull(
texture.acquireLatestImage());
472 Canvas canvas =
surface.lockHardwareCanvas();
473 canvas.drawARGB(255, 255, 0, 0);
474 surface.unlockCanvasAndPost(canvas);
477 shadowOf(Looper.getMainLooper()).idle();
481 assert
image !=
null;
482 assertEquals(1,
image.getWidth());
483 assertEquals(1,
image.getHeight());
492 canvas =
surface.lockHardwareCanvas();
493 canvas.drawARGB(255, 255, 0, 0);
494 surface.unlockCanvasAndPost(canvas);
497 shadowOf(Looper.getMainLooper()).idle();
501 assert
image !=
null;
502 assertEquals(5,
image.getWidth());
503 assertEquals(5,
image.getHeight());
506 assertNull(
texture.acquireLatestImage());
513 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
515 FlutterRenderer.ImageReaderSurfaceProducer
texture =
520 assertNull(
texture.acquireLatestImage());
528 Canvas canvas =
surface.lockHardwareCanvas();
529 canvas.drawARGB(255, 255, 0, 0);
530 surface.unlockCanvasAndPost(canvas);
536 shadowOf(Looper.getMainLooper()).idle();
539 assertNotNull(
texture.acquireLatestImage());
544 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
546 FlutterRenderer.ImageReaderSurfaceProducer
texture =
551 assertNull(
texture.acquireLatestImage());
559 Canvas canvas =
surface.lockHardwareCanvas();
560 canvas.drawARGB(255, 255, 0, 0);
561 surface.unlockCanvasAndPost(canvas);
564 shadowOf(Looper.getMainLooper()).idle();
566 assertEquals(1,
texture.numImageReaders());
567 assertEquals(1,
texture.numImages());
573 canvas =
surface.lockHardwareCanvas();
574 canvas.drawARGB(255, 255, 0, 0);
575 surface.unlockCanvasAndPost(canvas);
578 shadowOf(Looper.getMainLooper()).idle();
580 assertEquals(1,
texture.numImageReaders());
581 assertEquals(2,
texture.numImages());
586 canvas =
surface.lockHardwareCanvas();
587 canvas.drawARGB(255, 255, 0, 0);
588 surface.unlockCanvasAndPost(canvas);
591 shadowOf(Looper.getMainLooper()).idle();
593 assertEquals(2,
texture.numImageReaders());
594 assertEquals(3,
texture.numImages());
598 assertNotNull(produced);
599 assertEquals(1, produced.getWidth());
600 assertEquals(1, produced.getHeight());
601 assertEquals(2,
texture.numImageReaders());
602 assertEquals(2,
texture.numImages());
605 produced =
texture.acquireLatestImage();
606 assertNotNull(produced);
607 assertEquals(1, produced.getWidth());
608 assertEquals(1, produced.getHeight());
609 assertEquals(2,
texture.numImageReaders());
610 assertEquals(1,
texture.numImages());
612 produced =
texture.acquireLatestImage();
613 assertNotNull(produced);
614 assertEquals(4, produced.getWidth());
615 assertEquals(4, produced.getHeight());
616 assertEquals(1,
texture.numImageReaders());
617 assertEquals(0,
texture.numImages());
620 assertNull(
texture.acquireLatestImage());
621 assertEquals(1,
texture.numImageReaders());
622 assertEquals(0,
texture.numImages());
627 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
629 FlutterRenderer.ImageReaderSurfaceProducer
texture =
635 assertNull(
texture.acquireLatestImage());
643 Canvas canvas =
surface.lockHardwareCanvas();
644 canvas.drawARGB(255, 255, 0, 0);
645 surface.unlockCanvasAndPost(canvas);
648 shadowOf(Looper.getMainLooper()).idle();
650 assertEquals(1,
texture.numImageReaders());
651 assertEquals(1,
texture.numImages());
656 shadowOf(Looper.getMainLooper()).idle();
658 assertEquals(1,
texture.numImageReaders());
659 assertEquals(1,
texture.numImages());
660 assertEquals(0,
texture.numTrims());
665 shadowOf(Looper.getMainLooper()).idle();
667 assertEquals(0,
texture.numImageReaders());
668 assertEquals(0,
texture.numImages());
669 assertEquals(1,
texture.numTrims());
673 assertEquals(1,
texture.numImageReaders());
674 assertEquals(0,
texture.numImages());
675 assertEquals(1,
texture.numTrims());
678 canvas =
surface.lockHardwareCanvas();
679 canvas.drawARGB(255, 255, 0, 0);
680 surface.unlockCanvasAndPost(canvas);
683 shadowOf(Looper.getMainLooper()).idle();
685 assertEquals(1,
texture.numImageReaders());
686 assertEquals(1,
texture.numImages());
687 assertEquals(1,
texture.numTrims());
693 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
697 assertEquals(producer.getWidth(), 1);
698 assertEquals(producer.getHeight(), 1);
701 producer.setSize(0, 0);
704 assertNotNull(producer.getSurface());
707 assertEquals(producer.getWidth(), 1);
708 assertEquals(producer.getHeight(), 1);
714 Surface fakeSurface = mock(Surface.class);
716 FlutterRenderer.debugForceSurfaceProducerGlTextures =
true;
717 FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
723 assertEquals(producer.id(), 0);
724 verify(fakeFlutterJNI,
times(1)).registerTexture(
eq(producer.id()),
any());
726 FlutterRenderer.debugForceSurfaceProducerGlTextures =
false;
733 scenarioRule.getScenario().moveToState(Lifecycle.State.RESUMED);
static SkISize times(const SkISize &size, float factor)
static bool eq(const SkM44 &a, const SkM44 &b, float tol)
void CanLaunchActivityUsingFlutterEngine()
void iStopsRenderingToSurfaceWhenSurfaceAlreadySet()
void itAddsListenerWhenSurfaceTextureEntryCreated()
void itDoesNotInvokeCreatesSurfaceWhenResumingRendering()
void ImageReaderSurfaceProducerTrimMemoryCallback()
void itStopsUnregisteringTextureWhenDetached()
void itStopsSurfaceTextureCallbackWhenDetached()
void itNeverStopsRenderingToSurfaceWhenRequested()
void ImageReaderSurfaceProducerImageReadersAndImagesCount()
void itConvertsDisplayFeatureArrayToPrimitiveArrays()
void ImageReaderSurfaceProducerClampsWidthAndHeightTo1()
void itForwardsSurfaceDestructionNotificationToFlutterJNI()
void itNotifyImageFrameListener()
void itForwardsSurfaceChangeNotificationToFlutterJNI()
void itDoesDispatchSurfaceDestructionNotificationOnlyOnce()
void runFinalization(FlutterRenderer.SurfaceTextureRegistryEntry entry)
void ImageReaderSurfaceProducerDoesNotDropFramesWhenResizeInFlight()
void SurfaceTextureSurfaceProducerCreatesAConnectedTexture()
void itStopsRenderingToSurfaceWhenRequested()
void itStopsRenderingToOneSurfaceBeforeRenderingToANewSurface()
void itNotifySurfaceTextureEntryWhenMemoryPressureWarning()
void itRemovesListenerWhenSurfaceTextureEntryReleased()
void itForwardsSurfaceCreationNotificationToFlutterJNI()
void itRegistersExistingSurfaceTexture()
void itInvokesCreatesSurfaceWhenStartingRendering()
void ImageReaderSurfaceProducerProducesImageOfCorrectSize()
void itUnregistersTextureWhenSurfaceTextureFinalized()
List< DisplayFeature > displayFeatures
SurfaceProducer createSurfaceProducer()
SurfaceTextureEntry registerSurfaceTexture(@NonNull SurfaceTexture surfaceTexture)
void stopRenderingToSurface()
void surfaceChanged(int width, int height)
void startRenderingToSurface(@NonNull Surface surface, boolean onlySwap)
SurfaceTextureEntry createSurfaceTexture()
void onTrimMemory(int level)
void setViewportMetrics(@NonNull ViewportMetrics viewportMetrics)
default void setOnFrameConsumedListener(@Nullable OnFrameConsumedListener listener)
default void setOnTrimMemoryListener(@Nullable OnTrimMemoryListener listener)
sk_sp< const SkImage > image
SIT bool any(const Vec< 1, T > &x)