summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristian Stromme <christian.stromme@qt.io>2017-06-07 15:46:07 +0200
committerChristian Stromme <christian.stromme@qt.io>2017-07-03 14:38:01 +0000
commit5dcd9491454390b198db1d2ab45b0b418d926cde (patch)
tree5395d043d1836bbb23b29e06ebc9ea8ddcc995f1 /src
parent5c144a72d5f9b376a0351e9dcf6f0a4c8cc91294 (diff)
Android: Add lock to protect access to the platform interface
Fixes dubious lock protecting the platform interface handle, and makes sure that we lock and hold a valid reference to the platform interface before accessing it. Since the platform interface is exposed we also need to expose the mutex protecting it. Change-Id: I1ec1219a75c589bc793676369b11fb403de20102 Reviewed-by: BogDan Vatra <bogdan@kdab.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/android/androidjniaccessibility.cpp1
-rw-r--r--src/plugins/platforms/android/androidjniinput.cpp1
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp50
-rw-r--r--src/plugins/platforms/android/androidjnimain.h2
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.cpp9
5 files changed, 32 insertions, 31 deletions
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp
index eeaecd53b4..06624415d3 100644
--- a/src/plugins/platforms/android/androidjniaccessibility.cpp
+++ b/src/plugins/platforms/android/androidjniaccessibility.cpp
@@ -80,6 +80,7 @@ namespace QtAndroidAccessibility
static void setActive(JNIEnv */*env*/, jobject /*thiz*/, jboolean active)
{
+ QMutexLocker lock(QtAndroid::platformInterfaceMutex());
QAndroidPlatformIntegration *platformIntegration = QtAndroid::androidPlatformIntegration();
if (platformIntegration)
platformIntegration->accessibility()->setActive(active);
diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp
index ef95b80dd4..f19b7d5484 100644
--- a/src/plugins/platforms/android/androidjniinput.cpp
+++ b/src/plugins/platforms/android/androidjniinput.cpp
@@ -272,6 +272,7 @@ namespace QtAndroidInput
if (m_touchPoints.isEmpty())
return;
+ QMutexLocker lock(QtAndroid::platformInterfaceMutex());
QAndroidPlatformIntegration *platformIntegration = QtAndroid::androidPlatformIntegration();
if (!platformIntegration)
return;
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index 06bca0354d..4f95e84283 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -83,7 +83,7 @@ static jmethodID m_setSurfaceGeometryMethodID = nullptr;
static jmethodID m_destroySurfaceMethodID = nullptr;
static int m_pendingApplicationState = -1;
-static QBasicMutex m_pendingAppStateMtx;
+static QBasicMutex m_platformMutex;
static jclass m_bitmapClass = nullptr;
static jmethodID m_createBitmapMethodID = nullptr;
@@ -123,28 +123,26 @@ static const char m_qtTag[] = "Qt";
static const char m_classErrorMsg[] = "Can't find class \"%s\"";
static const char m_methodErrorMsg[] = "Can't find method \"%s%s\"";
-static void flushPendingApplicationState();
-
namespace QtAndroid
{
+ QBasicMutex *platformInterfaceMutex()
+ {
+ return &m_platformMutex;
+ }
+
void setAndroidPlatformIntegration(QAndroidPlatformIntegration *androidPlatformIntegration)
{
- QMutexLocker lock(&m_surfacesMutex);
m_androidPlatformIntegration = androidPlatformIntegration;
// flush the pending state if necessary.
- if (m_androidPlatformIntegration) {
- flushPendingApplicationState();
- m_androidPlatformIntegration->flushPendingUpdates();
- } else {
- QMutexLocker locker(&m_pendingAppStateMtx);
- m_pendingApplicationState = -1;
- }
+ if (m_androidPlatformIntegration && (m_pendingApplicationState != -1))
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState(m_pendingApplicationState));
+
+ m_pendingApplicationState = -1;
}
QAndroidPlatformIntegration *androidPlatformIntegration()
{
- QMutexLocker locker(&m_surfacesMutex);
return m_androidPlatformIntegration;
}
@@ -443,17 +441,6 @@ namespace QtAndroid
} // namespace QtAndroid
-// Force an update of the pending application state (state set before the platform plugin was created)
-static void flushPendingApplicationState()
-{
- QMutexLocker locker(&m_pendingAppStateMtx);
- if (m_pendingApplicationState == -1)
- return;
-
- QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState(m_pendingApplicationState));
- m_pendingApplicationState = -1;
-}
-
static jboolean startQtAndroidPlugin(JNIEnv* /*env*/, jobject /*object*//*, jobject applicationAssetManager*/)
{
m_androidPlatformIntegration = nullptr;
@@ -621,7 +608,7 @@ static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/,
m_scaledDensity = scaledDensity;
m_density = density;
- QMutexLocker lock(&m_surfacesMutex);
+ QMutexLocker lock(&m_platformMutex);
if (!m_androidPlatformIntegration) {
QAndroidPlatformIntegration::setDefaultDisplayMetrics(desktopWidthPixels,
desktopHeightPixels,
@@ -663,18 +650,22 @@ static void updateWindow(JNIEnv */*env*/, jobject /*thiz*/)
static void updateApplicationState(JNIEnv */*env*/, jobject /*thiz*/, jint state)
{
- if (!m_main || !QtAndroid::androidPlatformIntegration()) {
- QMutexLocker locker(&m_pendingAppStateMtx);
- m_pendingApplicationState = Qt::ApplicationState(state);
+ QMutexLocker lock(&m_platformMutex);
+ if (!m_main || !m_androidPlatformIntegration) {
+ m_pendingApplicationState = state;
return;
}
- flushPendingApplicationState();
-
+ // We're about to call user code from the Android thread, since we don't know
+ //the side effects we'll unlock first!
+ lock.unlock();
if (state == Qt::ApplicationActive)
QtAndroidPrivate::handleResume();
else if (state == Qt::ApplicationInactive)
QtAndroidPrivate::handlePause();
+ lock.relock();
+ if (!m_androidPlatformIntegration)
+ return;
if (state <= Qt::ApplicationInactive) {
// NOTE: sometimes we will receive two consecutive suspended notifications,
@@ -722,6 +713,7 @@ static void handleOrientationChanged(JNIEnv */*env*/, jobject /*thiz*/, jint new
Qt::ScreenOrientation native = orientations[nativeOrientation - 1];
QAndroidPlatformIntegration::setScreenOrientation(screenOrientation, native);
+ QMutexLocker lock(&m_platformMutex);
if (m_androidPlatformIntegration) {
QPlatformScreen *screen = m_androidPlatformIntegration->screen();
QWindowSystemInterface::handleScreenOrientationChange(screen->screen(),
diff --git a/src/plugins/platforms/android/androidjnimain.h b/src/plugins/platforms/android/androidjnimain.h
index 170596082d..08f1d50fe3 100644
--- a/src/plugins/platforms/android/androidjnimain.h
+++ b/src/plugins/platforms/android/androidjnimain.h
@@ -58,9 +58,11 @@ class QWidget;
class QString;
class QWindow;
class AndroidSurfaceClient;
+class QBasicMutex;
namespace QtAndroid
{
+ QBasicMutex *platformInterfaceMutex();
QAndroidPlatformIntegration *androidPlatformIntegration();
void setAndroidPlatformIntegration(QAndroidPlatformIntegration *androidPlatformIntegration);
void setQtThread(QThread *thread);
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp
index 403badb2e1..7185b573cd 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.cpp
+++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp
@@ -121,8 +121,13 @@ void *QAndroidPlatformNativeInterface::nativeResourceForIntegration(const QByteA
void QAndroidPlatformNativeInterface::customEvent(QEvent *event)
{
- if (event->type() == QEvent::User)
- QtAndroid::setAndroidPlatformIntegration(static_cast<QAndroidPlatformIntegration *>(QGuiApplicationPrivate::platformIntegration()));
+ if (event->type() != QEvent::User)
+ return;
+
+ QMutexLocker lock(QtAndroid::platformInterfaceMutex());
+ QAndroidPlatformIntegration *api = static_cast<QAndroidPlatformIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ QtAndroid::setAndroidPlatformIntegration(api);
+ api->flushPendingUpdates();
}
QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList &paramList)