From 66d6281a7fea47287b4e601c6822c32d2c8e5960 Mon Sep 17 00:00:00 2001 From: Ryan Pavlik Date: Wed, 28 Oct 2020 10:24:28 -0500 Subject: [PATCH] a/android: Monitor whether MonadoView is still being used by native code. --- .../android/android_custom_surface.cpp | 25 ++++++++-- .../android/android_custom_surface.h | 3 +- .../monado/auxiliary/MonadoView.java | 47 ++++++++++++++++++- 3 files changed, 69 insertions(+), 6 deletions(-) diff --git a/src/xrt/auxiliary/android/android_custom_surface.cpp b/src/xrt/auxiliary/android/android_custom_surface.cpp index 452b546fe..b93846720 100644 --- a/src/xrt/auxiliary/android/android_custom_surface.cpp +++ b/src/xrt/auxiliary/android/android_custom_surface.cpp @@ -27,12 +27,27 @@ using wrap::android::view::SurfaceHolder; struct android_custom_surface { - Activity activity; - jni::Class monadoViewClass; - jni::Object monadoView; - jni::method_t waitGetSurfaceHolderMethod; + ~android_custom_surface(); + Activity activity{}; + jni::Class monadoViewClass{}; + jni::Object monadoView{}; + jni::method_t waitGetSurfaceHolderMethod = nullptr; + jni::method_t markAsDiscardedMethod = nullptr; }; +android_custom_surface::~android_custom_surface() +{ + if (!monadoView.isNull() && markAsDiscardedMethod != nullptr) { + try { + monadoView.call(markAsDiscardedMethod); + } catch (std::exception const &e) { + U_LOG_E( + "Failure while marking MonadoView as discarded: %s", + e.what()); + } + } +} + constexpr auto FULLY_QUALIFIED_CLASSNAME = "org.freedesktop.monado.auxiliary.MonadoView"; @@ -89,6 +104,8 @@ android_custom_surface_async_start(struct _JavaVM *vm, void *activity) ret->monadoViewClass.getMethod( "waitGetSurfaceHolder", "(I)Landroid/view/SurfaceHolder;"); + ret->markAsDiscardedMethod = ret->monadoViewClass.getMethod( + "markAsDiscardedByNative", "()V;"); attachToActivity = ret->monadoViewClass.getStaticMethod( "attachToActivity", diff --git a/src/xrt/auxiliary/android/android_custom_surface.h b/src/xrt/auxiliary/android/android_custom_surface.h index 012badbd4..3ee44217d 100644 --- a/src/xrt/auxiliary/android/android_custom_surface.h +++ b/src/xrt/auxiliary/android/android_custom_surface.h @@ -55,7 +55,8 @@ android_custom_surface_async_start(struct _JavaVM *vm, void *activity); * Destroy the native handle for the custom surface. * * Depending on the state, this may not necessarily destroy the underlying - * surface, if other references exist. + * surface, if other references exist. However, a flag will be set to indicate + * that native code is done using it. * * @param ptr_custom_surface Pointer to the opaque pointer: will be set to NULL. * diff --git a/src/xrt/auxiliary/android/src/main/java/org/freedesktop/monado/auxiliary/MonadoView.java b/src/xrt/auxiliary/android/src/main/java/org/freedesktop/monado/auxiliary/MonadoView.java index f4f68a270..9787e4714 100644 --- a/src/xrt/auxiliary/android/src/main/java/org/freedesktop/monado/auxiliary/MonadoView.java +++ b/src/xrt/auxiliary/android/src/main/java/org/freedesktop/monado/auxiliary/MonadoView.java @@ -43,13 +43,18 @@ public class MonadoView extends SurfaceView implements SurfaceHolder.Callback, S /// Guards currentSurfaceHolder private final Object currentSurfaceHolderSync = new Object(); + /// Guards the usedByNativeCode flag + private final Object usedByNativeCodeSync = new Object(); private final Method viewSetSysUiVis; + public int width = -1; public int height = -1; public int format = -1; /// Guarded by currentSurfaceHolderSync private SurfaceHolder currentSurfaceHolder = null; + /// Guarded by usedByNativeCodeSync + private boolean usedByNativeCode = false; private MonadoView(Activity activity) { super(activity); @@ -124,9 +129,34 @@ public class MonadoView extends SurfaceView implements SurfaceHolder.Callback, S } } } + if (ret != null) { + synchronized (usedByNativeCodeSync) { + usedByNativeCode = true; + usedByNativeCodeSync.notifyAll(); + } + } return ret; } + /** + * Change the flag and notify those waiting on it, to indicate that native code is done with + * this object. + *

+ * Called by native code! + */ + @Keep + public void markAsDiscardedByNative() { + + synchronized (usedByNativeCodeSync) { + if (!usedByNativeCode) { + Log.w(TAG, "This should not have happened: Discarding by native code, but not marked as used!"); + } + usedByNativeCode = false; + usedByNativeCodeSync.notifyAll(); + } + + } + private boolean makeFullscreen() { if (activity == null) { return false; @@ -190,11 +220,26 @@ public class MonadoView extends SurfaceView implements SurfaceHolder.Callback, S @Override public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) { - //! @todo this function should block until the surface is no longer used in the native code. Log.i(TAG, "surfaceDestroyed: Lost our surface."); + boolean lost = false; synchronized (currentSurfaceHolderSync) { if (surfaceHolder == currentSurfaceHolder) { currentSurfaceHolder = null; + lost = true; + } + } + if (lost) { + //! @todo this function should notify native code that the surface is gone. + try { + synchronized (usedByNativeCodeSync) { + while (usedByNativeCode) { + usedByNativeCodeSync.wait(); + } + } + } catch (InterruptedException e) { + e.printStackTrace(); + Log.i(TAG, + "Interrupted in surfaceDestroyed while waiting for native code to finish up: " + e.toString()); } } }