From 703614f03b73fbcc63d8315bb6a2a86156476341 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Thu, 26 Oct 2023 16:30:36 +0200 Subject: [PATCH] Android: replace QtAndroid::activity/service with QtAndroidPrivate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's no need for both, and QtAndroidPrivate is a documented namespace. Replace all calls to QtAndroid::activity/service with QtAndroidPrivate equivalents, and drop the QtAndroid version. Since we no longer store a global copy of the activity and service, we can drop the reference right away. This comes with a bit of overhead - QtAndroid::activity returned a copy of a global static QJniObject (62cb5589b3723fe8162e190cd54d9c78929b98d2, after which declared QtJniTypes became QJniObjects), while QtAndroidPrivate::activity returns a newly created QtJniTypes::Activity on each call. This however makes it also safer, as the QJniObject is then associated with the calling thread's JNI environment, and we can optimize critical code paths where it's safe to do so later. Also, QtAndroid's activity object was never updated, while QtAndroidPrivate's activity is updated in the updateNativeActivity native method. Change-Id: I36c5b504eac52d9e28b4c6b265daab8fedc877e2 Reviewed-by: Tinja Paavoseppä Reviewed-by: Assam Boudjelthia Reviewed-by: Ivan Solovev --- src/corelib/kernel/qjnihelpers.cpp | 12 +++++++ .../platforms/android/androidjnimain.cpp | 36 ++++++------------- .../platforms/android/androidjnimain.h | 2 -- .../android/qandroidplatformdialoghelpers.cpp | 2 +- .../qandroidplatformfiledialoghelper.cpp | 2 +- .../android/qandroidplatformintegration.cpp | 36 ++++++++++--------- .../android/qandroidplatformscreen.cpp | 2 +- .../android/qandroidsystemlocale.cpp | 8 ++--- 8 files changed, 49 insertions(+), 51 deletions(-) diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp index 47c4e0ed17..b84fc09f9a 100644 --- a/src/corelib/kernel/qjnihelpers.cpp +++ b/src/corelib/kernel/qjnihelpers.cpp @@ -253,12 +253,24 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env) return JNI_OK; } +Q_CORE_EXPORT jobject qt_androidActivity() +{ + QReadLocker locker(g_updateMutex()); + return g_jActivity; +} + + QtJniTypes::Activity QtAndroidPrivate::activity() { QReadLocker locker(g_updateMutex()); return g_jActivity; } +Q_CORE_EXPORT jobject qt_androidService() +{ + return g_jService; +} + QtJniTypes::Service QtAndroidPrivate::service() { return g_jService; diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 0a0c7b7a9f..d0e1c4b739 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -44,9 +44,7 @@ static jmethodID m_loadClassMethodID = nullptr; static AAssetManager *m_assetManager = nullptr; static jobject m_assets = nullptr; static jobject m_resourcesObj = nullptr; -static QtJniTypes::Activity m_activityObject = nullptr; static jmethodID m_createSurfaceMethodID = nullptr; -static QtJniTypes::Service m_serviceObject = nullptr; static jmethodID m_setSurfaceGeometryMethodID = nullptr; static jmethodID m_destroySurfaceMethodID = nullptr; @@ -160,16 +158,6 @@ namespace QtAndroid return m_applicationClass; } - QtJniTypes::Activity activity() - { - return m_activityObject; - } - - QtJniTypes::Service service() - { - return m_serviceObject; - } - void setSystemUiVisibility(SystemUiVisibility uiVisibility) { QJniObject::callStaticMethod(m_applicationClass, "setSystemUiVisibility", "(I)V", jint(uiVisibility)); @@ -496,7 +484,7 @@ static void waitForServiceSetup(JNIEnv *env, jclass /*clazz*/) Q_UNUSED(env); // The service must wait until the QCoreApplication starts otherwise onBind will be // called too early - if (m_serviceObject) + if (QtAndroidPrivate::service()) QtAndroidPrivate::waitForServiceSetup(); } @@ -867,28 +855,24 @@ static int registerNatives(JNIEnv *env) jmethodID methodID; GET_AND_CHECK_STATIC_METHOD(methodID, m_applicationClass, "activity", "()Landroid/app/Activity;"); - jobject activityObject = env->CallStaticObjectMethod(m_applicationClass, methodID); - GET_AND_CHECK_STATIC_METHOD(methodID, m_applicationClass, "service", "()Landroid/app/Service;"); - jobject serviceObject = env->CallStaticObjectMethod(m_applicationClass, methodID); + jobject contextObject = env->CallStaticObjectMethod(m_applicationClass, methodID); + if (!contextObject) { + GET_AND_CHECK_STATIC_METHOD(methodID, m_applicationClass, "service", "()Landroid/app/Service;"); + contextObject = env->CallStaticObjectMethod(m_applicationClass, methodID); + } GET_AND_CHECK_STATIC_METHOD(methodID, m_applicationClass, "classLoader", "()Ljava/lang/ClassLoader;"); m_classLoaderObject = env->NewGlobalRef(env->CallStaticObjectMethod(m_applicationClass, methodID)); clazz = env->GetObjectClass(m_classLoaderObject); GET_AND_CHECK_METHOD(m_loadClassMethodID, clazz, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); - if (serviceObject) - m_serviceObject = serviceObject; // m_serviceObject creates and manages as global ref - if (activityObject) - m_activityObject = activityObject; // m_activityObject creates and manages as global ref - - jobject object = activityObject ? activityObject : serviceObject; - if (object) { + if (contextObject) { FIND_AND_CHECK_CLASS("android/content/ContextWrapper"); GET_AND_CHECK_METHOD(methodID, clazz, "getAssets", "()Landroid/content/res/AssetManager;"); - m_assets = env->NewGlobalRef(env->CallObjectMethod(object, methodID)); + m_assets = env->NewGlobalRef(env->CallObjectMethod(contextObject, methodID)); m_assetManager = AAssetManager_fromJava(env, m_assets); GET_AND_CHECK_METHOD(methodID, clazz, "getResources", "()Landroid/content/res/Resources;"); - m_resourcesObj = env->NewGlobalRef(env->CallObjectMethod(object, methodID)); + m_resourcesObj = env->NewGlobalRef(env->CallObjectMethod(contextObject, methodID)); FIND_AND_CHECK_CLASS("android/graphics/Bitmap"); m_bitmapClass = static_cast(env->NewGlobalRef(clazz)); @@ -907,6 +891,8 @@ static int registerNatives(JNIEnv *env) m_bitmapDrawableClass, "", "(Landroid/content/res/Resources;Landroid/graphics/Bitmap;)V"); + + env->DeleteLocalRef(contextObject); } return JNI_TRUE; diff --git a/src/plugins/platforms/android/androidjnimain.h b/src/plugins/platforms/android/androidjnimain.h index 4879d7e5b2..6a52a4e319 100644 --- a/src/plugins/platforms/android/androidjnimain.h +++ b/src/plugins/platforms/android/androidjnimain.h @@ -50,8 +50,6 @@ namespace QtAndroid jobject assets(); AAssetManager *assetManager(); jclass applicationClass(); - QtJniTypes::Activity activity(); - QtJniTypes::Service service(); // Keep synchronized with flags in ActivityDelegate.java enum SystemUiVisibility { diff --git a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp index 087aca943b..a2bfb277ac 100644 --- a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp +++ b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp @@ -19,7 +19,7 @@ static jclass g_messageDialogHelperClass = nullptr; QAndroidPlatformMessageDialogHelper::QAndroidPlatformMessageDialogHelper() : m_javaMessageDialog(g_messageDialogHelperClass, "(Landroid/app/Activity;)V", - static_cast(QtAndroid::activity())) + static_cast(QtAndroidPrivate::activity())) { } diff --git a/src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp b/src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp index 8eb8858ab5..d8a5c58d2c 100644 --- a/src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp +++ b/src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp @@ -25,7 +25,7 @@ const char JniIntentClass[] = "android/content/Intent"; QAndroidPlatformFileDialogHelper::QAndroidPlatformFileDialogHelper() : QPlatformFileDialogHelper(), - m_activity(QtAndroid::activity()) + m_activity(QtAndroidPrivate::activity()) { } diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index bf6dc85a06..cc3711b746 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -80,10 +80,14 @@ void *QAndroidPlatformNativeInterface::nativeResourceForIntegration(const QByteA { if (resource=="JavaVM") return QtAndroid::javaVM(); - if (resource == "QtActivity") - return QtAndroid::activity(); - if (resource == "QtService") - return QtAndroid::service(); + if (resource == "QtActivity") { + extern Q_CORE_EXPORT jobject qt_androidActivity(); + return qt_androidActivity(); + } + if (resource == "QtService") { + extern Q_CORE_EXPORT jobject qt_androidService(); + return qt_androidService(); + } if (resource == "AndroidStyleData") { if (m_androidStyle) { if (m_androidStyle->m_styleData.isEmpty()) @@ -227,9 +231,9 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList ¶ m_accessibility = new QAndroidPlatformAccessibility(); #endif // QT_CONFIG(accessibility) - QJniObject javaActivity(QtAndroid::activity()); + QJniObject javaActivity = QtAndroidPrivate::activity(); if (!javaActivity.isValid()) - javaActivity = QtAndroid::service(); + javaActivity = QtAndroidPrivate::service(); if (javaActivity.isValid()) { QJniObject resources = javaActivity.callObjectMethod("getResources", "()Landroid/content/res/Resources;"); @@ -316,11 +320,11 @@ bool QAndroidPlatformIntegration::hasCapability(Capability cap) const switch (cap) { case ApplicationState: return true; case ThreadedPixmaps: return true; - case NativeWidgets: return QtAndroid::activity(); - case OpenGL: return QtAndroid::activity(); - case ForeignWindows: return QtAndroid::activity(); - case ThreadedOpenGL: return !needsBasicRenderloopWorkaround() && QtAndroid::activity(); - case RasterGLSurface: return QtAndroid::activity(); + case NativeWidgets: return QtAndroidPrivate::activity(); + case OpenGL: return QtAndroidPrivate::activity(); + case ForeignWindows: return QtAndroidPrivate::activity(); + case ThreadedOpenGL: return !needsBasicRenderloopWorkaround() && QtAndroidPrivate::activity(); + case RasterGLSurface: return QtAndroidPrivate::activity(); case TopStackedNativeChildWindows: return false; case MaximizeUsingFullscreenGeometry: return true; default: @@ -330,7 +334,7 @@ bool QAndroidPlatformIntegration::hasCapability(Capability cap) const QPlatformBackingStore *QAndroidPlatformIntegration::createPlatformBackingStore(QWindow *window) const { - if (!QtAndroid::activity()) + if (!QtAndroidPrivate::activity()) return nullptr; return new QAndroidPlatformBackingStore(window); @@ -338,7 +342,7 @@ QPlatformBackingStore *QAndroidPlatformIntegration::createPlatformBackingStore(Q QPlatformOpenGLContext *QAndroidPlatformIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { - if (!QtAndroid::activity()) + if (!QtAndroidPrivate::activity()) return nullptr; QSurfaceFormat format(context->format()); format.setAlphaBufferSize(8); @@ -356,7 +360,7 @@ QOpenGLContext *QAndroidPlatformIntegration::createOpenGLContext(EGLContext cont QPlatformOffscreenSurface *QAndroidPlatformIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const { - if (!QtAndroid::activity()) + if (!QtAndroidPrivate::activity()) return nullptr; QSurfaceFormat format(surface->requestedFormat()); @@ -370,7 +374,7 @@ QPlatformOffscreenSurface *QAndroidPlatformIntegration::createPlatformOffscreenS QOffscreenSurface *QAndroidPlatformIntegration::createOffscreenSurface(ANativeWindow *nativeSurface) const { - if (!QtAndroid::activity() || !nativeSurface) + if (!QtAndroidPrivate::activity() || !nativeSurface) return nullptr; auto *surface = new QOffscreenSurface; @@ -381,7 +385,7 @@ QOffscreenSurface *QAndroidPlatformIntegration::createOffscreenSurface(ANativeWi QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *window) const { - if (!QtAndroid::activity()) + if (!QtAndroidPrivate::activity()) return nullptr; #if QT_CONFIG(vulkan) diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index aec2d69fc0..3b497472ff 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -368,7 +368,7 @@ int QAndroidPlatformScreen::rasterSurfaces() void QAndroidPlatformScreen::doRedraw(QImage* screenGrabImage) { PROFILE_SCOPE; - if (!QtAndroid::activity()) + if (!QtAndroidPrivate::activity()) return; if (m_dirtyRect.isEmpty()) diff --git a/src/plugins/platforms/android/qandroidsystemlocale.cpp b/src/plugins/platforms/android/qandroidsystemlocale.cpp index 858934b1f8..ab1ece7d39 100644 --- a/src/plugins/platforms/android/qandroidsystemlocale.cpp +++ b/src/plugins/platforms/android/qandroidsystemlocale.cpp @@ -21,11 +21,9 @@ void QAndroidSystemLocale::getLocaleFromJava() const QWriteLocker locker(&m_lock); QJniObject javaLocaleObject; - QJniObject javaActivity(QtAndroid::activity()); - if (!javaActivity.isValid()) - javaActivity = QtAndroid::service(); - if (javaActivity.isValid()) { - QJniObject resources = javaActivity.callObjectMethod("getResources", "()Landroid/content/res/Resources;"); + const QJniObject javaContext = QtAndroidPrivate::context(); + if (javaContext.isValid()) { + QJniObject resources = javaContext.callObjectMethod("getResources", "()Landroid/content/res/Resources;"); QJniObject configuration = resources.callObjectMethod("getConfiguration", "()Landroid/content/res/Configuration;"); javaLocaleObject = configuration.getObjectField("locale", "Ljava/util/Locale;");