53 private static final String TAG =
"PlatformViewsController";
66 private static Class[] VIEW_TYPES_REQUIRE_VIRTUAL_DISPLAY = {SurfaceView.class};
70 private AndroidTouchProcessor androidTouchProcessor;
79 @Nullable
private TextureRegistry textureRegistry;
81 @Nullable
private TextInputPlugin textInputPlugin;
84 private PlatformViewsChannel platformViewsChannel;
93 @VisibleForTesting
final HashMap<Integer, VirtualDisplayController>
vdControllers;
102 private final SparseArray<PlatformView> platformViews;
117 private final SparseArray<FlutterMutatorView> platformViewParent;
120 private final SparseArray<PlatformOverlayView> overlayLayerViews;
128 private final SparseArray<PlatformViewWrapper> viewWrappers;
131 private int nextOverlayLayerId = 0;
134 private boolean flutterViewConvertedToImageView =
false;
139 private boolean synchronizeToNativeViewHierarchy =
true;
142 private final HashSet<Integer> currentFrameUsedOverlayLayerIds;
145 private final HashSet<Integer> currentFrameUsedPlatformViewIds;
148 private final MotionEventTracker motionEventTracker;
151 private boolean usesSoftwareRendering =
false;
153 private static boolean enableImageRenderTarget =
true;
155 private static boolean enableSurfaceProducerRenderTarget =
true;
157 private final PlatformViewsChannel.PlatformViewsHandler channelHandler =
158 new PlatformViewsChannel.PlatformViewsHandler() {
163 public void createForPlatformViewLayer(
164 @NonNull PlatformViewsChannel.PlatformViewCreationRequest request) {
166 enforceMinimumAndroidApiVersion(19);
167 ensureValidRequest(request);
171 configureForHybridComposition(platformView, request);
177 public long createForTextureLayer(
178 @NonNull PlatformViewsChannel.PlatformViewCreationRequest request) {
179 ensureValidRequest(request);
180 final int viewId = request.viewId;
181 if (viewWrappers.get(viewId) !=
null) {
182 throw new IllegalStateException(
183 "Trying to create an already created platform view, view id: " + viewId);
185 if (textureRegistry ==
null) {
186 throw new IllegalStateException(
187 "Texture registry is null. This means that platform views controller was detached,"
191 if (flutterView ==
null) {
192 throw new IllegalStateException(
193 "Flutter view is null. This means the platform views controller doesn't have an"
194 +
" attached view, view id: "
200 final View embeddedView = platformView.
getView();
201 if (embeddedView.getParent() !=
null) {
202 throw new IllegalStateException(
203 "The Android view returned from PlatformView#getView() was already added to a"
213 final boolean supportsTextureLayerMode =
214 Build.VERSION.SDK_INT >= API_LEVELS.API_23
215 && !ViewUtils.hasChildViewOfType(
216 embeddedView, VIEW_TYPES_REQUIRE_VIRTUAL_DISPLAY);
220 if (!supportsTextureLayerMode) {
221 if (request.displayMode
222 == PlatformViewsChannel.PlatformViewCreationRequest.RequestedDisplayMode
223 .TEXTURE_WITH_HYBRID_FALLBACK) {
224 configureForHybridComposition(platformView, request);
225 return PlatformViewsChannel.PlatformViewsHandler.NON_TEXTURE_FALLBACK;
226 }
else if (!usesSoftwareRendering) {
227 return configureForVirtualDisplay(platformView, request);
237 public void dispose(
int viewId) {
238 final PlatformView platformView = platformViews.get(viewId);
239 if (platformView ==
null) {
240 Log.
e(
TAG,
"Disposing unknown platform view with id: " + viewId);
243 if (platformView.
getView() !=
null) {
244 final View embeddedView = platformView.
getView();
245 final ViewGroup pvParent = (ViewGroup) embeddedView.getParent();
246 if (pvParent !=
null) {
250 pvParent.removeView(embeddedView);
253 platformViews.remove(viewId);
256 }
catch (RuntimeException exception) {
257 Log.
e(
TAG,
"Disposing platform view threw an exception", exception);
261 final View embeddedView = vdController.
getView();
262 if (embeddedView !=
null) {
272 if (viewWrapper !=
null) {
273 viewWrapper.removeAllViews();
277 final ViewGroup wrapperParent = (ViewGroup) viewWrapper.getParent();
278 if (wrapperParent !=
null) {
279 wrapperParent.removeView(viewWrapper);
281 viewWrappers.remove(viewId);
286 if (parentView !=
null) {
287 parentView.removeAllViews();
288 parentView.unsetOnDescendantFocusChangeListener();
290 final ViewGroup mutatorViewParent = (ViewGroup) parentView.getParent();
291 if (mutatorViewParent !=
null) {
292 mutatorViewParent.removeView(parentView);
294 platformViewParent.remove(viewId);
299 public void offset(
int viewId,
double top,
double left) {
312 if (viewWrapper ==
null) {
313 Log.
e(
TAG,
"Setting offset for unknown platform view with id: " + viewId);
316 final int physicalTop = toPhysicalPixels(top);
317 final int physicalLeft = toPhysicalPixels(
left);
318 final FrameLayout.LayoutParams layoutParams =
319 (FrameLayout.LayoutParams) viewWrapper.getLayoutParams();
320 layoutParams.topMargin = physicalTop;
321 layoutParams.leftMargin = physicalLeft;
327 @NonNull PlatformViewsChannel.PlatformViewResizeRequest request,
328 @NonNull PlatformViewsChannel.PlatformViewBufferResized onComplete) {
329 final int physicalWidth = toPhysicalPixels(request.newLogicalWidth);
330 final int physicalHeight = toPhysicalPixels(request.newLogicalHeight);
331 final int viewId = request.viewId;
334 final float originalDisplayDensity = getDisplayDensity();
340 lockInputConnection(vdController);
345 unlockInputConnection(vdController);
349 final float displayDensity =
350 context ==
null ? originalDisplayDensity : getDisplayDensity();
352 new PlatformViewsChannel.PlatformViewBufferSize(
359 final PlatformView platformView = platformViews.get(viewId);
361 if (platformView ==
null || viewWrapper ==
null) {
362 Log.
e(
TAG,
"Resizing unknown platform view with id: " + viewId);
377 final ViewGroup.LayoutParams viewWrapperLayoutParams = viewWrapper.getLayoutParams();
378 viewWrapperLayoutParams.width = physicalWidth;
379 viewWrapperLayoutParams.height = physicalHeight;
382 final View embeddedView = platformView.
getView();
383 if (embeddedView !=
null) {
384 final ViewGroup.LayoutParams embeddedViewLayoutParams = embeddedView.getLayoutParams();
385 embeddedViewLayoutParams.width = physicalWidth;
386 embeddedViewLayoutParams.height = physicalHeight;
387 embeddedView.setLayoutParams(embeddedViewLayoutParams);
390 new PlatformViewsChannel.PlatformViewBufferSize(
396 public void onTouch(@NonNull PlatformViewsChannel.PlatformViewTouch touch) {
397 final int viewId = touch.viewId;
398 final float density = context.getResources().getDisplayMetrics().density;
402 final MotionEvent
event =
toMotionEvent(density, touch,
true);
407 final PlatformView platformView = platformViews.get(viewId);
408 if (platformView ==
null) {
409 Log.
e(
TAG,
"Sending touch to an unknown view with id: " + viewId);
412 final View view = platformView.
getView();
414 Log.
e(
TAG,
"Sending touch to a null view with id: " + viewId);
417 final MotionEvent
event =
toMotionEvent(density, touch,
false);
418 view.dispatchTouchEvent(
event);
422 public void setDirection(
int viewId,
int direction) {
423 if (!validateDirection(direction)) {
424 throw new IllegalStateException(
425 "Trying to set unknown direction value: "
436 embeddedView = controller.
getView();
438 final PlatformView platformView = platformViews.get(viewId);
439 if (platformView ==
null) {
440 Log.
e(
TAG,
"Setting direction to an unknown view with id: " + viewId);
443 embeddedView = platformView.
getView();
445 if (embeddedView ==
null) {
446 Log.
e(
TAG,
"Setting direction to a null view with id: " + viewId);
449 embeddedView.setLayoutDirection(direction);
453 public void clearFocus(
int viewId) {
458 embeddedView = controller.
getView();
460 final PlatformView platformView = platformViews.get(viewId);
461 if (platformView ==
null) {
462 Log.
e(
TAG,
"Clearing focus on an unknown view with id: " + viewId);
465 embeddedView = platformView.
getView();
467 if (embeddedView ==
null) {
468 Log.
e(
TAG,
"Clearing focus on a null view with id: " + viewId);
471 embeddedView.clearFocus();
475 public void synchronizeToNativeViewHierarchy(
boolean yes) {
476 synchronizeToNativeViewHierarchy = yes;
481 private void enforceMinimumAndroidApiVersion(
int minSdkVersion) {
482 if (
Build.VERSION.SDK_INT < minSdkVersion) {
483 throw new IllegalStateException(
484 "Trying to use platform views with API "
485 +
Build.VERSION.SDK_INT
486 +
", required API level is: "
491 private void ensureValidRequest(
492 @NonNull PlatformViewsChannel.PlatformViewCreationRequest request) {
493 if (!validateDirection(request.direction)) {
494 throw new IllegalStateException(
495 "Trying to create a view with unknown direction value: "
505 @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
507 @NonNull PlatformViewsChannel.PlatformViewCreationRequest request,
boolean wrapContext) {
509 if (viewFactory ==
null) {
510 throw new IllegalStateException(
511 "Trying to create a platform view of unregistered type: " + request.viewType);
514 Object createParams =
null;
515 if (request.params !=
null) {
522 final Context mutableContext = wrapContext ?
new MutableContextWrapper(context) : context;
524 viewFactory.
create(mutableContext, request.viewId, createParams);
527 final View embeddedView = platformView.
getView();
528 if (embeddedView ==
null) {
529 throw new IllegalStateException(
530 "PlatformView#getView() returned null, but an Android view reference was expected.");
532 embeddedView.setLayoutDirection(request.direction);
533 platformViews.put(request.viewId, platformView);
534 maybeInvokeOnFlutterViewAttached(platformView);
539 private void configureForHybridComposition(
541 @NonNull PlatformViewsChannel.PlatformViewCreationRequest request) {
542 enforceMinimumAndroidApiVersion(19);
543 Log.
i(TAG,
"Using hybrid composition for platform view: " + request.viewId);
547 private long configureForVirtualDisplay(
548 @NonNull PlatformView platformView,
549 @NonNull PlatformViewsChannel.PlatformViewCreationRequest request) {
554 enforceMinimumAndroidApiVersion(20);
556 Log.
i(TAG,
"Hosting view in a virtual display for platform view: " + request.viewId);
558 final PlatformViewRenderTarget renderTarget = makePlatformViewRenderTarget(textureRegistry);
559 final int physicalWidth = toPhysicalPixels(request.logicalWidth);
560 final int physicalHeight = toPhysicalPixels(request.logicalHeight);
561 final VirtualDisplayController vdController =
562 VirtualDisplayController.create(
564 accessibilityEventsDelegate,
571 (view, hasFocus) -> {
573 platformViewsChannel.invokeViewFocused(request.viewId);
577 if (vdController ==
null) {
578 throw new IllegalStateException(
579 "Failed creating virtual display for a "
589 final View embeddedView = platformView.getView();
592 return renderTarget.getId();
597 @TargetApi(API_LEVELS.API_23)
598 @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
599 public
long configureForTextureLayerComposition(
601 @NonNull PlatformViewsChannel.PlatformViewCreationRequest request) {
607 enforceMinimumAndroidApiVersion(23);
608 Log.
i(
TAG,
"Hosting view in view hierarchy for platform view: " + request.viewId);
610 final int physicalWidth = toPhysicalPixels(request.logicalWidth);
611 final int physicalHeight = toPhysicalPixels(request.logicalHeight);
614 if (usesSoftwareRendering) {
620 textureId = renderTarget.
getId();
625 final FrameLayout.LayoutParams viewWrapperLayoutParams =
626 new FrameLayout.LayoutParams(physicalWidth, physicalHeight);
629 final int physicalTop = toPhysicalPixels(request.logicalTop);
630 final int physicalLeft = toPhysicalPixels(request.logicalLeft);
631 viewWrapperLayoutParams.topMargin = physicalTop;
632 viewWrapperLayoutParams.leftMargin = physicalLeft;
636 final View embeddedView = platformView.getView();
637 embeddedView.setLayoutParams(
new FrameLayout.LayoutParams(physicalWidth, physicalHeight));
646 embeddedView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
649 viewWrapper.addView(embeddedView);
656 platformViewsChannel.invokeViewFocused(request.viewId);
662 flutterView.addView(viewWrapper);
663 viewWrappers.append(request.viewId, viewWrapper);
665 maybeInvokeOnFlutterViewAttached(platformView);
672 float density, PlatformViewsChannel.PlatformViewTouch touch,
boolean usingVirtualDiplay) {
673 MotionEventTracker.MotionEventId motionEventId =
674 MotionEventTracker.MotionEventId.from(touch.motionEventId);
675 MotionEvent trackedEvent = motionEventTracker.pop(motionEventId);
677 if (!usingVirtualDiplay && trackedEvent !=
null) {
690 PointerProperties[] pointerProperties =
691 parsePointerPropertiesList(touch.rawPointerPropertiesList)
692 .toArray(
new PointerProperties[touch.pointerCount]);
693 PointerCoords[] pointerCoords =
694 parsePointerCoordsList(touch.rawPointerCoords, density)
695 .toArray(
new PointerCoords[touch.pointerCount]);
699 return MotionEvent.obtain(
700 touch.downTime.longValue(),
701 touch.eventTime.longValue(),
718 vdControllers =
new HashMap<>();
720 contextToEmbeddedView =
new HashMap<>();
721 overlayLayerViews =
new SparseArray<>();
722 currentFrameUsedOverlayLayerIds =
new HashSet<>();
723 currentFrameUsedPlatformViewIds =
new HashSet<>();
724 viewWrappers =
new SparseArray<>();
725 platformViews =
new SparseArray<>();
726 platformViewParent =
new SparseArray<>();
728 motionEventTracker = MotionEventTracker.getInstance();
742 @NonNull TextureRegistry textureRegistry,
743 @NonNull DartExecutor dartExecutor) {
744 if (this.context !=
null) {
745 throw new AssertionError(
746 "A PlatformViewsController can only be attached to a single output target.\n"
747 +
"attach was called while the PlatformViewsController was already attached.");
749 this.context = context;
750 this.textureRegistry = textureRegistry;
751 platformViewsChannel =
new PlatformViewsChannel(dartExecutor);
752 platformViewsChannel.setPlatformViewsHandler(channelHandler);
768 usesSoftwareRendering = useSoftwareRendering;
781 if (platformViewsChannel !=
null) {
782 platformViewsChannel.setPlatformViewsHandler(
null);
784 destroyOverlaySurfaces();
785 platformViewsChannel =
null;
787 textureRegistry =
null;
797 flutterView = newFlutterView;
799 for (
int index = 0; index < viewWrappers.size(); index++) {
801 flutterView.addView(view);
804 for (
int index = 0; index < platformViewParent.size(); index++) {
806 flutterView.addView(view);
809 for (
int index = 0; index < platformViews.size(); index++) {
824 for (
int index = 0; index < viewWrappers.size(); index++) {
826 flutterView.removeView(view);
829 for (
int index = 0; index < platformViewParent.size(); index++) {
831 flutterView.removeView(view);
834 destroyOverlaySurfaces();
835 removeOverlaySurfaces();
837 flutterViewConvertedToImageView =
false;
840 for (
int index = 0; index < platformViews.size(); index++) {
846 private void maybeInvokeOnFlutterViewAttached(
PlatformView view) {
847 if (flutterView ==
null) {
848 Log.
i(
TAG,
"null flutterView");
896 if (!contextToEmbeddedView.containsKey(view.getContext())) {
899 View platformView = contextToEmbeddedView.get(view.getContext());
900 if (platformView == view) {
903 return platformView.checkInputConnectionProxy(view);
933 if (usesVirtualDisplay(viewId)) {
938 final PlatformView platformView = platformViews.get(viewId);
939 if (platformView ==
null) {
947 return vdControllers.containsKey(
id);
955 controller.onInputConnectionLocked();
958 private void unlockInputConnection(@NonNull VirtualDisplayController controller) {
963 controller.onInputConnectionUnlocked();
966 private static PlatformViewRenderTarget makePlatformViewRenderTarget(
967 TextureRegistry textureRegistry) {
968 if (enableSurfaceProducerRenderTarget && Build.VERSION.SDK_INT >= API_LEVELS.API_29) {
969 final TextureRegistry.SurfaceProducer textureEntry = textureRegistry.createSurfaceProducer();
970 Log.i(
TAG,
"PlatformView is using SurfaceProducer backend");
971 return new SurfaceProducerPlatformViewRenderTarget(textureEntry);
973 if (enableImageRenderTarget &&
Build.VERSION.SDK_INT >= API_LEVELS.API_29) {
974 final TextureRegistry.ImageTextureEntry textureEntry = textureRegistry.createImageTexture();
975 Log.i(
TAG,
"PlatformView is using ImageReader backend");
976 return new ImageReaderPlatformViewRenderTarget(textureEntry);
978 final TextureRegistry.SurfaceTextureEntry textureEntry = textureRegistry.createSurfaceTexture();
979 Log.i(
TAG,
"PlatformView is using SurfaceTexture backend");
980 return new SurfaceTexturePlatformViewRenderTarget(textureEntry);
983 private static boolean validateDirection(
int direction) {
984 return direction == View.LAYOUT_DIRECTION_LTR || direction == View.LAYOUT_DIRECTION_RTL;
987 @SuppressWarnings(
"unchecked")
988 private static
List<PointerProperties> parsePointerPropertiesList(Object rawPropertiesList) {
991 for (Object o : rawProperties) {
992 pointerProperties.
add(parsePointerProperties(o));
994 return pointerProperties;
997 @SuppressWarnings(
"unchecked")
998 private static PointerProperties parsePointerProperties(Object rawProperties) {
1000 PointerProperties properties =
new MotionEvent.PointerProperties();
1001 properties.id = (
int) propertiesList.get(0);
1002 properties.toolType = (
int) propertiesList.get(1);
1006 @SuppressWarnings(
"unchecked")
1007 private static
List<PointerCoords> parsePointerCoordsList(Object rawCoordsList,
float density) {
1010 for (Object o : rawCoords) {
1011 pointerCoords.
add(parsePointerCoords(o, density));
1013 return pointerCoords;
1016 @SuppressWarnings(
"unchecked")
1017 private static PointerCoords parsePointerCoords(Object rawCoords,
float density) {
1019 PointerCoords coords =
new MotionEvent.PointerCoords();
1020 coords.orientation = (
float) (
double) coordsList.get(0);
1021 coords.pressure = (
float) (
double) coordsList.get(1);
1022 coords.size = (
float) (
double) coordsList.get(2);
1023 coords.toolMajor = (
float) ((
double) coordsList.get(3) * density);
1024 coords.toolMinor = (
float) ((
double) coordsList.get(4) * density);
1025 coords.touchMajor = (
float) ((
double) coordsList.get(5) * density);
1026 coords.touchMinor = (
float) ((
double) coordsList.get(6) * density);
1027 coords.x = (
float) ((
double) coordsList.get(7) * density);
1028 coords.y = (
float) ((
double) coordsList.get(8) * density);
1032 private float getDisplayDensity() {
1033 return context.getResources().getDisplayMetrics().density;
1036 private int toPhysicalPixels(
double logicalPixels) {
1037 return (
int) Math.round(logicalPixels * getDisplayDensity());
1040 private int toLogicalPixels(
double physicalPixels,
float displayDensity) {
1041 return (
int) Math.round(physicalPixels / displayDensity);
1044 private int toLogicalPixels(
double physicalPixels) {
1045 return toLogicalPixels(physicalPixels, getDisplayDensity());
1048 private void diposeAllViews() {
1049 while (platformViews.size() > 0) {
1050 final int viewId = platformViews.keyAt(0);
1052 channelHandler.dispose(viewId);
1063 channelHandler.dispose(viewId);
1066 private void initializeRootImageViewIfNeeded() {
1067 if (synchronizeToNativeViewHierarchy && !flutterViewConvertedToImageView) {
1068 flutterView.convertToImageView();
1069 flutterViewConvertedToImageView =
true;
1081 final PlatformView platformView = platformViews.get(viewId);
1082 if (platformView ==
null) {
1083 throw new IllegalStateException(
1084 "Platform view hasn't been initialized from the platform view channel.");
1086 if (platformViewParent.get(viewId) !=
null) {
1089 final View embeddedView = platformView.
getView();
1090 if (embeddedView ==
null) {
1091 throw new IllegalStateException(
1092 "PlatformView#getView() returned null, but an Android view reference was expected.");
1094 if (embeddedView.getParent() !=
null) {
1095 throw new IllegalStateException(
1096 "The Android view returned from PlatformView#getView() was already added to a parent"
1101 context, context.getResources().getDisplayMetrics().density, androidTouchProcessor);
1103 parentView.setOnDescendantFocusChangeListener(
1104 (view, hasFocus) -> {
1106 platformViewsChannel.invokeViewFocused(viewId);
1112 platformViewParent.put(viewId, parentView);
1121 embeddedView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
1123 parentView.addView(embeddedView);
1124 flutterView.addView(parentView);
1128 androidTouchProcessor =
new AndroidTouchProcessor(flutterRenderer,
true);
1152 @NonNull FlutterMutatorsStack mutatorsStack) {
1153 initializeRootImageViewIfNeeded();
1154 initializePlatformViewIfNeeded(viewId);
1157 parentView.readyToDisplay(mutatorsStack,
x,
y,
width,
height);
1158 parentView.setVisibility(View.VISIBLE);
1159 parentView.bringToFront();
1161 final FrameLayout.LayoutParams layoutParams =
1162 new FrameLayout.LayoutParams(viewWidth, viewHeight);
1163 final View view = platformViews.get(viewId).
getView();
1165 view.setLayoutParams(layoutParams);
1166 view.bringToFront();
1168 currentFrameUsedPlatformViewIds.add(viewId);
1182 if (overlayLayerViews.get(
id) ==
null) {
1183 throw new IllegalStateException(
"The overlay surface (id:" +
id +
") doesn't exist");
1185 initializeRootImageViewIfNeeded();
1188 if (overlayView.getParent() ==
null) {
1189 flutterView.addView(overlayView);
1192 FrameLayout.LayoutParams layoutParams =
new FrameLayout.LayoutParams((
int)
width, (
int)
height);
1193 layoutParams.leftMargin = (
int)
x;
1194 layoutParams.topMargin = (
int)
y;
1195 overlayView.setLayoutParams(layoutParams);
1196 overlayView.setVisibility(View.VISIBLE);
1197 overlayView.bringToFront();
1198 currentFrameUsedOverlayLayerIds.add(
id);
1202 currentFrameUsedOverlayLayerIds.clear();
1203 currentFrameUsedPlatformViewIds.clear();
1216 if (flutterViewConvertedToImageView && currentFrameUsedPlatformViewIds.isEmpty()) {
1217 flutterViewConvertedToImageView =
false;
1218 flutterView.revertImageView(
1234 final boolean isFrameRenderedUsingImageReaders =
1235 flutterViewConvertedToImageView && flutterView.acquireLatestImageViewFrame();
1236 finishFrame(isFrameRenderedUsingImageReaders);
1239 private void finishFrame(
boolean isFrameRenderedUsingImageReaders) {
1240 for (
int i = 0; i < overlayLayerViews.size(); i++) {
1241 final int overlayId = overlayLayerViews.keyAt(i);
1244 if (currentFrameUsedOverlayLayerIds.contains(overlayId)) {
1245 flutterView.attachOverlaySurfaceToRender(overlayView);
1246 final boolean didAcquireOverlaySurfaceImage = overlayView.acquireLatestImage();
1247 isFrameRenderedUsingImageReaders &= didAcquireOverlaySurfaceImage;
1252 if (!flutterViewConvertedToImageView) {
1253 overlayView.detachFromRenderer();
1256 overlayView.setVisibility(View.GONE);
1257 flutterView.removeView(overlayView);
1261 for (
int i = 0; i < platformViewParent.size(); i++) {
1262 final int viewId = platformViewParent.keyAt(i);
1263 final View parentView = platformViewParent.get(viewId);
1274 if (currentFrameUsedPlatformViewIds.contains(viewId)
1275 && (isFrameRenderedUsingImageReaders || !synchronizeToNativeViewHierarchy)) {
1276 parentView.setVisibility(View.VISIBLE);
1278 parentView.setVisibility(View.GONE);
1293 final int id = nextOverlayLayerId++;
1294 overlayLayerViews.put(
id, imageView);
1295 return new FlutterOverlaySurface(
id, imageView.getSurface());
1313 return createOverlaySurface(
1315 flutterView.getContext(),
1316 flutterView.getWidth(),
1317 flutterView.getHeight(),
1318 accessibilityEventsDelegate));
1327 for (
int viewId = 0; viewId < overlayLayerViews.size(); viewId++) {
1329 overlayView.detachFromRenderer();
1330 overlayView.closeImageReader();
1338 private void removeOverlaySurfaces() {
1339 if (flutterView ==
null) {
1340 Log.
e(
TAG,
"removeOverlaySurfaces called while flutter view is null");
1343 for (
int viewId = 0; viewId < overlayLayerViews.size(); viewId++) {
1344 flutterView.removeView(overlayLayerViews.valueAt(viewId));
1346 overlayLayerViews.clear();
1351 return overlayLayerViews;