Merge "ViewRootImpl/SurfaceView: Listen for queue stalls" into tm-dev
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user