Android A11Y: Fix deadlock in QtAndroidAccessibility::runInObjectContext()

On android the event loop is normally blocked, when the application
is suspended, e.g. when it enters the background or when the screen is
locked (see android.app.background_running). This leads to a problem
when we try to process events after this happens, e.g. when android
sends us an ACTION_CLEAR_ACCESSIBILITY_FOCUS event after the event loop
is suspended. While handling it we eventually call
QtAndroidAccessibility::runInObjectContext() which tries to do a
blocking call on the object context, however, with the event loop being
suspended we run into a deadlock which leads to an ANR.  So we need to
make sure to never make a blocking call while the event loop is
suspended.

Task-number: QTBUG-102594
Pick-to: 6.4 6.3 6.2 5.15
Change-Id: I33f0440a3da84fb4bdae5ab0fc10d514c73f23ad
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This commit is contained in:
Mike Achtelik 2022-06-28 09:55:25 +02:00
parent 100d5bd582
commit ac984bd876

View File

@ -61,7 +61,13 @@ namespace QtAndroidAccessibility
template <typename Func, typename Ret> template <typename Func, typename Ret>
void runInObjectContext(QObject *context, Func &&func, Ret *retVal) void runInObjectContext(QObject *context, Func &&func, Ret *retVal)
{ {
QMetaObject::invokeMethod(context, func, Qt::BlockingQueuedConnection, retVal); if (!QtAndroid::blockEventLoopsWhenSuspended()
|| QGuiApplication::applicationState() != Qt::ApplicationSuspended) {
QMetaObject::invokeMethod(context, func, Qt::BlockingQueuedConnection, retVal);
} else {
__android_log_print(ANDROID_LOG_WARN, m_qtTag,
"Could not run accessibility call in object context, event loop suspended.");
}
} }
void initialize() void initialize()