android.go 4.2 KB

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