Merge "ViewRootImpl/SurfaceView: Listen for queue stalls" into tm-dev

This commit is contained in:
Rob Carr
2022-05-05 15:11:39 +00:00
committed by Android (Google) Code Review
4 changed files with 95 additions and 1 deletions

View File

@@ -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() {

View File

@@ -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) {
@@ -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.

View File

@@ -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);
@@ -141,6 +178,20 @@ static bool nativeIsSameSurfaceControl(JNIEnv* env, jclass clazz, jlong ptr, jlo
sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
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) {
@@ -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
};
@@ -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;
}

View File

@@ -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,
@@ -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);
}
}