android: Support for using device's set display refresh rate

* Adds support for querying the device's currently set display refresh rate to
  be used for android driver on creation. Allowing for devices which support
  selecting other refresh rate modes beyond 60hz.
* Changes hardcoded sensor polling rate to now match refresh queried from the
  device.
This commit is contained in:
korejan 2022-03-22 12:33:30 +00:00 committed by Jakob Bornecrantz
parent e2e65aa241
commit d43c7ffa71
7 changed files with 47 additions and 3 deletions

View file

@ -175,6 +175,11 @@ android_custom_surface_get_display_metrics(struct _JavaVM *vm,
MonadoView::staticInitClass((jclass)clazz.object().getHandle()); MonadoView::staticInitClass((jclass)clazz.object().getHandle());
jni::Object displayMetrics = MonadoView::getDisplayMetrics(Activity((jobject)activity)); 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<int>("widthPixels"), *out_metrics = {.width_pixels = displayMetrics.get<int>("widthPixels"),
.height_pixels = displayMetrics.get<int>("heightPixels"), .height_pixels = displayMetrics.get<int>("heightPixels"),
@ -182,7 +187,8 @@ android_custom_surface_get_display_metrics(struct _JavaVM *vm,
.density = displayMetrics.get<float>("xdpi"), .density = displayMetrics.get<float>("xdpi"),
.scaled_density = displayMetrics.get<float>("ydpi"), .scaled_density = displayMetrics.get<float>("ydpi"),
.xdpi = displayMetrics.get<float>("density"), .xdpi = displayMetrics.get<float>("density"),
.ydpi = displayMetrics.get<float>("scaledDensity")}; .ydpi = displayMetrics.get<float>("scaledDensity"),
.refresh_rate = displayRefreshRate};
return true; return true;
} catch (std::exception const &e) { } catch (std::exception const &e) {

View file

@ -32,6 +32,7 @@ struct xrt_android_display_metrics
float scaled_density; float scaled_density;
float xdpi; float xdpi;
float ydpi; float ydpi;
float refresh_rate;
}; };
/*! /*!

View file

@ -20,6 +20,7 @@ namespace org::freedesktop::monado::auxiliary {
"attachToActivity", "(Landroid/app/Activity;)Lorg/freedesktop/monado/auxiliary/MonadoView;")), "attachToActivity", "(Landroid/app/Activity;)Lorg/freedesktop/monado/auxiliary/MonadoView;")),
getDisplayMetrics(classRef().getStaticMethod("getDisplayMetrics", getDisplayMetrics(classRef().getStaticMethod("getDisplayMetrics",
"(Landroid/app/Activity;)Landroid/util/DisplayMetrics;")), "(Landroid/app/Activity;)Landroid/util/DisplayMetrics;")),
getDisplayRefreshRate(classRef().getStaticMethod("getDisplayRefreshRate", "(Landroid/app/Activity;)F")),
getNativePointer(classRef().getMethod("getNativePointer", "()J")), getNativePointer(classRef().getMethod("getNativePointer", "()J")),
markAsDiscardedByNative(classRef().getMethod("markAsDiscardedByNative", "()V")), markAsDiscardedByNative(classRef().getMethod("markAsDiscardedByNative", "()V")),
waitGetSurfaceHolder(classRef().getMethod("waitGetSurfaceHolder", "(I)Landroid/view/SurfaceHolder;")) waitGetSurfaceHolder(classRef().getMethod("waitGetSurfaceHolder", "(I)Landroid/view/SurfaceHolder;"))

View file

@ -86,6 +86,18 @@ namespace org::freedesktop::monado::auxiliary {
static jni::Object static jni::Object
getDisplayMetrics(android::app::Activity const &activity); 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 * Wrapper for the getNativePointer method
* *
@ -140,6 +152,7 @@ namespace org::freedesktop::monado::auxiliary {
jni::method_t attachToActivity; jni::method_t attachToActivity;
jni::method_t attachToActivity1; jni::method_t attachToActivity1;
jni::method_t getDisplayMetrics; jni::method_t getDisplayMetrics;
jni::method_t getDisplayRefreshRate;
jni::method_t getNativePointer; jni::method_t getNativePointer;
jni::method_t markAsDiscardedByNative; jni::method_t markAsDiscardedByNative;
jni::method_t waitGetSurfaceHolder; jni::method_t waitGetSurfaceHolder;

View file

@ -37,6 +37,12 @@ namespace org::freedesktop::monado::auxiliary {
return Meta::data().clazz().call<jni::Object>(Meta::data().getDisplayMetrics, activity.object()); return Meta::data().clazz().call<jni::Object>(Meta::data().getDisplayMetrics, activity.object());
} }
inline float
MonadoView::getDisplayRefreshRate(android::app::Activity const &activity)
{
return Meta::data().clazz().call<float>(Meta::data().getDisplayRefreshRate, activity.object());
}
inline void * inline void *
MonadoView::getNativePointer() MonadoView::getNativePointer()
{ {

View file

@ -106,6 +106,11 @@ public class MonadoView extends SurfaceView implements SurfaceHolder.Callback, S
return displayMetrics; return displayMetrics;
} }
@Keep
public static float getDisplayRefreshRate(Activity activity) {
return activity.getWindowManager().getDefaultDisplay().getRefreshRate();
}
@Keep @Keep
public long getNativePointer() { public long getNativePointer() {
if (nativeCounterpart == null) { if (nativeCounterpart == null) {

View file

@ -82,10 +82,19 @@ android_sensor_callback(int fd, int events, void *data)
return 1; 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 * static void *
android_run_thread(void *ptr) android_run_thread(void *ptr)
{ {
struct android_device *d = (struct android_device *)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 #if __ANDROID_API__ >= 26
d->sensor_manager = ASensorManager_getInstanceForPackage(XRT_ANDROID_PACKAGE); 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. // Start sensors in case this was not done already.
if (d->accelerometer != NULL) { if (d->accelerometer != NULL) {
ASensorEventQueue_enableSensor(d->event_queue, d->accelerometer); 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) { if (d->gyroscope != NULL) {
ASensorEventQueue_enableSensor(d->event_queue, d->gyroscope); 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; int ret = 0;
@ -234,8 +243,11 @@ android_device_create()
metrics.width_pixels = 2960; metrics.width_pixels = 2960;
metrics.height_pixels = 1440; metrics.height_pixels = 1440;
metrics.density_dpi = 572; 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 w_pixels = metrics.width_pixels;
const uint32_t h_pixels = metrics.height_pixels; const uint32_t h_pixels = metrics.height_pixels;
const uint32_t ppi = metrics.density_dpi; const uint32_t ppi = metrics.density_dpi;