diff options
4 files changed, 39 insertions, 0 deletions
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index b58c68f782ee..aa86c03c53c7 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -36,6 +36,7 @@ public class SurfaceControl { throws OutOfResourcesException; private static native void nativeRelease(long nativeObject); private static native void nativeDestroy(long nativeObject); + private static native void nativeDisconnect(long nativeObject); private static native Bitmap nativeScreenshot(IBinder displayToken, Rect sourceCrop, int width, int height, int minLayer, int maxLayer, @@ -341,6 +342,15 @@ public class SurfaceControl { mCloseGuard.close(); } + /** + * Disconnect any client still connected to the surface. + */ + public void disconnect() { + if (mNativeObject != 0) { + nativeDisconnect(mNativeObject); + } + } + private void checkNotReleased() { if (mNativeObject == 0) throw new NullPointerException( "mNativeObject is null. Have you called release() already?"); diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 1dfe40a324b3..c838d038c4c2 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -110,6 +110,13 @@ static void nativeDestroy(JNIEnv* env, jclass clazz, jlong nativeObject) { ctrl->decStrong((void *)nativeCreate); } +static void nativeDisconnect(JNIEnv* env, jclass clazz, jlong nativeObject) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + if (ctrl != NULL) { + ctrl->disconnect(); + } +} + static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject displayTokenObj, jobject sourceCropObj, jint width, jint height, jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform, @@ -595,6 +602,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeRelease }, {"nativeDestroy", "(J)V", (void*)nativeDestroy }, + {"nativeDisconnect", "(J)V", + (void*)nativeDisconnect }, {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/Bitmap;", (void*)nativeScreenshotBitmap }, {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V", diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 40b6b50da6dd..e8f1b5d8d326 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1902,6 +1902,12 @@ final class WindowState implements WindowManagerPolicy.WindowState { mWinAnimator.hide("saved surface"); mWinAnimator.mDrawState = WindowStateAnimator.NO_SURFACE; setHasSurface(false); + // The client should have disconnected at this point, but if it doesn't, + // we need to make sure it's disconnected. Otherwise when we reuse the surface + // the client can't reconnect to the buffer queue, and rendering will fail. + if (mWinAnimator.mSurfaceController != null) { + mWinAnimator.mSurfaceController.disconnectInTransaction(); + } } else { mWinAnimator.destroySurfaceLocked(); } diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index 2972a248b00d..2cdf471c1420 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -152,6 +152,20 @@ class WindowSurfaceController { } } + void disconnectInTransaction() { + if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { + Slog.i(TAG, "Disconnecting client: " + this); + } + + try { + if (mSurfaceControl != null) { + mSurfaceControl.disconnect(); + } + } catch (RuntimeException e) { + Slog.w(TAG, "Error disconnecting surface in: " + this, e); + } + } + void setCropInTransaction(Rect clipRect, boolean recoveringMemory) { if (SHOW_TRANSACTIONS) logSurface( "CROP " + clipRect.toShortString(), null); |