Flutter Engine
The Flutter Engine
AndroidTouchProcessorTest.java
Go to the documentation of this file.
1package io.flutter.embedding.android;
2
3import static io.flutter.Build.API_LEVELS;
4import static junit.framework.TestCase.assertEquals;
5import static org.mockito.Mockito.inOrder;
6import static org.mockito.Mockito.mock;
7import static org.mockito.Mockito.never;
8import static org.mockito.Mockito.verify;
9import static org.mockito.Mockito.when;
10
11import android.annotation.TargetApi;
12import android.content.Context;
13import android.view.InputDevice;
14import android.view.MotionEvent;
15import android.view.ViewConfiguration;
16import androidx.test.core.app.ApplicationProvider;
17import androidx.test.ext.junit.runners.AndroidJUnit4;
18import io.flutter.embedding.engine.renderer.FlutterRenderer;
19import java.nio.ByteBuffer;
20import java.util.concurrent.TimeUnit;
21import org.junit.Before;
22import org.junit.Test;
23import org.junit.runner.RunWith;
24import org.mockito.ArgumentCaptor;
25import org.mockito.Captor;
26import org.mockito.InOrder;
27import org.mockito.Mock;
28import org.mockito.MockitoAnnotations;
29import org.robolectric.annotation.Config;
30
31@Config(manifest = Config.NONE)
32@RunWith(AndroidJUnit4.class)
33@TargetApi(API_LEVELS.API_28)
37 @Captor ArgumentCaptor<ByteBuffer> packetCaptor;
38 @Captor ArgumentCaptor<Integer> packetSizeCaptor;
39 // Used for mock events in SystemClock.uptimeMillis() time base.
40 // 2 days in milliseconds
41 final long eventTimeMilliseconds = 172800000;
42 final float pressure = 0.8f;
43 // https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/gestures/events.dart
44 final int enginePrimaryStylusButton = 0x02;
45
46 @Before
47 public void setUp() {
48 MockitoAnnotations.openMocks(this);
49 touchProcessor = new AndroidTouchProcessor(mockRenderer, false);
50 }
51
52 private long readTimeStamp(ByteBuffer buffer) {
54 }
55
56 private long readPointerChange(ByteBuffer buffer) {
57 return buffer.getLong(2 * AndroidTouchProcessor.BYTES_PER_FIELD);
58 }
59
60 private long readPointerDeviceKind(ByteBuffer buffer) {
61 return buffer.getLong(3 * AndroidTouchProcessor.BYTES_PER_FIELD);
62 }
63
64 private long readPointerSignalKind(ByteBuffer buffer) {
65 return buffer.getLong(4 * AndroidTouchProcessor.BYTES_PER_FIELD);
66 }
67
68 private long readDevice(ByteBuffer buffer) {
69 return buffer.getLong(5 * AndroidTouchProcessor.BYTES_PER_FIELD);
70 }
71
72 private double readPointerPhysicalX(ByteBuffer buffer) {
73 return buffer.getDouble(7 * AndroidTouchProcessor.BYTES_PER_FIELD);
74 }
75
76 private double readPointerPhysicalY(ByteBuffer buffer) {
77 return buffer.getDouble(8 * AndroidTouchProcessor.BYTES_PER_FIELD);
78 }
79
80 private long readButtons(ByteBuffer buffer) {
81 return buffer.getLong(11 * AndroidTouchProcessor.BYTES_PER_FIELD);
82 }
83
84 private double readObscured(ByteBuffer buffer) {
85 return buffer.getDouble(12 * AndroidTouchProcessor.BYTES_PER_FIELD);
86 }
87
88 private double readSynthesized(ByteBuffer buffer) {
89 return buffer.getDouble(13 * AndroidTouchProcessor.BYTES_PER_FIELD);
90 }
91
92 private double readPressure(ByteBuffer buffer) {
93 return buffer.getDouble(14 * AndroidTouchProcessor.BYTES_PER_FIELD);
94 }
95
96 private double readPressureMin(ByteBuffer buffer) {
97 return buffer.getDouble(15 * AndroidTouchProcessor.BYTES_PER_FIELD);
98 }
99
100 private double readPressureMax(ByteBuffer buffer) {
101 return buffer.getDouble(16 * AndroidTouchProcessor.BYTES_PER_FIELD);
102 }
103
104 private double readDistance(ByteBuffer buffer) {
105 return buffer.getDouble(17 * AndroidTouchProcessor.BYTES_PER_FIELD);
106 }
107
108 private double readDistanceMax(ByteBuffer buffer) {
109 return buffer.getDouble(18 * AndroidTouchProcessor.BYTES_PER_FIELD);
110 }
111
112 private double readSize(ByteBuffer buffer) {
113 return buffer.getDouble(19 * AndroidTouchProcessor.BYTES_PER_FIELD);
114 }
115
116 private double readRadiusMajor(ByteBuffer buffer) {
117 return buffer.getDouble(20 * AndroidTouchProcessor.BYTES_PER_FIELD);
118 }
119
120 private double readRadiusMinor(ByteBuffer buffer) {
121 return buffer.getDouble(21 * AndroidTouchProcessor.BYTES_PER_FIELD);
122 }
123
124 private double readRadiusMin(ByteBuffer buffer) {
125 return buffer.getDouble(22 * AndroidTouchProcessor.BYTES_PER_FIELD);
126 }
127
128 private double readRadiusMax(ByteBuffer buffer) {
129 return buffer.getDouble(23 * AndroidTouchProcessor.BYTES_PER_FIELD);
130 }
131
132 private double readStylusTilt(ByteBuffer buffer) {
133 return buffer.getDouble(25 * AndroidTouchProcessor.BYTES_PER_FIELD);
134 }
135
136 private double readScrollDeltaX(ByteBuffer buffer) {
137 return buffer.getDouble(27 * AndroidTouchProcessor.BYTES_PER_FIELD);
138 }
139
140 private double readScrollDeltaY(ByteBuffer buffer) {
141 return buffer.getDouble(28 * AndroidTouchProcessor.BYTES_PER_FIELD);
142 }
143
144 private double readPointerPanX(ByteBuffer buffer) {
145 return buffer.getDouble(29 * AndroidTouchProcessor.BYTES_PER_FIELD);
146 }
147
148 private double readPointerPanY(ByteBuffer buffer) {
149 return buffer.getDouble(30 * AndroidTouchProcessor.BYTES_PER_FIELD);
150 }
151
152 private double readPointerPanDeltaX(ByteBuffer buffer) {
153 return buffer.getDouble(31 * AndroidTouchProcessor.BYTES_PER_FIELD);
154 }
155
156 private double readPointerPanDeltaY(ByteBuffer buffer) {
157 return buffer.getDouble(32 * AndroidTouchProcessor.BYTES_PER_FIELD);
158 }
159
160 private double readScale(ByteBuffer buffer) {
161 return buffer.getDouble(33 * AndroidTouchProcessor.BYTES_PER_FIELD);
162 }
163
164 private double readRotation(ByteBuffer buffer) {
165 return buffer.getDouble(34 * AndroidTouchProcessor.BYTES_PER_FIELD);
166 }
167
168 private class MotionEventMocker {
169 int pointerId;
170 int source;
171 int toolType;
172
173 MotionEventMocker(int pointerId, int source, int toolType) {
174 this.pointerId = pointerId;
175 this.source = source;
176 this.toolType = toolType;
177 }
178
179 MotionEvent mockEvent(int action, float x, float y, int buttonState) {
180 return mockEvent(action, x, y, buttonState, x, y, x, y, x, x, y);
181 }
182
183 MotionEvent mockEvent(
184 int action,
185 float x,
186 float y,
187 int buttonState,
188 float hScroll,
189 float vScroll,
190 float axisDistance,
191 float axisTilt,
192 float size,
193 float toolMajor,
194 float toolMinor) {
195 MotionEvent event = mock(MotionEvent.class);
196 when(event.getDevice()).thenReturn(null);
197 when(event.getSource()).thenReturn(source);
198 when(event.getEventTime()).thenReturn(eventTimeMilliseconds);
199 when(event.getPointerCount()).thenReturn(1);
200 when(event.getActionMasked()).thenReturn(action);
201 final int actionIndex = 0;
202 when(event.getActionIndex()).thenReturn(actionIndex);
203 when(event.getButtonState()).thenReturn(buttonState);
204 when(event.getPointerId(actionIndex)).thenReturn(pointerId);
205 when(event.getX(actionIndex)).thenReturn(x);
206 when(event.getY(actionIndex)).thenReturn(y);
207 when(event.getToolType(actionIndex)).thenReturn(toolType);
208 when(event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)).thenReturn(true);
209 when(event.getAxisValue(MotionEvent.AXIS_HSCROLL, pointerId)).thenReturn(hScroll);
210 when(event.getAxisValue(MotionEvent.AXIS_VSCROLL, pointerId)).thenReturn(vScroll);
211 when(event.getAxisValue(MotionEvent.AXIS_DISTANCE, pointerId)).thenReturn(axisDistance);
212 when(event.getAxisValue(MotionEvent.AXIS_TILT, pointerId)).thenReturn(axisTilt);
213 when(event.getPressure(actionIndex)).thenReturn(pressure);
214 when(event.getSize(actionIndex)).thenReturn(size);
215 when(event.getToolMajor(actionIndex)).thenReturn(toolMajor);
216 when(event.getToolMinor(actionIndex)).thenReturn(toolMinor);
217 return event;
218 }
219 }
220
221 @Test
222 public void normalTouch() {
223 MotionEventMocker mocker =
224 new MotionEventMocker(0, InputDevice.SOURCE_TOUCHSCREEN, MotionEvent.TOOL_TYPE_FINGER);
225 touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_DOWN, 0.0f, 0.0f, 0));
226 InOrder inOrder = inOrder(mockRenderer);
227 inOrder
228 .verify(mockRenderer)
229 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
230 ByteBuffer packet = packetCaptor.getValue();
231 assertEquals(AndroidTouchProcessor.PointerChange.DOWN, readPointerChange(packet));
232 assertEquals(AndroidTouchProcessor.PointerDeviceKind.TOUCH, readPointerDeviceKind(packet));
233 assertEquals(AndroidTouchProcessor.PointerSignalKind.NONE, readPointerSignalKind(packet));
234 assertEquals(0.0, readPointerPhysicalX(packet));
235 assertEquals(0.0, readPointerPhysicalY(packet));
236 touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_MOVE, 10.0f, 5.0f, 0));
237 inOrder
238 .verify(mockRenderer)
239 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
240 packet = packetCaptor.getValue();
241 assertEquals(AndroidTouchProcessor.PointerChange.MOVE, readPointerChange(packet));
242 assertEquals(AndroidTouchProcessor.PointerDeviceKind.TOUCH, readPointerDeviceKind(packet));
243 assertEquals(AndroidTouchProcessor.PointerSignalKind.NONE, readPointerSignalKind(packet));
244 assertEquals(10.0, readPointerPhysicalX(packet));
245 assertEquals(5.0, readPointerPhysicalY(packet));
246 touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_UP, 10.0f, 5.0f, 0));
247 inOrder
248 .verify(mockRenderer)
249 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
250 packet = packetCaptor.getValue();
251 assertEquals(AndroidTouchProcessor.PointerChange.UP, readPointerChange(packet));
252 assertEquals(AndroidTouchProcessor.PointerDeviceKind.TOUCH, readPointerDeviceKind(packet));
253 assertEquals(AndroidTouchProcessor.PointerSignalKind.NONE, readPointerSignalKind(packet));
254 assertEquals(10.0, readPointerPhysicalX(packet));
255 assertEquals(5.0, readPointerPhysicalY(packet));
256 inOrder.verifyNoMoreInteractions();
257 }
258
259 @Test
260 public void trackpadGesture() {
261 MotionEventMocker mocker =
262 new MotionEventMocker(1, InputDevice.SOURCE_MOUSE, MotionEvent.TOOL_TYPE_MOUSE);
263 touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_DOWN, 0.0f, 0.0f, 0));
264 InOrder inOrder = inOrder(mockRenderer);
265 inOrder
266 .verify(mockRenderer)
267 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
268 ByteBuffer packet = packetCaptor.getValue();
269 assertEquals(AndroidTouchProcessor.PointerChange.PAN_ZOOM_START, readPointerChange(packet));
270 assertEquals(AndroidTouchProcessor.PointerDeviceKind.TRACKPAD, readPointerDeviceKind(packet));
271 assertEquals(AndroidTouchProcessor.PointerSignalKind.NONE, readPointerSignalKind(packet));
272 assertEquals(0.0, readPointerPhysicalX(packet));
273 assertEquals(0.0, readPointerPhysicalY(packet));
274 touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_MOVE, 10.0f, 5.0f, 0));
275 inOrder
276 .verify(mockRenderer)
277 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
278 packet = packetCaptor.getValue();
279 assertEquals(AndroidTouchProcessor.PointerChange.PAN_ZOOM_UPDATE, readPointerChange(packet));
280 assertEquals(AndroidTouchProcessor.PointerDeviceKind.TRACKPAD, readPointerDeviceKind(packet));
281 assertEquals(AndroidTouchProcessor.PointerSignalKind.NONE, readPointerSignalKind(packet));
282 assertEquals(0.0, readPointerPhysicalX(packet));
283 assertEquals(0.0, readPointerPhysicalY(packet));
284 assertEquals(10.0, readPointerPanX(packet));
285 assertEquals(5.0, readPointerPanY(packet));
286 // Always zero.
287 assertEquals(0.0, readPointerPanDeltaX(packet));
288 assertEquals(0.0, readPointerPanDeltaY(packet));
289 assertEquals(0.0, readRotation(packet));
290 // Always 1.
291 assertEquals(1.0, readScale(packet));
292 touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_UP, 10.0f, 5.0f, 0));
293 inOrder
294 .verify(mockRenderer)
295 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
296 packet = packetCaptor.getValue();
297 assertEquals(AndroidTouchProcessor.PointerChange.PAN_ZOOM_END, readPointerChange(packet));
298 assertEquals(AndroidTouchProcessor.PointerDeviceKind.TRACKPAD, readPointerDeviceKind(packet));
299 assertEquals(AndroidTouchProcessor.PointerSignalKind.NONE, readPointerSignalKind(packet));
300 assertEquals(0.0, readPointerPhysicalX(packet));
301 assertEquals(0.0, readPointerPhysicalY(packet));
302 inOrder.verifyNoMoreInteractions();
303 }
304
305 @Test
306 public void mouse() {
307 MotionEventMocker mocker =
308 new MotionEventMocker(2, InputDevice.SOURCE_MOUSE, MotionEvent.TOOL_TYPE_MOUSE);
309 touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_DOWN, 0.0f, 0.0f, 1));
310 InOrder inOrder = inOrder(mockRenderer);
311 inOrder
312 .verify(mockRenderer)
313 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
314 ByteBuffer packet = packetCaptor.getValue();
315 assertEquals(AndroidTouchProcessor.PointerChange.DOWN, readPointerChange(packet));
316 assertEquals(AndroidTouchProcessor.PointerDeviceKind.MOUSE, readPointerDeviceKind(packet));
317 assertEquals(AndroidTouchProcessor.PointerSignalKind.NONE, readPointerSignalKind(packet));
318 assertEquals(0.0, readPointerPhysicalX(packet));
319 assertEquals(0.0, readPointerPhysicalY(packet));
320 touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_MOVE, 10.0f, 5.0f, 1));
321 inOrder
322 .verify(mockRenderer)
323 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
324 packet = packetCaptor.getValue();
325 assertEquals(AndroidTouchProcessor.PointerChange.MOVE, readPointerChange(packet));
326 assertEquals(AndroidTouchProcessor.PointerDeviceKind.MOUSE, readPointerDeviceKind(packet));
327 assertEquals(AndroidTouchProcessor.PointerSignalKind.NONE, readPointerSignalKind(packet));
328 assertEquals(10.0, readPointerPhysicalX(packet));
329 assertEquals(5.0, readPointerPhysicalY(packet));
330 touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_UP, 10.0f, 5.0f, 1));
331 inOrder
332 .verify(mockRenderer)
333 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
334 packet = packetCaptor.getValue();
335 assertEquals(AndroidTouchProcessor.PointerChange.UP, readPointerChange(packet));
336 assertEquals(AndroidTouchProcessor.PointerDeviceKind.MOUSE, readPointerDeviceKind(packet));
337 assertEquals(AndroidTouchProcessor.PointerSignalKind.NONE, readPointerSignalKind(packet));
338 assertEquals(10.0, readPointerPhysicalX(packet));
339 assertEquals(5.0, readPointerPhysicalY(packet));
340 inOrder.verifyNoMoreInteractions();
341 }
342
343 @Test
345 // Regression test for https://github.com/flutter/flutter/issues/111068
346 MotionEventMocker mocker =
347 new MotionEventMocker(1, InputDevice.SOURCE_STYLUS, MotionEvent.TOOL_TYPE_STYLUS);
348 // ACTION_BUTTON_PRESS is not handled by AndroidTouchProcessor, nothing should be dispatched.
349 touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_BUTTON_PRESS, 0.0f, 0.0f, 0));
350 verify(mockRenderer, never()).dispatchPointerDataPacket(ByteBuffer.allocate(0), 0);
351 }
352
353 @Test
354 @Config(minSdk = API_LEVELS.API_26)
355 public void scrollWheelAbove26() {
356 // Pointer id must be zero to match actionIndex in mocked event.
357 final int pointerId = 0;
358 MotionEventMocker mocker =
359 new MotionEventMocker(
360 pointerId, InputDevice.SOURCE_CLASS_POINTER, MotionEvent.TOOL_TYPE_MOUSE);
361 final float horizontalScrollValue = -1f;
362 final float verticalScrollValue = .5f;
363 final Context context = ApplicationProvider.getApplicationContext();
364 final double horizontalScaleFactor =
365 ViewConfiguration.get(context).getScaledHorizontalScrollFactor();
366 final double verticalScaleFactor =
367 ViewConfiguration.get(context).getScaledVerticalScrollFactor();
368 // Zero verticalScaleFactor will cause this test to miss bugs.
369 assertEquals("zero horizontal scale factor", true, horizontalScaleFactor != 0);
370 assertEquals("zero vertical scale factor", true, verticalScaleFactor != 0);
371
372 final MotionEvent event =
373 mocker.mockEvent(
374 MotionEvent.ACTION_SCROLL,
375 0.0f,
376 0.0f,
377 1,
378 horizontalScrollValue,
379 verticalScrollValue,
380 0.0f,
381 0.0f,
382 0.0f,
383 0.0f,
384 0.0f);
385 boolean handled = touchProcessor.onGenericMotionEvent(event, context);
386
387 InOrder inOrder = inOrder(mockRenderer);
388 inOrder
389 .verify(mockRenderer)
390 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
391 ByteBuffer packet = packetCaptor.getValue();
392
393 assertEquals(-horizontalScrollValue * horizontalScaleFactor, readScrollDeltaX(packet));
394 assertEquals(-verticalScrollValue * verticalScaleFactor, readScrollDeltaY(packet));
395 verify(event).getAxisValue(MotionEvent.AXIS_HSCROLL, pointerId);
396 verify(event).getAxisValue(MotionEvent.AXIS_VSCROLL, pointerId);
397
398 inOrder.verifyNoMoreInteractions();
399 }
400
401 @Test
402 @Config(sdk = API_LEVELS.API_25)
403 public void scrollWheelBelow26() {
404 // Pointer id must be zero to match actionIndex in mocked event.
405 final int pointerId = 0;
406 MotionEventMocker mocker =
407 new MotionEventMocker(
408 pointerId, InputDevice.SOURCE_CLASS_POINTER, MotionEvent.TOOL_TYPE_MOUSE);
409 final float horizontalScrollValue = -1f;
410 final float verticalScrollValue = .5f;
411 final Context context = ApplicationProvider.getApplicationContext();
412
413 final MotionEvent event =
414 mocker.mockEvent(
415 MotionEvent.ACTION_SCROLL,
416 0.0f,
417 0.0f,
418 1,
419 horizontalScrollValue,
420 verticalScrollValue,
421 0.0f,
422 0.0f,
423 0.0f,
424 0.0f,
425 0.0f);
426 boolean handled = touchProcessor.onGenericMotionEvent(event, context);
427 assertEquals(true, handled);
428
429 InOrder inOrder = inOrder(mockRenderer);
430 inOrder
431 .verify(mockRenderer)
432 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
433 ByteBuffer packet = packetCaptor.getValue();
434
435 // Magic number from roboletric's theme.
436 final double magicScrollFactor = 64;
437 assertEquals(-horizontalScrollValue * magicScrollFactor, readScrollDeltaX(packet));
438 assertEquals(-verticalScrollValue * magicScrollFactor, readScrollDeltaY(packet));
439 verify(event).getAxisValue(MotionEvent.AXIS_HSCROLL, pointerId);
440 verify(event).getAxisValue(MotionEvent.AXIS_VSCROLL, pointerId);
441
442 // Trigger default values.
443 touchProcessor.onGenericMotionEvent(event, null);
444 inOrder
445 .verify(mockRenderer)
446 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
447 packet = packetCaptor.getValue();
448
449 assertEquals(
450 (double) -horizontalScrollValue * AndroidTouchProcessor.DEFAULT_HORIZONTAL_SCROLL_FACTOR,
451 readScrollDeltaX(packet));
452 assertEquals(
453 (double) -verticalScrollValue * AndroidTouchProcessor.DEFAULT_VERTICAL_SCROLL_FACTOR,
454 readScrollDeltaY(packet));
455
456 inOrder.verifyNoMoreInteractions();
457 }
458
459 @Test
460 public void timeStamp() {
461 final int pointerId = 0;
462 MotionEventMocker mocker =
463 new MotionEventMocker(
464 pointerId, InputDevice.SOURCE_CLASS_POINTER, MotionEvent.TOOL_TYPE_MOUSE);
465
466 final MotionEvent event = mocker.mockEvent(MotionEvent.ACTION_SCROLL, 1f, 1f, 1);
467 boolean handled = touchProcessor.onTouchEvent(event);
468
469 InOrder inOrder = inOrder(mockRenderer);
470 inOrder
471 .verify(mockRenderer)
472 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
473 ByteBuffer packet = packetCaptor.getValue();
474
475 assertEquals(TimeUnit.MILLISECONDS.toMicros(eventTimeMilliseconds), readTimeStamp(packet));
476
477 inOrder.verifyNoMoreInteractions();
478 }
479
480 @Test
481 public void device() {
482 final int pointerId = 2;
483 MotionEventMocker mocker =
484 new MotionEventMocker(
485 pointerId, InputDevice.SOURCE_CLASS_POINTER, MotionEvent.TOOL_TYPE_MOUSE);
486
487 final MotionEvent event = mocker.mockEvent(MotionEvent.ACTION_SCROLL, 1f, 1f, 1);
488 boolean handled = touchProcessor.onTouchEvent(event);
489
490 InOrder inOrder = inOrder(mockRenderer);
491 inOrder
492 .verify(mockRenderer)
493 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
494 ByteBuffer packet = packetCaptor.getValue();
495
496 assertEquals(pointerId, readDevice(packet));
497 verify(event).getPointerId(0);
498
499 inOrder.verifyNoMoreInteractions();
500 }
501
502 @Test
503 public void physicalXPhysicalY() {
504 MotionEventMocker mocker =
505 new MotionEventMocker(1, InputDevice.SOURCE_CLASS_POINTER, MotionEvent.TOOL_TYPE_MOUSE);
506 final float x = 10.0f;
507 final float y = 20.0f;
508 final MotionEvent event = mocker.mockEvent(MotionEvent.ACTION_DOWN, x, y, 0);
509 boolean handled = touchProcessor.onTouchEvent(event);
510
511 InOrder inOrder = inOrder(mockRenderer);
512 inOrder
513 .verify(mockRenderer)
514 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
515 ByteBuffer packet = packetCaptor.getValue();
516
517 assertEquals((double) x, readPointerPhysicalX(packet));
518 assertEquals((double) y, readPointerPhysicalY(packet));
519
520 inOrder.verifyNoMoreInteractions();
521 }
522
523 @Test
524 public void obscured() {
525 MotionEventMocker mocker =
526 new MotionEventMocker(1, InputDevice.SOURCE_CLASS_POINTER, MotionEvent.TOOL_TYPE_MOUSE);
527 final MotionEvent event = mocker.mockEvent(MotionEvent.ACTION_DOWN, 10.0f, 20.0f, 0);
528 boolean handled = touchProcessor.onTouchEvent(event);
529
530 InOrder inOrder = inOrder(mockRenderer);
531 inOrder
532 .verify(mockRenderer)
533 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
534 ByteBuffer packet = packetCaptor.getValue();
535
536 // Always zero.
537 assertEquals(0.0, readObscured(packet));
538
539 inOrder.verifyNoMoreInteractions();
540 }
541
542 @Test
543 public void synthesized() {
544 MotionEventMocker mocker =
545 new MotionEventMocker(1, InputDevice.SOURCE_CLASS_POINTER, MotionEvent.TOOL_TYPE_MOUSE);
546 final MotionEvent event = mocker.mockEvent(MotionEvent.ACTION_DOWN, 10.0f, 20.0f, 0);
547 boolean handled = touchProcessor.onTouchEvent(event);
548
549 InOrder inOrder = inOrder(mockRenderer);
550 inOrder
551 .verify(mockRenderer)
552 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
553 ByteBuffer packet = packetCaptor.getValue();
554
555 // Always zero.
556 assertEquals(0.0, readSynthesized(packet));
557
558 inOrder.verifyNoMoreInteractions();
559 }
560
561 @Test
562 public void pressure() {
563 MotionEventMocker mocker =
564 new MotionEventMocker(1, InputDevice.SOURCE_CLASS_POINTER, MotionEvent.TOOL_TYPE_MOUSE);
565 final MotionEvent event = mocker.mockEvent(MotionEvent.ACTION_DOWN, 10.0f, 20.0f, 0);
566 boolean handled = touchProcessor.onTouchEvent(event);
567
568 InOrder inOrder = inOrder(mockRenderer);
569 inOrder
570 .verify(mockRenderer)
571 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
572 ByteBuffer packet = packetCaptor.getValue();
573
574 // Always zero.
575 assertEquals((double) pressure, readPressure(packet));
576 // Verify default range with null device.
577 assertEquals(0.0, readPressureMin(packet));
578 assertEquals(1.0, readPressureMax(packet));
579
580 inOrder.verifyNoMoreInteractions();
581 }
582
583 @Test
584 public void stylusDistance() {
585 MotionEventMocker mocker =
586 new MotionEventMocker(0, InputDevice.SOURCE_STYLUS, MotionEvent.TOOL_TYPE_STYLUS);
587 final float distance = 10.0f;
588 final float tilt = 20.0f;
589 final MotionEvent event =
590 mocker.mockEvent(
591 MotionEvent.ACTION_DOWN,
592 0.0f,
593 0.0f,
594 MotionEvent.BUTTON_STYLUS_PRIMARY,
595 0.0f,
596 0.0f,
597 distance,
598 tilt,
599 0.0f,
600 0.0f,
601 0.0f);
602 boolean handled = touchProcessor.onTouchEvent(event);
603
604 InOrder inOrder = inOrder(mockRenderer);
605 inOrder
606 .verify(mockRenderer)
607 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
608 ByteBuffer packet = packetCaptor.getValue();
609 assertEquals(AndroidTouchProcessor.PointerDeviceKind.STYLUS, readPointerDeviceKind(packet));
610 assertEquals((double) distance, readDistance(packet));
611 // Always zero.
612 assertEquals(0.0, readDistanceMax(packet));
613 assertEquals((double) tilt, readStylusTilt(packet));
614 assertEquals(enginePrimaryStylusButton, readButtons(packet));
615
616 inOrder.verifyNoMoreInteractions();
617 }
618
619 @Test
620 public void sizeAndRadius() {
621 MotionEventMocker mocker =
622 new MotionEventMocker(0, InputDevice.SOURCE_STYLUS, MotionEvent.TOOL_TYPE_STYLUS);
623 final float size = 10.0f;
624 final float radiusMajor = 20.0f;
625 final float radiusMinor = 30.0f;
626 final MotionEvent event =
627 mocker.mockEvent(
628 MotionEvent.ACTION_DOWN,
629 0.0f,
630 0.0f,
631 0,
632 0.0f,
633 0.0f,
634 0.0f,
635 0.0f,
636 size,
637 radiusMajor,
638 radiusMinor);
639 boolean handled = touchProcessor.onTouchEvent(event);
640
641 InOrder inOrder = inOrder(mockRenderer);
642 inOrder
643 .verify(mockRenderer)
644 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
645 ByteBuffer packet = packetCaptor.getValue();
646
647 verify(event).getSize(0);
648 verify(event).getToolMajor(0);
649 verify(event).getToolMinor(0);
650
651 assertEquals((double) size, readSize(packet));
652 assertEquals((double) radiusMajor, readRadiusMajor(packet));
653 assertEquals((double) radiusMinor, readRadiusMinor(packet));
654 // Always zero.
655 assertEquals(0.0, readRadiusMin(packet));
656 assertEquals(0.0, readRadiusMax(packet));
657
658 inOrder.verifyNoMoreInteractions();
659 }
660
661 @Test
663 // Regression test for https://github.com/flutter/flutter/issues/129765
664 MotionEventMocker mocker =
665 new MotionEventMocker(0, InputDevice.SOURCE_MOUSE, MotionEvent.TOOL_TYPE_MOUSE);
666
667 touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_DOWN, 0.0f, 0.0f, 0));
668 InOrder inOrder = inOrder(mockRenderer);
669 inOrder
670 .verify(mockRenderer)
671 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
672 ByteBuffer packet = packetCaptor.getValue();
673 assertEquals(AndroidTouchProcessor.PointerChange.PAN_ZOOM_START, readPointerChange(packet));
674 assertEquals(AndroidTouchProcessor.PointerDeviceKind.TRACKPAD, readPointerDeviceKind(packet));
675 assertEquals(AndroidTouchProcessor.PointerSignalKind.NONE, readPointerSignalKind(packet));
676 assertEquals(0.0, readPointerPhysicalX(packet));
677 assertEquals(0.0, readPointerPhysicalY(packet));
678
679 touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_MOVE, 10.0f, 5.0f, 0));
680 inOrder
681 .verify(mockRenderer)
682 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
683 packet = packetCaptor.getValue();
684 assertEquals(AndroidTouchProcessor.PointerChange.PAN_ZOOM_UPDATE, readPointerChange(packet));
685 assertEquals(AndroidTouchProcessor.PointerDeviceKind.TRACKPAD, readPointerDeviceKind(packet));
686 assertEquals(AndroidTouchProcessor.PointerSignalKind.NONE, readPointerSignalKind(packet));
687 assertEquals(0.0, readPointerPhysicalX(packet));
688 assertEquals(0.0, readPointerPhysicalY(packet));
689 assertEquals(10.0, readPointerPanX(packet));
690 assertEquals(5.0, readPointerPanY(packet));
691
692 touchProcessor.onGenericMotionEvent(
693 mocker.mockEvent(MotionEvent.ACTION_SCROLL, 0.0f, 0.0f, 0),
694 ApplicationProvider.getApplicationContext());
695 inOrder
696 .verify(mockRenderer)
697 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
698 packet = packetCaptor.getValue();
699 packet.rewind();
700 while (packet.hasRemaining()) {
701 assertEquals(0, packet.get());
702 }
703
704 touchProcessor.onTouchEvent(mocker.mockEvent(MotionEvent.ACTION_UP, 10.0f, 5.0f, 0));
705 inOrder
706 .verify(mockRenderer)
707 .dispatchPointerDataPacket(packetCaptor.capture(), packetSizeCaptor.capture());
708 packet = packetCaptor.getValue();
709 assertEquals(AndroidTouchProcessor.PointerChange.PAN_ZOOM_END, readPointerChange(packet));
710 assertEquals(AndroidTouchProcessor.PointerDeviceKind.TRACKPAD, readPointerDeviceKind(packet));
711 assertEquals(AndroidTouchProcessor.PointerSignalKind.NONE, readPointerSignalKind(packet));
712 assertEquals(0.0, readPointerPhysicalX(packet));
713 assertEquals(0.0, readPointerPhysicalY(packet));
714 inOrder.verifyNoMoreInteractions();
715 }
716}
static final int API_26
Definition: Build.java:16
static final int API_25
Definition: Build.java:15
boolean onGenericMotionEvent(@NonNull MotionEvent event, @NonNull Context context)
SkBitmap source
Definition: examples.cpp:28
FlKeyEvent * event
double y
double x
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259