SensorManagerpublic abstract class SensorManager extends Object
SensorManager lets you access the device's {@link android.hardware.Sensor
sensors}. Get an instance of this class by calling
{@link android.content.Context#getSystemService(java.lang.String)
Context.getSystemService()} with the argument
{@link android.content.Context#SENSOR_SERVICE}.
Always make sure to disable sensors you don't need, especially when your
activity is paused. Failing to do so can drain the battery in just a few
hours. Note that the system will not disable sensors automatically when
the screen turns off.
Note: Don't use this mechanism with a Trigger Sensor, have a look
at {@link TriggerEventListener}. {@link Sensor#TYPE_SIGNIFICANT_MOTION}
is an example of a trigger sensor.
public class SensorActivity extends Activity, implements SensorEventListener {
private final SensorManager mSensorManager;
private final Sensor mAccelerometer;
public SensorActivity() {
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
protected void onResume() {
super.onResume();
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent event) {
}
}
|
Fields Summary |
---|
protected static final String | TAG | private static final float[] | mTempMatrix | private final android.util.SparseArray | mSensorListByType | private LegacySensorManager | mLegacySensorManager | public static final int | SENSOR_ORIENTATIONA constant describing an orientation sensor. See
{@link android.hardware.SensorListener SensorListener} for more details. | public static final int | SENSOR_ACCELEROMETERA constant describing an accelerometer. See
{@link android.hardware.SensorListener SensorListener} for more details. | public static final int | SENSOR_TEMPERATUREA constant describing a temperature sensor See
{@link android.hardware.SensorListener SensorListener} for more details. | public static final int | SENSOR_MAGNETIC_FIELDA constant describing a magnetic sensor See
{@link android.hardware.SensorListener SensorListener} for more details. | public static final int | SENSOR_LIGHTA constant describing an ambient light sensor See
{@link android.hardware.SensorListener SensorListener} for more details. | public static final int | SENSOR_PROXIMITYA constant describing a proximity sensor See
{@link android.hardware.SensorListener SensorListener} for more details. | public static final int | SENSOR_TRICORDERA constant describing a Tricorder See
{@link android.hardware.SensorListener SensorListener} for more details. | public static final int | SENSOR_ORIENTATION_RAWA constant describing an orientation sensor. See
{@link android.hardware.SensorListener SensorListener} for more details. | public static final int | SENSOR_ALLA constant that includes all sensors | public static final int | SENSOR_MINSmallest sensor ID | public static final int | SENSOR_MAXLargest sensor ID | public static final int | DATA_XIndex of the X value in the array returned by
{@link android.hardware.SensorListener#onSensorChanged} | public static final int | DATA_YIndex of the Y value in the array returned by
{@link android.hardware.SensorListener#onSensorChanged} | public static final int | DATA_ZIndex of the Z value in the array returned by
{@link android.hardware.SensorListener#onSensorChanged} | public static final int | RAW_DATA_INDEXOffset to the untransformed values in the array returned by
{@link android.hardware.SensorListener#onSensorChanged} | public static final int | RAW_DATA_XIndex of the untransformed X value in the array returned by
{@link android.hardware.SensorListener#onSensorChanged} | public static final int | RAW_DATA_YIndex of the untransformed Y value in the array returned by
{@link android.hardware.SensorListener#onSensorChanged} | public static final int | RAW_DATA_ZIndex of the untransformed Z value in the array returned by
{@link android.hardware.SensorListener#onSensorChanged} | public static final float | STANDARD_GRAVITYStandard gravity (g) on Earth. This value is equivalent to 1G | public static final float | GRAVITY_SUNSun's gravity in SI units (m/s^2) | public static final float | GRAVITY_MERCURYMercury's gravity in SI units (m/s^2) | public static final float | GRAVITY_VENUSVenus' gravity in SI units (m/s^2) | public static final float | GRAVITY_EARTHEarth's gravity in SI units (m/s^2) | public static final float | GRAVITY_MOONThe Moon's gravity in SI units (m/s^2) | public static final float | GRAVITY_MARSMars' gravity in SI units (m/s^2) | public static final float | GRAVITY_JUPITERJupiter's gravity in SI units (m/s^2) | public static final float | GRAVITY_SATURNSaturn's gravity in SI units (m/s^2) | public static final float | GRAVITY_URANUSUranus' gravity in SI units (m/s^2) | public static final float | GRAVITY_NEPTUNENeptune's gravity in SI units (m/s^2) | public static final float | GRAVITY_PLUTOPluto's gravity in SI units (m/s^2) | public static final float | GRAVITY_DEATH_STAR_IGravity (estimate) on the first Death Star in Empire units (m/s^2) | public static final float | GRAVITY_THE_ISLANDGravity on the island | public static final float | MAGNETIC_FIELD_EARTH_MAXMaximum magnetic field on Earth's surface | public static final float | MAGNETIC_FIELD_EARTH_MINMinimum magnetic field on Earth's surface | public static final float | PRESSURE_STANDARD_ATMOSPHEREStandard atmosphere, or average sea-level pressure in hPa (millibar) | public static final float | LIGHT_SUNLIGHT_MAXMaximum luminance of sunlight in lux | public static final float | LIGHT_SUNLIGHTluminance of sunlight in lux | public static final float | LIGHT_SHADEluminance in shade in lux | public static final float | LIGHT_OVERCASTluminance under an overcast sky in lux | public static final float | LIGHT_SUNRISEluminance at sunrise in lux | public static final float | LIGHT_CLOUDYluminance under a cloudy sky in lux | public static final float | LIGHT_FULLMOONluminance at night with full moon in lux | public static final float | LIGHT_NO_MOONluminance at night with no moon in lux | public static final int | SENSOR_DELAY_FASTESTget sensor data as fast as possible | public static final int | SENSOR_DELAY_GAMErate suitable for games | public static final int | SENSOR_DELAY_UIrate suitable for the user interface | public static final int | SENSOR_DELAY_NORMALrate (default) suitable for screen orientation changes | public static final int | SENSOR_STATUS_NO_CONTACTThe values returned by this sensor cannot be trusted because the sensor
had no contact with what it was measuring (for example, the heart rate
monitor is not in contact with the user). | public static final int | SENSOR_STATUS_UNRELIABLEThe values returned by this sensor cannot be trusted, calibration is
needed or the environment doesn't allow readings | public static final int | SENSOR_STATUS_ACCURACY_LOWThis sensor is reporting data with low accuracy, calibration with the
environment is needed | public static final int | SENSOR_STATUS_ACCURACY_MEDIUMThis sensor is reporting data with an average level of accuracy,
calibration with the environment may improve the readings | public static final int | SENSOR_STATUS_ACCURACY_HIGHThis sensor is reporting data with maximum accuracy | public static final int | AXIS_Xsee {@link #remapCoordinateSystem} | public static final int | AXIS_Ysee {@link #remapCoordinateSystem} | public static final int | AXIS_Zsee {@link #remapCoordinateSystem} | public static final int | AXIS_MINUS_Xsee {@link #remapCoordinateSystem} | public static final int | AXIS_MINUS_Ysee {@link #remapCoordinateSystem} | public static final int | AXIS_MINUS_Zsee {@link #remapCoordinateSystem} |
Constructors Summary |
---|
public SensorManager(){@hide}
|
Methods Summary |
---|
public boolean | cancelTriggerSensor(TriggerEventListener listener, Sensor sensor)Cancels receiving trigger events for a trigger sensor.
Note that a Trigger sensor will be auto disabled if
{@link TriggerEventListener#onTrigger(TriggerEvent)} has triggered.
This method is provided in case the user wants to explicitly cancel the request
to receive trigger events.
return cancelTriggerSensorImpl(listener, sensor, true);
| protected abstract boolean | cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor, boolean disable)
| public boolean | flush(SensorEventListener listener)Flushes the FIFO of all the sensors registered for this listener. If there are events
in the FIFO of the sensor, they are returned as if the maxReportLantecy of the FIFO has
expired. Events are returned in the usual way through the SensorEventListener.
This call doesn't affect the maxReportLantecy for this sensor. This call is asynchronous and
returns immediately.
{@link android.hardware.SensorEventListener2#onFlushCompleted onFlushCompleted} is called
after all the events in the batch at the time of calling this method have been delivered
successfully. If the hardware doesn't support flush, it still returns true and a trivial
flush complete event is sent after the current event for all the clients registered for this
sensor.
return flushImpl(listener);
| protected abstract boolean | flushImpl(SensorEventListener listener)
| public static float | getAltitude(float p0, float p)Computes the Altitude in meters from the atmospheric pressure and the
pressure at sea level.
Typically the atmospheric pressure is read from a
{@link Sensor#TYPE_PRESSURE} sensor. The pressure at sea level must be
known, usually it can be retrieved from airport databases in the
vicinity. If unknown, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE}
as an approximation, but absolute altitudes won't be accurate.
To calculate altitude differences, you must calculate the difference
between the altitudes at both points. If you don't know the altitude
as sea level, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE} instead,
which will give good results considering the range of pressure typically
involved.
float altitude_difference =
getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point2)
- getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point1);
final float coef = 1.0f / 5.255f;
return 44330.0f * (1.0f - (float)Math.pow(p/p0, coef));
| public static void | getAngleChange(float[] angleChange, float[] R, float[] prevR)Helper function to compute the angle change between two rotation matrices.
Given a current rotation matrix (R) and a previous rotation matrix
(prevR) computes the rotation around the z,x, and y axes which
transforms prevR to R.
outputs a 3 element vector containing the z,x, and y angle
change at indexes 0, 1, and 2 respectively.
Each input matrix is either as a 3x3 or 4x4 row-major matrix
depending on the length of the passed array:
If the array length is 9, then the array elements represent this matrix
/ R[ 0] R[ 1] R[ 2] \
| R[ 3] R[ 4] R[ 5] |
\ R[ 6] R[ 7] R[ 8] /
If the array length is 16, then the array elements represent this matrix
/ R[ 0] R[ 1] R[ 2] R[ 3] \
| R[ 4] R[ 5] R[ 6] R[ 7] |
| R[ 8] R[ 9] R[10] R[11] |
\ R[12] R[13] R[14] R[15] /
float rd1=0,rd4=0, rd6=0,rd7=0, rd8=0;
float ri0=0,ri1=0,ri2=0,ri3=0,ri4=0,ri5=0,ri6=0,ri7=0,ri8=0;
float pri0=0, pri1=0, pri2=0, pri3=0, pri4=0, pri5=0, pri6=0, pri7=0, pri8=0;
if(R.length == 9) {
ri0 = R[0];
ri1 = R[1];
ri2 = R[2];
ri3 = R[3];
ri4 = R[4];
ri5 = R[5];
ri6 = R[6];
ri7 = R[7];
ri8 = R[8];
} else if(R.length == 16) {
ri0 = R[0];
ri1 = R[1];
ri2 = R[2];
ri3 = R[4];
ri4 = R[5];
ri5 = R[6];
ri6 = R[8];
ri7 = R[9];
ri8 = R[10];
}
if(prevR.length == 9) {
pri0 = prevR[0];
pri1 = prevR[1];
pri2 = prevR[2];
pri3 = prevR[3];
pri4 = prevR[4];
pri5 = prevR[5];
pri6 = prevR[6];
pri7 = prevR[7];
pri8 = prevR[8];
} else if(prevR.length == 16) {
pri0 = prevR[0];
pri1 = prevR[1];
pri2 = prevR[2];
pri3 = prevR[4];
pri4 = prevR[5];
pri5 = prevR[6];
pri6 = prevR[8];
pri7 = prevR[9];
pri8 = prevR[10];
}
// calculate the parts of the rotation difference matrix we need
// rd[i][j] = pri[0][i] * ri[0][j] + pri[1][i] * ri[1][j] + pri[2][i] * ri[2][j];
rd1 = pri0 * ri1 + pri3 * ri4 + pri6 * ri7; //rd[0][1]
rd4 = pri1 * ri1 + pri4 * ri4 + pri7 * ri7; //rd[1][1]
rd6 = pri2 * ri0 + pri5 * ri3 + pri8 * ri6; //rd[2][0]
rd7 = pri2 * ri1 + pri5 * ri4 + pri8 * ri7; //rd[2][1]
rd8 = pri2 * ri2 + pri5 * ri5 + pri8 * ri8; //rd[2][2]
angleChange[0] = (float)Math.atan2(rd1, rd4);
angleChange[1] = (float)Math.asin(-rd7);
angleChange[2] = (float)Math.atan2(-rd6, rd8);
| public Sensor | getDefaultSensor(int type)Use this method to get the default sensor for a given type. Note that the
returned sensor could be a composite sensor, and its data could be
averaged or filtered. If you need to access the raw sensors use
{@link SensorManager#getSensorList(int) getSensorList}.
// TODO: need to be smarter, for now, just return the 1st sensor
List<Sensor> l = getSensorList(type);
boolean wakeUpSensor = false;
// For the following sensor types, return a wake-up sensor. These types are by default
// defined as wake-up sensors. For the rest of the SDK defined sensor types return a
// non_wake-up version.
if (type == Sensor.TYPE_PROXIMITY || type == Sensor.TYPE_SIGNIFICANT_MOTION ||
type == Sensor.TYPE_TILT_DETECTOR || type == Sensor.TYPE_WAKE_GESTURE ||
type == Sensor.TYPE_GLANCE_GESTURE || type == Sensor.TYPE_PICK_UP_GESTURE) {
wakeUpSensor = true;
}
for (Sensor sensor : l) {
if (sensor.isWakeUpSensor() == wakeUpSensor) return sensor;
}
return null;
| public Sensor | getDefaultSensor(int type, boolean wakeUp)Return a Sensor with the given type and wakeUp properties. If multiple sensors of this
type exist, any one of them may be returned.
For example,
- getDefaultSensor({@link Sensor#TYPE_ACCELEROMETER}, true) returns a wake-up accelerometer
sensor if it exists.
- getDefaultSensor({@link Sensor#TYPE_PROXIMITY}, false) returns a non wake-up proximity
sensor if it exists.
- getDefaultSensor({@link Sensor#TYPE_PROXIMITY}, true) returns a wake-up proximity sensor
which is the same as the Sensor returned by {@link #getDefaultSensor(int)}.
Note: Sensors like {@link Sensor#TYPE_PROXIMITY} and {@link Sensor#TYPE_SIGNIFICANT_MOTION}
are declared as wake-up sensors by default.
List<Sensor> l = getSensorList(type);
for (Sensor sensor : l) {
if (sensor.isWakeUpSensor() == wakeUp)
return sensor;
}
return null;
| private static int | getDelay(int rate)
int delay = -1;
switch (rate) {
case SENSOR_DELAY_FASTEST:
delay = 0;
break;
case SENSOR_DELAY_GAME:
delay = 20000;
break;
case SENSOR_DELAY_UI:
delay = 66667;
break;
case SENSOR_DELAY_NORMAL:
delay = 200000;
break;
default:
delay = rate;
break;
}
return delay;
| protected abstract java.util.List | getFullSensorList()Gets the full list of sensors that are available.
| public static float | getInclination(float[] I)Computes the geomagnetic inclination angle in radians from the
inclination matrix I returned by {@link #getRotationMatrix}.
if (I.length == 9) {
return (float)Math.atan2(I[5], I[4]);
} else {
return (float)Math.atan2(I[6], I[5]);
}
| private LegacySensorManager | getLegacySensorManager()
synchronized (mSensorListByType) {
if (mLegacySensorManager == null) {
Log.i(TAG, "This application is using deprecated SensorManager API which will "
+ "be removed someday. Please consider switching to the new API.");
mLegacySensorManager = new LegacySensorManager(this);
}
return mLegacySensorManager;
}
| public static float[] | getOrientation(float[] R, float[] values)Computes the device's orientation based on the rotation matrix.
When it returns, the array values is filled with the result:
- values[0]: azimuth, rotation around the Z axis.
- values[1]: pitch, rotation around the X axis.
- values[2]: roll, rotation around the Y axis.
The reference coordinate-system used is different from the world
coordinate-system defined for the rotation matrix:
- X is defined as the vector product Y.Z (It is tangential to
the ground at the device's current location and roughly points West).
- Y is tangential to the ground at the device's current location and
points towards the magnetic North Pole.
- Z points towards the center of the Earth and is perpendicular to the ground.
All three angles above are in radians and positive in the
counter-clockwise direction.
/*
* 4x4 (length=16) case:
* / R[ 0] R[ 1] R[ 2] 0 \
* | R[ 4] R[ 5] R[ 6] 0 |
* | R[ 8] R[ 9] R[10] 0 |
* \ 0 0 0 1 /
*
* 3x3 (length=9) case:
* / R[ 0] R[ 1] R[ 2] \
* | R[ 3] R[ 4] R[ 5] |
* \ R[ 6] R[ 7] R[ 8] /
*
*/
if (R.length == 9) {
values[0] = (float)Math.atan2(R[1], R[4]);
values[1] = (float)Math.asin(-R[7]);
values[2] = (float)Math.atan2(-R[6], R[8]);
} else {
values[0] = (float)Math.atan2(R[1], R[5]);
values[1] = (float)Math.asin(-R[9]);
values[2] = (float)Math.atan2(-R[8], R[10]);
}
return values;
| public static void | getQuaternionFromVector(float[] Q, float[] rv)Helper function to convert a rotation vector to a normalized quaternion.
Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a normalized
quaternion in the array Q. The quaternion is stored as [w, x, y, z]
if (rv.length >= 4) {
Q[0] = rv[3];
} else {
Q[0] = 1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2];
Q[0] = (Q[0] > 0) ? (float)Math.sqrt(Q[0]) : 0;
}
Q[1] = rv[0];
Q[2] = rv[1];
Q[3] = rv[2];
| public static boolean | getRotationMatrix(float[] R, float[] I, float[] gravity, float[] geomagnetic)
Computes the inclination matrix I as well as the rotation matrix
R transforming a vector from the device coordinate system to the
world's coordinate system which is defined as a direct orthonormal basis,
where:
- X is defined as the vector product Y.Z (It is tangential to
the ground at the device's current location and roughly points East).
- Y is tangential to the ground at the device's current location and
points towards the magnetic North Pole.
- Z points towards the sky and is perpendicular to the ground.
By definition:
[0 0 g] = R * gravity (g = magnitude of gravity)
[0 m 0] = I * R * geomagnetic (m = magnitude of
geomagnetic field)
R is the identity matrix when the device is aligned with the
world's coordinate system, that is, when the device's X axis points
toward East, the Y axis points to the North Pole and the device is facing
the sky.
I is a rotation matrix transforming the geomagnetic vector into
the same coordinate space as gravity (the world's coordinate space).
I is a simple rotation around the X axis. The inclination angle in
radians can be computed with {@link #getInclination}.
Each matrix is returned either as a 3x3 or 4x4 row-major matrix depending
on the length of the passed array:
If the array length is 16:
/ M[ 0] M[ 1] M[ 2] M[ 3] \
| M[ 4] M[ 5] M[ 6] M[ 7] |
| M[ 8] M[ 9] M[10] M[11] |
\ M[12] M[13] M[14] M[15] /
This matrix is ready to be used by OpenGL ES's
{@link javax.microedition.khronos.opengles.GL10#glLoadMatrixf(float[], int)
glLoadMatrixf(float[], int)}.
Note that because OpenGL matrices are column-major matrices you must
transpose the matrix before using it. However, since the matrix is a
rotation matrix, its transpose is also its inverse, conveniently, it is
often the inverse of the rotation that is needed for rendering; it can
therefore be used with OpenGL ES directly.
Also note that the returned matrices always have this form:
/ M[ 0] M[ 1] M[ 2] 0 \
| M[ 4] M[ 5] M[ 6] 0 |
| M[ 8] M[ 9] M[10] 0 |
\ 0 0 0 1 /
If the array length is 9:
/ M[ 0] M[ 1] M[ 2] \
| M[ 3] M[ 4] M[ 5] |
\ M[ 6] M[ 7] M[ 8] /
The inverse of each matrix can be computed easily by taking its
transpose.
The matrices returned by this function are meaningful only when the
device is not free-falling and it is not close to the magnetic north. If
the device is accelerating, or placed into a strong magnetic field, the
returned matrices may be inaccurate.
// TODO: move this to native code for efficiency
float Ax = gravity[0];
float Ay = gravity[1];
float Az = gravity[2];
final float Ex = geomagnetic[0];
final float Ey = geomagnetic[1];
final float Ez = geomagnetic[2];
float Hx = Ey*Az - Ez*Ay;
float Hy = Ez*Ax - Ex*Az;
float Hz = Ex*Ay - Ey*Ax;
final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
if (normH < 0.1f) {
// device is close to free fall (or in space?), or close to
// magnetic north pole. Typical values are > 100.
return false;
}
final float invH = 1.0f / normH;
Hx *= invH;
Hy *= invH;
Hz *= invH;
final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az);
Ax *= invA;
Ay *= invA;
Az *= invA;
final float Mx = Ay*Hz - Az*Hy;
final float My = Az*Hx - Ax*Hz;
final float Mz = Ax*Hy - Ay*Hx;
if (R != null) {
if (R.length == 9) {
R[0] = Hx; R[1] = Hy; R[2] = Hz;
R[3] = Mx; R[4] = My; R[5] = Mz;
R[6] = Ax; R[7] = Ay; R[8] = Az;
} else if (R.length == 16) {
R[0] = Hx; R[1] = Hy; R[2] = Hz; R[3] = 0;
R[4] = Mx; R[5] = My; R[6] = Mz; R[7] = 0;
R[8] = Ax; R[9] = Ay; R[10] = Az; R[11] = 0;
R[12] = 0; R[13] = 0; R[14] = 0; R[15] = 1;
}
}
if (I != null) {
// compute the inclination matrix by projecting the geomagnetic
// vector onto the Z (gravity) and X (horizontal component
// of geomagnetic vector) axes.
final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez);
final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE;
final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE;
if (I.length == 9) {
I[0] = 1; I[1] = 0; I[2] = 0;
I[3] = 0; I[4] = c; I[5] = s;
I[6] = 0; I[7] =-s; I[8] = c;
} else if (I.length == 16) {
I[0] = 1; I[1] = 0; I[2] = 0;
I[4] = 0; I[5] = c; I[6] = s;
I[8] = 0; I[9] =-s; I[10]= c;
I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
I[15] = 1;
}
}
return true;
| public static void | getRotationMatrixFromVector(float[] R, float[] rotationVector)Helper function to convert a rotation vector to a rotation matrix.
Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a
9 or 16 element rotation matrix in the array R. R must have length 9 or 16.
If R.length == 9, the following matrix is returned:
/ R[ 0] R[ 1] R[ 2] \
| R[ 3] R[ 4] R[ 5] |
\ R[ 6] R[ 7] R[ 8] /
If R.length == 16, the following matrix is returned:
/ R[ 0] R[ 1] R[ 2] 0 \
| R[ 4] R[ 5] R[ 6] 0 |
| R[ 8] R[ 9] R[10] 0 |
\ 0 0 0 1 /
float q0;
float q1 = rotationVector[0];
float q2 = rotationVector[1];
float q3 = rotationVector[2];
if (rotationVector.length >= 4) {
q0 = rotationVector[3];
} else {
q0 = 1 - q1*q1 - q2*q2 - q3*q3;
q0 = (q0 > 0) ? (float)Math.sqrt(q0) : 0;
}
float sq_q1 = 2 * q1 * q1;
float sq_q2 = 2 * q2 * q2;
float sq_q3 = 2 * q3 * q3;
float q1_q2 = 2 * q1 * q2;
float q3_q0 = 2 * q3 * q0;
float q1_q3 = 2 * q1 * q3;
float q2_q0 = 2 * q2 * q0;
float q2_q3 = 2 * q2 * q3;
float q1_q0 = 2 * q1 * q0;
if(R.length == 9) {
R[0] = 1 - sq_q2 - sq_q3;
R[1] = q1_q2 - q3_q0;
R[2] = q1_q3 + q2_q0;
R[3] = q1_q2 + q3_q0;
R[4] = 1 - sq_q1 - sq_q3;
R[5] = q2_q3 - q1_q0;
R[6] = q1_q3 - q2_q0;
R[7] = q2_q3 + q1_q0;
R[8] = 1 - sq_q1 - sq_q2;
} else if (R.length == 16) {
R[0] = 1 - sq_q2 - sq_q3;
R[1] = q1_q2 - q3_q0;
R[2] = q1_q3 + q2_q0;
R[3] = 0.0f;
R[4] = q1_q2 + q3_q0;
R[5] = 1 - sq_q1 - sq_q3;
R[6] = q2_q3 - q1_q0;
R[7] = 0.0f;
R[8] = q1_q3 - q2_q0;
R[9] = q2_q3 + q1_q0;
R[10] = 1 - sq_q1 - sq_q2;
R[11] = 0.0f;
R[12] = R[13] = R[14] = 0.0f;
R[15] = 1.0f;
}
| public java.util.List | getSensorList(int type)Use this method to get the list of available sensors of a certain type.
Make multiple calls to get sensors of different types or use
{@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all the
sensors.
NOTE: Both wake-up and non wake-up sensors matching the given type are
returned. Check {@link Sensor#isWakeUpSensor()} to know the wake-up properties
of the returned {@link Sensor}.
// cache the returned lists the first time
List<Sensor> list;
final List<Sensor> fullList = getFullSensorList();
synchronized (mSensorListByType) {
list = mSensorListByType.get(type);
if (list == null) {
if (type == Sensor.TYPE_ALL) {
list = fullList;
} else {
list = new ArrayList<Sensor>();
for (Sensor i : fullList) {
if (i.getType() == type)
list.add(i);
}
}
list = Collections.unmodifiableList(list);
mSensorListByType.append(type, list);
}
}
return list;
| public int | getSensors()
return getLegacySensorManager().getSensors();
| public boolean | registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs)Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
sensor at the given sampling frequency.
The events will be delivered to the provided {@code SensorEventListener} as soon as they are
available. To reduce the power consumption, applications can use
{@link #registerListener(SensorEventListener, Sensor, int, int)} instead and specify a
positive non-zero maximum reporting latency.
In the case of non-wake-up sensors, the events are only delivered while the Application
Processor (AP) is not in suspend mode. See {@link Sensor#isWakeUpSensor()} for more details.
To ensure delivery of events from non-wake-up sensors even when the screen is OFF, the
application registering to the sensor must hold a partial wake-lock to keep the AP awake,
otherwise some events might be lost while the AP is asleep. Note that although events might
be lost while the AP is asleep, the sensor will still consume power if it is not explicitly
deactivated by the application. Applications must unregister their {@code
SensorEventListener}s in their activity's {@code onPause()} method to avoid consuming power
while the device is inactive. See {@link #registerListener(SensorEventListener, Sensor, int,
int)} for more details on hardware FIFO (queueing) capabilities and when some sensor events
might be lost.
In the case of wake-up sensors, each event generated by the sensor will cause the AP to
wake-up, ensuring that each event can be delivered. Because of this, registering to a wake-up
sensor has very significant power implications. Call {@link Sensor#isWakeUpSensor()} to check
whether a sensor is a wake-up sensor. See
{@link #registerListener(SensorEventListener, Sensor, int, int)} for information on how to
reduce the power impact of registering to wake-up sensors.
Note: Don't use this method with one-shot trigger sensors such as
{@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use
{@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. Use
{@link Sensor#getReportingMode()} to obtain the reporting mode of a given sensor.
return registerListener(listener, sensor, samplingPeriodUs, null);
| public boolean | registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, int maxReportLatencyUs)Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
sensor at the given sampling frequency and the given maximum reporting latency.
This function is similar to {@link #registerListener(SensorEventListener, Sensor, int)} but
it allows events to stay temporarily in the hardware FIFO (queue) before being delivered. The
events can be stored in the hardware FIFO up to {@code maxReportLatencyUs} microseconds. Once
one of the events in the FIFO needs to be reported, all of the events in the FIFO are
reported sequentially. This means that some events will be reported before the maximum
reporting latency has elapsed.
When {@code maxReportLatencyUs} is 0, the call is equivalent to a call to
{@link #registerListener(SensorEventListener, Sensor, int)}, as it requires the events to be
delivered as soon as possible.
When {@code sensor.maxFifoEventCount()} is 0, the sensor does not use a FIFO, so the call
will also be equivalent to {@link #registerListener(SensorEventListener, Sensor, int)}.
Setting {@code maxReportLatencyUs} to a positive value allows to reduce the number of
interrupts the AP (Application Processor) receives, hence reducing power consumption, as the
AP can switch to a lower power state while the sensor is capturing the data. This is
especially important when registering to wake-up sensors, for which each interrupt causes the
AP to wake up if it was in suspend mode. See {@link Sensor#isWakeUpSensor()} for more
information on wake-up sensors.
Note: Don't use this method with one-shot trigger sensors such as
{@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use
{@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead.
int delay = getDelay(samplingPeriodUs);
return registerListenerImpl(listener, sensor, delay, null, maxReportLatencyUs, 0);
| public boolean | registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, android.os.Handler handler)Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
sensor. Events are delivered in continuous mode as soon as they are available. To reduce the
power consumption, applications can use
{@link #registerListener(SensorEventListener, Sensor, int, int)} instead and specify a
positive non-zero maximum reporting latency.
Note: Don't use this method with a one shot trigger sensor such as
{@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use
{@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead.
int delay = getDelay(samplingPeriodUs);
return registerListenerImpl(listener, sensor, delay, handler, 0, 0);
| public boolean | registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, int maxReportLatencyUs, android.os.Handler handler)Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
sensor at the given sampling frequency and the given maximum reporting latency.
int delayUs = getDelay(samplingPeriodUs);
return registerListenerImpl(listener, sensor, delayUs, handler, maxReportLatencyUs, 0);
| public boolean | registerListener(SensorListener listener, int sensors)Registers a listener for given sensors.
return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
| public boolean | registerListener(SensorListener listener, int sensors, int rate)Registers a SensorListener for given sensors.
return getLegacySensorManager().registerListener(listener, sensors, rate);
| protected abstract boolean | registerListenerImpl(SensorEventListener listener, Sensor sensor, int delayUs, android.os.Handler handler, int maxReportLatencyUs, int reservedFlags)
| public static boolean | remapCoordinateSystem(float[] inR, int X, int Y, float[] outR)
Rotates the supplied rotation matrix so it is expressed in a different
coordinate system. This is typically used when an application needs to
compute the three orientation angles of the device (see
{@link #getOrientation}) in a different coordinate system.
When the rotation matrix is used for drawing (for instance with OpenGL
ES), it usually doesn't need to be transformed by this function,
unless the screen is physically rotated, in which case you can use
{@link android.view.Display#getRotation() Display.getRotation()} to
retrieve the current rotation of the screen. Note that because the user
is generally free to rotate their screen, you often should consider the
rotation in deciding the parameters to use here.
Examples:
- Using the camera (Y axis along the camera's axis) for an augmented
reality application where the rotation angles are needed:
remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);
- Using the device as a mechanical compass when rotation is
{@link android.view.Surface#ROTATION_90 Surface.ROTATION_90}:
remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);
Beware of the above example. This call is needed only to account for a
rotation from its natural orientation when calculating the rotation
angles (see {@link #getOrientation}). If the rotation matrix is also used
for rendering, it may not need to be transformed, for instance if your
{@link android.app.Activity Activity} is running in landscape mode.
Since the resulting coordinate system is orthonormal, only two axes need
to be specified.
if (inR == outR) {
final float[] temp = mTempMatrix;
synchronized(temp) {
// we don't expect to have a lot of contention
if (remapCoordinateSystemImpl(inR, X, Y, temp)) {
final int size = outR.length;
for (int i=0 ; i<size ; i++)
outR[i] = temp[i];
return true;
}
}
}
return remapCoordinateSystemImpl(inR, X, Y, outR);
| private static boolean | remapCoordinateSystemImpl(float[] inR, int X, int Y, float[] outR)
/*
* X and Y define a rotation matrix 'r':
*
* (X==1)?((X&0x80)?-1:1):0 (X==2)?((X&0x80)?-1:1):0 (X==3)?((X&0x80)?-1:1):0
* (Y==1)?((Y&0x80)?-1:1):0 (Y==2)?((Y&0x80)?-1:1):0 (Y==3)?((X&0x80)?-1:1):0
* r[0] ^ r[1]
*
* where the 3rd line is the vector product of the first 2 lines
*
*/
final int length = outR.length;
if (inR.length != length)
return false; // invalid parameter
if ((X & 0x7C)!=0 || (Y & 0x7C)!=0)
return false; // invalid parameter
if (((X & 0x3)==0) || ((Y & 0x3)==0))
return false; // no axis specified
if ((X & 0x3) == (Y & 0x3))
return false; // same axis specified
// Z is "the other" axis, its sign is either +/- sign(X)*sign(Y)
// this can be calculated by exclusive-or'ing X and Y; except for
// the sign inversion (+/-) which is calculated below.
int Z = X ^ Y;
// extract the axis (remove the sign), offset in the range 0 to 2.
final int x = (X & 0x3)-1;
final int y = (Y & 0x3)-1;
final int z = (Z & 0x3)-1;
// compute the sign of Z (whether it needs to be inverted)
final int axis_y = (z+1)%3;
final int axis_z = (z+2)%3;
if (((x^axis_y)|(y^axis_z)) != 0)
Z ^= 0x80;
final boolean sx = (X>=0x80);
final boolean sy = (Y>=0x80);
final boolean sz = (Z>=0x80);
// Perform R * r, in avoiding actual muls and adds.
final int rowLength = ((length==16)?4:3);
for (int j=0 ; j<3 ; j++) {
final int offset = j*rowLength;
for (int i=0 ; i<3 ; i++) {
if (x==i) outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0];
if (y==i) outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1];
if (z==i) outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2];
}
}
if (length == 16) {
outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0;
outR[15] = 1;
}
return true;
| public boolean | requestTriggerSensor(TriggerEventListener listener, Sensor sensor)Requests receiving trigger events for a trigger sensor.
When the sensor detects a trigger event condition, such as significant motion in
the case of the {@link Sensor#TYPE_SIGNIFICANT_MOTION}, the provided trigger listener
will be invoked once and then its request to receive trigger events will be canceled.
To continue receiving trigger events, the application must request to receive trigger
events again.
return requestTriggerSensorImpl(listener, sensor);
| protected abstract boolean | requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor)
| public void | unregisterListener(SensorListener listener, int sensors)Unregisters a listener for the sensors with which it is registered.
getLegacySensorManager().unregisterListener(listener, sensors);
| public void | unregisterListener(SensorEventListener listener, Sensor sensor)Unregisters a listener for the sensors with which it is registered.
Note: Don't use this method with a one shot trigger sensor such as
{@link Sensor#TYPE_SIGNIFICANT_MOTION}.
Use {@link #cancelTriggerSensor(TriggerEventListener, Sensor)} instead.
if (listener == null || sensor == null) {
return;
}
unregisterListenerImpl(listener, sensor);
| public void | unregisterListener(SensorEventListener listener)Unregisters a listener for all sensors.
if (listener == null) {
return;
}
unregisterListenerImpl(listener, null);
| public void | unregisterListener(SensorListener listener)Unregisters a listener for all sensors.
unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW);
| protected abstract void | unregisterListenerImpl(SensorEventListener listener, Sensor sensor)
|
|