1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 
5 // +build android
6 
7 #include <stdlib.h>
8 #include <jni.h>
9 
10 #include <android/sensor.h>
11 
12 #define GO_ANDROID_SENSOR_LOOPER_ID 100
13 
14 #define GO_ANDROID_READ_TIMEOUT_MS 1000
15 
16 ASensorEventQueue* queue = NULL;
17 ALooper* looper = NULL;
18 
getSensorManager()19 static ASensorManager* getSensorManager() {
20   #pragma clang diagnostic push
21   // Builders convert C warnings to errors, so suppress the
22   // error from ASensorManager_getInstance being deprecated
23   // in Android 26.
24   #pragma clang diagnostic ignored "-Wdeprecated-declarations"
25   return ASensorManager_getInstance();
26   #pragma clang diagnostic pop
27 }
28 
GoAndroid_createManager()29 void GoAndroid_createManager() {
30   ASensorManager* manager = getSensorManager();
31   looper = ALooper_forThread();
32   if (looper == NULL) {
33     looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
34   }
35   queue = ASensorManager_createEventQueue(manager, looper, GO_ANDROID_SENSOR_LOOPER_ID, NULL, NULL);
36 }
37 
GoAndroid_enableSensor(int s,int32_t usec)38 int GoAndroid_enableSensor(int s, int32_t usec) {
39   ASensorManager* manager = getSensorManager();
40   const ASensor* sensor = ASensorManager_getDefaultSensor(manager, s);
41   if (sensor == NULL) {
42     return 1;
43   }
44   ASensorEventQueue_enableSensor(queue, sensor);
45   ASensorEventQueue_setEventRate(queue, sensor, usec);
46   return 0;
47 }
48 
GoAndroid_disableSensor(int s)49 void GoAndroid_disableSensor(int s) {
50   ASensorManager* manager = getSensorManager();
51   const ASensor* sensor = ASensorManager_getDefaultSensor(manager, s);
52   ASensorEventQueue_disableSensor(queue, sensor);
53 }
54 
GoAndroid_readQueue(int n,int32_t * types,int64_t * timestamps,float * vectors)55 int GoAndroid_readQueue(int n, int32_t* types, int64_t* timestamps, float* vectors) {
56   int id;
57   int events;
58   ASensorEvent event;
59   int i = 0;
60   // Try n times read from the event queue.
61   // If anytime timeout occurs, don't retry to read and immediately return.
62   // Consume the event queue entirely between polls.
63   while (i < n && (id = ALooper_pollAll(GO_ANDROID_READ_TIMEOUT_MS, NULL, &events, NULL)) >= 0) {
64     if (id != GO_ANDROID_SENSOR_LOOPER_ID) {
65       continue;
66     }
67     while (i < n && ASensorEventQueue_getEvents(queue, &event, 1)) {
68       types[i] = event.type;
69       timestamps[i] = event.timestamp;
70       vectors[i*3] = event.vector.x;
71       vectors[i*3+1] = event.vector.y;
72       vectors[i*3+2] = event.vector.z;
73       i++;
74     }
75   }
76   return i;
77 }
78 
GoAndroid_destroyManager()79 void GoAndroid_destroyManager() {
80   ASensorManager* manager = getSensorManager();
81   ASensorManager_destroyEventQueue(manager, queue);
82   queue = NULL;
83   looper = NULL;
84 }
85