Loading core/java/android/view/SurfaceView.java +2 −0 Original line number Diff line number Diff line Loading @@ -1208,8 +1208,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } mTransformHint = viewRoot.getBufferTransformHint(); mBlastSurfaceControl.setTransformHint(mTransformHint); mBlastBufferQueue = new BLASTBufferQueue(name, false /* updateDestinationFrame */); mBlastBufferQueue.update(mBlastSurfaceControl, mSurfaceWidth, mSurfaceHeight, mFormat); mBlastBufferQueue.setTransactionHangCallback(ViewRootImpl.sTransactionHangCallback); } private void onDrawFinished() { Loading core/java/android/view/ViewRootImpl.java +23 −0 Original line number Diff line number Diff line Loading @@ -858,6 +858,28 @@ public final class ViewRootImpl implements ViewParent, */ private Bundle mRelayoutBundle = new Bundle(); private static volatile boolean sAnrReported = false; static BLASTBufferQueue.TransactionHangCallback sTransactionHangCallback = new BLASTBufferQueue.TransactionHangCallback() { @Override public void onTransactionHang(boolean isGPUHang) { if (isGPUHang && !sAnrReported) { sAnrReported = true; try { ActivityManager.getService().appNotResponding( "Buffer processing hung up due to stuck fence. Indicates GPU hang"); } catch (RemoteException e) { // We asked the system to crash us, but the system // already crashed. Unfortunately things may be // out of control. } } else { // TODO: Do something with this later. For now we just ANR // in dequeue buffer later like we always have. } } }; private String mTag = TAG; public ViewRootImpl(Context context, Display display) { Loading Loading @@ -2100,6 +2122,7 @@ public final class ViewRootImpl implements ViewParent, } mBlastBufferQueue = new BLASTBufferQueue(mTag, mSurfaceControl, mSurfaceSize.x, mSurfaceSize.y, mWindowAttributes.format); mBlastBufferQueue.setTransactionHangCallback(sTransactionHangCallback); Surface blastSurface = mBlastBufferQueue.createSurface(); // Only call transferFrom if the surface has changed to prevent inc the generation ID and // causing EGL resources to be recreated. Loading core/jni/android_graphics_BLASTBufferQueue.cpp +60 −1 Original line number Diff line number Diff line Loading @@ -47,6 +47,43 @@ static JNIEnv* getenv(JavaVM* vm) { return env; } struct { jmethodID onTransactionHang; } gTransactionHangCallback; class TransactionHangCallbackWrapper : public LightRefBase<TransactionHangCallbackWrapper> { public: explicit TransactionHangCallbackWrapper(JNIEnv* env, jobject jobject) { env->GetJavaVM(&mVm); mTransactionHangObject = env->NewGlobalRef(jobject); LOG_ALWAYS_FATAL_IF(!mTransactionHangObject, "Failed to make global ref"); } ~TransactionHangCallbackWrapper() { if (mTransactionHangObject) { getenv()->DeleteGlobalRef(mTransactionHangObject); mTransactionHangObject = nullptr; } } void onTransactionHang(bool isGpuHang) { if (mTransactionHangObject) { getenv()->CallVoidMethod(mTransactionHangObject, gTransactionHangCallback.onTransactionHang, isGpuHang); } } private: JavaVM* mVm; jobject mTransactionHangObject; JNIEnv* getenv() { JNIEnv* env; mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6); return env; } }; static jlong nativeCreate(JNIEnv* env, jclass clazz, jstring jName, jboolean updateDestinationFrame) { ScopedUtfChars name(env, jName); Loading Loading @@ -142,6 +179,20 @@ static bool nativeIsSameSurfaceControl(JNIEnv* env, jclass clazz, jlong ptr, jlo return queue->isSameSurfaceControl(reinterpret_cast<SurfaceControl*>(surfaceControl)); } static void nativeSetTransactionHangCallback(JNIEnv* env, jclass clazz, jlong ptr, jobject transactionHangCallback) { sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); if (transactionHangCallback == nullptr) { queue->setTransactionHangCallback(nullptr); } else { sp<TransactionHangCallbackWrapper> wrapper = new TransactionHangCallbackWrapper{env, transactionHangCallback}; queue->setTransactionHangCallback([wrapper](bool isGpuHang) { wrapper->onTransactionHang(isGpuHang); }); } } static jobject nativeGatherPendingTransactions(JNIEnv* env, jclass clazz, jlong ptr, jlong frameNum) { sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); Loading @@ -163,7 +214,10 @@ static const JNINativeMethod gMethods[] = { {"nativeGetLastAcquiredFrameNum", "(J)J", (void*)nativeGetLastAcquiredFrameNum}, {"nativeApplyPendingTransactions", "(JJ)V", (void*)nativeApplyPendingTransactions}, {"nativeIsSameSurfaceControl", "(JJ)Z", (void*)nativeIsSameSurfaceControl}, {"nativeGatherPendingTransactions", "(JJ)Landroid/view/SurfaceControl$Transaction;", (void*)nativeGatherPendingTransactions} {"nativeGatherPendingTransactions", "(JJ)Landroid/view/SurfaceControl$Transaction;", (void*)nativeGatherPendingTransactions}, {"nativeSetTransactionHangCallback", "(JLandroid/graphics/BLASTBufferQueue$TransactionHangCallback;)V", (void*)nativeSetTransactionHangCallback}, // clang-format on }; Loading @@ -180,6 +234,11 @@ int register_android_graphics_BLASTBufferQueue(JNIEnv* env) { jclass consumer = FindClassOrDie(env, "java/util/function/Consumer"); gTransactionConsumer.accept = GetMethodIDOrDie(env, consumer, "accept", "(Ljava/lang/Object;)V"); jclass transactionHangClass = FindClassOrDie(env, "android/graphics/BLASTBufferQueue$TransactionHangCallback"); gTransactionHangCallback.onTransactionHang = GetMethodIDOrDie(env, transactionHangClass, "onTransactionHang", "(Z)V"); return 0; } Loading graphics/java/android/graphics/BLASTBufferQueue.java +10 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,12 @@ public final class BLASTBufferQueue { private static native boolean nativeIsSameSurfaceControl(long ptr, long surfaceControlPtr); private static native SurfaceControl.Transaction nativeGatherPendingTransactions(long ptr, long frameNumber); private static native void nativeSetTransactionHangCallback(long ptr, TransactionHangCallback callback); public interface TransactionHangCallback { void onTransactionHang(boolean isGpuHang); } /** Create a new connection with the surface flinger. */ public BLASTBufferQueue(String name, SurfaceControl sc, int width, int height, Loading Loading @@ -184,4 +190,8 @@ public final class BLASTBufferQueue { public SurfaceControl.Transaction gatherPendingTransactions(long frameNumber) { return nativeGatherPendingTransactions(mNativeObject, frameNumber); } public void setTransactionHangCallback(TransactionHangCallback hangCallback) { nativeSetTransactionHangCallback(mNativeObject, hangCallback); } } Loading
core/java/android/view/SurfaceView.java +2 −0 Original line number Diff line number Diff line Loading @@ -1208,8 +1208,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } mTransformHint = viewRoot.getBufferTransformHint(); mBlastSurfaceControl.setTransformHint(mTransformHint); mBlastBufferQueue = new BLASTBufferQueue(name, false /* updateDestinationFrame */); mBlastBufferQueue.update(mBlastSurfaceControl, mSurfaceWidth, mSurfaceHeight, mFormat); mBlastBufferQueue.setTransactionHangCallback(ViewRootImpl.sTransactionHangCallback); } private void onDrawFinished() { Loading
core/java/android/view/ViewRootImpl.java +23 −0 Original line number Diff line number Diff line Loading @@ -858,6 +858,28 @@ public final class ViewRootImpl implements ViewParent, */ private Bundle mRelayoutBundle = new Bundle(); private static volatile boolean sAnrReported = false; static BLASTBufferQueue.TransactionHangCallback sTransactionHangCallback = new BLASTBufferQueue.TransactionHangCallback() { @Override public void onTransactionHang(boolean isGPUHang) { if (isGPUHang && !sAnrReported) { sAnrReported = true; try { ActivityManager.getService().appNotResponding( "Buffer processing hung up due to stuck fence. Indicates GPU hang"); } catch (RemoteException e) { // We asked the system to crash us, but the system // already crashed. Unfortunately things may be // out of control. } } else { // TODO: Do something with this later. For now we just ANR // in dequeue buffer later like we always have. } } }; private String mTag = TAG; public ViewRootImpl(Context context, Display display) { Loading Loading @@ -2100,6 +2122,7 @@ public final class ViewRootImpl implements ViewParent, } mBlastBufferQueue = new BLASTBufferQueue(mTag, mSurfaceControl, mSurfaceSize.x, mSurfaceSize.y, mWindowAttributes.format); mBlastBufferQueue.setTransactionHangCallback(sTransactionHangCallback); Surface blastSurface = mBlastBufferQueue.createSurface(); // Only call transferFrom if the surface has changed to prevent inc the generation ID and // causing EGL resources to be recreated. Loading
core/jni/android_graphics_BLASTBufferQueue.cpp +60 −1 Original line number Diff line number Diff line Loading @@ -47,6 +47,43 @@ static JNIEnv* getenv(JavaVM* vm) { return env; } struct { jmethodID onTransactionHang; } gTransactionHangCallback; class TransactionHangCallbackWrapper : public LightRefBase<TransactionHangCallbackWrapper> { public: explicit TransactionHangCallbackWrapper(JNIEnv* env, jobject jobject) { env->GetJavaVM(&mVm); mTransactionHangObject = env->NewGlobalRef(jobject); LOG_ALWAYS_FATAL_IF(!mTransactionHangObject, "Failed to make global ref"); } ~TransactionHangCallbackWrapper() { if (mTransactionHangObject) { getenv()->DeleteGlobalRef(mTransactionHangObject); mTransactionHangObject = nullptr; } } void onTransactionHang(bool isGpuHang) { if (mTransactionHangObject) { getenv()->CallVoidMethod(mTransactionHangObject, gTransactionHangCallback.onTransactionHang, isGpuHang); } } private: JavaVM* mVm; jobject mTransactionHangObject; JNIEnv* getenv() { JNIEnv* env; mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6); return env; } }; static jlong nativeCreate(JNIEnv* env, jclass clazz, jstring jName, jboolean updateDestinationFrame) { ScopedUtfChars name(env, jName); Loading Loading @@ -142,6 +179,20 @@ static bool nativeIsSameSurfaceControl(JNIEnv* env, jclass clazz, jlong ptr, jlo return queue->isSameSurfaceControl(reinterpret_cast<SurfaceControl*>(surfaceControl)); } static void nativeSetTransactionHangCallback(JNIEnv* env, jclass clazz, jlong ptr, jobject transactionHangCallback) { sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); if (transactionHangCallback == nullptr) { queue->setTransactionHangCallback(nullptr); } else { sp<TransactionHangCallbackWrapper> wrapper = new TransactionHangCallbackWrapper{env, transactionHangCallback}; queue->setTransactionHangCallback([wrapper](bool isGpuHang) { wrapper->onTransactionHang(isGpuHang); }); } } static jobject nativeGatherPendingTransactions(JNIEnv* env, jclass clazz, jlong ptr, jlong frameNum) { sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); Loading @@ -163,7 +214,10 @@ static const JNINativeMethod gMethods[] = { {"nativeGetLastAcquiredFrameNum", "(J)J", (void*)nativeGetLastAcquiredFrameNum}, {"nativeApplyPendingTransactions", "(JJ)V", (void*)nativeApplyPendingTransactions}, {"nativeIsSameSurfaceControl", "(JJ)Z", (void*)nativeIsSameSurfaceControl}, {"nativeGatherPendingTransactions", "(JJ)Landroid/view/SurfaceControl$Transaction;", (void*)nativeGatherPendingTransactions} {"nativeGatherPendingTransactions", "(JJ)Landroid/view/SurfaceControl$Transaction;", (void*)nativeGatherPendingTransactions}, {"nativeSetTransactionHangCallback", "(JLandroid/graphics/BLASTBufferQueue$TransactionHangCallback;)V", (void*)nativeSetTransactionHangCallback}, // clang-format on }; Loading @@ -180,6 +234,11 @@ int register_android_graphics_BLASTBufferQueue(JNIEnv* env) { jclass consumer = FindClassOrDie(env, "java/util/function/Consumer"); gTransactionConsumer.accept = GetMethodIDOrDie(env, consumer, "accept", "(Ljava/lang/Object;)V"); jclass transactionHangClass = FindClassOrDie(env, "android/graphics/BLASTBufferQueue$TransactionHangCallback"); gTransactionHangCallback.onTransactionHang = GetMethodIDOrDie(env, transactionHangClass, "onTransactionHang", "(Z)V"); return 0; } Loading
graphics/java/android/graphics/BLASTBufferQueue.java +10 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,12 @@ public final class BLASTBufferQueue { private static native boolean nativeIsSameSurfaceControl(long ptr, long surfaceControlPtr); private static native SurfaceControl.Transaction nativeGatherPendingTransactions(long ptr, long frameNumber); private static native void nativeSetTransactionHangCallback(long ptr, TransactionHangCallback callback); public interface TransactionHangCallback { void onTransactionHang(boolean isGpuHang); } /** Create a new connection with the surface flinger. */ public BLASTBufferQueue(String name, SurfaceControl sc, int width, int height, Loading Loading @@ -184,4 +190,8 @@ public final class BLASTBufferQueue { public SurfaceControl.Transaction gatherPendingTransactions(long frameNumber) { return nativeGatherPendingTransactions(mNativeObject, frameNumber); } public void setTransactionHangCallback(TransactionHangCallback hangCallback) { nativeSetTransactionHangCallback(mNativeObject, hangCallback); } }