19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.hardware;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
204481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brownimport android.util.Log;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.SparseArray;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Collections;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
2843c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * <p>
2974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * SensorManager lets you access the device's {@link android.hardware.Sensor
3074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * sensors}. Get an instance of this class by calling
3174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * {@link android.content.Context#getSystemService(java.lang.String)
3274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * Context.getSystemService()} with the argument
3374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * {@link android.content.Context#SENSOR_SERVICE}.
3443c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * </p>
3543c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * <p>
3643c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * Always make sure to disable sensors you don't need, especially when your
3743c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * activity is paused. Failing to do so can drain the battery in just a few
3843c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * hours. Note that the system will <i>not</i> disable sensors automatically when
3943c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * the screen turns off.
4043c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * </p>
419a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh * <p class="note">
429a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh * Note: Don't use this mechanism with a Trigger Sensor, have a look
439a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh * at {@link TriggerEventListener}. {@link Sensor#TYPE_SIGNIFICANT_MOTION}
449a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh * is an example of a trigger sensor.
459a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh * </p>
460f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * <pre class="prettyprint">
470f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * public class SensorActivity extends Activity, implements SensorEventListener {
480f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     private final SensorManager mSensorManager;
490f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     private final Sensor mAccelerometer;
500f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
510f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     public SensorActivity() {
520f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *         mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
530f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *         mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
5443c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *     }
5543c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *
5643c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *     protected void onResume() {
5743c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *         super.onResume();
580f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *         mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
590f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     }
600f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
6143c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *     protected void onPause() {
6243c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *         super.onPause();
6343c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *         mSensorManager.unregisterListener(this);
6443c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *     }
6543c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *
660f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     public void onAccuracyChanged(Sensor sensor, int accuracy) {
670f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     }
680f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
6943c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *     public void onSensorChanged(SensorEvent event) {
700f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     }
710f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * }
720f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * </pre>
730f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
740f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * @see SensorEventListener
750f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * @see SensorEvent
760f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * @see Sensor
770f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
7925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownpublic abstract class SensorManager {
804481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown    /** @hide */
814481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown    protected static final String TAG = "SensorManager";
8225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
834481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown    private static final float[] mTempMatrix = new float[16];
8425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
8525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    // Cached lists of sensors by type.  Guarded by mSensorListByType.
8625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private final SparseArray<List<Sensor>> mSensorListByType =
8725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            new SparseArray<List<Sensor>>();
8825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
894481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown    // Legacy sensor manager implementation.  Guarded by mSensorListByType during initialization.
904481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown    private LegacySensorManager mLegacySensorManager;
914481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* NOTE: sensor IDs must be a power of 2 */
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an orientation sensor. See
9674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
970f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ORIENTATION = 1 << 0;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an accelerometer. See
10574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1060f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ACCELEROMETER = 1 << 1;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a temperature sensor See
11474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1150f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_TEMPERATURE = 1 << 2;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a magnetic sensor See
12374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1240f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_MAGNETIC_FIELD = 1 << 3;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an ambient light sensor See
13274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1330f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_LIGHT = 1 << 4;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a proximity sensor See
14174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1420f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_PROXIMITY = 1 << 5;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a Tricorder See
15074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1510f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_TRICORDER = 1 << 6;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an orientation sensor. See
15974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1600f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ORIENTATION_RAW = 1 << 7;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
16774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant that includes all sensors
1680f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1694a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1704a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ALL = 0x7F;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
17574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Smallest sensor ID
1760f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1774a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1784a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_MIN = SENSOR_ORIENTATION;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
18374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Largest sensor ID
1840f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1854a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1864a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_MAX = ((SENSOR_ALL + 1)>>1);
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
19274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the X value in the array returned by
1934a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
1940f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1954a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1964a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int DATA_X = 0;
19974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
20074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
20174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the Y value in the array returned by
2024a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2030f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2044a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2054a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int DATA_Y = 1;
20874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
20974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
21074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the Z value in the array returned by
2114a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2120f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2134a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2144a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int DATA_Z = 2;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
21974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Offset to the untransformed values in the array returned by
2204a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2210f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2224a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2234a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_INDEX = 3;
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
22874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the untransformed X value in the array returned by
2294a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2300f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2314a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2324a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_X = 3;
23574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
23674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
23774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the untransformed Y value in the array returned by
2384a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2390f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2404a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2414a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_Y = 4;
24474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
24574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
24674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the untransformed Z value in the array returned by
2474a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2480f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2494a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2504a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_Z = 5;
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Standard gravity (g) on Earth. This value is equivalent to 1G */
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float STANDARD_GRAVITY = 9.80665f;
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Sun's gravity in SI units (m/s^2) */
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_SUN             = 275.0f;
25974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Mercury's gravity in SI units (m/s^2) */
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MERCURY         = 3.70f;
26174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Venus' gravity in SI units (m/s^2) */
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_VENUS           = 8.87f;
26374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Earth's gravity in SI units (m/s^2) */
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_EARTH           = 9.80665f;
26574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** The Moon's gravity in SI units (m/s^2) */
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MOON            = 1.6f;
26774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Mars' gravity in SI units (m/s^2) */
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MARS            = 3.71f;
26974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Jupiter's gravity in SI units (m/s^2) */
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_JUPITER         = 23.12f;
27174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Saturn's gravity in SI units (m/s^2) */
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_SATURN          = 8.96f;
27374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Uranus' gravity in SI units (m/s^2) */
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_URANUS          = 8.69f;
27574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Neptune's gravity in SI units (m/s^2) */
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_NEPTUNE         = 11.0f;
27774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Pluto's gravity in SI units (m/s^2) */
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_PLUTO           = 0.6f;
27974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Gravity (estimate) on the first Death Star in Empire units (m/s^2) */
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_DEATH_STAR_I    = 0.000000353036145f;
28174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Gravity on the island */
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_THE_ISLAND      = 4.815162342f;
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Maximum magnetic field on Earth's surface */
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f;
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Minimum magnetic field on Earth's surface */
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2900f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian
29104d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian    /** Standard atmosphere, or average sea-level pressure in hPa (millibar) */
29204d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian    public static final float PRESSURE_STANDARD_ATMOSPHERE = 1013.25f;
29304d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian
29404d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian
29574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Maximum luminance of sunlight in lux */
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
29774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance of sunlight in lux */
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNLIGHT     = 110000.0f;
29974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance in shade in lux */
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SHADE        = 20000.0f;
30174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance under an overcast sky in lux */
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_OVERCAST     = 10000.0f;
30374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance at sunrise in lux */
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNRISE      = 400.0f;
30574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance under a cloudy sky in lux */
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_CLOUDY       = 100.0f;
30774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance at night with full moon in lux */
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_FULLMOON     = 0.25f;
30974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance at night with no moon in lux*/
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_NO_MOON      = 0.001f;
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3120f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** get sensor data as fast as possible */
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_FASTEST = 0;
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate suitable for games */
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_GAME = 1;
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate suitable for the user interface  */
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_UI = 2;
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate (default) suitable for screen orientation changes */
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_NORMAL = 3;
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
32374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
32474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * The values returned by this sensor cannot be trusted, calibration is
32574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * needed or the environment doesn't allow readings
32674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     */
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_UNRELIABLE = 0;
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
32974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
33074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * This sensor is reporting data with low accuracy, calibration with the
33174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * environment is needed
33274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     */
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_LOW = 1;
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
33574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
33674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * This sensor is reporting data with an average level of accuracy,
33774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * calibration with the environment may improve the readings
33874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     */
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2;
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** This sensor is reporting data with maximum accuracy */
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_HIGH = 3;
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_X = 1;
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_Y = 2;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_Z = 3;
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_X = AXIS_X | 0x80;
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_Y = AXIS_Y | 0x80;
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_Z = AXIS_Z | 0x80;
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
36125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    public SensorManager() {
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
36425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /**
36525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * Gets the full list of sensors that are available.
36625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * @hide
36725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     */
36825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    protected abstract List<Sensor> getFullSensorList();
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
37074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
37174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return available sensors.
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
37374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#getSensorList(int)} instead
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getSensors() {
3774481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown        return getLegacySensorManager().getSensors();
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
38174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Use this method to get the list of available sensors of a certain type.
38274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Make multiple calls to get sensors of different types or use
38374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all the
38474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * sensors.
3850f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
38674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param type
38774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        of sensors requested
3880f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a list of sensors matching the asked type.
3900f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
3910f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getDefaultSensor(int)
3920f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see Sensor
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<Sensor> getSensorList(int type) {
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // cache the returned lists the first time
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Sensor> list;
39725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        final List<Sensor> fullList = getFullSensorList();
39825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        synchronized (mSensorListByType) {
39925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            list = mSensorListByType.get(type);
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (list == null) {
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (type == Sensor.TYPE_ALL) {
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    list = fullList;
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    list = new ArrayList<Sensor>();
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (Sensor i : fullList) {
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (i.getType() == type)
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            list.add(i);
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                list = Collections.unmodifiableList(list);
41125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                mSensorListByType.append(type, list);
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return list;
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
41874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Use this method to get the default sensor for a given type. Note that the
41974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * returned sensor could be a composite sensor, and its data could be
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * averaged or filtered. If you need to access the raw sensors use
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link SensorManager#getSensorList(int) getSensorList}.
4220f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
42374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param type
42474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        of sensors requested
4250f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the default sensors matching the asked type.
4270f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
4280f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getSensorList(int)
4290f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see Sensor
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Sensor getDefaultSensor(int type) {
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO: need to be smarter, for now, just return the 1st sensor
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Sensor> l = getSensorList(type);
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return l.isEmpty() ? null : l.get(0);
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registers a listener for given sensors.
4390f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
44174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
44274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
4430f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
44474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
44574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        sensor listener object
4460f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
44774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensors
44874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a bit masks of the sensors to register to
4490f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
45074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> if the sensor is supported and successfully
45174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         enabled
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorListener listener, int sensors) {
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registers a SensorListener for given sensors.
4600f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
46274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
46374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
4640f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
46574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
46674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        sensor listener object
4670f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
46874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensors
46974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a bit masks of the sensors to register to
4700f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
47174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param rate
47274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        rate of events. This is only a hint to the system. events may be
47374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        received faster or slower than the specified rate. Usually events
47474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        are received faster. The value must be one of
47574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
47674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
4770f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
47874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> if the sensor is supported and successfully
47974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         enabled
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorListener listener, int sensors, int rate) {
4834481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown        return getLegacySensorManager().registerListener(listener, sensors, rate);
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4874481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown     * Unregisters a listener for all sensors.
4880f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
4904481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown     *             {@link SensorManager#unregisterListener(SensorEventListener)}
49174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
4920f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
49374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
49474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorListener object
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
4974481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown    public void unregisterListener(SensorListener listener) {
4984481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown        unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW);
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5024481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown     * Unregisters a listener for the sensors with which it is registered.
5030f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
5054481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown     *             {@link SensorManager#unregisterListener(SensorEventListener, Sensor)}
50674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
5070f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
50874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
50974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorListener object
5104481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown     *
5114481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown     * @param sensors
5124481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown     *        a bit masks of the sensors to unregister from
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
5154481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown    public void unregisterListener(SensorListener listener, int sensors) {
5164481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown        getLegacySensorManager().unregisterListener(listener, sensors);
51725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
51825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for the sensors with which it is registered.
5210f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
5229a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * <p class="note"></p>
5239a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * Note: Don't use this method with a one shot trigger sensor such as
5249a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * {@link Sensor#TYPE_SIGNIFICANT_MOTION}.
5259a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * Use {@link #cancelTriggerSensor(TriggerEventListener, Sensor)} instead.
5269a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * </p>
5279a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *
52874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
52974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorEventListener object
5300f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
53174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensor
53274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the sensor to unregister from
5330f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
5340f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener)
5350f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #registerListener(SensorEventListener, Sensor, int)
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorEventListener listener, Sensor sensor) {
53825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        if (listener == null || sensor == null) {
53925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return;
54025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
54125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
54225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        unregisterListenerImpl(listener, sensor);
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for all sensors.
5470f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
54874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
54974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorListener object
5500f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
5510f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener, Sensor)
5520f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #registerListener(SensorEventListener, Sensor, int)
5530f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorEventListener listener) {
55625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        if (listener == null) {
55725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return;
55825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
55925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
56025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        unregisterListenerImpl(listener, null);
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
56325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /** @hide */
56425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    protected abstract void unregisterListenerImpl(SensorEventListener listener, Sensor sensor);
56525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
56774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Registers a {@link android.hardware.SensorEventListener
56874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * SensorEventListener} for the given sensor.
5690f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
5709a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * <p class="note"></p>
5719a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * Note: Don't use this method with a one shot trigger sensor such as
5729a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * {@link Sensor#TYPE_SIGNIFICANT_MOTION}.
5739a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * Use {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead.
5749a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * </p>
5759a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *
57674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
57774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        A {@link android.hardware.SensorEventListener SensorEventListener}
57874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        object.
5790f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
58074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensor
58174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The {@link android.hardware.Sensor Sensor} to register to.
5820f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
583d405e0fc8274e8dc9ce8d6e084f6ad679fa6e6faAravind Akella     * @param rateUs
58474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The rate {@link android.hardware.SensorEvent sensor events} are
58574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        delivered at. This is only a hint to the system. Events may be
58674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        received faster or slower than the specified rate. Usually events
58774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        are received faster. The value must be one of
58874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
589050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian     *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}
590a230b3cb96f8c73ab8703fbe0773fa02155369cdkmccormick     *        or, the desired delay between events in microseconds.
591a230b3cb96f8c73ab8703fbe0773fa02155369cdkmccormick     *        Specifying the delay in microseconds only works from Android
592a230b3cb96f8c73ab8703fbe0773fa02155369cdkmccormick     *        2.3 (API level 9) onwards. For earlier releases, you must use
593a230b3cb96f8c73ab8703fbe0773fa02155369cdkmccormick     *        one of the {@code SENSOR_DELAY_*} constants.
5940f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
59574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> if the sensor is supported and successfully
59674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         enabled.
5970f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
5980f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #registerListener(SensorEventListener, Sensor, int, Handler)
5990f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener)
6000f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener, Sensor)
6010f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
603d405e0fc8274e8dc9ce8d6e084f6ad679fa6e6faAravind Akella    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs) {
604d405e0fc8274e8dc9ce8d6e084f6ad679fa6e6faAravind Akella        return registerListener(listener, sensor, rateUs, null);
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
608b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * Enables batch mode for a sensor with the given rate and maxBatchReportLatency. If the
609b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * underlying hardware does not support batch mode, this defaults to
610d405e0fc8274e8dc9ce8d6e084f6ad679fa6e6faAravind Akella     * {@link #registerListener(SensorEventListener, Sensor, int)} and other parameters are
611b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * ignored. In non-batch mode, all sensor events must be reported as soon as they are detected.
612b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * While in batch mode, sensor events do not need to be reported as soon as they are detected.
613b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * They can be temporarily stored in batches and reported in batches, as long as no event is
614b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * delayed by more than "maxBatchReportLatency" microseconds. That is, all events since the
615b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * previous batch are recorded and returned all at once. This allows to reduce the amount of
616b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * interrupts sent to the SoC, and allows the SoC to switch to a lower power state (Idle) while
617b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * the sensor is capturing and batching data.
618b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * <p>
619b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * Registering to a sensor in batch mode will not prevent the SoC from going to suspend mode. In
620b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * this case, the sensor will continue to gather events and store it in a hardware FIFO. If the
621b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * FIFO gets full before the AP wakes up again, some events will be lost, as the older events
622b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * get overwritten by new events in the hardware FIFO. This can be avoided by holding a wake
623b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * lock. If the application holds a wake lock, the SoC will not go to suspend mode, so no events
624b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * will be lost, as the events will be reported before the FIFO gets full.
625b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * </p>
626b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * <p>
627b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * Batching is always best effort. If a different application requests updates in continuous
628b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * mode, this application will also get events in continuous mode. Batch mode updates can be
629b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * unregistered by calling {@link #unregisterListener(SensorEventListener)}.
630b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * </p>
631b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * <p class="note">
632b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * </p>
633b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * Note: Don't use this method with a one shot trigger sensor such as
634b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use
635b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p>
636b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     *
637b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object
6384bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *            that will receive the sensor events. If the application is interested in receiving
6394bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *            flush complete notifications, it should register with
6404bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *            {@link android.hardware.SensorEventListener SensorEventListener2} instead.
641b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
642d405e0fc8274e8dc9ce8d6e084f6ad679fa6e6faAravind Akella     * @param rateUs The desired delay between two consecutive events in microseconds. This is only
643d405e0fc8274e8dc9ce8d6e084f6ad679fa6e6faAravind Akella     *            a hint to the system. Events may be received faster or slower than the specified
644b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     *            rate. Usually events are received faster. Can be one of
645b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     *            {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
646b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     *            {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in
647b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     *            microseconds.
648d405e0fc8274e8dc9ce8d6e084f6ad679fa6e6faAravind Akella     * @param maxBatchReportLatencyUs An event in the batch can be delayed by at most
649b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     *            maxBatchReportLatency microseconds. More events can be batched if this value is
650b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     *            large. If this is set to zero, batch mode is disabled and events are delivered in
651b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     *            continuous mode as soon as they are available which is equivalent to calling
652b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     *            {@link #registerListener(SensorEventListener, Sensor, int)}.
6534bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * @return <code>true</code> if batch mode is successfully enabled for this sensor,
6544bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *         <code>false</code> otherwise.
655b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * @see #registerListener(SensorEventListener, Sensor, int)
656b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * @see #unregisterListener(SensorEventListener)
6574bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * @see #flush(SensorEventListener)
658b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     */
659b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs,
6604bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella            int maxBatchReportLatencyUs) {
661b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        int delay = getDelay(rateUs);
6624bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella        return registerListenerImpl(listener, sensor, delay, null, maxBatchReportLatencyUs, 0);
663b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    }
664b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella
665b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    /**
666b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
667d405e0fc8274e8dc9ce8d6e084f6ad679fa6e6faAravind Akella     * sensor. Events are delivered in continuous mode as soon as they are available. To reduce the
6684bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * battery usage, use {@link #registerListener(SensorEventListener, Sensor, int, int)} which
6694bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * enables batch mode for the sensor.
6700f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
6719a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * <p class="note"></p>
6729a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * Note: Don't use this method with a one shot trigger sensor such as
6739a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * {@link Sensor#TYPE_SIGNIFICANT_MOTION}.
6749a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * Use {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead.
6759a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * </p>
6769a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *
67774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
67874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        A {@link android.hardware.SensorEventListener SensorEventListener}
67974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        object.
6800f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
68174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensor
68274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The {@link android.hardware.Sensor Sensor} to register to.
6830f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
684d405e0fc8274e8dc9ce8d6e084f6ad679fa6e6faAravind Akella     * @param rateUs
68574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The rate {@link android.hardware.SensorEvent sensor events} are
68674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        delivered at. This is only a hint to the system. Events may be
68774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        received faster or slower than the specified rate. Usually events
68874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        are received faster. The value must be one of
68974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
69074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
691a230b3cb96f8c73ab8703fbe0773fa02155369cdkmccormick     *        or, the desired delay between events in microseconds.
692a230b3cb96f8c73ab8703fbe0773fa02155369cdkmccormick     *        Specifying the delay in microseconds only works from Android
693a230b3cb96f8c73ab8703fbe0773fa02155369cdkmccormick     *        2.3 (API level 9) onwards. For earlier releases, you must use
694a230b3cb96f8c73ab8703fbe0773fa02155369cdkmccormick     *        one of the {@code SENSOR_DELAY_*} constants.
6950f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
69674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param handler
69774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The {@link android.os.Handler Handler} the
69874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent sensor events} will be
69974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        delivered to.
7000f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
7014bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * @return <code>true</code> if the sensor is supported and successfully enabled.
7020f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
7030f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #registerListener(SensorEventListener, Sensor, int)
7040f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener)
7050f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener, Sensor)
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
707d405e0fc8274e8dc9ce8d6e084f6ad679fa6e6faAravind Akella    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs,
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Handler handler) {
709d405e0fc8274e8dc9ce8d6e084f6ad679fa6e6faAravind Akella        int delay = getDelay(rateUs);
7104bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella        return registerListenerImpl(listener, sensor, delay, handler, 0, 0);
711b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    }
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
713b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    /**
714b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     * Enables batch mode for a sensor with the given rate and maxBatchReportLatency.
7154bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object
7164bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *            that will receive the sensor events. If the application is interested in receiving
7174bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *            flush complete notifications, it should register with
7184bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *            {@link android.hardware.SensorEventListener SensorEventListener2} instead.
7194bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
7204bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * @param rateUs The desired delay between two consecutive events in microseconds. This is only
7214bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *            a hint to the system. Events may be received faster or slower than the specified
7224bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *            rate. Usually events are received faster. Can be one of
7234bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *            {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
7244bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *            {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in
7254bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *            microseconds.
7264bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * @param maxBatchReportLatencyUs An event in the batch can be delayed by at most
7274bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *            maxBatchReportLatency microseconds. More events can be batched if this value is
7284bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *            large. If this is set to zero, batch mode is disabled and events are delivered in
7294bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *            continuous mode as soon as they are available which is equivalent to calling
7304bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *            {@link #registerListener(SensorEventListener, Sensor, int)}.
7314bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * @param handler The {@link android.os.Handler Handler} the
7324bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *        {@link android.hardware.SensorEvent sensor events} will be delivered to.
733b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     *
7344bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * @return <code>true</code> if batch mode is successfully enabled for this sensor,
7354bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *         <code>false</code> otherwise.
7364bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * @see #registerListener(SensorEventListener, Sensor, int, int)
737b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     */
738b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs,
7394bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella            int maxBatchReportLatencyUs, Handler handler) {
740b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        int delayUs = getDelay(rateUs);
7414bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella        return registerListenerImpl(listener, sensor, delayUs, handler, maxBatchReportLatencyUs, 0);
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
74425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /** @hide */
74525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
7464bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella            int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags);
747b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella
748b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella
749b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    /**
7504bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * Flushes the batch FIFO of all the sensors registered for this listener. If there are events
7514bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * in the FIFO of the sensor, they are returned as if the batch timeout in the FIFO of the
7524bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * sensors had expired. Events are returned in the usual way through the SensorEventListener.
7534bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * This call doesn't affect the batch timeout for this sensor. This call is asynchronous and
7544bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * returns immediately.
7554bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * {@link android.hardware.SensorEventListener2#onFlushCompleted onFlushCompleted} is called
7564bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * after all the events in the batch at the time of calling this method have been delivered
7574bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * successfully. If the hardware doesn't support flush, it still returns true and a trivial
7584bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * flush complete event is sent after the current event for all the clients registered for this
7594bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * sensor.
7604bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *
7614bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object
7624bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *        which was previously used in a registerListener call.
7634bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * @return <code>true</code> if the flush is initiated successfully on all the sensors
7644bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *         registered for this listener, false if no sensor is previously registered for this
7654bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     *         listener or flush on one of the sensors fails.
7664bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * @see #registerListener(SensorEventListener, Sensor, int, int)
7674bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     * @throws IllegalArgumentException when listener is null.
7684bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella     */
7694bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella    public boolean flush(SensorEventListener listener) {
7704bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella        return flushImpl(listener);
771b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    }
772b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella
773b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    /** @hide */
7744bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella    protected abstract boolean flushImpl(SensorEventListener listener);
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
77774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
77874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Computes the inclination matrix <b>I</b> as well as the rotation matrix
77974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>R</b> transforming a vector from the device coordinate system to the
78074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * world's coordinate system which is defined as a direct orthonormal basis,
78174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * where:
78274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
7830f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
78474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the ground at the device's current location and roughly points East).</li>
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Y is tangential to the ground at the device's current location and
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * points towards the magnetic North Pole.</li>
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Z points towards the sky and is perpendicular to the ground.</li>
79074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
7910f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
7920f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * <p>
7930f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * <center><img src="../../../images/axis_globe.png"
794f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * alt="World coordinate-system diagram." border="0" /></center>
7950f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * </p>
7960f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
79974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
80074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * By definition:
80174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
80274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * [0 0 g] = <b>R</b> * <b>gravity</b> (g = magnitude of gravity)
80374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
80474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * [0 m 0] = <b>I</b> * <b>R</b> * <b>geomagnetic</b> (m = magnitude of
80574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * geomagnetic field)
80674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
80774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>R</b> is the identity matrix when the device is aligned with the
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * world's coordinate system, that is, when the device's X axis points
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * toward East, the Y axis points to the North Pole and the device is facing
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the sky.
8110f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
81274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
81374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>I</b> is a rotation matrix transforming the geomagnetic vector into
81474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * the same coordinate space as gravity (the world's coordinate space).
81574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>I</b> is a simple rotation around the X axis. The inclination angle in
81674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * radians can be computed with {@link #getInclination}.
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
8180f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
81974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
82074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Each matrix is returned either as a 3x3 or 4x4 row-major matrix depending
82174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * on the length of the passed array:
82274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
82374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <u>If the array length is 16:</u>
8240f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]   M[ 3]  \
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 4]   M[ 5]   M[ 6]   M[ 7]  |
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 8]   M[ 9]   M[10]   M[11]  |
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \  M[12]   M[13]   M[14]   M[15]  /
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
8310f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
83274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * This matrix is ready to be used by OpenGL ES's
83374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link javax.microedition.khronos.opengles.GL10#glLoadMatrixf(float[], int)
83474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * glLoadMatrixf(float[], int)}.
83574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
83674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Note that because OpenGL matrices are column-major matrices you must
83774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * transpose the matrix before using it. However, since the matrix is a
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * rotation matrix, its transpose is also its inverse, conveniently, it is
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * often the inverse of the rotation that is needed for rendering; it can
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * therefore be used with OpenGL ES directly.
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Also note that the returned matrices always have this form:
8430f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]   0  \
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 4]   M[ 5]   M[ 6]   0  |
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 8]   M[ 9]   M[10]   0  |
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \      0       0       0   1  /
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
8500f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
85174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
85274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <u>If the array length is 9:</u>
8530f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]  \
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 3]   M[ 4]   M[ 5]  |
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \  M[ 6]   M[ 7]   M[ 8]  /
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
8590f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
86174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
86274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * The inverse of each matrix can be computed easily by taking its
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * transpose.
8640f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
86574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
86674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * The matrices returned by this function are meaningful only when the
86774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * device is not free-falling and it is not close to the magnetic north. If
86874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * the device is accelerating, or placed into a strong magnetic field, the
86974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * returned matrices may be inaccurate.
8700f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
87174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param R
87274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 9 floats holding the rotation matrix <b>R</b> when
87374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        this function returns. R can be null.
87474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        <p>
8750f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
87674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param I
87774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 9 floats holding the rotation matrix <b>I</b> when
87874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        this function returns. I can be null.
87974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        <p>
8800f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
88174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param gravity
88274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 3 floats containing the gravity vector expressed in
88374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the device's coordinate. You can simply use the
88474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent#values values} returned by a
88574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent SensorEvent} of a
88674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor Sensor} of type
88774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor#TYPE_ACCELEROMETER
88874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        TYPE_ACCELEROMETER}.
88974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        <p>
8900f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
89174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param geomagnetic
89274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 3 floats containing the geomagnetic vector
89374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        expressed in the device's coordinate. You can simply use the
89474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent#values values} returned by a
89574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent SensorEvent} of a
89674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor Sensor} of type
89774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD
89874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        TYPE_MAGNETIC_FIELD}.
8990f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
90074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> on success, <code>false</code> on failure (for
90174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         instance, if the device is in free fall). On failure the output
90274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         matrices are not modified.
9030f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9040f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getInclination(float[])
9050f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getOrientation(float[], float[])
9060f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #remapCoordinateSystem(float[], int, int, float[])
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean getRotationMatrix(float[] R, float[] I,
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] gravity, float[] geomagnetic) {
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO: move this to native code for efficiency
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Ax = gravity[0];
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Ay = gravity[1];
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Az = gravity[2];
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ex = geomagnetic[0];
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ey = geomagnetic[1];
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ez = geomagnetic[2];
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hx = Ey*Az - Ez*Ay;
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hy = Ez*Ax - Ex*Az;
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hz = Ex*Ay - Ey*Ax;
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (normH < 0.1f) {
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // device is close to free fall (or in space?), or close to
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // magnetic north pole. Typical values are  > 100.
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float invH = 1.0f / normH;
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hx *= invH;
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hy *= invH;
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hz *= invH;
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az);
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Ax *= invA;
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Ay *= invA;
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Az *= invA;
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Mx = Ay*Hz - Az*Hy;
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float My = Az*Hx - Ax*Hz;
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Mz = Ax*Hy - Ay*Hx;
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (R != null) {
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (R.length == 9) {
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[0] = Hx;     R[1] = Hy;     R[2] = Hz;
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[3] = Mx;     R[4] = My;     R[5] = Mz;
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[6] = Ax;     R[7] = Ay;     R[8] = Az;
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (R.length == 16) {
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[0]  = Hx;    R[1]  = Hy;    R[2]  = Hz;   R[3]  = 0;
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[4]  = Mx;    R[5]  = My;    R[6]  = Mz;   R[7]  = 0;
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[8]  = Ax;    R[9]  = Ay;    R[10] = Az;   R[11] = 0;
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[12] = 0;     R[13] = 0;     R[14] = 0;    R[15] = 1;
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (I != null) {
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // compute the inclination matrix by projecting the geomagnetic
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // vector onto the Z (gravity) and X (horizontal component
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // of geomagnetic vector) axes.
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez);
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE;
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE;
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (I.length == 9) {
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[0] = 1;     I[1] = 0;     I[2] = 0;
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[3] = 0;     I[4] = c;     I[5] = s;
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[6] = 0;     I[7] =-s;     I[8] = c;
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (I.length == 16) {
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[0] = 1;     I[1] = 0;     I[2] = 0;
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[4] = 0;     I[5] = c;     I[6] = s;
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[8] = 0;     I[9] =-s;     I[10]= c;
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[15] = 1;
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Computes the geomagnetic inclination angle in radians from the
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * inclination matrix <b>I</b> returned by {@link #getRotationMatrix}.
9750f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
97674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param I
97774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        inclination matrix see {@link #getRotationMatrix}.
9780f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The geomagnetic inclination angle in radians.
9800f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9810f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getRotationMatrix(float[], float[], float[], float[])
9820f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getOrientation(float[], float[])
9830f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see GeomagneticField
9840f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static float getInclination(float[] I) {
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (I.length == 9) {
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (float)Math.atan2(I[5], I[4]);
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9900f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian            return (float)Math.atan2(I[6], I[5]);
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
99574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
99674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Rotates the supplied rotation matrix so it is expressed in a different
99774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * coordinate system. This is typically used when an application needs to
99874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * compute the three orientation angles of the device (see
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #getOrientation}) in a different coordinate system.
100074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
10010f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
100274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
100374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * When the rotation matrix is used for drawing (for instance with OpenGL
100474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * ES), it usually <b>doesn't need</b> to be transformed by this function,
100574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * unless the screen is physically rotated, in which case you can use
100674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.view.Display#getRotation() Display.getRotation()} to
100774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * retrieve the current rotation of the screen. Note that because the user
100874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * is generally free to rotate their screen, you often should consider the
100974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * rotation in deciding the parameters to use here.
101074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
10110f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
101274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
101374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <u>Examples:</u>
101474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
10150f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
101674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
101774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <li>Using the camera (Y axis along the camera's axis) for an augmented
101874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * reality application where the rotation angles are needed:</li>
10190f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
102074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
102174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
102274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <code>remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);</code>
102374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
102474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
10250f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
10265cb70b54156fb305d579a1cc167424c8705bfdf7Dianne Hackborn     * <li>Using the device as a mechanical compass when rotation is
102774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.view.Surface#ROTATION_90 Surface.ROTATION_90}:</li>
10280f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
102974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
103074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
103174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <code>remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);</code>
103274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
103374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
10340f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
103574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Beware of the above example. This call is needed only to account for a
103674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * rotation from its natural orientation when calculating the rotation
103774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * angles (see {@link #getOrientation}). If the rotation matrix is also used
103874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * for rendering, it may not need to be transformed, for instance if your
103974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.app.Activity Activity} is running in landscape mode.
104074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
10410f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
104274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
104374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Since the resulting coordinate system is orthonormal, only two axes need
104474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * to be specified.
10450f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
104674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param inR
104774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the rotation matrix to be transformed. Usually it is the matrix
104874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        returned by {@link #getRotationMatrix}.
10490f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
105074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param X
105174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        defines on which world axis and direction the X axis of the device
105274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is mapped.
10530f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
105474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param Y
105574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        defines on which world axis and direction the Y axis of the device
105674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is mapped.
10570f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
105874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param outR
105974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the transformed rotation matrix. inR and outR can be the same
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        array, but it is not recommended for performance reason.
10610f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
106274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> on success. <code>false</code> if the input
106374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         parameters are incorrect, for instance if X and Y define the same
106474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         axis. Or if inR and outR don't have the same length.
10650f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
10660f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getRotationMatrix(float[], float[], float[], float[])
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean remapCoordinateSystem(float[] inR, int X, int Y,
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] outR)
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (inR == outR) {
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float[] temp = mTempMatrix;
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(temp) {
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // we don't expect to have a lot of contention
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (remapCoordinateSystemImpl(inR, X, Y, temp)) {
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final int size = outR.length;
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (int i=0 ; i<size ; i++)
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        outR[i] = temp[i];
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return true;
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return remapCoordinateSystemImpl(inR, X, Y, outR);
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y,
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] outR)
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * X and Y define a rotation matrix 'r':
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *  (X==1)?((X&0x80)?-1:1):0    (X==2)?((X&0x80)?-1:1):0    (X==3)?((X&0x80)?-1:1):0
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *  (Y==1)?((Y&0x80)?-1:1):0    (Y==2)?((Y&0x80)?-1:1):0    (Y==3)?((X&0x80)?-1:1):0
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *                              r[0] ^ r[1]
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * where the 3rd line is the vector product of the first 2 lines
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int length = outR.length;
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (inR.length != length)
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // invalid parameter
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((X & 0x7C)!=0 || (Y & 0x7C)!=0)
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // invalid parameter
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (((X & 0x3)==0) || ((Y & 0x3)==0))
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // no axis specified
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((X & 0x3) == (Y & 0x3))
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // same axis specified
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y)
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // this can be calculated by exclusive-or'ing X and Y; except for
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the sign inversion (+/-) which is calculated below.
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int Z = X ^ Y;
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // extract the axis (remove the sign), offset in the range 0 to 2.
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int x = (X & 0x3)-1;
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int y = (Y & 0x3)-1;
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int z = (Z & 0x3)-1;
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // compute the sign of Z (whether it needs to be inverted)
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int axis_y = (z+1)%3;
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int axis_z = (z+2)%3;
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (((x^axis_y)|(y^axis_z)) != 0)
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Z ^= 0x80;
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sx = (X>=0x80);
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sy = (Y>=0x80);
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sz = (Z>=0x80);
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Perform R * r, in avoiding actual muls and adds.
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int rowLength = ((length==16)?4:3);
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int j=0 ; j<3 ; j++) {
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int offset = j*rowLength;
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0 ; i<3 ; i++) {
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (x==i)   outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0];
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (y==i)   outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1];
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (z==i)   outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2];
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (length == 16) {
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0;
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            outR[15] = 1;
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Computes the device's orientation based on the rotation matrix.
115074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
115174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * When it returns, the array values is filled with the result:
115274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[0]: <i>azimuth</i>, rotation around the Z axis.</li>
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[1]: <i>pitch</i>, rotation around the X axis.</li>
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[2]: <i>roll</i>, rotation around the Y axis.</li>
115674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
1157f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * <p>The reference coordinate-system used is different from the world
1158f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * coordinate-system defined for the rotation matrix:</p>
1159f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * <ul>
1160f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
1161f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * the ground at the device's current location and roughly points West).</li>
1162f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * <li>Y is tangential to the ground at the device's current location and
1163f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * points towards the magnetic North Pole.</li>
1164f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * <li>Z points towards the center of the Earth and is perpendicular to the ground.</li>
1165f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * </ul>
1166f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     *
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11680871ee0c6f43a7201ce49a66211c1c850eabeb6bDirk Dougherty     * <center><img src="../../../images/axis_globe_inverted.png"
1169f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * alt="Inverted world coordinate-system diagram." border="0" /></center>
11700f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * </p>
11710f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * <p>
1172210fc914db37b3cf77ebb3bf75b0b509a1ecb07cMathias Agopian     * All three angles above are in <b>radians</b> and <b>positive</b> in the
1173210fc914db37b3cf77ebb3bf75b0b509a1ecb07cMathias Agopian     * <b>counter-clockwise</b> direction.
1174b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     *
117574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param R
117674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        rotation matrix see {@link #getRotationMatrix}.
1177b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     *
117874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param values
117974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        an array of 3 floats to hold the result.
1180b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     *
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The array values passed as argument.
1182b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella     *
11830f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getRotationMatrix(float[], float[], float[], float[])
11840f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see GeomagneticField
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
118604d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian    public static float[] getOrientation(float[] R, float values[]) {
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * 4x4 (length=16) case:
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   /  R[ 0]   R[ 1]   R[ 2]   0  \
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 4]   R[ 5]   R[ 6]   0  |
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 8]   R[ 9]   R[10]   0  |
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   \      0       0       0   1  /
11930f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian         *
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * 3x3 (length=9) case:
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   /  R[ 0]   R[ 1]   R[ 2]  \
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 3]   R[ 4]   R[ 5]  |
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   \  R[ 6]   R[ 7]   R[ 8]  /
11980f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian         *
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (R.length == 9) {
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = (float)Math.atan2(R[1], R[4]);
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = (float)Math.asin(-R[7]);
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = (float)Math.atan2(-R[6], R[8]);
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = (float)Math.atan2(R[1], R[5]);
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = (float)Math.asin(-R[9]);
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = (float)Math.atan2(-R[8], R[10]);
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return values;
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
121304d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * Computes the Altitude in meters from the atmospheric pressure and the
121404d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * pressure at sea level.
121504d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * <p>
121604d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * Typically the atmospheric pressure is read from a
121704d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * {@link Sensor#TYPE_PRESSURE} sensor. The pressure at sea level must be
121804d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * known, usually it can be retrieved from airport databases in the
1219a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * vicinity. If unknown, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE}
1220a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * as an approximation, but absolute altitudes won't be accurate.
1221a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * </p>
1222a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * <p>
1223a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * To calculate altitude differences, you must calculate the difference
1224a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * between the altitudes at both points. If you don't know the altitude
1225a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * as sea level, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE} instead,
1226a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * which will give good results considering the range of pressure typically
1227a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * involved.
1228a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * </p>
1229a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * <p>
1230a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * <code><ul>
1231a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     *  float altitude_difference =
1232a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     *      getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point2)
1233a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     *      - getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point1);
1234a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * </ul></code>
123504d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * </p>
123604d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     *
123704d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * @param p0 pressure at sea level
123804d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * @param p atmospheric pressure
123904d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * @return Altitude in meters
124004d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     */
124125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    public static float getAltitude(float p0, float p) {
124204d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian        final float coef = 1.0f / 5.255f;
124304d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian        return 44330.0f * (1.0f - (float)Math.pow(p/p0, coef));
124404d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian    }
124504d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian
124625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /** Helper function to compute the angle change between two rotation matrices.
124725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  Given a current rotation matrix (R) and a previous rotation matrix
1248fb8909709979b883ff95b21db3e32666788637b4Mathias Agopian     *  (prevR) computes the rotation around the z,x, and y axes which
124925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  transforms prevR to R.
1250fb8909709979b883ff95b21db3e32666788637b4Mathias Agopian     *  outputs a 3 element vector containing the z,x, and y angle
125125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  change at indexes 0, 1, and 2 respectively.
125225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * <p> Each input matrix is either as a 3x3 or 4x4 row-major matrix
125325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * depending on the length of the passed array:
125425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * <p>If the array length is 9, then the array elements represent this matrix
125525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * <pre>
125625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   /  R[ 0]   R[ 1]   R[ 2]   \
125725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   |  R[ 3]   R[ 4]   R[ 5]   |
125825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   \  R[ 6]   R[ 7]   R[ 8]   /
125925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *</pre>
126025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * <p>If the array length is 16, then the array elements represent this matrix
126125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * <pre>
126225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   /  R[ 0]   R[ 1]   R[ 2]   R[ 3]  \
126325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   |  R[ 4]   R[ 5]   R[ 6]   R[ 7]  |
126425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   |  R[ 8]   R[ 9]   R[10]   R[11]  |
126525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   \  R[12]   R[13]   R[14]   R[15]  /
126625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *</pre>
126725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * @param R current rotation matrix
126825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * @param prevR previous rotation matrix
1269fb8909709979b883ff95b21db3e32666788637b4Mathias Agopian     * @param angleChange an an array of floats (z, x, and y) in which the angle change is stored
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
127225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    public static void getAngleChange( float[] angleChange, float[] R, float[] prevR) {
127325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float rd1=0,rd4=0, rd6=0,rd7=0, rd8=0;
127425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float ri0=0,ri1=0,ri2=0,ri3=0,ri4=0,ri5=0,ri6=0,ri7=0,ri8=0;
127525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float pri0=0, pri1=0, pri2=0, pri3=0, pri4=0, pri5=0, pri6=0, pri7=0, pri8=0;
127625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
127725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        if(R.length == 9) {
127825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri0 = R[0];
127925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri1 = R[1];
128025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri2 = R[2];
128125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri3 = R[3];
128225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri4 = R[4];
128325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri5 = R[5];
128425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri6 = R[6];
128525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri7 = R[7];
128625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri8 = R[8];
128725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        } else if(R.length == 16) {
128825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri0 = R[0];
128925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri1 = R[1];
129025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri2 = R[2];
129125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri3 = R[4];
129225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri4 = R[5];
129325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri5 = R[6];
129425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri6 = R[8];
129525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri7 = R[9];
129625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri8 = R[10];
129725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
129825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
129925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        if(prevR.length == 9) {
130025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri0 = prevR[0];
130125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri1 = prevR[1];
130225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri2 = prevR[2];
130325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri3 = prevR[3];
130425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri4 = prevR[4];
130525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri5 = prevR[5];
130625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri6 = prevR[6];
130725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri7 = prevR[7];
130825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri8 = prevR[8];
130925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        } else if(prevR.length == 16) {
131025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri0 = prevR[0];
131125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri1 = prevR[1];
131225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri2 = prevR[2];
131325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri3 = prevR[4];
131425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri4 = prevR[5];
131525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri5 = prevR[6];
131625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri6 = prevR[8];
131725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri7 = prevR[9];
131825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri8 = prevR[10];
131925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
132025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
132125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        // calculate the parts of the rotation difference matrix we need
132225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        // rd[i][j] = pri[0][i] * ri[0][j] + pri[1][i] * ri[1][j] + pri[2][i] * ri[2][j];
132325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
132425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        rd1 = pri0 * ri1 + pri3 * ri4 + pri6 * ri7; //rd[0][1]
132525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        rd4 = pri1 * ri1 + pri4 * ri4 + pri7 * ri7; //rd[1][1]
132625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        rd6 = pri2 * ri0 + pri5 * ri3 + pri8 * ri6; //rd[2][0]
132725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        rd7 = pri2 * ri1 + pri5 * ri4 + pri8 * ri7; //rd[2][1]
132825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        rd8 = pri2 * ri2 + pri5 * ri5 + pri8 * ri8; //rd[2][2]
132925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
133025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        angleChange[0] = (float)Math.atan2(rd1, rd4);
133125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        angleChange[1] = (float)Math.asin(-rd7);
133225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        angleChange[2] = (float)Math.atan2(-rd6, rd8);
133325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
133425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
133525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
133625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /** Helper function to convert a rotation vector to a rotation matrix.
133725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a
133825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  9  or 16 element rotation matrix in the array R.  R must have length 9 or 16.
133925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  If R.length == 9, the following matrix is returned:
134025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * <pre>
134125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   /  R[ 0]   R[ 1]   R[ 2]   \
134225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   |  R[ 3]   R[ 4]   R[ 5]   |
134325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   \  R[ 6]   R[ 7]   R[ 8]   /
134425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *</pre>
134525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * If R.length == 16, the following matrix is returned:
134625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * <pre>
134725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   /  R[ 0]   R[ 1]   R[ 2]   0  \
134825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   |  R[ 4]   R[ 5]   R[ 6]   0  |
134925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   |  R[ 8]   R[ 9]   R[10]   0  |
135025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   \  0       0       0       1  /
135125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *</pre>
135225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  @param rotationVector the rotation vector to convert
135325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  @param R an array of floats in which to store the rotation matrix
135425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     */
135525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    public static void getRotationMatrixFromVector(float[] R, float[] rotationVector) {
135625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
135725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q0;
135825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q1 = rotationVector[0];
135925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q2 = rotationVector[1];
136025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q3 = rotationVector[2];
136125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
136225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        if (rotationVector.length == 4) {
136325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            q0 = rotationVector[3];
136425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        } else {
136525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            q0 = 1 - q1*q1 - q2*q2 - q3*q3;
136625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            q0 = (q0 > 0) ? (float)Math.sqrt(q0) : 0;
136725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
136825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
136925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float sq_q1 = 2 * q1 * q1;
137025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float sq_q2 = 2 * q2 * q2;
137125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float sq_q3 = 2 * q3 * q3;
137225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q1_q2 = 2 * q1 * q2;
137325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q3_q0 = 2 * q3 * q0;
137425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q1_q3 = 2 * q1 * q3;
137525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q2_q0 = 2 * q2 * q0;
137625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q2_q3 = 2 * q2 * q3;
137725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q1_q0 = 2 * q1 * q0;
137825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
137925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        if(R.length == 9) {
138025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[0] = 1 - sq_q2 - sq_q3;
138125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[1] = q1_q2 - q3_q0;
138225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[2] = q1_q3 + q2_q0;
138325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
138425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[3] = q1_q2 + q3_q0;
138525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[4] = 1 - sq_q1 - sq_q3;
138625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[5] = q2_q3 - q1_q0;
138725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
138825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[6] = q1_q3 - q2_q0;
138925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[7] = q2_q3 + q1_q0;
139025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[8] = 1 - sq_q1 - sq_q2;
139125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        } else if (R.length == 16) {
139225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[0] = 1 - sq_q2 - sq_q3;
139325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[1] = q1_q2 - q3_q0;
139425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[2] = q1_q3 + q2_q0;
139525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[3] = 0.0f;
139625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
139725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[4] = q1_q2 + q3_q0;
139825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[5] = 1 - sq_q1 - sq_q3;
139925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[6] = q2_q3 - q1_q0;
140025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[7] = 0.0f;
140125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
140225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[8] = q1_q3 - q2_q0;
140325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[9] = q2_q3 + q1_q0;
140425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[10] = 1 - sq_q1 - sq_q2;
140525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[11] = 0.0f;
140625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
140725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[12] = R[13] = R[14] = 0.0f;
140825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[15] = 1.0f;
140925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
141025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
141125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
141225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /** Helper function to convert a rotation vector to a normalized quaternion.
141325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a normalized
141425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  quaternion in the array Q.  The quaternion is stored as [w, x, y, z]
141525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  @param rv the rotation vector to convert
141625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  @param Q an array of floats in which to store the computed quaternion
141725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     */
141825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    public static void getQuaternionFromVector(float[] Q, float[] rv) {
141925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        if (rv.length == 4) {
142025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            Q[0] = rv[3];
142125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        } else {
142225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            Q[0] = 1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2];
142325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            Q[0] = (Q[0] > 0) ? (float)Math.sqrt(Q[0]) : 0;
142425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
142525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        Q[1] = rv[0];
142625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        Q[2] = rv[1];
142725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        Q[3] = rv[2];
142825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
142925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
14309a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    /**
14319a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * Requests receiving trigger events for a trigger sensor.
14329a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *
14339a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * <p>
14349a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * When the sensor detects a trigger event condition, such as significant motion in
14359a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * the case of the {@link Sensor#TYPE_SIGNIFICANT_MOTION}, the provided trigger listener
14369a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * will be invoked once and then its request to receive trigger events will be canceled.
14379a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * To continue receiving trigger events, the application must request to receive trigger
14389a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * events again.
14399a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * </p>
14409a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *
14419a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * @param listener The listener on which the
14429a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *        {@link TriggerEventListener#onTrigger(TriggerEvent)} will be delivered.
14439a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * @param sensor The sensor to be enabled.
14449a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *
14459a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * @return true if the sensor was successfully enabled.
14469a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *
14479a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * @throws IllegalArgumentException when sensor is null or not a trigger sensor.
14489a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     */
14499a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    public boolean requestTriggerSensor(TriggerEventListener listener, Sensor sensor) {
14509a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        return requestTriggerSensorImpl(listener, sensor);
14519a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    }
14529a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh
14539a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    /**
14549a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * @hide
14559a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     */
14569a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    protected abstract boolean requestTriggerSensorImpl(TriggerEventListener listener,
14579a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            Sensor sensor);
14589a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh
14599a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    /**
14609a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * Cancels receiving trigger events for a trigger sensor.
14619a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *
14629a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * <p>
14639a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * Note that a Trigger sensor will be auto disabled if
14649a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * {@link TriggerEventListener#onTrigger(TriggerEvent)} has triggered.
14659a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * This method is provided in case the user wants to explicitly cancel the request
14669a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * to receive trigger events.
14679a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * </p>
14689a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *
14699a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * @param listener The listener on which the
14709a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *        {@link TriggerEventListener#onTrigger(TriggerEvent)}
14719a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *        is delivered.It should be the same as the one used
14729a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *        in {@link #requestTriggerSensor(TriggerEventListener, Sensor)}
14739a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * @param sensor The sensor for which the trigger request should be canceled.
14749a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *        If null, it cancels receiving trigger for all sensors associated
14759a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *        with the listener.
14769a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *
14779a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * @return true if successfully canceled.
14789a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     *
14799a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * @throws IllegalArgumentException when sensor is a trigger sensor.
14809a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     */
14819a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    public boolean cancelTriggerSensor(TriggerEventListener listener, Sensor sensor) {
14822e90089766c047687662d402819018b308e83d15Jaikumar Ganesh        return cancelTriggerSensorImpl(listener, sensor, true);
14839a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    }
14849a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh
14859a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    /**
14869a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * @hide
14879a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     */
14889a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    protected abstract boolean cancelTriggerSensorImpl(TriggerEventListener listener,
14892e90089766c047687662d402819018b308e83d15Jaikumar Ganesh            Sensor sensor, boolean disable);
14909a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh
14919a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh
14924481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown    private LegacySensorManager getLegacySensorManager() {
14934481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown        synchronized (mSensorListByType) {
14944481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown            if (mLegacySensorManager == null) {
14954481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown                Log.i(TAG, "This application is using deprecated SensorManager API which will "
14964481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown                        + "be removed someday.  Please consider switching to the new API.");
14974481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown                mLegacySensorManager = new LegacySensorManager(this);
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14994481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown            return mLegacySensorManager;
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1502b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella
1503b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    private static int getDelay(int rate) {
1504b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        int delay = -1;
1505b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        switch (rate) {
1506b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella            case SENSOR_DELAY_FASTEST:
1507b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                delay = 0;
1508b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                break;
1509b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella            case SENSOR_DELAY_GAME:
1510b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                delay = 20000;
1511b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                break;
1512b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella            case SENSOR_DELAY_UI:
1513b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                delay = 66667;
1514b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                break;
1515b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella            case SENSOR_DELAY_NORMAL:
1516b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                delay = 200000;
1517b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                break;
1518b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella            default:
1519b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                delay = rate;
1520b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                break;
1521b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        }
1522b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        return delay;
1523b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    }
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1525