What causes "getHistoricalRawPointerCoords: Invalid historical index 1 for MotionEvent" on Android 13 devices?

huangapple go评论123阅读模式
英文:

What causes "getHistoricalRawPointerCoords: Invalid historical index 1 for MotionEvent" on Android 13 devices?

问题

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: What causes "getHistoricalRawPointerCoords: Invalid historical index 1 for MotionEvent" on Android 13 devices?

What makes Android 13 so special to produce these crashes?

This crash may be related to this issue.

Update [2023-10-01]

Here is another crash report from an Android 13 device. This one's eventId is not <US_SOCIAL_SECURITY_NUMBER> but 2097529323.

Thread: getHistoricalRawPointerCoords: Invalid array index 6 for MotionEvent { action=POINTER_DOWN(3), id[0]=1, x[0]=748.557, y[0]=1198.73, id1=2, x1=728.326, y1=1627.55, id2=3, x2=295.227, y2=1446.13, id[3]=6, x[3]=633.913, y[3]=1036.8, pointerCount=4, eventTime=15864785755000, downTime=15491031632000, deviceId=2, source=TOUCHSCREEN, displayId=0, eventId=2097529323}

backtrace:
#00 pc 0x0000000000062eee /apex/com.android.runtime/lib/bionic/libc.so (abort+138)
#01 pc 0x00000000005406db /apex/com.android.art/lib/libart.so (art::Runtime::Abort(char const*)+1406)
#02 pc 0x00000000000238ad /apex/com.google.mainline.primary.libs@340817060/lib/libbase.so/23d1f2e6ffbc35ebafef6e31362a3ad20b7abe9823895afd2d10c652dbdbbe07db02a7a5f2db936dc8c8553a986dd6324be678f3d22e389cd8261ae6d5bcecc3/libbase.so (android::base::SetAborter(std::__1::function<void (char const*)>&&)::$_0::__invoke(char const*)+48)
#03 pc 0x0000000000071b5d /system/lib/libbinder.so (android::base::LogMessage::~LogMessage()+228)
#04 pc 0x00000000000206e1 /system/lib/libinput.so (android::MotionEvent::getHistoricalRawPointerCoords(unsigned int, unsigned int) const+456)
#05 pc 0x000000000002047d /system/lib/libinput.so (android::MotionEvent::getRawAxisValue(int, unsigned int) const+36)
#06 pc 0x000000000033d3b5 /data/misc/apexdata/com.android.art/dalvik-cache/arm/boot.oat (art_jni_trampoline+60)
#07 pc 0x0000000000b8bd4d /data/misc/apexdata/com.android.art/dalvik-cache/arm/boot.oat (android.view.MotionEvent.getRawX+156)
#08 pc 0x0000000000a69aa7 /data/misc/apexdata/com.android.art/dalvik-cache/arm/boot.oat (android.view.GestureDetector.onTouchEvent+438)

英文:

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=&lt;US_SOCIAL_SECURITY_NUMBER&gt;}

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&lt;void (char const*)&gt;&amp;&amp;)::$_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) -&gt; {
    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:
What causes "getHistoricalRawPointerCoords: Invalid historical index 1 for MotionEvent" on Android 13 devices?

What makes Android 13 so special to produce these crashes?

This crash may be related to this issue.

Update [2023-10-01]

Here is another crash report from an Android 13 device. This one's eventId is not <US_SOCIAL_SECURITY_NUMBER> but 2097529323.

Thread: getHistoricalRawPointerCoords: Invalid array index 6 for MotionEvent { action=POINTER_DOWN(3), id[0]=1, x[0]=748.557, y[0]=1198.73, id[1]=2, x[1]=728.326, y[1]=1627.55, id[2]=3, x[2]=295.227, y[2]=1446.13, id[3]=6, x[3]=633.913, y[3]=1036.8, pointerCount=4, eventTime=15864785755000, downTime=15491031632000, deviceId=2, source=TOUCHSCREEN, displayId=0, eventId=2097529323}

backtrace:
  #00  pc 0x0000000000062eee  /apex/com.android.runtime/lib/bionic/libc.so (abort+138)
  #01  pc 0x00000000005406db  /apex/com.android.art/lib/libart.so (art::Runtime::Abort(char const*)+1406)
  #02  pc 0x00000000000238ad  /apex/com.google.mainline.primary.libs@340817060/lib/libbase.so/23d1f2e6ffbc35ebafef6e31362a3ad20b7abe9823895afd2d10c652dbdbbe07db02a7a5f2db936dc8c8553a986dd6324be678f3d22e389cd8261ae6d5bcecc3/libbase.so (android::base::SetAborter(std::__1::function&lt;void (char const*)&gt;&amp;&amp;)::$_0::__invoke(char const*)+48)
  #03  pc 0x0000000000071b5d  /system/lib/libbinder.so (android::base::LogMessage::~LogMessage()+228)
  #04  pc 0x00000000000206e1  /system/lib/libinput.so (android::MotionEvent::getHistoricalRawPointerCoords(unsigned int, unsigned int) const+456)
  #05  pc 0x000000000002047d  /system/lib/libinput.so (android::MotionEvent::getRawAxisValue(int, unsigned int) const+36)
  #06  pc 0x000000000033d3b5  /data/misc/apexdata/com.android.art/dalvik-cache/arm/boot.oat (art_jni_trampoline+60)
  #07  pc 0x0000000000b8bd4d  /data/misc/apexdata/com.android.art/dalvik-cache/arm/boot.oat (android.view.MotionEvent.getRawX+156)
  #08  pc 0x0000000000a69aa7  /data/misc/apexdata/com.android.art/dalvik-cache/arm/boot.oat (android.view.GestureDetector.onTouchEvent+438)

答案1

得分: 1

tl;dr:在你的函数中,使用这种模式:

MotionEvent myEventCopy = MotionEvent.obtain(event);
// 存储或传递 &#39;myEventCopy&#39; 以供以后使用

长回答:
假设你正确地索引了 MotionEvent,这种崩溃的最典型原因是在它被回收后继续使用。你没有发布你的 OnTouchListener 的整个内容。但我假设它可能是这样的:
1)将事件存储在某个集合中,以在 'onTouchListener' 结束后使用
2)将事件传递给另一个线程
3)发布一个带有对此事件的引用的可运行对象

通常,MotionEvent 的生命周期是这样的(简单的代码示例):

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

在 View 的侦听器完成后,事件将被回收。这意味着相同的 MotionEvent 对象将用于存储具有不同指针数量或历史坐标的不同事件。

解决方案是要么在监听器代码中完全处理事件,要么通过 MotionEvent.obtain(MotionEvent e) API 复制接收到的事件,以避免竞态条件。

出于历史原因,Android 使用对象池来管理 MotionEvent,以试图减少分配和垃圾回收的次数。

英文:

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

MotionEvent myEventCopy = MotionEvent.obtain(event);
// store or pass around &#39;myEventCopy&#39; 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.

huangapple
  • 本文由 发表于 2023年4月10日 20:33:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/75977158.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定