]> git.eshelyaron.com Git - emacs.git/commitdiff
Avert race condition between window attachment and buffer swap
authorPo Lu <luangruo@yahoo.com>
Fri, 26 Jan 2024 03:24:51 +0000 (11:24 +0800)
committerEshel Yaron <me@eshelyaron.com>
Fri, 26 Jan 2024 11:23:31 +0000 (12:23 +0100)
* 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.

(cherry picked from commit 16831e290ed29f5f70dfe144ec63c583527485e8)

java/org/gnu/emacs/EmacsView.java
java/org/gnu/emacs/EmacsWindow.java
src/android.c
src/androidfns.c
src/androidgui.h

index 136d8abc7136f7613dff91ccbe44a797d5f7dc42..8398e4b784c6cb6c5542e042785b9a3735bf4a01 100644 (file)
@@ -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 ();
 
index 207bd22c538563c8aa8fba9aa1102efdd01477c9..304304a328b7f0f6ef75391bf00c9315f96307e5 100644 (file)
@@ -1784,4 +1784,32 @@ public final class EmacsWindow extends EmacsHandleObject
 
     return true;
   }
+
+\f
+
+  /* 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 ();
+       }
+      });
+  }
 };
index 509f30a759ba75ffd7e9fe30662f7304467df962..51eb85a97e8164ccdee806360ab0d51f50d3990e 100644 (file)
@@ -111,6 +111,7 @@ struct android_emacs_window
   jmethodID set_dont_focus_on_map;
   jmethodID define_cursor;
   jmethodID damage_rect;
+  jmethodID recreate_activity;
 };
 
 struct android_emacs_cursor
@@ -1802,12 +1803,12 @@ android_init_emacs_window (void)
   FIND_METHOD (set_dont_accept_focus, "setDontAcceptFocus", "(Z)V");
   FIND_METHOD (define_cursor, "defineCursor",
               "(Lorg/gnu/emacs/EmacsCursor;)V");
-
   /* In spite of the declaration of this function being located within
      EmacsDrawable, the ID of the `damage_rect' method is retrieved
      from EmacsWindow, which avoids virtual function dispatch within
      android_damage_window.  */
   FIND_METHOD (damage_rect, "damageRect", "(IIII)V");
+  FIND_METHOD (recreate_activity, "recreateActivity", "()V");
 #undef FIND_METHOD
 }
 
@@ -6638,6 +6639,24 @@ android_request_storage_access (void)
   android_exception_check ();
 }
 
+/* Recreate the activity to which WINDOW is attached to debug graphics
+   code executed in response to window attachment.  */
+
+void
+android_recreate_activity (android_window window)
+{
+  jobject object;
+  jmethodID method;
+
+  object = android_resolve_handle (window, ANDROID_HANDLE_WINDOW);
+  method = window_class.recreate_activity;
+
+  (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, object,
+                                                window_class.class,
+                                                method);
+  android_exception_check ();
+}
+
 \f
 
 /* The thread from which a query against a thread is currently being
index 34f1f53368446a74f2b64fe09a97496029b047f6..eaecb78338bca611b20c5605bfd51accf6572ed3 100644 (file)
@@ -3164,6 +3164,24 @@ android_set_preeditarea (struct window *w, int x, int y)
                                     y + w->phys_cursor_height);
 }
 
+\f
+
+/* Debugging.  */
+
+DEFUN ("android-recreate-activity", Fandroid_recreate_activity,
+       Sandroid_recreate_activity, 0, 0, "",
+       doc: /* Recreate the activity attached to the current frame.
+This function exists for debugging purposes and is of no interest to
+users.  */)
+  (void)
+{
+  struct frame *f;
+
+  f = decode_window_system_frame (Qnil);
+  android_recreate_activity (FRAME_ANDROID_WINDOW (f));
+  return Qnil;
+}
+
 #endif /* !ANDROID_STUBIFY */
 
 \f
@@ -3550,6 +3568,7 @@ language to be US English if LANGUAGE is empty.  */);
   defsubr (&Sandroid_request_directory_access);
   defsubr (&Sandroid_external_storage_available_p);
   defsubr (&Sandroid_request_storage_access);
+  defsubr (&Sandroid_recreate_activity);
 
   tip_timer = Qnil;
   staticpro (&tip_timer);
index 69efd393d5576c400a752261707d01ad068b3fe3..893175811914c981f647b1a39a8b5bb123888546 100644 (file)
@@ -708,6 +708,7 @@ extern void android_translate_coordinates (android_window, int,
 extern int android_wc_lookup_string (android_key_pressed_event *,
                                     wchar_t *, int, int *,
                                     enum android_lookup_status *);
+extern void android_recreate_activity (android_window);
 extern void android_update_ic (android_window, ptrdiff_t, ptrdiff_t,
                               ptrdiff_t, ptrdiff_t);
 extern void android_reset_ic (android_window, enum android_ic_mode);