Android A11Y: Check for active surface before calling into native code

This fixes a deadlock. The deadlock occurs on an application state
change. During this state change the QML plugin requests Android to
create a new surface for drawing and waits on the Android thread to
complete the request (QAndroidPlatformOpenGLWindow::eglSurface()).

In the meantime the android a11y delegate gets requests from the
android a11y interface. The delegate tries to access the a11y
information through the native interface, where it has to wait for the
main loop thread to get the a11y information from the QtQuick objects.

This leads to a deadlock in which the main loop thread waits on the
quick rendering thread, the rendering thread waits on the android thread
and the android thread waits on the main loop thread.

This workaround avoids this issue by not calling into native code until
a rendering surface has been created.

Task-number: QTBUG-105958
Pick-to: 6.4 6.3 6.2 5.15
Change-Id: Ib99145aa689d1d62e25d25e1f4f8598d53eee3a9
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This commit is contained in:
Jens Trillmann 2022-09-01 09:42:47 +02:00
parent 216fe24ca1
commit b8a9527544

View File

@ -282,6 +282,9 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate
return null;
}
if (m_activityDelegate.getSurfaceCount() == 0)
return null;
final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
event.setEnabled(true);
@ -344,9 +347,11 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate
// Spit out the entire hierarchy for debugging purposes
// dumpNodes(-1);
int[] ids = QtNativeAccessibility.childIdListForAccessibleObject(-1);
for (int i = 0; i < ids.length; ++i)
result.addChild(m_view, ids[i]);
if (m_activityDelegate.getSurfaceCount() != 0) {
int[] ids = QtNativeAccessibility.childIdListForAccessibleObject(-1);
for (int i = 0; i < ids.length; ++i)
result.addChild(m_view, ids[i]);
}
// The offset values have changed, so we need to re-focus the
// currently focused item, otherwise it will have an incorrect
@ -374,8 +379,9 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate
node.setClassName(m_view.getClass().getName() + DEFAULT_CLASS_NAME);
node.setPackageName(m_view.getContext().getPackageName());
if (!QtNativeAccessibility.populateNode(virtualViewId, node))
if (m_activityDelegate.getSurfaceCount() == 0 || !QtNativeAccessibility.populateNode(virtualViewId, node)) {
return node;
}
// set only if valid, otherwise we return a node that is invalid and will crash when accessed
node.setSource(m_view, virtualViewId);
@ -425,7 +431,7 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate
@Override
public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId)
{
if (virtualViewId == View.NO_ID) {
if (virtualViewId == View.NO_ID || m_activityDelegate.getSurfaceCount() == 0) {
return getNodeForView();
}
return getNodeForVirtualViewId(virtualViewId);