summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorBogDan Vatra <bogdan@kdab.com>2017-04-11 13:17:21 +0300
committerBogDan Vatra <bogdan@kdab.com>2017-06-07 13:01:40 +0000
commite8ea1edd89729d4caeffa70dd8cf76a686294987 (patch)
tree7d6b1d71d7112984cbbd256ca85a7063535d949c /src/corelib
parentd31deab6328d30ac31e87d6ac35ad81db37f5ae5 (diff)
Android: Fix deadlock when calling requestPermission
The hang happend when using QtAndroidPrivate::requestPermissions before the QApplication::exec. Android UI calls "sendRequestPermissionsResult" which was blocking until the event is delivered, but the qt main loop is blocked and waits for the main surface to be created by the Android UI thread which is already blocked. With this patch sendRequestPermissionsResult won't block for the result to be delivered. Change-Id: I48ada65fe9ea63471ab46d8a9d839ba1b91d17b3 Reviewed-by: Christian Stromme <christian.stromme@qt.io>
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/kernel/qjnihelpers.cpp15
-rw-r--r--src/corelib/kernel/qjnihelpers_p.h8
2 files changed, 14 insertions, 9 deletions
diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp
index 93bc477e7d..cb4b93905e 100644
--- a/src/corelib/kernel/qjnihelpers.cpp
+++ b/src/corelib/kernel/qjnihelpers.cpp
@@ -80,13 +80,13 @@ class PermissionsResultClass : public QObject
Q_OBJECT
public:
PermissionsResultClass(const QtAndroidPrivate::PermissionsResultFunc &func) : m_func(func) {}
- Q_INVOKABLE void sendResult(const QtAndroidPrivate::PermissionsHash &result) { m_func(result); }
+ Q_INVOKABLE void sendResult(const QtAndroidPrivate::PermissionsHash &result) { m_func(result); delete this;}
private:
QtAndroidPrivate::PermissionsResultFunc m_func;
};
-typedef QHash<int, QSharedPointer<PermissionsResultClass>> PendingPermissionRequestsHash;
+typedef QHash<int, PermissionsResultClass*> PendingPermissionRequestsHash;
Q_GLOBAL_STATIC(PendingPermissionRequestsHash, g_pendingPermissionRequests);
static QBasicMutex g_pendingPermissionRequestsMutex;
static int nextRequestCode()
@@ -131,11 +131,11 @@ static void sendRequestPermissionsResult(JNIEnv *env, jobject /*obj*/, jint requ
// show an error or something ?
return;
}
- auto request = std::move(*it);
+ auto request = *it;
g_pendingPermissionRequests->erase(it);
locker.unlock();
- Qt::ConnectionType connection = QThread::currentThread() == request->thread() ? Qt::DirectConnection : Qt::BlockingQueuedConnection;
+ Qt::ConnectionType connection = QThread::currentThread() == request->thread() ? Qt::DirectConnection : Qt::QueuedConnection;
QtAndroidPrivate::PermissionsHash hash;
const int size = env->GetArrayLength(permissions);
std::unique_ptr<jint[]> results(new jint[size]);
@@ -147,7 +147,7 @@ static void sendRequestPermissionsResult(JNIEnv *env, jobject /*obj*/, jint requ
QtAndroidPrivate::PermissionsResult::Denied;
hash[permission] = value;
}
- QMetaObject::invokeMethod(request.data(), "sendResult", connection, Q_ARG(QtAndroidPrivate::PermissionsHash, hash));
+ QMetaObject::invokeMethod(request, "sendResult", connection, Q_ARG(QtAndroidPrivate::PermissionsHash, hash));
}
static jboolean dispatchGenericMotionEvent(JNIEnv *, jclass, jobject event)
@@ -410,6 +410,7 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env)
g_jNativeClass = static_cast<jclass>(env->NewGlobalRef(jQtNative));
env->DeleteLocalRef(jQtNative);
+ qRegisterMetaType<QtAndroidPrivate::PermissionsHash>();
return JNI_OK;
}
@@ -491,13 +492,13 @@ void QtAndroidPrivate::requestPermissions(JNIEnv *env, const QStringList &permis
const int requestCode = nextRequestCode();
if (!directCall) {
QMutexLocker locker(&g_pendingPermissionRequestsMutex);
- (*g_pendingPermissionRequests)[requestCode] = QSharedPointer<PermissionsResultClass>::create(callbackFunc);
+ (*g_pendingPermissionRequests)[requestCode] = new PermissionsResultClass(callbackFunc);
}
runOnAndroidThread([permissions, callbackFunc, requestCode, directCall] {
if (directCall) {
QMutexLocker locker(&g_pendingPermissionRequestsMutex);
- (*g_pendingPermissionRequests)[requestCode] = QSharedPointer<PermissionsResultClass>::create(callbackFunc);
+ (*g_pendingPermissionRequests)[requestCode] = new PermissionsResultClass(callbackFunc);
}
QJNIEnvironmentPrivate env;
diff --git a/src/corelib/kernel/qjnihelpers_p.h b/src/corelib/kernel/qjnihelpers_p.h
index 62f9358513..d88e4fc19e 100644
--- a/src/corelib/kernel/qjnihelpers_p.h
+++ b/src/corelib/kernel/qjnihelpers_p.h
@@ -52,8 +52,10 @@
//
#include <jni.h>
-#include <QtCore/private/qglobal_p.h>
#include <functional>
+#include <QtCore/private/qglobal_p.h>
+#include <QHash>
+#include <QMetaType>
QT_BEGIN_NAMESPACE
@@ -117,7 +119,7 @@ namespace QtAndroidPrivate
Q_CORE_EXPORT void runOnAndroidThreadSync(const Runnable &runnable, JNIEnv *env, int timeoutMs = INT_MAX);
Q_CORE_EXPORT void runOnUiThread(QRunnable *runnable, JNIEnv *env);
Q_CORE_EXPORT void requestPermissions(JNIEnv *env, const QStringList &permissions, const PermissionsResultFunc &callbackFunc, bool directCall = false);
- Q_CORE_EXPORT QHash<QString, PermissionsResult> requestPermissionsSync(JNIEnv *env, const QStringList &permissions, int timeoutMs = INT_MAX);
+ Q_CORE_EXPORT PermissionsHash requestPermissionsSync(JNIEnv *env, const QStringList &permissions, int timeoutMs = INT_MAX);
Q_CORE_EXPORT PermissionsResult checkPermission(const QString &permission);
Q_CORE_EXPORT bool shouldShowRequestPermissionRationale(const QString &permission);
@@ -145,4 +147,6 @@ namespace QtAndroidPrivate
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QtAndroidPrivate::PermissionsHash)
+
#endif // QJNIHELPERS_H