From cff958587de263823cd9785de2fa722e6fd2d924 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 22 Jan 2026 10:24:39 -0800 Subject: [PATCH] initialize VirtualMachineEnv on the right thread (#9624) PerformanceHint manager needs a java thread during initialization, so we need to attach a jvm to the thread that's going to be used. That thread is the filament backend thread, not necessarily the thread the platform is created on. So we make sure to do that from the backend thread. FIXES=[427945768] --- .../backend/platforms/PlatformEGLAndroid.h | 5 ----- .../opengl/platforms/PlatformEGLAndroid.cpp | 21 ++++++++----------- .../utils/android/PerformanceHintManager.h | 7 ++++++- .../src/android/PerformanceHintManager.cpp | 9 ++++++-- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/filament/backend/include/backend/platforms/PlatformEGLAndroid.h b/filament/backend/include/backend/platforms/PlatformEGLAndroid.h index 9410a6819e..9bf8aaae88 100644 --- a/filament/backend/include/backend/platforms/PlatformEGLAndroid.h +++ b/filament/backend/include/backend/platforms/PlatformEGLAndroid.h @@ -180,10 +180,6 @@ private: int32_t setProducerThrottlingEnabled(EGLNativeWindowType nativeWindow, bool enabled) const; - struct InitializeJvmForPerformanceManagerIfNeeded { - InitializeJvmForPerformanceManagerIfNeeded(); - }; - struct ExternalTextureAndroid : public ExternalTexture { EGLImageKHR eglImage = EGL_NO_IMAGE; }; @@ -191,7 +187,6 @@ private: int mOSVersion; ExternalStreamManagerAndroid& mExternalStreamManager; AndroidDetails& mAndroidDetails; - InitializeJvmForPerformanceManagerIfNeeded const mInitializeJvmForPerformanceManagerIfNeeded; utils::PerformanceHintManager mPerformanceHintManager; utils::PerformanceHintManager::Session mPerformanceHintSession; using clock = std::chrono::high_resolution_clock; diff --git a/filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp b/filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp index 72d832f5d5..0ca672b455 100644 --- a/filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp +++ b/filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp @@ -119,18 +119,6 @@ struct PlatformEGLAndroid::AndroidDetails { // --------------------------------------------------------------------------------------------- -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 : mExternalStreamManager(ExternalStreamManagerAndroid::create()), mAndroidDetails(*(new(std::nothrow) AndroidDetails{})) { @@ -145,6 +133,7 @@ PlatformEGLAndroid::~PlatformEGLAndroid() noexcept { } void PlatformEGLAndroid::terminate() noexcept { + mPerformanceHintManager.terminate(); mAndroidDetails.androidFrameCallback.terminate(); ExternalStreamManagerAndroid::destroy(&mExternalStreamManager); PlatformEGL::terminate(); @@ -223,6 +212,14 @@ void PlatformEGLAndroid::preCommit() noexcept { Driver* PlatformEGLAndroid::createDriver(void* sharedContext, const DriverConfig& driverConfig) { + // PerformanceHintManager() needs the calling thread to be a Java thread; so we need + // to attach this thread to the JVM before we initialize PerformanceHintManager. + if (PerformanceHintManager::isSupported()) { + (void)VirtualMachineEnv::get().getEnvironment(); + } + + mPerformanceHintManager.init(); + // the refresh rate default value doesn't matter, we change it later int32_t const tid = gettid(); mPerformanceHintSession = PerformanceHintManager::Session{ diff --git a/libs/utils/include/utils/android/PerformanceHintManager.h b/libs/utils/include/utils/android/PerformanceHintManager.h index b5910abca1..20758fd569 100644 --- a/libs/utils/include/utils/android/PerformanceHintManager.h +++ b/libs/utils/include/utils/android/PerformanceHintManager.h @@ -55,10 +55,15 @@ public: int reportActualWorkDuration(int64_t actualDurationNanos) noexcept; }; - // caveat: This must be called on a Java thread PerformanceHintManager() noexcept; ~PerformanceHintManager() noexcept; + // caveat: This must be called on a Java thread + void init(); + + // caveat: This must be called on the same thread as init + void terminate(); + // Whether PerformanceHintManager APIs are supported (which doesn't mean PerformanceHintManager // itself is, use isValid()). static bool isSupported() noexcept; diff --git a/libs/utils/src/android/PerformanceHintManager.cpp b/libs/utils/src/android/PerformanceHintManager.cpp index 4b8dd08d83..02e6395634 100644 --- a/libs/utils/src/android/PerformanceHintManager.cpp +++ b/libs/utils/src/android/PerformanceHintManager.cpp @@ -39,13 +39,18 @@ struct PerformanceHintManager::SessionDetails { APerformanceHintSession* mSession = nullptr; }; -PerformanceHintManager::PerformanceHintManager() noexcept { +PerformanceHintManager::PerformanceHintManager() noexcept = default; + +PerformanceHintManager::~PerformanceHintManager() noexcept = default; + +void PerformanceHintManager::init() { if (__builtin_available(android __ANDROID_API_T__, *)) { mImpl->mManager = APerformanceHint_getManager(); } } -PerformanceHintManager::~PerformanceHintManager() noexcept = default; +void PerformanceHintManager::terminate() { +} bool PerformanceHintManager::isSupported() noexcept { if (__builtin_available(android __ANDROID_API_T__, *)) {