SensorManager.java revision 25157e458d6e10b027d1ba6b78b0487156c9f57a
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.RemoteException;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.SparseArray;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IRotationWatcher;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IWindowManager;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Surface;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Collections;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
3343c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * <p>
3474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * SensorManager lets you access the device's {@link android.hardware.Sensor
3574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * sensors}. Get an instance of this class by calling
3674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * {@link android.content.Context#getSystemService(java.lang.String)
3774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * Context.getSystemService()} with the argument
3874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian * {@link android.content.Context#SENSOR_SERVICE}.
3943c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * </p>
4043c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * <p>
4143c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * Always make sure to disable sensors you don't need, especially when your
4243c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * activity is paused. Failing to do so can drain the battery in just a few
4343c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * hours. Note that the system will <i>not</i> disable sensors automatically when
4443c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * the screen turns off.
4543c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian * </p>
460f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
470f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * <pre class="prettyprint">
480f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * public class SensorActivity extends Activity, implements SensorEventListener {
490f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     private final SensorManager mSensorManager;
500f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     private final Sensor mAccelerometer;
510f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
520f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     public SensorActivity() {
530f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *         mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
540f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *         mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
5543c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *     }
5643c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *
5743c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *     protected void onResume() {
5843c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *         super.onResume();
590f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *         mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
600f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     }
610f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
6243c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *     protected void onPause() {
6343c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *         super.onPause();
6443c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *         mSensorManager.unregisterListener(this);
6543c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *     }
6643c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *
670f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     public void onAccuracyChanged(Sensor sensor, int accuracy) {
680f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     }
690f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
7043c87e44fc0d7d7b37e039752c0dec093e227381Mathias Agopian *     public void onSensorChanged(SensorEvent event) {
710f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *     }
720f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * }
730f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * </pre>
740f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
750f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * @see SensorEventListener
760f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * @see SensorEvent
770f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian * @see Sensor
780f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian *
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
8025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownpublic abstract class SensorManager {
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final float[] mTempMatrix = new float[16];
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private static boolean sInitialized;
8425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private static IWindowManager sWindowManager;
8525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private static int sRotation = Surface.ROTATION_0;
8625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
8725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    // List of legacy listeners.  Guarded by mLegacyListenersMap.
8825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private final HashMap<SensorListener, LegacyListener> mLegacyListenersMap =
8925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            new HashMap<SensorListener, LegacyListener>();
9025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
9125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    // Cached lists of sensors by type.  Guarded by mSensorListByType.
9225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private final SparseArray<List<Sensor>> mSensorListByType =
9325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            new SparseArray<List<Sensor>>();
9425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* NOTE: sensor IDs must be a power of 2 */
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an orientation sensor. See
9974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1000f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ORIENTATION = 1 << 0;
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an accelerometer. See
10874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1090f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ACCELEROMETER = 1 << 1;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a temperature sensor See
11774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1180f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_TEMPERATURE = 1 << 2;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a magnetic sensor See
12674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1270f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_MAGNETIC_FIELD = 1 << 3;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an ambient light sensor See
13574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1360f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_LIGHT = 1 << 4;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a proximity sensor See
14474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1450f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_PROXIMITY = 1 << 5;
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing a Tricorder See
15374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1540f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_TRICORDER = 1 << 6;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant describing an orientation sensor. See
16274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.SensorListener SensorListener} for more details.
1630f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ORIENTATION_RAW = 1 << 7;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
17074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * A constant that includes all sensors
1710f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1724a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1734a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_ALL = 0x7F;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
17874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Smallest sensor ID
1790f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1804a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1814a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_MIN = SENSOR_ORIENTATION;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
18674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Largest sensor ID
1870f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1884a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1894a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_MAX = ((SENSOR_ALL + 1)>>1);
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
19574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the X value in the array returned by
1964a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
1970f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
1984a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
1994a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int DATA_X = 0;
20274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
20374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
20474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the Y value in the array returned by
2054a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2060f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2074a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2084a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int DATA_Y = 1;
21174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
21274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
21374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the Z value in the array returned by
2144a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2150f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2164a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2174a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int DATA_Z = 2;
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
22274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Offset to the untransformed values in the array returned by
2234a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2240f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2254a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2264a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_INDEX = 3;
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
23174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the untransformed X value in the array returned by
2324a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2330f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2344a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2354a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_X = 3;
23874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
23974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
24074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the untransformed Y value in the array returned by
2414a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2420f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2434a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2444a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_Y = 4;
24774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian
24874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
24974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Index of the untransformed Z value in the array returned by
2504a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * {@link android.hardware.SensorListener#onSensorChanged}
2510f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
2524a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     * @deprecated use {@link android.hardware.Sensor Sensor} instead.
2534a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn     */
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RAW_DATA_Z = 5;
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Standard gravity (g) on Earth. This value is equivalent to 1G */
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float STANDARD_GRAVITY = 9.80665f;
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Sun's gravity in SI units (m/s^2) */
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_SUN             = 275.0f;
26274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Mercury's gravity in SI units (m/s^2) */
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MERCURY         = 3.70f;
26474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Venus' gravity in SI units (m/s^2) */
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_VENUS           = 8.87f;
26674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Earth's gravity in SI units (m/s^2) */
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_EARTH           = 9.80665f;
26874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** The Moon's gravity in SI units (m/s^2) */
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MOON            = 1.6f;
27074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Mars' gravity in SI units (m/s^2) */
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_MARS            = 3.71f;
27274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Jupiter's gravity in SI units (m/s^2) */
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_JUPITER         = 23.12f;
27474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Saturn's gravity in SI units (m/s^2) */
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_SATURN          = 8.96f;
27674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Uranus' gravity in SI units (m/s^2) */
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_URANUS          = 8.69f;
27874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Neptune's gravity in SI units (m/s^2) */
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_NEPTUNE         = 11.0f;
28074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Pluto's gravity in SI units (m/s^2) */
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_PLUTO           = 0.6f;
28274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Gravity (estimate) on the first Death Star in Empire units (m/s^2) */
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_DEATH_STAR_I    = 0.000000353036145f;
28474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Gravity on the island */
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float GRAVITY_THE_ISLAND      = 4.815162342f;
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Maximum magnetic field on Earth's surface */
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f;
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Minimum magnetic field on Earth's surface */
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f;
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2930f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian
29404d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian    /** Standard atmosphere, or average sea-level pressure in hPa (millibar) */
29504d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian    public static final float PRESSURE_STANDARD_ATMOSPHERE = 1013.25f;
29604d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian
29704d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian
29874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** Maximum luminance of sunlight in lux */
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
30074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance of sunlight in lux */
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNLIGHT     = 110000.0f;
30274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance in shade in lux */
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SHADE        = 20000.0f;
30474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance under an overcast sky in lux */
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_OVERCAST     = 10000.0f;
30674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance at sunrise in lux */
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_SUNRISE      = 400.0f;
30874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance under a cloudy sky in lux */
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_CLOUDY       = 100.0f;
31074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance at night with full moon in lux */
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_FULLMOON     = 0.25f;
31274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /** luminance at night with no moon in lux*/
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float LIGHT_NO_MOON      = 0.001f;
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3150f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** get sensor data as fast as possible */
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_FASTEST = 0;
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate suitable for games */
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_GAME = 1;
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate suitable for the user interface  */
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_UI = 2;
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** rate (default) suitable for screen orientation changes */
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_DELAY_NORMAL = 3;
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
32674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
32774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * The values returned by this sensor cannot be trusted, calibration is
32874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * needed or the environment doesn't allow readings
32974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     */
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_UNRELIABLE = 0;
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
33274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
33374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * This sensor is reporting data with low accuracy, calibration with the
33474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * environment is needed
33574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     */
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_LOW = 1;
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
33874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
33974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * This sensor is reporting data with an average level of accuracy,
34074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * calibration with the environment may improve the readings
34174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     */
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2;
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** This sensor is reporting data with maximum accuracy */
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SENSOR_STATUS_ACCURACY_HIGH = 3;
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_X = 1;
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_Y = 2;
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_Z = 3;
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_X = AXIS_X | 0x80;
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_Y = AXIS_Y | 0x80;
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** see {@link #remapCoordinateSystem} */
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AXIS_MINUS_Z = AXIS_Z | 0x80;
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
36425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    public SensorManager() {
36525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        synchronized (SensorManager.class) {
36625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            if (!sInitialized) {
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sWindowManager = IWindowManager.Stub.asInterface(
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ServiceManager.getService("window"));
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (sWindowManager != null) {
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // if it's null we're running in the system process
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // which won't get the rotated values
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
373287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                        sRotation = sWindowManager.watchRotation(
37404d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian                                new IRotationWatcher.Stub() {
37504d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian                                    public void onRotationChanged(int rotation) {
37604d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian                                        SensorManager.this.onRotationChanged(rotation);
37704d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian                                    }
378287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                                }
379287b30920102b5466efa53a2f17ed69f2c776c16Mathias Agopian                        );
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
38725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /**
38825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * Gets the full list of sensors that are available.
38925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * @hide
39025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     */
39125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    protected abstract List<Sensor> getFullSensorList();
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
39374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian    /**
39474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return available sensors.
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
39674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#getSensorList(int)} instead
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getSensors() {
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int result = 0;
40125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        final List<Sensor> fullList = getFullSensorList();
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (Sensor i : fullList) {
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (i.getType()) {
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case Sensor.TYPE_ACCELEROMETER:
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result |= SensorManager.SENSOR_ACCELEROMETER;
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case Sensor.TYPE_MAGNETIC_FIELD:
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result |= SensorManager.SENSOR_MAGNETIC_FIELD;
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case Sensor.TYPE_ORIENTATION:
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result |= SensorManager.SENSOR_ORIENTATION |
41204d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian                    SensorManager.SENSOR_ORIENTATION_RAW;
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
42074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Use this method to get the list of available sensors of a certain type.
42174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Make multiple calls to get sensors of different types or use
42274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all the
42374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * sensors.
4240f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
42574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param type
42674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        of sensors requested
4270f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a list of sensors matching the asked type.
4290f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
4300f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getDefaultSensor(int)
4310f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see Sensor
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<Sensor> getSensorList(int type) {
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // cache the returned lists the first time
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Sensor> list;
43625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        final List<Sensor> fullList = getFullSensorList();
43725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        synchronized (mSensorListByType) {
43825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            list = mSensorListByType.get(type);
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (list == null) {
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (type == Sensor.TYPE_ALL) {
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    list = fullList;
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    list = new ArrayList<Sensor>();
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (Sensor i : fullList) {
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (i.getType() == type)
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            list.add(i);
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                list = Collections.unmodifiableList(list);
45025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                mSensorListByType.append(type, list);
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return list;
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
45774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Use this method to get the default sensor for a given type. Note that the
45874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * returned sensor could be a composite sensor, and its data could be
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * averaged or filtered. If you need to access the raw sensors use
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link SensorManager#getSensorList(int) getSensorList}.
4610f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
46274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param type
46374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        of sensors requested
4640f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the default sensors matching the asked type.
4660f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
4670f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getSensorList(int)
4680f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see Sensor
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Sensor getDefaultSensor(int type) {
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO: need to be smarter, for now, just return the 1st sensor
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Sensor> l = getSensorList(type);
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return l.isEmpty() ? null : l.get(0);
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registers a listener for given sensors.
4780f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
48074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
48174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
4820f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
48374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
48474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        sensor listener object
4850f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
48674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensors
48774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a bit masks of the sensors to register to
4880f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
48974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> if the sensor is supported and successfully
49074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         enabled
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorListener listener, int sensors) {
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registers a SensorListener for given sensors.
4990f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
50174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
50274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
5030f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
50474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
50574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        sensor listener object
5060f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
50774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensors
50874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a bit masks of the sensors to register to
5090f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
51074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param rate
51174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        rate of events. This is only a hint to the system. events may be
51274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        received faster or slower than the specified rate. Usually events
51374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        are received faster. The value must be one of
51474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
51574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
5160f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
51774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> if the sensor is supported and successfully
51874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         enabled
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorListener listener, int sensors, int rate) {
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null) {
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean result = false;
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = registerLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors, rate) || result;
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("deprecation")
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean registerLegacyListener(int legacyType, int type,
54125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            SensorListener listener, int sensors, int rate) {
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean result = false;
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Are we activating this legacy sensor?
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((sensors & legacyType) != 0) {
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // if so, find a suitable Sensor
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Sensor sensor = getDefaultSensor(type);
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sensor != null) {
54825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // We do all of this work holding the legacy listener lock to ensure
54925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // that the invariants around listeners are maintained.  This is safe
55025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // because neither registerLegacyListener nor unregisterLegacyListener
55125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // are called reentrantly while sensors are being registered or unregistered.
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                synchronized (mLegacyListenersMap) {
55325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    // If we don't already have one, create a LegacyListener
55425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    // to wrap this listener and process the events as
55525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    // they are expected by legacy apps.
55625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    LegacyListener legacyListener = mLegacyListenersMap.get(listener);
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (legacyListener == null) {
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // we didn't find a LegacyListener for this client,
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // create one, and put it in our list.
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        legacyListener = new LegacyListener(listener);
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mLegacyListenersMap.put(listener, legacyListener);
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
56325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
56425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    // register this legacy sensor with this legacy listener
56525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    if (legacyListener.registerSensor(legacyType)) {
56625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        // and finally, register the legacy listener with the new apis
56725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        result = registerListener(legacyListener, sensor, rate);
56825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    } else {
56925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        result = true; // sensor already enabled
57025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    }
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for the sensors with which it is registered.
5790f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
58174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#unregisterListener(SensorEventListener, Sensor)}
58274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
5830f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
58474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
58574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorListener object
5860f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
58774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensors
58874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a bit masks of the sensors to unregister from
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorListener listener, int sensors) {
59225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        if (listener == null) {
59325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return;
59425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listener, sensors);
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for all sensors.
6090f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated This method is deprecated, use
61174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             {@link SensorManager#unregisterListener(SensorEventListener)}
61274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *             instead.
6130f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
61474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
61574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorListener object
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Deprecated
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorListener listener) {
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW);
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
62225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    @SuppressWarnings("deprecation")
62325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private void unregisterLegacyListener(int legacyType, int type,
62425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            SensorListener listener, int sensors) {
62525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        // Are we deactivating this legacy sensor?
62625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        if ((sensors & legacyType) != 0) {
62725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            // if so, find the corresponding Sensor
62825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            Sensor sensor = getDefaultSensor(type);
62925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            if (sensor != null) {
63025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // We do all of this work holding the legacy listener lock to ensure
63125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // that the invariants around listeners are maintained.  This is safe
63225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // because neither registerLegacyListener nor unregisterLegacyListener
63325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // are called re-entrantly while sensors are being registered or unregistered.
63425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                synchronized (mLegacyListenersMap) {
63525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    // do we know about this listener?
63625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    LegacyListener legacyListener = mLegacyListenersMap.get(listener);
63725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    if (legacyListener != null) {
63825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        // unregister this legacy sensor and if we don't
63925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        // need the corresponding Sensor, unregister it too
64025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        if (legacyListener.unregisterSensor(legacyType)) {
64125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            // corresponding sensor not needed, unregister
64225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            unregisterListener(legacyListener, sensor);
64325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
64425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            // finally check if we still need the legacyListener
64525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            // in our mapping, if not, get rid of it too.
64625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            if (!legacyListener.hasSensors()) {
64725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                                mLegacyListenersMap.remove(listener);
64825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            }
64925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        }
65025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    }
65125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                }
65225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
65325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
65425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
65525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for the sensors with which it is registered.
6580f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
65974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
66074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorEventListener object
6610f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
66274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensor
66374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the sensor to unregister from
6640f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
6650f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener)
6660f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #registerListener(SensorEventListener, Sensor, int)
6670f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorEventListener listener, Sensor sensor) {
67025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        if (listener == null || sensor == null) {
67125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return;
67225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
67325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
67425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        unregisterListenerImpl(listener, sensor);
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregisters a listener for all sensors.
6790f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
68074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
68174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        a SensorListener object
6820f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
6830f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener, Sensor)
6840f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #registerListener(SensorEventListener, Sensor, int)
6850f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void unregisterListener(SensorEventListener listener) {
68825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        if (listener == null) {
68925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return;
69025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
69125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
69225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        unregisterListenerImpl(listener, null);
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
69525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /** @hide */
69625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    protected abstract void unregisterListenerImpl(SensorEventListener listener, Sensor sensor);
69725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
69974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Registers a {@link android.hardware.SensorEventListener
70074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * SensorEventListener} for the given sensor.
7010f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
70274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
70374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        A {@link android.hardware.SensorEventListener SensorEventListener}
70474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        object.
7050f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
70674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensor
70774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The {@link android.hardware.Sensor Sensor} to register to.
7080f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
70974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param rate
71074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The rate {@link android.hardware.SensorEvent sensor events} are
71174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        delivered at. This is only a hint to the system. Events may be
71274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        received faster or slower than the specified rate. Usually events
71374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        are received faster. The value must be one of
71474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
715050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian     *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}
716050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian     *        or, the desired delay between events in microsecond.
7170f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
71874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> if the sensor is supported and successfully
71974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         enabled.
7200f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
7210f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #registerListener(SensorEventListener, Sensor, int, Handler)
7220f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener)
7230f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener, Sensor)
7240f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) {
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return registerListener(listener, sensor, rate, null);
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
73174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Registers a {@link android.hardware.SensorEventListener
73274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * SensorEventListener} for the given sensor.
7330f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
73474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param listener
73574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        A {@link android.hardware.SensorEventListener SensorEventListener}
73674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        object.
7370f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
73874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param sensor
73974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The {@link android.hardware.Sensor Sensor} to register to.
7400f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
74174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param rate
74274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The rate {@link android.hardware.SensorEvent sensor events} are
74374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        delivered at. This is only a hint to the system. Events may be
74474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        received faster or slower than the specified rate. Usually events
74574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        are received faster. The value must be one of
74674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
74774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
748050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian     *        or, the desired delay between events in microsecond.
7490f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
75074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param handler
75174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        The {@link android.os.Handler Handler} the
75274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent sensor events} will be
75374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        delivered to.
7540f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the sensor is supported and successfully enabled.
7560f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
7570f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #registerListener(SensorEventListener, Sensor, int)
7580f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener)
7590f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #unregisterListener(SensorEventListener, Sensor)
7600f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate,
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Handler handler) {
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener == null || sensor == null) {
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
76725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int delay = -1;
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (rate) {
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_FASTEST:
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delay = 0;
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_GAME:
774050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian                delay = 20000;
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_UI:
7775263767cdae21f8f6968dfba974623b240746d6eMathias Agopian                delay = 66667;
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case SENSOR_DELAY_NORMAL:
780050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian                delay = 200000;
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:
783050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian                delay = rate;
784050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian                break;
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
78725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        return registerListenerImpl(listener, sensor, delay, handler);
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
79025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /** @hide */
79125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
79225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            int delay, Handler handler);
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
79574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
79674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Computes the inclination matrix <b>I</b> as well as the rotation matrix
79774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>R</b> transforming a vector from the device coordinate system to the
79874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * world's coordinate system which is defined as a direct orthonormal basis,
79974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * where:
80074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
8010f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
80274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the ground at the device's current location and roughly points East).</li>
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Y is tangential to the ground at the device's current location and
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * points towards the magnetic North Pole.</li>
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Z points towards the sky and is perpendicular to the ground.</li>
80874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
8090f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
8100f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * <p>
8110f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * <center><img src="../../../images/axis_globe.png"
812f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * alt="World coordinate-system diagram." border="0" /></center>
8130f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * </p>
8140f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
81774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
81874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * By definition:
81974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
82074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * [0 0 g] = <b>R</b> * <b>gravity</b> (g = magnitude of gravity)
82174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
82274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * [0 m 0] = <b>I</b> * <b>R</b> * <b>geomagnetic</b> (m = magnitude of
82374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * geomagnetic field)
82474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
82574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>R</b> is the identity matrix when the device is aligned with the
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * world's coordinate system, that is, when the device's X axis points
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * toward East, the Y axis points to the North Pole and the device is facing
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the sky.
8290f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
83074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
83174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>I</b> is a rotation matrix transforming the geomagnetic vector into
83274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * the same coordinate space as gravity (the world's coordinate space).
83374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <b>I</b> is a simple rotation around the X axis. The inclination angle in
83474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * radians can be computed with {@link #getInclination}.
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
8360f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
83774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
83874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Each matrix is returned either as a 3x3 or 4x4 row-major matrix depending
83974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * on the length of the passed array:
84074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
84174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <u>If the array length is 16:</u>
8420f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]   M[ 3]  \
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 4]   M[ 5]   M[ 6]   M[ 7]  |
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 8]   M[ 9]   M[10]   M[11]  |
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \  M[12]   M[13]   M[14]   M[15]  /
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
8490f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
85074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * This matrix is ready to be used by OpenGL ES's
85174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link javax.microedition.khronos.opengles.GL10#glLoadMatrixf(float[], int)
85274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * glLoadMatrixf(float[], int)}.
85374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
85474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Note that because OpenGL matrices are column-major matrices you must
85574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * transpose the matrix before using it. However, since the matrix is a
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * rotation matrix, its transpose is also its inverse, conveniently, it is
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * often the inverse of the rotation that is needed for rendering; it can
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * therefore be used with OpenGL ES directly.
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Also note that the returned matrices always have this form:
8610f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]   0  \
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 4]   M[ 5]   M[ 6]   0  |
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 8]   M[ 9]   M[10]   0  |
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \      0       0       0   1  /
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
8680f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
86974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
87074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <u>If the array length is 9:</u>
8710f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   /  M[ 0]   M[ 1]   M[ 2]  \
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   |  M[ 3]   M[ 4]   M[ 5]  |
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   \  M[ 6]   M[ 7]   M[ 8]  /
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *</pre>
8770f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <hr>
87974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
88074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * The inverse of each matrix can be computed easily by taking its
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * transpose.
8820f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
88374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
88474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * The matrices returned by this function are meaningful only when the
88574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * device is not free-falling and it is not close to the magnetic north. If
88674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * the device is accelerating, or placed into a strong magnetic field, the
88774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * returned matrices may be inaccurate.
8880f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
88974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param R
89074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 9 floats holding the rotation matrix <b>R</b> when
89174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        this function returns. R can be null.
89274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        <p>
8930f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
89474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param I
89574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 9 floats holding the rotation matrix <b>I</b> when
89674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        this function returns. I can be null.
89774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        <p>
8980f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
89974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param gravity
90074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 3 floats containing the gravity vector expressed in
90174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the device's coordinate. You can simply use the
90274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent#values values} returned by a
90374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent SensorEvent} of a
90474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor Sensor} of type
90574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor#TYPE_ACCELEROMETER
90674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        TYPE_ACCELEROMETER}.
90774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        <p>
9080f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
90974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param geomagnetic
91074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is an array of 3 floats containing the geomagnetic vector
91174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        expressed in the device's coordinate. You can simply use the
91274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent#values values} returned by a
91374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.SensorEvent SensorEvent} of a
91474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor Sensor} of type
91574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD
91674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        TYPE_MAGNETIC_FIELD}.
9170f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
91874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> on success, <code>false</code> on failure (for
91974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         instance, if the device is in free fall). On failure the output
92074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         matrices are not modified.
9210f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9220f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getInclination(float[])
9230f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getOrientation(float[], float[])
9240f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #remapCoordinateSystem(float[], int, int, float[])
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean getRotationMatrix(float[] R, float[] I,
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] gravity, float[] geomagnetic) {
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO: move this to native code for efficiency
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Ax = gravity[0];
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Ay = gravity[1];
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Az = gravity[2];
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ex = geomagnetic[0];
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ey = geomagnetic[1];
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Ez = geomagnetic[2];
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hx = Ey*Az - Ez*Ay;
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hy = Ez*Ax - Ex*Az;
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float Hz = Ex*Ay - Ey*Ax;
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (normH < 0.1f) {
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // device is close to free fall (or in space?), or close to
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // magnetic north pole. Typical values are  > 100.
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float invH = 1.0f / normH;
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hx *= invH;
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hy *= invH;
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Hz *= invH;
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az);
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Ax *= invA;
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Ay *= invA;
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Az *= invA;
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Mx = Ay*Hz - Az*Hy;
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float My = Az*Hx - Ax*Hz;
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float Mz = Ax*Hy - Ay*Hx;
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (R != null) {
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (R.length == 9) {
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[0] = Hx;     R[1] = Hy;     R[2] = Hz;
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[3] = Mx;     R[4] = My;     R[5] = Mz;
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[6] = Ax;     R[7] = Ay;     R[8] = Az;
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (R.length == 16) {
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[0]  = Hx;    R[1]  = Hy;    R[2]  = Hz;   R[3]  = 0;
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[4]  = Mx;    R[5]  = My;    R[6]  = Mz;   R[7]  = 0;
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[8]  = Ax;    R[9]  = Ay;    R[10] = Az;   R[11] = 0;
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R[12] = 0;     R[13] = 0;     R[14] = 0;    R[15] = 1;
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (I != null) {
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // compute the inclination matrix by projecting the geomagnetic
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // vector onto the Z (gravity) and X (horizontal component
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // of geomagnetic vector) axes.
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez);
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE;
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE;
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (I.length == 9) {
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[0] = 1;     I[1] = 0;     I[2] = 0;
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[3] = 0;     I[4] = c;     I[5] = s;
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[6] = 0;     I[7] =-s;     I[8] = c;
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (I.length == 16) {
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[0] = 1;     I[1] = 0;     I[2] = 0;
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[4] = 0;     I[5] = c;     I[6] = s;
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[8] = 0;     I[9] =-s;     I[10]= c;
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                I[15] = 1;
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Computes the geomagnetic inclination angle in radians from the
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * inclination matrix <b>I</b> returned by {@link #getRotationMatrix}.
9930f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
99474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param I
99574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        inclination matrix see {@link #getRotationMatrix}.
9960f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The geomagnetic inclination angle in radians.
9980f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
9990f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getRotationMatrix(float[], float[], float[], float[])
10000f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getOrientation(float[], float[])
10010f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see GeomagneticField
10020f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static float getInclination(float[] I) {
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (I.length == 9) {
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (float)Math.atan2(I[5], I[4]);
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
10080f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian            return (float)Math.atan2(I[6], I[5]);
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
101374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
101474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Rotates the supplied rotation matrix so it is expressed in a different
101574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * coordinate system. This is typically used when an application needs to
101674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * compute the three orientation angles of the device (see
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #getOrientation}) in a different coordinate system.
101874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
10190f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
102074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
102174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * When the rotation matrix is used for drawing (for instance with OpenGL
102274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * ES), it usually <b>doesn't need</b> to be transformed by this function,
102374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * unless the screen is physically rotated, in which case you can use
102474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.view.Display#getRotation() Display.getRotation()} to
102574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * retrieve the current rotation of the screen. Note that because the user
102674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * is generally free to rotate their screen, you often should consider the
102774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * rotation in deciding the parameters to use here.
102874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
10290f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
103074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
103174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <u>Examples:</u>
103274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
10330f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
103474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
103574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <li>Using the camera (Y axis along the camera's axis) for an augmented
103674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * reality application where the rotation angles are needed:</li>
10370f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
103874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
103974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
104074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <code>remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);</code>
104174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
104274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
10430f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
10445cb70b54156fb305d579a1cc167424c8705bfdf7Dianne Hackborn     * <li>Using the device as a mechanical compass when rotation is
104574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.view.Surface#ROTATION_90 Surface.ROTATION_90}:</li>
10460f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
104774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
104874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
104974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <code>remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);</code>
105074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
105174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </p>
10520f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
105374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Beware of the above example. This call is needed only to account for a
105474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * rotation from its natural orientation when calculating the rotation
105574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * angles (see {@link #getOrientation}). If the rotation matrix is also used
105674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * for rendering, it may not need to be transformed, for instance if your
105774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * {@link android.app.Activity Activity} is running in landscape mode.
105874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
10590f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
106074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
106174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * Since the resulting coordinate system is orthonormal, only two axes need
106274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * to be specified.
10630f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
106474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param inR
106574cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the rotation matrix to be transformed. Usually it is the matrix
106674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        returned by {@link #getRotationMatrix}.
10670f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
106874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param X
106974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        defines on which world axis and direction the X axis of the device
107074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is mapped.
10710f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
107274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param Y
107374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        defines on which world axis and direction the Y axis of the device
107474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        is mapped.
10750f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
107674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param outR
107774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        the transformed rotation matrix. inR and outR can be the same
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        array, but it is not recommended for performance reason.
10790f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
108074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @return <code>true</code> on success. <code>false</code> if the input
108174cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         parameters are incorrect, for instance if X and Y define the same
108274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *         axis. Or if inR and outR don't have the same length.
10830f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
10840f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getRotationMatrix(float[], float[], float[], float[])
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean remapCoordinateSystem(float[] inR, int X, int Y,
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] outR)
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (inR == outR) {
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float[] temp = mTempMatrix;
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(temp) {
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // we don't expect to have a lot of contention
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (remapCoordinateSystemImpl(inR, X, Y, temp)) {
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final int size = outR.length;
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (int i=0 ; i<size ; i++)
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        outR[i] = temp[i];
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return true;
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return remapCoordinateSystemImpl(inR, X, Y, outR);
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y,
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] outR)
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * X and Y define a rotation matrix 'r':
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *                              r[0] ^ r[1]
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * where the 3rd line is the vector product of the first 2 lines
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int length = outR.length;
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (inR.length != length)
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // invalid parameter
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((X & 0x7C)!=0 || (Y & 0x7C)!=0)
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // invalid parameter
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (((X & 0x3)==0) || ((Y & 0x3)==0))
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // no axis specified
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((X & 0x3) == (Y & 0x3))
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;   // same axis specified
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y)
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // this can be calculated by exclusive-or'ing X and Y; except for
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the sign inversion (+/-) which is calculated below.
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int Z = X ^ Y;
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // extract the axis (remove the sign), offset in the range 0 to 2.
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int x = (X & 0x3)-1;
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int y = (Y & 0x3)-1;
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int z = (Z & 0x3)-1;
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // compute the sign of Z (whether it needs to be inverted)
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int axis_y = (z+1)%3;
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int axis_z = (z+2)%3;
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (((x^axis_y)|(y^axis_z)) != 0)
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Z ^= 0x80;
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sx = (X>=0x80);
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sy = (Y>=0x80);
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean sz = (Z>=0x80);
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Perform R * r, in avoiding actual muls and adds.
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int rowLength = ((length==16)?4:3);
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int j=0 ; j<3 ; j++) {
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int offset = j*rowLength;
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0 ; i<3 ; i++) {
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (x==i)   outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0];
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (y==i)   outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1];
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (z==i)   outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2];
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (length == 16) {
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0;
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            outR[15] = 1;
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Computes the device's orientation based on the rotation matrix.
116874cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <p>
116974cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * When it returns, the array values is filled with the result:
117074cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * <ul>
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[0]: <i>azimuth</i>, rotation around the Z axis.</li>
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[1]: <i>pitch</i>, rotation around the X axis.</li>
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>values[2]: <i>roll</i>, rotation around the Y axis.</li>
117474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * </ul>
1175f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * <p>The reference coordinate-system used is different from the world
1176f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * coordinate-system defined for the rotation matrix:</p>
1177f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * <ul>
1178f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
1179f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * the ground at the device's current location and roughly points West).</li>
1180f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * <li>Y is tangential to the ground at the device's current location and
1181f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * points towards the magnetic North Pole.</li>
1182f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * <li>Z points towards the center of the Earth and is perpendicular to the ground.</li>
1183f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * </ul>
1184f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     *
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11860871ee0c6f43a7201ce49a66211c1c850eabeb6bDirk Dougherty     * <center><img src="../../../images/axis_globe_inverted.png"
1187f71384cd6141c50f589178d309db3ceeb848fb30Mathias Agopian     * alt="Inverted world coordinate-system diagram." border="0" /></center>
11880f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * </p>
11890f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * <p>
1190210fc914db37b3cf77ebb3bf75b0b509a1ecb07cMathias Agopian     * All three angles above are in <b>radians</b> and <b>positive</b> in the
1191210fc914db37b3cf77ebb3bf75b0b509a1ecb07cMathias Agopian     * <b>counter-clockwise</b> direction.
119274cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *
119374cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param R
119474cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        rotation matrix see {@link #getRotationMatrix}.
11950f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
119674cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     * @param values
119774cde2cee9e53006a710f4e80700cd560c2d0e4dMathias Agopian     *        an array of 3 floats to hold the result.
11980f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The array values passed as argument.
12000f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     *
12010f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see #getRotationMatrix(float[], float[], float[], float[])
12020f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian     * @see GeomagneticField
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
120404d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian    public static float[] getOrientation(float[] R, float values[]) {
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * 4x4 (length=16) case:
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   /  R[ 0]   R[ 1]   R[ 2]   0  \
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 4]   R[ 5]   R[ 6]   0  |
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 8]   R[ 9]   R[10]   0  |
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   \      0       0       0   1  /
12110f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian         *
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * 3x3 (length=9) case:
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   /  R[ 0]   R[ 1]   R[ 2]  \
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   |  R[ 3]   R[ 4]   R[ 5]  |
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *   \  R[ 6]   R[ 7]   R[ 8]  /
12160f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian         *
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (R.length == 9) {
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = (float)Math.atan2(R[1], R[4]);
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = (float)Math.asin(-R[7]);
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = (float)Math.atan2(-R[6], R[8]);
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = (float)Math.atan2(R[1], R[5]);
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = (float)Math.asin(-R[9]);
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = (float)Math.atan2(-R[8], R[10]);
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return values;
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
123104d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * Computes the Altitude in meters from the atmospheric pressure and the
123204d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * pressure at sea level.
123304d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * <p>
123404d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * Typically the atmospheric pressure is read from a
123504d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * {@link Sensor#TYPE_PRESSURE} sensor. The pressure at sea level must be
123604d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * known, usually it can be retrieved from airport databases in the
1237a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * vicinity. If unknown, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE}
1238a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * as an approximation, but absolute altitudes won't be accurate.
1239a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * </p>
1240a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * <p>
1241a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * To calculate altitude differences, you must calculate the difference
1242a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * between the altitudes at both points. If you don't know the altitude
1243a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * as sea level, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE} instead,
1244a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * which will give good results considering the range of pressure typically
1245a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * involved.
1246a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * </p>
1247a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * <p>
1248a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * <code><ul>
1249a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     *  float altitude_difference =
1250a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     *      getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point2)
1251a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     *      - getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point1);
1252a6704d39b31417dc674d3866f43dad4ce3f850b1Mathias Agopian     * </ul></code>
125304d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * </p>
125404d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     *
125504d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * @param p0 pressure at sea level
125604d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * @param p atmospheric pressure
125704d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     * @return Altitude in meters
125804d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian     */
125925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    public static float getAltitude(float p0, float p) {
126004d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian        final float coef = 1.0f / 5.255f;
126104d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian        return 44330.0f * (1.0f - (float)Math.pow(p/p0, coef));
126204d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian    }
126304d7e83e65e246e154b5b346e3eb0081b741ae88Mathias Agopian
126425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /** Helper function to compute the angle change between two rotation matrices.
126525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  Given a current rotation matrix (R) and a previous rotation matrix
126625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  (prevR) computes the rotation around the x,y, and z axes which
126725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  transforms prevR to R.
126825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  outputs a 3 element vector containing the x,y, and z angle
126925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  change at indexes 0, 1, and 2 respectively.
127025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * <p> Each input matrix is either as a 3x3 or 4x4 row-major matrix
127125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * depending on the length of the passed array:
127225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * <p>If the array length is 9, then the array elements represent this matrix
127325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * <pre>
127425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   /  R[ 0]   R[ 1]   R[ 2]   \
127525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   |  R[ 3]   R[ 4]   R[ 5]   |
127625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   \  R[ 6]   R[ 7]   R[ 8]   /
127725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *</pre>
127825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * <p>If the array length is 16, then the array elements represent this matrix
127925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * <pre>
128025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   /  R[ 0]   R[ 1]   R[ 2]   R[ 3]  \
128125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   |  R[ 4]   R[ 5]   R[ 6]   R[ 7]  |
128225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   |  R[ 8]   R[ 9]   R[10]   R[11]  |
128325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   \  R[12]   R[13]   R[14]   R[15]  /
128425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *</pre>
128525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * @param R current rotation matrix
128625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * @param prevR previous rotation matrix
128725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * @param angleChange an array of floats in which the angle change is stored
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
129025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    public static void getAngleChange( float[] angleChange, float[] R, float[] prevR) {
129125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float rd1=0,rd4=0, rd6=0,rd7=0, rd8=0;
129225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float ri0=0,ri1=0,ri2=0,ri3=0,ri4=0,ri5=0,ri6=0,ri7=0,ri8=0;
129325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float pri0=0, pri1=0, pri2=0, pri3=0, pri4=0, pri5=0, pri6=0, pri7=0, pri8=0;
129425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        int i, j, k;
129525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
129625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        if(R.length == 9) {
129725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri0 = R[0];
129825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri1 = R[1];
129925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri2 = R[2];
130025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri3 = R[3];
130125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri4 = R[4];
130225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri5 = R[5];
130325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri6 = R[6];
130425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri7 = R[7];
130525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri8 = R[8];
130625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        } else if(R.length == 16) {
130725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri0 = R[0];
130825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri1 = R[1];
130925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri2 = R[2];
131025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri3 = R[4];
131125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri4 = R[5];
131225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri5 = R[6];
131325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri6 = R[8];
131425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri7 = R[9];
131525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ri8 = R[10];
131625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
131725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
131825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        if(prevR.length == 9) {
131925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri0 = prevR[0];
132025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri1 = prevR[1];
132125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri2 = prevR[2];
132225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri3 = prevR[3];
132325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri4 = prevR[4];
132425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri5 = prevR[5];
132525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri6 = prevR[6];
132625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri7 = prevR[7];
132725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri8 = prevR[8];
132825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        } else if(prevR.length == 16) {
132925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri0 = prevR[0];
133025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri1 = prevR[1];
133125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri2 = prevR[2];
133225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri3 = prevR[4];
133325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri4 = prevR[5];
133425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri5 = prevR[6];
133525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri6 = prevR[8];
133625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri7 = prevR[9];
133725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            pri8 = prevR[10];
133825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
133925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
134025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        // calculate the parts of the rotation difference matrix we need
134125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        // rd[i][j] = pri[0][i] * ri[0][j] + pri[1][i] * ri[1][j] + pri[2][i] * ri[2][j];
134225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
134325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        rd1 = pri0 * ri1 + pri3 * ri4 + pri6 * ri7; //rd[0][1]
134425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        rd4 = pri1 * ri1 + pri4 * ri4 + pri7 * ri7; //rd[1][1]
134525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        rd6 = pri2 * ri0 + pri5 * ri3 + pri8 * ri6; //rd[2][0]
134625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        rd7 = pri2 * ri1 + pri5 * ri4 + pri8 * ri7; //rd[2][1]
134725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        rd8 = pri2 * ri2 + pri5 * ri5 + pri8 * ri8; //rd[2][2]
134825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
134925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        angleChange[0] = (float)Math.atan2(rd1, rd4);
135025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        angleChange[1] = (float)Math.asin(-rd7);
135125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        angleChange[2] = (float)Math.atan2(-rd6, rd8);
135225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
135325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
135425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
135525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /** Helper function to convert a rotation vector to a rotation matrix.
135625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a
135725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  9  or 16 element rotation matrix in the array R.  R must have length 9 or 16.
135825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  If R.length == 9, the following matrix is returned:
135925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * <pre>
136025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   /  R[ 0]   R[ 1]   R[ 2]   \
136125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   |  R[ 3]   R[ 4]   R[ 5]   |
136225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   \  R[ 6]   R[ 7]   R[ 8]   /
136325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *</pre>
136425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * If R.length == 16, the following matrix is returned:
136525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * <pre>
136625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   /  R[ 0]   R[ 1]   R[ 2]   0  \
136725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   |  R[ 4]   R[ 5]   R[ 6]   0  |
136825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   |  R[ 8]   R[ 9]   R[10]   0  |
136925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *   \  0       0       0       1  /
137025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *</pre>
137125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  @param rotationVector the rotation vector to convert
137225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  @param R an array of floats in which to store the rotation matrix
137325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     */
137425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    public static void getRotationMatrixFromVector(float[] R, float[] rotationVector) {
137525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
137625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q0;
137725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q1 = rotationVector[0];
137825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q2 = rotationVector[1];
137925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q3 = rotationVector[2];
138025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
138125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        if (rotationVector.length == 4) {
138225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            q0 = rotationVector[3];
138325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        } else {
138425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            q0 = 1 - q1*q1 - q2*q2 - q3*q3;
138525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            q0 = (q0 > 0) ? (float)Math.sqrt(q0) : 0;
138625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
138725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
138825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float sq_q1 = 2 * q1 * q1;
138925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float sq_q2 = 2 * q2 * q2;
139025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float sq_q3 = 2 * q3 * q3;
139125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q1_q2 = 2 * q1 * q2;
139225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q3_q0 = 2 * q3 * q0;
139325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q1_q3 = 2 * q1 * q3;
139425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q2_q0 = 2 * q2 * q0;
139525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q2_q3 = 2 * q2 * q3;
139625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        float q1_q0 = 2 * q1 * q0;
139725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
139825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        if(R.length == 9) {
139925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[0] = 1 - sq_q2 - sq_q3;
140025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[1] = q1_q2 - q3_q0;
140125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[2] = q1_q3 + q2_q0;
140225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
140325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[3] = q1_q2 + q3_q0;
140425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[4] = 1 - sq_q1 - sq_q3;
140525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[5] = q2_q3 - q1_q0;
140625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
140725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[6] = q1_q3 - q2_q0;
140825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[7] = q2_q3 + q1_q0;
140925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[8] = 1 - sq_q1 - sq_q2;
141025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        } else if (R.length == 16) {
141125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[0] = 1 - sq_q2 - sq_q3;
141225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[1] = q1_q2 - q3_q0;
141325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[2] = q1_q3 + q2_q0;
141425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[3] = 0.0f;
141525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
141625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[4] = q1_q2 + q3_q0;
141725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[5] = 1 - sq_q1 - sq_q3;
141825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[6] = q2_q3 - q1_q0;
141925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[7] = 0.0f;
142025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
142125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[8] = q1_q3 - q2_q0;
142225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[9] = q2_q3 + q1_q0;
142325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[10] = 1 - sq_q1 - sq_q2;
142425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[11] = 0.0f;
142525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
142625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[12] = R[13] = R[14] = 0.0f;
142725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            R[15] = 1.0f;
142825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
142925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
143025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
143125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /** Helper function to convert a rotation vector to a normalized quaternion.
143225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a normalized
143325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  quaternion in the array Q.  The quaternion is stored as [w, x, y, z]
143425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  @param rv the rotation vector to convert
143525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     *  @param Q an array of floats in which to store the computed quaternion
143625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     */
143725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    public static void getQuaternionFromVector(float[] Q, float[] rv) {
143825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        if (rv.length == 4) {
143925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            Q[0] = rv[3];
144025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        } else {
144125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            Q[0] = 1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2];
144225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            Q[0] = (Q[0] > 0) ? (float)Math.sqrt(Q[0]) : 0;
144325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
144425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        Q[1] = rv[0];
144525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        Q[2] = rv[1];
144625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        Q[3] = rv[2];
144725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
144825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
144925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    static void onRotationChanged(int rotation) {
145025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        synchronized (SensorManager.class) {
145125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            sRotation  = rotation;
145225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
145325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
145425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
145525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    static int getRotation() {
145625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        synchronized (SensorManager.class) {
145725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return sRotation;
145825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
145925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
146025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
146125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private static final class LegacyListener implements SensorEventListener {
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mValues[] = new float[6];
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private SensorListener mTarget;
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mSensors;
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final LmsFilter mYawfilter = new LmsFilter();
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LegacyListener(SensorListener target) {
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTarget = target;
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors = 0;
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
147425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        boolean registerSensor(int legacyType) {
147525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            if ((mSensors & legacyType) != 0) {
147625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                return false;
147725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
147825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            boolean alreadyHasOrientationSensor = hasOrientationSensor(mSensors);
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSensors |= legacyType;
148025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            if (alreadyHasOrientationSensor && hasOrientationSensor(legacyType)) {
148125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                return false; // don't need to re-register the orientation sensor
148225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
148325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return true;
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean unregisterSensor(int legacyType) {
148725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            if ((mSensors & legacyType) == 0) {
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
149025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            mSensors &= ~legacyType;
149125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            if (hasOrientationSensor(legacyType) && hasOrientationSensor(mSensors)) {
149225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                return false; // can't unregister the orientation sensor just yet
149325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
149725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        boolean hasSensors() {
149825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return mSensors != 0;
149925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
150025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
150125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        private static boolean hasOrientationSensor(int sensors) {
150225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return (sensors & (SENSOR_ORIENTATION | SENSOR_ORIENTATION_RAW)) != 0;
150325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
150425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onAccuracyChanged(Sensor sensor, int accuracy) {
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
150825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                mTarget.onAccuracyChanged(getLegacySensorType(sensor.getType()), accuracy);
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (AbstractMethodError e) {
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // old app that doesn't implement this method
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // just ignore it.
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @SuppressWarnings("deprecation")
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onSensorChanged(SensorEvent event) {
15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float v[] = mValues;
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[0] = event.values[0];
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[1] = event.values[1];
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v[2] = event.values[2];
152125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            int type = event.sensor.getType();
152225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            int legacyType = getLegacySensorType(type);
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mapSensorDataToWindow(legacyType, v, SensorManager.getRotation());
152425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            if (type == Sensor.TYPE_ORIENTATION) {
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((mSensors & SENSOR_ORIENTATION_RAW)!=0) {
15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTarget.onSensorChanged(SENSOR_ORIENTATION_RAW, v);
15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((mSensors & SENSOR_ORIENTATION)!=0) {
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    v[0] = mYawfilter.filter(event.timestamp, v[0]);
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTarget.onSensorChanged(SENSOR_ORIENTATION, v);
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTarget.onSensorChanged(legacyType, v);
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Helper function to convert the specified sensor's data to the windows's
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * coordinate space from the device's coordinate space.
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * output: 3,4,5: values in the old API format
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *         0,1,2: transformed values in the old API format
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private void mapSensorDataToWindow(int sensor,
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                float[] values, int orientation) {
15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x = values[0];
15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float y = values[1];
15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float z = values[2];
15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (sensor) {
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_ORIENTATION:
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_ORIENTATION_RAW:
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    z = -z;
15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_ACCELEROMETER:
15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    x = -x;
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    y = -y;
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    z = -z;
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SensorManager.SENSOR_MAGNETIC_FIELD:
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    x = -x;
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    y = -y;
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[0] = x;
15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[1] = y;
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[2] = z;
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[3] = x;
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[4] = y;
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[5] = z;
15727895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian
15737895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian            if ((orientation & Surface.ROTATION_90) != 0) {
15747895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                // handles 90 and 270 rotation
15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                switch (sensor) {
15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_ACCELEROMETER:
15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_MAGNETIC_FIELD:
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[0] =-y;
15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[1] = x;
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[2] = z;
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_ORIENTATION:
15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case SENSOR_ORIENTATION_RAW:
15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[0] = x + ((x < 270) ? 90 : -270);
15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[1] = z;
15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        values[2] = y;
15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15907895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian            if ((orientation & Surface.ROTATION_180) != 0) {
15917895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                x = values[0];
15927895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                y = values[1];
15937895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                z = values[2];
15947895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                // handles 180 (flip) and 270 (flip + 90) rotation
15957895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                switch (sensor) {
15967895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                    case SENSOR_ACCELEROMETER:
15977895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                    case SENSOR_MAGNETIC_FIELD:
15987895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[0] =-x;
15997895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[1] =-y;
16007895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[2] = z;
16017895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        break;
16027895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                    case SENSOR_ORIENTATION:
16037895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                    case SENSOR_ORIENTATION_RAW:
16047895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[0] = (x >= 180) ? (x - 180) : (x + 180);
16057895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[1] =-y;
16067895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        values[2] =-z;
16077895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                        break;
16087895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian                }
16097895da44e32e9c76e07663aae7084f11cbacbbdbMathias Agopian            }
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
161125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
161225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        private static int getLegacySensorType(int type) {
161325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            switch (type) {
161425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                case Sensor.TYPE_ACCELEROMETER:
161525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    return SENSOR_ACCELEROMETER;
161625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                case Sensor.TYPE_MAGNETIC_FIELD:
161725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    return SENSOR_MAGNETIC_FIELD;
161825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                case Sensor.TYPE_ORIENTATION:
161925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    return SENSOR_ORIENTATION_RAW;
162025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                case Sensor.TYPE_TEMPERATURE:
162125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    return SENSOR_TEMPERATURE;
162225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
162325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return 0;
162425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16260f791a799dc81d93935fd2597297cf7ac2c0a044Mathias Agopian
162725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private static final class LmsFilter {
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final int SENSORS_RATE_MS = 20;
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final int COUNT = 12;
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final float PREDICTION_RATIO = 1.0f/3.0f;
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static final float PREDICTION_TIME = (SENSORS_RATE_MS*COUNT/1000.0f)*PREDICTION_RATIO;
16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mV[] = new float[COUNT*2];
16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mT[] = new float[COUNT*2];
16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mIndex;
16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public LmsFilter() {
16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIndex = COUNT;
16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public float filter(long time, float in) {
16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float v = in;
16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float ns = 1.0f / 1000000000.0f;
16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float t = time*ns;
16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float v1 = mV[mIndex];
16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((v-v1) > 180) {
16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                v -= 360;
16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if ((v1-v) > 180) {
16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                v += 360;
16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* Manage the circular buffer, we write the data twice spaced
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * by COUNT values, so that we don't have to copy the array
16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * when it's full
16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIndex++;
16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mIndex >= COUNT*2)
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mIndex = COUNT;
16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mV[mIndex] = v;
16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mT[mIndex] = t;
16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mV[mIndex-COUNT] = v;
16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mT[mIndex-COUNT] = t;
16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float A, B, C, D, E;
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float a, b;
16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int i;
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            A = B = C = D = E = 0;
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (i=0 ; i<COUNT-1 ; i++) {
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int j = mIndex - 1 - i;
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final float Z = mV[j];
16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final float T = 0.5f*(mT[j] + mT[j+1]) - t;
16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                float dT = mT[j] - mT[j+1];
16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dT *= dT;
16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                A += Z*dT;
16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                B += T*(T*dT);
16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                C +=   (T*dT);
16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                D += Z*(T*dT);
16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                E += dT;
16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            b = (A*B + C*D) / (E*B + C*C);
16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            a = (E*b - A) / C;
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float f = b + PREDICTION_TIME*a;
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Normalize
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            f *= (1.0f / 360.0f);
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (((f>=0)?f:-f) >= 0.5f)
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                f = f - (float)Math.ceil(f + 0.5f) + 1.0f;
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (f < 0)
16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                f += 1.0f;
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            f *= 360.0f;
16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return f;
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
169425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /**
169525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * Sensor event pool implementation.
169625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * @hide
16977a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell     */
169825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    protected static final class SensorEventPool {
169925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        private final int mPoolSize;
170025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        private final SensorEvent mPool[];
170125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        private int mNumItemsInPool;
17027a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
170325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        private SensorEvent createSensorEvent() {
170425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            // maximal size for all legacy events is 3
170525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return new SensorEvent(3);
17067a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        }
17077a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
170825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        SensorEventPool(int poolSize) {
170925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            mPoolSize = poolSize;
171025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            mNumItemsInPool = poolSize;
171125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            mPool = new SensorEvent[poolSize];
17127badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian        }
17137badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian
171425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        SensorEvent getFromPool() {
171525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            SensorEvent t = null;
171625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            synchronized (this) {
171725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                if (mNumItemsInPool > 0) {
171825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    // remove the "top" item from the pool
171925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    final int index = mPoolSize - mNumItemsInPool;
172025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    t = mPool[index];
172125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    mPool[index] = null;
172225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    mNumItemsInPool--;
172325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                }
172425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
172525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            if (t == null) {
172625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // the pool was empty or this item was removed from the pool for
172725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // the first time. In any case, we need to create a new item.
172825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                t = createSensorEvent();
172925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
173025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return t;
17317a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell        }
17327a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell
173325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        void returnToPool(SensorEvent t) {
173425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            synchronized (this) {
173525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // is there space left in the pool?
173625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                if (mNumItemsInPool < mPoolSize) {
173725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    // if so, return the item to the pool
173825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    mNumItemsInPool++;
173925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    final int index = mPoolSize - mNumItemsInPool;
174025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    mPool[index] = t;
174125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                }
174225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
17437badd2c402f9e8e9fd13f6915ad2e32301f9f305Mathias Agopian        }
17447a0541d6b803da02b8724b1d140d6ccaaec23a36Kevin Powell    }
17459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1746