diff --git a/src/xrt/auxiliary/android/android_custom_surface.cpp b/src/xrt/auxiliary/android/android_custom_surface.cpp index eacfabe1c..50681155e 100644 --- a/src/xrt/auxiliary/android/android_custom_surface.cpp +++ b/src/xrt/auxiliary/android/android_custom_surface.cpp @@ -175,6 +175,11 @@ android_custom_surface_get_display_metrics(struct _JavaVM *vm, MonadoView::staticInitClass((jclass)clazz.object().getHandle()); jni::Object displayMetrics = MonadoView::getDisplayMetrics(Activity((jobject)activity)); + //! @todo implement non-deprecated codepath for api 30+ + float displayRefreshRate = MonadoView::getDisplayRefreshRate(Activity((jobject)activity)); + if (displayRefreshRate == 0.0) { + displayRefreshRate = 60.0f; + } *out_metrics = {.width_pixels = displayMetrics.get("widthPixels"), .height_pixels = displayMetrics.get("heightPixels"), @@ -182,7 +187,8 @@ android_custom_surface_get_display_metrics(struct _JavaVM *vm, .density = displayMetrics.get("xdpi"), .scaled_density = displayMetrics.get("ydpi"), .xdpi = displayMetrics.get("density"), - .ydpi = displayMetrics.get("scaledDensity")}; + .ydpi = displayMetrics.get("scaledDensity"), + .refresh_rate = displayRefreshRate}; return true; } catch (std::exception const &e) { diff --git a/src/xrt/auxiliary/android/android_custom_surface.h b/src/xrt/auxiliary/android/android_custom_surface.h index f42126a49..a82b3cd13 100644 --- a/src/xrt/auxiliary/android/android_custom_surface.h +++ b/src/xrt/auxiliary/android/android_custom_surface.h @@ -32,6 +32,7 @@ struct xrt_android_display_metrics float scaled_density; float xdpi; float ydpi; + float refresh_rate; }; /*! diff --git a/src/xrt/auxiliary/android/org.freedesktop.monado.auxiliary.cpp b/src/xrt/auxiliary/android/org.freedesktop.monado.auxiliary.cpp index 2d44d1149..2625df3e6 100644 --- a/src/xrt/auxiliary/android/org.freedesktop.monado.auxiliary.cpp +++ b/src/xrt/auxiliary/android/org.freedesktop.monado.auxiliary.cpp @@ -20,6 +20,7 @@ namespace org::freedesktop::monado::auxiliary { "attachToActivity", "(Landroid/app/Activity;)Lorg/freedesktop/monado/auxiliary/MonadoView;")), getDisplayMetrics(classRef().getStaticMethod("getDisplayMetrics", "(Landroid/app/Activity;)Landroid/util/DisplayMetrics;")), + getDisplayRefreshRate(classRef().getStaticMethod("getDisplayRefreshRate", "(Landroid/app/Activity;)F")), getNativePointer(classRef().getMethod("getNativePointer", "()J")), markAsDiscardedByNative(classRef().getMethod("markAsDiscardedByNative", "()V")), waitGetSurfaceHolder(classRef().getMethod("waitGetSurfaceHolder", "(I)Landroid/view/SurfaceHolder;")) diff --git a/src/xrt/auxiliary/android/org.freedesktop.monado.auxiliary.hpp b/src/xrt/auxiliary/android/org.freedesktop.monado.auxiliary.hpp index 909c11988..57209bd51 100644 --- a/src/xrt/auxiliary/android/org.freedesktop.monado.auxiliary.hpp +++ b/src/xrt/auxiliary/android/org.freedesktop.monado.auxiliary.hpp @@ -86,6 +86,18 @@ namespace org::freedesktop::monado::auxiliary { static jni::Object getDisplayMetrics(android::app::Activity const &activity); + /*! + * Wrapper for the getDisplayRefreshRate static method + * + * Java prototype: + * `public static float getDisplayRefreshRate(android.app.Activity);` + * + * JNI signature: (Landroid/app/Activity;)F; + * + */ + static float + getDisplayRefreshRate(android::app::Activity const &activity); + /*! * Wrapper for the getNativePointer method * @@ -140,6 +152,7 @@ namespace org::freedesktop::monado::auxiliary { jni::method_t attachToActivity; jni::method_t attachToActivity1; jni::method_t getDisplayMetrics; + jni::method_t getDisplayRefreshRate; jni::method_t getNativePointer; jni::method_t markAsDiscardedByNative; jni::method_t waitGetSurfaceHolder; diff --git a/src/xrt/auxiliary/android/org.freedesktop.monado.auxiliary.impl.hpp b/src/xrt/auxiliary/android/org.freedesktop.monado.auxiliary.impl.hpp index a34f3fa6c..bc0f44339 100644 --- a/src/xrt/auxiliary/android/org.freedesktop.monado.auxiliary.impl.hpp +++ b/src/xrt/auxiliary/android/org.freedesktop.monado.auxiliary.impl.hpp @@ -37,6 +37,12 @@ namespace org::freedesktop::monado::auxiliary { return Meta::data().clazz().call(Meta::data().getDisplayMetrics, activity.object()); } + inline float + MonadoView::getDisplayRefreshRate(android::app::Activity const &activity) + { + return Meta::data().clazz().call(Meta::data().getDisplayRefreshRate, activity.object()); + } + inline void * MonadoView::getNativePointer() { 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 029b3e34a..83f68924f 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 @@ -106,6 +106,11 @@ public class MonadoView extends SurfaceView implements SurfaceHolder.Callback, S return displayMetrics; } + @Keep + public static float getDisplayRefreshRate(Activity activity) { + return activity.getWindowManager().getDefaultDisplay().getRefreshRate(); + } + @Keep public long getNativePointer() { if (nativeCounterpart == null) { diff --git a/src/xrt/drivers/android/android_sensors.c b/src/xrt/drivers/android/android_sensors.c index 599f2617f..0e9ab5961 100644 --- a/src/xrt/drivers/android/android_sensors.c +++ b/src/xrt/drivers/android/android_sensors.c @@ -82,10 +82,19 @@ android_sensor_callback(int fd, int events, void *data) return 1; } +static inline int32_t +android_get_sensor_poll_rate(const struct android_device *d) +{ + const float freq_multiplier = 3.0f; + return (d == NULL) ? POLL_RATE_USEC + : (int32_t)(d->base.hmd->screens[0].nominal_frame_interval_ns * freq_multiplier * 0.001f); +} + static void * android_run_thread(void *ptr) { struct android_device *d = (struct android_device *)ptr; + const int32_t poll_rate_usec = android_get_sensor_poll_rate(d); #if __ANDROID_API__ >= 26 d->sensor_manager = ASensorManager_getInstanceForPackage(XRT_ANDROID_PACKAGE); @@ -104,11 +113,11 @@ android_run_thread(void *ptr) // Start sensors in case this was not done already. if (d->accelerometer != NULL) { ASensorEventQueue_enableSensor(d->event_queue, d->accelerometer); - ASensorEventQueue_setEventRate(d->event_queue, d->accelerometer, POLL_RATE_USEC); + ASensorEventQueue_setEventRate(d->event_queue, d->accelerometer, poll_rate_usec); } if (d->gyroscope != NULL) { ASensorEventQueue_enableSensor(d->event_queue, d->gyroscope); - ASensorEventQueue_setEventRate(d->event_queue, d->gyroscope, POLL_RATE_USEC); + ASensorEventQueue_setEventRate(d->event_queue, d->gyroscope, poll_rate_usec); } int ret = 0; @@ -234,8 +243,11 @@ android_device_create() metrics.width_pixels = 2960; metrics.height_pixels = 1440; metrics.density_dpi = 572; + metrics.refresh_rate = 60.0f; } + d->base.hmd->screens[0].nominal_frame_interval_ns = time_s_to_ns(1.0f / metrics.refresh_rate); + const uint32_t w_pixels = metrics.width_pixels; const uint32_t h_pixels = metrics.height_pixels; const uint32_t ppi = metrics.density_dpi;