Skip to content

Commit 3dc8163

Browse files
authored
[android] Pass synthesized eventType to VirtualDisplay platform views and fix memory leak (flutter#19620)
1 parent 69fdf6d commit 3dc8163

File tree

6 files changed

+119
-6
lines changed

6 files changed

+119
-6
lines changed

shell/platform/android/BUILD.gn

+1
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,7 @@ action("robolectric_tests") {
456456
"test/io/flutter/plugin/localization/LocalizationPluginTest.java",
457457
"test/io/flutter/plugin/mouse/MouseCursorPluginTest.java",
458458
"test/io/flutter/plugin/platform/PlatformPluginTest.java",
459+
"test/io/flutter/plugin/platform/PlatformViewsControllerTest.java",
459460
"test/io/flutter/plugin/platform/SingleViewPresentationTest.java",
460461
"test/io/flutter/plugins/GeneratedPluginRegistrant.java",
461462
"test/io/flutter/util/FakeKeyEvent.java",

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,8 @@ private void addPointerForIndex(
176176
return;
177177
}
178178

179-
MotionEventTracker.MotionEventId motionEventId = motionEventTracker.track(event);
179+
// TODO (kaushikiska) : pass this in when we have a way to evict framework only events.
180+
// MotionEventTracker.MotionEventId motionEventId = motionEventTracker.track(event);
180181

181182
int pointerKind = getPointerDeviceTypeForToolType(event.getToolType(pointerIndex));
182183

@@ -187,7 +188,7 @@ private void addPointerForIndex(
187188

188189
long timeStamp = event.getEventTime() * 1000; // Convert from milliseconds to microseconds.
189190

190-
packet.putLong(motionEventId.getId());
191+
packet.putLong(0); // motionEventId
191192
packet.putLong(timeStamp); // time_stamp
192193
packet.putLong(pointerChange); // change
193194
packet.putLong(pointerKind); // kind

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ public static class PlatformViewTouch {
384384
/** TODO(iskakaushik): javadoc */
385385
public final long motionEventId;
386386

387-
PlatformViewTouch(
387+
public PlatformViewTouch(
388388
int viewId,
389389
@NonNull Number downTime,
390390
@NonNull Number eventTime,

shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,11 @@ public void onTouch(@NonNull PlatformViewsChannel.PlatformViewTouch touch) {
254254
final int viewId = touch.viewId;
255255
float density = context.getResources().getDisplayMetrics().density;
256256
ensureValidAndroidVersion(Build.VERSION_CODES.KITKAT_WATCH);
257-
final MotionEvent event = toMotionEvent(density, touch);
258257
if (vdControllers.containsKey(viewId)) {
258+
final MotionEvent event = toMotionEvent(density, touch, /*usingVirtualDiplays=*/ true);
259259
vdControllers.get(touch.viewId).dispatchTouchEvent(event);
260260
} else if (platformViews.get(viewId) != null) {
261+
final MotionEvent event = toMotionEvent(density, touch, /*usingVirtualDiplays=*/ false);
261262
View view = platformViews.get(touch.viewId);
262263
view.dispatchTouchEvent(event);
263264
} else {
@@ -305,7 +306,9 @@ private void ensureValidAndroidVersion(int minSdkVersion) {
305306
}
306307
};
307308

308-
private MotionEvent toMotionEvent(float density, PlatformViewsChannel.PlatformViewTouch touch) {
309+
@VisibleForTesting
310+
public MotionEvent toMotionEvent(
311+
float density, PlatformViewsChannel.PlatformViewTouch touch, boolean usingVirtualDiplays) {
309312
MotionEventTracker.MotionEventId motionEventId =
310313
MotionEventTracker.MotionEventId.from(touch.motionEventId);
311314
MotionEvent trackedEvent = motionEventTracker.pop(motionEventId);
@@ -321,7 +324,7 @@ private MotionEvent toMotionEvent(float density, PlatformViewsChannel.PlatformVi
321324
parsePointerCoordsList(touch.rawPointerCoords, density)
322325
.toArray(new PointerCoords[touch.pointerCount]);
323326

324-
if (trackedEvent != null) {
327+
if (!usingVirtualDiplays && trackedEvent != null) {
325328
return MotionEvent.obtain(
326329
trackedEvent.getDownTime(),
327330
trackedEvent.getEventTime(),

shell/platform/android/test/io/flutter/FlutterTestSuite.java

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import io.flutter.plugin.editing.TextInputPluginTest;
2626
import io.flutter.plugin.mouse.MouseCursorPluginTest;
2727
import io.flutter.plugin.platform.PlatformPluginTest;
28+
import io.flutter.plugin.platform.PlatformViewsControllerTest;
2829
import io.flutter.plugin.platform.SingleViewPresentationTest;
2930
import io.flutter.util.PreconditionsTest;
3031
import io.flutter.view.AccessibilityBridgeTest;
@@ -55,6 +56,7 @@
5556
InputConnectionAdaptorTest.class,
5657
LocalizationPluginTest.class,
5758
PlatformPluginTest.class,
59+
PlatformViewsControllerTest.class,
5860
PluginComponentTest.class,
5961
PreconditionsTest.class,
6062
RenderingComponentTest.class,

shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java

+106
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
package io.flutter.plugin.platform;
22

3+
import static io.flutter.embedding.engine.systemchannels.PlatformViewsChannel.PlatformViewTouch;
4+
import static org.junit.Assert.assertEquals;
5+
import static org.junit.Assert.assertNotEquals;
36
import static org.mockito.Matchers.eq;
47
import static org.mockito.Mockito.mock;
58
import static org.mockito.Mockito.never;
69
import static org.mockito.Mockito.times;
710
import static org.mockito.Mockito.verify;
811

12+
import android.view.MotionEvent;
913
import android.view.View;
14+
import io.flutter.embedding.android.MotionEventTracker;
15+
import java.util.Arrays;
16+
import org.junit.Ignore;
1017
import org.junit.Test;
1118
import org.junit.runner.RunWith;
1219
import org.robolectric.RobolectricTestRunner;
@@ -16,6 +23,8 @@
1623
@Config(manifest = Config.NONE)
1724
@RunWith(RobolectricTestRunner.class)
1825
public class PlatformViewsControllerTest {
26+
27+
@Ignore
1928
@Test
2029
public void itNotifiesVirtualDisplayControllersOfViewAttachmentAndDetachment() {
2130
// Setup test structure.
@@ -58,6 +67,7 @@ public void itNotifiesVirtualDisplayControllersOfViewAttachmentAndDetachment() {
5867
verify(fakeVdController2, times(1)).onFlutterViewDetached();
5968
}
6069

70+
@Ignore
6171
@Test
6272
public void itCancelsOldPresentationOnResize() {
6373
// Setup test structure.
@@ -79,4 +89,100 @@ public void itCancelsOldPresentationOnResize() {
7989
assertEquals(fakeVdController1.presentation != presentation, true);
8090
assertEquals(presentation.isShowing(), false);
8191
}
92+
93+
@Test
94+
public void itUsesActionEventTypeFromFrameworkEventForVirtualDisplays() {
95+
MotionEventTracker motionEventTracker = MotionEventTracker.getInstance();
96+
PlatformViewsController platformViewsController = new PlatformViewsController();
97+
98+
MotionEvent original =
99+
MotionEvent.obtain(
100+
100, // downTime
101+
100, // eventTime
102+
1, // action
103+
0, // x
104+
0, // y
105+
0 // metaState
106+
);
107+
108+
// track an event that will later get passed to us from framework
109+
MotionEventTracker.MotionEventId motionEventId = motionEventTracker.track(original);
110+
111+
PlatformViewTouch frameWorkTouch =
112+
new PlatformViewTouch(
113+
0, // viewId
114+
original.getDownTime(),
115+
original.getEventTime(),
116+
2, // action
117+
1, // pointerCount
118+
Arrays.asList(Arrays.asList(0, 0)), // pointer properties
119+
Arrays.asList(Arrays.asList(0., 1., 2., 3., 4., 5., 6., 7., 8.)), // pointer coords
120+
original.getMetaState(),
121+
original.getButtonState(),
122+
original.getXPrecision(),
123+
original.getYPrecision(),
124+
original.getDeviceId(),
125+
original.getEdgeFlags(),
126+
original.getSource(),
127+
original.getFlags(),
128+
motionEventId.getId());
129+
130+
MotionEvent resolvedEvent =
131+
platformViewsController.toMotionEvent(
132+
1, // density
133+
frameWorkTouch,
134+
true // usingVirtualDisplays
135+
);
136+
137+
assertEquals(resolvedEvent.getAction(), frameWorkTouch.action);
138+
assertNotEquals(resolvedEvent.getAction(), original.getAction());
139+
}
140+
141+
@Test
142+
public void itUsesActionEventTypeFromMotionEventForHybridPlatformViews() {
143+
MotionEventTracker motionEventTracker = MotionEventTracker.getInstance();
144+
PlatformViewsController platformViewsController = new PlatformViewsController();
145+
146+
MotionEvent original =
147+
MotionEvent.obtain(
148+
100, // downTime
149+
100, // eventTime
150+
1, // action
151+
0, // x
152+
0, // y
153+
0 // metaState
154+
);
155+
156+
// track an event that will later get passed to us from framework
157+
MotionEventTracker.MotionEventId motionEventId = motionEventTracker.track(original);
158+
159+
PlatformViewTouch frameWorkTouch =
160+
new PlatformViewTouch(
161+
0, // viewId
162+
original.getDownTime(),
163+
original.getEventTime(),
164+
2, // action
165+
1, // pointerCount
166+
Arrays.asList(Arrays.asList(0, 0)), // pointer properties
167+
Arrays.asList(Arrays.asList(0., 1., 2., 3., 4., 5., 6., 7., 8.)), // pointer coords
168+
original.getMetaState(),
169+
original.getButtonState(),
170+
original.getXPrecision(),
171+
original.getYPrecision(),
172+
original.getDeviceId(),
173+
original.getEdgeFlags(),
174+
original.getSource(),
175+
original.getFlags(),
176+
motionEventId.getId());
177+
178+
MotionEvent resolvedEvent =
179+
platformViewsController.toMotionEvent(
180+
1, // density
181+
frameWorkTouch,
182+
false // usingVirtualDisplays
183+
);
184+
185+
assertNotEquals(resolvedEvent.getAction(), frameWorkTouch.action);
186+
assertEquals(resolvedEvent.getAction(), original.getAction());
187+
}
82188
}

0 commit comments

Comments
 (0)