a/android: Monitor whether MonadoView is still being used by native code.

This commit is contained in:
Ryan Pavlik 2020-10-28 10:24:28 -05:00
parent 6f989f5451
commit 66d6281a7f
3 changed files with 69 additions and 6 deletions

View file

@ -27,12 +27,27 @@ using wrap::android::view::SurfaceHolder;
struct android_custom_surface struct android_custom_surface
{ {
Activity activity; ~android_custom_surface();
jni::Class monadoViewClass; Activity activity{};
jni::Object monadoView; jni::Class monadoViewClass{};
jni::method_t waitGetSurfaceHolderMethod; 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<void>(markAsDiscardedMethod);
} catch (std::exception const &e) {
U_LOG_E(
"Failure while marking MonadoView as discarded: %s",
e.what());
}
}
}
constexpr auto FULLY_QUALIFIED_CLASSNAME = constexpr auto FULLY_QUALIFIED_CLASSNAME =
"org.freedesktop.monado.auxiliary.MonadoView"; "org.freedesktop.monado.auxiliary.MonadoView";
@ -89,6 +104,8 @@ android_custom_surface_async_start(struct _JavaVM *vm, void *activity)
ret->monadoViewClass.getMethod( ret->monadoViewClass.getMethod(
"waitGetSurfaceHolder", "waitGetSurfaceHolder",
"(I)Landroid/view/SurfaceHolder;"); "(I)Landroid/view/SurfaceHolder;");
ret->markAsDiscardedMethod = ret->monadoViewClass.getMethod(
"markAsDiscardedByNative", "()V;");
attachToActivity = ret->monadoViewClass.getStaticMethod( attachToActivity = ret->monadoViewClass.getStaticMethod(
"attachToActivity", "attachToActivity",

View file

@ -55,7 +55,8 @@ android_custom_surface_async_start(struct _JavaVM *vm, void *activity);
* Destroy the native handle for the custom surface. * Destroy the native handle for the custom surface.
* *
* Depending on the state, this may not necessarily destroy the underlying * 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. * @param ptr_custom_surface Pointer to the opaque pointer: will be set to NULL.
* *

View file

@ -43,13 +43,18 @@ public class MonadoView extends SurfaceView implements SurfaceHolder.Callback, S
/// Guards currentSurfaceHolder /// Guards currentSurfaceHolder
private final Object currentSurfaceHolderSync = new Object(); private final Object currentSurfaceHolderSync = new Object();
/// Guards the usedByNativeCode flag
private final Object usedByNativeCodeSync = new Object();
private final Method viewSetSysUiVis; private final Method viewSetSysUiVis;
public int width = -1; public int width = -1;
public int height = -1; public int height = -1;
public int format = -1; public int format = -1;
/// Guarded by currentSurfaceHolderSync /// Guarded by currentSurfaceHolderSync
private SurfaceHolder currentSurfaceHolder = null; private SurfaceHolder currentSurfaceHolder = null;
/// Guarded by usedByNativeCodeSync
private boolean usedByNativeCode = false;
private MonadoView(Activity activity) { private MonadoView(Activity activity) {
super(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; return ret;
} }
/**
* Change the flag and notify those waiting on it, to indicate that native code is done with
* this object.
* <p>
* 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() { private boolean makeFullscreen() {
if (activity == null) { if (activity == null) {
return false; return false;
@ -190,11 +220,26 @@ public class MonadoView extends SurfaceView implements SurfaceHolder.Callback, S
@Override @Override
public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) { 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."); Log.i(TAG, "surfaceDestroyed: Lost our surface.");
boolean lost = false;
synchronized (currentSurfaceHolderSync) { synchronized (currentSurfaceHolderSync) {
if (surfaceHolder == currentSurfaceHolder) { if (surfaceHolder == currentSurfaceHolder) {
currentSurfaceHolder = null; 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());
} }
} }
} }