From 20b179387b38bebea11ee53bf780c4c2c9434922 Mon Sep 17 00:00:00 2001 From: Mis012 Date: Sat, 16 Mar 2024 15:04:02 +0100 Subject: [PATCH] api-impl: implement accelerometer support, no backend yet currently x,y,z values are hardcoded and can only be changed with gdb --- meson.build | 1 + .../android_hardware_SensorManager.h | 21 ++++++++++ .../sensors/android_hardware_SensorManager.c | 40 +++++++++++++++++++ src/api-impl-jni/util.c | 3 ++ src/api-impl-jni/util.h | 4 ++ .../android/hardware/SensorEvent.java | 6 ++- .../android/hardware/SensorManager.java | 9 ++++- 7 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 src/api-impl-jni/generated_headers/android_hardware_SensorManager.h create mode 100644 src/api-impl-jni/sensors/android_hardware_SensorManager.c diff --git a/meson.build b/meson.build index 6962aded..328475d4 100644 --- a/meson.build +++ b/meson.build @@ -102,6 +102,7 @@ libtranslationlayer_so = shared_library('translation_layer_main', [ 'src/api-impl-jni/graphics/android_graphics_drawable_DrawableContainer.c', 'src/api-impl-jni/location/android_location_LocationManager.c', 'src/api-impl-jni/media/android_media_MediaCodec.c', + 'src/api-impl-jni/sensors/android_hardware_SensorManager.c', 'src/api-impl-jni/util.c', 'src/api-impl-jni/views/AndroidLayout.c', 'src/api-impl-jni/views/android_view_View.c', diff --git a/src/api-impl-jni/generated_headers/android_hardware_SensorManager.h b/src/api-impl-jni/generated_headers/android_hardware_SensorManager.h new file mode 100644 index 00000000..a7d60793 --- /dev/null +++ b/src/api-impl-jni/generated_headers/android_hardware_SensorManager.h @@ -0,0 +1,21 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class android_hardware_SensorManager */ + +#ifndef _Included_android_hardware_SensorManager +#define _Included_android_hardware_SensorManager +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: android_hardware_SensorManager + * Method: register_accelerometer_listener_native + * Signature: (Landroid/hardware/SensorEventListener;Landroid/hardware/Sensor;)V + */ +JNIEXPORT void JNICALL Java_android_hardware_SensorManager_register_1accelerometer_1listener_1native + (JNIEnv *, jobject, jobject, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/api-impl-jni/sensors/android_hardware_SensorManager.c b/src/api-impl-jni/sensors/android_hardware_SensorManager.c new file mode 100644 index 00000000..31f46c44 --- /dev/null +++ b/src/api-impl-jni/sensors/android_hardware_SensorManager.c @@ -0,0 +1,40 @@ +#include + +#include "../defines.h" +#include "../util.h" +#include "../generated_headers/android_hardware_SensorManager.h" + +/* FIXME */ +float x = 0; +float y = 2; +float z = 0; + +struct accel_callback_data { JavaVM *jvm; jobject listener; jclass listener_class; jobject sensor; }; +gboolean on_accel_data(struct accel_callback_data *d) +{ + JNIEnv *env; + (*d->jvm)->GetEnv(d->jvm, (void**)&env, JNI_VERSION_1_6); + + jfloatArray values = (*env)->NewFloatArray(env, 3); + (*env)->SetFloatArrayRegion(env, values, 0, 3, (jfloat[]){x, y, z}); + + jobject sensor_event = (*env)->NewObject(env, handle_cache.sensor_event.class, handle_cache.sensor_event.constructor, values, d->sensor); + + (*env)->CallVoidMethod(env, d->listener, _METHOD(d->listener_class, "onSensorChanged", "(Landroid/hardware/SensorEvent;)V"), sensor_event); + + return G_SOURCE_CONTINUE; +} + +JNIEXPORT void JNICALL Java_android_hardware_SensorManager_register_1accelerometer_1listener_1native(JNIEnv *env , jobject this, jobject listener, jobject sensor) +{ + JavaVM *jvm; + (*env)->GetJavaVM(env, &jvm); + + struct accel_callback_data *callback_data = malloc(sizeof(struct accel_callback_data)); + callback_data->jvm = jvm; + callback_data->listener = _REF(listener); + callback_data->listener_class = _REF(_CLASS(callback_data->listener)); + callback_data->sensor = _REF(sensor); + + g_timeout_add(10, G_SOURCE_FUNC(on_accel_data), callback_data); +} diff --git a/src/api-impl-jni/util.c b/src/api-impl-jni/util.c index 8161f43d..fc82c3cc 100644 --- a/src/api-impl-jni/util.c +++ b/src/api-impl-jni/util.c @@ -85,6 +85,9 @@ void set_up_handle_cache(JNIEnv *env) handle_cache.motion_event.class = _REF((*env)->FindClass(env, "android/view/MotionEvent")); handle_cache.motion_event.constructor = _METHOD(handle_cache.motion_event.class, "", "(IIFFJFF)V"); + handle_cache.sensor_event.class = _REF((*env)->FindClass(env, "android/hardware/SensorEvent")); + handle_cache.sensor_event.constructor = _METHOD(handle_cache.sensor_event.class, "", "([FLandroid/hardware/Sensor;)V"); + handle_cache.canvas.class = _REF((*env)->FindClass(env, "android/graphics/Canvas")); handle_cache.canvas.constructor = _METHOD(handle_cache.canvas.class, "", "(JJ)V"); diff --git a/src/api-impl-jni/util.h b/src/api-impl-jni/util.h index bd56461d..8e04549c 100644 --- a/src/api-impl-jni/util.h +++ b/src/api-impl-jni/util.h @@ -37,6 +37,10 @@ struct handle_cache { jclass class; jmethodID constructor; } motion_event; + struct { + jclass class; + jmethodID constructor; + } sensor_event; struct { jclass class; jmethodID constructor; diff --git a/src/api-impl/android/hardware/SensorEvent.java b/src/api-impl/android/hardware/SensorEvent.java index a3950a20..db2e9bb5 100644 --- a/src/api-impl/android/hardware/SensorEvent.java +++ b/src/api-impl/android/hardware/SensorEvent.java @@ -4,8 +4,10 @@ public class SensorEvent { public final float[] values; - public SensorEvent(float[] values) { + public Sensor sensor; + + public SensorEvent(float[] values, Sensor sensor) { this.values = values; + this.sensor = sensor; } - } diff --git a/src/api-impl/android/hardware/SensorManager.java b/src/api-impl/android/hardware/SensorManager.java index 0f106cb4..903f3f47 100644 --- a/src/api-impl/android/hardware/SensorManager.java +++ b/src/api-impl/android/hardware/SensorManager.java @@ -17,16 +17,19 @@ public class SensorManager { return true; // we could try saying that the sensor doesn't exist and hope the app just doesn't use it then, but as long as we never call the handler the app should leave this alone } - public boolean registerListener(final SensorEventListener listener, Sensor sensor, int samplingPeriodUs) { + public boolean registerListener(final SensorEventListener listener, final Sensor sensor, int samplingPeriodUs) { switch(sensor.getType()) { case Sensor.TYPE_ORIENTATION: new LocationManager().requestLocationUpdates(null, 0, 0, new LocationListener() { @Override public void onLocationChanged(Location location) { - listener.onSensorChanged(new SensorEvent(new float[]{(float)location.getBearing()})); + listener.onSensorChanged(new SensorEvent(new float[]{(float)location.getBearing()}, sensor)); } }); return true; + case Sensor.TYPE_ACCELEROMETER: + register_accelerometer_listener_native(listener, sensor); + return true; default: return false; } @@ -35,4 +38,6 @@ public class SensorManager { public void unregisterListener(final SensorEventListener listener, Sensor sensor) { System.out.println("STUB: andoroid.hw.SensorManager.unregisterListener"); } + + native void register_accelerometer_listener_native(SensorEventListener listener, Sensor sensor); }