From 8c0ef140b3a7202c03f223b692b31206aaf9d8b8 Mon Sep 17 00:00:00 2001 From: Liang Jian Date: Tue, 3 Mar 2015 17:16:16 +0800 Subject: Avoid deadlock with two consecutive suspended notification According to our Android app test, sometimes we will receive two consecutive app suspended notifications. In the second app suspended notification QWindowSystemInterface::flushWindowSystemEvents() will deadlock due to the fact that the event dispatcher has been stopped in the first app suspended notification. This patch will simply return if we found the event dispatcher has been stopped in the beginning of app suspended notification. Change-Id: I15fa4a6a118510b866ff16061862f4bb8360cc9b Reviewed-by: BogDan Vatra --- src/plugins/platforms/android/androidjnimain.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/plugins/platforms/android') diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 1c157c79c3..00ef8f670a 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -593,6 +593,13 @@ static void updateApplicationState(JNIEnv */*env*/, jobject /*thiz*/, jint state return; if (state <= Qt::ApplicationInactive) { + // NOTE: sometimes we will receive two consecutive suspended notifications, + // In the second suspended notification, QWindowSystemInterface::flushWindowSystemEvents() + // will deadlock since the dispatcher has been stopped in the first suspended notification. + // To avoid the deadlock we simply return if we found the event dispatcher has been stopped. + if (QAndroidEventDispatcherStopper::instance()->stopped()) + return; + // Don't send timers and sockets events anymore if we are going to hide all windows QAndroidEventDispatcherStopper::instance()->goingToStop(true); QCoreApplication::processEvents(); -- cgit v1.2.3 From 156be545785d959aa07bd2afd99ddfd6098ab85d Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Mon, 2 Mar 2015 12:55:37 +0100 Subject: Avoid deadlock when suspending app at startup QWindowSystemInterface::flushWindowSystemEvents() is a synchronous call. This will cause a deadlock if the GUI thread is waiting for an OpenGL surface at the same time. Add deadlock protection to this case as well. Task-number: QTBUG-44721 Change-Id: Id26370f6e07011dbcd861617bf96f59e85837db6 Reviewed-by: Christian Stromme --- src/plugins/platforms/android/androidjnimain.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/plugins/platforms/android') diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 00ef8f670a..721c3f6f54 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -42,6 +42,7 @@ #include "androidjniinput.h" #include "androidjniclipboard.h" #include "androidjnimenu.h" +#include "androiddeadlockprotector.h" #include "qandroidplatformdialoghelpers.h" #include "qandroidplatformintegration.h" #include "qandroidassetsfileenginehandler.h" @@ -604,7 +605,11 @@ static void updateApplicationState(JNIEnv */*env*/, jobject /*thiz*/, jint state QAndroidEventDispatcherStopper::instance()->goingToStop(true); QCoreApplication::processEvents(); QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState(state)); - QWindowSystemInterface::flushWindowSystemEvents(); + { + AndroidDeadlockProtector protector; + if (protector.acquire()) + QWindowSystemInterface::flushWindowSystemEvents(); + } if (state == Qt::ApplicationSuspended) QAndroidEventDispatcherStopper::instance()->stopAll(); } else { -- cgit v1.2.3 From d0d107ffc88c5a4be34355e8bd32fe3d9826445a Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 13 Mar 2015 10:05:21 +0100 Subject: Android: Also populate database with otf fonts On Android 5, the Chinese fallback fonts are .otf format, and these were ignored when we populated the font database. Note that this also requires an upgrade of FreeType, otherwise the Simplified Chinese font will not load. [ChangeLog][Android] Fixed rendering Chinese text on Android 5. Change-Id: I972d0fbc0b16458650a7b82ea82a0ddd5bdfa641 Task-number: QTBUG-44648 Reviewed-by: Liang Qi --- src/plugins/platforms/android/qandroidplatformfontdatabase.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/plugins/platforms/android') diff --git a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp index 2dcc0399c0..47bf4754f1 100644 --- a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp +++ b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp @@ -51,10 +51,10 @@ void QAndroidPlatformFontDatabase::populateFontDatabase() qPrintable(fontpath)); } - QDir dir(fontpath, QLatin1String("*.ttf")); - for (int i = 0; i < int(dir.count()); ++i) { - const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i])); - + QDir dir(fontpath); + QList entries = dir.entryInfoList(QStringList() << QStringLiteral("*.ttf") << QStringLiteral("*.otf"), QDir::Files); + for (int i = 0; i < int(entries.count()); ++i) { + const QByteArray file = QFile::encodeName(entries.at(i).absoluteFilePath()); QSupportedWritingSystems supportedWritingSystems; QStringList families = addTTFile(QByteArray(), file, &supportedWritingSystems); -- cgit v1.2.3 From 5d34bf9033531264cfaa87c0259d331a2f07443b Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Fri, 13 Mar 2015 11:41:49 +0100 Subject: Avoid deadlock on suspend/resume On some devices, there is a possibility of getting a state change while we are locking the event loop for suspend. This is probably related to change 8c0ef140b3a7202c, but we should in any case use the existing deadlock protection mutex mechanism, just to make sure that there are not other cases which could trigger the same deadlock. Task-number: QTBUG-44339 Change-Id: I3e0b5fa2ddf4ef86e6b29cb1d67c4cccedd8242e Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/plugins/platforms/android/qandroideventdispatcher.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/plugins/platforms/android') diff --git a/src/plugins/platforms/android/qandroideventdispatcher.cpp b/src/plugins/platforms/android/qandroideventdispatcher.cpp index 2ba1399c6a..2348467722 100644 --- a/src/plugins/platforms/android/qandroideventdispatcher.cpp +++ b/src/plugins/platforms/android/qandroideventdispatcher.cpp @@ -33,6 +33,7 @@ #include "qandroideventdispatcher.h" #include "androidjnimain.h" +#include "androiddeadlockprotector.h" QAndroidEventDispatcher::QAndroidEventDispatcher(QObject *parent) : QUnixEventDispatcherQPA(parent) @@ -78,11 +79,13 @@ void QAndroidEventDispatcher::goingToStop(bool stop) int QAndroidEventDispatcher::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timespec *timeout) { - if (m_stopRequest.testAndSetAcquire(StopRequest, Stopping)) { - m_semaphore.acquire(); - wakeUp(); + { + AndroidDeadlockProtector protector; + if (protector.acquire() && m_stopRequest.testAndSetAcquire(StopRequest, Stopping)) { + m_semaphore.acquire(); + wakeUp(); + } } - return QUnixEventDispatcherQPA::select(nfds, readfds, writefds, exceptfds, timeout); } -- cgit v1.2.3 From eea5a6ea15651a4bc2d0d1b1f45a2542a26083d0 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 24 Nov 2014 12:05:43 +0100 Subject: Android MessageDialog: order buttons according to OS X button layout At least the dismissive action should be on the left, but we can take the OS X rules as reasonable in cases where a lot of buttons are in use. Task-number: QTBUG-42808 Change-Id: If45f991a068d47009e02d39fbb3886ff4b31c8e1 Reviewed-by: BogDan Vatra --- .../android/qandroidplatformdialoghelpers.cpp | 25 +++++++++++++++++----- .../android/qandroidplatformdialoghelpers.h | 3 +++ 2 files changed, 23 insertions(+), 5 deletions(-) (limited to 'src/plugins/platforms/android') diff --git a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp index 2ea4c90324..bcd88547d2 100644 --- a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp +++ b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp @@ -97,11 +97,15 @@ bool QAndroidPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags if (!str.isEmpty()) m_javaMessageDialog.callMethod("setDetailedText", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object()); - for (int i = QPlatformDialogHelper::FirstButton; i < QPlatformDialogHelper::LastButton; i<<=1) { - if ( opt->standardButtons() & i ) { - const QString text = QGuiApplicationPrivate::platformTheme()->standardButtonText(i); - m_javaMessageDialog.callMethod("addButton", "(ILjava/lang/String;)V", i, QJNIObjectPrivate::fromString(text).object()); - } + // http://developer.android.com/design/building-blocks/dialogs.html + // dismissive action on the left, affirmative on the right + // There don't seem to be more fine-grained rules, but the OS X layout + // at least conforms to this one rule and makes the rest deterministic. + const int * currentLayout = buttonLayout(Qt::Horizontal, MacLayout); + while (*currentLayout != QPlatformDialogHelper::EOL) { + int role = (*currentLayout & ~QPlatformDialogHelper::Reverse); + addButtons(opt, static_cast(role)); + ++currentLayout; } m_javaMessageDialog.callMethod("show", "(J)V", jlong(static_cast(this))); @@ -109,6 +113,17 @@ bool QAndroidPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags return true; } +void QAndroidPlatformMessageDialogHelper::addButtons(QSharedPointer opt, ButtonRole role) +{ + for (int i = QPlatformDialogHelper::FirstButton; i < QPlatformDialogHelper::LastButton; i<<=1) { + StandardButton b = static_cast(i); + if (buttonRole(b) == role && (opt->standardButtons() & i)) { + const QString text = QGuiApplicationPrivate::platformTheme()->standardButtonText(b); + m_javaMessageDialog.callMethod("addButton", "(ILjava/lang/String;)V", i, QJNIObjectPrivate::fromString(text).object()); + } + } +} + void QAndroidPlatformMessageDialogHelper::hide() { m_javaMessageDialog.callMethod("hide", "()V"); diff --git a/src/plugins/platforms/android/qandroidplatformdialoghelpers.h b/src/plugins/platforms/android/qandroidplatformdialoghelpers.h index c1ec95a68c..7a7ad46723 100644 --- a/src/plugins/platforms/android/qandroidplatformdialoghelpers.h +++ b/src/plugins/platforms/android/qandroidplatformdialoghelpers.h @@ -56,6 +56,9 @@ public: public slots: void dialogResult(int buttonID); +private: + void addButtons(QSharedPointer opt, ButtonRole role); + private: int m_buttonId; QEventLoop m_loop; -- cgit v1.2.3