2

The following crash is rare but it does happen on different devices:

[libc.so] abort
SIGABRT

Thread:

getHistoricalRawPointerCoords: Invalid historical index 1 for MotionEvent { action=UP, id[0]=0, x[0]=810.527, y[0]=1609.98, eventTime=232287463228000, downTime=232287242045000, deviceId=3, source=TOUCHSCREEN, displayId=0, eventId=<US_SOCIAL_SECURITY_NUMBER>}

backtrace:

#00  pc 0x0000000000051ce8  /apex/com.android.runtime/lib64/bionic/libc.so (abort+164)
  #01  pc 0x00000000006f9f28  /apex/com.android.art/lib64/libart.so (art::Runtime::Abort(char const*)+472)
  #02  pc 0x0000000000016ea8  /apex/com.android.art/lib64/libbase.so (android::base::SetAborter(std::__1::function<void (char const*)>&&)::$_3::__invoke(char const*)+80)
  #03  pc 0x00000000000a3090  /system/lib64/libbinder.so (android::base::LogMessage::~LogMessage()+352)
  #04  pc 0x000000000002a824  /system/lib64/libinput.so (android::MotionEvent::getHistoricalRawPointerCoords(unsigned long, unsigned long) const+504)
  #05  pc 0x000000000002a578  /system/lib64/libinput.so (android::MotionEvent::getHistoricalRawAxisValue(int, unsigned long, unsigned long) const+28)
  #06  pc 0x0000000000048c40  /system/lib64/libinput.so (android::VelocityTracker::addMovement(android::MotionEvent const*)+496)
  #07  pc 0x00000000002f0384  /data/misc/apexdata/com.android.art/dalvik-cache/arm64/boot.oat (art_jni_trampoline+132)
  #08  pc 0x0000000000c93f14  /data/misc/apexdata/com.android.art/dalvik-cache/arm64/boot.oat (android.view.VelocityTracker.addMovement+68)
  #09  pc 0x0000000000c80bb4  /data/misc/apexdata/com.android.art/dalvik-cache/arm64/boot.oat (android.view.GestureDetector.onTouchEvent+660)
  #10  pc 0x0000000000c924d0  /data/misc/apexdata/com.android.art/dalvik-cache/arm64/boot.oat (android.view.ScaleGestureDetector.onTouchEvent+176)
  #11  pc 0x000000000020a2b0  /apex/com.android.art/lib64/libart.so (nterp_helper+4016)

The relevant code:

relativeLayoutFoo.setOnTouchListener((v, event) -> {
    try {
        if (event == null) {
            return false;
        } else {
            //consume event
  
        }
    } catch (Exception ex) {
        
    }
    return false;
}); 

Could anyone offer a tip about the possible causes of this crash?

Please note "eventId=<US_SOCIAL_SECURITY_NUMBER>" in the thread. The app has nothing to do with US social security. It does not access user account information at all. It does not use any third-party ad packages.

Update [2023-05-26]

I modified the code to consume only copies of MotionEvent by using MotionEvent.obtain(event) and it has not made any difference. This appears to occur only on Android 13 devices: enter image description here

What makes Android 13 so special to produce these crashes?

This crash may be related to this issue.

Hong
  • 17,643
  • 21
  • 81
  • 142
  • 1
    hi @Hong, were you able to solve the above issue? We're also suffering similar crash, same pattern (crash logs, 100% Android 13 for the last 60 days). – pqtuan86 Jun 13 '23 at 08:48
  • @pqtuan86 No, unfortunately. Actually, there are lots of MotionEvent related to crashes from Android 13. I will edit my question by adding some of them. Android 13 apparently has an issue with MotionEvent. – Hong Jun 13 '23 at 12:19

1 Answers1

1

tl;dr: In your function, use this pattern:

MotionEvent myEventCopy = MotionEvent.obtain(event);
// store or pass around 'myEventCopy' for later use

Long answer:

Assuming that you are correctly indexing into the MotionEvent, the most typical cause of this crash is the usage of the event after it has been recycled. You didn't post the entire contents of your OnTouchListener. But I assume it could be something like:

  1. Store the event in some collection, to be used after the 'onTouchListener' is finished
  2. Pass the event to another thread
  3. Post some runnable with a reference to this event

In general, the MotionEvent lifecycle is like this (just a code sketch):

MotionEvent event = MotionEvent.obtain();
View.onTouchListener(event);
event.recycle();

After the View's listener has finished, the event gets recycled. That means that the same MotionEvent object would be used to store a different event with different number of pointers or historical coordinates.

The solution is to either process the event completely inside your listener code, or to make a copy of the received event via MotionEvent.obtain(MotionEvent e) API to avoid the race condition.

For historical reasons, Android uses object pools for MotionEvents as an attempt to reduce the number of allocations and garbage collection.

vishniakou
  • 11
  • 2
  • Thank you for trying to help. The listener does start a thread and call another method to consume the event. However, the code passes MotionEvent.obtain(event) as a parameter. I am going to get an instance of MotionEvent with MotionEvent.obtain(event) immediately after the listener is invoked and consumes the new instance only to see if it will make any difference and get back here. – Hong Apr 20 '23 at 17:24
  • Unfortunately, using MotionEvent.obtain(event) has not made any difference. – Hong May 26 '23 at 14:09