diff --git a/src/xrt/auxiliary/android/android_custom_surface.cpp b/src/xrt/auxiliary/android/android_custom_surface.cpp index 42e9c8baf..fadfd53d8 100644 --- a/src/xrt/auxiliary/android/android_custom_surface.cpp +++ b/src/xrt/auxiliary/android/android_custom_surface.cpp @@ -17,6 +17,8 @@ #include "jni.h" #include +#include +#include using wrap::android::app::Activity; using wrap::android::view::SurfaceHolder; @@ -85,9 +87,7 @@ android_custom_surface_async_start(struct _JavaVM *vm, void *activity) "attachToActivity", "(Landroid/app/Activity;)Lorg/freedesktop/monado/auxiliary/" "MonadoView;"); - jni::method_t attachToActivity = - ret->monadoViewClass.getStaticMethod( - "attachToActivity", "Landroid.app.Activity"); + ret->monadoView = ret->monadoViewClass.call( attachToActivity, ret->activity.object()); return ret.release(); @@ -121,11 +121,18 @@ ANativeWindow * android_custom_surface_get_surface( struct android_custom_surface *custom_surface) { - auto holder = - custom_surface->monadoView.get("currentSurfaceHolder"); - if (holder.isNull()) { + jni::field_t curSurfaceId = nullptr; + jni::Object holder = nullptr; + try { + curSurfaceId = custom_surface->monadoViewClass.getField( + "currentSurfaceHolder", "Landroid/view/SurfaceHolder;"); + holder = + custom_surface->monadoView.get(curSurfaceId); + } catch (std::exception const &e) { + U_LOG_E("Could not get currentSurfaceHolder: %s", e.what()); return nullptr; } + SurfaceHolder surfaceHolder(holder); auto surf = surfaceHolder.getSurface(); if (surf.isNull()) { @@ -133,3 +140,39 @@ android_custom_surface_get_surface( } return ANativeWindow_fromSurface(jni::env(), surf.object().getHandle()); } + + +ANativeWindow * +android_custom_surface_wait_get_surface( + struct android_custom_surface *custom_surface, uint64_t timeout_ms) +{ + using clock = std::chrono::system_clock; + using std::chrono::duration_cast; + using std::chrono::milliseconds; + try { + auto start = clock::now(); + auto end = start + milliseconds(timeout_ms); + ANativeWindow *ret = + android_custom_surface_get_surface(custom_surface); + if (ret != nullptr) { + return ret; + } + while (clock::now() < end) { + //! @todo replace this with a block on the Java code + std::this_thread::sleep_for( + milliseconds(timeout_ms / 5)); + ANativeWindow *ret = + android_custom_surface_get_surface(custom_surface); + if (ret != nullptr) { + return ret; + } + } + } catch (std::exception const &e) { + // do nothing right now. + U_LOG_E( + "Could not wait for our custom surface: " + "%s", + e.what()); + } + return nullptr; +} diff --git a/src/xrt/auxiliary/android/android_custom_surface.h b/src/xrt/auxiliary/android/android_custom_surface.h index b29baaddf..7f25ee1a4 100644 --- a/src/xrt/auxiliary/android/android_custom_surface.h +++ b/src/xrt/auxiliary/android/android_custom_surface.h @@ -75,6 +75,17 @@ ANativeWindow * android_custom_surface_get_surface( struct android_custom_surface *custom_surface); +/*! + * Get the ANativeWindow pointer corresponding to the added Surface, if + * available, waiting up to the specified duration. + * + * This may return NULL because the underlying operation is asynchronous. + * + * @public @memberof android_custom_surface + */ +ANativeWindow * +android_custom_surface_wait_get_surface( + struct android_custom_surface *custom_surface, uint64_t timeout_ms); #ifdef __cplusplus } #endif