FileDocCategorySizeDatePackage
SensorManager.javaAPI DocAndroid 5.1 API64251Thu Mar 12 22:22:10 GMT 2015android.hardware

SensorManager

public 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) {
}
}
see
SensorEventListener
see
SensorEvent
see
Sensor

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_ORIENTATION
A constant describing an orientation sensor. See {@link android.hardware.SensorListener SensorListener} for more details.
public static final int
SENSOR_ACCELEROMETER
A constant describing an accelerometer. See {@link android.hardware.SensorListener SensorListener} for more details.
public static final int
SENSOR_TEMPERATURE
A constant describing a temperature sensor See {@link android.hardware.SensorListener SensorListener} for more details.
public static final int
SENSOR_MAGNETIC_FIELD
A constant describing a magnetic sensor See {@link android.hardware.SensorListener SensorListener} for more details.
public static final int
SENSOR_LIGHT
A constant describing an ambient light sensor See {@link android.hardware.SensorListener SensorListener} for more details.
public static final int
SENSOR_PROXIMITY
A constant describing a proximity sensor See {@link android.hardware.SensorListener SensorListener} for more details.
public static final int
SENSOR_TRICORDER
A constant describing a Tricorder See {@link android.hardware.SensorListener SensorListener} for more details.
public static final int
SENSOR_ORIENTATION_RAW
A constant describing an orientation sensor. See {@link android.hardware.SensorListener SensorListener} for more details.
public static final int
SENSOR_ALL
A constant that includes all sensors
public static final int
SENSOR_MIN
Smallest sensor ID
public static final int
SENSOR_MAX
Largest sensor ID
public static final int
DATA_X
Index of the X value in the array returned by {@link android.hardware.SensorListener#onSensorChanged}
public static final int
DATA_Y
Index of the Y value in the array returned by {@link android.hardware.SensorListener#onSensorChanged}
public static final int
DATA_Z
Index of the Z value in the array returned by {@link android.hardware.SensorListener#onSensorChanged}
public static final int
RAW_DATA_INDEX
Offset to the untransformed values in the array returned by {@link android.hardware.SensorListener#onSensorChanged}
public static final int
RAW_DATA_X
Index of the untransformed X value in the array returned by {@link android.hardware.SensorListener#onSensorChanged}
public static final int
RAW_DATA_Y
Index of the untransformed Y value in the array returned by {@link android.hardware.SensorListener#onSensorChanged}
public static final int
RAW_DATA_Z
Index of the untransformed Z value in the array returned by {@link android.hardware.SensorListener#onSensorChanged}
public static final float
STANDARD_GRAVITY
Standard gravity (g) on Earth. This value is equivalent to 1G
public static final float
GRAVITY_SUN
Sun's gravity in SI units (m/s^2)
public static final float
GRAVITY_MERCURY
Mercury's gravity in SI units (m/s^2)
public static final float
GRAVITY_VENUS
Venus' gravity in SI units (m/s^2)
public static final float
GRAVITY_EARTH
Earth's gravity in SI units (m/s^2)
public static final float
GRAVITY_MOON
The Moon's gravity in SI units (m/s^2)
public static final float
GRAVITY_MARS
Mars' gravity in SI units (m/s^2)
public static final float
GRAVITY_JUPITER
Jupiter's gravity in SI units (m/s^2)
public static final float
GRAVITY_SATURN
Saturn's gravity in SI units (m/s^2)
public static final float
GRAVITY_URANUS
Uranus' gravity in SI units (m/s^2)
public static final float
GRAVITY_NEPTUNE
Neptune's gravity in SI units (m/s^2)
public static final float
GRAVITY_PLUTO
Pluto's gravity in SI units (m/s^2)
public static final float
GRAVITY_DEATH_STAR_I
Gravity (estimate) on the first Death Star in Empire units (m/s^2)
public static final float
GRAVITY_THE_ISLAND
Gravity on the island
public static final float
MAGNETIC_FIELD_EARTH_MAX
Maximum magnetic field on Earth's surface
public static final float
MAGNETIC_FIELD_EARTH_MIN
Minimum magnetic field on Earth's surface
public static final float
PRESSURE_STANDARD_ATMOSPHERE
Standard atmosphere, or average sea-level pressure in hPa (millibar)
public static final float
LIGHT_SUNLIGHT_MAX
Maximum luminance of sunlight in lux
public static final float
LIGHT_SUNLIGHT
luminance of sunlight in lux
public static final float
LIGHT_SHADE
luminance in shade in lux
public static final float
LIGHT_OVERCAST
luminance under an overcast sky in lux
public static final float
LIGHT_SUNRISE
luminance at sunrise in lux
public static final float
LIGHT_CLOUDY
luminance under a cloudy sky in lux
public static final float
LIGHT_FULLMOON
luminance at night with full moon in lux
public static final float
LIGHT_NO_MOON
luminance at night with no moon in lux
public static final int
SENSOR_DELAY_FASTEST
get sensor data as fast as possible
public static final int
SENSOR_DELAY_GAME
rate suitable for games
public static final int
SENSOR_DELAY_UI
rate suitable for the user interface
public static final int
SENSOR_DELAY_NORMAL
rate (default) suitable for screen orientation changes
public static final int
SENSOR_STATUS_NO_CONTACT
The 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_UNRELIABLE
The 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_LOW
This sensor is reporting data with low accuracy, calibration with the environment is needed
public static final int
SENSOR_STATUS_ACCURACY_MEDIUM
This 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_HIGH
This sensor is reporting data with maximum accuracy
public static final int
AXIS_X
see {@link #remapCoordinateSystem}
public static final int
AXIS_Y
see {@link #remapCoordinateSystem}
public static final int
AXIS_Z
see {@link #remapCoordinateSystem}
public static final int
AXIS_MINUS_X
see {@link #remapCoordinateSystem}
public static final int
AXIS_MINUS_Y
see {@link #remapCoordinateSystem}
public static final int
AXIS_MINUS_Z
see {@link #remapCoordinateSystem}
Constructors Summary
public SensorManager()
{@hide}



          
      
    
Methods Summary
public booleancancelTriggerSensor(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.

param
listener The listener on which the {@link TriggerEventListener#onTrigger(TriggerEvent)} is delivered.It should be the same as the one used in {@link #requestTriggerSensor(TriggerEventListener, Sensor)}
param
sensor The sensor for which the trigger request should be canceled. If null, it cancels receiving trigger for all sensors associated with the listener.
return
true if successfully canceled.
throws
IllegalArgumentException when sensor is a trigger sensor.

        return cancelTriggerSensorImpl(listener, sensor, true);
    
protected abstract booleancancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor, boolean disable)

hide

public booleanflush(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.

param
listener A {@link android.hardware.SensorEventListener SensorEventListener} object which was previously used in a registerListener call.
return
true if the flush is initiated successfully on all the sensors registered for this listener, false if no sensor is previously registered for this listener or flush on one of the sensors fails.
see
#registerListener(SensorEventListener, Sensor, int, int)
throws
IllegalArgumentException when listener is null.

        return flushImpl(listener);
    
protected abstract booleanflushImpl(SensorEventListener listener)

hide

public static floatgetAltitude(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);

param
p0 pressure at sea level
param
p atmospheric pressure
return
Altitude in meters

        final float coef = 1.0f / 5.255f;
        return 44330.0f * (1.0f - (float)Math.pow(p/p0, coef));
    
public static voidgetAngleChange(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] /

param
R current rotation matrix
param
prevR previous rotation matrix
param
angleChange an an array of floats (z, x, and y) in which the angle change is stored

        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 SensorgetDefaultSensor(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}.

param
type of sensors requested
return
the default sensor matching the requested type if one exists and the application has the necessary permissions, or null otherwise.
see
#getSensorList(int)
see
Sensor

        // 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 SensorgetDefaultSensor(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.

param
type type of sensor requested
param
wakeUp flag to indicate whether the Sensor is a wake-up or non wake-up sensor.
return
the default sensor matching the requested type and wakeUp properties if one exists and the application has the necessary permissions, or null otherwise.
see
Sensor#isWakeUpSensor()

        List<Sensor> l = getSensorList(type);
        for (Sensor sensor : l) {
            if (sensor.isWakeUpSensor() == wakeUp)
                return sensor;
        }
        return null;
    
private static intgetDelay(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.ListgetFullSensorList()
Gets the full list of sensors that are available.

hide

public static floatgetInclination(float[] I)
Computes the geomagnetic inclination angle in radians from the inclination matrix I returned by {@link #getRotationMatrix}.

param
I inclination matrix see {@link #getRotationMatrix}.
return
The geomagnetic inclination angle in radians.
see
#getRotationMatrix(float[], float[], float[], float[])
see
#getOrientation(float[], float[])
see
GeomagneticField

        if (I.length == 9) {
            return (float)Math.atan2(I[5], I[4]);
        } else {
            return (float)Math.atan2(I[6], I[5]);
        }
    
private LegacySensorManagergetLegacySensorManager()

        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.

Inverted world coordinate-system diagram.

All three angles above are in radians and positive in the counter-clockwise direction.

param
R rotation matrix see {@link #getRotationMatrix}.
param
values an array of 3 floats to hold the result.
return
The array values passed as argument.
see
#getRotationMatrix(float[], float[], float[], float[])
see
GeomagneticField

        /*
         * 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 voidgetQuaternionFromVector(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]

param
rv the rotation vector to convert
param
Q an array of floats in which to store the computed quaternion

        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 booleangetRotationMatrix(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.

World coordinate-system diagram.


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.

param
R is an array of 9 floats holding the rotation matrix R when this function returns. R can be null.

param
I is an array of 9 floats holding the rotation matrix I when this function returns. I can be null.

param
gravity is an array of 3 floats containing the gravity vector expressed in the device's coordinate. You can simply use the {@link android.hardware.SensorEvent#values values} returned by a {@link android.hardware.SensorEvent SensorEvent} of a {@link android.hardware.Sensor Sensor} of type {@link android.hardware.Sensor#TYPE_ACCELEROMETER TYPE_ACCELEROMETER}.

param
geomagnetic is an array of 3 floats containing the geomagnetic vector expressed in the device's coordinate. You can simply use the {@link android.hardware.SensorEvent#values values} returned by a {@link android.hardware.SensorEvent SensorEvent} of a {@link android.hardware.Sensor Sensor} of type {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD TYPE_MAGNETIC_FIELD}.
return
true on success, false on failure (for instance, if the device is in free fall). On failure the output matrices are not modified.
see
#getInclination(float[])
see
#getOrientation(float[], float[])
see
#remapCoordinateSystem(float[], int, int, float[])

        // 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 voidgetRotationMatrixFromVector(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 /

param
rotationVector the rotation vector to convert
param
R an array of floats in which to store the rotation matrix


        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.ListgetSensorList(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}.

param
type of sensors requested
return
a list of sensors matching the asked type.
see
#getDefaultSensor(int)
see
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 intgetSensors()

return
available sensors.
deprecated
This method is deprecated, use {@link SensorManager#getSensorList(int)} instead

        return getLegacySensorManager().getSensors();
    
public booleanregisterListener(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.

param
listener A {@link android.hardware.SensorEventListener SensorEventListener} object.
param
sensor The {@link android.hardware.Sensor Sensor} to register to.
param
samplingPeriodUs The rate {@link android.hardware.SensorEvent sensor events} are delivered at. This is only a hint to the system. Events may be received faster or slower than the specified rate. Usually events are received faster. The value must be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} or, the desired delay between events in microseconds. Specifying the delay in microseconds only works from Android 2.3 (API level 9) onwards. For earlier releases, you must use one of the {@code SENSOR_DELAY_*} constants.
return
true if the sensor is supported and successfully enabled.
see
#registerListener(SensorEventListener, Sensor, int, Handler)
see
#unregisterListener(SensorEventListener)
see
#unregisterListener(SensorEventListener, Sensor)

        return registerListener(listener, sensor, samplingPeriodUs, null);
    
public booleanregisterListener(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.

param
listener A {@link android.hardware.SensorEventListener SensorEventListener} object that will receive the sensor events. If the application is interested in receiving flush complete notifications, it should register with {@link android.hardware.SensorEventListener SensorEventListener2} instead.
param
sensor The {@link android.hardware.Sensor Sensor} to register to.
param
samplingPeriodUs The desired delay between two consecutive events in microseconds. This is only a hint to the system. Events may be received faster or slower than the specified rate. Usually events are received faster. Can be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in microseconds.
param
maxReportLatencyUs Maximum time in microseconds that events can be delayed before being reported to the application. A large value allows reducing the power consumption associated with the sensor. If maxReportLatencyUs is set to zero, events are delivered as soon as they are available, which is equivalent to calling {@link #registerListener(SensorEventListener, Sensor, int)}.
return
true if the sensor is supported and successfully enabled.
see
#registerListener(SensorEventListener, Sensor, int)
see
#unregisterListener(SensorEventListener)
see
#flush(SensorEventListener)

        int delay = getDelay(samplingPeriodUs);
        return registerListenerImpl(listener, sensor, delay, null, maxReportLatencyUs, 0);
    
public booleanregisterListener(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.

param
listener A {@link android.hardware.SensorEventListener SensorEventListener} object.
param
sensor The {@link android.hardware.Sensor Sensor} to register to.
param
samplingPeriodUs The rate {@link android.hardware.SensorEvent sensor events} are delivered at. This is only a hint to the system. Events may be received faster or slower than the specified rate. Usually events are received faster. The value must be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} or, the desired delay between events in microseconds. Specifying the delay in microseconds only works from Android 2.3 (API level 9) onwards. For earlier releases, you must use one of the {@code SENSOR_DELAY_*} constants.
param
handler The {@link android.os.Handler Handler} the {@link android.hardware.SensorEvent sensor events} will be delivered to.
return
true if the sensor is supported and successfully enabled.
see
#registerListener(SensorEventListener, Sensor, int)
see
#unregisterListener(SensorEventListener)
see
#unregisterListener(SensorEventListener, Sensor)

        int delay = getDelay(samplingPeriodUs);
        return registerListenerImpl(listener, sensor, delay, handler, 0, 0);
    
public booleanregisterListener(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.

param
listener A {@link android.hardware.SensorEventListener SensorEventListener} object that will receive the sensor events. If the application is interested in receiving flush complete notifications, it should register with {@link android.hardware.SensorEventListener SensorEventListener2} instead.
param
sensor The {@link android.hardware.Sensor Sensor} to register to.
param
samplingPeriodUs The desired delay between two consecutive events in microseconds. This is only a hint to the system. Events may be received faster or slower than the specified rate. Usually events are received faster. Can be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in microseconds.
param
maxReportLatencyUs Maximum time in microseconds that events can be delayed before being reported to the application. A large value allows reducing the power consumption associated with the sensor. If maxReportLatencyUs is set to zero, events are delivered as soon as they are available, which is equivalent to calling {@link #registerListener(SensorEventListener, Sensor, int)}.
param
handler The {@link android.os.Handler Handler} the {@link android.hardware.SensorEvent sensor events} will be delivered to.
return
true if the sensor is supported and successfully enabled.
see
#registerListener(SensorEventListener, Sensor, int, int)

        int delayUs = getDelay(samplingPeriodUs);
        return registerListenerImpl(listener, sensor, delayUs, handler, maxReportLatencyUs, 0);
    
public booleanregisterListener(SensorListener listener, int sensors)
Registers a listener for given sensors.

deprecated
This method is deprecated, use {@link SensorManager#registerListener(SensorEventListener, Sensor, int)} instead.
param
listener sensor listener object
param
sensors a bit masks of the sensors to register to
return
true if the sensor is supported and successfully enabled

        return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
    
public booleanregisterListener(SensorListener listener, int sensors, int rate)
Registers a SensorListener for given sensors.

deprecated
This method is deprecated, use {@link SensorManager#registerListener(SensorEventListener, Sensor, int)} instead.
param
listener sensor listener object
param
sensors a bit masks of the sensors to register to
param
rate rate of events. This is only a hint to the system. events may be received faster or slower than the specified rate. Usually events are received faster. The value must be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
return
true if the sensor is supported and successfully enabled

        return getLegacySensorManager().registerListener(listener, sensors, rate);
    
protected abstract booleanregisterListenerImpl(SensorEventListener listener, Sensor sensor, int delayUs, android.os.Handler handler, int maxReportLatencyUs, int reservedFlags)

hide

public static booleanremapCoordinateSystem(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.

param
inR the rotation matrix to be transformed. Usually it is the matrix returned by {@link #getRotationMatrix}.
param
X defines on which world axis and direction the X axis of the device is mapped.
param
Y defines on which world axis and direction the Y axis of the device is mapped.
param
outR the transformed rotation matrix. inR and outR should not be the same array.
return
true on success. false if the input parameters are incorrect, for instance if X and Y define the same axis. Or if inR and outR don't have the same length.
see
#getRotationMatrix(float[], float[], float[], float[])

        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 booleanremapCoordinateSystemImpl(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 booleanrequestTriggerSensor(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.

param
listener The listener on which the {@link TriggerEventListener#onTrigger(TriggerEvent)} will be delivered.
param
sensor The sensor to be enabled.
return
true if the sensor was successfully enabled.
throws
IllegalArgumentException when sensor is null or not a trigger sensor.

        return requestTriggerSensorImpl(listener, sensor);
    
protected abstract booleanrequestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor)

hide

public voidunregisterListener(SensorListener listener, int sensors)
Unregisters a listener for the sensors with which it is registered.

deprecated
This method is deprecated, use {@link SensorManager#unregisterListener(SensorEventListener, Sensor)} instead.
param
listener a SensorListener object
param
sensors a bit masks of the sensors to unregister from

        getLegacySensorManager().unregisterListener(listener, sensors);
    
public voidunregisterListener(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.

param
listener a SensorEventListener object
param
sensor the sensor to unregister from
see
#unregisterListener(SensorEventListener)
see
#registerListener(SensorEventListener, Sensor, int)

        if (listener == null || sensor == null) {
            return;
        }

        unregisterListenerImpl(listener, sensor);
    
public voidunregisterListener(SensorEventListener listener)
Unregisters a listener for all sensors.

param
listener a SensorListener object
see
#unregisterListener(SensorEventListener, Sensor)
see
#registerListener(SensorEventListener, Sensor, int)

        if (listener == null) {
            return;
        }

        unregisterListenerImpl(listener, null);
    
public voidunregisterListener(SensorListener listener)
Unregisters a listener for all sensors.

deprecated
This method is deprecated, use {@link SensorManager#unregisterListener(SensorEventListener)} instead.
param
listener a SensorListener object

        unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW);
    
protected abstract voidunregisterListenerImpl(SensorEventListener listener, Sensor sensor)

hide