From 37d673313d65852c8c37b8066158046df9b5f49a Mon Sep 17 00:00:00 2001 From: Jens Trillmann Date: Thu, 1 Sep 2022 09:42:47 +0200 Subject: [PATCH] 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 Change-Id: Ib99145aa689d1d62e25d25e1f4f8598d53eee3a9 Reviewed-by: Assam Boudjelthia (cherry picked from commit b8a95275440b8a143ee648466fd8b5401ee1e839) Reviewed-by: Qt Cherry-pick Bot --- .../accessibility/QtAccessibilityDelegate.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java index 23d021b785b..dc821968a9c 100644 --- a/src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java @@ -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);