1 /*
2 * Copyright (C) 2016 SurroundIO
3 * Author: Martin Kelly <martin@surround.io>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 * The UNION_CAST macro is copyright:
21 * Copyright (C) 2008-2016 Matt Gallagher ( http://cocoawithlove.com ).
22 * All rights reserved.
23 * Permission to use, copy, modify, and/or distribute this software for any purpose
24 * with or without fee is hereby granted, provided that the above copyright notice
25 * and this permission notice appear in all copies.
26
27 * THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
28 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
29 * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
30 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
31 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
32 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
33 * THIS SOFTWARE.
34 */
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include <glib.h>
41 #include <gmodule.h>
42
43 #include "gstjniutils.h"
44 #include "gst-android-hardware-sensor.h"
45
46 static jobject (*gst_android_get_application_context) (void) = NULL;
47
48 GST_DEBUG_CATEGORY_STATIC (ahs_debug);
49 #define GST_CAT_DEFAULT ahs_debug
50
51 /*
52 * See:
53 * http://www.cocoawithlove.com/2008/04/using-pointers-to-recast-in-c-is-bad.html
54 * for details.
55 */
56 #define UNION_CAST(x, destType) \
57 (((union {__typeof__(x) a; destType b;})x).b)
58
59 static struct
60 {
61 jclass klass;
62 jstring SENSOR_SERVICE;
63 jmethodID getSystemService;
64 } android_content_context = {
65 0};
66
67 static struct
68 {
69 jclass klass;
70 jfieldID accuracy;
71 jfieldID values;
72 } android_hardware_sensor_event = {
73 0};
74
75 static struct
76 {
77 jclass klass;
78 jmethodID getDefaultSensor;;
79 jmethodID registerListener;
80 jmethodID unregisterListener;
81 } android_hardware_sensor_manager = {
82 0};
83
84 static struct
85 {
86 jclass klass;
87 jmethodID constructor;
88 } org_freedesktop_gstreamer_androidmedia_gstahscallback = {
89 0};
90
91 GHashTable *sensor_sizes = NULL;
92 static void
gst_ah_sensor_sensor_sizes_init(void)93 gst_ah_sensor_sensor_sizes_init (void)
94 {
95 gint i;
96 static struct
97 {
98 gint type;
99 gsize size;
100 } types[] = {
101 {
102 AHS_SENSOR_TYPE_ACCELEROMETER, sizeof (GstAHSAccelerometerValues)}
103 , {
104 AHS_SENSOR_TYPE_AMBIENT_TEMPERATURE,
105 sizeof (GstAHSAmbientTemperatureValues)}
106 , {
107 AHS_SENSOR_TYPE_GAME_ROTATION_VECTOR,
108 sizeof (GstAHSGameRotationVectorValues)}
109 , {
110 AHS_SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR,
111 sizeof (GstAHSGeomagneticRotationVectorValues)}
112 , {
113 AHS_SENSOR_TYPE_GRAVITY, sizeof (GstAHSGravityValues)}
114 , {
115 AHS_SENSOR_TYPE_GYROSCOPE, sizeof (GstAHSGyroscopeValues)}
116 , {
117 AHS_SENSOR_TYPE_GYROSCOPE_UNCALIBRATED,
118 sizeof (GstAHSGyroscopeUncalibratedValues)}
119 , {
120 AHS_SENSOR_TYPE_HEART_RATE, sizeof (GstAHSHeartRateValues)}
121 , {
122 AHS_SENSOR_TYPE_LIGHT, sizeof (GstAHSLightValues)}
123 , {
124 AHS_SENSOR_TYPE_LINEAR_ACCELERATION,
125 sizeof (GstAHSLinearAccelerationValues)}
126 , {
127 AHS_SENSOR_TYPE_MAGNETIC_FIELD, sizeof (GstAHSMagneticFieldValues)}
128 , {
129 AHS_SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED,
130 sizeof (GstAHSMagneticFieldUncalibratedValues)}
131 , {
132 AHS_SENSOR_TYPE_ORIENTATION, sizeof (GstAHSOrientationValues)}
133 , {
134 AHS_SENSOR_TYPE_PRESSURE, sizeof (GstAHSPressureValues)}
135 , {
136 AHS_SENSOR_TYPE_PROXIMITY, sizeof (GstAHSProximityValues)}
137 , {
138 AHS_SENSOR_TYPE_RELATIVE_HUMIDITY, sizeof (GstAHSRelativeHumidityValues)}
139 , {
140 AHS_SENSOR_TYPE_ROTATION_VECTOR, sizeof (GstAHSRotationVectorValues)}
141 , {
142 AHS_SENSOR_TYPE_STEP_COUNTER, sizeof (GstAHSStepCounterValues)}
143 , {
144 AHS_SENSOR_TYPE_STEP_DETECTOR, sizeof (GstAHSStepDetectorValues)}
145 ,};
146
147 g_assert_null (sensor_sizes);
148
149 sensor_sizes = g_hash_table_new (g_int_hash, g_int_equal);
150 for (i = 0; i < G_N_ELEMENTS (types); i++)
151 g_hash_table_insert (sensor_sizes, &types[i].type, &types[i].size);
152 }
153
154 static void
gst_ah_sensor_sensor_sizes_deinit(void)155 gst_ah_sensor_sensor_sizes_deinit (void)
156 {
157 g_hash_table_unref (sensor_sizes);
158 sensor_sizes = NULL;
159 }
160
161 gsize
gst_ah_sensor_get_sensor_data_size(gint sensor_type)162 gst_ah_sensor_get_sensor_data_size (gint sensor_type)
163 {
164 return *((gsize *) g_hash_table_lookup (sensor_sizes, &sensor_type));
165 }
166
167 static void
gst_ah_sensor_on_sensor_changed(JNIEnv * env,jclass klass,jobject sensor_event,jlong callback,jlong user_data)168 gst_ah_sensor_on_sensor_changed (JNIEnv * env, jclass klass,
169 jobject sensor_event, jlong callback, jlong user_data)
170 {
171 GstAHSensorCallback cb = (GstAHSensorCallback) (gsize) callback;
172
173 if (cb)
174 cb (sensor_event, (gpointer) (gsize) user_data);
175 }
176
177 static void
gst_ah_sensor_on_accuracy_changed(JNIEnv * env,jclass klass,jobject sensor,jint accuracy,jlong callback,jlong user_data)178 gst_ah_sensor_on_accuracy_changed (JNIEnv * env, jclass klass,
179 jobject sensor, jint accuracy, jlong callback, jlong user_data)
180 {
181 GstAHSAccuracyCallback cb = (GstAHSAccuracyCallback) (gsize) callback;
182
183 if (cb)
184 cb (sensor, accuracy, (gpointer) (gsize) user_data);
185 }
186
187 static gboolean natives_registered = FALSE;
188
189 static JNINativeMethod native_methods[] = {
190 {(gchar *) "gst_ah_sensor_on_sensor_changed",
191 (gchar *) "(Landroid/hardware/SensorEvent;JJ)V",
192 (void *) gst_ah_sensor_on_sensor_changed},
193 {(gchar *) "gst_ah_sensor_on_accuracy_changed",
194 (gchar *) "(Landroid/hardware/Sensor;IJJ)V",
195 (void *) gst_ah_sensor_on_accuracy_changed}
196 };
197
198 static gboolean
_init_classes(void)199 _init_classes (void)
200 {
201 gint32 delay;
202 JNIEnv *env = gst_amc_jni_get_env ();
203 GError *err = NULL;
204 jclass klass;
205 jfieldID fieldID;
206 GModule *module;
207 gboolean success;
208 gint32 type;
209
210 /*
211 * Lookup the Android function to get an Android context. This function will
212 * be provided when the plugin is built via ndk-build.
213 */
214 module = g_module_open (NULL, G_MODULE_BIND_LOCAL);
215 if (!module)
216 goto failed;
217 success = g_module_symbol (module, "gst_android_get_application_context",
218 (gpointer *) & gst_android_get_application_context);
219 if (!success || !gst_android_get_application_context)
220 goto failed;
221 g_module_close (module);
222
223 /* android.content.Context */
224 klass = android_content_context.klass = gst_amc_jni_get_class (env, &err,
225 "android/content/Context");
226 if (!klass)
227 goto failed;
228 android_content_context.getSystemService =
229 gst_amc_jni_get_method_id (env, &err, klass, "getSystemService",
230 "(Ljava/lang/String;)Ljava/lang/Object;");
231 if (!android_content_context.getSystemService)
232 goto failed;
233
234 fieldID =
235 gst_amc_jni_get_static_field_id (env, &err, klass, "SENSOR_SERVICE",
236 "Ljava/lang/String;");
237 if (!fieldID)
238 goto failed;
239 if (!gst_amc_jni_get_static_object_field (env, &err, klass, fieldID,
240 &android_content_context.SENSOR_SERVICE))
241 goto failed;
242 android_content_context.SENSOR_SERVICE =
243 gst_amc_jni_object_make_global (env,
244 android_content_context.SENSOR_SERVICE);
245 if (!android_content_context.SENSOR_SERVICE)
246 goto failed;
247
248 /* android.hardware.SensorEvent */
249 klass = android_hardware_sensor_event.klass =
250 gst_amc_jni_get_class (env, &err, "android/hardware/SensorEvent");
251 if (!klass)
252 goto failed;
253 android_hardware_sensor_event.accuracy =
254 gst_amc_jni_get_field_id (env, &err, klass, "accuracy", "I");
255 if (!android_hardware_sensor_event.accuracy)
256 goto failed;
257 android_hardware_sensor_event.values =
258 gst_amc_jni_get_field_id (env, &err, klass, "values", "[F");
259 if (!android_hardware_sensor_event.values)
260 goto failed;
261
262 /* android.hardware.SensorManager */
263 klass = android_hardware_sensor_manager.klass =
264 gst_amc_jni_get_class (env, &err, "android/hardware/SensorManager");
265 if (!klass)
266 goto failed;
267 android_hardware_sensor_manager.getDefaultSensor =
268 gst_amc_jni_get_method_id (env, &err, klass,
269 "getDefaultSensor", "(I)Landroid/hardware/Sensor;");
270 if (!android_hardware_sensor_manager.getDefaultSensor)
271 goto failed;
272 android_hardware_sensor_manager.registerListener =
273 gst_amc_jni_get_method_id (env, &err, klass,
274 "registerListener",
275 "(Landroid/hardware/SensorEventListener;Landroid/hardware/Sensor;I)Z");
276 if (!android_hardware_sensor_manager.registerListener)
277 goto failed;
278 android_hardware_sensor_manager.unregisterListener =
279 gst_amc_jni_get_method_id (env, &err, klass,
280 "unregisterListener", "(Landroid/hardware/SensorEventListener;)V");
281 if (!android_hardware_sensor_manager.unregisterListener)
282 goto failed;
283
284 fieldID =
285 gst_amc_jni_get_static_field_id (env, &err, klass, "SENSOR_DELAY_FASTEST",
286 "I");
287 if (!fieldID)
288 goto failed;
289 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &delay))
290 goto failed;
291 if (delay != AHS_SENSOR_DELAY_FASTEST) {
292 GST_ERROR ("SENSOR_DELAY_FASTEST has changed value");
293 goto failed;
294 }
295
296 fieldID =
297 gst_amc_jni_get_static_field_id (env, &err, klass, "SENSOR_DELAY_GAME",
298 "I");
299 if (!fieldID)
300 goto failed;
301 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &delay))
302 goto failed;
303 if (delay != AHS_SENSOR_DELAY_GAME) {
304 GST_ERROR ("SENSOR_DELAY_GAME has changed value");
305 goto failed;
306 }
307
308 fieldID =
309 gst_amc_jni_get_static_field_id (env, &err, klass, "SENSOR_DELAY_NORMAL",
310 "I");
311 if (!fieldID)
312 goto failed;
313 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &delay))
314 goto failed;
315 if (delay != AHS_SENSOR_DELAY_NORMAL) {
316 GST_ERROR ("SENSOR_DELAY_NORMAL has changed value");
317 goto failed;
318 }
319
320 fieldID =
321 gst_amc_jni_get_static_field_id (env, &err, klass, "SENSOR_DELAY_UI",
322 "I");
323 if (!fieldID)
324 goto failed;
325 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &delay))
326 goto failed;
327 if (delay != AHS_SENSOR_DELAY_UI) {
328 GST_ERROR ("SENSOR_DELAY_UI has changed value");
329 goto failed;
330 }
331
332 /* android.hardware.Sensor */
333 klass = gst_amc_jni_get_class (env, &err, "android/hardware/Sensor");
334 if (!klass)
335 goto failed;
336
337 fieldID =
338 gst_amc_jni_get_static_field_id (env, &err, klass, "TYPE_ACCELEROMETER",
339 "I");
340 if (!fieldID)
341 goto failed;
342 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
343 goto failed;
344 if (type != AHS_SENSOR_TYPE_ACCELEROMETER) {
345 GST_ERROR ("TYPE_ACCELEROMETER has changed value");
346 goto failed;
347 }
348
349 fieldID = gst_amc_jni_get_static_field_id (env, &err, klass,
350 "TYPE_AMBIENT_TEMPERATURE", "I");
351 if (!fieldID)
352 goto failed;
353 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
354 goto failed;
355 if (type != AHS_SENSOR_TYPE_AMBIENT_TEMPERATURE) {
356 GST_ERROR ("TYPE_AMBIENT_TEMPERATURE has changed value");
357 goto failed;
358 }
359
360 fieldID = gst_amc_jni_get_static_field_id (env, &err, klass,
361 "TYPE_GAME_ROTATION_VECTOR", "I");
362 if (!fieldID)
363 goto failed;
364 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
365 goto failed;
366 if (type != AHS_SENSOR_TYPE_GAME_ROTATION_VECTOR) {
367 GST_ERROR ("TYPE_GAME_ROTATION_VECTOR has changed value");
368 goto failed;
369 }
370
371 fieldID = gst_amc_jni_get_static_field_id (env, &err, klass,
372 "TYPE_GEOMAGNETIC_ROTATION_VECTOR", "I");
373 if (!fieldID)
374 goto failed;
375 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
376 goto failed;
377 if (type != AHS_SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR) {
378 GST_ERROR ("TYPE_GEOMAGNETIC_ROTATION_VECTOR has changed value");
379 goto failed;
380 }
381
382 fieldID =
383 gst_amc_jni_get_static_field_id (env, &err, klass, "TYPE_GRAVITY", "I");
384 if (!fieldID)
385 goto failed;
386 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
387 goto failed;
388 if (type != AHS_SENSOR_TYPE_GRAVITY) {
389 GST_ERROR ("TYPE_GRAVITY has changed value");
390 goto failed;
391 }
392
393 fieldID =
394 gst_amc_jni_get_static_field_id (env, &err, klass, "TYPE_GYROSCOPE", "I");
395 if (!fieldID)
396 goto failed;
397 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
398 goto failed;
399 if (type != AHS_SENSOR_TYPE_GYROSCOPE) {
400 GST_ERROR ("TYPE_GYROSCOPE has changed value");
401 goto failed;
402 }
403
404 fieldID =
405 gst_amc_jni_get_static_field_id (env, &err, klass,
406 "TYPE_GYROSCOPE_UNCALIBRATED", "I");
407 if (!fieldID)
408 goto failed;
409 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
410 goto failed;
411 if (type != AHS_SENSOR_TYPE_GYROSCOPE_UNCALIBRATED) {
412 GST_ERROR ("TYPE_GYROSCOPE_UNCALIBRATED has changed value");
413 goto failed;
414 }
415
416 fieldID =
417 gst_amc_jni_get_static_field_id (env, &err, klass, "TYPE_HEART_RATE",
418 "I");
419 if (!fieldID)
420 goto failed;
421 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
422 goto failed;
423 if (type != AHS_SENSOR_TYPE_HEART_RATE) {
424 GST_ERROR ("TYPE_HEART_RATE has changed value");
425 goto failed;
426 }
427
428 fieldID =
429 gst_amc_jni_get_static_field_id (env, &err, klass, "TYPE_LIGHT", "I");
430 if (!fieldID)
431 goto failed;
432 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
433 goto failed;
434 if (type != AHS_SENSOR_TYPE_LIGHT) {
435 GST_ERROR ("TYPE_LIGHT has changed value");
436 goto failed;
437 }
438
439 fieldID =
440 gst_amc_jni_get_static_field_id (env, &err, klass,
441 "TYPE_LINEAR_ACCELERATION", "I");
442 if (!fieldID)
443 goto failed;
444 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
445 goto failed;
446 if (type != AHS_SENSOR_TYPE_LINEAR_ACCELERATION) {
447 GST_ERROR ("TYPE_LINEAR_ACCELERATION has changed value");
448 goto failed;
449 }
450
451 fieldID =
452 gst_amc_jni_get_static_field_id (env, &err, klass, "TYPE_MAGNETIC_FIELD",
453 "I");
454 if (!fieldID)
455 goto failed;
456 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
457 goto failed;
458 if (type != AHS_SENSOR_TYPE_MAGNETIC_FIELD) {
459 GST_ERROR ("TYPE_MAGNETIC_FIELD has changed value");
460 goto failed;
461 }
462
463 fieldID =
464 gst_amc_jni_get_static_field_id (env, &err, klass,
465 "TYPE_MAGNETIC_FIELD_UNCALIBRATED", "I");
466 if (!fieldID)
467 goto failed;
468 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
469 goto failed;
470 if (type != AHS_SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED) {
471 GST_ERROR ("TYPE_MAGNETIC_FIELD_UNCALIBRATED has changed value");
472 goto failed;
473 }
474
475 fieldID =
476 gst_amc_jni_get_static_field_id (env, &err, klass, "TYPE_ORIENTATION",
477 "I");
478 if (!fieldID)
479 goto failed;
480 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
481 goto failed;
482 if (type != AHS_SENSOR_TYPE_ORIENTATION) {
483 GST_ERROR ("TYPE_ORIENTATION has changed value");
484 goto failed;
485 }
486
487 fieldID =
488 gst_amc_jni_get_static_field_id (env, &err, klass, "TYPE_PRESSURE", "I");
489 if (!fieldID)
490 goto failed;
491 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
492 goto failed;
493 if (type != AHS_SENSOR_TYPE_PRESSURE) {
494 GST_ERROR ("TYPE_PRESSURE has changed value");
495 goto failed;
496 }
497
498 fieldID =
499 gst_amc_jni_get_static_field_id (env, &err, klass, "TYPE_PROXIMITY", "I");
500 if (!fieldID)
501 goto failed;
502 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
503 goto failed;
504 if (type != AHS_SENSOR_TYPE_PROXIMITY) {
505 GST_ERROR ("TYPE_PROXIMITY has changed value");
506 goto failed;
507 }
508
509 fieldID =
510 gst_amc_jni_get_static_field_id (env, &err, klass,
511 "TYPE_RELATIVE_HUMIDITY", "I");
512 if (!fieldID)
513 goto failed;
514 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
515 goto failed;
516 if (type != AHS_SENSOR_TYPE_RELATIVE_HUMIDITY) {
517 GST_ERROR ("TYPE_RELATIVE_HUMIDITY has changed value");
518 goto failed;
519 }
520
521 fieldID =
522 gst_amc_jni_get_static_field_id (env, &err, klass, "TYPE_ROTATION_VECTOR",
523 "I");
524 if (!fieldID)
525 goto failed;
526 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
527 goto failed;
528 if (type != AHS_SENSOR_TYPE_ROTATION_VECTOR) {
529 GST_ERROR ("TYPE_ROTATION_VECTOR has changed value");
530 goto failed;
531 }
532
533 fieldID =
534 gst_amc_jni_get_static_field_id (env, &err, klass,
535 "TYPE_SIGNIFICANT_MOTION", "I");
536 if (!fieldID)
537 goto failed;
538 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
539 goto failed;
540 if (type != AHS_SENSOR_TYPE_SIGNIFICANT_MOTION) {
541 GST_ERROR ("TYPE_SIGNIFICANT_MOTION has changed value");
542 goto failed;
543 }
544
545 fieldID =
546 gst_amc_jni_get_static_field_id (env, &err, klass, "TYPE_STEP_COUNTER",
547 "I");
548 if (!fieldID)
549 goto failed;
550 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
551 goto failed;
552 if (type != AHS_SENSOR_TYPE_STEP_COUNTER) {
553 GST_ERROR ("TYPE_STEP_COUNTER has changed value");
554 goto failed;
555 }
556
557 fieldID =
558 gst_amc_jni_get_static_field_id (env, &err, klass, "TYPE_STEP_DETECTOR",
559 "I");
560 if (!fieldID)
561 goto failed;
562 if (!gst_amc_jni_get_static_int_field (env, &err, klass, fieldID, &type))
563 goto failed;
564 if (type != AHS_SENSOR_TYPE_STEP_DETECTOR) {
565 GST_ERROR ("TYPE_STEP_DETECTOR has changed value");
566 goto failed;
567 }
568
569 /* org.freedesktop.gstreamer.androidmedia.GstAhsCallback */
570 if (!org_freedesktop_gstreamer_androidmedia_gstahscallback.klass) {
571 org_freedesktop_gstreamer_androidmedia_gstahscallback.klass =
572 gst_amc_jni_get_application_class (env,
573 "org/freedesktop/gstreamer/androidmedia/GstAhsCallback", &err);
574 }
575 if (!org_freedesktop_gstreamer_androidmedia_gstahscallback.klass)
576 goto failed;
577 org_freedesktop_gstreamer_androidmedia_gstahscallback.constructor =
578 gst_amc_jni_get_method_id (env, &err,
579 org_freedesktop_gstreamer_androidmedia_gstahscallback.klass, "<init>",
580 "(JJJ)V");
581 if (!org_freedesktop_gstreamer_androidmedia_gstahscallback.constructor)
582 goto failed;
583
584 if ((*env)->RegisterNatives (env,
585 org_freedesktop_gstreamer_androidmedia_gstahscallback.klass,
586 native_methods, G_N_ELEMENTS (native_methods))) {
587 GST_ERROR ("Failed to register native methods for GstAhsCallback");
588 goto failed;
589 }
590 natives_registered = TRUE;
591
592 return TRUE;
593
594 failed:
595 if (err) {
596 GST_ERROR ("Failed to initialize Android classes: %s", err->message);
597 g_clear_error (&err);
598 }
599
600 return FALSE;
601 }
602
603 gboolean
gst_android_hardware_sensor_init(void)604 gst_android_hardware_sensor_init (void)
605 {
606 GST_DEBUG_CATEGORY_INIT (ahs_debug, "ahs", 0,
607 "Android Gstreamer Hardware Sensor");
608 if (!_init_classes ()) {
609 gst_android_hardware_sensor_deinit ();
610 return FALSE;
611 }
612
613 gst_ah_sensor_sensor_sizes_init ();
614
615 return TRUE;
616 }
617
618 void
gst_android_hardware_sensor_deinit(void)619 gst_android_hardware_sensor_deinit (void)
620 {
621 JNIEnv *env = gst_amc_jni_get_env ();
622
623 if (android_content_context.SENSOR_SERVICE) {
624 gst_amc_jni_object_unref (env, android_content_context.SENSOR_SERVICE);
625 android_content_context.SENSOR_SERVICE = NULL;
626 }
627
628 if (android_content_context.klass) {
629 gst_amc_jni_object_unref (env, android_content_context.klass);
630 android_content_context.klass = NULL;
631 }
632
633 if (android_hardware_sensor_event.klass) {
634 gst_amc_jni_object_unref (env, android_hardware_sensor_event.klass);
635 android_hardware_sensor_event.klass = NULL;
636 }
637
638 if (android_hardware_sensor_manager.klass) {
639 gst_amc_jni_object_unref (env, android_hardware_sensor_manager.klass);
640 android_hardware_sensor_manager.klass = NULL;
641 }
642
643 if (org_freedesktop_gstreamer_androidmedia_gstahscallback.klass) {
644 if (natives_registered) {
645 (*env)->UnregisterNatives (env,
646 org_freedesktop_gstreamer_androidmedia_gstahscallback.klass);
647 natives_registered = FALSE;
648 }
649 gst_amc_jni_object_unref (env,
650 org_freedesktop_gstreamer_androidmedia_gstahscallback.klass);
651 org_freedesktop_gstreamer_androidmedia_gstahscallback.klass = NULL;
652 }
653
654 if (sensor_sizes)
655 gst_ah_sensor_sensor_sizes_deinit ();
656 }
657
658 GstAHSensorManager *
gst_ah_sensor_get_manager(void)659 gst_ah_sensor_get_manager (void)
660 {
661 jobject context;
662 GError *err = NULL;
663 JNIEnv *env = gst_amc_jni_get_env ();
664 GstAHSensorManager *manager;
665 jobject object;
666 gboolean success;
667
668 context = gst_android_get_application_context ();
669 success = gst_amc_jni_call_object_method (env, &err, context,
670 android_content_context.getSystemService,
671 &object, android_content_context.SENSOR_SERVICE);
672 if (!success)
673 return NULL;
674
675 object = gst_amc_jni_object_make_global (env, object);
676 if (!object)
677 return NULL;
678
679 manager = g_slice_new (GstAHSensorManager);
680 manager->object = object;
681
682 return manager;
683 }
684
685 GstAHSensor *
gst_ah_sensor_get_default_sensor(GstAHSensorManager * self,gint32 sensor_type)686 gst_ah_sensor_get_default_sensor (GstAHSensorManager * self, gint32 sensor_type)
687 {
688 JNIEnv *env = gst_amc_jni_get_env ();
689 GError *err = NULL;
690 jobject object;
691 GstAHSensor *sensor;
692
693 if (!gst_amc_jni_call_object_method (env, &err, self->object,
694 android_hardware_sensor_manager.getDefaultSensor,
695 &object, sensor_type))
696 return NULL;
697
698 object = gst_amc_jni_object_make_global (env, object);
699 if (!object)
700 return NULL;
701
702 sensor = g_slice_new (GstAHSensor);
703 sensor->object = object;
704
705 return sensor;
706 }
707
708 GstAHSensorEventListener *
gst_ah_sensor_create_listener(GstAHSensorCallback sensor_cb,GstAHSAccuracyCallback accuracy_cb,gpointer user_data)709 gst_ah_sensor_create_listener (GstAHSensorCallback sensor_cb,
710 GstAHSAccuracyCallback accuracy_cb, gpointer user_data)
711 {
712 JNIEnv *env = gst_amc_jni_get_env ();
713 GError *err = NULL;
714 GstAHSensorEventListener *listener;
715 jobject object;
716
717 object = gst_amc_jni_new_object (env,
718 &err,
719 TRUE,
720 org_freedesktop_gstreamer_androidmedia_gstahscallback.klass,
721 org_freedesktop_gstreamer_androidmedia_gstahscallback.constructor,
722 UNION_CAST (sensor_cb, jlong),
723 UNION_CAST (accuracy_cb, jlong), UNION_CAST (user_data, jlong));
724 if (err) {
725 GST_ERROR ("Failed to create listener callback class");
726 g_clear_error (&err);
727 return NULL;
728 }
729
730 listener = g_slice_new (GstAHSensorEventListener);
731 listener->object = object;
732
733 return listener;
734 }
735
736 gboolean
gst_ah_sensor_register_listener(GstAHSensorManager * self,GstAHSensorEventListener * listener,GstAHSensor * sensor,gint32 delay)737 gst_ah_sensor_register_listener (GstAHSensorManager * self,
738 GstAHSensorEventListener * listener, GstAHSensor * sensor, gint32 delay)
739 {
740 JNIEnv *env = gst_amc_jni_get_env ();
741 GError *err = NULL;
742 gboolean success;
743
744 gst_amc_jni_call_boolean_method (env, &err, self->object,
745 android_hardware_sensor_manager.registerListener, &success,
746 listener->object, sensor->object, (jint) delay);
747 if (err) {
748 GST_ERROR
749 ("Failed to call android.hardware.SensorManager.registerListener: %s",
750 err->message);
751 g_clear_error (&err);
752 return FALSE;
753 }
754 listener->registered = TRUE;
755
756 return TRUE;
757 }
758
759 void
gst_ah_sensor_unregister_listener(GstAHSensorManager * self,GstAHSensorEventListener * listener)760 gst_ah_sensor_unregister_listener (GstAHSensorManager * self,
761 GstAHSensorEventListener * listener)
762 {
763 JNIEnv *env = gst_amc_jni_get_env ();
764 GError *err = NULL;
765
766 gst_amc_jni_call_void_method (env, &err, self->object,
767 android_hardware_sensor_manager.unregisterListener, listener->object);
768 if (err) {
769 GST_ERROR
770 ("Failed to call android.hardware.SensorManager.unregisterListener: %s",
771 err->message);
772 g_clear_error (&err);
773 }
774 listener->registered = FALSE;
775 }
776
777 gboolean
gst_ah_sensor_populate_event(GstAHSensorEvent * event,jobject event_object,gint size)778 gst_ah_sensor_populate_event (GstAHSensorEvent * event, jobject event_object,
779 gint size)
780 {
781 JNIEnv *env = gst_amc_jni_get_env ();
782 GError *err = NULL;
783 jfloatArray object_array;
784 jfloat *values;
785
786 gst_amc_jni_get_int_field (env, &err,
787 event_object, android_hardware_sensor_event.accuracy, &event->accuracy);
788 if (err) {
789 GST_ERROR ("Failed to get sensor accuracy field: %s", err->message);
790 goto error;
791 }
792
793 gst_amc_jni_get_object_field (env, &err, event_object,
794 android_hardware_sensor_event.values, &object_array);
795 if (err) {
796 GST_ERROR ("Failed to get sensor values field: %s", err->message);
797 goto error;
798 }
799
800 values = (*env)->GetFloatArrayElements (env, object_array, NULL);
801 if (!values) {
802 GST_ERROR ("Failed to get float array elements from object array");
803 gst_amc_jni_object_local_unref (env, object_array);
804 return FALSE;
805 }
806 /* We can't use gst_amc_jni_object_make_global here because we need to call
807 * ReleaseFloatArrayElements before doing a local unref in the failure case,
808 * but gst_amc_jni_object_make_global would unref before we could Release.
809 */
810 event->data.array = gst_amc_jni_object_ref (env, object_array);
811 if (!event->data.array) {
812 (*env)->ReleaseFloatArrayElements (env, object_array, values, JNI_ABORT);
813 gst_amc_jni_object_local_unref (env, object_array);
814 return FALSE;
815 }
816 event->data.values = values;
817 gst_amc_jni_object_local_unref (env, object_array);
818
819 return TRUE;
820
821 error:
822 g_clear_error (&err);
823 return FALSE;
824 }
825
826 void
gst_ah_sensor_free_sensor_data(GstAHSensorData * data)827 gst_ah_sensor_free_sensor_data (GstAHSensorData * data)
828 {
829 JNIEnv *env = gst_amc_jni_get_env ();
830
831 (*env)->ReleaseFloatArrayElements (env, data->array, data->values, JNI_ABORT);
832 gst_amc_jni_object_unref (env, data->array);
833 }
834