mobile/exp/sensor/android.go

236 lines
5.2 KiB
Go
Raw Normal View History

mobile/sensor: initialize the sensor package Sensors package will contain APIs to read data from a wide variety of movement, position and other physical signals. This CL contains the initial APIs that are targeting event-based sensors. Some of the concerns that influenced the APIs are: - Target game developers. Latency is critical, allow output rates up to ~10 samples per second. - It’s rarely possible to predetermine the minimally viable sample rate requirement of the app. - Allow users to set an upper bound rate to avoid garbage and preserve battery life. - Allow multiple instances of accelerometer, gyroscope, magnetometer and altimeter sensors to be started. Optimize the share of the underlying resources as long as it is not a bottleneck for the sample rate. - Prefer blocking APIs. An automatic poll-timeout could be useful if we’re far behind the sample rate. But, sensor initialization and waking-up significantly take longer and there is no easy way to determine a sensor is in either one of these states. - Provide timestamps for each event to determine the actual rate of the sensor data. - Allow user to return multiple events from each call. Buffering the events at the cost of additional latency is sometimes more neglectable than the overhead of a function call that polls the events one by one. Allow user to determine how many items they want to buffer. The typical latency of a read a single event is 56 usec. Reading 8-16 events at once has a relatively lower bound per event. For high precision throughput, the opportunity to minimize a function call overhead could be useful. - Allow users to check the sensor availability on the device. Change-Id: I9582c8f025d9f922d9635e247d60817f95bdacb9 Reviewed-on: https://go-review.googlesource.com/8174 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
2015-03-27 21:53:09 +00:00
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build android
mobile/sensor: initialize the sensor package Sensors package will contain APIs to read data from a wide variety of movement, position and other physical signals. This CL contains the initial APIs that are targeting event-based sensors. Some of the concerns that influenced the APIs are: - Target game developers. Latency is critical, allow output rates up to ~10 samples per second. - It’s rarely possible to predetermine the minimally viable sample rate requirement of the app. - Allow users to set an upper bound rate to avoid garbage and preserve battery life. - Allow multiple instances of accelerometer, gyroscope, magnetometer and altimeter sensors to be started. Optimize the share of the underlying resources as long as it is not a bottleneck for the sample rate. - Prefer blocking APIs. An automatic poll-timeout could be useful if we’re far behind the sample rate. But, sensor initialization and waking-up significantly take longer and there is no easy way to determine a sensor is in either one of these states. - Provide timestamps for each event to determine the actual rate of the sensor data. - Allow user to return multiple events from each call. Buffering the events at the cost of additional latency is sometimes more neglectable than the overhead of a function call that polls the events one by one. Allow user to determine how many items they want to buffer. The typical latency of a read a single event is 56 usec. Reading 8-16 events at once has a relatively lower bound per event. For high precision throughput, the opportunity to minimize a function call overhead could be useful. - Allow users to check the sensor availability on the device. Change-Id: I9582c8f025d9f922d9635e247d60817f95bdacb9 Reviewed-on: https://go-review.googlesource.com/8174 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
2015-03-27 21:53:09 +00:00
package sensor
/*
#cgo LDFLAGS: -landroid
mobile/sensor: initialize the sensor package Sensors package will contain APIs to read data from a wide variety of movement, position and other physical signals. This CL contains the initial APIs that are targeting event-based sensors. Some of the concerns that influenced the APIs are: - Target game developers. Latency is critical, allow output rates up to ~10 samples per second. - It’s rarely possible to predetermine the minimally viable sample rate requirement of the app. - Allow users to set an upper bound rate to avoid garbage and preserve battery life. - Allow multiple instances of accelerometer, gyroscope, magnetometer and altimeter sensors to be started. Optimize the share of the underlying resources as long as it is not a bottleneck for the sample rate. - Prefer blocking APIs. An automatic poll-timeout could be useful if we’re far behind the sample rate. But, sensor initialization and waking-up significantly take longer and there is no easy way to determine a sensor is in either one of these states. - Provide timestamps for each event to determine the actual rate of the sensor data. - Allow user to return multiple events from each call. Buffering the events at the cost of additional latency is sometimes more neglectable than the overhead of a function call that polls the events one by one. Allow user to determine how many items they want to buffer. The typical latency of a read a single event is 56 usec. Reading 8-16 events at once has a relatively lower bound per event. For high precision throughput, the opportunity to minimize a function call overhead could be useful. - Allow users to check the sensor availability on the device. Change-Id: I9582c8f025d9f922d9635e247d60817f95bdacb9 Reviewed-on: https://go-review.googlesource.com/8174 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
2015-03-27 21:53:09 +00:00
#include <stdlib.h>
#include <android/sensor.h>
#include "android.h"
*/
import "C"
import (
"fmt"
"runtime"
"sync"
"sync/atomic"
"time"
"unsafe"
)
var (
collectingMu sync.Mutex // guards collecting
// collecting is true if sensor event collecting background
// job has already started.
collecting bool
)
var nextLooperID int64 // each underlying ALooper should have a unique ID.
// initSignal initializes an underlying looper and event queue.
type initSignal struct{}
// closeSignal destroys the underlying looper and event queue.
type closeSignal struct{}
// readSignal reads up to len(dst) events and mutates n with
// the number of returned events. If error occurs during the read,
// it mutates err.
type readSignal struct {
dst []Event
n *int
err *error
}
// enableSignal enables the sensors events on the underlying
// event queue for the specified sensor type with the specified
// latency criterion.
type enableSignal struct {
t Type
delay time.Duration
err *error
}
// disableSignal disables the events on the underlying event queue
// from the sensor specified.
type disableSignal struct {
t Type
}
type inOut struct {
in interface{}
out chan struct{}
}
// manager is the Android-specific implementation of Manager.
mobile/sensor: initialize the sensor package Sensors package will contain APIs to read data from a wide variety of movement, position and other physical signals. This CL contains the initial APIs that are targeting event-based sensors. Some of the concerns that influenced the APIs are: - Target game developers. Latency is critical, allow output rates up to ~10 samples per second. - It’s rarely possible to predetermine the minimally viable sample rate requirement of the app. - Allow users to set an upper bound rate to avoid garbage and preserve battery life. - Allow multiple instances of accelerometer, gyroscope, magnetometer and altimeter sensors to be started. Optimize the share of the underlying resources as long as it is not a bottleneck for the sample rate. - Prefer blocking APIs. An automatic poll-timeout could be useful if we’re far behind the sample rate. But, sensor initialization and waking-up significantly take longer and there is no easy way to determine a sensor is in either one of these states. - Provide timestamps for each event to determine the actual rate of the sensor data. - Allow user to return multiple events from each call. Buffering the events at the cost of additional latency is sometimes more neglectable than the overhead of a function call that polls the events one by one. Allow user to determine how many items they want to buffer. The typical latency of a read a single event is 56 usec. Reading 8-16 events at once has a relatively lower bound per event. For high precision throughput, the opportunity to minimize a function call overhead could be useful. - Allow users to check the sensor availability on the device. Change-Id: I9582c8f025d9f922d9635e247d60817f95bdacb9 Reviewed-on: https://go-review.googlesource.com/8174 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
2015-03-27 21:53:09 +00:00
type manager struct {
m *C.GoAndroid_SensorManager
inout chan inOut
}
// initialize inits the manager and creates a goroutine to proxy the CGO calls.
// All actions related to an ALooper needs to be performed from the same
// OS thread. The goroutine proxy locks itself to an OS thread and handles the
// CGO traffic on the same thread.
func (m *manager) initialize() {
m.inout = make(chan inOut)
go func() {
runtime.LockOSThread()
for {
v := <-m.inout
switch s := v.in.(type) {
case initSignal:
id := atomic.AddInt64(&nextLooperID, 1)
var mgr C.GoAndroid_SensorManager
C.GoAndroid_createManager(C.int(id), &mgr)
m.m = &mgr
case enableSignal:
usecsDelay := s.delay.Nanoseconds() / 1000
code := int(C.GoAndroid_enableSensor(m.m.queue, typeToInt(s.t), C.int32_t(usecsDelay)))
if code != 0 {
*s.err = fmt.Errorf("sensor: no default %v sensor on the device", s.t)
}
case disableSignal:
C.GoAndroid_disableSensor(m.m.queue, typeToInt(s.t))
case readSignal:
n, err := readEvents(m, s.dst)
*s.n = n
*s.err = err
case closeSignal:
C.GoAndroid_destroyManager(m.m)
close(v.out)
return // we don't need this goroutine anymore
}
close(v.out)
}
}()
if m.m == nil {
done := make(chan struct{})
m.inout <- inOut{
in: initSignal{},
out: done,
}
<-done
}
}
func (m *manager) enable(s Sender, t Type, delay time.Duration) error {
m.startCollecting(s)
var err error
done := make(chan struct{})
m.inout <- inOut{
in: enableSignal{t: t, delay: delay, err: &err},
out: done,
}
<-done
return err
}
func (m *manager) startCollecting(s Sender) {
collectingMu.Lock()
defer collectingMu.Unlock()
if collecting {
// already collecting.
return
}
collecting = true
// TODO(jbd): Disable the goroutine if all sensors are disabled?
// Read will block until there are new events, a goroutine will be
// parked forever until a sensor is enabled. There must be no
// performance cost other than allocating blocking an OS thread
// forever to keep the goroutine running.
go func() {
ev := make([]Event, 8)
var n int
var err error // TODO(jbd): How to handle the errors? error channel?
for {
// TODO(jbd): readSignal is not required anymore. Use the proxying
// goroutine to continously poll the queue and send the events to s.
done := make(chan struct{})
m.inout <- inOut{
in: readSignal{dst: ev, n: &n, err: &err},
out: done,
}
<-done
for i := 0; i < n; i++ {
s.Send(ev[i])
}
}
}()
mobile/sensor: initialize the sensor package Sensors package will contain APIs to read data from a wide variety of movement, position and other physical signals. This CL contains the initial APIs that are targeting event-based sensors. Some of the concerns that influenced the APIs are: - Target game developers. Latency is critical, allow output rates up to ~10 samples per second. - It’s rarely possible to predetermine the minimally viable sample rate requirement of the app. - Allow users to set an upper bound rate to avoid garbage and preserve battery life. - Allow multiple instances of accelerometer, gyroscope, magnetometer and altimeter sensors to be started. Optimize the share of the underlying resources as long as it is not a bottleneck for the sample rate. - Prefer blocking APIs. An automatic poll-timeout could be useful if we’re far behind the sample rate. But, sensor initialization and waking-up significantly take longer and there is no easy way to determine a sensor is in either one of these states. - Provide timestamps for each event to determine the actual rate of the sensor data. - Allow user to return multiple events from each call. Buffering the events at the cost of additional latency is sometimes more neglectable than the overhead of a function call that polls the events one by one. Allow user to determine how many items they want to buffer. The typical latency of a read a single event is 56 usec. Reading 8-16 events at once has a relatively lower bound per event. For high precision throughput, the opportunity to minimize a function call overhead could be useful. - Allow users to check the sensor availability on the device. Change-Id: I9582c8f025d9f922d9635e247d60817f95bdacb9 Reviewed-on: https://go-review.googlesource.com/8174 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
2015-03-27 21:53:09 +00:00
}
func (m *manager) disable(t Type) error {
done := make(chan struct{})
m.inout <- inOut{
in: disableSignal{t: t},
out: done,
}
<-done
return nil
}
func readEvents(m *manager, e []Event) (n int, err error) {
num := len(e)
types := make([]C.int32_t, num)
timestamps := make([]C.int64_t, num)
vectors := make([]C.float, 3*num)
n = int(C.GoAndroid_readQueue(
m.m.looperId, m.m.queue,
C.int(num),
(*C.int32_t)(unsafe.Pointer(&types[0])),
(*C.int64_t)(unsafe.Pointer(&timestamps[0])),
(*C.float)(unsafe.Pointer(&vectors[0]))),
)
for i := 0; i < n; i++ {
e[i] = Event{
Sensor: intToType[int(types[i])],
Timestamp: int64(timestamps[i]),
Data: []float64{
float64(vectors[i*3]),
float64(vectors[i*3+1]),
float64(vectors[i*3+2]),
},
}
}
return
mobile/sensor: initialize the sensor package Sensors package will contain APIs to read data from a wide variety of movement, position and other physical signals. This CL contains the initial APIs that are targeting event-based sensors. Some of the concerns that influenced the APIs are: - Target game developers. Latency is critical, allow output rates up to ~10 samples per second. - It’s rarely possible to predetermine the minimally viable sample rate requirement of the app. - Allow users to set an upper bound rate to avoid garbage and preserve battery life. - Allow multiple instances of accelerometer, gyroscope, magnetometer and altimeter sensors to be started. Optimize the share of the underlying resources as long as it is not a bottleneck for the sample rate. - Prefer blocking APIs. An automatic poll-timeout could be useful if we’re far behind the sample rate. But, sensor initialization and waking-up significantly take longer and there is no easy way to determine a sensor is in either one of these states. - Provide timestamps for each event to determine the actual rate of the sensor data. - Allow user to return multiple events from each call. Buffering the events at the cost of additional latency is sometimes more neglectable than the overhead of a function call that polls the events one by one. Allow user to determine how many items they want to buffer. The typical latency of a read a single event is 56 usec. Reading 8-16 events at once has a relatively lower bound per event. For high precision throughput, the opportunity to minimize a function call overhead could be useful. - Allow users to check the sensor availability on the device. Change-Id: I9582c8f025d9f922d9635e247d60817f95bdacb9 Reviewed-on: https://go-review.googlesource.com/8174 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
2015-03-27 21:53:09 +00:00
}
// TODO(jbd): Remove close?
func (m *manager) close() error {
done := make(chan struct{})
m.inout <- inOut{
in: closeSignal{},
out: done,
}
<-done
return nil
mobile/sensor: initialize the sensor package Sensors package will contain APIs to read data from a wide variety of movement, position and other physical signals. This CL contains the initial APIs that are targeting event-based sensors. Some of the concerns that influenced the APIs are: - Target game developers. Latency is critical, allow output rates up to ~10 samples per second. - It’s rarely possible to predetermine the minimally viable sample rate requirement of the app. - Allow users to set an upper bound rate to avoid garbage and preserve battery life. - Allow multiple instances of accelerometer, gyroscope, magnetometer and altimeter sensors to be started. Optimize the share of the underlying resources as long as it is not a bottleneck for the sample rate. - Prefer blocking APIs. An automatic poll-timeout could be useful if we’re far behind the sample rate. But, sensor initialization and waking-up significantly take longer and there is no easy way to determine a sensor is in either one of these states. - Provide timestamps for each event to determine the actual rate of the sensor data. - Allow user to return multiple events from each call. Buffering the events at the cost of additional latency is sometimes more neglectable than the overhead of a function call that polls the events one by one. Allow user to determine how many items they want to buffer. The typical latency of a read a single event is 56 usec. Reading 8-16 events at once has a relatively lower bound per event. For high precision throughput, the opportunity to minimize a function call overhead could be useful. - Allow users to check the sensor availability on the device. Change-Id: I9582c8f025d9f922d9635e247d60817f95bdacb9 Reviewed-on: https://go-review.googlesource.com/8174 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
2015-03-27 21:53:09 +00:00
}
var intToType = map[int]Type{
C.ASENSOR_TYPE_ACCELEROMETER: Accelerometer,
C.ASENSOR_TYPE_GYROSCOPE: Gyroscope,
C.ASENSOR_TYPE_MAGNETIC_FIELD: Magnetometer,
mobile/sensor: initialize the sensor package Sensors package will contain APIs to read data from a wide variety of movement, position and other physical signals. This CL contains the initial APIs that are targeting event-based sensors. Some of the concerns that influenced the APIs are: - Target game developers. Latency is critical, allow output rates up to ~10 samples per second. - It’s rarely possible to predetermine the minimally viable sample rate requirement of the app. - Allow users to set an upper bound rate to avoid garbage and preserve battery life. - Allow multiple instances of accelerometer, gyroscope, magnetometer and altimeter sensors to be started. Optimize the share of the underlying resources as long as it is not a bottleneck for the sample rate. - Prefer blocking APIs. An automatic poll-timeout could be useful if we’re far behind the sample rate. But, sensor initialization and waking-up significantly take longer and there is no easy way to determine a sensor is in either one of these states. - Provide timestamps for each event to determine the actual rate of the sensor data. - Allow user to return multiple events from each call. Buffering the events at the cost of additional latency is sometimes more neglectable than the overhead of a function call that polls the events one by one. Allow user to determine how many items they want to buffer. The typical latency of a read a single event is 56 usec. Reading 8-16 events at once has a relatively lower bound per event. For high precision throughput, the opportunity to minimize a function call overhead could be useful. - Allow users to check the sensor availability on the device. Change-Id: I9582c8f025d9f922d9635e247d60817f95bdacb9 Reviewed-on: https://go-review.googlesource.com/8174 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
2015-03-27 21:53:09 +00:00
}
func typeToInt(t Type) C.int {
for k, v := range intToType {
if v == t {
return C.int(k)
}
}
return C.int(-1)
mobile/sensor: initialize the sensor package Sensors package will contain APIs to read data from a wide variety of movement, position and other physical signals. This CL contains the initial APIs that are targeting event-based sensors. Some of the concerns that influenced the APIs are: - Target game developers. Latency is critical, allow output rates up to ~10 samples per second. - It’s rarely possible to predetermine the minimally viable sample rate requirement of the app. - Allow users to set an upper bound rate to avoid garbage and preserve battery life. - Allow multiple instances of accelerometer, gyroscope, magnetometer and altimeter sensors to be started. Optimize the share of the underlying resources as long as it is not a bottleneck for the sample rate. - Prefer blocking APIs. An automatic poll-timeout could be useful if we’re far behind the sample rate. But, sensor initialization and waking-up significantly take longer and there is no easy way to determine a sensor is in either one of these states. - Provide timestamps for each event to determine the actual rate of the sensor data. - Allow user to return multiple events from each call. Buffering the events at the cost of additional latency is sometimes more neglectable than the overhead of a function call that polls the events one by one. Allow user to determine how many items they want to buffer. The typical latency of a read a single event is 56 usec. Reading 8-16 events at once has a relatively lower bound per event. For high precision throughput, the opportunity to minimize a function call overhead could be useful. - Allow users to check the sensor availability on the device. Change-Id: I9582c8f025d9f922d9635e247d60817f95bdacb9 Reviewed-on: https://go-review.googlesource.com/8174 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
2015-03-27 21:53:09 +00:00
}