From 31bde04846540f243bb1537c0dd39234e234e51d Mon Sep 17 00:00:00 2001 From: John Reck Date: Wed, 11 Aug 2021 13:21:41 -0400 Subject: [PATCH] Move HardwareObserver off of NewWeakGlobalRef Test: atest android.view.cts.FrameMetricsListenerTest Bug: 194893628 Change-Id: I352ba74ba03ac998ddcf53a2d5d65f2577e23dd5 --- .../graphics/HardwareRendererObserver.java | 26 +++++++++++++--- ...roid_graphics_HardwareRendererObserver.cpp | 31 ++++++++++--------- ...ndroid_graphics_HardwareRendererObserver.h | 3 +- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/graphics/java/android/graphics/HardwareRendererObserver.java b/graphics/java/android/graphics/HardwareRendererObserver.java index e2a05723166f6..d5a6a2fe158ad 100644 --- a/graphics/java/android/graphics/HardwareRendererObserver.java +++ b/graphics/java/android/graphics/HardwareRendererObserver.java @@ -21,12 +21,14 @@ import android.os.Handler; import com.android.internal.util.VirtualRefBasePtr; +import java.lang.ref.WeakReference; + /** * Provides streaming access to frame stats information from HardwareRenderer to apps. * * @hide */ -public class HardwareRendererObserver { +public final class HardwareRendererObserver { private final long[] mFrameMetrics; private final Handler mHandler; private final OnFrameMetricsAvailableListener mListener; @@ -74,15 +76,14 @@ public class HardwareRendererObserver { mFrameMetrics = frameMetrics; mHandler = handler; mListener = listener; - mNativePtr = new VirtualRefBasePtr(nCreateObserver(waitForPresentTime)); + mNativePtr = new VirtualRefBasePtr(nCreateObserver( + new WeakReference<>(this), waitForPresentTime)); } /*package*/ long getNativeInstance() { return mNativePtr.get(); } - // Called by native on the provided Handler - @SuppressWarnings("unused") private void notifyDataAvailable() { mHandler.post(() -> { boolean hasMoreData = true; @@ -98,6 +99,21 @@ public class HardwareRendererObserver { }); } - private native long nCreateObserver(boolean waitForPresentTime); + /** + * called by native + * @hide + * @return true to keep listening, false if this is a dead observer + */ + static boolean invokeDataAvailable(WeakReference weakObserver) { + HardwareRendererObserver observer = weakObserver.get(); + if (observer != null) { + observer.notifyDataAvailable(); + return true; + } + return false; + } + + private static native long nCreateObserver(WeakReference observer, + boolean waitForPresentTime); private static native int nGetNextBuffer(long nativePtr, long[] data); } diff --git a/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp b/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp index e5d5e75d0f3bc..6cae5ffa397f9 100644 --- a/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp +++ b/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp @@ -24,6 +24,7 @@ namespace android { struct { + jclass clazz; jmethodID callback; } gHardwareRendererObserverClassInfo; @@ -38,14 +39,13 @@ static JNIEnv* getenv(JavaVM* vm) { HardwareRendererObserver::HardwareRendererObserver(JavaVM* vm, jobject observer, bool waitForPresentTime) : uirenderer::FrameMetricsObserver(waitForPresentTime), mVm(vm) { - mObserverWeak = getenv(mVm)->NewWeakGlobalRef(observer); - LOG_ALWAYS_FATAL_IF(mObserverWeak == nullptr, - "unable to create frame stats observer reference"); + mObserver = getenv(mVm)->NewGlobalRef(observer); + LOG_ALWAYS_FATAL_IF(mObserver == nullptr, "unable to create frame stats observer reference"); } HardwareRendererObserver::~HardwareRendererObserver() { JNIEnv* env = getenv(mVm); - env->DeleteWeakGlobalRef(mObserverWeak); + env->DeleteGlobalRef(mObserver); } bool HardwareRendererObserver::getNextBuffer(JNIEnv* env, jlongArray metrics, int* dropCount) { @@ -66,6 +66,8 @@ bool HardwareRendererObserver::getNextBuffer(JNIEnv* env, jlongArray metrics, in } void HardwareRendererObserver::notify(const int64_t* stats) { + if (!mKeepListening) return; + FrameMetricsNotification& elem = mRingBuffer[mNextFree]; if (!elem.hasData.load()) { @@ -77,18 +79,17 @@ void HardwareRendererObserver::notify(const int64_t* stats) { elem.hasData = true; JNIEnv* env = getenv(mVm); - jobject target = env->NewLocalRef(mObserverWeak); - if (target != nullptr) { - env->CallVoidMethod(target, gHardwareRendererObserverClassInfo.callback); - env->DeleteLocalRef(target); - } + mKeepListening = env->CallStaticBooleanMethod(gHardwareRendererObserverClassInfo.clazz, + gHardwareRendererObserverClassInfo.callback, + mObserver); } else { mDroppedReports++; } } static jlong android_graphics_HardwareRendererObserver_createObserver(JNIEnv* env, - jobject observerObj, + jobject /*clazz*/, + jobject weakRefThis, jboolean waitForPresentTime) { JavaVM* vm = nullptr; if (env->GetJavaVM(&vm) != JNI_OK) { @@ -97,7 +98,7 @@ static jlong android_graphics_HardwareRendererObserver_createObserver(JNIEnv* en } HardwareRendererObserver* observer = - new HardwareRendererObserver(vm, observerObj, waitForPresentTime); + new HardwareRendererObserver(vm, weakRefThis, waitForPresentTime); return reinterpret_cast(observer); } @@ -114,7 +115,7 @@ static jint android_graphics_HardwareRendererObserver_getNextBuffer(JNIEnv* env, } static const std::array gMethods = { - MAKE_JNI_NATIVE_METHOD("nCreateObserver", "(Z)J", + MAKE_JNI_NATIVE_METHOD("nCreateObserver", "(Ljava/lang/ref/WeakReference;Z)J", android_graphics_HardwareRendererObserver_createObserver), MAKE_JNI_NATIVE_METHOD("nGetNextBuffer", "(J[J)I", android_graphics_HardwareRendererObserver_getNextBuffer), @@ -123,8 +124,10 @@ static const std::array gMethods = { int register_android_graphics_HardwareRendererObserver(JNIEnv* env) { jclass observerClass = FindClassOrDie(env, "android/graphics/HardwareRendererObserver"); - gHardwareRendererObserverClassInfo.callback = GetMethodIDOrDie(env, observerClass, - "notifyDataAvailable", "()V"); + gHardwareRendererObserverClassInfo.clazz = + reinterpret_cast(env->NewGlobalRef(observerClass)); + gHardwareRendererObserverClassInfo.callback = GetStaticMethodIDOrDie( + env, observerClass, "invokeDataAvailable", "(Ljava/lang/ref/WeakReference;)Z"); return RegisterMethodsOrDie(env, "android/graphics/HardwareRendererObserver", gMethods.data(), gMethods.size()); diff --git a/libs/hwui/jni/android_graphics_HardwareRendererObserver.h b/libs/hwui/jni/android_graphics_HardwareRendererObserver.h index d3076140541b8..5ee3e16695024 100644 --- a/libs/hwui/jni/android_graphics_HardwareRendererObserver.h +++ b/libs/hwui/jni/android_graphics_HardwareRendererObserver.h @@ -63,7 +63,8 @@ private: }; JavaVM* const mVm; - jweak mObserverWeak; + jobject mObserver; + bool mKeepListening = true; int mNextFree = 0; int mNextInQueue = 0;