github.com/SahandAslani/gomobile@v0.0.0-20210909130135-2cb2d44c09b2/exp/sensor/android.go (about) 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 //go:build android 6 // +build android 7 8 package sensor 9 10 /* 11 #cgo LDFLAGS: -landroid 12 13 #include <stdlib.h> 14 #include <android/sensor.h> 15 16 void GoAndroid_createManager(); 17 void GoAndroid_destroyManager(); 18 int GoAndroid_enableSensor(int, int32_t); 19 void GoAndroid_disableSensor(int); 20 int GoAndroid_readQueue(int n, int32_t* types, int64_t* timestamps, float* vectors); 21 */ 22 import "C" 23 import ( 24 "fmt" 25 "runtime" 26 "sync" 27 "time" 28 "unsafe" 29 ) 30 31 var ( 32 collectingMu sync.Mutex // guards collecting 33 34 // collecting is true if sensor event collecting background 35 // job has already started. 36 collecting bool 37 ) 38 39 // closeSignal destroys the underlying looper and event queue. 40 type closeSignal struct{} 41 42 // readSignal reads up to len(dst) events and mutates n with 43 // the number of returned events. 44 type readSignal struct { 45 dst []Event 46 n *int 47 } 48 49 // enableSignal enables the sensors events on the underlying 50 // event queue for the specified sensor type with the specified 51 // latency criterion. 52 type enableSignal struct { 53 t Type 54 delay time.Duration 55 err *error 56 } 57 58 // disableSignal disables the events on the underlying event queue 59 // from the sensor specified. 60 type disableSignal struct { 61 t Type 62 } 63 64 type inOut struct { 65 in interface{} 66 out chan struct{} 67 } 68 69 var inout = make(chan inOut) 70 71 // init inits the manager and creates a goroutine to proxy the CGO calls. 72 // All actions related to an ALooper needs to be performed from the same 73 // OS thread. The goroutine proxy locks itself to an OS thread and handles the 74 // CGO traffic on the same thread. 75 func init() { 76 go func() { 77 runtime.LockOSThread() 78 C.GoAndroid_createManager() 79 80 for { 81 v := <-inout 82 switch s := v.in.(type) { 83 84 case enableSignal: 85 usecsDelay := s.delay.Nanoseconds() / 1000 86 code := int(C.GoAndroid_enableSensor(typeToInt(s.t), C.int32_t(usecsDelay))) 87 if code != 0 { 88 *s.err = fmt.Errorf("sensor: no default %v sensor on the device", s.t) 89 } 90 case disableSignal: 91 C.GoAndroid_disableSensor(typeToInt(s.t)) 92 case readSignal: 93 n := readEvents(s.dst) 94 *s.n = n 95 case closeSignal: 96 C.GoAndroid_destroyManager() 97 close(v.out) 98 return // we don't need this goroutine anymore 99 } 100 close(v.out) 101 } 102 }() 103 } 104 105 // enable enables the sensor t on sender. A non-nil sender is 106 // required before calling enable. 107 func enable(t Type, delay time.Duration) error { 108 startCollecting() 109 110 var err error 111 done := make(chan struct{}) 112 inout <- inOut{ 113 in: enableSignal{t: t, delay: delay, err: &err}, 114 out: done, 115 } 116 <-done 117 return err 118 } 119 120 func startCollecting() { 121 collectingMu.Lock() 122 defer collectingMu.Unlock() 123 124 if collecting { 125 // already collecting. 126 return 127 } 128 collecting = true 129 130 go func() { 131 ev := make([]Event, 8) 132 var n int 133 for { 134 done := make(chan struct{}) 135 inout <- inOut{ 136 in: readSignal{dst: ev, n: &n}, 137 out: done, 138 } 139 <-done 140 for i := 0; i < n; i++ { 141 sender.Send(ev[i]) 142 } 143 } 144 }() 145 } 146 147 func disable(t Type) error { 148 done := make(chan struct{}) 149 inout <- inOut{ 150 in: disableSignal{t: t}, 151 out: done, 152 } 153 <-done 154 return nil 155 } 156 157 func readEvents(e []Event) int { 158 num := len(e) 159 types := make([]C.int32_t, num) 160 timestamps := make([]C.int64_t, num) 161 vectors := make([]C.float, 3*num) 162 163 n := int(C.GoAndroid_readQueue( 164 C.int(num), 165 (*C.int32_t)(unsafe.Pointer(&types[0])), 166 (*C.int64_t)(unsafe.Pointer(×tamps[0])), 167 (*C.float)(unsafe.Pointer(&vectors[0]))), 168 ) 169 for i := 0; i < n; i++ { 170 e[i] = Event{ 171 Sensor: intToType[int(types[i])], 172 Timestamp: int64(timestamps[i]), 173 Data: []float64{ 174 float64(vectors[i*3]), 175 float64(vectors[i*3+1]), 176 float64(vectors[i*3+2]), 177 }, 178 } 179 } 180 return n 181 } 182 183 // TODO(jbd): Remove destroy? 184 func destroy() error { 185 done := make(chan struct{}) 186 inout <- inOut{ 187 in: closeSignal{}, 188 out: done, 189 } 190 <-done 191 return nil 192 } 193 194 var intToType = map[int]Type{ 195 C.ASENSOR_TYPE_ACCELEROMETER: Accelerometer, 196 C.ASENSOR_TYPE_GYROSCOPE: Gyroscope, 197 C.ASENSOR_TYPE_MAGNETIC_FIELD: Magnetometer, 198 } 199 200 func typeToInt(t Type) C.int { 201 for k, v := range intToType { 202 if v == t { 203 return C.int(k) 204 } 205 } 206 return C.int(-1) 207 }