Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 06872e3

Browse files
author
Emmanuel Garcia
authored
Revert "Revert "Improve platform views performance (#31198)" (#31431)"
This reverts commit 80b7a8c.
1 parent fd6918d commit 06872e3

25 files changed

+927
-1612
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,10 +1191,9 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/Platfor
11911191
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewFactory.java
11921192
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewRegistry.java
11931193
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewRegistryImpl.java
1194+
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewWrapper.java
11941195
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewsAccessibilityDelegate.java
11951196
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java
1196-
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java
1197-
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/VirtualDisplayController.java
11981197
FILE: ../../../flutter/shell/platform/android/io/flutter/util/PathUtils.java
11991198
FILE: ../../../flutter/shell/platform/android/io/flutter/util/Preconditions.java
12001199
FILE: ../../../flutter/shell/platform/android/io/flutter/util/Predicate.java

shell/platform/android/BUILD.gn

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,9 @@ android_java_sources = [
268268
"io/flutter/plugin/platform/PlatformViewFactory.java",
269269
"io/flutter/plugin/platform/PlatformViewRegistry.java",
270270
"io/flutter/plugin/platform/PlatformViewRegistryImpl.java",
271+
"io/flutter/plugin/platform/PlatformViewWrapper.java",
271272
"io/flutter/plugin/platform/PlatformViewsAccessibilityDelegate.java",
272273
"io/flutter/plugin/platform/PlatformViewsController.java",
273-
"io/flutter/plugin/platform/SingleViewPresentation.java",
274-
"io/flutter/plugin/platform/VirtualDisplayController.java",
275274
"io/flutter/util/PathUtils.java",
276275
"io/flutter/util/Preconditions.java",
277276
"io/flutter/util/Predicate.java",

shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public boolean onTouchEvent(@NonNull MotionEvent event) {
107107
* the gesture pointers into screen coordinates.
108108
* @return True if the event was handled.
109109
*/
110-
public boolean onTouchEvent(@NonNull MotionEvent event, Matrix transformMatrix) {
110+
public boolean onTouchEvent(@NonNull MotionEvent event, @NonNull Matrix transformMatrix) {
111111
int pointerCount = event.getPointerCount();
112112

113113
// Prepare a data packet of the appropriate size and order.

shell/platform/android/io/flutter/embedding/android/FlutterView.java

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,6 @@ navigationBarVisible && guessBottomKeyboardInset(insets) == 0
791791
+ viewportMetrics.viewInsetBottom);
792792

793793
sendViewportMetricsToFlutter();
794-
795794
return newInsets;
796795
}
797796

@@ -867,21 +866,6 @@ public InputConnection onCreateInputConnection(@NonNull EditorInfo outAttrs) {
867866
return textInputPlugin.createInputConnection(this, keyboardManager, outAttrs);
868867
}
869868

870-
/**
871-
* Allows a {@code View} that is not currently the input connection target to invoke commands on
872-
* the {@link android.view.inputmethod.InputMethodManager}, which is otherwise disallowed.
873-
*
874-
* <p>Returns true to allow non-input-connection-targets to invoke methods on {@code
875-
* InputMethodManager}, or false to exclusively allow the input connection target to invoke such
876-
* methods.
877-
*/
878-
@Override
879-
public boolean checkInputConnectionProxy(View view) {
880-
return flutterEngine != null
881-
? flutterEngine.getPlatformViewsController().checkInputConnectionProxy(view)
882-
: super.checkInputConnectionProxy(view);
883-
}
884-
885869
/**
886870
* Invoked when a hardware key is pressed or released.
887871
*

shell/platform/android/io/flutter/embedding/engine/mutatorsstack/FlutterMutatorView.java

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@
99
import android.graphics.Path;
1010
import android.view.MotionEvent;
1111
import android.view.View;
12-
import android.view.ViewGroup;
1312
import android.view.ViewTreeObserver;
1413
import android.widget.FrameLayout;
1514
import androidx.annotation.NonNull;
1615
import androidx.annotation.Nullable;
1716
import androidx.annotation.VisibleForTesting;
1817
import io.flutter.embedding.android.AndroidTouchProcessor;
18+
import io.flutter.util.ViewUtils;
1919

2020
/**
2121
* A view that applies the {@link io.flutter.embedding.engine.mutatorsstack.FlutterMutatorsStack} to
@@ -49,31 +49,6 @@ public FlutterMutatorView(@NonNull Context context) {
4949
this(context, 1, /* androidTouchProcessor=*/ null);
5050
}
5151

52-
/**
53-
* Determines if the current view or any descendant view has focus.
54-
*
55-
* @param root The root view.
56-
* @return True if the current view or any descendant view has focus.
57-
*/
58-
@VisibleForTesting
59-
public static boolean childHasFocus(@Nullable View root) {
60-
if (root == null) {
61-
return false;
62-
}
63-
if (root.hasFocus()) {
64-
return true;
65-
}
66-
if (root instanceof ViewGroup) {
67-
final ViewGroup viewGroup = (ViewGroup) root;
68-
for (int idx = 0; idx < viewGroup.getChildCount(); idx++) {
69-
if (childHasFocus(viewGroup.getChildAt(idx))) {
70-
return true;
71-
}
72-
}
73-
}
74-
return false;
75-
}
76-
7752
@Nullable @VisibleForTesting ViewTreeObserver.OnGlobalFocusChangeListener activeFocusListener;
7853

7954
/**
@@ -95,7 +70,7 @@ public void setOnDescendantFocusChangeListener(@NonNull OnFocusChangeListener us
9570
new ViewTreeObserver.OnGlobalFocusChangeListener() {
9671
@Override
9772
public void onGlobalFocusChanged(View oldFocus, View newFocus) {
98-
userFocusListener.onFocusChange(mutatorView, childHasFocus(mutatorView));
73+
userFocusListener.onFocusChange(mutatorView, ViewUtils.childHasFocus(mutatorView));
9974
}
10075
};
10176
observer.addOnGlobalFocusChangeListener(activeFocusListener);

shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformViewsChannel.java

Lines changed: 106 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.io.PrintWriter;
1515
import java.io.StringWriter;
1616
import java.nio.ByteBuffer;
17+
import java.util.HashMap;
1718
import java.util.List;
1819
import java.util.Map;
1920

@@ -64,6 +65,9 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
6465
case "resize":
6566
resize(call, result);
6667
break;
68+
case "offset":
69+
offset(call, result);
70+
break;
6771
case "touch":
6872
touch(call, result);
6973
break;
@@ -82,29 +86,40 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
8286
}
8387

8488
private void create(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
85-
Map<String, Object> createArgs = call.arguments();
86-
boolean usesHybridComposition =
89+
final Map<String, Object> createArgs = call.arguments();
90+
// TODO(egarciad): Remove the "hybrid" case.
91+
final boolean usesPlatformViewLayer =
8792
createArgs.containsKey("hybrid") && (boolean) createArgs.get("hybrid");
88-
// In hybrid mode, the size of the view is determined by the size of the Flow layer.
89-
double width = (usesHybridComposition) ? 0 : (double) createArgs.get("width");
90-
double height = (usesHybridComposition) ? 0 : (double) createArgs.get("height");
91-
92-
PlatformViewCreationRequest request =
93-
new PlatformViewCreationRequest(
94-
(int) createArgs.get("id"),
95-
(String) createArgs.get("viewType"),
96-
width,
97-
height,
98-
(int) createArgs.get("direction"),
99-
createArgs.containsKey("params")
100-
? ByteBuffer.wrap((byte[]) createArgs.get("params"))
101-
: null);
93+
final ByteBuffer additionalParams =
94+
createArgs.containsKey("params")
95+
? ByteBuffer.wrap((byte[]) createArgs.get("params"))
96+
: null;
10297
try {
103-
if (usesHybridComposition) {
104-
handler.createAndroidViewForPlatformView(request);
98+
if (usesPlatformViewLayer) {
99+
final PlatformViewCreationRequest request =
100+
new PlatformViewCreationRequest(
101+
(int) createArgs.get("id"),
102+
(String) createArgs.get("viewType"),
103+
0,
104+
0,
105+
0,
106+
0,
107+
(int) createArgs.get("direction"),
108+
additionalParams);
109+
handler.createForPlatformViewLayer(request);
105110
result.success(null);
106111
} else {
107-
long textureId = handler.createVirtualDisplayForPlatformView(request);
112+
final PlatformViewCreationRequest request =
113+
new PlatformViewCreationRequest(
114+
(int) createArgs.get("id"),
115+
(String) createArgs.get("viewType"),
116+
createArgs.containsKey("top") ? (double) createArgs.get("top") : 0.0,
117+
createArgs.containsKey("left") ? (double) createArgs.get("left") : 0.0,
118+
(double) createArgs.get("width"),
119+
(double) createArgs.get("height"),
120+
(int) createArgs.get("direction"),
121+
additionalParams);
122+
long textureId = handler.createForTextureLayer(request);
108123
result.success(textureId);
109124
}
110125
} catch (IllegalStateException exception) {
@@ -115,15 +130,9 @@ private void create(@NonNull MethodCall call, @NonNull MethodChannel.Result resu
115130
private void dispose(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
116131
Map<String, Object> disposeArgs = call.arguments();
117132
int viewId = (int) disposeArgs.get("id");
118-
boolean usesHybridComposition =
119-
disposeArgs.containsKey("hybrid") && (boolean) disposeArgs.get("hybrid");
120133

121134
try {
122-
if (usesHybridComposition) {
123-
handler.disposeAndroidViewForPlatformView(viewId);
124-
} else {
125-
handler.disposeVirtualDisplayForPlatformView(viewId);
126-
}
135+
handler.dispose(viewId);
127136
result.success(null);
128137
} catch (IllegalStateException exception) {
129138
result.error("error", detailedExceptionString(exception), null);
@@ -138,14 +147,28 @@ private void resize(@NonNull MethodCall call, @NonNull MethodChannel.Result resu
138147
(double) resizeArgs.get("width"),
139148
(double) resizeArgs.get("height"));
140149
try {
141-
handler.resizePlatformView(
142-
resizeRequest,
143-
new Runnable() {
144-
@Override
145-
public void run() {
146-
result.success(null);
147-
}
148-
});
150+
final PlatformViewBufferSize sz = handler.resize(resizeRequest);
151+
if (sz == null) {
152+
result.error("error", "Failed to resize the platform view", null);
153+
} else {
154+
final Map<String, Object> response = new HashMap<>();
155+
response.put("width", (double) sz.width);
156+
response.put("height", (double) sz.height);
157+
result.success(response);
158+
}
159+
} catch (IllegalStateException exception) {
160+
result.error("error", detailedExceptionString(exception), null);
161+
}
162+
}
163+
164+
private void offset(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
165+
Map<String, Object> offsetArgs = call.arguments();
166+
try {
167+
handler.offset(
168+
(int) offsetArgs.get("id"),
169+
(double) offsetArgs.get("top"),
170+
(double) offsetArgs.get("left"));
171+
result.success(null);
149172
} catch (IllegalStateException exception) {
150173
result.error("error", detailedExceptionString(exception), null);
151174
}
@@ -249,36 +272,40 @@ public interface PlatformViewsHandler {
249272
* The Flutter application would like to display a new Android {@code View}, i.e., platform
250273
* view.
251274
*
252-
* <p>The Android {@code View} is added to the view hierarchy.
253-
*/
254-
void createAndroidViewForPlatformView(@NonNull PlatformViewCreationRequest request);
255-
256-
/**
257-
* The Flutter application would like to dispose of an existing Android {@code View} rendered in
258-
* the view hierarchy.
275+
* <p>The Android View is added to the view hierarchy. This view is rendered in the Flutter
276+
* framework by a PlatformViewLayer.
277+
*
278+
* @param request The metadata sent from the framework.
259279
*/
260-
void disposeAndroidViewForPlatformView(int viewId);
280+
void createForPlatformViewLayer(@NonNull PlatformViewCreationRequest request);
261281

262282
/**
263-
* The Flutter application would like to display a new Android {@code View}.
283+
* The Flutter application would like to display a new Android {@code View}, i.e., platform
284+
* view.
264285
*
265-
* <p>{@code View} is added to a {@code VirtualDisplay}. The framework uses id returned by this
266-
* method to lookup the texture in the engine.
286+
* <p>The Android View is added to the view hierarchy. This view is rendered in the Flutter
287+
* framework by a TextureLayer.
288+
*
289+
* @param request The metadata sent from the framework.
290+
* @return The texture ID.
267291
*/
268-
long createVirtualDisplayForPlatformView(@NonNull PlatformViewCreationRequest request);
292+
long createForTextureLayer(@NonNull PlatformViewCreationRequest request);
293+
294+
/** The Flutter application would like to dispose of an existing Android {@code View}. */
295+
void dispose(int viewId);
269296

270297
/**
271-
* The Flutter application would like to dispose of an existing Android {@code View} rendered in
272-
* a virtual display.
298+
* The Flutter application would like to resize an existing Android {@code View}.
299+
*
300+
* @param request The request to resize the platform view.
301+
* @return The buffer size where the platform view pixels are written to.
273302
*/
274-
void disposeVirtualDisplayForPlatformView(int viewId);
303+
PlatformViewBufferSize resize(@NonNull PlatformViewResizeRequest request);
275304

276305
/**
277-
* The Flutter application would like to resize an existing Android {@code View}, i.e., platform
278-
* view.
306+
* The Flutter application would like to change the offset of an existing Android {@code View}.
279307
*/
280-
void resizePlatformView(
281-
@NonNull PlatformViewResizeRequest request, @NonNull Runnable onComplete);
308+
void offset(int viewId, double top, double left);
282309

283310
/**
284311
* The user touched a platform view within Flutter.
@@ -321,6 +348,12 @@ public static class PlatformViewCreationRequest {
321348
/** The density independent height to display the platform view. */
322349
public final double logicalHeight;
323350

351+
/** The density independent top position to display the platform view. */
352+
public final double logicalTop;
353+
354+
/** The density independent left position to display the platform view. */
355+
public final double logicalLeft;
356+
324357
/**
325358
* The layout direction of the new platform view.
326359
*
@@ -332,28 +365,28 @@ public static class PlatformViewCreationRequest {
332365
/** Custom parameters that are unique to the desired platform view. */
333366
@Nullable public final ByteBuffer params;
334367

335-
/** Creates a request to construct a platform view that uses a virtual display. */
368+
/** Creates a request to construct a platform view. */
336369
public PlatformViewCreationRequest(
337370
int viewId,
338371
@NonNull String viewType,
372+
double logicalTop,
373+
double logicalLeft,
339374
double logicalWidth,
340375
double logicalHeight,
341376
int direction,
342377
@Nullable ByteBuffer params) {
343378
this.viewId = viewId;
344379
this.viewType = viewType;
380+
this.logicalTop = logicalTop;
381+
this.logicalLeft = logicalLeft;
345382
this.logicalWidth = logicalWidth;
346383
this.logicalHeight = logicalHeight;
347384
this.direction = direction;
348385
this.params = params;
349386
}
350387
}
351388

352-
/**
353-
* Request sent from Flutter to resize a platform view.
354-
*
355-
* <p>This only applies to platform views that use virtual displays.
356-
*/
389+
/** Request sent from Flutter to resize a platform view. */
357390
public static class PlatformViewResizeRequest {
358391
/** The ID of the platform view as seen by the Flutter side. */
359392
public final int viewId;
@@ -371,6 +404,20 @@ public PlatformViewResizeRequest(int viewId, double newLogicalWidth, double newL
371404
}
372405
}
373406

407+
/** The platform view buffer size. */
408+
public static class PlatformViewBufferSize {
409+
/** The width of the screen buffer. */
410+
public final int width;
411+
412+
/** The height of the screen buffer. */
413+
public final int height;
414+
415+
public PlatformViewBufferSize(int width, int height) {
416+
this.width = width;
417+
this.height = height;
418+
}
419+
}
420+
374421
/** The state of a touch event in Flutter within a platform view. */
375422
public static class PlatformViewTouch {
376423
/** The ID of the platform view as seen by the Flutter side. */

0 commit comments

Comments
 (0)