由于 AccessibilityNodeInfo getChild 而获得大量 ANR
获取大量 ANR 报告,
<块引用>"main" prio=5 tid=1 可运行|group="main" sCount=0 dsCount=0 flags=0 obj=0x72e8a568 self=0xe65da000|sysTid=20592 nice=0 cgrp=default sched=0/0 句柄=0xe9f6b4a8|state=R schedstat=(35792446568 9751828904 97371) utm=2328 stm=1249 core=2 HZ=100|堆栈=0xff6e5000-0xff6e7000 堆栈大小=8MB|持有互斥锁=mutator lock"(共享持有)本机:pc 00000000002c45b7/system/lib/libart.so (_ZN3art15DumpNativeStackERNSt3__113basic_ostreamIcNS0_11char_traitsIcEEEEiP12BacktraceMapPKcPNS_9ArtMethodEPv+130)本机:pc 0000000000355a83/system/lib/libart.so (_ZNK3art6Thread9DumpStackERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEEbP12BacktraceMapb+202)本机:pc 0000000000351f67/system/lib/libart.so (_ZNK3art6Thread4DumpERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEEbP12BacktraceMapb+34)本机:pc 00000000003698df/system/lib/libart.so (_ZN3art14DumpCheckpoint3RunEPNS_6ThreadE+654)本机:pc 000000000035662b/system/lib/libart.so (_ZN3art6Thread21RunCheckpointFunctionEv+298)本机:pc 00000000003bbcff/system/lib/libart.so (_ZN3art16JniMethodFastEndEjPNS_6ThreadE+46)本机: pc 0000000000403fdb/system/framework/arm/boot-framework.oat(Java_android_os_Parcel_nativeReadInt__J+114)在 android.os.Parcel.nativeReadInt (本机方法)在 android.os.Parcel.readInt (Parcel.java:1966)在 android.os.Parcel.readExceptionCode (Parcel.java:1906)在 android.os.Parcel.readException (Parcel.java:1885)在 android.accessibilityservice.IAccessibilityServiceConnection$Stub$Proxy.findAccessibilityNodeInfoByAccessibilityId(IAccessibilityServiceConnection.java:447)在 android.view.accessibility.AccessibilityInteractionClient.findAccessibilityNodeInfoByAccessibilityId(AccessibilityInteractionClient.java:286)在 android.view.accessibility.AccessibilityNodeInfo.getChild (AccessibilityNodeInfo.java:959)在 MyAccessibilityService.traverseNode (MyAccessibilityService.java:94)在 MyAccessibilityService.traverseNode (MyAccessibilityService.java:100)在 MyAccessibilityService.traverseNode (MyAccessibilityService.java:100)在 MyAccessibilityService.traverseNode (MyAccessibilityService.java:100)在 MyAccessibilityService.collectTextNodes (MyAccessibilityService.java:69)在 MyAccessibilityService.onAccessibilityEvent (MyAccessibilityService.java:384)在 android.accessibilityservice.AccessibilityService$2.onAccessibilityEvent(AccessibilityService.java:1527)在 android.accessibilityservice.AccessibilityService$IAccessibilityServiceClientWrapper.executeMessage(AccessibilityService.java:1712)在 com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:37)
"main" prio=5 tid=1 Native|group="main" sCount=1 dsCount=0 flags=1 obj=0x72e8a568 self=0xe65da000|sysTid=11518 nice=0 cgrp=default sched=0/0 句柄=0xe9f6b4a8|state=S schedstat=(34572861602 18459176949 199877) utm=2350 stm=1106 core=1 HZ=100|堆栈=0xff6e5000-0xff6e7000 堆栈大小=8MB|持有互斥体=本机: pc 0000000000018dac/system/lib/libc.so (syscall+28)本机: pc 00000000000b3729/system/lib/libart.so (_ZN3art17ConditionVariable16WaitHoldingLocksEPNS_6ThreadE+88)本机: pc 00000000003bbbe3/system/lib/libart.so (_ZN3artL12GoToRunnableEPNS_6ThreadE+306)本机: pc 00000000003bba81/system/lib/libart.so (_ZN3art12JniMethodEndEjPNS_6ThreadE+8)本机: pc 00000000007ca401/system/framework/arm/boot-framework.oat (Java_android_os_BinderProxy_transactNative__ILandroid_os_Parcel_2Landroid_os_Parcel_2I+144)在 android.os.BinderProxy.transactNative (本机方法)在 android.os.BinderProxy.transact (Binder.java:748)在 android.accessibilityservice.IAccessibilityServiceConnection$Stub$Proxy.findAccessibilityNodeInfoByAccessibilityId (IAccessibilityServiceConnection.java:446)在 android.view.accessibility.AccessibilityInteractionClient.findAccessibilityNodeInfoByAccessibilityId (AccessibilityInteractionClient.java:286)在 android.view.accessibility.AccessibilityNodeInfo.getChild (AccessibilityNodeInfo.java:959)在 MyAccessibilityService.traverseNode (MyAccessibilityService.java:94)在 MyAccessibilityService.traverseNode (MyAccessibilityService.java:100)在 MyAccessibilityService.traverseNode (MyAccessibilityService.java:100)在 MyAccessibilityService.traverseNode (MyAccessibilityService.java:100)在 MyAccessibilityService.collectTextNodes (MyAccessibilityService.java:69)在 MyAccessibilityService.onAccessibilityEvent (MyAccessibilityService.java:384)在 android.accessibilityservice.AccessibilityService$2.onAccessibilityEvent (AccessibilityService.java:1527)在 android.accessibilityservice.AccessibilityService$IAccessibilityServiceClientWrapper.executeMessage (AccessibilityService.java:1712)在 com.android.internal.os.HandlerCaller$MyHandler.handleMessage (HandlerCaller.java:37)在 android.os.Handler.dispatchMessage (Handler.java:105)主"prio=5 tid=1 可运行|group="main" sCount=0 dsCount=0 flags=0 obj=0x73bf7568 self=0xe7445000|sysTid=18941 nice=0 cgrp=default sched=0/0 句柄=0xeae2e4a8|state=R schedstat=(169234820933 190791369297 635928) utm=11752 stm=5170 core=0 HZ=100|堆栈=0xff795000-0xff797000 堆栈大小=8MB|持有互斥锁=mutator lock"(共享持有)在 java.util.ArrayList.clear (ArrayList.java:565)在 android.view.accessibility.AccessibilityNodeInfo.init (AccessibilityNodeInfo.java:3211)在 android.view.accessibility.AccessibilityNodeInfo.obtain (AccessibilityNodeInfo.java:3015)在 android.view.accessibility.AccessibilityCache.getNode (AccessibilityCache.java:231)- 锁定<0x0f41ae94>(一个java.lang.Object)在 android.view.accessibility.AccessibilityInteractionClient.findAccessibilityNodeInfoByAccessibilityId (AccessibilityInteractionClient.java:272)在 android.view.accessibility.AccessibilityNodeInfo.getChild (AccessibilityNodeInfo.java:959)在 MyAccessibilityService.traverseNode (MyAccessibilityService.java:84)在 MyAccessibilityService.traverseNode (MyAccessibilityService.java:85)在 MyAccessibilityService.traverseNode (MyAccessibilityService.java:85)在 MyAccessibilityService.traverseNode (MyAccessibilityService.java:85)在 MyAccessibilityService.collectTextNodes (MyAccessibilityService.java:66)在 MyAccessibilityService.onAccessibilityEvent (MyAccessibilityService.java:360)在 android.accessibilityservice.AccessibilityService$2.onAccessibilityEvent (AccessibilityService.java:1527)在 android.accessibilityservice.AccessibilityService$IAccessibilityServiceClientWrapper.executeMessage (AccessibilityService.java:1712)在 com.android.internal.os.HandlerCaller$MyHandler.handleMessage (HandlerCaller.java:37)在 android.os.Handler.dispatchMessage (Handler.java:105)主"prio=5 tid=1 TimedWaiting|group="main" sCount=1 dsCount=0 flags=1 obj=0x73228568 self=0xed55a000|sysTid=19996 nice=0 cgrp=default sched=0/0 句柄=0xed8414a8|state=S schedstat=(39022541552 53623486893 130046) utm=3252 stm=648 core=2 HZ=100|堆栈=0xff636000-0xff638000 堆栈大小=8MB|持有互斥体=在 java.lang.Object.wait (本机方法)- 等待 <0x0b44b730>(一个java.lang.Object)在 java.lang.Object.wait (Object.java:422)在 android.view.accessibility.AccessibilityInteractionClient.waitForResultTimedLocked (AccessibilityInteractionClient.java:687)在 android.view.accessibility.AccessibilityInteractionClient.getFindAccessibilityNodeInfosResultAndClear (AccessibilityInteractionClient.java:582)- 锁定<0x0b44b730>(一个java.lang.Object)在 android.view.accessibility.AccessibilityInteractionClient.findAccessibilityNodeInfoByAccessibilityId (AccessibilityInteractionClient.java:291)在 android.view.accessibility.AccessibilityInteractionClient.getRootInActiveWindow (AccessibilityInteractionClient.java:160)在 android.accessibilityservice.AccessibilityService.getRootInActiveWindow (AccessibilityService.java:572)在 MyAccessibilityService.onAccessibilityEvent (MyAccessibilityService.java:370)
我的代码
ArrayListcollectNodes(AccessibilityNodeInfo 节点){ArrayList<AccessibilityNodeInfo>nodeInfoArrayList = new ArrayList<>();尝试 {int childCount = node.getChildCount();for (int index = 0; index < childCount; index++) {AccessibilityNodeInfo childNode = node.getChild(index);遍历节点(子节点);if (childNodes != null && childNodes.size() > 0) {nodeInfoArrayList.addAll(childNodes);childNodes.clear();}}}捕获(异常 e){e.printStackTrace();}返回节点信息数组列表;}私人无效traverseNode(AccessibilityNodeInfo节点){尝试 {AccessibilityNodeInfo edittextNode = null;如果(空==节点)返回;最终 int 计数 = node.getChildCount();如果(计数 > 0){for (int i = 0; i < count; i++) {AccessibilityNodeInfo childNode = node.getChild(i);if (childNode == null) {node.recycle();返回;}别的 {遍历节点(子节点);}}} 别的 {}}捕捉(异常错误){错误.printStackTrace();}}
Android 8.0 中的更多问题.知道如何处理这些 ANR.
config.xml 文件
请注意几乎所有来自 Android 8.0 设备的 ANR 报告.
解决方案- 第一件重要的事情是回收由
getChild
、findAccessibilityNodeInfoByAccessibilityId
或任何其他函数分配的所有节点.所以你应该有这样的东西:
<块引用>
AccessibilityNodeInfo findFirstViewByText(AccessibilityNodeInfo rootNode, String text) {if (rootNode == null) 返回空值;if (rootNode.getText() != null && rootNode.getText().toString().equals(text))返回根节点;int childCount = rootNode.getChildCount();for (int i = 0; i < childCount; i++) {AccessibilityNodeInfo tmpNode = rootNode.getChild(i);如果(tmpNode!= null){AccessibilityNodeInfo res = findFirstViewByText(tmpNode, text);如果 (res != null) {返回资源;} 别的 {tmpNode.recycle();}}}返回空值;}}node = findFirstViewByText(rootNode, "something");如果(节点!= null){node.performAction(AccessibilityNodeInfo.ACTION_CLICK);node.recycle();}
请记住,当您与目标应用程序交互时,可能会过于频繁地调用
onAccessibilityEvent
,而且您在此函数中的处理会阻塞目标应用程序上的 UI 线程.你可以通过以下方式克服这个问题:- 限制对
onAccessibilityEvent
的调用,即如果最后一次执行发生在 x 毫秒之前,则不要执行您的代码,但请确保最后一次调用将触发您的代码的执行. - 通过避免不必要的遍历来提高代码的性能.定义状态,以便应用仅查找与当前状态相关的节点.
- 限制对
请随时分享您的更多代码,以便我/我们可以了解您的目标到底是什么,这样我们就可以提供更多帮助.正如我从您的日志中看到的,有几个线程遍历无障碍服务的虚拟 dom,它们导致了死锁.
Getting lot of ANR reports,
"main" prio=5 tid=1 Runnable | group="main" sCount=0 dsCount=0 flags=0 obj=0x72e8a568 self=0xe65da000 | sysTid=20592 nice=0 cgrp=default sched=0/0 handle=0xe9f6b4a8 | state=R schedstat=( 35792446568 9751828904 97371 ) utm=2328 stm=1249 core=2 HZ=100 | stack=0xff6e5000-0xff6e7000 stackSize=8MB | held mutexes= "mutator lock"(shared held) native: pc 00000000002c45b7 /system/lib/libart.so (_ZN3art15DumpNativeStackERNSt3__113basic_ostreamIcNS0_11char_traitsIcEEEEiP12BacktraceMapPKcPNS_9ArtMethodEPv+130) native: pc 0000000000355a83 /system/lib/libart.so (_ZNK3art6Thread9DumpStackERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEEbP12BacktraceMapb+202) native: pc 0000000000351f67 /system/lib/libart.so (_ZNK3art6Thread4DumpERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEEbP12BacktraceMapb+34) native: pc 00000000003698df /system/lib/libart.so (_ZN3art14DumpCheckpoint3RunEPNS_6ThreadE+654) native: pc 000000000035662b /system/lib/libart.so (_ZN3art6Thread21RunCheckpointFunctionEv+298) native: pc 00000000003bbcff /system/lib/libart.so (_ZN3art16JniMethodFastEndEjPNS_6ThreadE+46) native: pc 0000000000403fdb /system/framework/arm/boot-framework.oat (Java_android_os_Parcel_nativeReadInt__J+114) at android.os.Parcel.nativeReadInt (Native method) at android.os.Parcel.readInt (Parcel.java:1966) at android.os.Parcel.readExceptionCode (Parcel.java:1906) at android.os.Parcel.readException (Parcel.java:1885) at android.accessibilityservice.IAccessibilityServiceConnection$Stub$Proxy.findAccessibilityNodeInfoByAccessibilityId (IAccessibilityServiceConnection.java:447) at android.view.accessibility.AccessibilityInteractionClient.findAccessibilityNodeInfoByAccessibilityId (AccessibilityInteractionClient.java:286) at android.view.accessibility.AccessibilityNodeInfo.getChild (AccessibilityNodeInfo.java:959) at MyAccessibilityService.traverseNode (MyAccessibilityService.java:94) at MyAccessibilityService.traverseNode (MyAccessibilityService.java:100) at MyAccessibilityService.traverseNode (MyAccessibilityService.java:100) at MyAccessibilityService.traverseNode (MyAccessibilityService.java:100) at MyAccessibilityService.collectTextNodes (MyAccessibilityService.java:69) at MyAccessibilityService.onAccessibilityEvent (MyAccessibilityService.java:384) at android.accessibilityservice.AccessibilityService$2.onAccessibilityEvent (AccessibilityService.java:1527) at android.accessibilityservice.AccessibilityService$IAccessibilityServiceClientWrapper.executeMessage (AccessibilityService.java:1712) at com.android.internal.os.HandlerCaller$MyHandler.handleMessage (HandlerCaller.java:37)
"main" prio=5 tid=1 Native
| group="main" sCount=1 dsCount=0 flags=1 obj=0x72e8a568 self=0xe65da000
| sysTid=11518 nice=0 cgrp=default sched=0/0 handle=0xe9f6b4a8
| state=S schedstat=( 34572861602 18459176949 199877 ) utm=2350 stm=1106 core=1 HZ=100
| stack=0xff6e5000-0xff6e7000 stackSize=8MB
| held mutexes=
native: pc 0000000000018dac /system/lib/libc.so (syscall+28)
native: pc 00000000000b3729 /system/lib/libart.so (_ZN3art17ConditionVariable16WaitHoldingLocksEPNS_6ThreadE+88)
native: pc 00000000003bbbe3 /system/lib/libart.so (_ZN3artL12GoToRunnableEPNS_6ThreadE+306)
native: pc 00000000003bba81 /system/lib/libart.so (_ZN3art12JniMethodEndEjPNS_6ThreadE+8)
native: pc 00000000007ca401 /system/framework/arm/boot-framework.oat (Java_android_os_BinderProxy_transactNative__ILandroid_os_Parcel_2Landroid_os_Parcel_2I+144)
at android.os.BinderProxy.transactNative (Native method)
at android.os.BinderProxy.transact (Binder.java:748)
at android.accessibilityservice.IAccessibilityServiceConnection$Stub$Proxy.findAccessibilityNodeInfoByAccessibilityId (IAccessibilityServiceConnection.java:446)
at android.view.accessibility.AccessibilityInteractionClient.findAccessibilityNodeInfoByAccessibilityId (AccessibilityInteractionClient.java:286)
at android.view.accessibility.AccessibilityNodeInfo.getChild (AccessibilityNodeInfo.java:959)
at MyAccessibilityService.traverseNode (MyAccessibilityService.java:94)
at MyAccessibilityService.traverseNode (MyAccessibilityService.java:100)
at MyAccessibilityService.traverseNode (MyAccessibilityService.java:100)
at MyAccessibilityService.traverseNode (MyAccessibilityService.java:100)
at MyAccessibilityService.collectTextNodes (MyAccessibilityService.java:69)
at MyAccessibilityService.onAccessibilityEvent (MyAccessibilityService.java:384)
at android.accessibilityservice.AccessibilityService$2.onAccessibilityEvent (AccessibilityService.java:1527)
at android.accessibilityservice.AccessibilityService$IAccessibilityServiceClientWrapper.executeMessage (AccessibilityService.java:1712)
at com.android.internal.os.HandlerCaller$MyHandler.handleMessage (HandlerCaller.java:37)
at android.os.Handler.dispatchMessage (Handler.java:105)
"main" prio=5 tid=1 Runnable
| group="main" sCount=0 dsCount=0 flags=0 obj=0x73bf7568 self=0xe7445000
| sysTid=18941 nice=0 cgrp=default sched=0/0 handle=0xeae2e4a8
| state=R schedstat=( 169234820933 190791369297 635928 ) utm=11752 stm=5170 core=0 HZ=100
| stack=0xff795000-0xff797000 stackSize=8MB
| held mutexes= "mutator lock"(shared held)
at java.util.ArrayList.clear (ArrayList.java:565)
at android.view.accessibility.AccessibilityNodeInfo.init (AccessibilityNodeInfo.java:3211)
at android.view.accessibility.AccessibilityNodeInfo.obtain (AccessibilityNodeInfo.java:3015)
at android.view.accessibility.AccessibilityCache.getNode (AccessibilityCache.java:231)
- locked <0x0f41ae94> (a java.lang.Object)
at android.view.accessibility.AccessibilityInteractionClient.findAccessibilityNodeInfoByAccessibilityId (AccessibilityInteractionClient.java:272)
at android.view.accessibility.AccessibilityNodeInfo.getChild (AccessibilityNodeInfo.java:959)
at MyAccessibilityService.traverseNode (MyAccessibilityService.java:84)
at MyAccessibilityService.traverseNode (MyAccessibilityService.java:85)
at MyAccessibilityService.traverseNode (MyAccessibilityService.java:85)
at MyAccessibilityService.traverseNode (MyAccessibilityService.java:85)
at MyAccessibilityService.collectTextNodes (MyAccessibilityService.java:66)
at MyAccessibilityService.onAccessibilityEvent (MyAccessibilityService.java:360)
at android.accessibilityservice.AccessibilityService$2.onAccessibilityEvent (AccessibilityService.java:1527)
at android.accessibilityservice.AccessibilityService$IAccessibilityServiceClientWrapper.executeMessage (AccessibilityService.java:1712)
at com.android.internal.os.HandlerCaller$MyHandler.handleMessage (HandlerCaller.java:37)
at android.os.Handler.dispatchMessage (Handler.java:105)
"main" prio=5 tid=1 TimedWaiting
| group="main" sCount=1 dsCount=0 flags=1 obj=0x73228568 self=0xed55a000
| sysTid=19996 nice=0 cgrp=default sched=0/0 handle=0xed8414a8
| state=S schedstat=( 39022541552 53623486893 130046 ) utm=3252 stm=648 core=2 HZ=100
| stack=0xff636000-0xff638000 stackSize=8MB
| held mutexes=
at java.lang.Object.wait (Native method)
- waiting on <0x0b44b730> (a java.lang.Object)
at java.lang.Object.wait (Object.java:422)
at android.view.accessibility.AccessibilityInteractionClient.waitForResultTimedLocked (AccessibilityInteractionClient.java:687)
at android.view.accessibility.AccessibilityInteractionClient.getFindAccessibilityNodeInfosResultAndClear (AccessibilityInteractionClient.java:582)
- locked <0x0b44b730> (a java.lang.Object)
at android.view.accessibility.AccessibilityInteractionClient.findAccessibilityNodeInfoByAccessibilityId (AccessibilityInteractionClient.java:291)
at android.view.accessibility.AccessibilityInteractionClient.getRootInActiveWindow (AccessibilityInteractionClient.java:160)
at android.accessibilityservice.AccessibilityService.getRootInActiveWindow (AccessibilityService.java:572)
at MyAccessibilityService.onAccessibilityEvent (MyAccessibilityService.java:370)
My code
ArrayList<AccessibilityNodeInfo> collectNodes(AccessibilityNodeInfo node) {
ArrayList<AccessibilityNodeInfo> nodeInfoArrayList = new ArrayList<>();
try {
int childCount = node.getChildCount();
for (int index = 0; index < childCount; index++) {
AccessibilityNodeInfo childNode = node.getChild(index);
traverseNode(childNode);
if (childNodes != null && childNodes.size() > 0) {
nodeInfoArrayList.addAll(childNodes);
childNodes.clear();
}
}
}
catch (Exception e){
e.printStackTrace();
}
return nodeInfoArrayList;
}
private void traverseNode(AccessibilityNodeInfo node) {
try {
AccessibilityNodeInfo edittextNode = null;
if (null == node)
return;
final int count = node.getChildCount();
if (count > 0) {
for (int i = 0; i < count; i++) {
AccessibilityNodeInfo childNode = node.getChild(i);
if (childNode == null) {
node.recycle();
return;
}
else {
traverseNode(childNode);
}
}
} else {
}
}
catch (Exception error){
error.printStackTrace();
}
}
even more issues in Android 8.0. Any idea how to deal with these ANR's.
config.xml file
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeWindowStateChanged|typeViewFocused|typeWindowContentChanged"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagReportViewIds|flagRequestEnhancedWebAccessibility"
android:description="Test"/>
please note almost all the ANR report from Android 8.0 devices.
解决方案- The first important thing is to recycle all the nodes allocated by
getChild
,findAccessibilityNodeInfoByAccessibilityId
or any other function. So you should have something like this:
AccessibilityNodeInfo findFirstViewByText(AccessibilityNodeInfo rootNode, String text) { if (rootNode == null) return null; if (rootNode.getText() != null && rootNode.getText().toString().equals(text)) return rootNode; int childCount = rootNode.getChildCount(); for (int i = 0; i < childCount; i++) { AccessibilityNodeInfo tmpNode = rootNode.getChild(i); if (tmpNode != null) { AccessibilityNodeInfo res = findFirstViewByText(tmpNode, text); if (res != null) { return res; } else { tmpNode.recycle(); } } } return null; } } node = findFirstViewByText(rootNode, "something"); if(node != null) { node.performAction(AccessibilityNodeInfo.ACTION_CLICK); node.recycle(); }
Keep in mind that
onAccessibilityEvent
may be called too often while you interact with the target application and also your processing in this function is blocking UI Thread on the target application. You can overcome this by:- Throttling the calls to
onAccessibilityEvent
i.e. don't execute your code if the last execution happened less than x milliseconds ago, but make sure that last call will trigger execution of your code. - Improve the performance of your code by avoiding unnecessary traversing. Define states so the app will look only for the nodes relevant for the current state.
- Throttling the calls to
Feel free to share more of your code so i/we can understand what exactly is your goal, that way we can be more helpful. As i can see from your log, there are several threads traversing the virtual dom of accessibility service and they are causing deadlock.
相关文章