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
{
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<void>(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",

View file

@ -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.
*

View file

@ -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.
* <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() {
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());
}
}
}