Bug 1144674; Implement HAL support for ROTATION_VECTOR and GAME_ROTATION_VECTOR sensors; r=snorp

This commit is contained in:
Vladimir Vukicevic 2015-04-01 16:02:20 -04:00
parent fda5495483
commit c24a005f1e
8 changed files with 129 additions and 20 deletions

View File

@ -15,15 +15,18 @@ namespace hal {
/**
* Enumeration of sensor types. They are used to specify type while
* register or unregister an observer for a sensor of given type.
* If you add or change any here, do the same in GeckoHalDefines.java.
*/
enum SensorType {
SENSOR_UNKNOWN = -1,
SENSOR_ORIENTATION,
SENSOR_ACCELERATION,
SENSOR_PROXIMITY,
SENSOR_LINEAR_ACCELERATION,
SENSOR_GYROSCOPE,
SENSOR_LIGHT,
SENSOR_ORIENTATION = 0,
SENSOR_ACCELERATION = 1,
SENSOR_PROXIMITY = 2,
SENSOR_LINEAR_ACCELERATION = 3,
SENSOR_GYROSCOPE = 4,
SENSOR_LIGHT = 5,
SENSOR_ROTATION_VECTOR = 6,
SENSOR_GAME_ROTATION_VECTOR = 7,
NUM_SENSOR_TYPE
};

View File

@ -38,6 +38,10 @@ namespace mozilla {
// different orientation angles
#define ACCELEROMETER_POLL_RATE 66667000 /*66.667ms*/
// This is present in Android from API level 18 onwards, which is 4.3. We might
// be building on something before 4.3, so use a local define for its value
#define MOZ_SENSOR_TYPE_GAME_ROTATION_VECTOR 15
double radToDeg(double a) {
return a * (180.0 / M_PI);
}
@ -58,6 +62,10 @@ HardwareSensorToHalSensor(int type)
return SENSOR_GYROSCOPE;
case SENSOR_TYPE_LINEAR_ACCELERATION:
return SENSOR_LINEAR_ACCELERATION;
case SENSOR_TYPE_ROTATION_VECTOR:
return SENSOR_ROTATION_VECTOR;
case MOZ_SENSOR_TYPE_GAME_ROTATION_VECTOR:
return SENSOR_GAME_ROTATION_VECTOR;
default:
return SENSOR_UNKNOWN;
}
@ -84,6 +92,10 @@ HalSensorToHardwareSensor(SensorType type)
return SENSOR_TYPE_GYROSCOPE;
case SENSOR_LINEAR_ACCELERATION:
return SENSOR_TYPE_LINEAR_ACCELERATION;
case SENSOR_ROTATION_VECTOR:
return SENSOR_TYPE_ROTATION_VECTOR;
case SENSOR_GAME_ROTATION_VECTOR:
return MOZ_SENSOR_TYPE_GAME_ROTATION_VECTOR;
default:
return -1;
}
@ -131,6 +143,28 @@ public:
}
} else if (mSensorData.sensor() == SENSOR_LIGHT) {
mSensorValues.AppendElement(data.data[0]);
} else if (mSensorData.sensor() == SENSOR_ROTATION_VECTOR) {
mSensorValues.AppendElement(data.data[0]);
mSensorValues.AppendElement(data.data[1]);
mSensorValues.AppendElement(data.data[2]);
if (data.data[3] == 0.0) {
// data.data[3] was optional in Android <= API level 18. It can be computed from 012,
// but it's better to take the actual value if one is provided. The computation is
// v = 1 - d[0]*d[0] - d[1]*d[1] - d[2]*d[2]
// d[3] = v > 0 ? sqrt(v) : 0;
// I'm assuming that it will be 0 if it's not passed in. (The values form a unit
// quaternion, so the angle can be computed from the direction vector.)
float sx = data.data[0], sy = data.data[1], sz = data.data[2];
float v = 1.0f - sx*sx - sy*sy - sz*sz;
mSensorValues.AppendElement(v > 0.0f ? sqrt(v) : 0.0f);
} else {
mSensorValues.AppendElement(data.data[3]);
}
} else if (mSensorData.sensor() == SENSOR_GAME_ROTATION_VECTOR) {
mSensorValues.AppendElement(data.data[0]);
mSensorValues.AppendElement(data.data[1]);
mSensorValues.AppendElement(data.data[2]);
mSensorValues.AppendElement(data.data[3]);
} else {
mSensorValues.AppendElement(data.data[0]);
mSensorValues.AppendElement(data.data[1]);
@ -149,7 +183,7 @@ public:
private:
SensorData mSensorData;
InfallibleTArray<float> mSensorValues;
nsAutoTArray<float, 4> mSensorValues;
};
namespace hal_impl {

View File

@ -226,6 +226,8 @@ public class GeckoAppShell
private static Sensor gOrientationSensor;
private static Sensor gProximitySensor;
private static Sensor gLightSensor;
private static Sensor gRotationVectorSensor;
private static Sensor gGameRotationVectorSensor;
private static final String GECKOREQUEST_RESPONSE_KEY = "response";
private static final String GECKOREQUEST_ERROR_KEY = "error";
@ -648,46 +650,61 @@ public class GeckoAppShell
switch(aSensortype) {
case GeckoHalDefines.SENSOR_ORIENTATION:
if(gOrientationSensor == null)
if (gOrientationSensor == null)
gOrientationSensor = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION);
if (gOrientationSensor != null)
if (gOrientationSensor != null)
sm.registerListener(gi.getSensorEventListener(), gOrientationSensor, SensorManager.SENSOR_DELAY_GAME);
break;
case GeckoHalDefines.SENSOR_ACCELERATION:
if(gAccelerometerSensor == null)
if (gAccelerometerSensor == null)
gAccelerometerSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (gAccelerometerSensor != null)
sm.registerListener(gi.getSensorEventListener(), gAccelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
break;
case GeckoHalDefines.SENSOR_PROXIMITY:
if(gProximitySensor == null )
if (gProximitySensor == null)
gProximitySensor = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY);
if (gProximitySensor != null)
sm.registerListener(gi.getSensorEventListener(), gProximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
break;
case GeckoHalDefines.SENSOR_LIGHT:
if(gLightSensor == null)
if (gLightSensor == null)
gLightSensor = sm.getDefaultSensor(Sensor.TYPE_LIGHT);
if (gLightSensor != null)
sm.registerListener(gi.getSensorEventListener(), gLightSensor, SensorManager.SENSOR_DELAY_NORMAL);
break;
case GeckoHalDefines.SENSOR_LINEAR_ACCELERATION:
if(gLinearAccelerometerSensor == null)
gLinearAccelerometerSensor = sm.getDefaultSensor(10 /* API Level 9 - TYPE_LINEAR_ACCELERATION */);
if (gLinearAccelerometerSensor == null)
gLinearAccelerometerSensor = sm.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
if (gLinearAccelerometerSensor != null)
sm.registerListener(gi.getSensorEventListener(), gLinearAccelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
break;
case GeckoHalDefines.SENSOR_GYROSCOPE:
if(gGyroscopeSensor == null)
if (gGyroscopeSensor == null)
gGyroscopeSensor = sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
if (gGyroscopeSensor != null)
sm.registerListener(gi.getSensorEventListener(), gGyroscopeSensor, SensorManager.SENSOR_DELAY_GAME);
break;
case GeckoHalDefines.SENSOR_ROTATION_VECTOR:
if (gRotationVectorSensor == null)
gRotationVectorSensor = sm.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
if (gRotationVectorSensor != null)
sm.registerListener(gi.getSensorEventListener(), gRotationVectorSensor, SensorManager.SENSOR_DELAY_GAME);
break;
case GeckoHalDefines.SENSOR_GAME_ROTATION_VECTOR:
if (gGameRotationVectorSensor == null)
gGameRotationVectorSensor = sm.getDefaultSensor(15 /* Sensor.TYPE_GAME_ROTATION_VECTOR */); // API >= 18
if (gGameRotationVectorSensor != null)
sm.registerListener(gi.getSensorEventListener(), gGameRotationVectorSensor, SensorManager.SENSOR_DELAY_GAME);
break;
default:
Log.w(LOGTAG, "Error! Can't enable unknown SENSOR type " + aSensortype);
}
@ -728,6 +745,16 @@ public class GeckoAppShell
sm.unregisterListener(gi.getSensorEventListener(), gLinearAccelerometerSensor);
break;
case GeckoHalDefines.SENSOR_ROTATION_VECTOR:
if (gRotationVectorSensor != null)
sm.unregisterListener(gi.getSensorEventListener(), gRotationVectorSensor);
break;
case GeckoHalDefines.SENSOR_GAME_ROTATION_VECTOR:
if (gGameRotationVectorSensor != null)
sm.unregisterListener(gi.getSensorEventListener(), gGameRotationVectorSensor);
break;
case GeckoHalDefines.SENSOR_GYROSCOPE:
if (gGyroscopeSensor != null)
sm.unregisterListener(gi.getSensorEventListener(), gGyroscopeSensor);

View File

@ -179,6 +179,7 @@ public class GeckoEvent {
private double mX;
private double mY;
private double mZ;
private double mW;
private int mMetaState;
private int mFlags;
@ -509,7 +510,7 @@ public class GeckoEvent {
event.mZ = s.values[2];
break;
case 10 /* Requires API Level 9, so just use the raw value - Sensor.TYPE_LINEAR_ACCELEROMETER*/ :
case Sensor.TYPE_LINEAR_ACCELERATION:
event = GeckoEvent.get(NativeGeckoEvent.SENSOR_EVENT);
event.mFlags = GeckoHalDefines.SENSOR_LINEAR_ACCELERATION;
event.mMetaState = HalSensorAccuracyFor(s.accuracy);
@ -551,6 +552,35 @@ public class GeckoEvent {
event.mMetaState = HalSensorAccuracyFor(s.accuracy);
event.mX = s.values[0];
break;
case Sensor.TYPE_ROTATION_VECTOR:
event = GeckoEvent.get(NativeGeckoEvent.SENSOR_EVENT);
event.mFlags = GeckoHalDefines.SENSOR_ROTATION_VECTOR;
event.mMetaState = HalSensorAccuracyFor(s.accuracy);
event.mX = s.values[0];
event.mY = s.values[1];
event.mZ = s.values[2];
if (s.values.length >= 4) {
event.mW = 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.
event.mW = 1 - s.values[0]*s.values[0] - s.values[1]*s.values[1] - s.values[2]*s.values[2];
event.mW = (event.mW > 0.0) ? Math.sqrt(event.mW) : 0.0;
}
break;
// case Sensor.TYPE_GAME_ROTATION_VECTOR: // API >= 18
case 15:
event = GeckoEvent.get(NativeGeckoEvent.SENSOR_EVENT);
event.mFlags = GeckoHalDefines.SENSOR_GAME_ROTATION_VECTOR;
event.mMetaState = HalSensorAccuracyFor(s.accuracy);
event.mX = s.values[0];
event.mY = s.values[1];
event.mZ = s.values[2];
event.mW = s.values[3];
break;
}
return event;
}

View File

@ -8,14 +8,16 @@ package org.mozilla.gecko;
public class GeckoHalDefines
{
/*
* Keep these values consistent with |SensorType| in Hal.h
*/
* Keep these values consistent with |SensorType| in HalSensor.h
*/
public static final int SENSOR_ORIENTATION = 0;
public static final int SENSOR_ACCELERATION = 1;
public static final int SENSOR_PROXIMITY = 2;
public static final int SENSOR_LINEAR_ACCELERATION = 3;
public static final int SENSOR_GYROSCOPE = 4;
public static final int SENSOR_LIGHT = 5;
public static final int SENSOR_ROTATION_VECTOR = 6;
public static final int SENSOR_GAME_ROTATION_VECTOR = 7;
public static final int SENSOR_ACCURACY_UNKNOWN = -1;
public static final int SENSOR_ACCURACY_UNRELIABLE = 0;

View File

@ -29,6 +29,7 @@ jfieldID AndroidGeckoEvent::jOrientations = 0;
jfieldID AndroidGeckoEvent::jXField = 0;
jfieldID AndroidGeckoEvent::jYField = 0;
jfieldID AndroidGeckoEvent::jZField = 0;
jfieldID AndroidGeckoEvent::jWField = 0;
jfieldID AndroidGeckoEvent::jDistanceField = 0;
jfieldID AndroidGeckoEvent::jRectField = 0;
jfieldID AndroidGeckoEvent::jNativeWindowField = 0;
@ -138,6 +139,7 @@ AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv)
jXField = geckoEvent.getField("mX", "D");
jYField = geckoEvent.getField("mY", "D");
jZField = geckoEvent.getField("mZ", "D");
jWField = geckoEvent.getField("mW", "D");
jRectField = geckoEvent.getField("mRect", "Landroid/graphics/Rect;");
jCharactersField = geckoEvent.getField("mCharacters", "Ljava/lang/String;");
@ -466,6 +468,7 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj)
mX = jenv->GetDoubleField(jobj, jXField);
mY = jenv->GetDoubleField(jobj, jYField);
mZ = jenv->GetDoubleField(jobj, jZField);
mW = jenv->GetDoubleField(jobj, jWField);
mFlags = jenv->GetIntField(jobj, jFlagsField);
mMetaState = jenv->GetIntField(jobj, jMetaStateField);
break;

View File

@ -518,6 +518,7 @@ public:
double X() { return mX; }
double Y() { return mY; }
double Z() { return mZ; }
double W() { return mW; }
const nsIntRect& Rect() { return mRect; }
nsAString& Characters() { return mCharacters; }
nsAString& CharactersExtra() { return mCharactersExtra; }
@ -591,7 +592,7 @@ protected:
int mRangeType, mRangeStyles, mRangeLineStyle;
bool mRangeBoldLine;
int mRangeForeColor, mRangeBackColor, mRangeLineColor;
double mX, mY, mZ;
double mX, mY, mZ, mW;
int mPointerIndex;
nsString mCharacters, mCharactersExtra, mData;
nsRefPtr<nsGeoPosition> mGeoPosition;
@ -648,6 +649,7 @@ protected:
static jfieldID jXField;
static jfieldID jYField;
static jfieldID jZField;
static jfieldID jWField;
static jfieldID jDistanceField;
static jfieldID jRectField;
static jfieldID jNativeWindowField;

View File

@ -274,7 +274,7 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
break;
case AndroidGeckoEvent::SENSOR_EVENT: {
InfallibleTArray<float> values;
nsAutoTArray<float, 4> values;
mozilla::hal::SensorType type = (mozilla::hal::SensorType) curEvent->Flags();
switch (type) {
@ -299,6 +299,14 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
values.AppendElement(curEvent->X());
break;
case hal::SENSOR_ROTATION_VECTOR:
case hal::SENSOR_GAME_ROTATION_VECTOR:
values.AppendElement(curEvent->X());
values.AppendElement(curEvent->Y());
values.AppendElement(curEvent->Z());
values.AppendElement(curEvent->W());
break;
default:
__android_log_print(ANDROID_LOG_ERROR,
"Gecko", "### SENSOR_EVENT fired, but type wasn't known %d",