-
Notifications
You must be signed in to change notification settings - Fork 29.8k
Closed
flutter/engine
#43949Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listc: fatal crashCrashes that terminate the processCrashes that terminate the processe: device-specificOnly manifests on certain devicesOnly manifests on certain devicesr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-engineOwned by Engine teamOwned by Engine teamtriaged-engineTriaged by Engine teamTriaged by Engine team
Description
Is there an existing issue for this?
- I have searched the existing issues
- I have read the guide to filing a bug
Steps to reproduce
- flutter create myapp
- run app on some special device
- do two finger tap and move using trackpad.
Expected results
No Crash
Actual results
App will crash in AndroidTouchProcessor.java, because AssertionError("Unexpected pointer change") is throwed out.
After adding debug log, I find out that ACTION_SCROLL is generated by that devices, just as below:
ACTION_DOWN -> ACTION_MOVE -> ACTION_SCROLL
PS : it looks like that device uses mouse events to simulate two finger tap and move.
06-29 19:19:42.562 4919 4919 V AndroidTouchProcessor: onGenericMotionEvent, event MotionEvent { action=ACTION_HOVER_ENTER, actionButton=0, id[0]=0, x[0]=1296.2535, y[0]=398.5768, toolType[0]=TOOL_TYPE_MOUSE, buttonState=
0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=628215, downTime=144832, deviceId=7, source=0x2002, displayId=0 }
06-29 19:19:42.567 4919 4919 V AndroidTouchProcessor: onGenericMotionEvent, event MotionEvent { action=ACTION_HOVER_MOVE, actionButton=0, id[0]=0, x[0]=1296.2535, y[0]=398.5768, toolType[0]=TOOL_TYPE_MOUSE, buttonState=0
, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=628215, downTime=144832, deviceId=7, source=0x2002, displayId=0 }
06-29 19:19:42.575 4919 4919 V AndroidTouchProcessor: onGenericMotionEvent, event MotionEvent { action=ACTION_HOVER_EXIT, actionButton=0, id[0]=0, x[0]=1296.2535, y[0]=398.5768, toolType[0]=TOOL_TYPE_MOUSE, buttonState=0
, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=628222, downTime=628222, deviceId=7, source=0x2002, displayId=0 }
06-29 19:19:42.578 4919 4919 V AndroidTouchProcessor: onTouchEvent, event MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=1296.2535, y[0]=398.5768, toolType[0]=TOOL_TYPE_MOUSE, buttonState=0, classificati
on=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=628222, downTime=628222, deviceId=7, source=0x2002, displayId=0 }
06-29 19:19:42.673 4919 4919 V AndroidTouchProcessor: onTouchEvent, event MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=1277.6, y[0]=448.00885, toolType[0]=TOOL_TYPE_MOUSE, buttonState=0, classification
=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=628328, downTime=628222, deviceId=7, source=0x2002, displayId=0 }
06-29 19:19:42.675 4919 4919 V AndroidTouchProcessor: onGenericMotionEvent, event MotionEvent { action=ACTION_SCROLL, actionButton=0, id[0]=0, x[0]=0.0, y[0]=0.0, toolType[0]=TOOL_TYPE_MOUSE, buttonState=0, classificatio
n=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=628328, downTime=628222, deviceId=7, source=0x2002, displayId=0 }
Code sample
The patch below will solve this issue, and throw new AssertionError is a bad idea... Hope it will help.
From f1dced036755aa9c0860db07a615ee324894f54c Mon Sep 17 00:00:00 2001
Date: Wed, 28 Jun 2023 13:28:21 +0800
Subject: [PATCH 2/2] Fix Unexpected pointer change on Some Special device
(CPA001)
.../android/AndroidTouchProcessor.java | 26 ++++++++++++++-----
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java b/shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java
index 52715481ad..ca72ffa173 100644
--- a/shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java
+++ b/shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java
@@ -13,9 +13,12 @@ import java.nio.ByteOrder;
import java.util.HashMap;
import java.util.Map;
+import io.flutter.Log;
+
/** Sends touch information from Android to Flutter in a format that Flutter understands. */
public class AndroidTouchProcessor {
+ private static final String TAG = "AndroidTouchProcessor";
// Must match the PointerChange enum in pointer.dart.
@IntDef({
PointerChange.CANCEL,
@@ -101,6 +104,7 @@ public class AndroidTouchProcessor {
}
public boolean onTouchEvent(@NonNull MotionEvent event) {
+ Log.v(TAG, "onTouchEvent, event " + event);
return onTouchEvent(event, IDENTITY_TRANSFORM);
}
@@ -178,6 +182,9 @@ public class AndroidTouchProcessor {
public boolean onGenericMotionEvent(@NonNull MotionEvent event) {
// Method isFromSource is only available in API 18+ (Jelly Bean MR2)
// Mouse hover support is not implemented for API < 18.
+
+ Log.v(TAG, "onGenericMotionEvent, event " + event);
+
boolean isPointerEvent =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2
&& event.isFromSource(InputDevice.SOURCE_CLASS_POINTER);
@@ -244,6 +251,7 @@ public class AndroidTouchProcessor {
buttons = 0;
}
+ int panZoomType = -1;
boolean isTrackpadPan = ongoingPans.containsKey(event.getPointerId(pointerIndex));
int signalKind =
@@ -256,8 +264,14 @@ public class AndroidTouchProcessor {
packet.putLong(motionEventId); // motionEventId
packet.putLong(timeStamp); // time_stamp
if (isTrackpadPan) {
- packet.putLong(getPointerChangeForPanZoom(pointerChange)); // change
- packet.putLong(PointerDeviceKind.TRACKPAD); // kind
+ panZoomType = getPointerChangeForPanZoom(pointerChange);
+ if (panZoomType > 0) {
+ packet.putLong(panZoomType); // change
+ packet.putLong(PointerDeviceKind.TRACKPAD); // kind
+ } else {
+ packet.putLong(pointerChange); // change
+ packet.putLong(pointerKind); // kind
+ }
} else {
packet.putLong(pointerChange); // change
packet.putLong(pointerKind); // kind
@@ -266,7 +280,7 @@ public class AndroidTouchProcessor {
packet.putLong(event.getPointerId(pointerIndex)); // device
packet.putLong(0); // pointer_identifier, will be generated in pointer_data_packet_converter.cc.
- if (isTrackpadPan) {
+ if (isTrackpadPan && (panZoomType > 0)) {
float[] panStart = ongoingPans.get(event.getPointerId(pointerIndex));
packet.putDouble(panStart[0]);
packet.putDouble(panStart[1]);
@@ -334,7 +348,7 @@ public class AndroidTouchProcessor {
packet.putDouble(0.0); // scroll_delta_x
}
- if (isTrackpadPan) {
+ if (isTrackpadPan && (panZoomType > 0)) {
float[] panStart = ongoingPans.get(event.getPointerId(pointerIndex));
packet.putDouble(viewToScreenCoords[0] - panStart[0]);
packet.putDouble(viewToScreenCoords[1] - panStart[1]);
@@ -347,7 +361,7 @@ public class AndroidTouchProcessor {
packet.putDouble(1.0); // scale
packet.putDouble(0.0); // rotation
- if (isTrackpadPan && getPointerChangeForPanZoom(pointerChange) == PointerChange.PAN_ZOOM_END) {
+ if (isTrackpadPan && (panZoomType == PointerChange.PAN_ZOOM_END)) {
ongoingPans.remove(event.getPointerId(pointerIndex));
}
}
@@ -393,7 +407,7 @@ public class AndroidTouchProcessor {
} else if (pointerChange == PointerChange.UP || pointerChange == PointerChange.CANCEL) {
return PointerChange.PAN_ZOOM_END;
}
- throw new AssertionError("Unexpected pointer change");
+ return -1;
}
@PointerDeviceKind
2.41.0
Screenshots or Video
Screenshots / Video demonstration
[Upload media here]
Logs
Logs
[Paste your logs here]Flutter Doctor output
Doctor output
[Paste your output here]Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listc: fatal crashCrashes that terminate the processCrashes that terminate the processe: device-specificOnly manifests on certain devicesOnly manifests on certain devicesr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-engineOwned by Engine teamOwned by Engine teamtriaged-engineTriaged by Engine teamTriaged by Engine team