Status Update
Comments
il...@google.com <il...@google.com> #2
Michael - can you clarify what guarantees we should expect from multi touch events and if out of order timestamps is expected (and something every View needs to be resilient to, which seems a bit excessive) or if there's something we can do at the Activity subclass level to filter out these motion events?
py...@gmail.com <py...@gmail.com> #3
MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=370.98633, y[0]=2096.3086, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=55702626, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=370.72266, y[0]=2088.5156, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=55702642, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=370.98633, y[0]=2077.3828, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=55702660, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_POINTER_DOWN(1), actionButton=0, id[0]=0, x[0]=370.98633, y[0]=2077.3828, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=916.25977, y[1]=818.81836, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=55702660, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=371.51367, y[0]=2068.4766, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=915.9961, y[1]=819.93164, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=55702676, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=372.04102, y[0]=2060.127, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=915.46875, y[1]=821.0449, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=55702693, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=372.04102, y[0]=2052.8906, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=915.7324, y[1]=823.8281, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=55702708, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=370.45898, y[0]=2036.748, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=915.7324, y[1]=828.28125, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=55702725, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=365.97656, y[0]=2025.0586, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=916.25977, y[1]=833.84766, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=55702744, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=361.49414, y[0]=2016.709, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=917.5781, y[1]=846.09375, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=55702760, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=357.53906, y[0]=2011.1426, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=920.21484, y[1]=866.68945, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=55702777, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=354.375, y[0]=2007.8027, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=923.90625, y[1]=887.28516, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=55702794, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=349.6289, y[0]=2005.5762, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=928.916, y[1]=907.88086, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=55702810, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=345.14648, y[0]=2005.0195, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=935.7715, y[1]=929.0332, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=55702827, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=342.50977, y[0]=2005.5762, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=945.791, y[1]=952.4121, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=55702844, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=340.13672, y[0]=2007.2461, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=956.0742, y[1]=974.1211, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=1, eventTime=55702861, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_POINTER_UP(1), actionButton=0, id[0]=0, x[0]=336.70898, y[0]=2007.8027, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=956.0742, y[1]=974.1211, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=55702877, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=336.70898, y[0]=2007.8027, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=55702877, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=336.4453, y[0]=2009.4727, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=55702894, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=337.5, y[0]=2011.1426, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=55702912, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=1, x[0]=1058.6426, y[0]=1087.6758, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=55702912, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=341.45508, y[0]=2015.0391, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=55702927, downTime=55702626, deviceId=5, source=0x1002, displayId=0 }
I added new lines at the end to highlight the bogus events right before the crash. Here's the TL;DR of this stream: ACTION_DOWN(0), ACTION_POINTER_DOWN(1), ACTION_POINTER_UP(1) then an unexpected ACTION_DOWN(1) followed by ACTION_MOVE(0)
Device is a Samsung SM-N975U running Android 10 (not that we have a recipe to repro..)
So my next step is to just strip out down events that don't follow the contract.
de...@gmail.com <de...@gmail.com> #4
TÅŸkler
ra...@gmail.com <ra...@gmail.com> #5
jb...@google.com <jb...@google.com> #6
Hey, Adam can you comment on #2 or help find someone that can?
ab...@gmail.com <ab...@gmail.com> #7
Hi
ro...@gmail.com <ro...@gmail.com> #8
cd word-count-beam
il...@google.com <il...@google.com>
sv...@google.com <sv...@google.com> #9
Thanks for reporting the issue. In the past ~ 2 years, the input team has spent significant effort making sure that the touch stream received by the applications is consistent. All of the known issues have been fixed in the latest Android versions. In this bug, the reported versions are Android 6 -> 10, for which we unfortunately aren't able to issue fixes at this point.
If you experience issues on the newest versions, please reopen this bug or file a new one.
il...@google.com <il...@google.com> #10
This bug is about providing a backported fix via AndroidX (which has its own ComponentActivity
subclass of the framework Activity
) that would ensure that these events are ignored even on older versions of Android.
sv...@google.com <sv...@google.com> #11
I see. There's not a specific fix from the android framework input team that comes to mind. We did a lot of internal refactoring to improve the streams. Sending this to the AndroidX owners to develop a custom solution for those versions.
sv...@google.com <sv...@google.com> #12
Hi George,
Could you please help route this to the correct AndroidX team responsible for input stream handling? Currently joseprio@ is the default assignee for the jetpack - input component, which does not seem correct.
mo...@google.com <mo...@google.com> #13
I think Ian's team owns ComponentActivity
Description
This isn't a bug report, it's a "feature request" / proposal for having the base Activity class fix a multi touch bug that happens across Android version (Android 6 - 10), though the vast majority seems to be on Samsung devices (>94%)
I shared some data points here:
The bug manifests as an ACTION_DOWN event being sent in the middle of a stream of multi touch events (which is never supposed to happen). The ACTION_DOWN event has an eventTime timestamp that is in the past of previous events. Right after that unexpected ACTION_DOWN event we get events that are still from the original stream, which introduces crashes in widgets such as ViewPager because the ACTION_DOWN event caused such widgets to forget the pointer id they were tracking.
The proposed fix here is to filter these bogus ACTION_DOWN touch events at the activity level. i.e. when a MOVE, POINTER_UP or POINTER_DOWN event is followed by a ACTION_DOWN event with an eventTime that's prior to the last event, we could skip that event.
I'm implementing this workaround in the Square POS app right now and will report back, but this bug has been around for a while and it's symptoms (e.g. ViewPager crashing with IllegalArgumentExcepion: pointerIndex out of range) have been impacting numerous Android apps for a long time.