SurfaceView: Force surface disconnection before reuse.
am: 387838be95
Change-Id: Ied6c33fac75612ed2cdeb45b24c521bbff979afa
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 9f46f3f..22e68a3 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -71,6 +71,7 @@
private static native long nativeGetNextFrameNumber(long nativeObject);
private static native int nativeSetScalingMode(long nativeObject, int scalingMode);
private static native void nativeSetBuffersTransform(long nativeObject, long transform);
+ private static native int nativeForceScopedDisconnect(long nativeObject);
public static final Parcelable.Creator<Surface> CREATOR =
new Parcelable.Creator<Surface>() {
@@ -550,6 +551,16 @@
}
}
+ void forceScopedDisconnect() {
+ synchronized (mLock) {
+ checkNotReleasedLocked();
+ int err = nativeForceScopedDisconnect(mNativeObject);
+ if (err != 0) {
+ throw new RuntimeException("Failed to disconnect Surface instance (bad object?)");
+ }
+ }
+ }
+
/**
* Returns whether or not this Surface is backed by a single-buffered SurfaceTexture
* @hide
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 8a16d63..754cdd8 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -587,6 +587,18 @@
for (SurfaceHolder.Callback c : callbacks) {
c.surfaceDestroyed(mSurfaceHolder);
}
+ // Since Android N the same surface may be reused and given to us
+ // again by the system server at a later point. However
+ // as we didn't do this in previous releases, clients weren't
+ // necessarily required to clean up properly in
+ // surfaceDestroyed. This leads to problems for example when
+ // clients don't destroy their EGL context, and try
+ // and create a new one on the same surface following reuse.
+ // Since there is no valid use of the surface in-between
+ // surfaceDestroyed and surfaceCreated, we force a disconnect,
+ // so the next connect will always work if we end up reusing
+ // the surface.
+ mSurface.forceScopedDisconnect();
}
}
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 21e4d2f..a0c62c3 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -487,6 +487,11 @@
return surface->setScalingMode(scalingMode);
}
+static jint nativeForceScopedDisconnect(JNIEnv *env, jclass clazz, jlong nativeObject) {
+ Surface* surface = reinterpret_cast<Surface*>(nativeObject);
+ return surface->disconnect(-1, IGraphicBufferProducer::DisconnectMode::AllLocal);
+}
+
namespace uirenderer {
using namespace android::uirenderer::renderthread;
@@ -564,6 +569,7 @@
{"nativeGetHeight", "(J)I", (void*)nativeGetHeight },
{"nativeGetNextFrameNumber", "(J)J", (void*)nativeGetNextFrameNumber },
{"nativeSetScalingMode", "(JI)I", (void*)nativeSetScalingMode },
+ {"nativeForceScopedDisconnect", "(J)I", (void*)nativeForceScopedDisconnect},
// HWUI context
{"nHwuiCreate", "(JJ)J", (void*) hwui::create },