diff options
author | BogDan Vatra <bogdan@kde.org> | 2019-09-17 09:54:28 +0300 |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2019-09-22 14:25:11 +0200 |
commit | ec0e9f29dfd0b45edf5fd33e8ccf763e604612d7 (patch) | |
tree | 7d65b5af4bf0291c67dfbd709c09c6563ea762cf | |
parent | f155c40fdc0b7bbc12804ba77c00e217ba6c2bb3 (diff) |
Android: Fix loading of plugins
In 5bb178c479a247720fbc3fbb7f06a32b725193ac, the Android platform plugin was moved from
platforms/android to platforms/. The unforeseen consequence of this was that the plugin
loader for plugins/platforms would now find it, whereas before it would be ignored. It
would therefore be detected as the appropriate plugin, but since it was intended to be
loaded as a static plugin, loading it dynamically would fail.
Instead of fixing the static plugin loading, we remove this hack.
Fixes: QTBUG-78440
Change-Id: Idcb6c075fdebaf67644f32a59d7aaf0d1c0bbe20
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 24 | ||||
-rw-r--r-- | src/corelib/plugin/qfactoryloader.cpp | 12 | ||||
-rw-r--r-- | src/corelib/plugin/qlibrary_unix.cpp | 8 | ||||
-rw-r--r-- | src/corelib/plugin/qpluginloader.cpp | 10 | ||||
-rw-r--r-- | src/plugins/platforms/android/android.pro | 8 | ||||
-rw-r--r-- | src/plugins/platforms/android/androidjnimain.cpp | 2 | ||||
-rw-r--r-- | src/plugins/platforms/android/main.cpp | 63 |
7 files changed, 109 insertions, 18 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index c537e8f51b..e25049f821 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2708,18 +2708,22 @@ QStringList QCoreApplication::libraryPathsLocked() QStringList *app_libpaths = new QStringList; coreappdata()->app_libpaths.reset(app_libpaths); - QString libPathEnv = qEnvironmentVariable("QT_PLUGIN_PATH"); - if (!libPathEnv.isEmpty()) { - QStringList paths = libPathEnv.split(QDir::listSeparator(), QString::SkipEmptyParts); - for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) { - QString canonicalPath = QDir(*it).canonicalPath(); - if (!canonicalPath.isEmpty() - && !app_libpaths->contains(canonicalPath)) { - app_libpaths->append(canonicalPath); + auto setPathsFromEnv = [&](QString libPathEnv) { + if (!libPathEnv.isEmpty()) { + QStringList paths = libPathEnv.split(QDir::listSeparator(), QString::SkipEmptyParts); + for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) { + QString canonicalPath = QDir(*it).canonicalPath(); + if (!canonicalPath.isEmpty() + && !app_libpaths->contains(canonicalPath)) { + app_libpaths->append(canonicalPath); + } } } - } - + }; + setPathsFromEnv(qEnvironmentVariable("QT_PLUGIN_PATH")); +#ifdef Q_OS_ANDROID + setPathsFromEnv(qEnvironmentVariable("QT_BUNDLED_LIBS_PATH")); +#endif #ifdef Q_OS_DARWIN // Check the main bundle's PlugIns directory as this is a standard location for Apple OSes. // Note that the QLibraryInfo::PluginsPath below will coincidentally be the same as this value diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index 6737aeccd2..79315ae50f 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -193,7 +193,11 @@ void QFactoryLoader::update() continue; d->loadedPaths << pluginDir; +#ifdef Q_OS_ANDROID + QString path = pluginDir; +#else QString path = pluginDir + d->suffix; +#endif if (qt_debug_component()) qDebug() << "QFactoryLoader::QFactoryLoader() checking directory path" << path << "..."; @@ -202,8 +206,10 @@ void QFactoryLoader::update() continue; QStringList plugins = QDir(path).entryList( -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) QStringList(QStringLiteral("*.dll")), +#elif defined(Q_OS_ANDROID) + QStringList(QLatin1String("plugins_%1_*.so").arg(d->suffix)), #endif QDir::Files); QLibraryPrivate *library = 0; @@ -339,6 +345,10 @@ QFactoryLoader::QFactoryLoader(const char *iid, #if QT_CONFIG(library) d->cs = cs; d->suffix = suffix; +# ifdef Q_OS_ANDROID + if (!d->suffix.isEmpty() && d->suffix.at(0) == QLatin1Char('/')) + d->suffix.remove(0, 1); +# endif QMutexLocker locker(qt_factoryloader_mutex()); update(); diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp index 44d5513163..f0de1010d7 100644 --- a/src/corelib/plugin/qlibrary_unix.cpp +++ b/src/corelib/plugin/qlibrary_unix.cpp @@ -236,6 +236,14 @@ bool QLibraryPrivate::load_sys() auto attemptFromBundle = attempt; pHnd = dlopen(QFile::encodeName(attemptFromBundle.replace(QLatin1Char('/'), QLatin1Char('_'))), dlFlags); } + if (pHnd) { + using JniOnLoadPtr = jint (*)(JavaVM *vm, void *reserved); + JniOnLoadPtr jniOnLoad = reinterpret_cast<JniOnLoadPtr>(dlsym(pHnd, "JNI_OnLoad")); + if (jniOnLoad && jniOnLoad(QtAndroidPrivate::javaVM(), nullptr) == JNI_ERR) { + dlclose(pHnd); + pHnd = nullptr; + } + } #endif if (!pHnd && fileName.startsWith(QLatin1Char('/')) && QFile::exists(attempt)) { diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp index 4e0c3a511b..cadff4f32b 100644 --- a/src/corelib/plugin/qpluginloader.cpp +++ b/src/corelib/plugin/qpluginloader.cpp @@ -311,6 +311,16 @@ static QString locatePlugin(const QString& fileName) for (const QString &path : qAsConst(paths)) { for (const QString &prefix : qAsConst(prefixes)) { for (const QString &suffix : qAsConst(suffixes)) { +#ifdef Q_OS_ANDROID + { + QString pluginPath = basePath + prefix + baseName + suffix; + const QString fn = path + QLatin1String("/lib") + pluginPath.replace(QLatin1Char('/'), QLatin1Char('_')); + if (debug) + qDebug() << "Trying..." << fn; + if (QFileInfo(fn).isFile()) + return fn; + } +#endif const QString fn = path + QLatin1Char('/') + basePath + prefix + baseName + suffix; if (debug) qDebug() << "Trying..." << fn; diff --git a/src/plugins/platforms/android/android.pro b/src/plugins/platforms/android/android.pro index 346df84038..730247cd7f 100644 --- a/src/plugins/platforms/android/android.pro +++ b/src/plugins/platforms/android/android.pro @@ -1,9 +1,5 @@ TARGET = qtforandroid -# STATICPLUGIN needed because there's a Q_IMPORT_PLUGIN in androidjnimain.cpp -# Yes, the plugin imports itself statically -DEFINES += QT_STATICPLUGIN - LIBS += -ljnigraphics -landroid QT += \ @@ -19,7 +15,8 @@ INCLUDEPATH += \ $$PWD \ $$QT_SOURCE_TREE/src/3rdparty/android -SOURCES += $$PWD/androidplatformplugin.cpp \ +SOURCES += $$PWD/main.cpp \ + $$PWD/androidplatformplugin.cpp \ $$PWD/androidcontentfileengine.cpp \ $$PWD/androiddeadlockprotector.cpp \ $$PWD/androidjnimain.cpp \ @@ -92,4 +89,5 @@ qtConfig(vulkan) { } PLUGIN_TYPE = platforms +PLUGIN_CLASS_NAME = QAndroidIntegrationPlugin load(qt_plugin) diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 915f7f0f5b..27eb337aaa 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -68,8 +68,6 @@ #include <qpa/qwindowsysteminterface.h> -Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin) - QT_BEGIN_NAMESPACE static JavaVM *m_javaVM = nullptr; diff --git a/src/plugins/platforms/android/main.cpp b/src/plugins/platforms/android/main.cpp new file mode 100644 index 0000000000..c304fc8d69 --- /dev/null +++ b/src/plugins/platforms/android/main.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2019 BogDan Vatra <bogdan@kde.org> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <qpa/qplatformintegrationplugin.h> +#include "qandroidplatformintegration.h" + +QT_BEGIN_NAMESPACE + +class QAndroidIntegrationPlugin : public QPlatformIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "android.json") + +public: + QPlatformIntegration *create(const QString& system, const QStringList& paramList) override; +}; + +QPlatformIntegration *QAndroidIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + if (!system.compare(QLatin1String("android"), Qt::CaseInsensitive)) + return new QAndroidPlatformIntegration(paramList); + + return nullptr; +} + +QT_END_NAMESPACE |