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>
This commit is contained in:
parent
5c144a72d5
commit
5dcd949145
@ -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);
|
||||
|
@ -272,6 +272,7 @@ namespace QtAndroidInput
|
||||
if (m_touchPoints.isEmpty())
|
||||
return;
|
||||
|
||||
QMutexLocker lock(QtAndroid::platformInterfaceMutex());
|
||||
QAndroidPlatformIntegration *platformIntegration = QtAndroid::androidPlatformIntegration();
|
||||
if (!platformIntegration)
|
||||
return;
|
||||
|
@ -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(),
|
||||
|
@ -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);
|
||||
|
@ -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 ¶mList)
|
||||
|
Loading…
Reference in New Issue
Block a user