From 749b063af39b2752276cb1268d199ee82abb80cc Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Mon, 3 Jun 2024 10:21:23 -0700 Subject: [PATCH] PerformanceHintManager needs a valid Java thread FIXES=[343965368, 343550453] --- .../backend/platforms/PlatformEGLAndroid.h | 5 +++++ filament/backend/src/VirtualMachineEnv.cpp | 12 +++++++++++- .../opengl/platforms/PlatformEGLAndroid.cpp | 18 +++++++++++++++++- .../utils/android/PerformanceHintManager.h | 6 ++++++ .../src/android/PerformanceHintManager.cpp | 7 +++++++ 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/filament/backend/include/backend/platforms/PlatformEGLAndroid.h b/filament/backend/include/backend/platforms/PlatformEGLAndroid.h index d0caeb8c89b..c3cc7da89d8 100644 --- a/filament/backend/include/backend/platforms/PlatformEGLAndroid.h +++ b/filament/backend/include/backend/platforms/PlatformEGLAndroid.h @@ -90,8 +90,13 @@ class PlatformEGLAndroid : public PlatformEGL { AcquiredImage transformAcquiredImage(AcquiredImage source) noexcept override; private: + struct InitializeJvmForPerformanceManagerIfNeeded { + InitializeJvmForPerformanceManagerIfNeeded(); + }; + int mOSVersion; ExternalStreamManagerAndroid& mExternalStreamManager; + InitializeJvmForPerformanceManagerIfNeeded const mInitializeJvmForPerformanceManagerIfNeeded; utils::PerformanceHintManager mPerformanceHintManager; utils::PerformanceHintManager::Session mPerformanceHintSession; diff --git a/filament/backend/src/VirtualMachineEnv.cpp b/filament/backend/src/VirtualMachineEnv.cpp index ba156a8ad48..c7ff7b17906 100644 --- a/filament/backend/src/VirtualMachineEnv.cpp +++ b/filament/backend/src/VirtualMachineEnv.cpp @@ -16,13 +16,23 @@ #include "private/backend/VirtualMachineEnv.h" +#include #include +#include + namespace filament { JavaVM* VirtualMachineEnv::sVirtualMachine = nullptr; -// This is called when the library is loaded. We need this to get a reference to the global VM +/* + * This is typically called by filament_jni.so when it is loaded. If filament_jni.so is not used, + * then this must be called manually -- however, this is a problem because VirtualMachineEnv.h + * is currently private and part of backend. + * For now, we authorize this usage, but we will need to fix it; by making a proper public + * API for this. + */ +UTILS_PUBLIC UTILS_NOINLINE jint VirtualMachineEnv::JNI_OnLoad(JavaVM* vm) noexcept { JNIEnv* env = nullptr; diff --git a/filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp b/filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp index 94d602a0ba8..577b66fb315 100644 --- a/filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp +++ b/filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp @@ -19,6 +19,8 @@ #include #include +#include + #include "opengl/GLUtils.h" #include "ExternalStreamManagerAndroid.h" @@ -82,9 +84,23 @@ using EGLStream = Platform::Stream; // --------------------------------------------------------------------------------------------- +PlatformEGLAndroid::InitializeJvmForPerformanceManagerIfNeeded::InitializeJvmForPerformanceManagerIfNeeded() { + // PerformanceHintManager() needs the calling thread to be a Java thread; so we need + // to attach this thread to the JVM before we initialize PerformanceHintManager. + // This should be done in PerformanceHintManager(), but libutils doesn't have access to + // VirtualMachineEnv. + if (PerformanceHintManager::isSupported()) { + (void)VirtualMachineEnv::get().getEnvironment(); + } +} + +// --------------------------------------------------------------------------------------------- + PlatformEGLAndroid::PlatformEGLAndroid() noexcept : PlatformEGL(), - mExternalStreamManager(ExternalStreamManagerAndroid::create()) { + mExternalStreamManager(ExternalStreamManagerAndroid::create()), + mInitializeJvmForPerformanceManagerIfNeeded(), + mPerformanceHintManager() { char scratch[PROP_VALUE_MAX + 1]; int length = __system_property_get("ro.build.version.release", scratch); diff --git a/libs/utils/include/utils/android/PerformanceHintManager.h b/libs/utils/include/utils/android/PerformanceHintManager.h index 9808186475c..40101773157 100644 --- a/libs/utils/include/utils/android/PerformanceHintManager.h +++ b/libs/utils/include/utils/android/PerformanceHintManager.h @@ -55,9 +55,15 @@ class UTILS_PUBLIC PerformanceHintManager : int reportActualWorkDuration(int64_t actualDurationNanos) noexcept; }; + // caveat: This must be called on a Java thread PerformanceHintManager() noexcept; ~PerformanceHintManager() noexcept; + // Whether PerformanceHintManager APIs are supported (which doesn't mean PerformanceHintManager + // itself is, use isValid()). + static bool isSupported() noexcept; + + // Whether PerformanceHintManager can be used. bool isValid() const; int64_t getPreferredUpdateRateNanos() const noexcept; diff --git a/libs/utils/src/android/PerformanceHintManager.cpp b/libs/utils/src/android/PerformanceHintManager.cpp index c2c8f8b8f15..4b8dd08d83e 100644 --- a/libs/utils/src/android/PerformanceHintManager.cpp +++ b/libs/utils/src/android/PerformanceHintManager.cpp @@ -47,6 +47,13 @@ PerformanceHintManager::PerformanceHintManager() noexcept { PerformanceHintManager::~PerformanceHintManager() noexcept = default; +bool PerformanceHintManager::isSupported() noexcept { + if (__builtin_available(android __ANDROID_API_T__, *)) { + return true; + } + return false; +} + bool PerformanceHintManager::isValid() const { return mImpl->mManager != nullptr; }