From 16831e290ed29f5f70dfe144ec63c583527485e8 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Fri, 26 Jan 2024 11:24:51 +0800 Subject: Avert race condition between window attachment and buffer swap * java/org/gnu/emacs/EmacsView.java (swapBuffers): Synchronize such that code cannot execute between the bitmap's being loaded and being transferred to surfaceView. (onDetachedFromWindow): Recycle bitmap after the surface view is reset. * java/org/gnu/emacs/EmacsWindow.java (recreateActivity): * src/android.c (android_init_emacs_window) (android_recreate_activity): * src/androidfns.c (Fandroid_recreate_activity) (syms_of_androidfns): New functions for debugging window attachment. * src/androidgui.h: Update prototypes. --- java/org/gnu/emacs/EmacsView.java | 27 +++++++++++++++------------ java/org/gnu/emacs/EmacsWindow.java | 28 ++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 12 deletions(-) (limited to 'java') diff --git a/java/org/gnu/emacs/EmacsView.java b/java/org/gnu/emacs/EmacsView.java index 136d8abc713..8398e4b784c 100644 --- a/java/org/gnu/emacs/EmacsView.java +++ b/java/org/gnu/emacs/EmacsView.java @@ -456,7 +456,6 @@ public final class EmacsView extends ViewGroup { Canvas canvas; Rect damageRect; - Bitmap bitmap; /* Make sure this function is called only from the Emacs thread. */ @@ -474,11 +473,12 @@ public final class EmacsView extends ViewGroup damageRect = damageRegion.getBounds (); damageRegion.setEmpty (); - bitmap = getBitmap (); - - /* Transfer the bitmap to the surface view, then invalidate - it. */ - surfaceView.setBitmap (bitmap, damageRect); + synchronized (this) + { + /* Transfer the bitmap to the surface view, then invalidate + it. */ + surfaceView.setBitmap (bitmap, damageRect); + } } @Override @@ -724,17 +724,20 @@ public final class EmacsView extends ViewGroup public synchronized void onDetachedFromWindow () { - isAttachedToWindow = false; - - /* Recycle the bitmap and call GC. */ - - if (bitmap != null) - bitmap.recycle (); + Bitmap savedBitmap; + savedBitmap = bitmap; + isAttachedToWindow = false; bitmap = null; canvas = null; + surfaceView.setBitmap (null, null); + /* Recycle the bitmap and call GC. */ + + if (savedBitmap != null) + savedBitmap.recycle (); + /* Collect the bitmap storage; it could be large. */ Runtime.getRuntime ().gc (); diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index 207bd22c538..304304a328b 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java @@ -1784,4 +1784,32 @@ public final class EmacsWindow extends EmacsHandleObject return true; } + + + + /* Miscellaneous functions for debugging graphics code. */ + + /* Recreate the activity to which this window is attached, if any. + This is nonfunctional on Android 2.3.7 and earlier. */ + + public void + recreateActivity () + { + final EmacsWindowAttachmentManager.WindowConsumer attached; + + attached = this.attached; + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) + return; + + view.post (new Runnable () { + @Override + public void + run () + { + if (attached instanceof EmacsActivity) + ((EmacsActivity) attached).recreate (); + } + }); + } }; -- cgit v1.2.3