android.go 4.1 KB

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