2
0
mirror of synced 2025-02-22 06:28:04 +00:00

exp/sensor: remove the manager type

The manager type is not required, because the APIs don't allow
more than one event sources as they used to. In this CL, I am
flattening out the underlying implementations by removing the
manager type.

Change-Id: I3b606ac160b9cecd85cb657e3df1d7d789604764
Reviewed-on: https://go-review.googlesource.com/14293
Reviewed-by: Nigel Tao <nigeltao@golang.org>
This commit is contained in:
Burcu Dogan 2015-09-04 00:17:01 -07:00
parent 043428404d
commit c76d5c8830
6 changed files with 61 additions and 113 deletions

View File

@ -9,39 +9,38 @@
#include <android/sensor.h> #include <android/sensor.h>
#include "android.h" #define GO_ANDROID_SENSOR_LOOPER_ID 100
void GoAndroid_createManager(int looperId, GoAndroid_SensorManager* dst) { ASensorEventQueue* queue = NULL;
ALooper* looper = NULL;
void GoAndroid_createManager() {
ASensorManager* manager = ASensorManager_getInstance(); ASensorManager* manager = ASensorManager_getInstance();
looper = ALooper_forThread();
ALooper* looper = ALooper_forThread();
if (looper == NULL) { if (looper == NULL) {
looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
} }
ASensorEventQueue* queue = ASensorManager_createEventQueue(manager, looper, looperId, NULL, NULL); queue = ASensorManager_createEventQueue(manager, looper, GO_ANDROID_SENSOR_LOOPER_ID, NULL, NULL);
dst->looper = looper;
dst->queue = queue;
dst->looperId = looperId;
} }
int GoAndroid_enableSensor(ASensorEventQueue* q, int s, int32_t usec) { int GoAndroid_enableSensor(int s, int32_t usec) {
ASensorManager* manager = ASensorManager_getInstance(); ASensorManager* manager = ASensorManager_getInstance();
const ASensor* sensor = ASensorManager_getDefaultSensor(manager, s); const ASensor* sensor = ASensorManager_getDefaultSensor(manager, s);
if (sensor == NULL) { if (sensor == NULL) {
return 1; return 1;
} }
ASensorEventQueue_enableSensor(q, sensor); ASensorEventQueue_enableSensor(queue, sensor);
ASensorEventQueue_setEventRate(q, sensor, usec); ASensorEventQueue_setEventRate(queue, sensor, usec);
return 0; return 0;
} }
void GoAndroid_disableSensor(ASensorEventQueue* q, int s) { void GoAndroid_disableSensor(int s) {
ASensorManager* manager = ASensorManager_getInstance(); ASensorManager* manager = ASensorManager_getInstance();
const ASensor* sensor = ASensorManager_getDefaultSensor(manager, s); const ASensor* sensor = ASensorManager_getDefaultSensor(manager, s);
ASensorEventQueue_disableSensor(q, sensor); ASensorEventQueue_disableSensor(queue, sensor);
} }
int GoAndroid_readQueue(int looperId, ASensorEventQueue* q, int n, int32_t* types, int64_t* timestamps, float* vectors) { int GoAndroid_readQueue(int n, int32_t* types, int64_t* timestamps, float* vectors) {
int id; int id;
int events; int events;
ASensorEvent event; ASensorEvent event;
@ -50,10 +49,10 @@ int GoAndroid_readQueue(int looperId, ASensorEventQueue* q, int n, int32_t* type
// If anytime timeout occurs, don't retry to read and immediately return. // If anytime timeout occurs, don't retry to read and immediately return.
// Consume the event queue entirely between polls. // Consume the event queue entirely between polls.
while (i < n && (id = ALooper_pollAll(-1, NULL, &events, NULL)) >= 0) { while (i < n && (id = ALooper_pollAll(-1, NULL, &events, NULL)) >= 0) {
if (id != looperId) { if (id != GO_ANDROID_SENSOR_LOOPER_ID) {
continue; continue;
} }
while (i < n && ASensorEventQueue_getEvents(q, &event, 1)) { while (i < n && ASensorEventQueue_getEvents(queue, &event, 1)) {
types[i] = event.type; types[i] = event.type;
timestamps[i] = event.timestamp; timestamps[i] = event.timestamp;
vectors[i*3] = event.vector.x; vectors[i*3] = event.vector.x;
@ -65,8 +64,8 @@ int GoAndroid_readQueue(int looperId, ASensorEventQueue* q, int n, int32_t* type
return i; return i;
} }
void GoAndroid_destroyManager(GoAndroid_SensorManager* m) { void GoAndroid_destroyManager() {
ASensorManager* manager = ASensorManager_getInstance(); ASensorManager* manager = ASensorManager_getInstance();
ASensorManager_destroyEventQueue(manager, m->queue); ASensorManager_destroyEventQueue(manager, queue);
ALooper_release(m->looper); ALooper_release(looper);
} }

View File

@ -12,14 +12,17 @@ package sensor
#include <stdlib.h> #include <stdlib.h>
#include <android/sensor.h> #include <android/sensor.h>
#include "android.h" void GoAndroid_createManager();
void GoAndroid_destroyManager();
int GoAndroid_enableSensor(int, int32_t);
void GoAndroid_disableSensor(int);
int GoAndroid_readQueue(int n, int32_t* types, int64_t* timestamps, float* vectors);
*/ */
import "C" import "C"
import ( import (
"fmt" "fmt"
"runtime" "runtime"
"sync" "sync"
"sync/atomic"
"time" "time"
"unsafe" "unsafe"
) )
@ -32,8 +35,6 @@ var (
collecting bool collecting bool
) )
var nextLooperID int64 // each underlying ALooper should have a unique ID.
// initSignal initializes an underlying looper and event queue. // initSignal initializes an underlying looper and event queue.
type initSignal struct{} type initSignal struct{}
@ -69,43 +70,34 @@ type inOut struct {
out chan struct{} out chan struct{}
} }
// manager is the Android-specific implementation of Manager. var inout = make(chan inOut)
type manager struct {
m *C.GoAndroid_SensorManager
inout chan inOut
}
// initialize inits the manager and creates a goroutine to proxy the CGO calls. // init 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 // 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 // OS thread. The goroutine proxy locks itself to an OS thread and handles the
// CGO traffic on the same thread. // CGO traffic on the same thread.
func (m *manager) initialize() { func init() {
m.inout = make(chan inOut)
go func() { go func() {
runtime.LockOSThread() runtime.LockOSThread()
for { for {
v := <-m.inout v := <-inout
switch s := v.in.(type) { switch s := v.in.(type) {
case initSignal: case initSignal:
id := atomic.AddInt64(&nextLooperID, 1) C.GoAndroid_createManager()
var mgr C.GoAndroid_SensorManager
C.GoAndroid_createManager(C.int(id), &mgr)
m.m = &mgr
case enableSignal: case enableSignal:
usecsDelay := s.delay.Nanoseconds() / 1000 usecsDelay := s.delay.Nanoseconds() / 1000
code := int(C.GoAndroid_enableSensor(m.m.queue, typeToInt(s.t), C.int32_t(usecsDelay))) code := int(C.GoAndroid_enableSensor(typeToInt(s.t), C.int32_t(usecsDelay)))
if code != 0 { if code != 0 {
*s.err = fmt.Errorf("sensor: no default %v sensor on the device", s.t) *s.err = fmt.Errorf("sensor: no default %v sensor on the device", s.t)
} }
case disableSignal: case disableSignal:
C.GoAndroid_disableSensor(m.m.queue, typeToInt(s.t)) C.GoAndroid_disableSensor(typeToInt(s.t))
case readSignal: case readSignal:
n, err := readEvents(m, s.dst) n, err := readEvents(s.dst)
*s.n = n *s.n = n
*s.err = err *s.err = err
case closeSignal: case closeSignal:
C.GoAndroid_destroyManager(m.m) C.GoAndroid_destroyManager()
close(v.out) close(v.out)
return // we don't need this goroutine anymore return // we don't need this goroutine anymore
} }
@ -113,22 +105,20 @@ func (m *manager) initialize() {
} }
}() }()
if m.m == nil { done := make(chan struct{})
done := make(chan struct{}) inout <- inOut{
m.inout <- inOut{ in: initSignal{},
in: initSignal{}, out: done,
out: done,
}
<-done
} }
<-done
} }
func (m *manager) enable(s Sender, t Type, delay time.Duration) error { func enable(s Sender, t Type, delay time.Duration) error {
m.startCollecting(s) startCollecting(s)
var err error var err error
done := make(chan struct{}) done := make(chan struct{})
m.inout <- inOut{ inout <- inOut{
in: enableSignal{t: t, delay: delay, err: &err}, in: enableSignal{t: t, delay: delay, err: &err},
out: done, out: done,
} }
@ -136,7 +126,7 @@ func (m *manager) enable(s Sender, t Type, delay time.Duration) error {
return err return err
} }
func (m *manager) startCollecting(s Sender) { func startCollecting(s Sender) {
collectingMu.Lock() collectingMu.Lock()
defer collectingMu.Unlock() defer collectingMu.Unlock()
@ -159,7 +149,7 @@ func (m *manager) startCollecting(s Sender) {
// TODO(jbd): readSignal is not required anymore. Use the proxying // TODO(jbd): readSignal is not required anymore. Use the proxying
// goroutine to continously poll the queue and send the events to s. // goroutine to continously poll the queue and send the events to s.
done := make(chan struct{}) done := make(chan struct{})
m.inout <- inOut{ inout <- inOut{
in: readSignal{dst: ev, n: &n, err: &err}, in: readSignal{dst: ev, n: &n, err: &err},
out: done, out: done,
} }
@ -171,9 +161,9 @@ func (m *manager) startCollecting(s Sender) {
}() }()
} }
func (m *manager) disable(t Type) error { func disable(t Type) error {
done := make(chan struct{}) done := make(chan struct{})
m.inout <- inOut{ inout <- inOut{
in: disableSignal{t: t}, in: disableSignal{t: t},
out: done, out: done,
} }
@ -181,14 +171,13 @@ func (m *manager) disable(t Type) error {
return nil return nil
} }
func readEvents(m *manager, e []Event) (n int, err error) { func readEvents(e []Event) (n int, err error) {
num := len(e) num := len(e)
types := make([]C.int32_t, num) types := make([]C.int32_t, num)
timestamps := make([]C.int64_t, num) timestamps := make([]C.int64_t, num)
vectors := make([]C.float, 3*num) vectors := make([]C.float, 3*num)
n = int(C.GoAndroid_readQueue( n = int(C.GoAndroid_readQueue(
m.m.looperId, m.m.queue,
C.int(num), C.int(num),
(*C.int32_t)(unsafe.Pointer(&types[0])), (*C.int32_t)(unsafe.Pointer(&types[0])),
(*C.int64_t)(unsafe.Pointer(&timestamps[0])), (*C.int64_t)(unsafe.Pointer(&timestamps[0])),
@ -208,10 +197,10 @@ func readEvents(m *manager, e []Event) (n int, err error) {
return return
} }
// TODO(jbd): Remove close? // TODO(jbd): Remove destroy?
func (m *manager) close() error { func destroy() error {
done := make(chan struct{}) done := make(chan struct{})
m.inout <- inOut{ inout <- inOut{
in: closeSignal{}, in: closeSignal{},
out: done, out: done,
} }

View File

@ -1,22 +0,0 @@
// 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
#ifndef GO_SENSORS_ANDROID_H
#define GO_SENSORS_ANDROID_H
typedef struct GoAndroid_SensorManager {
ASensorEventQueue* queue;
ALooper* looper;
int looperId;
} GoAndroid_SensorManager;
void GoAndroid_createManager(int looperId, GoAndroid_SensorManager* dst);
void GoAndroid_destroyManager(GoAndroid_SensorManager* m);
int GoAndroid_enableSensor(ASensorEventQueue*, int, int32_t);
void GoAndroid_disableSensor(ASensorEventQueue*, int);
int GoAndroid_readQueue(int looperId, ASensorEventQueue* q, int n, int32_t* types, int64_t* timestamps, float* vectors);
#endif

View File

@ -42,10 +42,7 @@ var channels struct {
done [nTypes]chan struct{} done [nTypes]chan struct{}
} }
type manager struct { func init() {
}
func (m *manager) initialize() {
C.GoIOS_createManager() C.GoIOS_createManager()
} }
@ -63,7 +60,7 @@ func (m *manager) initialize() {
const minDelay = 10 * time.Millisecond const minDelay = 10 * time.Millisecond
func (m *manager) enable(s Sender, t Type, delay time.Duration) error { func enable(s Sender, t Type, delay time.Duration) error {
channels.Lock() channels.Lock()
defer channels.Unlock() defer channels.Unlock()
@ -85,11 +82,11 @@ func (m *manager) enable(s Sender, t Type, delay time.Duration) error {
case Magnetometer: case Magnetometer:
C.GoIOS_startMagneto(interval) C.GoIOS_startMagneto(interval)
} }
go m.pollSensor(s, t, delay, channels.done[t]) go pollSensor(s, t, delay, channels.done[t])
return nil return nil
} }
func (m *manager) disable(t Type) error { func disable(t Type) error {
channels.Lock() channels.Lock()
defer channels.Unlock() defer channels.Unlock()
@ -110,7 +107,7 @@ func (m *manager) disable(t Type) error {
return nil return nil
} }
func (m *manager) pollSensor(s Sender, t Type, d time.Duration, done chan struct{}) { func pollSensor(s Sender, t Type, d time.Duration, done chan struct{}) {
var lastTimestamp int64 var lastTimestamp int64
var timestamp C.int64_t var timestamp C.int64_t
@ -148,8 +145,8 @@ func (m *manager) pollSensor(s Sender, t Type, d time.Duration, done chan struct
} }
} }
// TODO(jbd): Remove close? // TODO(jbd): Remove destroy?
func (m *manager) close() error { func destroy() error {
C.GoIOS_destroyManager() C.GoIOS_destroyManager()
return nil return nil
} }

View File

@ -11,18 +11,14 @@ import (
"time" "time"
) )
type manager struct{} func enable(s Sender, t Type, delay time.Duration) error {
func (m *manager) initialize() {}
func (m *manager) enable(s Sender, t Type, delay time.Duration) error {
return errors.New("sensor: no sensors available") return errors.New("sensor: no sensors available")
} }
func (m *manager) disable(t Type) error { func disable(t Type) error {
return errors.New("sensor: no sensors available") return errors.New("sensor: no sensors available")
} }
func (m *manager) close() error { func destroy() error {
return nil return nil
} }

View File

@ -15,7 +15,7 @@ type Type int
var sensorNames = map[Type]string{ var sensorNames = map[Type]string{
Accelerometer: "Accelerometer", Accelerometer: "Accelerometer",
Gyroscope: "Gyrsocope", Gyroscope: "Gyroscope",
Magnetometer: "Magnetometer", Magnetometer: "Magnetometer",
} }
@ -71,9 +71,6 @@ type Sender interface {
Send(event interface{}) Send(event interface{})
} }
// m is the underlying platform-specific sensor manager.
var m = newManager()
// Enable enables the specified sensor type with the given delay rate. // Enable enables the specified sensor type with the given delay rate.
// Sensor events will be sent to s, a typical example of Sender // Sensor events will be sent to s, a typical example of Sender
// implementations is app.App. // implementations is app.App.
@ -82,7 +79,7 @@ func Enable(s Sender, t Type, delay time.Duration) error {
if t < 0 || int(t) >= len(sensorNames) { if t < 0 || int(t) >= len(sensorNames) {
return errors.New("sensor: unknown sensor type") return errors.New("sensor: unknown sensor type")
} }
return m.enable(s, t, delay) return enable(s, t, delay)
} }
// Disable disables to feed the manager with the specified sensor. // Disable disables to feed the manager with the specified sensor.
@ -91,13 +88,5 @@ func Disable(t Type) error {
if t < 0 || int(t) >= len(sensorNames) { if t < 0 || int(t) >= len(sensorNames) {
return errors.New("sensor: unknown sensor type") return errors.New("sensor: unknown sensor type")
} }
return m.disable(t) return disable(t)
}
func newManager() *manager {
// TODO(jbd): manager type is unnecessary, flatten out the
// platform specific implementation.
mgr := new(manager)
mgr.initialize()
return mgr
} }