Source code
Revision control
Copy as Markdown
Other Tools
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
package org.mozilla.gecko;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import org.mozilla.gecko.annotation.WrapForJNI;
/* package */ class GeckoSensor {
private static final String LOGTAG = "GeckoSensor";
/*
* Keep these values consistent with |SensorType| in HalSensor.h
*/
private static final int SENSOR_ORIENTATION = 0;
private static final int SENSOR_ACCELERATION = 1;
private static final int SENSOR_PROXIMITY = 2;
private static final int SENSOR_LINEAR_ACCELERATION = 3;
private static final int SENSOR_GYROSCOPE = 4;
private static final int SENSOR_LIGHT = 5;
private static final int SENSOR_ROTATION_VECTOR = 6;
private static final int SENSOR_GAME_ROTATION_VECTOR = 7;
private static final int ORIENTATION_SENSOR_DELAY = 16666; // 60Hz
private static final int MOTION_SENSOR_DELAY = 16666; // 60Hz
private static SensorListeners sListeners;
private static Sensor gAccelerometerSensor;
private static Sensor gLinearAccelerometerSensor;
private static Sensor gGyroscopeSensor;
private static Sensor gOrientationSensor;
private static Sensor gLightSensor;
private static Sensor gRotationVectorSensor;
private static Sensor gGameRotationVectorSensor;
private static class SensorListeners implements SensorEventListener {
@Override
public void onAccuracyChanged(final Sensor sensor, final int accuracy) {}
@Override
public void onSensorChanged(final SensorEvent s) {
final int sensorType = s.sensor.getType();
int halType = 0;
float x = 0.0f, y = 0.0f, z = 0.0f, w = 0.0f;
// SensorEvent timestamp is in nanoseconds, Gecko expects microseconds.
final long time = s.timestamp / 1000;
switch (sensorType) {
case Sensor.TYPE_ACCELEROMETER:
case Sensor.TYPE_LINEAR_ACCELERATION:
case Sensor.TYPE_ORIENTATION:
if (sensorType == Sensor.TYPE_ACCELEROMETER) {
halType = SENSOR_ACCELERATION;
} else if (sensorType == Sensor.TYPE_LINEAR_ACCELERATION) {
halType = SENSOR_LINEAR_ACCELERATION;
} else {
halType = SENSOR_ORIENTATION;
}
x = s.values[0];
y = s.values[1];
z = s.values[2];
break;
case Sensor.TYPE_GYROSCOPE:
halType = SENSOR_GYROSCOPE;
x = (float) Math.toDegrees(s.values[0]);
y = (float) Math.toDegrees(s.values[1]);
z = (float) Math.toDegrees(s.values[2]);
break;
case Sensor.TYPE_LIGHT:
halType = SENSOR_LIGHT;
x = s.values[0];
break;
case Sensor.TYPE_ROTATION_VECTOR:
case Sensor.TYPE_GAME_ROTATION_VECTOR: // API >= 18
halType =
(sensorType == Sensor.TYPE_ROTATION_VECTOR
? SENSOR_ROTATION_VECTOR
: SENSOR_GAME_ROTATION_VECTOR);
x = s.values[0];
y = s.values[1];
z = s.values[2];
if (s.values.length >= 4) {
w = s.values[3];
} else {
// s.values[3] was optional in API <= 18, so we need to compute it
// The values form a unit quaternion, so we can compute the angle of
// rotation purely based on the given 3 values.
w =
1.0f
- s.values[0] * s.values[0]
- s.values[1] * s.values[1]
- s.values[2] * s.values[2];
w = (w > 0.0f) ? (float) Math.sqrt(w) : 0.0f;
}
break;
}
GeckoSensor.onSensorChanged(halType, x, y, z, w, time);
}
}
// All methods are static
private GeckoSensor() {}
@SuppressWarnings("fallthrough")
@WrapForJNI(calledFrom = "gecko")
private static void enableSensor(final int aSensortype) {
if (sListeners == null) {
sListeners = new SensorListeners();
}
final SensorManager sm =
(SensorManager)
GeckoAppShell.getApplicationContext().getSystemService(Context.SENSOR_SERVICE);
switch (aSensortype) {
case SENSOR_GAME_ROTATION_VECTOR:
if (gGameRotationVectorSensor == null) {
gGameRotationVectorSensor = sm.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);
}
if (gGameRotationVectorSensor != null) {
// The game rotation vector sensor is available according to the system, but a few devices
// for it.
if (gGyroscopeSensor == null) {
gGyroscopeSensor = sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
}
if (gGyroscopeSensor != null) {
sm.registerListener(sListeners, gGameRotationVectorSensor, ORIENTATION_SENSOR_DELAY);
break;
}
// This device has a broken game rotation vector sensor. Use rotation vector sensor if
// available.
gGameRotationVectorSensor = null;
}
// Fallthrough
case SENSOR_ROTATION_VECTOR:
if (gRotationVectorSensor == null) {
gRotationVectorSensor = sm.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
}
if (gRotationVectorSensor != null) {
sm.registerListener(sListeners, gRotationVectorSensor, ORIENTATION_SENSOR_DELAY);
break;
}
// Fallthrough
case SENSOR_ORIENTATION:
if (gOrientationSensor == null) {
gOrientationSensor = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION);
}
if (gOrientationSensor != null) {
sm.registerListener(sListeners, gOrientationSensor, ORIENTATION_SENSOR_DELAY);
}
break;
case SENSOR_ACCELERATION:
if (gAccelerometerSensor == null) {
gAccelerometerSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
if (gAccelerometerSensor != null) {
sm.registerListener(sListeners, gAccelerometerSensor, MOTION_SENSOR_DELAY);
}
break;
case SENSOR_LIGHT:
if (gLightSensor == null) {
gLightSensor = sm.getDefaultSensor(Sensor.TYPE_LIGHT);
}
if (gLightSensor != null) {
sm.registerListener(sListeners, gLightSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
break;
case SENSOR_LINEAR_ACCELERATION:
if (gLinearAccelerometerSensor == null) {
gLinearAccelerometerSensor = sm.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
}
if (gLinearAccelerometerSensor != null) {
sm.registerListener(sListeners, gLinearAccelerometerSensor, MOTION_SENSOR_DELAY);
}
break;
case SENSOR_GYROSCOPE:
if (gGyroscopeSensor == null) {
gGyroscopeSensor = sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
}
if (gGyroscopeSensor != null) {
sm.registerListener(sListeners, gGyroscopeSensor, MOTION_SENSOR_DELAY);
}
break;
default:
Log.w(LOGTAG, "Error! Can't enable unknown SENSOR type " + aSensortype);
}
}
@SuppressWarnings("fallthrough")
@WrapForJNI(calledFrom = "gecko")
private static void disableSensor(final int aSensortype) {
if (sListeners == null) {
return;
}
final SensorManager sm =
(SensorManager)
GeckoAppShell.getApplicationContext().getSystemService(Context.SENSOR_SERVICE);
switch (aSensortype) {
case SENSOR_GAME_ROTATION_VECTOR:
if (gGameRotationVectorSensor != null) {
sm.unregisterListener(sListeners, gGameRotationVectorSensor);
break;
}
// Fallthrough
case SENSOR_ROTATION_VECTOR:
if (gRotationVectorSensor != null) {
sm.unregisterListener(sListeners, gRotationVectorSensor);
break;
}
// Fallthrough
case SENSOR_ORIENTATION:
if (gOrientationSensor != null) {
sm.unregisterListener(sListeners, gOrientationSensor);
}
break;
case SENSOR_ACCELERATION:
if (gAccelerometerSensor != null) {
sm.unregisterListener(sListeners, gAccelerometerSensor);
}
break;
case SENSOR_LIGHT:
if (gLightSensor != null) {
sm.unregisterListener(sListeners, gLightSensor);
}
break;
case SENSOR_LINEAR_ACCELERATION:
if (gLinearAccelerometerSensor != null) {
sm.unregisterListener(sListeners, gLinearAccelerometerSensor);
}
break;
case SENSOR_GYROSCOPE:
if (gGyroscopeSensor != null) {
sm.unregisterListener(sListeners, gGyroscopeSensor);
}
break;
default:
Log.w(LOGTAG, "Error! Can't disable unknown SENSOR type " + aSensortype);
}
}
@WrapForJNI(calledFrom = "ui", dispatchTo = "gecko")
/* package */ static native void onSensorChanged(
int halType, float x, float y, float z, float w, long time);
}